/** * Builds the XML structure to export. * * @return array An array of XML lines (strings). * * @since 11.1 * @throws Exception if an error occurs. */ protected function buildXmlStructure() { $buffer = array(); foreach ($this->from as $table) { // Replace the magic prefix if found. $table = $this->getGenericTableName($table); // Get the details columns information. $fields = $this->db->getTableColumns($table); $keys = $this->db->getTableKeys($table); $buffer[] = ' <table_structure name="' . $table . '">'; foreach ($fields as $field) { $buffer[] = ' <field Field="' . $field->Field . '"' . ' Type="' . $field->Type . '"' . ' Null="' . $field->Null . '"' . ' Key="' . $field->Key . '"' . (isset($field->Default) ? ' Default="' . $field->Default . '"' : '') . ' Extra="' . $field->Extra . '"' . ' />'; } foreach ($keys as $key) { $buffer[] = ' <key Table="' . $table . '"' . ' Non_unique="' . $key->Non_unique . '"' . ' Key_name="' . $key->Key_name . '"' . ' Seq_in_index="' . $key->Seq_in_index . '"' . ' Column_name="' . $key->Column_name . '"' . ' Collation="' . $key->Collation . '"' . ' Null="' . $key->Null . '"' . ' Index_type="' . $key->Index_type . '"' . ' Comment="' . htmlspecialchars($key->Comment) . '"' . ' />'; } $buffer[] = ' </table_structure>'; } return $buffer; }
/** * Builds the XML structure to export. * * @return array An array of XML lines (strings). * * @since 11.1 * @throws Exception if an error occurs. */ protected function buildXmlStructure() { $buffer = array(); $query = $this->db->getQuery(true); foreach ($this->from as $table) { // Replace the magic prefix if found. $table = $this->getGenericTableName($table); /* * Table structure */ // Get the details columns information. $fields = $this->db->getTableColumns($table, false); $keys = $this->db->getTableKeys($table); $buffer[] = ' <table_structure name="' . $table . '">'; foreach ($fields as $field) { $buffer[] = ' <field' . ' Field="' . $field->Field . '"' . ' Type="' . $field->Type . '"' . ' Null="' . $field->Null . '"' . ' Key="' . $field->Key . '"' . (isset($field->Default) ? ' Default="' . $field->Default . '"' : '') . ' Extra="' . $field->Extra . '"' . ' Comment="' . htmlspecialchars($field->Comment) . '"' . ' />'; } foreach ($keys as $key) { $buffer[] = ' <key' . ' Table="' . $table . '"' . ' Non_unique="' . $key->Non_unique . '"' . ' Key_name="' . $key->Key_name . '"' . ' Seq_in_index="' . $key->Seq_in_index . '"' . ' Column_name="' . $key->Column_name . '"' . ' Collation="' . $key->Collation . '"' . ' Null="' . $key->Null . '"' . ' Index_type="' . $key->Index_type . '"' . ' Comment="' . htmlspecialchars($key->Comment) . '"' . ' />'; } $buffer[] = ' </table_structure>'; /* * Table data */ if (!$this->options->get('with-data')) { continue; } $query->clear()->from($this->db->quoteName($table))->select('*'); $rows = $this->db->setQuery($query)->loadObjectList(); $buffer[] = ' <table_data name="' . $table . '">'; foreach ($rows as $row) { $buffer[] = ' <row>'; foreach ($row as $fieldName => $fieldValue) { $buffer[] = ' <field' . ' name="' . $fieldName . '">' . htmlspecialchars($fieldValue) . '</field>'; } $buffer[] = ' </row>'; } $buffer[] = ' </table_data>'; } return $buffer; }
/** * Get alters for table if there is a difference. * * @param SimpleXMLElement $structure The XML structure pf the table. * * @return array * * @since 11.1 */ protected function getAlterTableSQL(SimpleXMLElement $structure) { // Initialise variables. $table = $this->getRealTableName($structure['name']); $oldFields = $this->db->getTableColumns($table); $oldKeys = $this->db->getTableKeys($table); $alters = array(); // Get the fields and keys from the XML that we are aiming for. $newFields = $structure->xpath('field'); $newKeys = $structure->xpath('key'); // Loop through each field in the new structure. foreach ($newFields as $field) { $fName = (string) $field['Field']; if (isset($oldFields[$fName])) { // The field exists, check it's the same. $column = $oldFields[$fName]; // Test whether there is a change. $change = (string) $field['Type'] != $column->Type || (string) $field['Null'] != $column->Null || (string) $field['Default'] != $column->Default || (string) $field['Extra'] != $column->Extra; if ($change) { $alters[] = $this->getChangeColumnSQL($table, $field); } // Unset this field so that what we have left are fields that need to be removed. unset($oldFields[$fName]); } else { // The field is new. $alters[] = $this->getAddColumnSQL($table, $field); } } // Any columns left are orphans foreach ($oldFields as $name => $column) { // Delete the column. $alters[] = $this->getDropColumnSQL($table, $name); } // Get the lookups for the old and new keys. $oldLookup = $this->getKeyLookup($oldKeys); $newLookup = $this->getKeyLookup($newKeys); // Loop through each key in the new structure. foreach ($newLookup as $name => $keys) { // Check if there are keys on this field in the existing table. if (isset($oldLookup[$name])) { $same = true; $newCount = count($newLookup[$name]); $oldCount = count($oldLookup[$name]); // There is a key on this field in the old and new tables. Are they the same? if ($newCount == $oldCount) { // Need to loop through each key and do a fine grained check. for ($i = 0; $i < $newCount; $i++) { $same = (string) $newLookup[$name][$i]['Non_unique'] == $oldLookup[$name][$i]->Non_unique && (string) $newLookup[$name][$i]['Column_name'] == $oldLookup[$name][$i]->Column_name && (string) $newLookup[$name][$i]['Seq_in_index'] == $oldLookup[$name][$i]->Seq_in_index && (string) $newLookup[$name][$i]['Collation'] == $oldLookup[$name][$i]->Collation && (string) $newLookup[$name][$i]['Index_type'] == $oldLookup[$name][$i]->Index_type; // Debug. // echo '<pre>'; // echo '<br />Non_unique: '. // ((string) $newLookup[$name][$i]['Non_unique'] == $oldLookup[$name][$i]->Non_unique ? 'Pass' : 'Fail').' '. // (string) $newLookup[$name][$i]['Non_unique'].' vs '.$oldLookup[$name][$i]->Non_unique; // echo '<br />Column_name: '. // ((string) $newLookup[$name][$i]['Column_name'] == $oldLookup[$name][$i]->Column_name ? 'Pass' : 'Fail').' '. // (string) $newLookup[$name][$i]['Column_name'].' vs '.$oldLookup[$name][$i]->Column_name; // echo '<br />Seq_in_index: '. // ((string) $newLookup[$name][$i]['Seq_in_index'] == $oldLookup[$name][$i]->Seq_in_index ? 'Pass' : 'Fail').' '. // (string) $newLookup[$name][$i]['Seq_in_index'].' vs '.$oldLookup[$name][$i]->Seq_in_index; // echo '<br />Collation: '. // ((string) $newLookup[$name][$i]['Collation'] == $oldLookup[$name][$i]->Collation ? 'Pass' : 'Fail').' '. // (string) $newLookup[$name][$i]['Collation'].' vs '.$oldLookup[$name][$i]->Collation; // echo '<br />Index_type: '. // ((string) $newLookup[$name][$i]['Index_type'] == $oldLookup[$name][$i]->Index_type ? 'Pass' : 'Fail').' '. // (string) $newLookup[$name][$i]['Index_type'].' vs '.$oldLookup[$name][$i]->Index_type; // echo '<br />Same = '.($same ? 'true' : 'false'); // echo '</pre>'; if (!$same) { // Break out of the loop. No need to check further. break; } } } else { // Count is different, just drop and add. $same = false; } if (!$same) { $alters[] = $this->getDropKeySQL($table, $name); $alters[] = $this->getAddKeySQL($table, $keys); } // Unset this field so that what we have left are fields that need to be removed. unset($oldLookup[$name]); } else { // This is a new key. $alters[] = $this->getAddKeySQL($table, $keys); } } // Any keys left are orphans. foreach ($oldLookup as $name => $keys) { if (strtoupper($name) == 'PRIMARY') { $alters[] = $this->getDropPrimaryKeySQL($table); } else { $alters[] = $this->getDropKeySQL($table, $name); } } return $alters; }
/** * Tests the JDatabaseMySQL getTableKeys method. * * @return void * * @since 11.4 */ public function testGetTableKeys() { $this->assertThat($this->object->getTableKeys('#__dbtest'), $this->isType('array'), 'The list of keys for the table is returned in an array.'); }