Merge pull request #181 from mangototango/ver_21_9

Fixes to make the tests pass on ClickHouse v21.9
This commit is contained in:
Kobi Tal 2021-10-17 09:55:22 +03:00 committed by GitHub
commit 76d432b838
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 40 additions and 27 deletions

View File

@ -51,6 +51,11 @@ class ServerError(DatabaseException):
Code:\ (?P<code>\d+), Code:\ (?P<code>\d+),
\ e\.displayText\(\)\ =\ (?P<type1>[^ \n]+):\ (?P<msg>.+) \ e\.displayText\(\)\ =\ (?P<type1>[^ \n]+):\ (?P<msg>.+)
''', re.VERBOSE | re.DOTALL), ''', re.VERBOSE | re.DOTALL),
# ClickHouse v21+
re.compile(r'''
Code:\ (?P<code>\d+).
\ (?P<type1>[^ \n]+):\ (?P<msg>.+)
''', re.VERBOSE | re.DOTALL),
) )
@classmethod @classmethod

View File

@ -109,7 +109,7 @@ class Field(FunctionOperatorsMixin):
elif self.default: elif self.default:
default = self.to_db_string(self.default) default = self.to_db_string(self.default)
sql += ' DEFAULT %s' % default sql += ' DEFAULT %s' % default
if self.codec and db and db.has_codec_support: if self.codec and db and db.has_codec_support and not self.alias:
sql += ' CODEC(%s)' % self.codec sql += ' CODEC(%s)' % self.codec
return sql return sql

View File

