@@ -302,6 +302,7 @@ class ParseableDialect(default.DefaultDialect):
302
302
driver = 'rest'
303
303
statement_compiler = ParseableCompiler
304
304
305
+ # Basic dialect properties
305
306
supports_alter = False
306
307
supports_pk_autoincrement = False
307
308
supports_default_values = False
@@ -311,11 +312,24 @@ class ParseableDialect(default.DefaultDialect):
311
312
returns_unicode_strings = True
312
313
description_encoding = None
313
314
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
314
325
315
326
@classmethod
316
327
def dbapi (cls ):
317
328
return sys .modules [__name__ ]
318
329
330
+ def _get_server_version_info (self , connection ):
331
+ return (1 , 0 , 0 )
332
+
319
333
def create_connect_args (self , url ):
320
334
table_name = url .database if url .database else None
321
335
@@ -342,6 +356,34 @@ def create_connect_args(self, url):
342
356
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 )
343
357
return [], kwargs
344
358
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
+
345
387
def do_ping (self , dbapi_connection ):
346
388
try :
347
389
cursor = dbapi_connection .cursor ()
@@ -423,6 +465,29 @@ def get_foreign_keys(self, connection: Connection, table_name: str, schema: Opti
423
465
def get_indexes (self , connection : Connection , table_name : str , schema : Optional [str ] = None , ** kw ) -> List [Dict [str , Any ]]:
424
466
return []
425
467
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
+
426
491
def connect (* args , ** kwargs ):
427
492
"""Connect to a Parseable database."""
428
493
return ParseableConnection (
@@ -433,7 +498,7 @@ def connect(*args, **kwargs):
433
498
database = kwargs .get ('database' ),
434
499
verify_ssl = kwargs .get ('verify_ssl' , True ),
435
500
use_https = kwargs .get ('use_https' , True )
436
- )
501
+ )
437
502
438
503
# Export the connect function at module level
439
504
__all__ = ['ParseableDialect' , 'connect' , 'Error' , 'DatabaseError' , 'InterfaceError' ]
0 commit comments