Skip to content
41 changes: 40 additions & 1 deletion src/Import.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ public function run( $sql_file_path, $args ) {
$is_stdin = '-' === $sql_file_path;
$import_file = $is_stdin ? 'php://stdin' : $sql_file_path;

$this->execute_statements( $import_file );
if ( method_exists( $this->driver, 'create_parser' ) ) {
$this->execute_statements_with_ast_parser( $import_file );
} else {
$this->execute_statements( $import_file );
}

$imported_from = $is_stdin ? 'STDIN' : $sql_file_path;
WP_CLI::success( sprintf( "Imported from '%s'.", $imported_from ) );
Expand Down Expand Up @@ -133,4 +137,39 @@ public function parse_statements( $sql_file_path ) {

fclose( $handle );
}

/**
* Execute SQL statements from an SQL dump file using the AST parser.
*
* @param $import_file
*
* @return void
* @throws Exception
*/
protected function execute_statements_with_ast_parser( $import_file ) {
$raw_queries = file_get_contents( $import_file );

// Detect and convert encoding to UTF-8
$detected_encoding = mb_detect_encoding( $raw_queries, mb_list_encodings(), true );
if ( $detected_encoding && 'UTF-8' !== $detected_encoding ) {
$raw_queries = mb_convert_encoding( $raw_queries, 'UTF-8', $detected_encoding );
}

$parser = $this->driver->create_parser( $raw_queries );
while ( $parser->next_query() ) {
$ast = $parser->get_query_ast();
$statement = substr( $raw_queries, $ast->get_start(), $ast->get_length() );
try {
$this->driver->query( $statement );
} catch ( Exception $e ) {
// Skip errors when executing SET comment statements
if ( 0 === strpos( $statement, 'SET ' ) && false !== strpos( $statement, '*/' ) ) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot use str_starts_with or str_contains because we support PHP 7.4

echo 'Warning - SQLite import skipped SET comment statement: ' . $statement . PHP_EOL;
continue;
}
WP_CLI::error( 'SQLite import could not execute statement: ' . $statement );
echo $this->driver->get_error_message();
}
}
}
}