db-attribute 2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- db_attribute/__init__.py +320 -0
- db_attribute/connector.py +31 -0
- db_attribute/db_class.py +942 -0
- db_attribute/db_types.py +178 -0
- db_attribute/db_work.py +365 -0
- db_attribute/discriptor.py +176 -0
- db_attribute-2.1.dist-info/METADATA +398 -0
- db_attribute-2.1.dist-info/RECORD +11 -0
- db_attribute-2.1.dist-info/WHEEL +5 -0
- db_attribute-2.1.dist-info/licenses/LICENSE +21 -0
- db_attribute-2.1.dist-info/top_level.txt +1 -0
db_attribute/db_types.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import collections, json
|
|
2
|
+
|
|
3
|
+
import db_attribute
|
|
4
|
+
|
|
5
|
+
db_class = db_attribute.db_class
|
|
6
|
+
|
|
7
|
+
class _NotSetMetaClass(type):
|
|
8
|
+
def __repr__(cls):
|
|
9
|
+
return cls.__name__
|
|
10
|
+
|
|
11
|
+
class NotSet(metaclass=_NotSetMetaClass):
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
class MISSING(metaclass=_NotSetMetaClass):
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
class Id:
|
|
18
|
+
def __init__(self, Id: int, cls_name=None):
|
|
19
|
+
self.Id = Id
|
|
20
|
+
self.cls_name = cls_name
|
|
21
|
+
def __repr__(self):
|
|
22
|
+
return f'{self.cls_name}(id={self.Id})' if self.cls_name else f'Any(id={self.Id})'
|
|
23
|
+
|
|
24
|
+
class Ids:
|
|
25
|
+
def __init__(self, Ids=None, cls_name=None):
|
|
26
|
+
if Ids is None:
|
|
27
|
+
Ids = []
|
|
28
|
+
self.set_ids = set(Ids)
|
|
29
|
+
self.list_ids = sorted(list(self.set_ids))
|
|
30
|
+
self.cls_name = cls_name
|
|
31
|
+
for i in range(len(self.list_ids)):
|
|
32
|
+
if not isinstance(self.list_ids[i], Id):
|
|
33
|
+
self.list_ids[i] = Id(self.list_ids[i], cls_name=cls_name)
|
|
34
|
+
self.set_ids = set(self.list_ids)
|
|
35
|
+
def __len__(self):
|
|
36
|
+
return len(self.list_ids)
|
|
37
|
+
def __bool__(self):
|
|
38
|
+
return bool(self.list_ids)
|
|
39
|
+
def __iter__(self):
|
|
40
|
+
return iter(self.list_ids)
|
|
41
|
+
def __repr__(self):
|
|
42
|
+
return f'{self.cls_name if self.cls_name else "Ids"}({[i.Id for i in self.list_ids]})'
|
|
43
|
+
|
|
44
|
+
class JsonType:
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
class Factory:
|
|
48
|
+
def __init__(self, fabric):
|
|
49
|
+
self.fabric = fabric
|
|
50
|
+
def get_value(self):
|
|
51
|
+
return self.fabric()
|
|
52
|
+
def __call__(self):
|
|
53
|
+
return self.fabric()
|
|
54
|
+
def __repr__(self):
|
|
55
|
+
return 'FACTORY'
|
|
56
|
+
|
|
57
|
+
class DbField:
|
|
58
|
+
def __init__(self, default=MISSING, default_factory=MISSING, python_type=MISSING, mysql_type=MISSING, repr=True, init=True, **kwargs):
|
|
59
|
+
"""Attention! python_type takes precedence over the data type specified in the annotation"""
|
|
60
|
+
self.default = default
|
|
61
|
+
self.default_factory = MISSING if default_factory is MISSING else Factory(default_factory)
|
|
62
|
+
self.python_type = python_type
|
|
63
|
+
self.mysql_type = mysql_type
|
|
64
|
+
self.repr = repr
|
|
65
|
+
self.init = init
|
|
66
|
+
def __repr__(self):
|
|
67
|
+
return f'DbField({", ".join([f"{i} = {self.__dict__[i]}" for i in self.__dict__ if self.__dict__[i] is not MISSING])})'
|
|
68
|
+
|
|
69
|
+
def get_default(self):
|
|
70
|
+
if self.default is not MISSING:
|
|
71
|
+
return self.default
|
|
72
|
+
if self.default_factory is not MISSING:
|
|
73
|
+
return self.default_factory.get_value()
|
|
74
|
+
return MISSING
|
|
75
|
+
|
|
76
|
+
class TableType:
|
|
77
|
+
def __init__(self, name_cls):
|
|
78
|
+
self.name_cls = name_cls
|
|
79
|
+
def __repr__(self):
|
|
80
|
+
return f'temp type of {self.name_cls} class'
|
|
81
|
+
|
|
82
|
+
class TableObject:
|
|
83
|
+
def __init__(self, name_cls, args=None, kwargs=None):
|
|
84
|
+
self.name_cls = name_cls
|
|
85
|
+
self.args = [] if args is None else args
|
|
86
|
+
self.kwargs = dict() if kwargs is None else kwargs
|
|
87
|
+
def __repr__(self):
|
|
88
|
+
return f'temp type of {self.name_cls} class'
|
|
89
|
+
|
|
90
|
+
class DictClasses:
|
|
91
|
+
"""
|
|
92
|
+
DictClasses is used to store DbAttribute classes.
|
|
93
|
+
It replaces the TableType and TableObject classes, which use a string to define these classes.
|
|
94
|
+
Created DbContainer for classes (for saved in DbList, DbDict and other).
|
|
95
|
+
:argument data: main data store. Example: {'User': User, 'Book': Book}
|
|
96
|
+
"""
|
|
97
|
+
def __init__(self):
|
|
98
|
+
self.data = dict()
|
|
99
|
+
self.needdata = collections.defaultdict(set)
|
|
100
|
+
self.db_containers = dict()
|
|
101
|
+
|
|
102
|
+
def add(self, cls):
|
|
103
|
+
self.data[cls.__name__] = cls
|
|
104
|
+
self.db_containers[cls.__name__] = _created_db_class(cls)
|
|
105
|
+
for othercls in self.needdata.get(cls.__name__, []):
|
|
106
|
+
self.replace(othercls)
|
|
107
|
+
if cls.__name__ in self.needdata:
|
|
108
|
+
del self.needdata[cls.__name__]
|
|
109
|
+
self.replace(cls)
|
|
110
|
+
|
|
111
|
+
def replace(self, cls):
|
|
112
|
+
temp = cls.__db_fields__
|
|
113
|
+
for nameattr in temp:
|
|
114
|
+
if isinstance(temp[nameattr].python_type, TableType):
|
|
115
|
+
if temp[nameattr].python_type.name_cls in self.data:
|
|
116
|
+
temp[nameattr].python_type = self.data[temp[nameattr].python_type.name_cls]
|
|
117
|
+
else:
|
|
118
|
+
self.needdata[temp[nameattr].python_type.name_cls].add(cls)
|
|
119
|
+
value = temp[nameattr].get_default()
|
|
120
|
+
if isinstance(value, TableObject):
|
|
121
|
+
if value.name_cls in self.data:
|
|
122
|
+
now_need_cls = self.data[value.name_cls]
|
|
123
|
+
now_need_args = value.args
|
|
124
|
+
now_need_kwargs = value.kwargs
|
|
125
|
+
temp[nameattr].default = MISSING
|
|
126
|
+
temp[nameattr].default_factory = Factory(lambda: now_need_cls(*now_need_args, **now_need_kwargs))
|
|
127
|
+
else:
|
|
128
|
+
self.needdata[value.name_cls].add(cls)
|
|
129
|
+
|
|
130
|
+
def _created_db_class(cls):
|
|
131
|
+
@db_class.DbClassDecorator
|
|
132
|
+
class ContainerDbAttribute(db_class.DbClass, cls, need_DbAttributeMetaclass=False, __repr_class_name__=cls.__name__):
|
|
133
|
+
def __init__(self, id: int = NotSet, *args, _use_db=False, _convert_arguments=True, _obj_dbattribute=None, _name_attribute=None, _first_container=None, **kwargs):
|
|
134
|
+
super().__init__(*args, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container, _call_init=False, **kwargs)
|
|
135
|
+
object.__setattr__(self, 'id', id)
|
|
136
|
+
|
|
137
|
+
@classmethod
|
|
138
|
+
def __convert_to_db__(cls, obj: db_attribute.DbAttribute, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
|
|
139
|
+
if isinstance(obj, int):
|
|
140
|
+
Id = obj
|
|
141
|
+
else:
|
|
142
|
+
Id = obj.id
|
|
143
|
+
return cls(id=Id, _use_db=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
|
|
144
|
+
|
|
145
|
+
def dumps(self, _return_json=True):
|
|
146
|
+
if _return_json: return json.dumps({'t': f'ContainerDbAttribute_{cls.__name__}', 'i': self.id})
|
|
147
|
+
return {'t': f'ContainerDbAttribute_{cls.__name__}', 'i': self.id}
|
|
148
|
+
|
|
149
|
+
def copy(self):
|
|
150
|
+
return cls(id=self.id)
|
|
151
|
+
|
|
152
|
+
@classmethod
|
|
153
|
+
def _loads(cls, tempdata: dict, *, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
|
|
154
|
+
return cls(id=tempdata['i'], _use_db=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
|
|
155
|
+
|
|
156
|
+
ContainerDbAttribute.__name__ = f'ContainerDbAttribute_{cls.__name__}'
|
|
157
|
+
|
|
158
|
+
db_class.cheaker.add_db_class((cls, ContainerDbAttribute))
|
|
159
|
+
return ContainerDbAttribute
|
|
160
|
+
|
|
161
|
+
#dict_classes = DictClasses()
|
|
162
|
+
|
|
163
|
+
if __name__ == "__main__":
|
|
164
|
+
Field = DbField(default_factory=lambda:10)
|
|
165
|
+
print(Field.get_default())
|
|
166
|
+
"""
|
|
167
|
+
class A:
|
|
168
|
+
b: DbAttributeType('B')
|
|
169
|
+
print(A.__annotations__, f'{dict_classes.data=} {dict_classes.needdata=}')
|
|
170
|
+
dict_classes.add(A)
|
|
171
|
+
print(A.__annotations__, f'{dict_classes.data=} {dict_classes.needdata=}')
|
|
172
|
+
class B:
|
|
173
|
+
a: DbAttributeType('A')
|
|
174
|
+
print(A.__annotations__, B.__annotations__, f'{dict_classes.data=} {dict_classes.needdata=}')
|
|
175
|
+
dict_classes.add(B)
|
|
176
|
+
print(A.__annotations__, B.__annotations__, f'{dict_classes.data=} {dict_classes.needdata=}')
|
|
177
|
+
"""
|
|
178
|
+
|
db_attribute/db_work.py
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import json
|
|
3
|
+
import orjson
|
|
4
|
+
import collections
|
|
5
|
+
|
|
6
|
+
from mysql.connector import errorcode
|
|
7
|
+
|
|
8
|
+
import db_attribute.db_class as db_class
|
|
9
|
+
import db_attribute.db_types as dbtypes
|
|
10
|
+
import db_attribute
|
|
11
|
+
|
|
12
|
+
def get_default_value_from_type(attribute_type):
|
|
13
|
+
if attribute_type == str:
|
|
14
|
+
return {'status_code': 200, 'data': ''}
|
|
15
|
+
if attribute_type == int:
|
|
16
|
+
return {'status_code': 200, 'data': '0'}
|
|
17
|
+
if attribute_type == float:
|
|
18
|
+
return {'status_code': 200, 'data': '0.0'}
|
|
19
|
+
if attribute_type == bool:
|
|
20
|
+
return {'status_code': 200, 'data': 'False'}
|
|
21
|
+
if attribute_type is dbtypes.JsonType:
|
|
22
|
+
return {'status_code': 200, 'data': json.dumps(json.dumps(dict()))}
|
|
23
|
+
return {'status_code': 300}
|
|
24
|
+
|
|
25
|
+
def convert_attribute_type_to_mysql_type(attribute_type, len_varchar=50):
|
|
26
|
+
if attribute_type == str:
|
|
27
|
+
return {'status_code': 200, 'data': f'varchar({len_varchar})'}
|
|
28
|
+
if attribute_type == int or issubclass(attribute_type, db_attribute.DbAttribute):
|
|
29
|
+
return {'status_code': 200, 'data': f'bigint'}
|
|
30
|
+
if attribute_type == float or attribute_type == bool:
|
|
31
|
+
return {'status_code': 200, 'data': attribute_type.__name__.upper()}
|
|
32
|
+
if db_class.cheaker.this_db_attribute_support_class(attribute_type, this_is_cls=True) or db_class.cheaker.this_support_class(attribute_type, this_is_cls=True) or attribute_type is dbtypes.JsonType:
|
|
33
|
+
return {'status_code': 200, 'data': 'json'}
|
|
34
|
+
return {'status_code': 300}
|
|
35
|
+
|
|
36
|
+
def convert_attribute_value_to_mysql_value(attribute_value, attribute_type):
|
|
37
|
+
if attribute_type in (int, float, bool):
|
|
38
|
+
return {'status_code': 200, 'data': f'{attribute_value}'}
|
|
39
|
+
if attribute_type == str:
|
|
40
|
+
return {'status_code': 200, 'data': json.dumps(attribute_value, ensure_ascii=False)}
|
|
41
|
+
if attribute_type is dbtypes.JsonType:
|
|
42
|
+
return {'status_code': 200, 'data': json.dumps(json.dumps(attribute_value))}
|
|
43
|
+
if issubclass(attribute_type, db_attribute.discriptor.ConditionCore):
|
|
44
|
+
return {'status_code': 200, 'data': attribute_value._get_condition_repr()}
|
|
45
|
+
if issubclass(attribute_type, db_attribute.DbAttribute):
|
|
46
|
+
if type(attribute_value) is int:
|
|
47
|
+
return {'status_code': 200, 'data': f'{attribute_value}'}
|
|
48
|
+
return {'status_code': 200, 'data': f'{object.__getattribute__(attribute_value, 'id')}'}
|
|
49
|
+
if db_class.cheaker.this_db_attribute_support_class(attribute_type, this_is_cls=True) or db_class.cheaker.this_support_class(attribute_type, this_is_cls=True):
|
|
50
|
+
if db_class.cheaker.this_db_attribute_support_class(attribute_value):
|
|
51
|
+
return {'status_code': 200, 'data': f'CAST({json.dumps(attribute_value.dumps(), ensure_ascii=False)} AS JSON)'}
|
|
52
|
+
return {'status_code': 200, 'data': f'CAST({json.dumps(db_class.cheaker.create_db_class(attribute_value).dumps(), ensure_ascii=False)} AS JSON)'}
|
|
53
|
+
return {'status_code': 300}
|
|
54
|
+
|
|
55
|
+
def convert_mysql_value_to_attribute_value(mysql_value, attribute_type, _obj_dbattribute=None, attribute_name=None):
|
|
56
|
+
if attribute_type in (int, float, str):
|
|
57
|
+
return {'status_code': 200, 'data': mysql_value}
|
|
58
|
+
if attribute_type == bool:
|
|
59
|
+
return {'status_code': 200, 'data': True if mysql_value else False}
|
|
60
|
+
if attribute_type is dbtypes.JsonType:
|
|
61
|
+
return {'status_code': 200, 'data': orjson.loads(mysql_value)}
|
|
62
|
+
if issubclass(attribute_type, db_attribute.DbAttribute):
|
|
63
|
+
return {'status_code': 200, 'data': attribute_type.get(id=mysql_value)}
|
|
64
|
+
if db_class.cheaker.this_support_class(attribute_type, this_is_cls=True) or db_class.cheaker.this_db_attribute_support_class(attribute_type, this_is_cls=True):
|
|
65
|
+
return {'status_code': 200, 'data': db_class.DbClass.loads(mysql_value, _obj_dbattribute=_obj_dbattribute, _name_attribute=attribute_name)}
|
|
66
|
+
return {'status_code': 300}
|
|
67
|
+
|
|
68
|
+
def sql_decorator(func_d=None, /, standart_return=None):
|
|
69
|
+
def active_decorator(func):
|
|
70
|
+
@functools.wraps(func)
|
|
71
|
+
def method_wrapper(self, *args, **kwargs):
|
|
72
|
+
if self.connobj.notconn:
|
|
73
|
+
if standart_return:
|
|
74
|
+
return standart_return
|
|
75
|
+
return {'status_code': 100}
|
|
76
|
+
res = func(self, *args, **kwargs)
|
|
77
|
+
return res
|
|
78
|
+
return method_wrapper
|
|
79
|
+
if func_d is None:
|
|
80
|
+
return active_decorator
|
|
81
|
+
return active_decorator(func_d)
|
|
82
|
+
|
|
83
|
+
def get_table_name(class_name:str, attribute_name:str):
|
|
84
|
+
if ' ' in class_name:
|
|
85
|
+
raise Exception(f'The "{class_name}" class has the space (" ") in the name')
|
|
86
|
+
if ' ' in attribute_name:
|
|
87
|
+
raise Exception(f'The "{attribute_name}" attribute has the space (" ") in the name')
|
|
88
|
+
return f'cls {class_name} atr {attribute_name}'.lower()
|
|
89
|
+
|
|
90
|
+
def get_id_table_name(class_name:str):
|
|
91
|
+
return f'cls {class_name} ids'.lower()
|
|
92
|
+
|
|
93
|
+
def screening(name, db_name="MySQL"):
|
|
94
|
+
if db_name == "MySQL":
|
|
95
|
+
return f'`{name}`'
|
|
96
|
+
return f'"{name}"'
|
|
97
|
+
|
|
98
|
+
class Db_work:
|
|
99
|
+
def __init__(self, connobj, sittings_for_mysql_types=None):
|
|
100
|
+
"""
|
|
101
|
+
:param connobj: obj of connector.Connection
|
|
102
|
+
:param sittings_for_mysql_types: (at this moment not used) example: {str: 'VARCHAR(255)', int: 'BIGINT', bytes: 'BLOB'}
|
|
103
|
+
"""
|
|
104
|
+
self.connobj = connobj
|
|
105
|
+
self.sittings_for_mysql_types = {str: 'VARCHAR(255)', int: 'BIGINT', bytes: 'BLOB'}
|
|
106
|
+
if isinstance(sittings_for_mysql_types, dict):
|
|
107
|
+
self.sittings_for_mysql_types |= sittings_for_mysql_types
|
|
108
|
+
self.tables = self.get_tables_list()['data']
|
|
109
|
+
self.class_names = self.get_class_names_list()
|
|
110
|
+
|
|
111
|
+
def get_class_names_list(self):
|
|
112
|
+
Res = collections.defaultdict(list)
|
|
113
|
+
for i in self.tables:
|
|
114
|
+
try:
|
|
115
|
+
temp = i.split()
|
|
116
|
+
if temp[0] == 'cls' and temp[2] == 'atr':
|
|
117
|
+
Res[temp[1]].append(i)
|
|
118
|
+
except:
|
|
119
|
+
pass
|
|
120
|
+
return dict(Res)
|
|
121
|
+
|
|
122
|
+
@sql_decorator()
|
|
123
|
+
def get_tables_list(self):
|
|
124
|
+
self.connobj.cur.execute(f"""show tables""")
|
|
125
|
+
return {'status_code': 200, 'data': {i[0] for i in self.connobj.cur.fetchall()}}
|
|
126
|
+
|
|
127
|
+
@sql_decorator
|
|
128
|
+
def _create_table(self, table_name: str, attributes: list[tuple[str, str]]):
|
|
129
|
+
if table_name.lower() in self.tables:
|
|
130
|
+
return {'status_code': 301}
|
|
131
|
+
screening_table_name = screening(table_name, self.connobj.sql_name)
|
|
132
|
+
self.connobj.cur.execute(f"""CREATE TABLE {screening_table_name} (id BIGINT PRIMARY KEY AUTO_INCREMENT{', ' if attributes else ''}{', '.join((f'{attribute[0]} {attribute[1]}' for attribute in attributes))})""")
|
|
133
|
+
self.connobj.conn.commit()
|
|
134
|
+
self.tables = self.get_tables_list()['data']
|
|
135
|
+
self.class_names = self.get_class_names_list()
|
|
136
|
+
return {'status_code': 200}
|
|
137
|
+
|
|
138
|
+
@sql_decorator
|
|
139
|
+
def _create_id_table(self, table_name: str):
|
|
140
|
+
if table_name.lower() in self.tables:
|
|
141
|
+
return {'status_code': 301}
|
|
142
|
+
scr_table_name = screening(table_name, self.connobj.sql_name)
|
|
143
|
+
self.connobj.cur.execute(f"""CREATE TABLE {scr_table_name} (id BIGINT PRIMARY KEY AUTO_INCREMENT)""")
|
|
144
|
+
self.connobj.conn.commit()
|
|
145
|
+
self.tables = self.get_tables_list()['data']
|
|
146
|
+
self.class_names = self.get_class_names_list()
|
|
147
|
+
return {'status_code': 200}
|
|
148
|
+
|
|
149
|
+
@sql_decorator
|
|
150
|
+
def _deleate_table(self, table_name: str, ignore_302:bool=False):
|
|
151
|
+
if table_name.lower() not in self.tables:
|
|
152
|
+
if ignore_302:
|
|
153
|
+
return {'status_code': 200}
|
|
154
|
+
return {'status_code': 302}
|
|
155
|
+
scr_table_name = screening(table_name, self.connobj.sql_name)
|
|
156
|
+
self.connobj.cur.execute(f"""DROP TABLE {scr_table_name}""")
|
|
157
|
+
self.connobj.conn.commit()
|
|
158
|
+
self.tables = self.get_tables_list()['data']
|
|
159
|
+
self.class_names = self.get_class_names_list()
|
|
160
|
+
return {'status_code': 200}
|
|
161
|
+
|
|
162
|
+
@sql_decorator
|
|
163
|
+
def _get_type_data_table(self, table_name: str):
|
|
164
|
+
if table_name not in self.tables:
|
|
165
|
+
return {'status_code': 302}
|
|
166
|
+
self.connobj.cur.execute(f"""SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 'data' AND TABLE_SCHEMA = '{self.connobj.database}' AND TABLE_NAME = '{table_name}';""")
|
|
167
|
+
return {'status_code': 200, 'data': self.connobj.cur.fetchall()[-1][0]}
|
|
168
|
+
|
|
169
|
+
@sql_decorator
|
|
170
|
+
def _get_values_by_id(self, table_name:str, ID:int, operator:str= "=", ignore_302:bool=False):
|
|
171
|
+
if table_name not in self.tables:
|
|
172
|
+
if ignore_302:
|
|
173
|
+
return {'status_code': 200, 'data': []}
|
|
174
|
+
return {'status_code': 302}
|
|
175
|
+
scr_table_name = screening(table_name, self.connobj.sql_name)
|
|
176
|
+
self.connobj.cur.execute(f"""select * from {scr_table_name} where id {operator} {ID}""")
|
|
177
|
+
return {'status_code': 200, 'data': [i[-1] for i in self.connobj.cur.fetchall()]}
|
|
178
|
+
|
|
179
|
+
@sql_decorator
|
|
180
|
+
def _get_ids_by_value(self, table_name:str, value, operator:str= "=", ignore_302:bool=False):
|
|
181
|
+
if table_name not in self.tables:
|
|
182
|
+
if ignore_302:
|
|
183
|
+
return {'status_code': 200, 'data': []}
|
|
184
|
+
return {'status_code': 302}
|
|
185
|
+
scr_table_name = screening(table_name, self.connobj.sql_name)
|
|
186
|
+
self.connobj.cur.execute(f"""select id from {scr_table_name} where data {operator} {value}""")
|
|
187
|
+
return {'status_code': 200, 'data': {i[0] for i in self.connobj.cur.fetchall()}}
|
|
188
|
+
|
|
189
|
+
@sql_decorator
|
|
190
|
+
def _get_all_ids(self, table_name: str, ignore_302: bool = False):
|
|
191
|
+
if table_name not in self.tables:
|
|
192
|
+
if ignore_302:
|
|
193
|
+
return {'status_code': 200, 'data': []}
|
|
194
|
+
return {'status_code': 302}
|
|
195
|
+
scr_table_name = screening(table_name, self.connobj.sql_name)
|
|
196
|
+
self.connobj.cur.execute(f"""select id from {scr_table_name}""")
|
|
197
|
+
return {'status_code': 200, 'data': {i[0] for i in self.connobj.cur.fetchall()}}
|
|
198
|
+
|
|
199
|
+
@sql_decorator
|
|
200
|
+
def _get_ids_by_condition(self, class_name:str, condition:str, ignore_302:bool=False):
|
|
201
|
+
if class_name not in self.class_names:
|
|
202
|
+
if ignore_302:
|
|
203
|
+
return {'status_code': 200, 'data': []}
|
|
204
|
+
return {'status_code': 302}
|
|
205
|
+
id_table = get_id_table_name(class_name)
|
|
206
|
+
scr_id_table = screening(id_table, self.connobj.sql_name)
|
|
207
|
+
scr_id = screening('id', self.connobj.sql_name)
|
|
208
|
+
temp = [screening(i, self.connobj.sql_name) for i in self.class_names[class_name]]
|
|
209
|
+
self.connobj.cur.execute(f"""select {scr_id_table}.{scr_id} from {scr_id_table} {' '.join((f'left join {i} on {scr_id_table}.{scr_id} = {i}.{scr_id}' for i in temp))} where {condition}""")
|
|
210
|
+
return {'status_code': 200, 'data': {i[0] for i in self.connobj.cur.fetchall()}}
|
|
211
|
+
|
|
212
|
+
@sql_decorator
|
|
213
|
+
def _del_value_by_id(self, table_name:str, ID:int, ignore_302:bool=False):
|
|
214
|
+
if table_name not in self.tables:
|
|
215
|
+
if ignore_302:
|
|
216
|
+
return {'status_code': 200}
|
|
217
|
+
return {'status_code': 302}
|
|
218
|
+
scr_table_name = screening(table_name, self.connobj.sql_name)
|
|
219
|
+
self.connobj.cur.execute(f"""delete from {scr_table_name} where id={ID}""")
|
|
220
|
+
self.connobj.conn.commit()
|
|
221
|
+
return {'status_code': 200}
|
|
222
|
+
|
|
223
|
+
@sql_decorator
|
|
224
|
+
def _add_value_by_id(self, table_name:str, ID:int, value, ignore_302:bool=False):
|
|
225
|
+
try:
|
|
226
|
+
scr_table_name = screening(table_name, self.connobj.sql_name)
|
|
227
|
+
self.connobj.cur.execute(f"""insert ignore into {scr_table_name} (id, data) values ({ID}, {value}) on duplicate key update data=VALUES(data)""")
|
|
228
|
+
self.connobj.conn.commit()
|
|
229
|
+
except Exception as e:
|
|
230
|
+
if e.errno == errorcode.ER_NO_SUCH_TABLE:
|
|
231
|
+
return {'status_code': 200} if ignore_302 else {'status_code': 302}
|
|
232
|
+
raise e
|
|
233
|
+
return {'status_code': 200}
|
|
234
|
+
|
|
235
|
+
@sql_decorator
|
|
236
|
+
def _add_id(self, table_name:str, ID:int, ignore_302:bool=False):
|
|
237
|
+
try:
|
|
238
|
+
scr_table_name = screening(table_name, self.connobj.sql_name)
|
|
239
|
+
self.connobj.cur.execute(f"""insert into {scr_table_name} (id) values ({ID}) on duplicate key update id=VALUES(id)""")
|
|
240
|
+
self.connobj.conn.commit()
|
|
241
|
+
except Exception as e:
|
|
242
|
+
if e.errno == errorcode.ER_NO_SUCH_TABLE:
|
|
243
|
+
return {'status_code': 200} if ignore_302 else {'status_code': 302}
|
|
244
|
+
raise e
|
|
245
|
+
return {'status_code': 200}
|
|
246
|
+
|
|
247
|
+
@sql_decorator
|
|
248
|
+
def _get_new_id(self, table_name:str):
|
|
249
|
+
try:
|
|
250
|
+
scr_table_name = screening(table_name, self.connobj.sql_name)
|
|
251
|
+
self.connobj.cur.execute(f"INSERT INTO {scr_table_name} () VALUES ()")
|
|
252
|
+
next_id = self.connobj.cur.lastrowid
|
|
253
|
+
self.connobj.conn.commit()
|
|
254
|
+
except Exception as e:
|
|
255
|
+
if e.errno == errorcode.ER_NO_SUCH_TABLE:
|
|
256
|
+
return {'status_code': 302}
|
|
257
|
+
raise e
|
|
258
|
+
return {'status_code': 200, 'data': next_id}
|
|
259
|
+
|
|
260
|
+
def create_attribute_table(self, class_name: str, attribute_name: str, attribute_type=None, _cls_dbattribute=None, len_varchar:int=50):
|
|
261
|
+
"""
|
|
262
|
+
create attribute table
|
|
263
|
+
:param class_name: name of class attribute (obj.__class__.__name__)
|
|
264
|
+
:param attribute_name: name of attribute, example: 'name', 'id', 'nickname', 'password_hash'
|
|
265
|
+
:param attribute_type: type of attribute (type(obj)), example: str, DbList, int, bool, DbSet, dbtypes.JsonType (for create DbList, DbSet use db_class.cheaker.create_one_db_class)
|
|
266
|
+
:param _cls_dbattribute: db_attribute cls, used if attribute_type is None
|
|
267
|
+
:param len_varchar: len for string attributes, example: with len_varchar=5, attribute name='VeryLongName' convert to 'VeryL'
|
|
268
|
+
:return: {'status_code': 300 | 200 | 100} (for 'status_code' read in connector)
|
|
269
|
+
"""
|
|
270
|
+
table_name = get_table_name(class_name=class_name, attribute_name=attribute_name)
|
|
271
|
+
if attribute_type is None:
|
|
272
|
+
attribute_type = object.__getattribute__(_cls_dbattribute, '__db_fields__')[attribute_name].python_type
|
|
273
|
+
temp_data = convert_attribute_type_to_mysql_type(attribute_type=attribute_type, len_varchar=len_varchar)
|
|
274
|
+
if temp_data['status_code'] != 200: return temp_data
|
|
275
|
+
attribute_table_type = temp_data['data']
|
|
276
|
+
temp_data = self._create_table(table_name=table_name, attributes=[('data', attribute_table_type)])
|
|
277
|
+
if temp_data['status_code'] != 200: return temp_data
|
|
278
|
+
return {'status_code': 200}
|
|
279
|
+
|
|
280
|
+
def create_id_table(self, class_name: str):
|
|
281
|
+
return self._create_id_table(get_id_table_name(class_name=class_name))
|
|
282
|
+
|
|
283
|
+
def add_attribute_value(self, class_name: str, attribute_name: str, ID:int, data, attribute_type=None, _cls_dbattribute=None, ignore_302:bool=False):
|
|
284
|
+
if attribute_type is None:
|
|
285
|
+
attribute_type = object.__getattribute__(_cls_dbattribute, '__db_fields__')[attribute_name].python_type
|
|
286
|
+
temp_data = convert_attribute_value_to_mysql_value(data, attribute_type=attribute_type)
|
|
287
|
+
if temp_data['status_code'] != 200: return temp_data
|
|
288
|
+
value = temp_data['data']
|
|
289
|
+
table_name = get_table_name(class_name=class_name, attribute_name=attribute_name)
|
|
290
|
+
return self._add_value_by_id(table_name=table_name, ID=ID, value=value, ignore_302=ignore_302)
|
|
291
|
+
|
|
292
|
+
def add_id(self, class_name: str, ID:int, ignore_302:bool=False):
|
|
293
|
+
return self._add_id(table_name=get_id_table_name(class_name), ID=ID, ignore_302=ignore_302)
|
|
294
|
+
|
|
295
|
+
def get_new_id(self, class_name: str):
|
|
296
|
+
return self._get_new_id(table_name=get_id_table_name(class_name))
|
|
297
|
+
|
|
298
|
+
def get_attribute_value(self, class_name: str, attribute_name: str, ID:int, attribute_type=None, _obj_dbattribute=None):
|
|
299
|
+
table_name = get_table_name(class_name=class_name, attribute_name=attribute_name)
|
|
300
|
+
temp_data = self._get_values_by_id(table_name=table_name, ID=ID)
|
|
301
|
+
if temp_data['status_code'] != 200: return temp_data
|
|
302
|
+
if len(temp_data['data']) == 0: return {'status_code': 304}
|
|
303
|
+
value = temp_data['data'][0]
|
|
304
|
+
if attribute_type is None:
|
|
305
|
+
attribute_type = object.__getattribute__(_obj_dbattribute, '__db_fields__')[attribute_name].python_type
|
|
306
|
+
return convert_mysql_value_to_attribute_value(value, attribute_type=attribute_type, _obj_dbattribute=_obj_dbattribute, attribute_name=attribute_name)
|
|
307
|
+
|
|
308
|
+
def get_all_ids(self, class_name: str, ignore_302:bool=False):
|
|
309
|
+
return self._get_all_ids(table_name=get_id_table_name(class_name=class_name), ignore_302=ignore_302)
|
|
310
|
+
|
|
311
|
+
def del_attribute_value(self, class_name: str, attribute_name: str, ID:int, ignore_302:bool=False):
|
|
312
|
+
table_name = get_table_name(class_name=class_name, attribute_name=attribute_name)
|
|
313
|
+
return self._del_value_by_id(table_name=table_name, ID=ID, ignore_302=ignore_302)
|
|
314
|
+
|
|
315
|
+
def found_ids_by_value(self, class_name: str, attribute_name: str, data, attribute_type=None, _cls_dbattribute=None, operator: str="=", ignore_302:bool=False):
|
|
316
|
+
"""
|
|
317
|
+
:param class_name: ex: 'User'
|
|
318
|
+
:param attribute_name: ex: 'name'/'age'
|
|
319
|
+
:param data: any data, ex: 10 / {3, 5, 6} / 'Bob'
|
|
320
|
+
:param attribute_type: ex: int, bool, list, User (Db attribute type)
|
|
321
|
+
:param _cls_dbattribute: User
|
|
322
|
+
:param operator: '=' / '!=' / '<>' / '<' / '>' / '>=' / '<=' / 'Like'
|
|
323
|
+
:param ignore_302: bool, if true, ignore 302 error, return 200 and empty data
|
|
324
|
+
:return: set of id's
|
|
325
|
+
"""
|
|
326
|
+
if attribute_type is None:
|
|
327
|
+
attribute_type = object.__getattribute__(_cls_dbattribute, '__db_fields__')[attribute_name].python_type
|
|
328
|
+
temp_data = convert_attribute_value_to_mysql_value(data, attribute_type=attribute_type)
|
|
329
|
+
if temp_data['status_code'] != 200: return temp_data
|
|
330
|
+
value = temp_data['data']
|
|
331
|
+
table_name = get_table_name(class_name=class_name, attribute_name=attribute_name)
|
|
332
|
+
return self._get_ids_by_value(table_name=table_name, value=value, operator=operator, ignore_302=ignore_302)
|
|
333
|
+
|
|
334
|
+
def found_ids_by_condition(self, class_name: str, condition: str, ignore_302:bool=False):
|
|
335
|
+
return self._get_ids_by_condition(class_name=class_name.lower(), condition=condition, ignore_302=ignore_302)
|
|
336
|
+
|
|
337
|
+
def cheak_exists_attribute_table(self, class_name: str, attribute_name: str):
|
|
338
|
+
return get_table_name(class_name, attribute_name) in self.tables
|
|
339
|
+
|
|
340
|
+
def cheak_exists_id_table(self, class_name: str):
|
|
341
|
+
return get_id_table_name(class_name) in self.tables
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
if __name__ == '__main__':
|
|
345
|
+
from config import host, user, password, database
|
|
346
|
+
import connector
|
|
347
|
+
|
|
348
|
+
connect_obj = connector.Connection(host=host, user=user, password=password, database=database)
|
|
349
|
+
db_work_obj = Db_work(connect_obj)
|
|
350
|
+
#print(db_work_obj.class_names)
|
|
351
|
+
#print(db_work_obj.tables)
|
|
352
|
+
#db_work_obj.create_attribute_table('User', 'name', str)
|
|
353
|
+
#db_work_obj.add_attribute_value('User', 'name', 10, 'Bob', str)
|
|
354
|
+
#print(db_work_obj.get_attribute_value('User', 'name', 10, str))
|
|
355
|
+
print(db_work_obj.tables)
|
|
356
|
+
print(db_work_obj.class_names)
|
|
357
|
+
#db_work_obj._deleate_table('cls dbattributemetaclass ids')
|
|
358
|
+
#for i in db_work_obj.tables:
|
|
359
|
+
# db_work_obj._deleate_table(i)
|
|
360
|
+
# print(i)
|
|
361
|
+
|
|
362
|
+
#db_work_obj.deleate_table('cls_a_atr_b_obj')
|
|
363
|
+
|
|
364
|
+
#db_work_obj.update_value_by_id(table_name='cls_user_atr_age', ID=12, value=10, cheak_exists_value=False)
|
|
365
|
+
|