@@ -302,6 +302,7 @@ class ParseableDialect(default.DefaultDialect):
302302 driver = 'rest'
303303 statement_compiler = ParseableCompiler
304304
305+ # Basic dialect properties
305306 supports_alter = False
306307 supports_pk_autoincrement = False
307308 supports_default_values = False
@@ -311,11 +312,24 @@ class ParseableDialect(default.DefaultDialect):
311312 returns_unicode_strings = True
312313 description_encoding = None
313314 supports_native_boolean = True
315+ supports_multivalues_insert = False
316+
317+ # Read-only properties
318+ supports_statement_cache = True
319+ is_readonly = True
320+ supports_schemas = False
321+ postfetch_lastrowid = False
322+ supports_sane_rowcount = False
323+ supports_sane_multi_rowcount = False
324+ supports_default_metavalue = False
314325
315326 @classmethod
316327 def dbapi (cls ):
317328 return sys .modules [__name__ ]
318329
330+ def _get_server_version_info (self , connection ):
331+ return (1 , 0 , 0 )
332+
319333 def create_connect_args (self , url ):
320334 table_name = url .database if url .database else None
321335
@@ -342,6 +356,34 @@ def create_connect_args(self, url):
342356 print (f"\n === CONNECTION ARGS ===\n Protocol: { 'HTTPS' if use_https else 'HTTP' } \n Port: { kwargs ['port' ]} \n SSL Verify: { kwargs ['verify_ssl' ]} \n =====================\n " , file = sys .stderr )
343357 return [], kwargs
344358
359+ def _check_unicode_returns (self , connection , additional_tests = None ):
360+ return True
361+
362+ def _check_unicode_description (self , connection ):
363+ return True
364+
365+ def do_execute (self , cursor , statement , parameters , context = None ):
366+ """Execute a statement with parameters."""
367+ import sqlparse
368+
369+ # Parse and validate the SQL statement
370+ parsed = sqlparse .parse (statement )
371+ if not parsed :
372+ raise DatabaseError ("Empty SQL statement" )
373+
374+ stmt = parsed [0 ]
375+ stmt_type = stmt .get_type ().upper ()
376+
377+ # Only allow SELECT statements
378+ if stmt_type not in ('SELECT' , 'UNKNOWN' ):
379+ raise DatabaseError (f"Only SELECT statements are allowed. Got: { stmt_type } " )
380+
381+ # For UNKNOWN type, check if it starts with SELECT
382+ if stmt_type == 'UNKNOWN' and not statement .strip ().upper ().startswith ('SELECT' ):
383+ raise DatabaseError ("Only SELECT statements are allowed" )
384+
385+ return cursor .execute (statement , parameters )
386+
345387 def do_ping (self , dbapi_connection ):
346388 try :
347389 cursor = dbapi_connection .cursor ()
@@ -423,6 +465,29 @@ def get_foreign_keys(self, connection: Connection, table_name: str, schema: Opti
423465 def get_indexes (self , connection : Connection , table_name : str , schema : Optional [str ] = None , ** kw ) -> List [Dict [str , Any ]]:
424466 return []
425467
468+ def get_isolation_level (self , connection ):
469+ """Return AUTOCOMMIT as isolation level."""
470+ return 'AUTOCOMMIT'
471+
472+ def do_rollback (self , dbapi_connection ):
473+ """No-op for rollback in read-only mode."""
474+ pass
475+
476+ def do_commit (self , dbapi_connection ):
477+ """No-op for commit in read-only mode."""
478+ pass
479+
480+ def do_terminate (self , dbapi_connection ):
481+ """Close the connection."""
482+ dbapi_connection .close ()
483+
484+ def has_sequence (self , connection , sequence_name , schema = None ):
485+ return False
486+
487+ @classmethod
488+ def get_sync_status (cls ):
489+ return True
490+
426491def connect (* args , ** kwargs ):
427492 """Connect to a Parseable database."""
428493 return ParseableConnection (
@@ -433,7 +498,7 @@ def connect(*args, **kwargs):
433498 database = kwargs .get ('database' ),
434499 verify_ssl = kwargs .get ('verify_ssl' , True ),
435500 use_https = kwargs .get ('use_https' , True )
436- )
501+ )
437502
438503# Export the connect function at module level
439504__all__ = ['ParseableDialect' , 'connect' , 'Error' , 'DatabaseError' , 'InterfaceError' ]
0 commit comments