mirror of
				https://github.com/Infinidat/infi.clickhouse_orm.git
				synced 2025-11-04 01:37:34 +03:00 
			
		
		
		
	- Add log_statements parameter to database initializer
				
					
				
			- Fix test_merge which fails on ClickHouse v19.8.3
This commit is contained in:
		
							parent
							
								
									6a2509b96e
								
							
						
					
					
						commit
						9dd1a8f409
					
				| 
						 | 
					@ -11,6 +11,8 @@ Unreleased
 | 
				
			||||||
- Use HTTP Basic Authentication instead of passing the credentials in the URL
 | 
					- Use HTTP Basic Authentication instead of passing the credentials in the URL
 | 
				
			||||||
- Support default/alias/materialized for nullable fields
 | 
					- Support default/alias/materialized for nullable fields
 | 
				
			||||||
- Add UUIDField (kpotehin)
 | 
					- Add UUIDField (kpotehin)
 | 
				
			||||||
 | 
					- Add `log_statements` parameter to database initializer
 | 
				
			||||||
 | 
					- Fix test_merge which fails on ClickHouse v19.8.3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
v1.0.4
 | 
					v1.0.4
 | 
				
			||||||
------
 | 
					------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +83,7 @@ class Database(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, db_name, db_url='http://localhost:8123/',
 | 
					    def __init__(self, db_name, db_url='http://localhost:8123/',
 | 
				
			||||||
                 username=None, password=None, readonly=False, autocreate=True,
 | 
					                 username=None, password=None, readonly=False, autocreate=True,
 | 
				
			||||||
                 timeout=60, verify_ssl_cert=True):
 | 
					                 timeout=60, verify_ssl_cert=True, log_statements=False):
 | 
				
			||||||
        '''
 | 
					        '''
 | 
				
			||||||
        Initializes a database instance. Unless it's readonly, the database will be
 | 
					        Initializes a database instance. Unless it's readonly, the database will be
 | 
				
			||||||
        created on the ClickHouse server if it does not already exist.
 | 
					        created on the ClickHouse server if it does not already exist.
 | 
				
			||||||
| 
						 | 
					@ -96,6 +96,7 @@ class Database(object):
 | 
				
			||||||
        - `autocreate`: automatically create the database if it does not exist (unless in readonly mode).
 | 
					        - `autocreate`: automatically create the database if it does not exist (unless in readonly mode).
 | 
				
			||||||
        - `timeout`: the connection timeout in seconds.
 | 
					        - `timeout`: the connection timeout in seconds.
 | 
				
			||||||
        - `verify_ssl_cert`: whether to verify the server's certificate when connecting via HTTPS.
 | 
					        - `verify_ssl_cert`: whether to verify the server's certificate when connecting via HTTPS.
 | 
				
			||||||
 | 
					        - `log_statements`: when True, all database statements are logged.
 | 
				
			||||||
        '''
 | 
					        '''
 | 
				
			||||||
        self.db_name = db_name
 | 
					        self.db_name = db_name
 | 
				
			||||||
        self.db_url = db_url
 | 
					        self.db_url = db_url
 | 
				
			||||||
| 
						 | 
					@ -105,6 +106,7 @@ class Database(object):
 | 
				
			||||||
        self.request_session.verify = verify_ssl_cert
 | 
					        self.request_session.verify = verify_ssl_cert
 | 
				
			||||||
        if username:
 | 
					        if username:
 | 
				
			||||||
            self.request_session.auth = (username, password or '')
 | 
					            self.request_session.auth = (username, password or '')
 | 
				
			||||||
 | 
					        self.log_statements = log_statements
 | 
				
			||||||
        self.settings = {}
 | 
					        self.settings = {}
 | 
				
			||||||
        self.db_exists = False # this is required before running _is_existing_database
 | 
					        self.db_exists = False # this is required before running _is_existing_database
 | 
				
			||||||
        self.db_exists = self._is_existing_database()
 | 
					        self.db_exists = self._is_existing_database()
 | 
				
			||||||