@ -391,11 +391,11 @@ class F(Cond, FunctionOperatorsMixin, metaclass=FMeta):
return F('toYear', d) return F('toYear', d)
@staticmethod @staticmethod
def toISOYear(d, timezone=''): def toISOYear(d, timezone=NO_VALUE):
return F('toISOYear', d, timezone) return F('toISOYear', d, timezone)
@staticmethod @staticmethod
def toQuarter(d, timezone=''): def toQuarter(d, timezone=NO_VALUE):
return F('toQuarter', d, timezone) if timezone else F('toQuarter', d) return F('toQuarter', d, timezone) if timezone else F('toQuarter', d)
@staticmethod @staticmethod
@ -403,11 +403,11 @@ class F(Cond, FunctionOperatorsMixin, metaclass=FMeta):
return F('toMonth', d) return F('toMonth', d)
@staticmethod @staticmethod
def toWeek(d, mode=0, timezone=''): def toWeek(d, mode=0, timezone=NO_VALUE):
return F('toWeek', d, mode, timezone) return F('toWeek', d, mode, timezone)
@staticmethod @staticmethod
def toISOWeek(d, timezone=''): def toISOWeek(d, timezone=NO_VALUE):
return F('toISOWeek', d, timezone) if timezone else F('toISOWeek', d) return F('toISOWeek', d, timezone) if timezone else F('toISOWeek', d)
@staticmethod @staticmethod
@ -483,7 +483,7 @@ class F(Cond, FunctionOperatorsMixin, metaclass=FMeta):
return F('toStartOfDay', d) return F('toStartOfDay', d)
@staticmethod @staticmethod
def toTime(d, timezone=''): def toTime(d, timezone=NO_VALUE):
return F('toTime', d, timezone) return F('toTime', d, timezone)
@staticmethod @staticmethod
@ -491,47 +491,47 @@ class F(Cond, FunctionOperatorsMixin, metaclass=FMeta):
return F('toTimeZone', dt, timezone) return F('toTimeZone', dt, timezone)
@staticmethod @staticmethod
def toUnixTimestamp(dt, timezone=''): def toUnixTimestamp(dt, timezone=NO_VALUE):
return F('toUnixTimestamp', dt, timezone) return F('toUnixTimestamp', dt, timezone)
@staticmethod @staticmethod
def toYYYYMM(dt, timezone=''): def toYYYYMM(dt, timezone=NO_VALUE):
return F('toYYYYMM', dt, timezone) if timezone else F('toYYYYMM', dt) return F('toYYYYMM', dt, timezone) if timezone else F('toYYYYMM', dt)
@staticmethod @staticmethod
def toYYYYMMDD(dt, timezone=''): def toYYYYMMDD(dt, timezone=NO_VALUE):
return F('toYYYYMMDD', dt, timezone) if timezone else F('toYYYYMMDD', dt) return F('toYYYYMMDD', dt, timezone) if timezone else F('toYYYYMMDD', dt)
@staticmethod @staticmethod
def toYYYYMMDDhhmmss(dt, timezone=''): def toYYYYMMDDhhmmss(dt, timezone=NO_VALUE):
return F('toYYYYMMDDhhmmss', dt, timezone) if timezone else F('toYYYYMMDDhhmmss', dt) return F('toYYYYMMDDhhmmss', dt, timezone) if timezone else F('toYYYYMMDDhhmmss', dt)
@staticmethod @staticmethod
def toRelativeYearNum(d, timezone=''): def toRelativeYearNum(d, timezone=NO_VALUE):
return F('toRelativeYearNum', d, timezone) return F('toRelativeYearNum', d, timezone)
@staticmethod @staticmethod
def toRelativeMonthNum(d, timezone=''): def toRelativeMonthNum(d, timezone=NO_VALUE):
return F('toRelativeMonthNum', d, timezone) return F('toRelativeMonthNum', d, timezone)
@staticmethod @staticmethod
def toRelativeWeekNum(d, timezone=''): def toRelativeWeekNum(d, timezone=NO_VALUE):
return F('toRelativeWeekNum', d, timezone) return F('toRelativeWeekNum', d, timezone)
@staticmethod @staticmethod
def toRelativeDayNum(d, timezone=''): def toRelativeDayNum(d, timezone=NO_VALUE):
return F('toRelativeDayNum', d, timezone) return F('toRelativeDayNum', d, timezone)
@staticmethod @staticmethod
def toRelativeHourNum(d, timezone=''): def toRelativeHourNum(d, timezone=NO_VALUE):
return F('toRelativeHourNum', d, timezone) return F('toRelativeHourNum', d, timezone)
@staticmethod @staticmethod
def toRelativeMinuteNum(d, timezone=''): def toRelativeMinuteNum(d, timezone=NO_VALUE):
return F('toRelativeMinuteNum', d, timezone) return F('toRelativeMinuteNum', d, timezone)
@staticmethod @staticmethod
def toRelativeSecondNum(d, timezone=''): def toRelativeSecondNum(d, timezone=NO_VALUE):
return F('toRelativeSecondNum', d, timezone) return F('toRelativeSecondNum', d, timezone)
@staticmethod @staticmethod
@ -555,7 +555,7 @@ class F(Cond, FunctionOperatorsMixin, metaclass=FMeta):
return F('timeSlots', start_time, F.toUInt32(duration)) return F('timeSlots', start_time, F.toUInt32(duration))
@staticmethod @staticmethod
def formatDateTime(d, format, timezone=''): def formatDateTime(d, format, timezone=NO_VALUE):
return F('formatDateTime', d, format, timezone) return F('formatDateTime', d, format, timezone)
@staticmethod @staticmethod

View File

@ -106,7 +106,7 @@ class CompressedFieldsTestCase(unittest.TestCase):
('nullable_field', 'CODEC(ZSTD(1))'), ('nullable_field', 'CODEC(ZSTD(1))'),
('array_field', 'CODEC(Delta(2), LZ4HC(0))'), ('array_field', 'CODEC(Delta(2), LZ4HC(0))'),
('float_field', 'CODEC(NONE)'), ('float_field', 'CODEC(NONE)'),
('alias_field', 'CODEC(ZSTD(4))')]) ('alias_field', '')])
class CompressedModel(Model): class CompressedModel(Model):

View File

