diff --git a/.github/workflows/cs.yml b/.github/workflows/cs.yml
new file mode 100644
index 0000000..3dc0cd1
--- /dev/null
+++ b/.github/workflows/cs.yml
@@ -0,0 +1,68 @@
+name: CS
+
+on:
+ # Run on all relevant pushes (except to main) and on all relevant pull requests.
+ push:
+ paths:
+ - '**.php'
+ - 'composer.json'
+ - 'composer.lock'
+ - '.phpcs.xml.dist'
+ - 'phpcs.xml.dist'
+ - '.github/workflows/cs.yml'
+ pull_request:
+ paths:
+ - '**.php'
+ - 'composer.json'
+ - 'composer.lock'
+ - '.phpcs.xml.dist'
+ - 'phpcs.xml.dist'
+ - '.github/workflows/cs.yml'
+ # Allow manually triggering the workflow.
+ workflow_dispatch:
+
+# Cancels all previous workflow runs for the same branch that have not yet completed.
+concurrency:
+ # The concurrency group contains the workflow name and the branch name.
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ checkcs:
+ name: 'Check code style'
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@main
+
+ - name: Install PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '7.4'
+ coverage: none
+ tools: cs2pr
+
+ # Validate the composer.json file.
+ # @link https://getcomposer.org/doc/03-cli.md#validate
+ - name: Validate Composer installation
+ run: composer validate --no-check-all
+
+ # Install dependencies and handle caching in one go.
+ # @link https://github.com/marketplace/actions/install-composer-dependencies
+ - name: Install Composer dependencies
+ uses: ramsey/composer-install@v2
+ with:
+ # Bust the cache at least once a month - output format: YYYY-MM.
+ custom-cache-suffix: $(date -u "+%Y-%m")
+
+ # Check the codestyle of the files.
+ # The results of the CS check will be shown inline in the PR via the CS2PR tool.
+ # @link https://github.com/staabm/annotate-pull-request-from-checkstyle/
+ - name: Check PHP code style
+ id: phpcs
+ run: composer check-cs -- --no-cache --report-full --report-checkstyle=./phpcs-report.xml
+
+ - name: Show PHPCS results in PR
+ if: ${{ always() && steps.phpcs.outcome == 'failure' }}
+ run: cs2pr ./phpcs-report.xml
diff --git a/composer.json b/composer.json
index 7b25a2d..b64928b 100644
--- a/composer.json
+++ b/composer.json
@@ -13,13 +13,26 @@
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"squizlabs/php_codesniffer": "^3.7",
- "wp-coding-standards/wpcs": "^3.0",
- "phpcompatibility/phpcompatibility-wp": "^2.1",
+ "wp-coding-standards/wpcs": "^3.1",
+ "phpcompatibility/phpcompatibility-wp": "*",
+ "php-parallel-lint/php-parallel-lint": "^1.3",
+ "phpstan/phpstan": "^1.10",
+ "szepeviktor/phpstan-wordpress": "^1.3",
+ "phpstan/extension-installer": "^1.3",
"yoast/phpunit-polyfills": "2.0.0"
},
"config": {
"allow-plugins": {
- "dealerdirect/phpcodesniffer-composer-installer": true
+ "dealerdirect/phpcodesniffer-composer-installer": true,
+ "phpstan/extension-installer": true
}
+ },
+ "scripts": {
+ "check-cs": [
+ "@php ./vendor/bin/phpcs"
+ ],
+ "fix-cs": [
+ "@php ./vendor/bin/phpcbf"
+ ]
}
}
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
index 557065e..7a3b78b 100644
--- a/phpcs.xml.dist
+++ b/phpcs.xml.dist
@@ -5,11 +5,11 @@
-
-
+
@@ -20,50 +20,172 @@
- .
+
-
-
+ .
/vendor/*
-
+ /wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php
-
-
- /wp-includes/*.php
+
+
+
+
+
+
+
+
+
+ warning
+
+ /tests/phpunit/*
-
- /wp-includes/*.php
+
+ warning
+
+
+ warning
+
+
+ warning
+
+
+ warning
-
-
- 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
- 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
- 0
+
+
+
+
+
+ /wp-includes/sqlite/class-wp-sqlite-translator.php
+
+
+
+
+ *
-
-
+
+ /src/wp-includes/sqlite/*\.php
/tests/*
- /wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php
-
+
+
+
/tests/*
+
+
/wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php
-
+
+ /tests/*
+
+
/tests/*
- /wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php
/tests/*
- /wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php
/wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php
diff --git a/tests/WP_SQLite_Translator_Tests.php b/tests/WP_SQLite_Translator_Tests.php
index e6399c3..f30c6f6 100644
--- a/tests/WP_SQLite_Translator_Tests.php
+++ b/tests/WP_SQLite_Translator_Tests.php
@@ -33,17 +33,17 @@ public function setUp(): void {
$this->engine = new WP_SQLite_Translator( $this->sqlite );
$this->engine->query(
"CREATE TABLE _options (
- ID INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
- option_name TEXT NOT NULL default '',
- option_value TEXT NOT NULL default ''
- );"
+ ID INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
+ option_name TEXT NOT NULL default '',
+ option_value TEXT NOT NULL default ''
+ );"
);
$this->engine->query(
"CREATE TABLE _dates (
- ID INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
- option_name TEXT NOT NULL default '',
- option_value DATE NOT NULL
- );"
+ ID INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
+ option_name TEXT NOT NULL default '',
+ option_value DATE NOT NULL
+ );"
);
}
@@ -202,7 +202,7 @@ public function testUpdateWithoutWhereButWithSubSelect() {
);
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('first', '2003-05-27 10:08:48');"
- );
+ );
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('second', '2003-05-27 10:08:48');"
);
@@ -210,7 +210,7 @@ public function testUpdateWithoutWhereButWithSubSelect() {
"UPDATE _dates SET option_value = (SELECT option_value from _options WHERE option_name = 'User 0000019')"
);
$this->assertSame( 2, $return, 'UPDATE query did not return 2 when two row were changed' );
-
+
$result1 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='first'" );
$result2 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='second'" );
$this->assertEquals( 'second', $result1[0]->option_value );
@@ -220,7 +220,7 @@ public function testUpdateWithoutWhereButWithSubSelect() {
public function testUpdateWithoutWhereButWithLimit() {
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('first', '2003-05-27 10:08:48');"
- );
+ );
$this->assertQuery(
"INSERT INTO _dates (option_name, option_value) VALUES ('second', '2003-05-27 10:08:48');"
);
@@ -228,7 +228,7 @@ public function testUpdateWithoutWhereButWithLimit() {
"UPDATE _dates SET option_value = 'second' LIMIT 1"
);
$this->assertSame( 1, $return, 'UPDATE query did not return 2 when two row were changed' );
-
+
$result1 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='first'" );
$result2 = $this->engine->query( "SELECT option_value FROM _dates WHERE option_name='second'" );
$this->assertEquals( 'second', $result1[0]->option_value );
@@ -252,6 +252,84 @@ public function testSelectFromDual() {
$this->assertEquals( 1, $result[0]->output );
}
+ public function testShowCreateTable1() {
+ $this->assertQuery(
+ "CREATE TABLE _tmp_table (
+ ID BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL,
+ option_name VARCHAR(255) default '',
+ option_value TEXT NOT NULL,
+ UNIQUE KEY option_name (option_name),
+ KEY composite (option_name, option_value)
+ );"
+ );
+
+ $this->assertQuery(
+ 'SHOW CREATE TABLE _tmp_table;'
+ );
+ $results = $this->engine->get_query_results();
+ $this->assertEquals(
+ "CREATE TABLE _tmp_table (
+ `ID` bigint PRIMARY KEY AUTO_INCREMENT NOT NULL,
+ `option_name` varchar(255) DEFAULT '',
+ `option_value` text NOT NULL,
+ KEY _tmp_table__composite (option_name, option_value),
+ UNIQUE KEY _tmp_table__option_name (option_name)
+ );",
+ $results[0]->{'Create Table'}
+ );
+ }
+
+ public function testShowCreateTableSimpleTable() {
+ $this->assertQuery(
+ 'CREATE TABLE _tmp_table (
+ ID BIGINT NOT NULL
+ );'
+ );
+
+ $this->assertQuery(
+ 'SHOW CREATE TABLE _tmp_table;'
+ );
+ $results = $this->engine->get_query_results();
+ $this->assertEquals(
+ 'CREATE TABLE _tmp_table (
+ `ID` bigint NOT NULL
+);',
+ $results[0]->{'Create Table'}
+ );
+ }
+
+ public function testShowCreateTableWithAlterAndCreateIndex() {
+ $this->assertQuery(
+ "CREATE TABLE _tmp_table (
+ ID BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL,
+ option_name VARCHAR(255) default '',
+ option_value TEXT NOT NULL
+ );"
+ );
+
+ $this->assertQuery(
+ 'ALTER TABLE _tmp_table CHANGE COLUMN option_name option_name SMALLINT NOT NULL default 14'
+ );
+
+ $this->assertQuery(
+ 'ALTER TABLE _tmp_table ADD INDEX option_name (option_name);'
+ );
+
+ $this->assertQuery(
+ 'SHOW CREATE TABLE _tmp_table;'
+ );
+ $results = $this->engine->get_query_results();
+ $this->assertEquals(
+ 'CREATE TABLE _tmp_table (
+ `ID` bigint PRIMARY KEY AUTO_INCREMENT NOT NULL,
+ `option_name` smallint NOT NULL DEFAULT 14,
+ `option_value` text NOT NULL,
+ KEY _tmp_table__option_name (option_name)
+);',
+ $results[0]->{'Create Table'}
+ );
+ }
+
public function testSelectIndexHintForce() {
$this->assertQuery( "INSERT INTO _options (option_name) VALUES ('first');" );
$result = $this->assertQuery(
@@ -303,7 +381,6 @@ public function testInsertSelectFromDual() {
$this->assertEquals( 1, $result );
}
-
public function testCreateTemporaryTable() {
$this->assertQuery(
"CREATE TEMPORARY TABLE _tmp_table (
@@ -346,11 +423,10 @@ public function testShowTablesLike() {
);
}
- public function testShowTableStatusFrom()
- {
+ public function testShowTableStatusFrom() {
// Created in setUp() function
- $this->assertQuery("DROP TABLE _options");
- $this->assertQuery("DROP TABLE _dates");
+ $this->assertQuery( 'DROP TABLE _options' );
+ $this->assertQuery( 'DROP TABLE _dates' );
$this->assertQuery(
"CREATE TABLE _tmp_table (
@@ -370,11 +446,10 @@ public function testShowTableStatusFrom()
);
}
- public function testShowTableStatusIn()
- {
+ public function testShowTableStatusIn() {
// Created in setUp() function
- $this->assertQuery("DROP TABLE _options");
- $this->assertQuery("DROP TABLE _dates");
+ $this->assertQuery( 'DROP TABLE _options' );
+ $this->assertQuery( 'DROP TABLE _dates' );
$this->assertQuery(
"CREATE TABLE _tmp_table (
@@ -394,11 +469,10 @@ public function testShowTableStatusIn()
);
}
- public function testShowTableStatusInTwoTables()
- {
+ public function testShowTableStatusInTwoTables() {
// Created in setUp() function
- $this->assertQuery("DROP TABLE _options");
- $this->assertQuery("DROP TABLE _dates");
+ $this->assertQuery( 'DROP TABLE _options' );
+ $this->assertQuery( 'DROP TABLE _dates' );
$this->assertQuery(
"CREATE TABLE _tmp_table (
@@ -427,8 +501,8 @@ public function testShowTableStatusInTwoTables()
public function testShowTableStatusLike() {
// Created in setUp() function
- $this->assertQuery("DROP TABLE _options");
- $this->assertQuery("DROP TABLE _dates");
+ $this->assertQuery( 'DROP TABLE _options' );
+ $this->assertQuery( 'DROP TABLE _dates' );
$this->assertQuery(
"CREATE TABLE _tmp_table1 (
@@ -769,7 +843,6 @@ public function testAlterTableAddFulltextIndex() {
);
}
-
public function testAlterTableModifyColumn() {
$this->assertQuery(
"CREATE TABLE _tmp_table (
@@ -2060,8 +2133,7 @@ public function testTranslatesUtf8SELECT() {
$this->assertQuery( 'DELETE FROM _options' );
}
- public function testOnConflictReplace()
- {
+ public function testOnConflictReplace() {
$this->assertQuery(
"CREATE TABLE _tmp_table (
ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
@@ -2076,15 +2148,15 @@ public function testOnConflictReplace()
$this->assertQuery(
"INSERT INTO _tmp_table VALUES (1, null, null, null, '');"
);
- $result = $this->assertQuery("SELECT * FROM _tmp_table WHERE ID = 1");
+ $result = $this->assertQuery( 'SELECT * FROM _tmp_table WHERE ID = 1' );
$this->assertEquals(
array(
(object) array(
- 'ID' => '1',
- 'name' => 'default-value',
- 'unique_name' => 'unique-default-value',
+ 'ID' => '1',
+ 'name' => 'default-value',
+ 'unique_name' => 'unique-default-value',
'inline_unique_name' => 'inline-unique-default-value',
- 'no_default' => '',
+ 'no_default' => '',
),
),
$result
@@ -2094,10 +2166,10 @@ public function testOnConflictReplace()
"INSERT INTO _tmp_table VALUES (2, '1', '2', '3', '4');"
);
$this->assertQuery(
- "UPDATE _tmp_table SET name = null WHERE ID = 2;"
+ 'UPDATE _tmp_table SET name = null WHERE ID = 2;'
);
- $result = $this->assertQuery("SELECT name FROM _tmp_table WHERE ID = 2");
+ $result = $this->assertQuery( 'SELECT name FROM _tmp_table WHERE ID = 2' );
$this->assertEquals(
array(
(object) array(
@@ -2109,48 +2181,47 @@ public function testOnConflictReplace()
// This should fail because of the UNIQUE constraint
$this->assertQuery(
- "UPDATE _tmp_table SET unique_name = NULL WHERE ID = 2;",
+ 'UPDATE _tmp_table SET unique_name = NULL WHERE ID = 2;',
'UNIQUE constraint failed: _tmp_table.unique_name'
);
// Inline unique constraint aren't supported currently, so this should pass
$this->assertQuery(
- "UPDATE _tmp_table SET inline_unique_name = NULL WHERE ID = 2;",
+ 'UPDATE _tmp_table SET inline_unique_name = NULL WHERE ID = 2;',
''
);
// WPDB allows for NULL values in columns that don't have a default value and a NOT NULL constraint
$this->assertQuery(
- "UPDATE _tmp_table SET no_default = NULL WHERE ID = 2;",
+ 'UPDATE _tmp_table SET no_default = NULL WHERE ID = 2;',
''
);
- $result = $this->assertQuery("SELECT * FROM _tmp_table WHERE ID = 2");
+ $result = $this->assertQuery( 'SELECT * FROM _tmp_table WHERE ID = 2' );
$this->assertEquals(
array(
(object) array(
- 'ID' => '2',
- 'name' => 'default-value',
- 'unique_name' => '2',
+ 'ID' => '2',
+ 'name' => 'default-value',
+ 'unique_name' => '2',
'inline_unique_name' => 'inline-unique-default-value',
- 'no_default' => '',
+ 'no_default' => '',
),
),
$result
);
}
- public function testDefaultNullValue()
- {
+ public function testDefaultNullValue() {
$this->assertQuery(
- "CREATE TABLE _tmp_table (
+ 'CREATE TABLE _tmp_table (
name varchar(20) NOT NULL default NULL,
no_default varchar(20) NOT NULL
- );"
+ );'
);
$result = $this->assertQuery(
- "DESCRIBE _tmp_table;"
+ 'DESCRIBE _tmp_table;'
);
$this->assertEquals(
array(
diff --git a/wp-includes/sqlite/class-wp-sqlite-translator.php b/wp-includes/sqlite/class-wp-sqlite-translator.php
index c56ec1f..6ef1eed 100644
--- a/wp-includes/sqlite/class-wp-sqlite-translator.php
+++ b/wp-includes/sqlite/class-wp-sqlite-translator.php
@@ -1128,23 +1128,23 @@ private function make_sqlite_field_definition( $field ) {
* This mode allows the use of `NULL` when NOT NULL is set on a column that falls back to DEFAULT.
* SQLite does not support this behavior, so we need to add the `ON CONFLICT REPLACE` clause to the column definition.
*/
- if ($field->not_null) {
+ if ( $field->not_null ) {
$definition .= ' ON CONFLICT REPLACE';
}
/**
* The value of DEFAULT can be NULL. PHP would print this as an empty string, so we need a special case for it.
*/
- if (null === $field->default) {
+ if ( null === $field->default ) {
$definition .= ' DEFAULT NULL';
- } else if (false !== $field->default) {
+ } elseif ( false !== $field->default ) {
$definition .= ' DEFAULT ' . $field->default;
- } else if ($field->not_null) {
+ } elseif ( $field->not_null ) {
/**
* If the column is NOT NULL, we need to provide a default value to match WPDB behavior caused by removing the STRICT_TRANS_TABLES mode.
*/
- if ('text' === $field->sqlite_data_type) {
+ if ( 'text' === $field->sqlite_data_type ) {
$definition .= ' DEFAULT \'\'';
- } else if (in_array($field->sqlite_data_type, array('integer', 'real'), true)) {
+ } elseif ( in_array( $field->sqlite_data_type, array( 'integer', 'real' ), true ) ) {
$definition .= ' DEFAULT 0';
}
}
@@ -1501,7 +1501,7 @@ private function execute_select() {
* [FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])
* | {IGNORE|FORCE} {INDEX|KEY}
* [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
- *
+ *
* @see https://dev.mysql.com/doc/refman/8.3/en/index-hints.html
* @return bool
*/
@@ -1524,8 +1524,8 @@ private function skip_index_hint() {
return false;
}
- $this->rewriter->skip(); // USE, FORCE, IGNORE
- $this->rewriter->skip(); // INDEX, KEY
+ $this->rewriter->skip(); // USE, FORCE, IGNORE.
+ $this->rewriter->skip(); // INDEX, KEY.
$maybe_for = $this->rewriter->peek();
if ( $maybe_for && $maybe_for->matches(
@@ -1533,7 +1533,7 @@ private function skip_index_hint() {
WP_SQLite_Token::FLAG_KEYWORD_RESERVED,
array( 'FOR' )
) ) {
- $this->rewriter->skip(); // FOR
+ $this->rewriter->skip(); // FOR.
$token = $this->rewriter->peek();
if ( $token && $token->matches(
@@ -1541,9 +1541,9 @@ private function skip_index_hint() {
WP_SQLite_Token::FLAG_KEYWORD_RESERVED,
array( 'JOIN', 'ORDER', 'GROUP' )
) ) {
- $this->rewriter->skip(); // JOIN, ORDER, GROUP
+ $this->rewriter->skip(); // JOIN, ORDER, GROUP.
if ( 'BY' === strtoupper( $this->rewriter->peek()->value ) ) {
- $this->rewriter->skip(); // BY
+ $this->rewriter->skip(); // BY.
}
}
}
@@ -1584,7 +1584,23 @@ private function execute_truncate() {
private function execute_describe() {
$this->rewriter->skip();
$this->table_name = $this->rewriter->consume()->value;
- $stmt = $this->execute_sqlite_query(
+ $this->set_results_from_fetched_data(
+ $this->describe( $this->table_name )
+ );
+ if ( ! $this->results ) {
+ throw new PDOException( 'Table not found' );
+ }
+ }
+
+ /**
+ * Executes a SELECT statement.
+ *
+ * @param string $table_name The table name.
+ *
+ * @return array
+ */
+ private function describe( $table_name ) {
+ return $this->execute_sqlite_query(
"SELECT
`name` as `Field`,
(
@@ -1593,7 +1609,7 @@ private function execute_describe() {
WHEN 1 THEN 'NO'
END
) as `Null`,
- IFNULL(
+ COALESCE(
d.`mysql_type`,
(
CASE `type`
@@ -1613,19 +1629,14 @@ private function execute_describe() {
ELSE 'PRI'
END
) as `Key`
- FROM pragma_table_info(\"$this->table_name\") p
+ FROM pragma_table_info(\"$table_name\") p
LEFT JOIN " . self::DATA_TYPES_CACHE_TABLE . " d
- ON d.`table` = \"$this->table_name\"
+ ON d.`table` = \"$table_name\"
AND d.`column_or_index` = p.`name`
;
"
- );
- $this->set_results_from_fetched_data(
- $stmt->fetchAll( $this->pdo_fetch_mode )
- );
- if ( ! $this->results ) {
- throw new PDOException( 'Table not found' );
- }
+ )
+ ->fetchAll( $this->pdo_fetch_mode );
}
/**
@@ -1642,9 +1653,9 @@ private function execute_describe() {
*/
private function execute_update() {
$this->rewriter->consume(); // Consume the UPDATE keyword.
- $has_where = false;
+ $has_where = false;
$needs_closing_parenthesis = false;
- $params = array();
+ $params = array();
while ( true ) {
$token = $this->rewriter->peek();
if ( ! $token ) {
@@ -1659,20 +1670,20 @@ private function execute_update() {
* will be rewritten to:
* - UPDATE table SET column = value WHERE rowid IN (SELECT rowid FROM table WHERE condition LIMIT 1);
*/
- if ($this->rewriter->depth === 0) {
- if (($token->value === 'LIMIT' || $token->value === 'ORDER') && !$has_where) {
+ if ( 0 === $this->rewriter->depth ) {
+ if ( ( 'LIMIT' === $token->value || 'ORDER' === $token->value ) && ! $has_where ) {
$this->rewriter->add(
- new WP_SQLite_Token('WHERE', WP_SQLite_Token::TYPE_KEYWORD)
+ new WP_SQLite_Token( 'WHERE', WP_SQLite_Token::TYPE_KEYWORD )
);
$needs_closing_parenthesis = true;
- $this->preface_WHERE_clause_with_a_subquery();
- } else if ($token->value === 'WHERE') {
- $has_where = true;
+ $this->preface_where_clause_with_a_subquery();
+ } elseif ( 'WHERE' === $token->value ) {
+ $has_where = true;
$needs_closing_parenthesis = true;
$this->rewriter->consume();
- $this->preface_WHERE_clause_with_a_subquery();
+ $this->preface_where_clause_with_a_subquery();
$this->rewriter->add(
- new WP_SQLite_Token('WHERE', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED)
+ new WP_SQLite_Token( 'WHERE', WP_SQLite_Token::TYPE_KEYWORD, WP_SQLite_Token::FLAG_KEYWORD_RESERVED )
);
}
}
@@ -1705,7 +1716,7 @@ private function execute_update() {
$this->rewriter->consume();
}
- // Wrap up the WHERE clause with the nested SELECT statement
+ // Wrap up the WHERE clause with the nested SELECT statement.
if ( $needs_closing_parenthesis ) {
$this->rewriter->add( new WP_SQLite_Token( ')', WP_SQLite_Token::TYPE_OPERATOR ) );
}
@@ -1720,16 +1731,16 @@ private function execute_update() {
/**
* Injects `rowid IN (SELECT rowid FROM table WHERE ...` into the WHERE clause at the current
* position in the query.
- *
+ *
* This is necessary to emulate the behavior of MySQL's UPDATE LIMIT and DELETE LIMIT statement
* as SQLite does not support LIMIT in UPDATE and DELETE statements.
- *
+ *
* The WHERE clause is wrapped in a subquery that selects the rowid of the rows that match the original
- * WHERE clause.
- *
+ * WHERE clause.
+ *
* @return void
*/
- private function preface_WHERE_clause_with_a_subquery() {
+ private function preface_where_clause_with_a_subquery() {
$this->rewriter->add_many(
array(
new WP_SQLite_Token( ' ', WP_SQLite_Token::TYPE_WHITESPACE ),
@@ -3248,41 +3259,8 @@ private function execute_show() {
// Fall through.
case 'COLUMNS FROM':
$table_name = $this->rewriter->consume()->token;
- $stmt = $this->execute_sqlite_query(
- "PRAGMA table_info(\"$table_name\");"
- );
- /* @todo we may need to add the Extra column if anybdy needs it. 'auto_increment' is the value */
- $name_map = array(
- 'name' => 'Field',
- 'type' => 'Type',
- 'dflt_value' => 'Default',
- 'cid' => null,
- 'notnull' => null,
- 'pk' => null,
- );
- $columns = $stmt->fetchAll( $this->pdo_fetch_mode );
- $columns = array_map(
- function ( $row ) use ( $name_map ) {
- $new = array();
- $is_object = is_object( $row );
- $row = $is_object ? (array) $row : $row;
- foreach ( $row as $k => $v ) {
- $k = array_key_exists( $k, $name_map ) ? $name_map [ $k ] : $k;
- if ( $k ) {
- $new[ $k ] = $v;
- }
- }
- if ( array_key_exists( 'notnull', $row ) ) {
- $new['Null'] = ( '1' === $row ['notnull'] ) ? 'NO' : 'YES';
- }
- if ( array_key_exists( 'pk', $row ) ) {
- $new['Key'] = ( '1' === $row ['pk'] ) ? 'PRI' : '';
- }
- return $is_object ? (object) $new : $new;
- },
- $columns
- );
- $this->set_results_from_fetched_data( $columns );
+
+ $this->set_results_from_fetched_data( $this->get_columns_from( $table_name ) );
return;
case 'INDEX FROM':
@@ -3357,22 +3335,67 @@ function ( $row ) use ( $name_map ) {
return;
+ case 'CREATE TABLE':
+ $table_name = $this->rewriter->consume()->token;
+ $columns = $this->get_columns_from( $table_name );
+ $keys = $this->get_keys( $table_name );
+
+ foreach ( $columns as $column ) {
+ $column = (array) $column;
+ $definition = '';
+ $definition .= '`' . $column['Field'] . '` ';
+ $definition .= $this->get_cached_mysql_data_type(
+ $table_name,
+ $column['Field']
+ ) ?? $column['Type'];
+ $definition .= 'PRI' === $column['Key'] ? ' PRIMARY KEY' : '';
+ $definition .= 'PRI' === $column['Key'] && 'INTEGER' === $column['Type'] ? ' AUTO_INCREMENT' : '';
+ $definition .= 'NO' === $column['Null'] ? ' NOT NULL' : '';
+ $definition .= $column['Default'] ? ' DEFAULT ' . $column['Default'] : '';
+ $entries[] = $definition;
+ }
+ foreach ( $keys as $key ) {
+ $key = (array) $key;
+ $definition = '';
+ $definition .= '1' === $key['index']['unique'] ? 'UNIQUE ' : '';
+ $definition .= 'KEY ';
+ $definition .= $key['index']['name'];
+ $definition .= ' (';
+ $definition .= implode(
+ ', ',
+ array_column( $key['columns'], 'name' )
+ );
+ $definition .= ')';
+ $entries[] = $definition;
+ }
+ $create_table = "CREATE TABLE $table_name (\n\t";
+ $create_table .= implode( ",\n\t", $entries );
+ $create_table .= "\n);";
+ $this->set_results_from_fetched_data(
+ array(
+ (object) array(
+ 'Create Table' => $create_table,
+ ),
+ )
+ );
+ return;
+
case 'TABLE STATUS': // FROM `database`.
- // Match the optional [{FROM | IN} db_name]
+ // Match the optional [{FROM | IN} db_name].
$database_expression = $this->rewriter->consume();
- if ( $database_expression->token === 'FROM' || $database_expression->token === 'IN' ) {
+ if ( 'FROM' === $database_expression->token || 'IN' === $database_expression->token ) {
$this->rewriter->consume();
$database_expression = $this->rewriter->consume();
}
$pattern = '%';
// [LIKE 'pattern' | WHERE expr]
- if($database_expression->token === 'LIKE') {
+ if ( 'LIKE' === $database_expression->token ) {
$pattern = $this->rewriter->consume()->value;
- } else if($database_expression->token === 'WHERE') {
+ } elseif ( 'WHERE' === $database_expression->token ) {
// @TODO Support me please.
- } else if($database_expression->token !== ';') {
- throw new Exception( 'Syntax error: Unexpected token ' . $database_expression->token .' in query '. $this->mysql_query );
+ } elseif ( ';' !== $database_expression->token ) {
+ throw new Exception( 'Syntax error: Unexpected token ' . $database_expression->token . ' in query ' . $this->mysql_query );
}
$database_expression = $this->rewriter->skip();
@@ -3401,12 +3424,11 @@ function ( $row ) use ( $name_map ) {
type='table'
AND name LIKE :pattern
ORDER BY name",
-
array(
':pattern' => $pattern,
)
);
- $tables = $this->strip_sqlite_system_tables( $stmt->fetchAll( $this->pdo_fetch_mode ) );
+ $tables = $this->strip_sqlite_system_tables( $stmt->fetchAll( $this->pdo_fetch_mode ) );
foreach ( $tables as $table ) {
$table_name = $table->Name; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
$stmt = $this->execute_sqlite_query( "SELECT COUNT(1) as `Rows` FROM $table_name" );
@@ -3455,6 +3477,51 @@ function ( $row ) use ( $name_map ) {
}
}
+ /**
+ * Gets the columns from a table.
+ *
+ * @param string $table_name The table name.
+ *
+ * @return array The columns.
+ */
+ private function get_columns_from( $table_name ) {
+ $stmt = $this->execute_sqlite_query(
+ "PRAGMA table_info(\"$table_name\");"
+ );
+ /* @todo we may need to add the Extra column if anybdy needs it. 'auto_increment' is the value */
+ $name_map = array(
+ 'name' => 'Field',
+ 'type' => 'Type',
+ 'dflt_value' => 'Default',
+ 'cid' => null,
+ 'notnull' => null,
+ 'pk' => null,
+ );
+ $columns = $stmt->fetchAll( $this->pdo_fetch_mode );
+ $columns = array_map(
+ function ( $row ) use ( $name_map ) {
+ $new = array();
+ $is_object = is_object( $row );
+ $row = $is_object ? (array) $row : $row;
+ foreach ( $row as $k => $v ) {
+ $k = array_key_exists( $k, $name_map ) ? $name_map [ $k ] : $k;
+ if ( $k ) {
+ $new[ $k ] = $v;
+ }
+ }
+ if ( array_key_exists( 'notnull', $row ) ) {
+ $new['Null'] = ( '1' === $row ['notnull'] ) ? 'NO' : 'YES';
+ }
+ if ( array_key_exists( 'pk', $row ) ) {
+ $new['Key'] = ( '1' === $row ['pk'] ) ? 'PRI' : '';
+ }
+ return $is_object ? (object) $new : $new;
+ },
+ $columns
+ );
+ return $columns;
+ }
+
/**
* Consumes data types from the query.
*
diff --git a/wp-includes/sqlite/install-functions.php b/wp-includes/sqlite/install-functions.php
index 5145164..cfce3a2 100644
--- a/wp-includes/sqlite/install-functions.php
+++ b/wp-includes/sqlite/install-functions.php
@@ -31,7 +31,7 @@ function sqlite_make_db_sqlite() {
wp_die( $message, 'Database Error!' );
}
- $translator = new WP_SQLite_Translator( $pdo, $GLOBALS['table_prefix'] );
+ $translator = new WP_SQLite_Translator( $pdo );
$query = null;
try {