Skip to content

Commit b9aae37

Browse files
committed
Add basic support for session system variables
1 parent 08fdfe3 commit b9aae37

2 files changed

Lines changed: 41 additions & 7 deletions

File tree

tests/WP_SQLite_Driver_Tests.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6056,6 +6056,20 @@ public function testSetStatement(): void {
60566056
$this->assertQuery( 'SET CHARACTER SET utf8mb4' );
60576057
}
60586058

6059+
public function testSessionSystemVariables(): void {
6060+
$this->assertQuery( "SET character_set_client = 'latin1'" );
6061+
$result = $this->assertQuery( 'SELECT @@character_set_client' );
6062+
$this->assertSame( 'latin1', $result[0]->{'@@character_set_client'} );
6063+
6064+
$this->assertQuery( "SET @@character_set_client = 'utf8mb3'" );
6065+
$result = $this->assertQuery( 'SELECT @@character_set_client' );
6066+
$this->assertSame( 'utf8mb3', $result[0]->{'@@character_set_client'} );
6067+
6068+
$this->assertQuery( "SET @@session.character_set_client = 'utf8mb4'" );
6069+
$result = $this->assertQuery( 'SELECT @@session.character_set_client' );
6070+
$this->assertSame( 'utf8mb4', $result[0]->{'@@session.character_set_client'} );
6071+
}
6072+
60596073
public function testUserVariables(): void {
60606074
$this->assertQuery( 'SET @my_var = 1' );
60616075
$result = $this->assertQuery( 'SELECT @my_var' );

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

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,19 @@ class WP_SQLite_Driver {
425425
'STRICT_TRANS_TABLES',
426426
);
427427

428+
/**
429+
* A name-to-value map of MySQL system variables for the current session.
430+
*
431+
* MySQL session system variables are session-specific, so we can store them
432+
* in-memory. In SQL queries, they are combined with global system variables.
433+
*
434+
* See:
435+
* https://dev.mysql.com/doc/refman/8.4/en/using-system-variables.html
436+
*
437+
* @var array<string, string>
438+
*/
439+
private $session_system_variables = array();
440+
428441
/**
429442
* A name-to-value map of MySQL user variables.
430443
*
@@ -2175,15 +2188,14 @@ private function execute_set_system_variable_statement(
21752188
$type = $var_ident_type->get_first_child_token()->id;
21762189
}
21772190

2178-
// Get the variable value.
2179-
$value = $this->translate( $value_node );
2180-
$value = str_replace( "''", "'", $value );
2181-
$value = substr( $value, 1, -1 );
2191+
$value = $this->evaluate_expression( $value_node );
21822192

21832193
if ( WP_MySQL_Lexer::SESSION_SYMBOL === $type ) {
21842194
if ( 'sql_mode' === $name ) {
21852195
$modes = explode( ',', strtoupper( $value ) );
21862196
$this->active_sql_modes = $modes;
2197+
} else {
2198+
$this->session_system_variables[ $name ] = $value;
21872199
}
21882200
} elseif ( WP_MySQL_Lexer::GLOBAL_SYMBOL === $type ) {
21892201
throw $this->new_not_supported_exception( "SET statement type: 'GLOBAL'" );
@@ -2485,16 +2497,24 @@ private function translate( $node ): ?string {
24852497
$name = strtolower( $original_name );
24862498
$type = $type_token ? $type_token->id : WP_MySQL_Lexer::SESSION_SYMBOL;
24872499
if ( 'sql_mode' === $name ) {
2488-
$value = $this->connection->quote( implode( ',', $this->active_sql_modes ) );
2500+
$value = implode( ',', $this->active_sql_modes );
2501+
} elseif ( WP_MySQL_Lexer::SESSION_SYMBOL === $type ) {
2502+
$value = $this->session_system_variables[ $name ] ?? null;
24892503
} else {
24902504
// When we have no value, it's reasonable to use NULL.
2491-
$value = 'NULL';
2505+
$value = null;
24922506
}
24932507

24942508
// @TODO: Emulate more system variables, or use reasonable defaults.
24952509
// See: https://dev.mysql.com/doc/refman/8.4/en/server-system-variable-reference.html
24962510
// See: https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html
2497-
return $value;
2511+
if ( null === $value ) {
2512+
return 'NULL';
2513+
}
2514+
if ( is_string( $value ) ) {
2515+
return $this->connection->quote( $value );
2516+
}
2517+
return (string) $value;
24982518
case 'userVariable':
24992519
$name = $this->unquote_sqlite_identifier( $this->translate( $node->get_first_child() ) );
25002520
$name = strtolower( substr( $name, 1 ) ); // Remove '@', normalize case.

0 commit comments

Comments
 (0)