@ -181,12 +181,13 @@ class DatabaseTestCase(TestCaseWithData):
Database(self.database.db_name, username='default', password='wrong') Database(self.database.db_name, username='default', password='wrong')
exc = cm.exception exc = cm.exception
print(exc.code, exc.message)
if exc.code == 193: # ClickHouse version < 20.3 if exc.code == 193: # ClickHouse version < 20.3
self.assertTrue(exc.message.startswith('Wrong password for user default')) self.assertTrue(exc.message.startswith('Wrong password for user default'))
elif exc.code == 516: # ClickHouse version >= 20.3 elif exc.code == 516: # ClickHouse version >= 20.3
self.assertTrue(exc.message.startswith('default: Authentication failed')) self.assertTrue(exc.message.startswith('default: Authentication failed'))
else: else:
raise Exception('Unexpected error code - %s' % exc.code) raise Exception('Unexpected error code - %s %s' % (exc.code, exc.message))
def test_nonexisting_db(self): def test_nonexisting_db(self):
db = Database('db_not_here', autocreate=False) db = Database('db_not_here', autocreate=False)
@ -251,6 +252,8 @@ class DatabaseTestCase(TestCaseWithData):
from infi.clickhouse_orm.models import ModelBase from infi.clickhouse_orm.models import ModelBase
query = "SELECT DISTINCT type FROM system.columns" query = "SELECT DISTINCT type FROM system.columns"
for row in self.database.select(query): for row in self.database.select(query):
if row.type.startswith('Map'):
continue # Not supported yet
ModelBase.create_ad_hoc_field(row.type) ModelBase.create_ad_hoc_field(row.type)
def test_get_model_for_table(self): def test_get_model_for_table(self):
@ -271,7 +274,12 @@ class DatabaseTestCase(TestCaseWithData):
query = "SELECT name FROM system.tables WHERE database='system'" query = "SELECT name FROM system.tables WHERE database='system'"
for row in self.database.select(query): for row in self.database.select(query):
print(row.name) print(row.name)
model = self.database.get_model_for_table(row.name, system_table=True) if row.name in ('distributed_ddl_queue',):
continue # Not supported
try:
model = self.database.get_model_for_table(row.name, system_table=True)
except NotImplementedError:
continue # Table contains an unsupported field type
self.assertTrue(model.is_system_model()) self.assertTrue(model.is_system_model())
self.assertTrue(model.is_read_only()) self.assertTrue(model.is_read_only())
self.assertEqual(model.table_name(), row.name) self.assertEqual(model.table_name(), row.name)

View File

@ -105,7 +105,7 @@ class HierarchicalDictionaryTest(DictionaryTestMixin, unittest.TestCase):
def test_dictgethierarchy(self): def test_dictgethierarchy(self):
self._test_func(F.dictGetHierarchy(self.dict_name, F.toUInt64(3)), [3, 2, 1]) self._test_func(F.dictGetHierarchy(self.dict_name, F.toUInt64(3)), [3, 2, 1])
self._test_func(F.dictGetHierarchy(self.dict_name, F.toUInt64(99)), [99]) self._test_func(F.dictGetHierarchy(self.dict_name, F.toUInt64(99)), [])
def test_dictisin(self): def test_dictisin(self):
self._test_func(F.dictIsIn(self.dict_name, F.toUInt64(3), F.toUInt64(1)), 1) self._test_func(F.dictIsIn(self.dict_name, F.toUInt64(3), F.toUInt64(1)), 1)

View File

@ -17,10 +17,10 @@ class _EnginesHelperTestCase(unittest.TestCase):
class EnginesTestCase(_EnginesHelperTestCase): class EnginesTestCase(_EnginesHelperTestCase):
def _create_and_insert(self, model_class): def _create_and_insert(self, model_class, **kwargs):
self.database.create_table(model_class) self.database.create_table(model_class)
self.database.insert([ self.database.insert([
model_class(date='2017-01-01', event_id=23423, event_group=13, event_count=7, event_version=1) model_class(date='2017-01-01', event_id=23423, event_group=13, event_count=7, event_version=1, **kwargs)
]) ])
def test_merge_tree(self): def test_merge_tree(self):
@ -155,7 +155,7 @@ class EnginesTestCase(_EnginesHelperTestCase):
) )
self._create_and_insert(TestModel) self._create_and_insert(TestModel)
self._create_and_insert(TestCollapseModel) self._create_and_insert(TestCollapseModel, sign=1)
# Result order may be different, lets sort manually # Result order may be different, lets sort manually
parts = sorted(list(SystemPart.get(self.database)), key=lambda x: x.table) parts = sorted(list(SystemPart.get(self.database)), key=lambda x: x.table)
@ -188,7 +188,7 @@ class EnginesTestCase(_EnginesHelperTestCase):
) )
self._create_and_insert(TestModel) self._create_and_insert(TestModel)
self._create_and_insert(TestCollapseModel) self._create_and_insert(TestCollapseModel, sign=1)
self.assertEqual(2, len(list(SystemPart.get(self.database)))) self.assertEqual(2, len(list(SystemPart.get(self.database))))