Skip to content
This repository was archived by the owner on Jun 2, 2025. It is now read-only.

Commit 5d977cc

Browse files
committed
Implement reading session SQL modes
1 parent 242371e commit 5d977cc

File tree

3 files changed

+61
-9
lines changed

3 files changed

+61
-9
lines changed

tests/WP_SQLite_Driver_Tests.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4297,4 +4297,31 @@ public function testNonStrictSqlModeNotNullWithDefault(): void {
42974297
$this->assertCount( 1, $result );
42984298
$this->assertSame( '', $result[0]->value );
42994299
}
4300+
4301+
public function testSessionSqlModes(): void {
4302+
// Syntax: "sql_mode" ("@@sql_mode" for SELECT)
4303+
$this->assertQuery( 'SET sql_mode = "ERROR_FOR_DIVISION_BY_ZERO"' );
4304+
$result = $this->assertQuery( 'SELECT @@sql_mode' );
4305+
$this->assertSame( 'ERROR_FOR_DIVISION_BY_ZERO', $result[0]->{'@@sql_mode'} );
4306+
4307+
// Syntax: "@@sql_mode"
4308+
$this->assertQuery( 'SET @@sql_mode = "NO_ENGINE_SUBSTITUTION"' );
4309+
$result = $this->assertQuery( 'SELECT @@sql_mode' );
4310+
$this->assertSame( 'NO_ENGINE_SUBSTITUTION', $result[0]->{'@@sql_mode'} );
4311+
4312+
// Syntax: "SESSION sql_mode" ("@@sql_mode" for SELECT)
4313+
$this->assertQuery( 'SET SESSION sql_mode = "NO_ZERO_DATE"' );
4314+
$result = $this->assertQuery( 'SELECT @@sql_mode' );
4315+
$this->assertSame( 'NO_ZERO_DATE', $result[0]->{'@@sql_mode'} );
4316+
4317+
// Syntax: "@@SESSION.sql_mode"
4318+
$this->assertQuery( 'SET @@SESSION.sql_mode = "NO_ZERO_IN_DATE"' );
4319+
$result = $this->assertQuery( 'SELECT @@SESSION.sql_mode' );
4320+
$this->assertSame( 'NO_ZERO_IN_DATE', $result[0]->{'@@SESSION.sql_mode'} );
4321+
4322+
// Mixed case
4323+
$this->assertQuery( 'SET @@session.SQL_mode = "only_full_group_by"' );
4324+
$result = $this->assertQuery( 'SELECT @@session.SQL_mode' );
4325+
$this->assertSame( 'ONLY_FULL_GROUP_BY', $result[0]->{'@@session.SQL_mode'} );
4326+
}
43004327
}

tests/WP_SQLite_Driver_Translation_Tests.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,17 +1220,17 @@ public function testSerialDataTypes(): void {
12201220

12211221
public function testSystemVariables(): void {
12221222
$this->assertQuery(
1223-
'SELECT NULL',
1223+
"SELECT 'ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES' AS `@@sql_mode`",
12241224
'SELECT @@sql_mode'
12251225
);
12261226

12271227
$this->assertQuery(
1228-
'SELECT NULL',
1228+
"SELECT 'ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES' AS `@@SESSION.sql_mode`",
12291229
'SELECT @@SESSION.sql_mode'
12301230
);
12311231

12321232
$this->assertQuery(
1233-
'SELECT NULL',
1233+
"SELECT 'ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES' AS `@@GLOBAL.sql_mode`",
12341234
'SELECT @@GLOBAL.sql_mode'
12351235
);
12361236
}

wp-includes/sqlite-ast/class-wp-sqlite-driver.php

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,9 +2094,9 @@ private function translate( $node ): ?string {
20942094
throw $this->new_invalid_input_exception();
20952095
}
20962096

2097-
$type = self::DATA_TYPE_MAP[ $child->id ] ?? null;
2098-
if ( null !== $type ) {
2099-
return $type;
2097+
$type_token = self::DATA_TYPE_MAP[ $child->id ] ?? null;
2098+
if ( null !== $type_token ) {
2099+
return $type_token;
21002100
}
21012101

21022102
// SERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.
@@ -2136,12 +2136,37 @@ private function translate( $node ): ?string {
21362136
case 'functionCall':
21372137
return $this->translate_function_call( $node );
21382138
case 'systemVariable':
2139-
// @TODO: Emulate some system variables, or use reasonable defaults.
2139+
$var_ident_type = $node->get_first_child_node( 'varIdentType' );
2140+
$type_token = $var_ident_type ? $var_ident_type->get_first_child_token() : null;
2141+
$original_name = $this->unquote_sqlite_identifier(
2142+
$this->translate( $node->get_first_child_node( 'textOrIdentifier' ) )
2143+
);
2144+
2145+
$name = strtolower( $original_name );
2146+
$type = $type_token ? $type_token->id : WP_MySQL_Lexer::SESSION_SYMBOL;
2147+
if ( 'sql_mode' === $name ) {
2148+
$value = $this->pdo->quote( implode( ',', $this->active_sql_modes ) );
2149+
} else {
2150+
// When we have no value, it's reasonable to use NULL.
2151+
$value = 'NULL';
2152+
}
2153+
2154+
// @TODO: Emulate more system variables, or use reasonable defaults.
21402155
// See: https://dev.mysql.com/doc/refman/8.4/en/server-system-variable-reference.html
21412156
// See: https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html
21422157

2143-
// When we have no value, it's reasonable to use NULL.
2144-
return 'NULL';
2158+
// TODO: Original name should come from the original MySQL input,
2159+
// exactly as it was written by the user, and not translated.
2160+
2161+
// TODO: The '% AS %' syntax is compatible with SELECT lists only.
2162+
// We need to translate it differently when used as a value.
2163+
return sprintf(
2164+
'%s AS %s',
2165+
$value,
2166+
$this->quote_sqlite_identifier(
2167+
'@@' . ( $type_token ? "$type_token->value." : '' ) . $original_name
2168+
)
2169+
);
21452170
case 'castType':
21462171
// Translate "CAST(... AS BINARY)" to "CAST(... AS BLOB)".
21472172
if ( $node->has_child_token( WP_MySQL_Lexer::BINARY_SYMBOL ) ) {

0 commit comments

Comments
 (0)