Skip to content

Commit 234198a

Browse files
feat(exasol): transpile USE/OPEN SCHEMA and SHOW TABLES to system-table query (#7538)
* feat(exasol): transpile USE/OPEN SCHEMA and SHOW TABLES to system-table query Exasol uses `OPEN SCHEMA <name>` where other dialects use `USE <name>`, and has no native `SHOW TABLES` statement — the equivalent is a SELECT on `SYS.EXA_ALL_TABLES`. Previously both statements produced invalid Exasol output (parse error or empty string). Changes: * Add `use_sql` in ExasolGenerator that emits `OPEN SCHEMA <this>` for the default `USE schema` form. For other kinds (e.g. `USE ROLE admin`, `USE WAREHOUSE wh`), emit an unsupported warning and fall back to the base `USE` generator rather than silently rewriting them as schema switches. * Add parser support in ExasolParser for `OPEN SCHEMA <id>` so it round- trips as an `exp.Use` node. * Add `show_sql` in ExasolGenerator that rewrites `SHOW TABLES [FROM db]` to `SELECT TABLE_NAME FROM SYS.EXA_ALL_TABLES WHERE TABLE_SCHEMA = ...`, using the provided schema (uppercased to match Exasol metadata) or `CURRENT_SCHEMA` when absent. Other SHOW kinds fall through to the base generator (which marks them unsupported). * Update sqlglot/parsers/exasol.py * Update sqlglot/parsers/exasol.py --------- Co-authored-by: Jo <46752250+georgesittas@users.noreply.github.com>
1 parent 8e4386d commit 234198a

3 files changed

Lines changed: 68 additions & 0 deletions

File tree

sqlglot/generators/exasol.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,31 @@ def if_sql(self, expression: exp.If) -> str:
890890
false = self.sql(expression, "false")
891891
return f"IF {this} THEN {true} ELSE {false} ENDIF"
892892

893+
# https://docs.exasol.com/db/latest/sql/open_schema.htm
894+
def use_sql(self, expression: exp.Use) -> str:
895+
kind = expression.args.get("kind")
896+
if kind and self.sql(kind).upper() != "SCHEMA":
897+
self.unsupported(f"'USE {self.sql(kind)}' is not supported in Exasol")
898+
return super().use_sql(expression)
899+
this = self.sql(expression, "this")
900+
return f"OPEN SCHEMA {this}"
901+
902+
# https://docs.exasol.com/db/latest/sql_references/metadata/metadata_system_tables.htm
903+
def show_sql(self, expression: exp.Show) -> str:
904+
if expression.name == "TABLES":
905+
db_name = expression.text("db")
906+
schema_filter: exp.Expression = (
907+
exp.Literal.string(db_name.upper()) if db_name else exp.CurrentSchema()
908+
)
909+
select = (
910+
exp.select(exp.column("TABLE_NAME"))
911+
.from_(exp.table_("EXA_ALL_TABLES", db="SYS"))
912+
.where(exp.column("TABLE_SCHEMA").eq(schema_filter))
913+
)
914+
return self.sql(select)
915+
916+
return super().show_sql(expression)
917+
893918
def collate_sql(self, expression: exp.Collate) -> str:
894919
return self.sql(expression.this)
895920

sqlglot/parsers/exasol.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ class ExasolParser(parser.Parser):
127127
"JSON_EXTRACT": lambda self: self._parse_json_extract(),
128128
}
129129

130+
def _parse_statement(self) -> exp.Expr | None:
131+
# https://docs.exasol.com/db/latest/sql/open_schema.htm
132+
if self._match_text_seq("OPEN", "SCHEMA"):
133+
return self.expression(exp.Use(this=self._parse_table(schema=False)))
134+
return super()._parse_statement()
135+
130136
def _parse_column(self) -> exp.Expr | None:
131137
column = super()._parse_column()
132138
if not isinstance(column, exp.Column):

tests/dialects/test_exasol.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,3 +954,40 @@ def test_group_by_all(self):
954954
write="exasol",
955955
unsupported_level=ErrorLevel.RAISE,
956956
)
957+
958+
def test_use_to_open_schema(self):
959+
self.validate_all(
960+
"OPEN SCHEMA test",
961+
read={"mysql": "USE test"},
962+
write={"exasol": "OPEN SCHEMA test"},
963+
)
964+
self.validate_identity("OPEN SCHEMA test")
965+
self.validate_all(
966+
'OPEN SCHEMA "my_database"',
967+
read={"mysql": "USE `my_database`"},
968+
write={"exasol": 'OPEN SCHEMA "my_database"'},
969+
)
970+
# USE ROLE / USE WAREHOUSE have no Exasol equivalent — emit unsupported
971+
with self.assertRaises(UnsupportedError):
972+
transpile(
973+
"USE ROLE admin",
974+
read="snowflake",
975+
write="exasol",
976+
unsupported_level=ErrorLevel.RAISE,
977+
)
978+
979+
def test_show_tables(self):
980+
self.validate_all(
981+
"SELECT TABLE_NAME FROM SYS.EXA_ALL_TABLES WHERE TABLE_SCHEMA = 'TEST'",
982+
read={"mysql": "SHOW TABLES FROM test"},
983+
write={
984+
"exasol": "SELECT TABLE_NAME FROM SYS.EXA_ALL_TABLES WHERE TABLE_SCHEMA = 'TEST'"
985+
},
986+
)
987+
self.validate_all(
988+
"SELECT TABLE_NAME FROM SYS.EXA_ALL_TABLES WHERE TABLE_SCHEMA = CURRENT_SCHEMA",
989+
read={"mysql": "SHOW TABLES"},
990+
write={
991+
"exasol": "SELECT TABLE_NAME FROM SYS.EXA_ALL_TABLES WHERE TABLE_SCHEMA = CURRENT_SCHEMA"
992+
},
993+
)

0 commit comments

Comments
 (0)