@@ -3416,7 +3416,16 @@ private function translate_qualified_identifier(
34163416
34173417 // Object child name (column, index, etc.).
34183418 if ( null !== $ child_node ) {
3419- $ parts [] = $ this ->translate ( $ child_node );
3419+ $ translated = $ this ->translate ( $ child_node );
3420+ $ name = $ this ->unquote_sqlite_identifier ( $ translated );
3421+ $ parts [] = $ translated ;
3422+
3423+ // When targeting a database name column from the information schema,
3424+ // we need to inject the configured database name.
3425+ if ( $ this ->is_information_schema_db_column ( $ name ) ) {
3426+ $ fully_qualified_column = implode ( '. ' , $ parts );
3427+ return $ this ->inject_configured_database_name ( $ fully_qualified_column );
3428+ }
34203429 }
34213430
34223431 return implode ( '. ' , $ parts );
@@ -3916,7 +3925,16 @@ public function translate_select_item( WP_Parser_Node $node ): string {
39163925 $ column_ref = $ node ->get_first_descendant_node ( 'columnRef ' );
39173926 $ is_column_ref = $ column_ref && $ item === $ this ->translate ( $ column_ref );
39183927 if ( $ is_column_ref ) {
3919- return $ item ;
3928+ $ translated = $ this ->translate ( $ column_ref );
3929+
3930+ // When targeting a database name column from the information schema,
3931+ // we need to inject the configured database name and add an alias.
3932+ $ identifiers = $ column_ref ->get_descendant_nodes ( 'identifier ' );
3933+ $ column_name = $ this ->unquote_sqlite_identifier ( $ this ->translate ( end ( $ identifiers ) ) );
3934+ if ( $ this ->is_information_schema_db_column ( $ column_name ) ) {
3935+ return sprintf ( '%s AS %s ' , $ translated , strtoupper ( $ column_name ) );
3936+ }
3937+ return $ translated ;
39203938 }
39213939
39223940 /*
@@ -3939,6 +3957,51 @@ public function translate_select_item( WP_Parser_Node $node ): string {
39393957 return sprintf ( '%s AS %s ' , $ item , $ alias );
39403958 }
39413959
3960+ /**
3961+ * Check if a column name appears to target an information schema column that
3962+ * references the database name ("SCHEMA_NAME", "TABLE_SCHEMA", etc.).
3963+ *
3964+ * TODO: Fully resolve the column references to ensure that they are really
3965+ * referencing the information schema tables.
3966+ *
3967+ * @param string $column_name The name of the column to check.
3968+ * @return bool True if the column is an information schema
3969+ * database name column, false otherwise.
3970+ */
3971+ private function is_information_schema_db_column ( string $ column_name ): bool {
3972+ static $ information_schema_columns = array (
3973+ 'SCHEMA_NAME ' => true ,
3974+ 'TABLE_SCHEMA ' => true ,
3975+ 'VIEW_SCHEMA ' => true ,
3976+ 'INDEX_SCHEMA ' => true ,
3977+ 'CONSTRAINT_SCHEMA ' => true ,
3978+ 'UNIQUE_CONSTRAINT_SCHEMA ' => true ,
3979+ 'REFERENCED_TABLE_SCHEMA ' => true ,
3980+ 'TRIGGER_SCHEMA ' => true ,
3981+ );
3982+ return isset ( $ information_schema_columns [ strtoupper ( $ column_name ) ] );
3983+ }
3984+
3985+ /**
3986+ * Translate a name targeting an information schema database name column
3987+ * to an expression that injects the configured database name value.
3988+ *
3989+ * For example, a reference like "`t`.`table_schema`" will be translated to:
3990+ *
3991+ * IIF(`t`.`table_schema` = 'information_schema', `t`.`table_schema`, 'database_name')
3992+ *
3993+ * @param string $column_name The name of the column to translate.
3994+ * @return string The translated value.
3995+ */
3996+ private function inject_configured_database_name ( string $ column_name ): string {
3997+ return sprintf (
3998+ "IIF(%s = 'information_schema', %s, %s) " ,
3999+ $ column_name ,
4000+ $ column_name ,
4001+ $ this ->connection ->quote ( $ this ->main_db_name ),
4002+ );
4003+ }
4004+
39424005 /**
39434006 * Recreate an existing table using data in the information schema.
39444007 *
0 commit comments