mirror of
https://github.com/Infinidat/infi.clickhouse_orm.git
synced 2025-02-22 11:12:46 +03:00
1) Replaced is_insertable() field mehtod with readonly property (unification with model and tables)
2) Method SystemPart.all() was replaced with get() 3) Added conditions parameter to SystemPart.get() and SystemPart.get_active() methods.
This commit is contained in:
parent
58b7a9aeac
commit
5f2195f87f
23
README.rst
23
README.rst
|
@ -182,6 +182,29 @@ You can optionally pass conditions to the query::
|
||||||
Note that ``order_by`` must be chosen so that the ordering is unique, otherwise there might be
|
Note that ``order_by`` must be chosen so that the ordering is unique, otherwise there might be
|
||||||
inconsistencies in the pagination (such as an instance that appears on two different pages).
|
inconsistencies in the pagination (such as an instance that appears on two different pages).
|
||||||
|
|
||||||
|
System models
|
||||||
|
-------------
|
||||||
|
`Clickhouse docs <https://clickhouse.yandex/reference_en.html#System tables>`
|
||||||
|
System models are read only models for implementing part of the system's functionality,
|
||||||
|
and for providing access to information about how the system is working.
|
||||||
|
|
||||||
|
Usage example:
|
||||||
|
|
||||||
|
>>>> from infi.clickhouse_orm import system_models
|
||||||
|
>>>> print(system_models.SystemPart.all())
|
||||||
|
|
||||||
|
Currently the fllowing system models are supported:
|
||||||
|
|
||||||
|
=================== ======== ================= ===================================================
|
||||||
|
Class DB Table Pythonic Type Comments
|
||||||
|
=================== ======== ================= ===================================================
|
||||||
|
SystemPart
|
||||||
|
|
||||||
|
Partitions and parts
|
||||||
|
--------------------
|
||||||
|
`ClickHouse docs <https://clickhouse.yandex/reference_en.html#Manipulations with partitions and parts>`
|
||||||
|
|
||||||
|
|
||||||
Schema Migrations
|
Schema Migrations
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
|
|
@ -70,8 +70,9 @@ class Field(object):
|
||||||
else:
|
else:
|
||||||
return self.db_type
|
return self.db_type
|
||||||
|
|
||||||
def is_insertable(self):
|
@property
|
||||||
return self.alias is None and self.materialized is None
|
def readonly(self):
|
||||||
|
return self.alias is not None or self.materialized is not None
|
||||||
|
|
||||||
|
|
||||||
class StringField(Field):
|
class StringField(Field):
|
||||||
|
|
|
@ -159,9 +159,8 @@ class Model(with_metaclass(ModelBase)):
|
||||||
:param bool insertable_only: If True, returns only fields, that can be inserted into database
|
:param bool insertable_only: If True, returns only fields, that can be inserted into database
|
||||||
'''
|
'''
|
||||||
data = self.__dict__
|
data = self.__dict__
|
||||||
fields = self._fields
|
|
||||||
if insertable_only:
|
fields = [f for f in self._fields if not f[1].readonly] if insertable_only else self._fields
|
||||||
fields = [f for f in fields if f[1].is_insertable()]
|
|
||||||
return '\t'.join(field.to_db_string(data[name], quote=False) for name, field in fields)
|
return '\t'.join(field.to_db_string(data[name], quote=False) for name, field in fields)
|
||||||
|
|
||||||
def to_dict(self, insertable_only=False, field_names=None):
|
def to_dict(self, insertable_only=False, field_names=None):
|
||||||
|
@ -170,7 +169,7 @@ class Model(with_metaclass(ModelBase)):
|
||||||
:param bool insertable_only: If True, returns only fields, that can be inserted into database
|
:param bool insertable_only: If True, returns only fields, that can be inserted into database
|
||||||
:param field_names: An iterable of field names to return
|
:param field_names: An iterable of field names to return
|
||||||
'''
|
'''
|
||||||
fields = [f for f in self._fields if f[1].is_insertable()] if insertable_only else self._fields
|
fields = [f for f in self._fields if not f[1].readonly] if insertable_only else self._fields
|
||||||
if field_names is not None:
|
if field_names is not None:
|
||||||
fields = [f for f in fields if f[0] in field_names]
|
fields = [f for f in fields if f[0] in field_names]
|
||||||
|
|
||||||
|
|
|
@ -113,25 +113,30 @@ class SystemPart(Model):
|
||||||
return self._partition_operation_sql(database, 'FETCH', settings=settings, from_part=zookeeper_path)
|
return self._partition_operation_sql(database, 'FETCH', settings=settings, from_part=zookeeper_path)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_active(cls, database):
|
def get(cls, database, conditions=""):
|
||||||
"""
|
"""
|
||||||
Get all active parts
|
Get all data from system.parts table
|
||||||
:param database: A database object to fetch data from.
|
:param database: A database object to fetch data from.
|
||||||
|
:param conditions: WHERE clause conditions. Database condition is added automatically
|
||||||
:return: A list of SystemPart objects
|
:return: A list of SystemPart objects
|
||||||
"""
|
"""
|
||||||
assert isinstance(database, Database), "database must be database.Database class instance"
|
assert isinstance(database, Database), "database must be database.Database class instance"
|
||||||
|
assert isinstance(conditions, str), "conditions must be a string"
|
||||||
|
if conditions:
|
||||||
|
conditions += " AND"
|
||||||
field_names = ','.join([f[0] for f in cls._fields])
|
field_names = ','.join([f[0] for f in cls._fields])
|
||||||
return database.select("SELECT %s FROM %s WHERE active AND database='%s'" %
|
return database.select("SELECT %s FROM %s WHERE %s database='%s'" %
|
||||||
(field_names, cls.table_name(), database.db_name), model_class=cls)
|
(field_names, cls.table_name(), conditions, database.db_name), model_class=cls)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def all(cls, database):
|
def get_active(cls, database, conditions=""):
|
||||||
"""
|
"""
|
||||||
Gets all data from system.parts database
|
Gets active data from system.parts table
|
||||||
:param database:
|
:param database: A database object to fetch data from.
|
||||||
:return:
|
:param conditions: WHERE clause conditions. Database and active conditions are added automatically
|
||||||
|
:return: A list of SystemPart objects
|
||||||
"""
|
"""
|
||||||
assert isinstance(database, Database), "database must be database.Database class instance"
|
if conditions:
|
||||||
field_names = ','.join([f[0] for f in cls._fields])
|
conditions += ' AND '
|
||||||
return database.select("SELECT %s FROM %s WHERE database='%s'" %
|
conditions += 'active'
|
||||||
(field_names, cls.table_name(), database.db_name), model_class=cls)
|
return SystemPart.get(database, conditions=conditions)
|
||||||
|
|
|
@ -26,7 +26,7 @@ class SystemPartTest(unittest.TestCase):
|
||||||
return dirnames
|
return dirnames
|
||||||
|
|
||||||
def test_get_all(self):
|
def test_get_all(self):
|
||||||
parts = SystemPart.all(self.database)
|
parts = SystemPart.get(self.database)
|
||||||
self.assertEqual(len(list(parts)), 1)
|
self.assertEqual(len(list(parts)), 1)
|
||||||
|
|
||||||
def test_get_active(self):
|
def test_get_active(self):
|
||||||
|
@ -35,6 +35,12 @@ class SystemPartTest(unittest.TestCase):
|
||||||
parts[0].detach(self.database)
|
parts[0].detach(self.database)
|
||||||
self.assertEqual(len(list(SystemPart.get_active(self.database))), 0)
|
self.assertEqual(len(list(SystemPart.get_active(self.database))), 0)
|
||||||
|
|
||||||
|
def test_get_conditions(self):
|
||||||
|
parts = list(SystemPart.get(self.database, conditions="table='testtable'"))
|
||||||
|
self.assertEqual(len(parts), 1)
|
||||||
|
parts = list(SystemPart.get(self.database, conditions="table='othertable'"))
|
||||||
|
self.assertEqual(len(parts), 0)
|
||||||
|
|
||||||
def test_attach_detach(self):
|
def test_attach_detach(self):
|
||||||
parts = list(SystemPart.get_active(self.database))
|
parts = list(SystemPart.get_active(self.database))
|
||||||
self.assertEqual(len(parts), 1)
|
self.assertEqual(len(parts), 1)
|
||||||
|
@ -49,7 +55,7 @@ class SystemPartTest(unittest.TestCase):
|
||||||
self.assertEqual(len(list(SystemPart.get_active(self.database))), 0)
|
self.assertEqual(len(list(SystemPart.get_active(self.database))), 0)
|
||||||
|
|
||||||
def test_freeze(self):
|
def test_freeze(self):
|
||||||
parts = list(SystemPart.all(self.database))
|
parts = list(SystemPart.get(self.database))
|
||||||
# There can be other backups in the folder
|
# There can be other backups in the folder
|
||||||
prev_backups = set(self._get_backups())
|
prev_backups = set(self._get_backups())
|
||||||
parts[0].freeze(self.database)
|
parts[0].freeze(self.database)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user