Server synchronize: fix PMA_get_table_indexes to return null when there are no indexe...
[phpmyadmin.git] / libraries / server_synchronize.lib.php
blob5ddd07a8d3ca003ee015ebec197854b90e3b3c9e
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Server synchronisation functions.
6 * @package phpMyAdmin
7 */
9 /**
10 * Places matching tables in source and target databases in $matching_tables
11 * array whereas $uncommon_source_tables array gets the tables present in
12 * source database but are absent from target database. Criterion for
13 * matching tables is just comparing their names.
15 * @param array $trg_tables array of target database table names,
16 * @param array $src_tables array of source database table names,
17 * @param array &$matching_tables empty array passed by reference to save
18 * names of matching tables,
19 * @param array &$uncommon_source_tables empty array passed by reference to save
20 * names of tables present in source database
21 * but absent from target database
23 function PMA_getMatchingTables($trg_tables, $src_tables, &$matching_tables, &$uncommon_source_tables)
25 for ($k=0; $k< sizeof($src_tables); $k++) {
26 $present_in_target = false;
27 for ($l=0; $l < sizeof($trg_tables); $l++) {
28 if ($src_tables[$k] === $trg_tables[$l]) {
29 $present_in_target = true;
30 $matching_tables[] = $src_tables[$k];
33 if ($present_in_target === false) {
34 $uncommon_source_tables[] = $src_tables[$k];
39 /**
40 * Places tables present in target database but are absent from source database
42 * @param array $trg_tables array of target database table names,
43 * @param array $matching_tables matching tables array containing names
44 * of matching tables,
45 * @param array &$uncommon_target_tables empty array passed by reference to save
46 * names of tables presnet in target database
47 * but absent from source database
49 function PMA_getNonMatchingTargetTables($trg_tables, $matching_tables, &$uncommon_target_tables)
51 for ($c=0; $c<sizeof($trg_tables); $c++) {
52 $match = false;
53 for ($d=0; $d < sizeof($matching_tables); $d++) {
54 if ($trg_tables[$c] === $matching_tables[$d]) {
55 $match=true;
58 if ($match === false) {
59 $uncommon_target_tables[] = $trg_tables[$c];
64 /**
65 * Finds the difference in source and target matching tables by
66 * first comparing source table's primary key entries with target table enteries.
67 * It gets the field names for the matching table also for comparisons.
68 * If the entry is found in target table also then it is checked for the remaining
69 * field values also, in order to check whether update is required or not.
70 * If update is required, it is placed in $update_array
71 * Otherwise that entry is placed in the $insert_array.
73 * @param string $src_db name of source database
74 * @param string $trg_db name of target database
75 * @param db_link $src_link connection established with source server
76 * @param db_link $trg_link connection established with target server
77 * @param array &$matching_table array containing matching table names
78 * @param array &$matching_tables_fields A two dimensional array passed by reference to contain names of fields for each matching table
79 * @param array &$update_array A three dimensional array passed by reference to
80 * contain updates required for each matching table
81 * @param array &$insert_array A three dimensional array passed by reference to
82 * contain inserts required for each matching table
83 * @param array &$delete_array Unused
84 * @param array &$fields_num A two dimensional array passed by reference to
85 * contain number of fields for each matching table
86 * @param int $matching_table_index Index of a table from $matching_table array
87 * @param array &$matching_tables_keys A two dimensional array passed by reference to contain names of keys for each matching table
89 function PMA_dataDiffInTables($src_db, $trg_db, $src_link, $trg_link, &$matching_table, &$matching_tables_fields,
90 &$update_array, &$insert_array, &$delete_array, &$fields_num, $matching_table_index, &$matching_tables_keys)
92 if (isset($matching_table[$matching_table_index])) {
93 $fld = array();
94 $fld_results = PMA_DBI_get_columns($src_db, $matching_table[$matching_table_index], true, $src_link);
95 $is_key = array();
96 if (isset($fld_results)) {
97 foreach ($fld_results as $each_field) {
98 $field_name = $each_field['Field'];
99 if ($each_field['Key'] == 'PRI') {
100 $is_key[] = $field_name;
102 $fld[] = $field_name;
105 $matching_tables_fields[$matching_table_index] = $fld;
106 $fields_num[$matching_table_index] = sizeof($fld);
107 $matching_tables_keys[$matching_table_index] = $is_key;
109 $source_result_set = PMA_get_column_values($src_db, $matching_table[$matching_table_index], $is_key, $src_link);
110 $source_size = sizeof($source_result_set);
112 $trg_fld_results = PMA_DBI_get_columns($trg_db, $matching_table[$matching_table_index], true, $trg_link);
113 $all_keys_match = true;
114 $trg_keys = array();
116 if (isset($trg_fld_results)) {
117 foreach ($trg_fld_results as $each_field) {
118 if ($each_field['Key'] == 'PRI') {
119 $trg_keys[] = $each_field['Field'];
120 if (! (in_array($each_field['Field'], $is_key))) {
121 $all_keys_match = false;
126 $update_row = 0;
127 $insert_row = 0;
128 $update_field = 0;
129 $insert_field = 0;
130 $starting_index = 0;
132 for ($j = 0; $j < $source_size; $j++) {
133 $starting_index = 0;
134 $update_field = 0;
136 if (isset($source_result_set[$j]) && ($all_keys_match)) {
138 // Query the target server to see which rows already exist
139 $trg_select_query = "SELECT * FROM " . PMA_backquote($trg_db) . "."
140 . PMA_backquote($matching_table[$matching_table_index]) . " WHERE ";
142 if (sizeof($is_key) == 1) {
143 $trg_select_query .= $is_key[0]. "='" . $source_result_set[$j] . "'";
144 } elseif (sizeof($is_key) > 1) {
145 for ($k=0; $k < sizeof($is_key); $k++) {
146 $trg_select_query .= $is_key[$k] . "='" . $source_result_set[$j][$is_key[$k]] . "'";
147 if ($k < (sizeof($is_key)-1)) {
148 $trg_select_query .= " AND ";
153 $target_result_set = PMA_DBI_fetch_result($trg_select_query, null, null, $trg_link);
154 if ($target_result_set) {
156 // Fetch the row from the source server to do a comparison
157 $src_select_query = "SELECT * FROM " . PMA_backquote($src_db) . "."
158 . PMA_backquote($matching_table[$matching_table_index]) . " WHERE ";
160 if (sizeof($is_key) == 1) {
161 $src_select_query .= $is_key[0] . "='" . $source_result_set[$j] . "'";
162 } elseif (sizeof($is_key) > 1) {
163 for ($k=0; $k< sizeof($is_key); $k++) {
164 $src_select_query .= $is_key[$k] . "='" . $source_result_set[$j][$is_key[$k]] . "'";
165 if ($k < (sizeof($is_key) - 1)) {
166 $src_select_query .= " AND ";
171 $src_result_set = PMA_DBI_fetch_result($src_select_query, null, null, $src_link);
174 * Comparing each corresponding field of the source and target matching rows.
175 * Placing the primary key, value of primary key, field to be updated, and the
176 * new value of field to be updated in each row of the update array.
178 for ($m = 0; ($m < $fields_num[$matching_table_index]) && ($starting_index == 0) ; $m++) {
179 if (isset($src_result_set[0][$fld[$m]])) {
180 if (isset($target_result_set[0][$fld[$m]])) {
181 if (($src_result_set[0][$fld[$m]] != $target_result_set[0][$fld[$m]]) && (! (in_array($fld[$m], $is_key)))) {
182 if (sizeof($is_key) == 1) {
183 if ($source_result_set[$j]) {
184 $update_array[$matching_table_index][$update_row][$is_key[0]] = $source_result_set[$j];
186 } elseif (sizeof($is_key) > 1) {
187 for ($n=0; $n < sizeof($is_key); $n++) {
188 if (isset($src_result_set[0][$is_key[$n]])) {
189 $update_array[$matching_table_index][$update_row][$is_key[$n]] = $src_result_set[0][$is_key[$n]];
194 $update_array[$matching_table_index][$update_row][$update_field] = $fld[$m];
196 $update_field++;
197 if (isset($src_result_set[0][$fld[$m]])) {
198 $update_array[$matching_table_index][$update_row][$update_field] = $src_result_set[0][$fld[$m]];
199 $update_field++;
201 $starting_index = $m;
202 $update_row++;
204 } else {
205 if (sizeof($is_key) == 1) {
206 if ($source_result_set[$j]) {
207 $update_array[$matching_table_index][$update_row][$is_key[0]] = $source_result_set[$j];
209 } elseif (sizeof($is_key) > 1) {
210 for ($n = 0; $n < sizeof($is_key); $n++) {
211 if (isset($src_result_set[0][$is_key[$n]])) {
212 $update_array[$matching_table_index][$update_row][$is_key[$n]] = $src_result_set[0][$is_key[$n]];
217 $update_array[$matching_table_index][$update_row][$update_field] = $fld[$m];
219 $update_field++;
220 if (isset($src_result_set[0][$fld[$m]])) {
221 $update_array[$matching_table_index][$update_row][$update_field] = $src_result_set[0][$fld[$m]];
222 $update_field++;
224 $starting_index = $m;
225 $update_row++;
229 for ($m = $starting_index + 1; $m < $fields_num[$matching_table_index] ; $m++) {
230 if (isset($src_result_set[0][$fld[$m]])) {
231 if (isset($target_result_set[0][$fld[$m]])) {
232 if (($src_result_set[0][$fld[$m]] != $target_result_set[0][$fld[$m]]) && (!(in_array($fld[$m], $is_key)))) {
233 $update_row--;
234 $update_array[$matching_table_index][$update_row][$update_field] = $fld[$m];
235 $update_field++;
236 if ($src_result_set[0][$fld[$m]]) {
237 $update_array[$matching_table_index][$update_row][$update_field] = $src_result_set[0][$fld[$m]];
238 $update_field++;
240 $update_row++;
242 } else {
243 $update_row--;
244 $update_array[$matching_table_index][$update_row][$update_field] = $fld[$m];
245 $update_field++;
246 if ($src_result_set[0][$fld[$m]]) {
247 $update_array[$matching_table_index][$update_row][$update_field] = $src_result_set[0][$fld[$m]];
248 $update_field++;
250 $update_row++;
254 } else {
256 * Placing the primary key, and the value of primary key of the row that is to be inserted in the target table
258 if (sizeof($is_key) == 1) {
259 if (isset($source_result_set[$j])) {
260 $insert_array[$matching_table_index][$insert_row][$is_key[0]] = $source_result_set[$j];
262 } elseif (sizeof($is_key) > 1) {
263 for ($l = 0; $l < sizeof($is_key); $l++) {
264 if (isset($source_result_set[$j][$matching_tables_fields[$matching_table_index][$l]])) {
265 $insert_array[$matching_table_index][$insert_row][$is_key[$l]] = $source_result_set[$j][$matching_tables_fields[$matching_table_index][$l]];
269 $insert_row++;
271 } else {
273 * Placing the primary key, and the value of primary key of the row that is to be inserted in the target table
274 * This condition is met when there is an additional column in the source table
276 if (sizeof($is_key) == 1) {
277 if (isset($source_result_set[$j])) {
278 $insert_array[$matching_table_index][$insert_row][$is_key[0]] = $source_result_set[$j];
280 } elseif (sizeof($is_key) > 1) {
281 for ($l = 0; $l < sizeof($is_key); $l++) {
282 if (isset($source_result_set[$j][$matching_tables_fields[$matching_table_index][$l]])) {
283 $insert_array[$matching_table_index][$insert_row][$is_key[$l]] = $source_result_set[$j][$matching_tables_fields[$matching_table_index][$l]];
287 $insert_row++;
289 } // for loop ends
294 * Finds the rows which are to be deleted from target table.
296 * @param array &$delete_array array containing rows that are to be deleted
297 * @param array $matching_table array containing matching table names
298 * @param int $matching_table_index index of a table from $matching_table array
299 * @param array $trg_keys array of target table keys
300 * @param array $src_keys array of source table keys
301 * @param string $trg_db name of target database
302 * @param db_link $trg_link connection established with target server
303 * @param string $src_db name of source database
304 * @param db_link $src_link connection established with source server
306 function PMA_findDeleteRowsFromTargetTables(&$delete_array, $matching_table, $matching_table_index, $trg_keys, $src_keys, $trg_db, $trg_link, $src_db, $src_link)
308 if (isset($trg_keys[$matching_table_index])) {
309 $target_key_values = PMA_get_column_values($trg_db, $matching_table[$matching_table_index], $trg_keys[$matching_table_index], $trg_link);
310 $target_row_size = sizeof($target_key_values);
312 if (isset($src_keys[$matching_table_index])) {
313 $source_key_values = PMA_get_column_values($src_db, $matching_table[$matching_table_index], $src_keys[$matching_table_index], $src_link);
314 $source_size = sizeof($source_key_values);
316 $all_keys_match = 1;
317 for ($a = 0; $a < sizeof($trg_keys[$matching_table_index]); $a++) {
318 if (isset($trg_keys[$matching_table_index][$a])) {
319 if (! (in_array($trg_keys[$matching_table_index][$a], $src_keys[$matching_table_index]))) {
320 $all_keys_match = 0;
324 if (! ($all_keys_match)) {
325 if (isset($target_key_values)) {
326 $delete_array[$matching_table_index] = $target_key_values;
329 if (isset($trg_keys[$matching_table_index])) {
330 if ((sizeof($trg_keys[$matching_table_index]) == 1) && $all_keys_match) {
331 $row = 0;
332 if (isset($target_key_values)) {
333 for ($i = 0; $i < sizeof($target_key_values); $i++) {
334 if (! (in_array($target_key_values[$i], $source_key_values))) {
335 $delete_array[$matching_table_index][$row] = $target_key_values[$i];
336 $row++;
340 } elseif ((sizeof($trg_keys[$matching_table_index]) > 1) && $all_keys_match) {
341 $row = 0;
342 if (isset($target_key_values)) {
343 for ($i = 0; $i < sizeof($target_key_values); $i++) {
344 $is_present = false;
345 for ($j = 0; $j < sizeof($source_key_values) && ($is_present == false) ; $j++) {
346 $check = true;
347 for ($k = 0; $k < sizeof($trg_keys[$matching_table_index]); $k++) {
348 if ($target_key_values[$i][$trg_keys[$matching_table_index][$k]] != $source_key_values[$j][$trg_keys[$matching_table_index][$k]]) {
349 $check = false;
352 if ($check) {
353 $is_present = true;
356 if (! ($is_present)) {
357 for ($l = 0; $l < sizeof($trg_keys[$matching_table_index]); $l++) {
358 $delete_array[$matching_table_index][$row][$trg_keys[$matching_table_index][$l]] = $target_key_values[$i][$trg_keys[$matching_table_index][$l]];
360 $row++;
369 * PMA_dataDiffInUncommonTables() finds the data difference in $source_tables_uncommon
371 * @param array $source_tables_uncommon table names that are in source db and not in target db
372 * @param string $src_db name of source database
373 * @param mixed $src_link connection established with source server
374 * @param int $index index of a table from $matching_table array
375 * @param array $row_count number of rows
377 function PMA_dataDiffInUncommonTables($source_tables_uncommon, $src_db, $src_link, $index, &$row_count)
379 $query = "SELECT COUNT(*) FROM " . PMA_backquote($src_db) . "." . PMA_backquote($source_tables_uncommon[$index]);
380 $rows = PMA_DBI_fetch_result($query, null, null, $src_link);
381 $row_count[$index] = $rows[0];
385 * PMA_updateTargetTables() sets the updated field values to target table rows using $update_array[$matching_table_index]
388 * @param array $table Matching tables' names
389 * @param array $update_array A three dimensional array containing field
390 * value updates required for each matching table
391 * @param string $src_db Name of source database
392 * @param string $trg_db Name of target database
393 * @param mixed $trg_link Connection established with target server
394 * @param int $matching_table_index index of matching table in matching_table_array
395 * @param array $matching_table_keys
396 * @param boolean $display
398 function PMA_updateTargetTables($table, $update_array, $src_db, $trg_db, $trg_link, $matching_table_index, $matching_table_keys, $display)
400 if (isset($update_array[$matching_table_index])) {
401 if (sizeof($update_array[$matching_table_index])) {
403 for ($update_row = 0; $update_row < sizeof($update_array[$matching_table_index]); $update_row++) {
405 if (isset($update_array[$matching_table_index][$update_row])) {
406 $update_fields_num = sizeof($update_array[$matching_table_index][$update_row])-sizeof($matching_table_keys[$matching_table_index]);
407 if ($update_fields_num > 0) {
408 $query = "UPDATE " . PMA_backquote($trg_db) . "." .PMA_backquote($table[$matching_table_index]) . " SET ";
410 for ($update_field = 0; $update_field < $update_fields_num; $update_field = $update_field+2) {
411 if (isset($update_array[$matching_table_index][$update_row][$update_field]) && isset($update_array[$matching_table_index][$update_row][$update_field+1])) {
412 $query .= $update_array[$matching_table_index][$update_row][$update_field] . "='" . $update_array[$matching_table_index][$update_row][$update_field+1] . "'";
414 if ($update_field < ($update_fields_num - 2)) {
415 $query .= ", ";
418 $query .= " WHERE ";
419 if (isset($matching_table_keys[$matching_table_index])) {
420 for ($key = 0; $key < sizeof($matching_table_keys[$matching_table_index]); $key++)
422 if (isset($matching_table_keys[$matching_table_index][$key])) {
423 $query .= $matching_table_keys[$matching_table_index][$key] . "='" . $update_array[$matching_table_index][$update_row][$matching_table_keys[$matching_table_index][$key]] . "'";
425 if ($key < (sizeof($matching_table_keys[$matching_table_index]) - 1)) {
426 $query .= " AND ";
430 if ($display == true) {
431 echo "<p>" . $query . "</p>";
433 PMA_DBI_try_query($query, $trg_link, 0);
442 * PMA_insertIntoTargetTable() inserts missing rows in the target table using $array_insert[$matching_table_index]
444 * @param array $matching_table matching table names
445 * @param string $src_db name of source database
446 * @param string $trg_db name of target database
447 * @param mixed $src_link connection established with source server
448 * @param mixed $trg_link connection established with target server
449 * @param array $table_fields field names of a table
450 * @param array &$array_insert
451 * @param int $matching_table_index index of matching table in matching_table_array
452 * @param array $matching_tables_keys field names that are keys in the matching table
453 * @param array $source_columns source column information
454 * @param array &$add_column_array column names that are to be added in target table
455 * @param array $criteria criteria like type, null, collation, default etc
456 * @param array $target_tables_keys field names that are keys in the target table
457 * @param array $uncommon_tables table names that are present in source db but not in targt db
458 * @param array &$uncommon_tables_fields field names of the uncommon tables
459 * @param array $uncommon_cols column names that are present in target table and not in source table
460 * @param array &$alter_str_array column names that are to be altered
461 * @param array &$source_indexes column names on which indexes are made in source table
462 * @param array &$target_indexes column names on which indexes are made in target table
463 * @param array &$add_indexes_array column names on which index is to be added in target table
464 * @param array &$alter_indexes_array column names whose indexes are to be altered. Only index name and uniqueness of an index can be changed
465 * @param array &$delete_array rows that are to be deleted
466 * @param array &$update_array rows that are to be updated in target
467 * @param bool $display
469 function PMA_insertIntoTargetTable($matching_table, $src_db, $trg_db, $src_link, $trg_link, $table_fields, &$array_insert, $matching_table_index,
470 $matching_tables_keys, $source_columns, &$add_column_array, $criteria, $target_tables_keys, $uncommon_tables, &$uncommon_tables_fields, $uncommon_cols,
471 &$alter_str_array,&$source_indexes, &$target_indexes, &$add_indexes_array, &$alter_indexes_array, &$delete_array, &$update_array, $display)
473 if (isset($array_insert[$matching_table_index])) {
474 if (sizeof($array_insert[$matching_table_index])) {
475 for ($insert_row = 0; $insert_row< sizeof($array_insert[$matching_table_index]); $insert_row++) {
476 if (isset($array_insert[$matching_table_index][$insert_row][$matching_tables_keys[$matching_table_index][0]])) {
478 $select_query = "SELECT * FROM " . PMA_backquote($src_db) . "." . PMA_backquote($matching_table[$matching_table_index]) . " WHERE ";
479 for ($i = 0; $i < sizeof($matching_tables_keys[$matching_table_index]); $i++) {
480 $select_query .= $matching_tables_keys[$matching_table_index][$i] . "='";
481 $select_query .= $array_insert[$matching_table_index][$insert_row][$matching_tables_keys[$matching_table_index][$i]] . "'" ;
483 if ($i < (sizeof($matching_tables_keys[$matching_table_index]) - 1)) {
484 $select_query.= " AND ";
487 $select_query .= "; ";
488 $result = PMA_DBI_fetch_result ($select_query, null, null, $src_link);
489 $insert_query = "INSERT INTO " . PMA_backquote($trg_db) . "." . PMA_backquote($matching_table[$matching_table_index]) ." (";
491 for ($field_index = 0; $field_index < sizeof($table_fields[$matching_table_index]); $field_index++)
493 $insert_query .= $table_fields[$matching_table_index][$field_index];
495 $is_fk_query = "SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = '" . $trg_db ."'
496 AND TABLE_NAME = '" . $matching_table[$matching_table_index]. "'AND COLUMN_NAME = '" .
497 $table_fields[$matching_table_index][$field_index] . "' AND TABLE_NAME <> REFERENCED_TABLE_NAME;" ;
499 $is_fk_result = PMA_DBI_fetch_result($is_fk_query, null, null, $trg_link);
500 if (sizeof($is_fk_result) > 0) {
501 for ($j = 0; $j < sizeof($is_fk_result); $j++)
503 $table_index = array_keys($matching_table, $is_fk_result[$j]['REFERENCED_TABLE_NAME']);
505 if (isset($alter_str_array[$table_index[0]])) {
506 PMA_alterTargetTableStructure($trg_db, $trg_link, $matching_tables, $source_columns, $alter_str_array, $matching_tables_fields,
507 $criteria, $matching_tables_keys, $target_tables_keys, $table_index[0], $display);
508 unset($alter_str_array[$table_index[0]]);
510 if (isset($uncommon_columns[$table_index[0]])) {
511 PMA_removeColumnsFromTargetTable($trg_db, $trg_link, $matching_tables, $uncommon_columns, $table_index[0], $display);
512 unset($uncommon_columns[$table_index[0]]);
514 if (isset($add_column_array[$table_index[0]])) {
515 PMA_findDeleteRowsFromTargetTables($delete_array, $matching_tables, $table_index[0], $target_tables_keys, $matching_tables_keys,
516 $trg_db, $trg_link, $src_db, $src_link);
518 if (isset($delete_array[$table_index[0]])) {
519 PMA_deleteFromTargetTable($trg_db, $trg_link, $matching_tables, $table_index[0], $target_tables_keys, $delete_array, $display);
520 unset($delete_array[$table_index[0]]);
522 PMA_addColumnsInTargetTable($src_db, $trg_db, $src_link, $trg_link, $matching_tables, $source_columns, $add_column_array,
523 $matching_tables_fields, $criteria, $matching_tables_keys, $target_tables_keys, $uncommon_tables,$uncommon_tables_fields,
524 $table_index[0], $uncommon_cols, $display);
525 unset($add_column_array[$table_index[0]]);
527 if (isset($add_indexes_array[$table_index[0]]) || isset($remove_indexes_array[$table_index[0]])
528 || isset($alter_indexes_array[$table_index[0]])) {
529 PMA_applyIndexesDiff ($trg_db, $trg_link, $matching_tables, $source_indexes, $target_indexes, $add_indexes_array, $alter_indexes_array,
530 $remove_indexes_array, $table_index[0], $display);
532 unset($add_indexes_array[$table_index[0]]);
533 unset($alter_indexes_array[$table_index[0]]);
534 unset($remove_indexes_array[$table_index[0]]);
536 if (isset($update_array[$table_index[0]])) {
537 PMA_updateTargetTables($matching_tables, $update_array, $src_db, $trg_db, $trg_link, $table_index[0], $matching_table_keys,
538 $display);
539 unset($update_array[$table_index[0]]);
541 if (isset($array_insert[$table_index[0]])) {
542 PMA_insertIntoTargetTable($matching_table, $src_db, $trg_db, $src_link, $trg_link, $table_fields, $array_insert,
543 $table_index[0], $matching_tables_keys, $source_columns, $add_column_array, $criteria, $target_tables_keys, $uncommon_tables,
544 $uncommon_tables_fields, $uncommon_cols, $alter_str_array, $source_indexes, $target_indexes, $add_indexes_array,
545 $alter_indexes_array, $delete_array, $update_array, $display);
546 unset($array_insert[$table_index[0]]);
550 if ($field_index < sizeof($table_fields[$matching_table_index])-1) {
551 $insert_query .= ", ";
554 $insert_query .= ") VALUES(";
555 if (sizeof($table_fields[$matching_table_index]) == 1) {
556 $insert_query .= "'" . PMA_sqlAddSlashes($result[0]) . "'";
557 } else {
558 for ($field_index = 0; $field_index < sizeof($table_fields[$matching_table_index]); $field_index++) {
559 if (isset($result[0][$table_fields[$matching_table_index][$field_index]])) {
560 $insert_query .= "'" . PMA_sqlAddSlashes($result[0][$table_fields[$matching_table_index][$field_index]]) . "'";
561 } else {
562 $insert_query .= "'NULL'";
564 if ($field_index < (sizeof($table_fields[$matching_table_index])) - 1) {
565 $insert_query .= " ," ;
569 $insert_query .= ");";
570 if ($display == true) {
571 PMA_displayQuery($insert_query);
573 PMA_DBI_try_query($insert_query, $trg_link, 0);
581 * PMA_createTargetTables() Create the missing table $uncommon_table in target database
583 * @param string $src_db name of source database
584 * @param string $trg_db name of target database
585 * @param mixed $src_link connection established with source server
586 * @param mixed $trg_link connection established with target server
587 * @param array &$uncommon_tables names of tables present in source but not in target
588 * @param int $table_index index of table in $uncommon_tables array
589 * @param array &$uncommon_tables_fields field names of the uncommon table
590 * @param bool $display
592 function PMA_createTargetTables($src_db, $trg_db, $src_link, $trg_link, &$uncommon_tables, $table_index, &$uncommon_tables_fields, $display)
594 if (isset($uncommon_tables[$table_index])) {
595 $fields_result = PMA_DBI_get_columns($src_db, $uncommon_tables[$table_index], true, $src_link);
596 $fields = array();
597 foreach ($fields_result as $each_field) {
598 $field_name = $each_field['Field'];
599 $fields[] = $field_name;
601 $uncommon_tables_fields[$table_index] = $fields;
603 $Create_Query = PMA_DBI_fetch_value("SHOW CREATE TABLE " . PMA_backquote($src_db) . '.' . PMA_backquote($uncommon_tables[$table_index]), 0, 1, $src_link);
605 // Replace the src table name with a `dbname`.`tablename`
606 $Create_Table_Query = preg_replace('/' . preg_quote(PMA_backquote($uncommon_tables[$table_index]), '/') . '/',
607 PMA_backquote($trg_db) . '.' .PMA_backquote($uncommon_tables[$table_index]),
608 $Create_Query,
609 $limit = 1
612 $is_fk_query = "SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = '" . $src_db . "'
613 AND TABLE_NAME = '" . $uncommon_tables[$table_index] . "' AND TABLE_NAME <> REFERENCED_TABLE_NAME;" ;
615 $is_fk_result = PMA_DBI_fetch_result($is_fk_query, null, null, $src_link);
616 if (sizeof($is_fk_result) > 0) {
617 for ($j = 0; $j < sizeof($is_fk_result); $j++)
619 if (in_array($is_fk_result[$j]['REFERENCED_TABLE_NAME'], $uncommon_tables)) {
620 $table_index = array_keys($uncommon_tables, $is_fk_result[$j]['REFERENCED_TABLE_NAME']);
621 PMA_createTargetTables($src_db, $trg_db, $trg_link, $src_link, $uncommon_tables, $table_index[0], $uncommon_tables_fields, $display);
622 unset($uncommon_tables[$table_index[0]]);
626 if ($display == true) {
627 echo '<p>' . $Create_Table_Query . '</p>';
629 PMA_DBI_try_query($Create_Table_Query, $trg_link, 0);
633 * PMA_populateTargetTables() inserts data into uncommon tables after they have been created
635 * @param string $src_db name of source database
636 * @param string $trg_db name of target database
637 * @param mixed $src_link connection established with source server
638 * @param mixed $trg_link connection established with target server
639 * @param array $uncommon_tables uncommon table names (table names that are present in source but not in target db)
640 * @param int $table_index index of table in matching_table_array
641 * @param array $uncommon_tables_fields field names of the uncommon table
642 * @param bool $display
644 * @todo This turns NULL values into '' (empty string)
646 function PMA_populateTargetTables($src_db, $trg_db, $src_link, $trg_link, $uncommon_tables, $table_index, $uncommon_tables_fields, $display)
648 $display = false; // todo: maybe display some of the queries if they are not too numerous
649 $unbuffered_result = PMA_DBI_try_query('SELECT * FROM ' . PMA_backquote($src_db) . '.' . PMA_backquote($uncommon_tables[$table_index]), $src_link, PMA_DBI_QUERY_UNBUFFERED);
650 if (false !== $unbuffered_result) {
651 $insert_query = 'INSERT INTO ' . PMA_backquote($trg_db) . '.' .PMA_backquote($uncommon_tables[$table_index]) . ' VALUES';
652 while ($one_row = PMA_DBI_fetch_row($unbuffered_result)) {
653 $insert_query .= '(';
654 $key_of_last_value = count($one_row) - 1;
655 foreach ($one_row as $key => $value) {
656 $insert_query .= "'" . PMA_sqlAddSlashes($value) . "'";
657 if ($key < $key_of_last_value) {
658 $insert_query .= ",";
661 $insert_query .= '),';
663 $insert_query = substr($insert_query, 0, -1);
664 $insert_query .= ';';
665 if ($display == true) {
666 PMA_displayQuery($insert_query);
668 PMA_DBI_try_query($insert_query, $trg_link, 0);
673 * PMA_deleteFromTargetTable() delete rows from target table
675 * @param string $trg_db name of target database
676 * @param mixed $trg_link connection established with target server
677 * @param array $matching_tables matching table names
678 * @param int $table_index index of table in matching_table_array
679 * @param array $target_tables_keys primary key names of the target tables
680 * @param array $delete_array key values of rows that are to be deleted
681 * @param bool $display
683 function PMA_deleteFromTargetTable($trg_db, $trg_link, $matching_tables, $table_index, $target_tables_keys, $delete_array, $display)
685 for ($i = 0; $i < sizeof($delete_array[$table_index]); $i++) {
686 if (isset($target_tables_keys[$table_index])) {
687 $delete_query = 'DELETE FROM ' . PMA_backquote($trg_db) . '.' .PMA_backquote($matching_tables[$table_index]) . ' WHERE ';
688 for ($y = 0; $y < sizeof($target_tables_keys[$table_index]); $y++) {
689 $delete_query .= $target_tables_keys[$table_index][$y] . " = '";
691 if (sizeof($target_tables_keys[$table_index]) == 1) {
692 $delete_query .= $delete_array[$table_index][$i] . "'";
693 } elseif (sizeof($target_tables_keys[$table_index]) > 1) {
694 $delete_query .= $delete_array[$table_index][$i][$target_tables_keys[$table_index][$y]] . "'";
696 if ($y < (sizeof($target_tables_keys[$table_index]) - 1)) {
697 $delete_query .= ' AND ';
699 $pk_query = "SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_SCHEMA = '" . $trg_db . "'
700 AND REFERENCED_TABLE_NAME = '" . $matching_tables[$table_index]."' AND REFERENCED_COLUMN_NAME = '"
701 . $target_tables_keys[$table_index][$y] . "' AND TABLE_NAME <> REFERENCED_TABLE_NAME;";
703 $pk_query_result = PMA_DBI_fetch_result($pk_query, null, null, $trg_link);
704 $result_size = sizeof($pk_query_result);
706 if ($result_size > 0) {
707 for ($b = 0; $b < $result_size; $b++) {
708 $drop_pk_query = "DELETE FROM " . PMA_backquote($pk_query_result[$b]['TABLE_SCHEMA']) . "." . PMA_backquote($pk_query_result[$b]['TABLE_NAME']) . " WHERE " . $pk_query_result[$b]['COLUMN_NAME'] . " = " . $target_tables_keys[$table_index][$y] . ";";
709 PMA_DBI_try_query($drop_pk_query, $trg_link, 0);
714 if ($display == true) {
715 echo '<p>' . $delete_query . '</p>';
717 PMA_DBI_try_query($delete_query, $trg_link, 0);
722 * PMA_structureDiffInTables() Gets all the column information for source and target table.
723 * Compare columns on their names.
724 * If column exists in target then compare Type, Null, Collation, Key, Default and Comment for that column.
725 * If column does not exist in target table then it is placed in $add_column_array.
726 * If column exists in target table but criteria is different then it is palced in $alter_str_array.
727 * If column does not exist in source table but is present in target table then it is placed in $uncommon_columns.
728 * Keys for all the source tables that have a corresponding target table are placed in $matching_tables_keys.
729 * Keys for all the target tables that have a corresponding source table are placed in $target_tables_keys.
731 * @param string $src_db name of source database
732 * @param string $trg_db name of target database
733 * @param mixed $src_link connection established with source server
734 * @param mixed $trg_link connection established with target server
735 * @param array $matching_tables names of matching tables
736 * @param array &$source_columns columns information of the source tables
737 * @param array &$target_columns columns information of the target tables
738 * @param array &$alter_str_array three dimensional associative array first index being the matching table index, second index being column name for which target
739 * column have some criteria different and third index containing the criteria which is different.
740 * @param array &$add_column_array two dimensional associative array, first index of the array contain the matching table number and second index contain the
741 * column name which is to be added in the target table
742 * @param array &$uncommon_columns columns that are present in the target table but not in the source table
743 * @param array $criteria criteria which are to be checked for field that is present in source table and target table
744 * @param array &$target_tables_keys field names which is key in the target table
745 * @param int $matching_table_index number of the matching table
747 function PMA_structureDiffInTables($src_db, $trg_db, $src_link, $trg_link, $matching_tables, &$source_columns, &$target_columns, &$alter_str_array,
748 &$add_column_array, &$uncommon_columns, $criteria, &$target_tables_keys, $matching_table_index)
750 //Gets column information for source and target table
751 $source_columns[$matching_table_index] = PMA_DBI_get_columns_full($src_db, $matching_tables[$matching_table_index], null, $src_link);
752 $target_columns[$matching_table_index] = PMA_DBI_get_columns_full($trg_db, $matching_tables[$matching_table_index], null, $trg_link);
753 foreach ($source_columns[$matching_table_index] as $column_name => $each_column) {
754 if (isset($target_columns[$matching_table_index][$column_name]['Field'])) {
755 //If column exists in target table then matches criteria like type, null, collation, key, default, comment of the column
756 for ($i = 0; $i < sizeof($criteria); $i++) {
757 if ($source_columns[$matching_table_index][$column_name][$criteria[$i]] != $target_columns[$matching_table_index][$column_name][$criteria[$i]]) {
758 if (($criteria[$i] == 'Default') && ($source_columns[$matching_table_index][$column_name][$criteria[$i]] == '' )) {
759 $alter_str_array[$matching_table_index][$column_name][$criteria[$i]] = 'None';
760 } else {
761 if (! (($criteria[$i] == 'Key') && (($source_columns[$matching_table_index][$column_name][$criteria[$i]] == 'MUL')
762 || ($target_columns[$matching_table_index][$column_name][$criteria[$i]] == 'MUL')
763 || ($source_columns[$matching_table_index][$column_name][$criteria[$i]] == 'UNI')
764 || ($target_columns[$matching_table_index][$column_name][$criteria[$i]] == 'UNI')))) {
765 $alter_str_array[$matching_table_index][$column_name][$criteria[$i]] = $source_columns[$matching_table_index][$column_name][$criteria[$i]];
770 } else {
771 $add_column_array[$matching_table_index][$column_name]= $column_name;
774 //Finds column names that are present in target table but not in source table
775 foreach ($target_columns[$matching_table_index] as $fld_name => $each_column) {
776 if (! (isset($source_columns[$matching_table_index][$fld_name]['Field']))) {
777 $fields_uncommon[] = $fld_name;
779 if ($target_columns[$matching_table_index][$fld_name]['Key'] == 'PRI') {
780 $keys[] = $fld_name;
783 if (isset($fields_uncommon)) {
784 $uncommon_columns[$matching_table_index] = $fields_uncommon;
786 if (isset($keys)) {
787 $target_tables_keys[$matching_table_index] = $keys;
791 * PMA_addColumnsInTargetTable() adds column that are present in source table but not in target table
793 * @param string $src_db name of source database
794 * @param string $trg_db name of target database
795 * @param mixed $src_link connection established with source server
796 * @param mixed $trg_link connection established with target server
797 * @param array $matching_tables names of matching tables
798 * @param array $source_columns columns information of the source tables
799 * @param array &$add_column_array the names of the column(field) that are to be added in the target
800 * @param array $matching_tables_fields
801 * @param array $criteria criteria
802 * @param array $matching_tables_keys field names which is key in the source table
803 * @param array $target_tables_keys field names which is key in the target table
804 * @param array $uncommon_tables table names that are present in source db and not in target db
805 * @param array &$uncommon_tables_fields names of the fields of the uncommon tables
806 * @param int $table_counter number of the matching table
807 * @param array $uncommon_cols
808 * @param bool $display
810 function PMA_addColumnsInTargetTable($src_db, $trg_db, $src_link, $trg_link, $matching_tables, $source_columns, &$add_column_array, $matching_tables_fields,
811 $criteria, $matching_tables_keys, $target_tables_keys, $uncommon_tables, &$uncommon_tables_fields, $table_counter, $uncommon_cols, $display)
813 for ($i = 0; $i < sizeof($matching_tables_fields[$table_counter]); $i++) {
814 if (isset($add_column_array[$table_counter][$matching_tables_fields[$table_counter][$i]])) {
815 $query = "ALTER TABLE " . PMA_backquote($trg_db) . '.' . PMA_backquote($matching_tables[$table_counter]). " ADD COLUMN " .
816 $add_column_array[$table_counter][$matching_tables_fields[$table_counter][$i]] . " " . $source_columns[$table_counter][$matching_tables_fields[$table_counter][$i]]['Type'];
818 if ($source_columns[$table_counter][$matching_tables_fields[$table_counter][$i]]['Null'] == 'NO') {
819 $query .= ' Not Null ';
820 } elseif ($source_columns[$table_counter][$matching_tables_fields[$table_counter][$i]]['Null'] == 'YES') {
821 $query .= ' Null ';
823 if ($source_columns[$table_counter][$matching_tables_fields[$table_counter][$i]]['Collation'] != '') {
824 $query .= ' COLLATE ' . $source_columns[$table_counter][$matching_tables_fields[$table_counter][$i]]['Collation'];
826 if ($source_columns[$table_counter][$matching_tables_fields[$table_counter][$i]]['Default'] != '') {
827 $query .= " DEFAULT " . $source_columns[$table_counter][$matching_tables_fields[$table_counter][$i]]['Default'];
829 if ($source_columns[$table_counter][$matching_tables_fields[$table_counter][$i]]['Comment'] != '') {
830 $query .= " COMMENT " . $source_columns[$table_counter][$matching_tables_fields[$table_counter][$i]]['Comment'];
832 if ($source_columns[$table_counter][$matching_tables_fields[$table_counter][$i]]['Key'] == 'PRI' ) {
833 $trg_key_size = sizeof($target_tables_keys[$table_counter]);
834 if ($trg_key_size) {
835 $check = true;
836 for ($a = 0; ($a < $trg_key_size) && ($check); $a++) {
837 if (! (in_array($target_tables_keys[$table_counter], $uncommon_cols))) {
838 $check = false;
841 if (! $check) {
842 $query .= " ,DROP PRIMARY KEY " ;
845 $query .= " , ADD PRIMARY KEY (";
846 for ($t = 0; $t < sizeof($matching_tables_keys[$table_counter]); $t++) {
847 $query .= $matching_tables_keys[$table_counter][$t];
848 if ($t < (sizeof($matching_tables_keys[$table_counter]) - 1)) {
849 $query .= " , " ;
852 $query .= ")";
855 $query .= ";";
856 if ($display == true) {
857 echo '<p>' . $query . '</p>';
859 PMA_DBI_try_query($query, $trg_link, 0);
861 //Checks if column to be added is a foreign key or not
862 $is_fk_query = "SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = '" . $trg_db . "' AND TABLE_NAME = '"
863 . $matching_tables[$table_counter] . "' AND COLUMN_NAME ='" . $add_column_array[$table_counter][$matching_tables_fields[$table_counter][$i]] .
864 "' AND TABLE_NAME <> REFERENCED_TABLE_NAME;";
866 $is_fk_result = PMA_DBI_fetch_result($is_fk_query, null, null, $src_link);
868 //If column is a foreign key then it is checked that referenced table exist in target db. If referenced table does not exist in target db then
869 //it is created first.
870 if (isset($is_fk_result)) {
871 if (in_array($is_fk_result[0]['REFERENCED_TABLE_NAME'], $uncommon_tables)) {
872 $table_index = array_keys($uncommon_tables, $is_fk_result[0]['REFERENCED_TABLE_NAME']);
873 PMA_checkForeignKeys($src_db, $src_link, $trg_db, $trg_link, $is_fk_result[0]['REFERENCED_TABLE_NAME'], $uncommon_tables, $uncommon_tables_fields);
874 PMA_createTargetTables($src_db, $trg_db, $trg_link, $src_link, $uncommon_tables, $table_index[0], $uncommon_tables_fields);
875 unset($uncommon_tables[$table_index[0]]);
877 $fk_query = "ALTER TABLE " . PMA_backquote($trg_db) . '.' . PMA_backquote($matching_tables[$table_counter]) .
878 "ADD CONSTRAINT FOREIGN KEY " . $add_column_array[$table_counter][$matching_tables_fields[$table_counter][$i]] . "
879 (" . $add_column_array[$table_counter][$matching_tables_fields[$table_counter][$i]] . ") REFERENCES " . PMA_backquote($trg_db) .
880 '.' . PMA_backquote($is_fk_result[0]['REFERENCED_TABLE_NAME']) . " (" . $is_fk_result[0]['REFERENCED_COLUMN_NAME'] . ");";
882 PMA_DBI_try_query($fk_query, $trg_link, null);
888 * PMA_checkForeignKeys() checks if the referenced table have foreign keys.
889 * uses PMA_createTargetTables()
891 * @param string $src_db name of source database
892 * @param mixed $src_link connection established with source server
893 * @param string $trg_db name of target database
894 * @param mixed $trg_link connection established with target server
895 * @param string $referenced_table table whose column is a foreign key in another table
896 * @param array &$uncommon_tables names that are uncommon
897 * @param array &$uncommon_tables_fields field names of the uncommon table
898 * @param bool $display
900 function PMA_checkForeignKeys($src_db, $src_link, $trg_db, $trg_link, $referenced_table, &$uncommon_tables, &$uncommon_tables_fields, $display)
902 $is_fk_query = "SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = '" . $src_db . "'
903 AND TABLE_NAME = '" . $referenced_table . "' AND TABLE_NAME <> REFERENCED_TABLE_NAME;";
905 $is_fk_result = PMA_DBI_fetch_result($is_fk_query, null, null, $src_link);
906 if (sizeof($is_fk_result) > 0) {
907 for ($j = 0; $j < sizeof($is_fk_result); $j++) {
908 if (in_array($is_fk_result[$j]['REFERENCED_TABLE_NAME'], $uncommon_tables)) {
909 $table_index = array_keys($uncommon_tables, $is_fk_result[$j]['REFERENCED_TABLE_NAME']);
910 PMA_checkForeignKeys($src_db, $src_link, $trg_db, $trg_link, $is_fk_result[$j]['REFERENCED_TABLE_NAME'], $uncommon_tables,
911 $uncommon_tables_fields, $display);
912 PMA_createTargetTables($src_db, $trg_db, $trg_link, $src_link, $uncommon_tables, $table_index[0], $uncommon_tables_fields, $display);
913 unset($uncommon_tables[$table_index[0]]);
919 * PMA_alterTargetTableStructure() alters structure of the target table using $alter_str_array
921 * @param string $trg_db name of target database
922 * @param mixed $trg_link connection established with target server
923 * @param array $matching_tables names of matching tables
924 * @param array &$source_columns columns information of the source table
925 * @param array &$alter_str_array column name and criteria which is to be altered for the targert table
926 * @param array $matching_tables_fields name of the fields for the matching table
927 * @param array $criteria criteria
928 * @param array &$matching_tables_keys field names which is key in the source table
929 * @param array &$target_tables_keys field names which is key in the target table
930 * @param int $matching_table_index number of the matching table
931 * @param bool $display
933 function PMA_alterTargetTableStructure($trg_db, $trg_link, $matching_tables, &$source_columns, &$alter_str_array, $matching_tables_fields, $criteria,
934 &$matching_tables_keys, &$target_tables_keys, $matching_table_index, $display)
936 $check = true;
937 $sql_query = '';
938 $found = false;
940 //Checks if the criteria to be altered is primary key
941 for ($v = 0; $v < sizeof($matching_tables_fields[$matching_table_index]); $v++) {
942 if (isset($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$v]]['Key'])) {
943 if ($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$v]]['Key'] == 'PRI' ) {
944 $check = false;
949 $pri_query = null;
950 if (! $check) {
951 $pri_query = "ALTER TABLE " . PMA_backquote($trg_db) . '.' . PMA_backquote($matching_tables[$matching_table_index]);
952 if (sizeof($target_tables_keys[$matching_table_index]) > 0) {
953 $pri_query .= " DROP PRIMARY KEY ," ;
955 $pri_query .= " ADD PRIMARY KEY (";
956 for ($z = 0; $z < sizeof($matching_tables_keys[$matching_table_index]); $z++) {
957 $pri_query .= $matching_tables_keys[$matching_table_index][$z];
958 if ($z < (sizeof($matching_tables_keys[$matching_table_index]) - 1)) {
959 $pri_query .= " , " ;
962 $pri_query .= ");";
965 if (isset($pri_query)) {
966 if ($display == true) {
967 echo '<p>' . $pri_query . '</p>';
969 PMA_DBI_try_query($pri_query, $trg_link, 0);
971 for ($t = 0; $t < sizeof($matching_tables_fields[$matching_table_index]); $t++) {
972 if ((isset($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]])) && (sizeof($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]]) > 0)) {
973 $sql_query = 'ALTER TABLE ' . PMA_backquote($trg_db) . '.' . PMA_backquote($matching_tables[$matching_table_index]) . ' MODIFY ' .
974 $matching_tables_fields[$matching_table_index][$t] . ' ' . $source_columns[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]]['Type'];
975 $found = false;
976 for ($i = 0; $i < sizeof($criteria); $i++)
978 if (isset($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i]]) && $criteria[$i] != 'Key') {
979 $found = true;
980 if (($criteria[$i] == 'Type') && (! isset($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i+1]]))) {
981 if ($source_columns[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i + 1]] == 'NO') {
982 $sql_query .= " Not Null" ;
983 } elseif ($source_columns[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i + 1]] == 'YES') {
984 $sql_query .= " Null" ;
987 if (($criteria[$i] == 'Null') && ( $alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i]] == 'NO')) {
988 $sql_query .= " Not Null " ;
989 } elseif (($criteria[$i] == 'Null') && ($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i]] == 'YES')) {
990 $sql_query .= " Null " ;
992 if ($criteria[$i] == 'Collation') {
993 if ( !(isset($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[2]]))) {
994 $sql_query .= " Not Null " ;
996 $sql_query .= " COLLATE " . $alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i]] ;
998 if (($criteria[$i] == 'Default') && ($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i]] == 'None')) {
999 if ( !(isset($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[2]]))) {
1000 $sql_query .= " Not Null " ;
1002 } elseif ($criteria[$i] == 'Default') {
1003 if (! (isset($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[2]]))) {
1004 $sql_query .= " Not Null " ;
1006 if (is_string($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i]])) {
1007 if ($source_columns[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]]['Type'] != 'timestamp') {
1008 $sql_query .= " DEFAULT '" . $alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i]] . "'";
1009 } elseif ($source_columns[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]]['Type'] == 'timestamp') {
1010 $sql_query .= " DEFAULT " . $alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i]];
1012 } elseif (is_numeric($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i]])) {
1013 $sql_query .= " DEFAULT " . $alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i]];
1016 if ($criteria[$i] == 'Comment') {
1017 if ( !(isset($alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[2]]))) {
1018 $sql_query .= " Not Null " ;
1020 $sql_query .= " COMMENT '" . $alter_str_array[$matching_table_index][$matching_tables_fields[$matching_table_index][$t]][$criteria[$i]] . "'" ;
1025 $sql_query .= ";";
1026 if ($found) {
1027 if ($display == true) {
1028 echo '<p>' . $sql_query . '</p>';
1030 PMA_DBI_try_query($sql_query, $trg_link, 0);
1033 $check = false;
1034 $query = "ALTER TABLE " . PMA_backquote($trg_db) . '.' . PMA_backquote($matching_tables[$matching_table_index]);
1035 for ($p = 0; $p < sizeof($matching_tables_keys[$matching_table_index]); $p++) {
1036 if ((isset($alter_str_array[$matching_table_index][$matching_tables_keys[$matching_table_index][$p]]['Key']))) {
1037 $check = true;
1038 $query .= ' MODIFY ' . $matching_tables_keys[$matching_table_index][$p] . ' '
1039 . $source_columns[$matching_table_index][$matching_tables_fields[$matching_table_index][$p]]['Type'] . ' Not Null ';
1040 if ($p < (sizeof($matching_tables_keys[$matching_table_index]) - 1)) {
1041 $query .= ', ';
1045 if ($check) {
1046 if ($display == true) {
1047 echo '<p>' . $query . '</p>';
1049 PMA_DBI_try_query($query, $trg_link, 0);
1054 * PMA_removeColumnsFromTargetTable() removes the columns which are present in target table but not in source table.
1056 * @param string $trg_db name of target database
1057 * @param mixed $trg_link connection established with target server
1058 * @param array $matching_tables names of matching tables
1059 * @param array $uncommon_columns array containing the names of the column which are to be dropped from the target table
1060 * @param int $table_counter index of the matching table as in $matchiing_tables array
1061 * @param bool $display
1063 function PMA_removeColumnsFromTargetTable($trg_db, $trg_link, $matching_tables, $uncommon_columns, $table_counter, $display)
1065 if (isset($uncommon_columns[$table_counter])) {
1066 $drop_query = "ALTER TABLE " . PMA_backquote($trg_db) . "." . PMA_backquote($matching_tables[$table_counter]);
1067 for ($a = 0; $a < sizeof($uncommon_columns[$table_counter]); $a++) {
1068 //Checks if column to be removed is a foreign key in any table
1069 $pk_query = "SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_SCHEMA = '" . $trg_db . "'
1070 AND REFERENCED_TABLE_NAME = '" . $matching_tables[$table_counter]."' AND REFERENCED_COLUMN_NAME = '"
1071 . $uncommon_columns[$table_counter][$a] . "' AND TABLE_NAME <> REFERENCED_TABLE_NAME;";
1073 $pk_query_result = PMA_DBI_fetch_result($pk_query, null, null, $trg_link);
1074 $result_size = sizeof($pk_query_result);
1076 if ($result_size > 0) {
1077 for ($b = 0; $b < $result_size; $b++) {
1078 $drop_pk_query = "ALTER TABLE " . PMA_backquote($pk_query_result[$b]['TABLE_SCHEMA']) . "." . PMA_backquote($pk_query_result[$b]['TABLE_NAME']) . "
1079 DROP FOREIGN KEY " . $pk_query_result[$b]['CONSTRAINT_NAME'] . ", DROP COLUMN " . $pk_query_result[$b]['COLUMN_NAME'] . ";";
1080 PMA_DBI_try_query($drop_pk_query, $trg_link, 0);
1083 $query = "SELECT * FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA = '" . $trg_db . "' AND TABLE_NAME = '"
1084 . $matching_tables[$table_counter]. "' AND COLUMN_NAME = '" . $uncommon_columns[$table_counter][$a] . "'
1085 AND TABLE_NAME <> REFERENCED_TABLE_NAME;";
1087 $result = PMA_DBI_fetch_result($query, null, null, $trg_link);
1089 if (sizeof($result) > 0) {
1090 $drop_query .= " DROP FOREIGN KEY " . $result[0]['CONSTRAINT_NAME'] . ",";
1092 $drop_query .= " DROP COLUMN " . $uncommon_columns[$table_counter][$a];
1093 if ($a < (sizeof($uncommon_columns[$table_counter]) - 1)) {
1094 $drop_query .= " , " ;
1097 $drop_query .= ";" ;
1099 if ($display == true) {
1100 echo '<p>' . $drop_query . '</p>';
1102 PMA_DBI_try_query($drop_query, $trg_link, 0);
1107 * PMA_indexesDiffInTables() compares the source table indexes with target table indexes and keep the indexes to be added in target table in $add_indexes_array
1108 * indexes to be altered in $alter_indexes_array and indexes to be removed from target table in $remove_indexes_array.
1109 * Only keyname and uniqueness characteristic of the indexes are altered.
1111 * @param string $src_db name of source database
1112 * @param string $trg_db name of target database
1113 * @param mixed $src_link connection established with source server
1114 * @param mixed $trg_link connection established with target server
1115 * @param array $matching_tables matching tables name
1116 * @param array &$source_indexes indexes of the source table
1117 * @param array &$target_indexes indexes of the target table
1118 * @param array &$add_indexes_array name of the column on which the index is to be added in the target table
1119 * @param array &$alter_indexes_array key name which needs to be altered
1120 * @param array &$remove_indexes_array key name of the index which is to be removed from the target table
1121 * @param int $table_counter number of the matching table
1123 function PMA_indexesDiffInTables($src_db, $trg_db, $src_link, $trg_link, $matching_tables, &$source_indexes, &$target_indexes, &$add_indexes_array,
1124 &$alter_indexes_array, &$remove_indexes_array, $table_counter)
1126 //Gets indexes information for source and target table
1127 $source_indexes[$table_counter] = PMA_get_table_indexes($src_db, $matching_tables[$table_counter],$src_link);
1128 $target_indexes[$table_counter] = PMA_get_table_indexes($trg_db, $matching_tables[$table_counter],$trg_link);
1129 for ($a = 0; $a < sizeof($source_indexes[$table_counter]); $a++) {
1130 $found = false;
1131 $z = 0;
1132 //Compares key name and non_unique characteristic of source indexes with target indexes
1134 * @todo compare the length of each sub part
1136 while (($z <= sizeof($target_indexes[$table_counter])) && ($found == false))
1138 if (isset($source_indexes[$table_counter][$a]) && isset($target_indexes[$table_counter][$z]) && $source_indexes[$table_counter][$a]['Key_name'] == $target_indexes[$table_counter][$z]['Key_name']) {
1139 $found = true;
1140 if (($source_indexes[$table_counter][$a]['Column_name'] != $target_indexes[$table_counter][$z]['Column_name']) || ($source_indexes[$table_counter][$a]['Non_unique'] != $target_indexes[$table_counter][$z]['Non_unique'])) {
1141 if (! (($source_indexes[$table_counter][$a]['Key_name'] == "PRIMARY") || ($target_indexes[$table_counter][$z]['Key_name'] == 'PRIMARY'))) {
1142 $alter_indexes_array[$table_counter][] = $source_indexes[$table_counter][$a]['Key_name'];
1146 $z++;
1148 if ($found === false) {
1149 if (! ($source_indexes[$table_counter][$a]['Key_name'] == 'PRIMARY')) {
1150 $add_indexes_array [$table_counter][] = $source_indexes[$table_counter][$a]['Column_name'];
1155 //Finds indexes that exist on target table but not on source table
1156 for ($b = 0; $b < sizeof($target_indexes[$table_counter]); $b++) {
1157 $found = false;
1158 $c = 0;
1159 while (($c <= sizeof($source_indexes[$table_counter])) && ($found == false))
1161 if ($target_indexes[$table_counter][$b]['Column_name'] == $source_indexes[$table_counter][$c]['Column_name']) {
1162 $found = true;
1164 $c++;
1166 if ($found === false) {
1167 $remove_indexes_array[$table_counter][] = $target_indexes[$table_counter][$b]['Key_name'];
1173 * PMA_applyIndexesDiff() create indexes, alters indexes and remove indexes.
1175 * @param string $trg_db name of target database
1176 * @param mixed $trg_link connection established with target server
1177 * @param array $matching_tables matching tables name
1178 * @param array $source_indexes indexes of the source table
1179 * @param array $target_indexes indexes of the target table
1180 * @param array $add_indexes_array column names on which indexes are to be created in target table
1181 * @param array $alter_indexes_array column names for which indexes are to be altered
1182 * @param array $remove_indexes_array key name of the indexes which are to be removed from the target table
1183 * @param int $table_counter number of the matching table
1184 * @param $display
1186 function PMA_applyIndexesDiff ($trg_db, $trg_link, $matching_tables, $source_indexes, $target_indexes, $add_indexes_array, $alter_indexes_array,
1187 $remove_indexes_array, $table_counter, $display)
1189 //Adds indexes on target table
1190 if (isset($add_indexes_array[$table_counter])) {
1191 $sql = "ALTER TABLE " . PMA_backquote($trg_db) . "." . PMA_backquote($matching_tables[$table_counter]) . " ADD" ;
1192 for ($a = 0; $a < sizeof($source_indexes[$table_counter]); $a++) {
1193 if (isset($add_indexes_array[$table_counter][$a])) {
1194 for ($b = 0; $b < sizeof($source_indexes[$table_counter]); $b++) {
1195 if ($source_indexes[$table_counter][$b]['Column_name'] == $add_indexes_array[$table_counter][$a]) {
1196 if ($source_indexes[$table_counter][$b]['Non_unique'] == '0') {
1197 $sql .= " UNIQUE ";
1199 $sql .= " INDEX " . $source_indexes[$table_counter][$b]['Key_name'] . " (" . $add_indexes_array[$table_counter][$a] . " );";
1200 if ($display == true) {
1201 echo '<p>' . $sql . '</p>';
1203 PMA_DBI_try_query($sql, $trg_link, 0);
1209 //Alter indexes of target table
1211 if (isset($alter_indexes_array[$table_counter])) {
1212 $query = "ALTER TABLE " . PMA_backquote($trg_db) . "." . PMA_backquote($matching_tables[$table_counter]);
1213 for ($a = 0; $a < sizeof($alter_indexes_array[$table_counter]); $a++) {
1214 if (isset($alter_indexes_array[$table_counter][$a])) {
1215 $query .= ' DROP INDEX ' . PMA_backquote($alter_indexes_array[$table_counter][$a]) . " , ADD ";
1216 $got_first_index_column = false;
1217 for ($z = 0; $z < sizeof($source_indexes[$table_counter]); $z++) {
1218 if ($source_indexes[$table_counter][$z]['Key_name'] == $alter_indexes_array[$table_counter][$a]) {
1219 if (! $got_first_index_column) {
1220 if ($source_indexes[$table_counter][$z]['Non_unique'] == '0') {
1221 $query .= " UNIQUE ";
1223 $query .= " INDEX " . PMA_backquote($source_indexes[$table_counter][$z]['Key_name']) . " (" . PMA_backquote($source_indexes[$table_counter][$z]['Column_name']);
1224 $got_first_index_column = true;
1225 } else {
1226 // another column for this index
1227 $query .= ', ' . PMA_backquote($source_indexes[$table_counter][$z]['Column_name']);
1231 $query .= " )";
1234 if ($display == true) {
1235 echo '<p>' . $query . '</p>';
1237 PMA_DBI_try_query($query, $trg_link, 0);
1239 //Removes indexes from target table
1240 if (isset($remove_indexes_array[$table_counter])) {
1241 $drop_index_query = "ALTER TABLE " . PMA_backquote($trg_db) . "." . PMA_backquote($matching_tables[$table_counter]);
1242 for ($a = 0; $a < sizeof($target_indexes[$table_counter]); $a++) {
1243 if (isset($remove_indexes_array[$table_counter][$a])) {
1244 $drop_index_query .= " DROP INDEX " . $remove_indexes_array[$table_counter][$a];
1246 if ($a < (sizeof($remove_indexes_array[$table_counter]) - 1)) {
1247 $drop_index_query .= " , " ;
1250 $drop_index_query .= " ; " ;
1251 if ($display == true) {
1252 echo '<p>' . $drop_index_query . '</p>';
1254 PMA_DBI_try_query($drop_index_query, $trg_link, 0);
1259 * PMA_displayQuery() displays a query, taking the maximum display size
1260 * into account
1262 * @param string $query the query to display
1264 function PMA_displayQuery($query) {
1265 if (strlen($query) > $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) {
1266 $query = substr($query, 0, $GLOBALS['cfg']['MaxCharactersInDisplayedSQL']) . '[...]';
1268 echo '<p>' . htmlspecialchars($query) . '</p>';
1272 * PMA_syncDisplayHeaderCompare() shows the header for source database
1274 * @param string $src_db source db name
1275 * @param string $trg_db target db name
1277 function PMA_syncDisplayHeaderCompare($src_db, $trg_db) {
1278 echo '<fieldset style="padding:0"><div style="padding:1.5em; overflow:auto; height:220px">';
1280 echo '<table class="data">';
1281 echo '<tr>';
1282 echo '<th>' . __('Source database') . ': ' . htmlspecialchars($src_db) . '<br />(';
1283 if ('cur' == $_SESSION['src_type']) {
1284 echo __('Current server');
1285 } else {
1286 echo __('Remote server') . ' ' . htmlspecialchars($_SESSION['src_server']['host']);
1288 echo ')</th>';
1289 echo '<th>' . __('Difference') . '</th>';
1290 echo '<th>' . __('Target database') . ': '. htmlspecialchars($trg_db) . '<br />(';
1291 if ('cur' == $_SESSION['trg_type']) {
1292 echo __('Current server');
1293 } else {
1294 echo __('Remote server') . ' ' . htmlspecialchars($_SESSION['trg_server']['host']);
1296 echo ')</th>';
1297 echo '</tr>';
1301 * Prints table row
1303 * $rows contains following keys:
1304 * - src_table_name - source server table name
1305 * - dst_table_name - target server table name
1306 * - btn_type - 'M' or 'U'
1307 * - btn_structure - null or arguments for showDetails in server_synchronize.js (without img_obj and table_name):
1308 * i, update_size, insert_size, remove_size, insert_index, remove_index
1310 * @param array $rows
1312 function PMA_syncDisplayDataCompare($rows) {
1313 global $pmaThemeImage;
1315 $odd_row = true;
1316 foreach ($rows as $row) {
1317 echo '<tr class=" ' . ($odd_row ? 'odd' : 'even') . '">';
1318 echo '<td>' . htmlspecialchars($row['src_table_name']) . '</td><td style="text-align:center">';
1319 if (isset($row['btn_structure']) && $row['btn_structure']) {
1320 // parameters: i, update_size, insert_size, remove_size, insert_index, remove_index
1321 $p = $row['btn_structure'];
1322 $p[0] = $row['btn_type'] . 'S' . $p[0];
1323 echo '<img class="icon struct_img" src="' . $pmaThemeImage . 'new_struct.png" width="16" height="16"
1324 alt="Structure" title="' . __('Click to select') . '" style="cursor:pointer" onclick="showDetails('
1325 . "'" . implode($p, "','") . "'"
1326 . ', this, ' . "'" . PMA_escapeJsString(htmlspecialchars($row['src_table_name'])) . "'" . ')" /> ';
1328 if (isset($row['btn_data']) && $row['btn_data']) {
1329 // parameters: i, update_size, insert_size, remove_size, insert_index, remove_index
1330 $p = $row['btn_data'];
1331 $p[0] = $row['btn_type'] . 'D' . $p[0];
1332 echo '<img class="icon data_img" src="' . $pmaThemeImage . 'new_data.png" width="16" height="16"
1333 alt="Data" title="' . __('Click to select') . '" style="cursor:pointer" onclick="showDetails('
1334 . "'" . implode($p, "','") . "'"
1335 . ', this, ' . "'" . PMA_escapeJsString(htmlspecialchars($row['src_table_name'])) . "'" . ')" />';
1337 echo '</td><td>' . htmlspecialchars($row['dst_table_name']) . '</td></tr>';
1338 $odd_row = !$odd_row;
1343 * array PMA_get_column_values (string $database, string $table, string $column , mysql db link $link = null)
1345 * @param string $database name of database
1346 * @param string $table name of table to retrieve columns from
1347 * @param string $column name of the column to retrieve data from
1348 * @param mixed $link mysql link resource
1349 * @return array $field_values
1351 function PMA_get_column_values($database, $table, $column, $link = null)
1353 $query = 'SELECT ';
1354 for ($i=0; $i< sizeof($column); $i++)
1356 $query.= PMA_backquote($column[$i]);
1357 if ($i < (sizeof($column)-1))
1359 $query.= ', ';
1362 $query.= ' FROM ' . PMA_backquote($database) . '.' . PMA_backquote($table);
1363 $field_values = PMA_DBI_fetch_result($query, null, null, $link);
1365 if (! is_array($field_values) || count($field_values) < 1) {
1366 return false;
1368 return $field_values;
1372 * array PMA_get_table_indexes($database, $table, $link = null)
1374 * @param string $database name of database
1375 * @param string $table name of the table whose indexes are to be retreived
1376 * @param mixed $link mysql link resource
1377 * @return array $indexes
1379 function PMA_get_table_indexes($database, $table, $link = null)
1381 $indexes = PMA_DBI_fetch_result(
1382 'SHOW INDEXES FROM ' .PMA_backquote($database) . '.' . PMA_backquote($table),
1383 null, null, $link);
1385 if (!is_array($indexes) || count($indexes) == 0) {
1386 return null;
1388 return $indexes;