Aestate
orm.py
Go to the documentation of this file.
1 from enum import Enum
2 from typing import List
3 
4 from aestate.exception import SqlResultError
5 from aestate.util.Log import ALog
6 from prettytable import PrettyTable
7 
8 from aestate.work.Serialize import QuerySet
9 
10 
11 class BaseCover:
12 
13  def table_visual(self, title: list, val: List[dict]) -> PrettyTable:
14  if not val:
15  ALog.log_error(
16  msg='The database gets no return from the SQL of the field type in the table,'
17  ' and the SQL is written incorrectly, please check the SQL',
18  obj=SqlResultError, raise_exception=True)
19 
20  table = PrettyTable(title)
21  table.border = True
22  [table.add_row(list(i.values())) for i in val]
23  return table
24 
25  def check(self, res, fields) -> bool:
26  """
27  检查表与数据库中的数据是否对应
28  """
29  comment = {
30  'auto_increment': "自增",
31  'DEFAULT_GENERATED': "自动追加日期",
32  'DEFAULT_GENERATED on update CURRENT_TIMESTAMP': "自动更新时间为最后一次更改时间"
33  }
34  return False
35 
36  def deal(self, res, fields):
37  """
38  同步数据库与pojo的字段配置项
39  """
40  return True
41 
42  def res(self, tb_name, db_name, extool) -> dict:
43  """
44  获得表结构
45  """
46  sql = """SELECT
47  COLUMN_NAME AS name, -- 名称
48  DATA_TYPE AS typer, -- 类型
49  CHARACTER_MAXIMUM_LENGTH AS length, -- 长度
50  NUMERIC_SCALE AS num_scale, -- 数字小数点
51  IS_NULLABLE AS is_null, -- 是否允许为空
52  COLUMN_KEY AS c_key, -- 是否为键
53  EXTRA as def_val, -- 默认值
54  COLUMN_COMMENT as comment -- 描述
55  FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s"""
56  # 使用传入的sql执行器执行查询表结构的sql
57  res = extool.select(sql=sql, params=[db_name, tb_name])
58  # 获得表结构可视化
59  # table = self.table_visual(list(res[0].keys()), res)
60  # print(table)
61 
62  # 对比结构
63 
64  return res
65 
66 
67 class AOrm(object):
68  """
69  纯净的ORM模式:
70  你可以使用find('table').by('args').order_by('args').desc().end()方式执行sql
71  好处就是:
72  能更好的拒绝sql注入
73  无需写sql语句
74  代码简单易懂
75  上手快
76  """
77 
78  class Mode(Enum):
79  FIND = 0
80  INSERT = 1
81 
82  def __init__(self, repository):
83  """
84  初始化ORM
85 
86 
87  自定义方言除了可使用默认已存在的方法,还可以使用自定义sql方言拼接
88 
89  :param repository:仓库
90 s """
91  self.exmode = None
92  self.args = []
93  self.params = []
94  self.sqlFields = None
95  # self.sqlFields = sqlFields
96  self.ParseUtil = repository.config_obj
97  self.serializer = repository.serializer
98  self.sqlFields = repository.sqlFields
99  # 创建sql语法
100  if repository is None:
101  ALog.log_error(
102  msg='Repository is null,Place use repository of ORM framework',
103  obj=AttributeError, LogObject=self.repository.log_obj, raise_exception=True)
104  self.repository = repository
105  # self.__table_name__ = '{}{}{}'.format(self.sqlFields.left_subscript, repository.__table_name__,
106  # self.sqlFields.right_subscript)
107  self.__table_name__ = repository.__table_name__
108 
109  self.first_data = False
110  self._result = []
111 
112  def top(self):
113  self.find()
114  self.first_data = True
115  return self.limit(1)
116 
117  def first(self):
118  """
119  是否只返回第一行数据
120  """
121  self.first_data = True
122  return self
123 
124  # ------------------------主键--------------------------
125  def find(self, *args, **kwargs):
126  """
127 
128  example:
129  find('all')
130  find('param1',asses=['p'],h_func=True)
131  Attributes:
132  asses:将对应的字段转成另一个别名,不需要转换的使用None标识
133  h_func:不将字段转换成 `%s` 格式
134  更新:
135  如果args字段长度为0,默认为查找全部
136  """
137  self.exmode = AOrm.Mode.FIND
138  self.args.append(self.sqlFields.find_str)
139  # 如果有as字段
140  alias = None
141  if 'alias' in kwargs.keys():
142  alias = kwargs['alias']
143  # 如果包含方法的字段,则不加密
144  func_flag = False
145  if 'h_func' in kwargs.keys():
146  func_flag = kwargs['h_func']
147  # 1.1.0.05更新,默认为all
148  _all = False
149  if len(args) == 0:
150  _all = True
151  # 如果存在all
152  # 1.1.1.2修复:tuple index out of range
153  if _all or 'all'.upper() == args[0].upper():
154  # 如果包含all关键字,则使用解析工具解析成字段参数
155  if not func_flag:
156  fields = self.ParseUtil.parse_key(
157  *self.repository.fields, is_field=True)
158  else:
159  fields = self.ParseUtil.parse_key(
160  *self.repository.fields, is_field=False)
161  else:
162  if not func_flag:
163  fields = self.ParseUtil.parse_key(*args, is_field=True)
164  else:
165  fields = self.ParseUtil.parse_key(*args, is_field=False)
166  # 解决as问题
167  if alias is not None:
168  fs = fields.split(',')
169  if len(fs) != len(alias):
170  # 匿名参数长度与字段长度不符合
171  ALog.log_error(obj=TypeError,
172  msg='The length of the anonymous parameter does not match the length of the field',
173  raise_exception=True)
174  for i, v in enumerate(fs):
175  if alias[i] is not None:
176  self.args.append('{}{}{}'.format(
177  v, self.sqlFields.asses_str, alias[i]))
178  else:
179  self.args.append(v)
180  # 逗号
181  self.args.append(self.sqlFields.comma)
182  else:
183  self.args.append(fields)
184  if alias is not None:
185  # 去掉末尾的逗号
186  self.rep_sym()
187  # 加上from关键字
188  if 'poly' not in kwargs.keys():
189  self.con_from()
190  else:
191  self.args += kwargs['poly']
192  return self
193 
194  def order_by(self, *args, **kwargs):
195  """
196  根据什么查
197  example:
198  find('all').order_by('param')
199  find('all').order_by('param').end()
200  find('all').order_by('p1','p2').desc().limit(10,20)
201  """
202  return self.by_opera(field=self.sqlFields.order_by_str, args_list=args, **kwargs)
203 
204  def group_by(self, *args, **kwargs):
205  """
206  聚合函数
207  example:
208  select shop_id,count(*) as count from comments group by shop_id having count>1;
209  """
210  return self.by_opera(field=self.sqlFields.group_by_str, args_list=args, **kwargs)
211 
212  def by_opera(self, field, args_list, **kwargs):
213  """
214  根据什么查
215  """
216  self.args.append(field)
217  for i in args_list:
218  if not kwargs.get('text', False):
219  self.args.append(self.sqlFields.left_subscript)
220  self.args.append(i)
221  if not kwargs.get('text', False):
222  self.args.append(self.sqlFields.right_subscript)
223  self.args.append(self.sqlFields.comma)
224  self.rep_sym(self.sqlFields.comma, self.sqlFields.space)
225  return self
226 
227  def filter(self, **kwargs):
228  return self.find().where(**kwargs).end()
229 
230  def where(self, **kwargs):
231  """
232  当....
233  example:
234  find('ALL').where(param='%s') - 默认符号为等于 ==
235  find('ALL').where(param='==%s')
236  find('ALL').where(param='>%d')
237  find('ALL').where(param='<%d')
238  find('ALL').where(param='<=%d')
239  find('ALL').where(param='>=%.2f')
240  find('ALL').where(param='!=%.2f')
241  复杂语法:
242  find('ALL').where(param='+%d/%d==%d')
243  find('ALL').where(param='-%.2f*%d==12')
244  find('ALL').where(param='*10-1==12')
245  find('ALL').where(param='/10+1==12')
246  """
247  self.args.append(self.sqlFields.where_str)
248  for key, value in kwargs.items():
249  cp_key = key
250  customize = False
251  sym = '='
252 
253  sps = cp_key.split('__')
254 
255  if len(str(value)) > 2 and str(value)[0:2] in self.sqlFields.symbol:
256  sym = value[0:2]
257  value = str(value)[2:len(str(value))]
258  if sym == '==':
259  sym = '='
260  elif sym == '>>':
261  sym = '>'
262  elif sym == '<<':
263  sym = '<'
264  else:
265  # 没有找到符号的话就从字段名开始
266  # 截取最后一段从两段下划线开始的末尾
267  if not len(sps) == 1:
268  customize = True
269  sym = sps[len(sps) - 1]
270  self.ParseUtil.fieldExist(
271  self.ParseUtil, 'adapter', raise_exception=True)
272  cp_key = cp_key[:cp_key.rfind('__' + sym)]
273  self.ParseUtil.adapter.funcs[sym](self, cp_key, value)
274 
275  elif not len(sps) == 1:
276  customize = True
277  sym = sps[len(sps) - 1]
278  self.ParseUtil.fieldExist(
279  self.ParseUtil, 'adapter', raise_exception=True)
280  cp_key = cp_key[:cp_key.rfind('__' + sym)]
281  self.ParseUtil.adapter.funcs[sym](self, cp_key, value)
282 
283  if not customize:
284  self.args.append(
285  '{}{}{}{}%s'.format(self.sqlFields.left_subscript,
286  cp_key,
287  self.sqlFields.right_subscript,
288  sym))
289  self.args.append(self.sqlFields.ander_str)
290  self.params.append(value)
291  self.rep_sym(self.sqlFields.ander_str)
292 
293  return self
294 
295  def on(self, from_where, to_where, symbol='='):
296  self.args.append(self.sqlFields.space)
297  self.args.append(self.sqlFields.on_str)
298  self.args.append(self.sqlFields.space)
299  self.args.append(from_where)
300  self.args.append(self.sqlFields.space)
301  self.args.append(symbol)
302  self.args.append(self.sqlFields.space)
303  self.args.append(to_where)
304  return self
305 
306  def limit(self, start=0, end=None):
307  """
308  分页
309  :param start:开始
310  :param end:末尾
311  example:
312  find('all').limit(start=10,end=20)
313  find('all').limit(end=10)
314  """
315  self.args.append(self.sqlFields.limit_str)
316  # 死亡空格
317  if end is None:
318  limit_param = '{}{}{}'.format(
319  self.sqlFields.space, start, self.sqlFields.space)
320  else:
321  limit_param = '{}{}{}{}{}'.format(self.sqlFields.space, start, self.sqlFields.comma, end,
322  self.sqlFields.space)
323  self.args.append(limit_param)
324  return self
325 
326  def desc(self):
327  """
328  倒叙
329  example:
330  find('all').desc()
331  find('all').desc().end()
332  find('all').order_by('param').desc().limit(10,20)
333  """
334 
335  if self.sqlFields.order_by_str not in self.args:
336  ALog.log_error(
337  'There is no `order by` field before calling `desc` field,You have an error in your SQL syntax',
338  AttributeError, LogObject=self.repository.log_obj, raise_exception=True)
339 
340  self.args.append(self.sqlFields.desc_str)
341  return self
342 
343  def set(self, **kwargs):
344  """
345  设置
346  example:
347  update('table').set('param','value').end()
348  update('table').set('param1','value1').where('param2=value2').end()
349  """
350  self.args.append(self.sqlFields.set_str)
351  _size = len(kwargs.keys())
352  for key, value in kwargs.items():
353  self.args.append('{}{}{}{}%s'.format(self.sqlFields.left_subscript,
354  key,
355  self.sqlFields.right_subscript,
356  self.sqlFields.eq))
357  # set是加逗号不是and
358  self.args.append(self.sqlFields.comma)
359  self.params.append(value)
360  self.rep_sym(self.sqlFields.comma)
361  return self
362 
363  # ------------------------预设符--------------------------
364 
365  def ander(self):
366  """
367 
368  example:
369  update('table').set('param1','value1').and().set('param2','value2')
370  update('table').set('param1','value1').and().set('param2','value2').end()
371  update('table').set('param1','value1').and().set('param2','value2').where('param3=value3').end()
372  """
373  self.args.append(self.sqlFields.ander_str)
374  return self
375 
376  def run(self, need_sql=False, serializer=True) -> QuerySet:
377  """
378  最终执行任务
379  """
380  sql = ''
381  conf = self.ParseUtil.get_dict()
382  print_sql = 'print_sql' in conf.keys() and conf['print_sql'] is True
383  last_id = 'last_id' in conf.keys() and conf['last_id'] is True
384  sql += ''.join(self.args)
385  if need_sql:
386  return sql
387  if self.exmode == AOrm.Mode.FIND:
388  self._result = self.repository.db_util.select(
389  sql=sql,
390  params=self.params,
391  print_sql=print_sql,
392  last_id=last_id,
393  **self.repository.__dict__
394  )
395  _result_objs = []
396  for i in self._result:
397  _obj = self.ParseUtil.parse_obj(
398  data=i, instance=self.repository.instance)
399  _result_objs.append(_obj)
400  self._result = _result_objs
401  else:
402  self._result = self.repository.db_util.update(
403  sql=sql,
404  params=self.params,
405  print_sql=print_sql,
406  last_id=last_id
407  )
408  # 清空资源,为下一次使用做准备
409  self.args.clear()
410  self.params.clear()
411  if self.first_data:
412  if (isinstance(self._result, list) or isinstance(self._result, tuple)) and self._result and len(
413  self._result) > 0:
414  if not serializer:
415  return self._result[0]
416  self.repository.result = self.serializer(instance=self.repository.instance,
417  base_data=self._result).first()
418  return self.repository.result
419  else:
420  self.repository.result = self.serializer()
421  return self.repository.result
422  else:
423  if not serializer:
424  return self._result
425  self.repository.result = self.serializer(
426  instance=self.repository.instance, base_data=self._result)
427  return self.repository.result
428 
429  def con_from(self):
430  """
431  如果没有被from包含,则在末尾加上from __table_name__关键字
432  """
433  if self.sqlFields.from_str not in self.args:
434  self.args.append(self.sqlFields.from_str)
435  # 然后加上表名
436  self.args.append(self.sqlFields.left_subscript)
437  self.args.append(self.__table_name__)
438  self.args.append(self.sqlFields.right_subscript)
439 
440  def append(self, app_sql):
441  """
442  末尾追加一些sql
443  """
444  self.args.append(app_sql)
445  return self
446 
447  def rep_sym(self, sym=',', rep=''):
448  """
449  将最后一个参数包含的指定字符替换为指定字符
450  """
451  self.args[len(self.args) -
452  1] = str(self.args[len(self.args) - 1]).replace(sym, rep)
453  return self
454 
455  def end(self, **kwargs):
456  return self.run(**kwargs)
457 
458  def __rshift__(self, other):
459  """
460  将左边orm迁移至右边
461  """
462  new_args = self.args.copy()
463  new_args.append(' ) ')
464  other.args.append(' ( ')
465  other.args += new_args
466  return other
467 
468  def __lshift__(self, other):
469  """
470  将右边迁移至左边
471  """
472  new_args = other.args.copy()
473  new_args.append(' ) ')
474  self.args.append(' ( ')
475  self.args = self.args + new_args
476  return self
477 
478  def alias(self, name):
479  """
480  设置别名
481  """
482  self.args.append(' AS ')
483  self.args.append(name)
484  return self
485 
486  def left_join(self, sql_orm, name):
487  """
488  left join
489  """
490  self.args.append(self.sqlFields.left_join_str)
491  self.args.append(sql_orm.__table_name__)
492  return self.alias(name)
493 
494  def __str__(self):
495  sql = ''.join(self.args)
496  return sql
497 
498  def check(self):
499  """sudo apt install containerd
500  检查表结构与数据库中是否对应
501  """
502  return self.repository.config_obj.opera(self.repository).check()
503 
504  def create(self):
505  return self.repository.config_obj.opera(self.repository).create()
aestate.work.orm.AOrm.serializer
serializer
Definition: orm.py:97
aestate.work.orm.AOrm.left_join
def left_join(self, sql_orm, name)
Definition: orm.py:486
aestate.work.orm.AOrm.run
QuerySet run(self, need_sql=False, serializer=True)
Definition: orm.py:376
aestate.work.orm.AOrm.alias
def alias(self, name)
Definition: orm.py:478
aestate.work.orm.AOrm.order_by
def order_by(self, *args, **kwargs)
Definition: orm.py:194
aestate.work.orm.BaseCover.check
bool check(self, res, fields)
Definition: orm.py:25
aestate.work.orm.AOrm.find
def find(self, *args, **kwargs)
Definition: orm.py:125
aestate.work.orm.AOrm.create
def create(self)
Definition: orm.py:504
aestate.work.orm.AOrm.repository
repository
Definition: orm.py:104
aestate.work.orm.BaseCover
Definition: orm.py:11
aestate.work.orm.AOrm.__table_name__
__table_name__
Definition: orm.py:107
aestate.work.orm.AOrm.group_by
def group_by(self, *args, **kwargs)
Definition: orm.py:204
aestate.work.orm.AOrm.by_opera
def by_opera(self, field, args_list, **kwargs)
Definition: orm.py:212
aestate.work.orm.AOrm.where
def where(self, **kwargs)
Definition: orm.py:230
aestate.work.orm.AOrm.__str__
def __str__(self)
Definition: orm.py:494
aestate.work.orm.AOrm.Mode
Definition: orm.py:78
aestate.work.orm.AOrm.ParseUtil
ParseUtil
Definition: orm.py:96
aestate.work.Serialize
Definition: Serialize.py:1
aestate.work.orm.AOrm.__rshift__
def __rshift__(self, other)
Definition: orm.py:458
aestate.work.orm.AOrm._result
_result
Definition: orm.py:110
aestate.work.orm.AOrm.end
def end(self, **kwargs)
Definition: orm.py:455
aestate.work.orm.AOrm.params
params
Definition: orm.py:93
aestate.work.orm.AOrm.args
args
Definition: orm.py:92
aestate.work.orm.AOrm.exmode
exmode
Definition: orm.py:91
aestate.work.orm.AOrm.rep_sym
def rep_sym(self, sym=',', rep='')
Definition: orm.py:447
aestate.work.orm.AOrm.ander
def ander(self)
Definition: orm.py:365
aestate.work.orm.AOrm.__init__
def __init__(self, repository)
Definition: orm.py:82
aestate.work.orm.AOrm.filter
def filter(self, **kwargs)
Definition: orm.py:227
aestate.work.orm.AOrm.on
def on(self, from_where, to_where, symbol='=')
Definition: orm.py:295
aestate.util.Log
Definition: Log.py:1
aestate.work.orm.AOrm.desc
def desc(self)
Definition: orm.py:326
aestate.exception
Definition: __init__.py:1
aestate.work.orm.BaseCover.res
dict res(self, tb_name, db_name, extool)
Definition: orm.py:42
aestate.work.orm.AOrm.con_from
def con_from(self)
Definition: orm.py:429
aestate.work.orm.AOrm.set
def set(self, **kwargs)
Definition: orm.py:343
aestate.work.orm.AOrm.append
def append(self, app_sql)
Definition: orm.py:440
aestate.work.orm.AOrm.first_data
first_data
Definition: orm.py:109
aestate.work.orm.AOrm.sqlFields
sqlFields
Definition: orm.py:94
aestate.work.orm.BaseCover.table_visual
PrettyTable table_visual(self, list title, List[dict] val)
Definition: orm.py:13
aestate.work.orm.AOrm.first
def first(self)
Definition: orm.py:117
aestate.work.orm.BaseCover.deal
def deal(self, res, fields)
Definition: orm.py:36
aestate.work.orm.AOrm.top
def top(self)
Definition: orm.py:112
aestate.work.orm.AOrm
Definition: orm.py:67
aestate.work.orm.AOrm.__lshift__
def __lshift__(self, other)
Definition: orm.py:468
aestate.work.orm.AOrm.check
def check(self)
Definition: orm.py:498
aestate.work.orm.AOrm.limit
def limit(self, start=0, end=None)
Definition: orm.py:306