| 
						 | 
					@ -334,6 +336,8 @@ class Database(object):
 | 
				
			||||||
    def _send(self, data, settings=None, stream=False):
 | 
					    def _send(self, data, settings=None, stream=False):
 | 
				
			||||||
        if isinstance(data, string_types):
 | 
					        if isinstance(data, string_types):
 | 
				
			||||||
            data = data.encode('utf-8')
 | 
					            data = data.encode('utf-8')
 | 
				
			||||||
 | 
					            if self.log_statements:
 | 
				
			||||||
 | 
					                logger.info(data)
 | 
				
			||||||
        params = self._build_params(settings)
 | 
					        params = self._build_params(settings)
 | 
				
			||||||
        r = self.request_session.post(self.db_url, params=params, data=data, stream=stream, timeout=self.timeout)
 | 
					        r = self.request_session.post(self.db_url, params=params, data=data, stream=stream, timeout=self.timeout)
 | 
				
			||||||
        if r.status_code != 200:
 | 
					        if r.status_code != 200:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -311,9 +311,16 @@ class MergeModel(Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def create_table_sql(cls, db):
 | 
					    def create_table_sql(cls, db):
 | 
				
			||||||
        assert isinstance(cls.engine, Merge), "engine must be engines.Merge instance"
 | 
					        assert isinstance(cls.engine, Merge), "engine must be an instance of engines.Merge"
 | 
				
			||||||
        return super(MergeModel, cls).create_table_sql(db)
 | 
					        parts = ['CREATE TABLE IF NOT EXISTS `%s`.`%s` (' % (db.db_name, cls.table_name())]
 | 
				
			||||||
 | 
					        cols = []
 | 
				
			||||||
 | 
					        for name, field in iteritems(cls.fields()):
 | 
				
			||||||
 | 
					            if name != '_table':
 | 
				
			||||||
 | 
					                cols.append('    %s %s' % (name, field.get_sql()))
 | 
				
			||||||
 | 
					        parts.append(',\n'.join(cols))
 | 
				
			||||||
 | 
					        parts.append(')')
 | 
				
			||||||
 | 
					        parts.append('ENGINE = ' + cls.engine.create_table_sql(db))
 | 
				
			||||||
 | 
					        return '\n'.join(parts)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# TODO: base class for models that require specific engine
 | 
					# TODO: base class for models that require specific engine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -324,7 +331,7 @@ class DistributedModel(Model):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def set_database(self, db):
 | 
					    def set_database(self, db):
 | 
				
			||||||
        assert isinstance(self.engine, Distributed), "engine must be engines.Distributed instance"
 | 
					        assert isinstance(self.engine, Distributed), "engine must be an instance of engines.Distributed"
 | 
				
			||||||
        res = super(DistributedModel, self).set_database(db)
 | 
					        res = super(DistributedModel, self).set_database(db)
 | 
				
			||||||
        return res
 | 
					        return res
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@ logging.getLogger("requests").setLevel(logging.WARNING)
 | 
				
			||||||
class TestCaseWithData(unittest.TestCase):
 | 
					class TestCaseWithData(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
        self.database.create_table(Person)
 | 
					        self.database.create_table(Person)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tearDown(self):
 | 
					    def tearDown(self):
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ class Person(Model):
 | 
				
			||||||
data = [
 | 
					data = [
 | 
				
			||||||
    {"first_name": "Abdul", "last_name": "Hester", "birthday": "1970-12-02", "height": "1.63",
 | 
					    {"first_name": "Abdul", "last_name": "Hester", "birthday": "1970-12-02", "height": "1.63",
 | 
				
			||||||
     "passport": 35052255},
 | 
					     "passport": 35052255},
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    {"first_name": "Adam", "last_name": "Goodman", "birthday": "1986-01-07", "height": "1.74",
 | 
					    {"first_name": "Adam", "last_name": "Goodman", "birthday": "1986-01-07", "height": "1.74",
 | 
				
			||||||
     "passport": 36052255},
 | 
					     "passport": 36052255},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ from infi.clickhouse_orm.engines import *
 | 
				
			||||||
class MaterializedFieldsTest(unittest.TestCase):
 | 
					class MaterializedFieldsTest(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
        self.database.create_table(ModelWithAliasFields)
 | 
					        self.database.create_table(ModelWithAliasFields)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tearDown(self):
 | 
					    def tearDown(self):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ from infi.clickhouse_orm.engines import *
 | 
				
			||||||
class ArrayFieldsTest(unittest.TestCase):
 | 
					class ArrayFieldsTest(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
        self.database.create_table(ModelWithArrays)
 | 
					        self.database.create_table(ModelWithArrays)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tearDown(self):
 | 
					    def tearDown(self):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ from infi.clickhouse_orm.engines import Memory
 | 
				
			||||||
class CustomFieldsTest(unittest.TestCase):
 | 
					class CustomFieldsTest(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tearDown(self):
 | 
					    def tearDown(self):
 | 
				
			||||||
        self.database.drop_database()
 | 
					        self.database.drop_database()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ from infi.clickhouse_orm.engines import *
 | 
				
			||||||
class DateFieldsTest(unittest.TestCase):
 | 
					class DateFieldsTest(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
        self.database.create_table(ModelWithDate)
 | 
					        self.database.create_table(ModelWithDate)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tearDown(self):
 | 
					    def tearDown(self):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ from infi.clickhouse_orm.engines import *
 | 
				
			||||||
class DecimalFieldsTest(unittest.TestCase):
 | 
					class DecimalFieldsTest(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
        self.database.add_setting('allow_experimental_decimal_type', 1)
 | 
					        self.database.add_setting('allow_experimental_decimal_type', 1)
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            self.database.create_table(DecimalModel)
 | 
					            self.database.create_table(DecimalModel)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@ logging.getLogger("requests").setLevel(logging.WARNING)
 | 
				
			||||||
class _EnginesHelperTestCase(unittest.TestCase):
 | 
					class _EnginesHelperTestCase(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tearDown(self):
 | 
					    def tearDown(self):
 | 
				
			||||||
        self.database.drop_database()
 | 
					        self.database.drop_database()
 | 
				
			||||||
| 
						 | 
					@ -115,8 +115,8 @@ class EnginesTestCase(_EnginesHelperTestCase):
 | 
				
			||||||
            TestModel2(date='2017-01-02', event_id=2, event_group=2, event_count=2, event_version=2)
 | 
					            TestModel2(date='2017-01-02', event_id=2, event_group=2, event_count=2, event_version=2)
 | 
				
			||||||
        ])
 | 
					        ])
 | 
				
			||||||
        # event_uversion is materialized field. So * won't select it and it will be zero
 | 
					        # event_uversion is materialized field. So * won't select it and it will be zero
 | 
				
			||||||
        res = self.database.select('SELECT *, event_uversion FROM $table ORDER BY event_id', model_class=TestMergeModel)
 | 
					        res = self.database.select('SELECT *, _table, event_uversion FROM $table ORDER BY event_id', model_class=TestMergeModel)
 | 
				
			||||||
        res = [row for row in res]
 | 
					        res = list(res)
 | 
				
			||||||
        self.assertEqual(2, len(res))
 | 
					        self.assertEqual(2, len(res))
 | 
				
			||||||
        self.assertDictEqual({
 | 
					        self.assertDictEqual({
 | 
				
			||||||
            '_table': 'testmodel1',
 | 
					            '_table': 'testmodel1',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ except NameError:
 | 
				
			||||||
class EnumFieldsTest(unittest.TestCase):
 | 
					class EnumFieldsTest(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
        self.database.create_table(ModelWithEnum)
 | 
					        self.database.create_table(ModelWithEnum)
 | 
				
			||||||
        self.database.create_table(ModelWithEnumArray)
 | 
					        self.database.create_table(ModelWithEnumArray)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ from infi.clickhouse_orm.engines import *
 | 
				
			||||||
class FixedStringFieldsTest(unittest.TestCase):
 | 
					class FixedStringFieldsTest(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
        self.database.create_table(FixedStringModel)
 | 
					        self.database.create_table(FixedStringModel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tearDown(self):
 | 
					    def tearDown(self):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ from infi.clickhouse_orm import database, engines, fields, models
 | 
				
			||||||
class JoinTest(unittest.TestCase):
 | 
					class JoinTest(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = database.Database('test-db')
 | 
					        self.database = database.Database('test-db', log_statements=True)
 | 
				
			||||||
        self.database.create_table(Foo)
 | 
					        self.database.create_table(Foo)
 | 
				
			||||||
        self.database.create_table(Bar)
 | 
					        self.database.create_table(Bar)
 | 
				
			||||||
        self.database.insert([Foo(id=i) for i in range(3)])
 | 
					        self.database.insert([Foo(id=i) for i in range(3)])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ from infi.clickhouse_orm.engines import *
 | 
				
			||||||
class MaterializedFieldsTest(unittest.TestCase):
 | 
					class MaterializedFieldsTest(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
        self.database.create_table(ModelWithMaterializedFields)
 | 
					        self.database.create_table(ModelWithMaterializedFields)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tearDown(self):
 | 
					    def tearDown(self):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@ logging.getLogger("requests").setLevel(logging.WARNING)
 | 
				
			||||||
class MigrationsTestCase(unittest.TestCase):
 | 
					class MigrationsTestCase(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
        self.database.drop_table(MigrationHistory)
 | 
					        self.database.drop_table(MigrationHistory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tearDown(self):
 | 
					    def tearDown(self):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@ from datetime import date, datetime
 | 
				
			||||||
class NullableFieldsTest(unittest.TestCase):
 | 
					class NullableFieldsTest(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
        self.database.create_table(ModelWithNullable)
 | 
					        self.database.create_table(ModelWithNullable)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tearDown(self):
 | 
					    def tearDown(self):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@ from infi.clickhouse_orm.system_models import SystemPart
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SystemTest(unittest.TestCase):
 | 
					class SystemTest(unittest.TestCase):
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tearDown(self):
 | 
					    def tearDown(self):
 | 
				
			||||||
        self.database.drop_database()
 | 
					        self.database.drop_database()
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@ class SystemPartTest(unittest.TestCase):
 | 
				
			||||||
    BACKUP_DIRS = ['/var/lib/clickhouse/shadow', '/opt/clickhouse/shadow/']
 | 
					    BACKUP_DIRS = ['/var/lib/clickhouse/shadow', '/opt/clickhouse/shadow/']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
        self.database.create_table(TestTable)
 | 
					        self.database.create_table(TestTable)
 | 
				
			||||||
        self.database.create_table(CustomPartitionedTable)
 | 
					        self.database.create_table(CustomPartitionedTable)
 | 
				
			||||||
        self.database.insert([TestTable(date_field=date.today())])
 | 
					        self.database.insert([TestTable(date_field=date.today())])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ from infi.clickhouse_orm.engines import Memory
 | 
				
			||||||
class UUIDFieldsTest(unittest.TestCase):
 | 
					class UUIDFieldsTest(unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setUp(self):
 | 
					    def setUp(self):
 | 
				
			||||||
        self.database = Database('test-db')
 | 
					        self.database = Database('test-db', log_statements=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tearDown(self):
 | 
					    def tearDown(self):
 | 
				
			||||||
        self.database.drop_database()
 | 
					        self.database.drop_database()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user