connect_errno ) { fatal_error( "ERROR: " . $mysqli->connect_error . "\n" ); } $mysqli->autocommit( false ); const TEMP_FILES_TABLE = 'files_table_rows_owned_by_webforms'; create_temporary_table_files_rows_owned_by_webforms( TEMP_FILES_TABLE, $mysqli ); $files_table_rows = $mysqli->query( 'SELECT * FROM ' . TEMP_FILES_TABLE . ' ORDER BY timestamp ASC' ); if ( ! $files_table_rows ) { fatal_error( 'ERROR fetching rows from ' . TEMP_FILES_TABLE . ': (' . $mysqli->errno . ') ' . $mysqli->error, $mysqli ); } // Loop through webform-owned files table rows and migrate while ( $file_table_row = $files_table_rows->fetch_assoc() ) { // The data migration functions below all call fatal_error() at the first sign of trouble, nevertheless // we'll check return codes and do a silent abort on failure just in case if ( ! $fid = insert_into_file_managed_table( $file_table_row, $mysqli ) ) { abort( $mysqli ); } if ( ! insert_into_file_usage_table( $fid, $file_table_row[ 'sid' ], $mysqli ) ) { abort( $mysqli ); } if ( ! update_webform_submitted_data_table( $fid, $file_table_row[ 'nid' ], $file_table_row[ 'sid' ], $file_table_row[ 'cid' ], $mysqli ) ) { abort( $mysqli ); } } if ( ! $mysqli->commit() ) { fatal_error( 'ERROR: $mysqli->commit(): (' . $stmt->errno . ') ' . $stmt->error, $mysqli ); $mysqli->rollback(); } cleanup( $mysqli ); function create_temporary_table_files_rows_owned_by_webforms( $tablename, $mysqli ) { // Since the query for identifying webform-owned files in files table is expensive, // save the results in a temporary table. $insert_sql =<<query( "CREATE TABLE ${tablename} LIKE files" ) || ! $mysqli->query( "ALTER TABLE ${tablename} ADD COLUMN nid INT(10) FIRST" ) || ! $mysqli->query( "ALTER TABLE ${tablename} ADD COLUMN sid INT(10) AFTER nid" ) || ! $mysqli->query( "ALTER TABLE ${tablename} ADD COLUMN cid INT(10) AFTER sid" ) || ! $mysqli->query( $insert_sql ) ) { fatal_error( 'ERROR create_temporary_table_files_rows_owned_by_webforms(): (' . $mysqli->errno . ') ' . $mysqli->error, $mysqli ); } // This will call fatal_error() if it fails, so no need to check return value alter_duplicate_filepaths( $mysqli ); $mysqli->commit(); } function alter_duplicate_filepaths( $mysqli ) { $update_sql = <<query( $update_sql ); if ( ! $mysqli->affected_rows == 1 ) { fatal_error( 'ERROR alter_duplicate_filepaths(): expected 1 updated row, got ' . $mysqli->affected_rows ); } } function insert_into_file_managed_table( $row, $mysqli ) { static $stmt; if ( ! $stmt ) { $sql = <<prepare( $sql ); if ( ! $stmt ) { fatal_error( 'ERROR: insert_into_file_managed_table(): (' . $mysqli->errno . ') ' . $mysqli->error, $mysqli ); } } $filepath = $row[ 'filepath' ]; $uri = preg_replace( '/sites\/dsa\/files\//', 'public://', $filepath ); if ( ! $uri) { fatal_error( "ERROR insert_into_file_managed_table(): Couldn't construct URI from " . $row[ 'filepath' ] . "\n", $mysqli ); } // Note on casting the timestamp string to integer // PHP_MAX_INT for positive numbers: // 32-bit: 2147483647 (chameleon, juggernaut, ) // 64-bit: 9223372036854775807 (ein) // Current timestamps are 10 digits with 1 in the most significant digit. Should be totally safe. // $ date +%s // 1360598933 // $ php -r 'echo PHP_INT_MAX;'; echo // 2147483647 // $ if [ `date +%s` -le `php -r 'echo PHP_INT_MAX;'` ]; then echo "OK"; else echo "NOT OK"; fi // OK if ( ! $stmt->bind_param( 'isssiii', $row[ 'uid' ], $row[ 'filename' ], $uri, $row[ 'filesize' ], $row[ 'filemime' ], $row[ 'status' ], $row[ 'timestamp' ] ) ) { fatal_error( 'ERROR: insert_into_file_managed_table(): (' . $stmt->errno . ') ' . $stmt->error, $mysqli ); } if ( ! $stmt->execute() ) { fatal_error( 'ERROR: insert_into_file_managed_table(): (' . $stmt->errno . ') ' . $stmt->error, $mysqli ); } $fid = $mysqli->insert_id; if ( ! $fid ) { fatal_error( 'ERROR: insert_into_file_managed_table(): (' . $mysqli->errno . ') ' . $mysqli->error, $mysqli ); } return $fid; } function insert_into_file_usage_table( $fid, $sid, $mysqli ) { static $stmt; if ( ! $stmt ) { $sql = <<prepare( $sql ); if ( ! $stmt ) { fatal_error( 'ERROR: insert_into_file_usage_table(): (' . $mysqli->errno . ') ' . $mysqli->error, $mysqli ); } } if ( ! $stmt->bind_param( 'ii', $fid, $sid ) ) { fatal_error( 'ERROR: insert_into_file_usage_table(): (' . $mysqli->errno . ') ' . $mysqli->error, $mysqli ); } if ( ! $stmt->execute() ) { fatal_error( 'ERROR: insert_into_file_usage_table(): (' . $stmt->errno . ') ' . $stmt->error, $mysqli ); } return true; } function update_webform_submitted_data_table( $fid, $nid, $sid, $cid, $mysqli ) { static $stmt; if ( ! $stmt ) { $sql = <<prepare( $sql ); if ( ! $stmt ) { fatal_error( 'ERROR: update_webform_submitted_data_table(): (' . $mysqli->errno . ') ' . $mysqli->error, $mysqli ); } } if ( ! $stmt->bind_param( 'iiii', $fid, $nid, $sid, $cid ) ) { fatal_error( 'ERROR: update_webform_submitted_data_table(): (' . $mysqli->errno . ') ' . $mysqli->error, $mysqli ); } if ( ! $stmt->execute() ) { fatal_error( 'ERROR: update_webform_submitted_data_table(): (' . $stmt->errno . ') ' . $stmt->error, $mysqli ); } return true; } function fatal_error( $message, $mysqli = null ) { fprintf( STDERR, $message . "\n" ); abort( $mysqli ); } function abort( $mysqli = null ) { if ( $mysqli ) { $mysqli->rollback(); cleanup( $mysqli ); } die; } function cleanup( $mysqli ) { $mysqli->query( 'DROP TABLE ' . TEMP_FILES_TABLE ); $mysqli->close(); }