[ Index ] |
PHP Cross Reference of BuddyPress |
[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' => ( 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 $_new_column_data['Default'] !== $_existing_table_columns[$_new_column_name]['Default'] && 426 !in_array( 427 strtolower( $_new_column_data['Type'] ), 428 array( 'tinytext', 'text', 'mediumtext', 'longtext', 'blob', 'mediumblob', 'longblob' ) 429 ) 430 ) { 431 // Change the default value for the column 432 $alterations[$_dbhname][$_new_table_name][] = array( 433 'action' => 'set_default', 434 'message' => sprintf( __( 'Setting default on column: %s' ), $_new_column_name ), 435 'column' => $_new_column_name, 436 'query' => 'ALTER TABLE `' . $_new_table_name . '` ALTER COLUMN `' . $_new_column_name . '` SET DEFAULT \'' . $_new_column_data['Default'] . '\';' 437 ); 438 // Don't continue, overwrite this if the next conditional is met 439 } 440 441 if ( 442 $_new_column_data['Type'] !== $_existing_table_columns[$_new_column_name]['Type'] || 443 ( 'YES' === $_new_column_data['Null'] xor 'YES' === $_existing_table_columns[$_new_column_name]['Null'] ) || 444 $_new_column_data['Extra'] !== $_existing_table_columns[$_new_column_name]['Extra'] 445 ) { 446 // Change the structure for the column 447 $alterations[$_dbhname][$_new_table_name][] = array( 448 'action' => 'change_column', 449 'message' => sprintf( __( 'Changing column: %s' ), $_new_column_name ), 450 'column' => $_new_column_name, 451 'query' => 'ALTER TABLE `' . $_new_table_name . '` CHANGE COLUMN `' . $_new_column_name . '` ' . BP_SQL_Schema_Parser::get_column_definition( $_new_column_data ) . ';' 452 ); 453 } 454 } 455 } 456 unset( $_existing_table_columns, $_new_column_name, $_new_column_data ); 457 458 // Fetch the table index structure from the database 459 if ( !$_existing_table_indices = $db_object->get_results( 'SHOW INDEX FROM `' . $_new_table_name . '`;', ARRAY_A ) ) { 460 continue; 461 } 462 463 // Add an index to the existing columns array and organise by index name 464 $__existing_table_indices = array(); 465 foreach ( $_existing_table_indices as $_existing_table_index ) { 466 // Remove unused parts from returned index structure 467 unset( 468 $_existing_table_index['Collation'], 469 $_existing_table_index['Cardinality'], 470 $_existing_table_index['Packed'], 471 $_existing_table_index['Null'], 472 $_existing_table_index['Comment'] 473 ); 474 $__existing_table_indices[$_existing_table_index['Key_name']][] = $_existing_table_index; 475 } 476 $_existing_table_indices = $__existing_table_indices; 477 unset( $__existing_table_indices ); 478 479 // Loop over the indices in this table and look for differences 480 foreach ( $_new_table_data['indices'] as $_new_index_name => $_new_index_data ) { 481 if ( isset( $ignore['indices'][$_new_table_name] ) && in_array( $_new_index_name, $ignore['indices'][$_new_table_name] ) ) { 482 continue; 483 } 484 485 if ( !in_array( $_new_index_data, $_existing_table_indices ) ) { 486 // There is a difference 487 if ( !isset( $_existing_table_indices[$_new_index_name] ) ) { 488 // The index doesn't exist, so add it 489 $alterations[$_dbhname][$_new_table_name][] = array( 490 'action' => 'add_index', 491 'message' => sprintf( __( 'Adding index: %s' ), $_new_index_name ), 492 'index' => $_new_index_name, 493 'query' => 'ALTER TABLE `' . $_new_table_name . '` ADD ' . BP_SQL_Schema_Parser::get_index_definition( $_new_index_data ) . ';' 494 ); 495 continue; 496 } 497 498 if ( $_new_index_data !== $_existing_table_indices[$_new_index_name] ) { 499 // The index is incorrect, so drop it and add the new one 500 if ( $_new_index_name == 'PRIMARY' ) { 501 $_drop_index_name = 'PRIMARY KEY'; 502 } else { 503 $_drop_index_name = 'INDEX `' . $_new_index_name . '`'; 504 } 505 $alterations[$_dbhname][$_new_table_name][] = array( 506 'action' => 'drop_index', 507 'message' => sprintf( __( 'Dropping index: %s' ), $_new_index_name ), 508 'index' => $_new_index_name, 509 'query' => 'ALTER TABLE `' . $_new_table_name . '` DROP ' . $_drop_index_name . ';' 510 ); 511 unset( $_drop_index_name ); 512 $alterations[$_dbhname][$_new_table_name][] = array( 513 'action' => 'add_index', 514 'message' => sprintf( __( 'Adding index: %s' ), $_new_index_name ), 515 'index' => $_new_index_name, 516 'query' => 'ALTER TABLE `' . $_new_table_name . '` ADD ' . BP_SQL_Schema_Parser::get_index_definition( $_new_index_data ) . ';' 517 ); 518 } 519 } 520 } 521 unset( $_new_index_name, $_new_index_data ); 522 523 // Go back to the default database connection 524 $db_object->_force_dbhname = false; 525 } 526 unset( $_new_table_name, $_new_table_data, $_dbhname ); 527 } 528 529 // Now deal with the sundry INSERT and UPDATE statements (if any) 530 if ( isset( $_queries['insert'] ) && is_array( $_queries['insert'] ) && count( $_queries['insert'] ) ) { 531 foreach ( $_queries['insert'] as $_table_name => $_inserts ) { 532 foreach ( $_inserts as $_insert ) { 533 $alterations['dbh_global'][$_table_name][] = array( 534 'action' => 'insert', 535 'message' => __( 'Inserting data' ), 536 'query' => $_insert 537 ); 538 } 539 unset( $_insert ); 540 } 541 unset( $_table_name, $_inserts ); 542 } 543 if ( isset( $_queries['update'] ) && is_array( $_queries['update'] ) && count( $_queries['update'] ) ) { 544 foreach ( $_queries['update'] as $_table_name => $_updates ) { 545 foreach ( $_updates as $_update ) { 546 $alterations['dbh_global'][$_table_name][] = array( 547 'action' => 'update', 548 'message' => __( 'Updating data' ), 549 'query' => $_update 550 ); 551 } 552 unset( $_update ); 553 } 554 unset( $_table_name, $_updates ); 555 } 556 557 // Initialise an array to hold the output messages 558 $messages = array(); 559 $errors = array(); 560 561 foreach ( $alterations as $_dbhname => $_tables ) { 562 // Force the database connection (this was already checked to be valid in the previous loop) 563 $db_object->_force_dbhname = $_dbhname; 564 565 // Note the database in the return messages 566 $messages[] = '>>> ' . sprintf( __( 'Modifying database: %s (%s)' ), $db_object->db_servers[$_dbhname]['name'], $db_object->db_servers[$_dbhname]['host'] ); 567 568 foreach ( $_tables as $_table_name => $_alterations ) { 569 // Note the table in the return messages 570 $messages[] = '>>>>>> ' . sprintf( __( 'Table: %s' ), $_table_name ); 571 572 foreach ( $_alterations as $_alteration ) { 573 // If there is no query, then skip 574 if ( !$_alteration['query'] ) { 575 continue; 576 } 577 578 // Note the action in the return messages 579 $messages[] = '>>>>>>>>> ' . $_alteration['message']; 580 581 if ( !$execute ) { 582 $messages[] = '>>>>>>>>>>>> ' . __( 'Skipped' ); 583 continue; 584 } 585 586 // Run the query 587 $_result = $db_object->query( $_alteration['query'] ); 588 $_result_error = $db_object->get_error(); 589 590 if ( $_result_error ) { 591 // There was an error 592 $_result =& $_result_error; 593 unset( $_result_error ); 594 $messages[] = '>>>>>>>>>>>> ' . __( 'SQL ERROR! See the error log for more detail' ); 595 $errors[] = __( 'SQL ERROR!' ); 596 $errors[] = '>>> ' . sprintf( __( 'Database: %s (%s)' ), $db_object->db_servers[$_dbhname]['name'], $db_object->db_servers[$_dbhname]['host'] ); 597 $errors[] = '>>>>>> ' . $_result->error_data['db_query']['query']; 598 $errors[] = '>>>>>> ' . $_result->error_data['db_query']['error']; 599 } else { 600 $messages[] = '>>>>>>>>>>>> ' . __( 'Done' ); 601 } 602 unset( $_result ); 603 } 604 unset( $_alteration ); 605 } 606 unset( $_table_name, $_alterations ); 607 } 608 unset( $_dbhname, $_tables ); 609 610 // Reset the database connection 611 $db_object->_force_dbhname = false; 612 613 return array( 'messages' => $messages, 'errors' => $errors ); 614 } 615 } // END class BP_SQL_Schema_Parser
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 22 01:00:56 2024 | Cross-referenced by PHPXref 0.7.1 |