[ Index ] |
PHP Cross Reference of BackPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Parses SQL schema statements for comparison to real table structures 4 * 5 * @package BackPress 6 **/ 7 class BP_SQL_Schema_Parser 8 { 9 /** 10 * Builds a column definition as used in CREATE TABLE statements from 11 * an array such as those returned by DESCRIBE `foo` statements 12 */ 13 function get_column_definition( $column_data ) 14 { 15 if ( !is_array( $column_data ) ) { 16 return $column_data; 17 } 18 19 $null = ''; 20 if ( $column_data['Null'] != 'YES' ) { 21 $null = 'NOT NULL'; 22 } 23 24 $default = ''; 25 26 // Defaults aren't allowed at all on certain column types 27 if ( !in_array( 28 strtolower( $column_data['Type'] ), 29 array( 'tinytext', 'text', 'mediumtext', 'longtext', 'blob', 'mediumblob', 'longblob' ) 30 ) ) { 31 if ( $column_data['Null'] == 'YES' && $column_data['Default'] === null ) { 32 $default = 'default NULL'; 33 } elseif ( preg_match( '@^\d+$@', $column_data['Default'] ) ) { 34 $default = 'default ' . $column_data['Default']; 35 } elseif ( is_string( $column_data['Default'] ) || is_float( $column_data['Default'] ) ) { 36 $default = 'default \'' . $column_data['Default'] . '\''; 37 } 38 } 39 40 $column_definition = '`' . $column_data['Field'] . '` ' . $column_data['Type'] . ' ' . $null . ' ' . $column_data['Extra'] . ' ' . $default; 41 return preg_replace( '@\s+@', ' ', trim( $column_definition ) ); 42 } 43 44 /** 45 * Builds an index definition as used in CREATE TABLE statements from 46 * an array similar to those returned by SHOW INDEX FROM `foo` statements 47 */ 48 function get_index_definition( $index_data ) 49 { 50 if ( !is_array( $index_data ) ) { 51 return $index_data; 52 } 53 54 if ( !count( $index_data ) ) { 55 return $index_data; 56 } 57 58 $_name = '`' . $index_data[0]['Key_name'] . '`'; 59 60 if ( $index_data[0]['Index_type'] == 'BTREE' && $index_data[0]['Key_name'] == 'PRIMARY' ) { 61 $_type = 'PRIMARY KEY'; 62 $_name = ''; 63 } elseif ( $index_data[0]['Index_type'] == 'BTREE' && !$index_data[0]['Non_unique'] ) { 64 $_type = 'UNIQUE KEY'; 65 } elseif ( $index_data[0]['Index_type'] == 'FULLTEXT' ) { 66 $_type = 'FULLTEXT KEY'; 67 } else { 68 $_type = 'KEY'; 69 } 70 71 $_columns = array(); 72 foreach ( $index_data as $_index ) { 73 if ( $_index['Sub_part'] ) { 74 $_columns[] = '`' . $_index['Column_name'] . '`(' . $_index['Sub_part'] . ')'; 75 } else { 76 $_columns[] = '`' . $_index['Column_name'] . '`'; 77 } 78 } 79 $_columns = join( ', ', $_columns ); 80 81 $index_definition = $_type . ' ' . $_name . ' (' . $_columns . ')'; 82 return preg_replace( '@\s+@', ' ', $index_definition ); 83 } 84 85 /** 86 * Returns a table structure from a raw sql query of the form "CREATE TABLE foo" etc. 87 * The resulting array contains the original query, the columns as would be returned by DESCRIBE `foo` 88 * and the indices as would be returned by SHOW INDEX FROM `foo` on a real table 89 */ 90 function describe_table( $query ) 91 { 92 // Retrieve the table structure from the query 93 if ( !preg_match( '@^CREATE\s+TABLE(\s+IF\s+NOT\s+EXISTS)?\s+`?([^\s|`]+)`?\s+\((.*)\)\s*([^\)|;]*)\s*;?@ims', $query, $_matches ) ) { 94 return $query; 95 } 96 97 $_if_not_exists = $_matches[1]; 98 99 // Tidy up the table name 100 $_table_name = trim( $_matches[2] ); 101 102 // Tidy up the table columns/indices 103 $_columns_indices = trim( $_matches[3], " \t\n\r\0\x0B," ); 104 // Split by commas not followed by a closing parenthesis ")", using fancy lookaheads 105 $_columns_indices = preg_split( '@,(?!(?:[^\(]+\)))$@ms', $_columns_indices ); 106 $_columns_indices = array_map( 'trim', $_columns_indices ); 107 108 // Tidy the table attributes 109 $_attributes = preg_replace( '@\s+@', ' ', trim( $_matches[4] ) ); 110 unset( $_matches ); 111 112 // Initialise some temporary arrays 113 $_columns = array(); 114 $_indices = array(); 115 116 // Loop over the columns/indices 117 foreach ( $_columns_indices as $_column_index ) { 118 if ( preg_match( '@^(PRIMARY\s+KEY|UNIQUE\s+(?:KEY|INDEX)|FULLTEXT\s+(?:KEY|INDEX)|KEY|INDEX)\s+(?:`?(\w+)`?\s+)*\((.+?)\)$@im', $_column_index, $_matches ) ) { 119 // It's an index 120 121 // Tidy the type 122 $_index_type = strtoupper( preg_replace( '@\s+@', ' ', trim( $_matches[1] ) ) ); 123 $_index_type = str_replace( 'INDEX', 'KEY', $_index_type ); 124 // Set the index name 125 $_index_name = ( 'PRIMARY KEY' == $_matches[1] ) ? 'PRIMARY' : $_matches[2]; 126 // Split into columns 127 $_index_columns = array_map( 'trim', explode( ',', $_matches[3] ) ); 128 129 foreach ( $_index_columns as $_index_columns_index => $_index_column ) { 130 preg_match( '@`?(\w+)`?(?:\s*\(\s*(\d+)\s*\))?@i', $_index_column, $_matches_column ); 131 132 $_indices[$_index_name][] = array( 133 'Table' => $_table_name, 134 'Non_unique' => ( 'UNIQUE KEY' == $_index_type || 'PRIMARY' == $_index_name ) ? '0' : '1', 135 'Key_name' => $_index_name, 136 'Seq_in_index' => (string) ( $_index_columns_index + 1 ), 137 'Column_name' => $_matches_column[1], 138 'Sub_part' => ( isset( $_matches_column[2] ) && $_matches_column[2] ) ? $_matches_column[2] : null, 139 'Index_type' => ( 'FULLTEXT KEY' == $_index_type ) ? 'FULLTEXT' : 'BTREE' 140 ); 141 } 142 unset( $_index_type, $_index_name, $_index_columns, $_index_columns_index, $_index_column, $_matches_column ); 143 144 } elseif ( preg_match( "@^`?(\w+)`?\s+(?:(\w+)(?:\s*\(\s*(\d+)\s*\))?(?:\s+(unsigned)){0,1})(?:\s+(NOT\s+NULL))?(?:\s+(auto_increment))?(?:\s+(default)\s+(?:(NULL|'[^']*'|\d+)))?@im", $_column_index, $_matches ) ) { 145 // It's a column 146 147 // Tidy the NOT NULL 148 $_matches[5] = isset( $_matches[5] ) ? strtoupper( preg_replace( '@\s+@', ' ', trim( $_matches[5] ) ) ) : ''; 149 150 $_columns[$_matches[1]] = array( 151 'Field' => $_matches[1], 152 'Type' => ( isset( $_matches[3] ) && is_numeric( $_matches[3] ) ) ? $_matches[2] . '(' . $_matches[3] . ')' . ( ( isset( $_matches[4] ) && strtolower( $_matches[4] ) == 'unsigned' ) ? ' unsigned' : '' ) : $_matches[2], 153 'Null' => ( 'NOT NULL' == strtoupper( $_matches[5] ) ) ? 'NO' : 'YES', 154 'Default' => ( isset( $_matches[7] ) && 'default' == strtolower( $_matches[7] ) && 'NULL' !== strtoupper( $_matches[8] ) ) ? trim( $_matches[8], "'" ) : null, 155 'Extra' => ( isset( $_matches[6] ) && 'auto_increment' == strtolower( $_matches[6] ) ) ? 'auto_increment' : '' 156 ); 157 } 158 } 159 unset( $_matches, $_columns_indices, $_column_index ); 160 161 // Tidy up the original query 162 $_tidy_query = 'CREATE TABLE'; 163 if ( $_if_not_exists ) { 164 $_tidy_query .= ' IF NOT EXISTS'; 165 } 166 $_tidy_query .= ' `' . $_table_name . '` (' . "\n"; 167 foreach ( $_columns as $_column ) { 168 $_tidy_query .= "\t" . BP_SQL_Schema_Parser::get_column_definition( $_column ) . ",\n"; 169 } 170 unset( $_column ); 171 foreach ( $_indices as $_index ) { 172 $_tidy_query .= "\t" . BP_SQL_Schema_Parser::get_index_definition( $_index ) . ",\n"; 173 } 174 $_tidy_query = substr( $_tidy_query, 0, -2 ) . "\n" . ') ' . $_attributes . ';'; 175 176 // Add to the query array using the table name as the index 177 $description = array( 178 'query_original' => $query, 179 'query_tidy' => $_tidy_query, 180 'columns' => $_columns, 181 'indices' => $_indices 182 ); 183 unset( $_table_name, $_columns, $_indices, $_tidy_query ); 184 185 return $description; 186 } 187 188 /** 189 * Helper function to flatten arrays 190 */ 191 function _flatten_array( $array, $cut_branch = 0, $keep_child_array_keys = true ) 192 { 193 if ( !is_array( $array ) ) { 194 return $array; 195 } 196 197 if ( empty( $array ) ) { 198 return null; 199 } 200 201 $temp = array(); 202 foreach ( $array as $k => $v ) { 203 if ( $cut_branch && $k == $cut_branch ) 204 continue; 205 if ( is_array( $v ) ) { 206 if ( $keep_child_array_keys ) { 207 $temp[$k] = true; 208 } 209 $temp += BP_SQL_Schema_Parser::_flatten_array( $v, $cut_branch, $keep_child_array_keys ); 210 } else { 211 $temp[$k] = $v; 212 } 213 } 214 return $temp; 215 } 216 217 /** 218 * Splits grouped SQL statements into queries within a highly structured array 219 * Only supports CREATE TABLE, INSERT and UPDATE 220 */ 221 function parse( $sql ) 222 { 223 // Only accept strings or arrays 224 if ( is_string( $sql ) ) { 225 // Just pop strings into an array to start with 226 $queries = array( $sql ); 227 } elseif ( is_array( $sql ) ) { 228 // Flatten the array 229 $queries = BP_SQL_Schema_Parser::_flatten_array( $sql, 0, false ); 230 // Remove empty nodes 231 $queries = array_filter( $queries ); 232 } else { 233 return false; 234 } 235 236 // Clean up the queries 237 $_clean_queries = array(); 238 foreach ( $queries as $_query ) { 239 // Trim space and semi-colons 240 $_query = trim( $_query, "; \t\n\r\0\x0B" ); 241 // If it exists and isn't a number 242 if ( $_query && !is_numeric( $_query ) ) { 243 // Is it more than one query? 244 if ( strpos( ';', $_query ) !== false ) { 245 // Explode by semi-colon 246 foreach ( explode( ';', $_query ) as $_part ) { 247 $_part = trim( $_part ); 248 if ( $_part && !is_numeric( $_part ) ) { 249 // Pull out any commented code 250 // Can't properly deal with /*!4321 FOO `bar` */ version specific inclusion, just includes it regardless of version 251 $_part = preg_replace( '@/\*![0-9]*([^\*]*)\*/@', '$1', $_part ); 252 $_part = preg_replace( '@/\*[^\*]*\*/@', '', $_part ); 253 $_part = preg_replace( '@[\-\-|#].*$@m', '', $_part ); 254 $_clean_queries[] = trim( $_part ) . ';'; 255 } 256 } 257 unset( $_part ); 258 } else { 259 $_clean_queries[] = $_query . ';'; 260 } 261 } 262 } 263 unset( $_query ); 264 if ( !count( $_clean_queries ) ) { 265 return false; 266 } 267 $queries = $_clean_queries; 268 unset( $_clean_queries ); 269 270 $_queries = array(); 271 foreach ( $queries as $_query ) { 272 // Only process table creation, inserts and updates, capture the table/database name while we are at it 273 if ( !preg_match( '@^(CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?|INSERT\s+INTO|UPDATE)\s+`?([^\s|`]+)`?@im', $_query, $_matches ) ) { 274 continue; 275 } 276 277 // Tidy up the type so we can switch it 278 $_type = strtoupper( preg_replace( '@\s+@', ' ', trim( $_matches[1] ) ) ); 279 $_table_name = trim( $_matches[2] ); 280 unset( $_matches ); 281 282 switch ( $_type ) { 283 case 'CREATE TABLE': 284 case 'CREATE TABLE IF NOT EXISTS': 285 $_description = BP_SQL_Schema_Parser::describe_table( $_query ); 286 if ( is_array( $_description ) ) { 287 $_queries['tables'][$_table_name] = $_description; 288 } 289 break; 290 291 case 'INSERT INTO': 292 // Just add the query as is for now 293 $_queries['insert'][$_table_name][] = $_query; 294 break; 295 296 case 'UPDATE': 297 // Just add the query as is for now 298 $_queries['update'][$_table_name][] = $_query; 299 break; 300 } 301 unset( $_type, $_table_name ); 302 } 303 unset( $_query ); 304 305 if ( !count( $_queries ) ) { 306 return false; 307 } 308 return $_queries; 309 } 310 311 /** 312 * Evaluates the difference between a given set of SQL queries and real database structure 313 */ 314 function delta( $db_object, $queries, $ignore = false, $execute = true ) 315 { 316 if ( !$db_object || !is_object( $db_object ) || !( is_a( $db_object, 'BPDB' ) || is_a( $db_object, 'BPDB_Multi' ) || is_a( $db_object, 'BPDB_Hyper' ) ) ) { 317 return __( 'Passed variable is not a BackPress database object.' ); 318 } 319 320 if ( !$_queries = BP_SQL_Schema_Parser::parse( $queries ) ) { 321 return __( 'No schema available.' ); 322 } 323 324 // Set up default elements to ignore 325 $ignore_defaults = array( 326 'tables' => array(), // Just a list of tablenames, including prefix. Does not affect INSERT and UPDATE queries. 327 'columns' => array(), // Arrays of column names, keyed with the table names, including prefix. 328 'indices' => array() // Arrays of index names, keyed with the table names, including prefix. 329 ); 330 331 // Add the elements to ignore that were passed to the function 332 if ( !$ignore || !is_array( $ignore ) ) { 333 $ignore = $ignore_defaults; 334 } else { 335 if ( isset( $ignore['tables'] ) && is_array( $ignore['tables'] ) ) { 336 $ignore['tables'] = array_merge( $ignore_defaults['tables'], $ignore['tables'] ); 337 } 338 if ( isset( $ignore['columns'] ) && is_array( $ignore['columns'] ) ) { 339 $ignore['columns'] = array_merge( $ignore_defaults['columns'], $ignore['columns'] ); 340 } 341 if ( isset( $ignore['indices'] ) && is_array( $ignore['indices'] ) ) { 342 $ignore['indices'] = array_merge( $ignore_defaults['indices'], $ignore['indices'] ); 343 } 344 } 345 346 // Build an array of $db_object registered tables and their database identifiers 347 $_tables = $db_object->tables; 348 $db_object_tables = array(); 349 foreach ( $_tables as $_table_id => $_table_name ) { 350 if ( is_array( $_table_name ) && isset( $db_object->db_servers['dbh_' . $_table_name[0]] ) ) { 351 $db_object_tables[$db_object->$_table_id] = 'dbh_' . $_table_name[0]; 352 } else { 353 $db_object_tables[$db_object->$_table_id] = 'dbh_global'; 354 } 355 } 356 unset( $_tables, $_table_id, $_table_name ); 357 358 $alterations = array(); 359 360 // Loop through table queries 361 if ( isset( $_queries['tables'] ) ) { 362 foreach ( $_queries['tables'] as $_new_table_name => $_new_table_data ) { 363 if ( in_array( $_new_table_name, $ignore['tables'] ) ) { 364 continue; 365 } 366 367 // See if the table is custom and registered in $db_object under a custom database 368 if ( 369 isset( $db_object_tables[$_new_table_name] ) && 370 $db_object_tables[$_new_table_name] != 'dbh_global' && 371 isset( $db_object->db_servers[$db_object_tables[$_new_table_name]]['ds'] ) 372 ) { 373 // Force the database connection 374 $_dbhname = $db_object->db_servers[$db_object_tables[$_new_table_name]]['ds']; 375 $db_object->_force_dbhname = $_dbhname; 376 } else { 377 $_dbhname = 'dbh_global'; 378 } 379 380 // Fetch the existing table column structure from the database 381 $db_object->suppress_errors(); 382 if ( !$_existing_table_columns = $db_object->get_results( 'DESCRIBE `' . $_new_table_name . '`;', ARRAY_A ) ) { 383 $db_object->suppress_errors( false ); 384 // The table doesn't exist, add it and then continue to the next table 385 $alterations[$_dbhname][$_new_table_name][] = array( 386 'action' => 'create_table', 387 'message' => __( 'Creating table' ), 388 'query' => $_new_table_data['query_tidy'] 389 ); 390 continue; 391 } 392 $db_object->suppress_errors( false ); 393 394 // Add an index to the existing columns array 395 $__existing_table_columns = array(); 396 foreach ( $_existing_table_columns as $_existing_table_column ) { 397 // Remove 'Key' from returned column structure 398 unset( $_existing_table_column['Key'] ); 399 $__existing_table_columns[$_existing_table_column['Field']] = $_existing_table_column; 400 } 401 $_existing_table_columns = $__existing_table_columns; 402 unset( $__existing_table_columns ); 403 404 // Loop over the columns in this table and look for differences 405 foreach ( $_new_table_data['columns'] as $_new_column_name => $_new_column_data ) { 406 if ( isset( $ignore['columns'][$_new_table_name] ) && in_array( $_new_column_name, $ignore['columns'][$_new_table_name] ) ) { 407 continue; 408 } 409 410 if ( !in_array( $_new_column_data, $_existing_table_columns ) ) { 411 // There is a difference 412 if ( !isset( $_existing_table_columns[$_new_column_name] ) ) { 413 // The column doesn't exist, so add it 414 $alterations[$_dbhname][$_new_table_name][] = array( 415 'action' => 'add_column', 416 'message' => sprintf( __( 'Adding column: %s' ), $_new_column_name ), 417 'column' => $_new_column_name, 418 'query' => 'ALTER TABLE `' . $_new_table_name . '` ADD COLUMN ' . BP_SQL_Schema_Parser::get_column_definition( $_new_column_data ) . ';' 419 ); 420 continue; 421 } 422 423 // Adjust defaults on columns that allow defaults 424 if ( 425 ! is_null( $_new_column_data['Default'] ) && // Possibly should use DROP DEFAULT here 426 $_new_column_data['Default'] !== $_existing_table_columns[$_new_column_name]['Default'] && 427 !in_array( 428 strtolower( $_new_column_data['Type'] ), 429 array( 'tinytext', 'text', 'mediumtext', 'longtext', 'blob', 'mediumblob', 'longblob' ) 430 ) 431 ) { 432 // Change the default value for the column 433 $alterations[$_dbhname][$_new_table_name][] = array( 434 'action' => 'set_default', 435 'message' => sprintf( __( 'Setting default on column: %s' ), $_new_column_name ), 436 'column' => $_new_column_name, 437 'query' => 'ALTER TABLE `' . $_new_table_name . '` ALTER COLUMN `' . $_new_column_name . '` SET DEFAULT \'' . $_new_column_data['Default'] . '\';' 438 ); 439 // Don't continue, overwrite this if the next conditional is met 440 } 441 442 // TODO Improve handling of scenarios like http://dev.mysql.com/doc/refman/5.0/en/silent-column-changes.html 443 // The db picks different column data types from the schema and we can't make it change it's mind ;) 444 // e.g. varchar(32) and char(32) 445 if ( 446 $_new_column_data['Type'] !== $_existing_table_columns[$_new_column_name]['Type'] || 447 ( 'YES' === $_new_column_data['Null'] xor 'YES' === $_existing_table_columns[$_new_column_name]['Null'] ) || 448 $_new_column_data['Extra'] !== $_existing_table_columns[$_new_column_name]['Extra'] 449 ) { 450 // Change the structure for the column 451 $alterations[$_dbhname][$_new_table_name][] = array( 452 'action' => 'change_column', 453 'message' => sprintf( __( 'Changing column: %s' ), $_new_column_name ), 454 'column' => $_new_column_name, 455 'query' => 'ALTER TABLE `' . $_new_table_name . '` CHANGE COLUMN `' . $_new_column_name . '` ' . BP_SQL_Schema_Parser::get_column_definition( $_new_column_data ) . ';' 456 ); 457 } 458 } 459 } 460 unset( $_existing_table_columns, $_new_column_name, $_new_column_data ); 461 462 // Fetch the table index structure from the database 463 if ( !$_existing_table_indices = $db_object->get_results( 'SHOW INDEX FROM `' . $_new_table_name . '`;', ARRAY_A ) ) { 464 continue; 465 } 466 467 // Add an index to the existing columns array and organise by index name 468 $__existing_table_indices = array(); 469 foreach ( $_existing_table_indices as $_existing_table_index ) { 470 // Remove unused parts from returned index structure 471 unset( 472 $_existing_table_index['Collation'], 473 $_existing_table_index['Cardinality'], 474 $_existing_table_index['Packed'], 475 $_existing_table_index['Null'], 476 $_existing_table_index['Comment'], 477 $_existing_table_index['Index_comment'] 478 ); 479 $__existing_table_indices[$_existing_table_index['Key_name']][] = $_existing_table_index; 480 } 481 $_existing_table_indices = $__existing_table_indices; 482 unset( $__existing_table_indices ); 483 484 // Loop over the indices in this table and look for differences 485 foreach ( $_new_table_data['indices'] as $_new_index_name => $_new_index_data ) { 486 if ( isset( $ignore['indices'][$_new_table_name] ) && in_array( $_new_index_name, $ignore['indices'][$_new_table_name] ) ) { 487 continue; 488 } 489 490 if ( !in_array( $_new_index_data, $_existing_table_indices ) ) { 491 // There is a difference 492 if ( !isset( $_existing_table_indices[$_new_index_name] ) ) { 493 // The index doesn't exist, so add it 494 $alterations[$_dbhname][$_new_table_name][] = array( 495 'action' => 'add_index', 496 'message' => sprintf( __( 'Adding index: %s' ), $_new_index_name ), 497 'index' => $_new_index_name, 498 'query' => 'ALTER TABLE `' . $_new_table_name . '` ADD ' . BP_SQL_Schema_Parser::get_index_definition( $_new_index_data ) . ';' 499 ); 500 continue; 501 } 502 503 if ( $_new_index_data !== $_existing_table_indices[$_new_index_name] ) { 504 // The index is incorrect, so drop it and add the new one 505 if ( $_new_index_name == 'PRIMARY' ) { 506 $_drop_index_name = 'PRIMARY KEY'; 507 } else { 508 $_drop_index_name = 'INDEX `' . $_new_index_name . '`'; 509 } 510 $alterations[$_dbhname][$_new_table_name][] = array( 511 'action' => 'drop_index', 512 'message' => sprintf( __( 'Dropping index: %s' ), $_new_index_name ), 513 'index' => $_new_index_name, 514 'query' => 'ALTER TABLE `' . $_new_table_name . '` DROP ' . $_drop_index_name . ';' 515 ); 516 unset( $_drop_index_name ); 517 $alterations[$_dbhname][$_new_table_name][] = array( 518 'action' => 'add_index', 519 'message' => sprintf( __( 'Adding index: %s' ), $_new_index_name ), 520 'index' => $_new_index_name, 521 'query' => 'ALTER TABLE `' . $_new_table_name . '` ADD ' . BP_SQL_Schema_Parser::get_index_definition( $_new_index_data ) . ';' 522 ); 523 } 524 } 525 } 526 unset( $_new_index_name, $_new_index_data ); 527 528 // Go back to the default database connection 529 $db_object->_force_dbhname = false; 530 } 531 unset( $_new_table_name, $_new_table_data, $_dbhname ); 532 } 533 534 // Now deal with the sundry INSERT and UPDATE statements (if any) 535 if ( isset( $_queries['insert'] ) && is_array( $_queries['insert'] ) && count( $_queries['insert'] ) ) { 536 foreach ( $_queries['insert'] as $_table_name => $_inserts ) { 537 foreach ( $_inserts as $_insert ) { 538 $alterations['dbh_global'][$_table_name][] = array( 539 'action' => 'insert', 540 'message' => __( 'Inserting data' ), 541 'query' => $_insert 542 ); 543 } 544 unset( $_insert ); 545 } 546 unset( $_table_name, $_inserts ); 547 } 548 if ( isset( $_queries['update'] ) && is_array( $_queries['update'] ) && count( $_queries['update'] ) ) { 549 foreach ( $_queries['update'] as $_table_name => $_updates ) { 550 foreach ( $_updates as $_update ) { 551 $alterations['dbh_global'][$_table_name][] = array( 552 'action' => 'update', 553 'message' => __( 'Updating data' ), 554 'query' => $_update 555 ); 556 } 557 unset( $_update ); 558 } 559 unset( $_table_name, $_updates ); 560 } 561 562 // Initialise an array to hold the output messages 563 $messages = array(); 564 $errors = array(); 565 566 foreach ( $alterations as $_dbhname => $_tables ) { 567 // Force the database connection (this was already checked to be valid in the previous loop) 568 $db_object->_force_dbhname = $_dbhname; 569 570 // Note the database in the return messages 571 $messages[] = '>>> ' . sprintf( __( 'Modifying database: %s (%s)' ), $db_object->db_servers[$_dbhname]['name'], $db_object->db_servers[$_dbhname]['host'] ); 572 573 foreach ( $_tables as $_table_name => $_alterations ) { 574 // Note the table in the return messages 575 $messages[] = '>>>>>> ' . sprintf( __( 'Table: %s' ), $_table_name ); 576 577 foreach ( $_alterations as $_alteration ) { 578 // If there is no query, then skip 579 if ( !$_alteration['query'] ) { 580 continue; 581 } 582 583 // Note the action in the return messages 584 $messages[] = '>>>>>>>>> ' . $_alteration['message']; 585 586 if ( !$execute ) { 587 $messages[] = '>>>>>>>>>>>> ' . __( 'Skipped' ); 588 continue; 589 } 590 591 // Run the query 592 $_result = $db_object->query( $_alteration['query'] ); 593 $_result_error = $db_object->get_error(); 594 595 if ( $_result_error ) { 596 // There was an error 597 $_result =& $_result_error; 598 unset( $_result_error ); 599 $messages[] = '>>>>>>>>>>>> ' . __( 'SQL ERROR! See the error log for more detail' ); 600 $errors[] = __( 'SQL ERROR!' ); 601 $errors[] = '>>> ' . sprintf( __( 'Database: %s (%s)' ), $db_object->db_servers[$_dbhname]['name'], $db_object->db_servers[$_dbhname]['host'] ); 602 $errors[] = '>>>>>> ' . $_result->error_data['db_query']['query']; 603 $errors[] = '>>>>>> ' . $_result->error_data['db_query']['error']; 604 } else { 605 $messages[] = '>>>>>>>>>>>> ' . __( 'Done' ); 606 } 607 unset( $_result ); 608 } 609 unset( $_alteration ); 610 } 611 unset( $_table_name, $_alterations ); 612 } 613 unset( $_dbhname, $_tables ); 614 615 // Reset the database connection 616 $db_object->_force_dbhname = false; 617 618 return array( 'messages' => $messages, 'errors' => $errors ); 619 } 620 } // END class BP_SQL_Schema_Parser
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sat Nov 23 01:00:54 2024 | Cross-referenced by PHPXref 0.7.1 |