dialect.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. from sqlalchemy.engine.default import DefaultDialect
  2. from clickhouse_connect import dbapi
  3. from clickhouse_connect.cc_sqlalchemy.inspector import ChInspector
  4. from clickhouse_connect.cc_sqlalchemy.sql import full_table
  5. from clickhouse_connect.cc_sqlalchemy.sql.ddlcompiler import ChDDLCompiler
  6. from clickhouse_connect.cc_sqlalchemy import ischema_names, dialect_name
  7. from clickhouse_connect.cc_sqlalchemy.sql.preparer import ChIdentifierPreparer
  8. from clickhouse_connect.driver.query import quote_identifier, format_str
  9. # pylint: disable=too-many-public-methods,no-self-use,unused-argument
  10. class ClickHouseDialect(DefaultDialect):
  11. """
  12. See :py:class:`sqlalchemy.engine.interfaces`
  13. """
  14. name = dialect_name
  15. driver = 'connect'
  16. default_schema_name = 'default'
  17. supports_native_decimal = True
  18. supports_native_boolean = True
  19. supports_statement_cache = False
  20. returns_unicode_strings = True
  21. postfetch_lastrowid = False
  22. ddl_compiler = ChDDLCompiler
  23. preparer = ChIdentifierPreparer
  24. description_encoding = None
  25. max_identifier_length = 127
  26. ischema_names = ischema_names
  27. inspector = ChInspector
  28. # pylint: disable=method-hidden
  29. @classmethod
  30. def dbapi(cls):
  31. return dbapi
  32. def initialize(self, connection):
  33. pass
  34. @staticmethod
  35. def get_schema_names(connection, **_):
  36. return [row.name for row in connection.execute('SHOW DATABASES')]
  37. @staticmethod
  38. def has_database(connection, db_name):
  39. return (connection.execute('SELECT name FROM system.databases ' +
  40. f'WHERE name = {format_str(db_name)}')).rowcount > 0
  41. def get_table_names(self, connection, schema=None, **kw):
  42. cmd = 'SHOW TABLES'
  43. if schema:
  44. cmd += ' FROM ' + quote_identifier(schema)
  45. return [row.name for row in connection.execute(cmd)]
  46. def get_primary_keys(self, connection, table_name, schema=None, **kw):
  47. return []
  48. # pylint: disable=arguments-renamed
  49. def get_pk_constraint(self, connection, table_name, schema=None, **kw):
  50. return []
  51. def get_foreign_keys(self, connection, table_name, schema=None, **kw):
  52. return []
  53. def get_temp_table_names(self, connection, schema=None, **kw):
  54. return []
  55. def get_view_names(self, connection, schema=None, **kw):
  56. return []
  57. def get_temp_view_names(self, connection, schema=None, **kw):
  58. return []
  59. def get_view_definition(self, connection, view_name, schema=None, **kw):
  60. pass
  61. def get_indexes(self, connection, table_name, schema=None, **kw):
  62. return []
  63. def get_unique_constraints(self, connection, table_name, schema=None, **kw):
  64. return []
  65. def get_check_constraints(self, connection, table_name, schema=None, **kw):
  66. return []
  67. def has_table(self, connection, table_name, schema=None, **_kw):
  68. result = connection.execute(f'EXISTS TABLE {full_table(table_name, schema)}')
  69. row = result.fetchone()
  70. return row[0] == 1
  71. def has_sequence(self, connection, sequence_name, schema=None, **_kw):
  72. return False
  73. def do_begin_twophase(self, connection, xid):
  74. raise NotImplementedError
  75. def do_prepare_twophase(self, connection, xid):
  76. raise NotImplementedError
  77. def do_rollback_twophase(self, connection, xid, is_prepared=True, recover=False):
  78. raise NotImplementedError
  79. def do_commit_twophase(self, connection, xid, is_prepared=True, recover=False):
  80. raise NotImplementedError
  81. def do_recover_twophase(self, connection):
  82. raise NotImplementedError
  83. def set_isolation_level(self, dbapi_conn, level):
  84. pass
  85. def get_isolation_level(self, dbapi_conn):
  86. return None