22from __future__ import annotations
33
44from typing import Any
5+ from typing import Literal
56from typing import Protocol
67from typing import TYPE_CHECKING
78
@@ -48,11 +49,29 @@ def _escape_string_literal(value: str) -> str:
4849
4950def _get_table_backend_and_db (
5051 table : ir .Table ,
51- ) -> tuple [BackendExtensionsMixin , str | None ]:
52- """Get SingleStoreDB backend and database from table."""
52+ * ,
53+ escape : Literal ['identifier' , 'literal' ] | None = None ,
54+ ) -> tuple [BackendExtensionsMixin , str ]:
55+ """Get SingleStoreDB backend and database from table.
56+
57+ Parameters
58+ ----------
59+ table
60+ The Ibis table object.
61+ escape
62+ How to escape the database name:
63+ - None: return unescaped
64+ - 'identifier': escape for SQL identifiers (backticks)
65+ - 'literal': escape for string literals (quotes)
66+ """
5367 op = table .op ()
5468 if hasattr (op , 'source' ) and op .source .name == 'singlestoredb' :
5569 db = getattr (getattr (op , 'namespace' , None ), 'database' , None )
70+ db = db or op .source .current_database
71+ if escape == 'identifier' :
72+ db = _quote_identifier (db )
73+ elif escape == 'literal' :
74+ db = _escape_string_literal (db )
5675 return op .source , db # type: ignore[return-value]
5776 raise TypeError (
5877 f'This method only works with SingleStoreDB tables, '
@@ -131,52 +150,6 @@ def get_workload_metrics(self) -> ir.Table:
131150 'SELECT * FROM information_schema.mv_workload_management_events' ,
132151 )
133152
134- def optimize_table (self , table_name : str , * , database : str | None = None ) -> None :
135- """Optimize a specific table.
136-
137- Parameters
138- ----------
139- table_name
140- Name of table to optimize.
141- database
142- Database name. Defaults to current database.
143- """
144- db = _quote_identifier (database or self .current_database )
145- table = _quote_identifier (table_name )
146- with self .raw_sql (f'OPTIMIZE TABLE { db } .{ table } FULL' ):
147- pass
148-
149- def get_table_stats (
150- self ,
151- table_name : str ,
152- * ,
153- database : str | None = None ,
154- ) -> dict [str , Any ]:
155- """Get statistics for a specific table.
156-
157- Parameters
158- ----------
159- table_name
160- Name of table.
161- database
162- Database name. Defaults to current database.
163-
164- Returns
165- -------
166- dict
167- Table statistics.
168- """
169- db = _escape_string_literal (database or self .current_database )
170- table = _escape_string_literal (table_name )
171- # S608: db and table are escaped via _escape_string_literal
172- result = self .sql (
173- f"""
174- SELECT * FROM information_schema.table_statistics
175- WHERE database_name = '{ db } ' AND table_name = '{ table } '
176- """ , # noqa: S608
177- ).execute ()
178- return result .to_dict (orient = 'records' )[0 ] if len (result ) else {}
179-
180153
181154class TableExtensionsMixin (_TableBase ):
182155 """Mixin for ir.Table extensions (SingleStoreDB only)."""
@@ -185,13 +158,23 @@ class TableExtensionsMixin(_TableBase):
185158
186159 def optimize (self ) -> None :
187160 """Optimize this table (SingleStoreDB only)."""
188- backend , db = _get_table_backend_and_db (self )
189- backend .optimize_table (self .get_name (), database = db )
161+ backend , db = _get_table_backend_and_db (self , escape = 'identifier' )
162+ table = _quote_identifier (self .get_name ())
163+ with backend .raw_sql (f'OPTIMIZE TABLE { db } .{ table } FULL' ):
164+ pass
190165
191166 def get_stats (self ) -> dict [str , Any ]:
192167 """Get statistics for this table (SingleStoreDB only)."""
193- backend , db = _get_table_backend_and_db (self )
194- return backend .get_table_stats (self .get_name (), database = db )
168+ backend , db = _get_table_backend_and_db (self , escape = 'literal' )
169+ table = _escape_string_literal (self .get_name ())
170+ # S608: db and table are escaped via _escape_string_literal
171+ result = backend .sql (
172+ f"""
173+ SELECT * FROM information_schema.table_statistics
174+ WHERE database_name = '{ db } ' AND table_name = '{ table } '
175+ """ , # noqa: S608
176+ ).execute ()
177+ return result .to_dict (orient = 'records' )[0 ] if len (result ) else {}
195178
196179 def get_column_statistics (self , column : str | None = None ) -> ir .Table :
197180 """Get column statistics (SingleStoreDB only).
@@ -201,11 +184,9 @@ def get_column_statistics(self, column: str | None = None) -> ir.Table:
201184 column
202185 Specific column name, or None for all columns.
203186 """
204- backend , db = _get_table_backend_and_db (self )
205- db_name = db or backend .current_database
206- db_quoted = _quote_identifier (db_name )
187+ backend , db = _get_table_backend_and_db (self , escape = 'identifier' )
207188 table = _quote_identifier (self .get_name ())
208- query = f'SHOW COLUMNAR_SEGMENT_INDEX ON { db_quoted } .{ table } '
189+ query = f'SHOW COLUMNAR_SEGMENT_INDEX ON { db } .{ table } '
209190 if column :
210191 query += f' COLUMNS ({ _quote_identifier (column )} )'
211192 return backend .sql (query )
0 commit comments