cloudoll 2.4.0__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.
cloudoll/orm/field.py ADDED
@@ -0,0 +1,522 @@
1
+ class objdict(dict):
2
+ def __getattr__(self, attr):
3
+ try:
4
+ return self[attr]
5
+ except KeyError:
6
+ raise AttributeError(attr)
7
+
8
+
9
+ OP = objdict(
10
+ AND="AND",
11
+ OR="OR",
12
+ ADD="+",
13
+ SUB="-",
14
+ MUL="*",
15
+ DIV="/",
16
+ BIN_AND="&",
17
+ BIN_OR="|",
18
+ XOR="#",
19
+ MOD="%",
20
+ EQ="=",
21
+ LT="<",
22
+ LTE="<=",
23
+ GT=">",
24
+ GTE=">=",
25
+ NE="!=",
26
+ IN="IN",
27
+ NOT_IN="NOT IN",
28
+ IS="IS",
29
+ DESC="DESC",
30
+ ASC="ASC",
31
+ AVG="AVG",
32
+ AS="AS",
33
+ SUM="SUM",
34
+ MAX="MAX",
35
+ MIN="MIN",
36
+ IS_TODAY="IS_TODAY",
37
+ IS_THIS_WEEK="THIS_WEEK",
38
+ IS_THIS_MONTH="THIS_MONTH",
39
+ IS_THIS_YEAR="THIS_YEAR",
40
+ LASTED_HOURS="LASTED_HOURS",
41
+ LASTED_MINUTES="LASTED_MINUTES",
42
+ LASTED_SECONDS="LASTED_SECONDS",
43
+ LASTED_YEARS="LASTED_YEARS",
44
+ LASTED_MONTHS="LASTED_MONTHS",
45
+ LASTED_DAYS="LASTED_DAYS",
46
+ BEFORE_YEARS="BEFORE_YEARS",
47
+ BEFORE_MONTHS="BEFORE_MONTHS",
48
+ BEFORE_DAYS="BEFORE_DAYS",
49
+ BEFORE_HOURS="BEFORE_HOURS",
50
+ BEFORE_MINUTES="BEFORE_MINUTES",
51
+ BEFORE_SECONDS="BEFORE_SECONDS",
52
+ DATE_FORMAT="DATE_FORMAT",
53
+ JSON_CONTAINS_OBJECT="JSON_CONTAINS_OBJECT",
54
+ JSON_CONTAINS_ARRAY="JSON_CONTAINS_ARRAY",
55
+ COUNT="COUNT",
56
+ COUNT_WHEN="COUNT_WHEN",
57
+ SUM_WHEN="SUM_WHEN",
58
+ MAX_WHEN="MAX_WHEN",
59
+ MIN_WHEN="MIN_WHEN",
60
+ AVG_WHEN="AVG_WHEN",
61
+ IS_NOT="IS NOT",
62
+ IS_NOT_NULL="IS NOT NULL",
63
+ IS_NULL="IS NULL",
64
+ LIKE="LIKE",
65
+ NOT_LIKE="NOT LIKE",
66
+ ILIKE="ILIKE",
67
+ BETWEEN="BETWEEN",
68
+ CONTAINS="CONTAINS",
69
+ NOT_BETWEEN="NOT BETWEEN",
70
+ REGEXP="REGEXP",
71
+ IREGEXP="IREGEXP",
72
+ GROUP_CONCAT="GROUP_CONCAT",
73
+ DISTINCT="DISTINCT",
74
+ CONCAT="||",
75
+ BITWISE_NEGATION="~",
76
+ )
77
+
78
+
79
+ class FieldBase(object):
80
+ def _op(op, inverse=False):
81
+ def inner(self, rhs):
82
+ if inverse:
83
+ return Expression(rhs, op, self)
84
+ return Expression(self, op, rhs)
85
+
86
+ return inner
87
+
88
+ def __eq__(self, rhs):
89
+ return Expression(self, OP.EQ, rhs)
90
+
91
+ def __ne__(self, rhs):
92
+ return Expression(self, OP.NE, rhs)
93
+
94
+ __lt__ = _op(OP.LT) # <
95
+ __le__ = _op(OP.LTE) # <=
96
+ __gt__ = _op(OP.GT) # >
97
+ __ge__ = _op(OP.GTE) # >=
98
+ __and__ = _op(OP.AND) # and
99
+ __or__ = _op(OP.OR) # or
100
+
101
+ # 运算
102
+ __add__ = _op(OP.ADD) # +
103
+ __radd__ = _op(OP.ADD, True) # +=
104
+ __sub__ = _op(OP.SUB) # -
105
+ __rsub__ = _op(OP.SUB, True) # -=
106
+ __mul__ = _op(OP.MUL) # *
107
+ __rmul__ = _op(OP.MUL, True) # *=
108
+ __div__ = _op(OP.DIV) # /
109
+ __rdiv__ = _op(OP.DIV, True) # /=
110
+
111
+ In = _op(OP.IN) # in
112
+ not_in = _op(OP.NOT_IN) # not in
113
+ like = _op(OP.LIKE) # like
114
+ ilike = _op(OP.ILIKE) # ilike for pg
115
+ not_like = _op(OP.NOT_LIKE) # not like
116
+
117
+ def group_concat(self, *arg):
118
+ return Function(self, OP.GROUP_CONCAT, arg)
119
+
120
+ def distinct(self, *arg):
121
+ return Function(self, OP.DISTINCT, arg)
122
+
123
+ def desc(self):
124
+ return Expression(self, OP.DESC, None)
125
+
126
+ def asc(self):
127
+ return Expression(self, OP.ASC, None)
128
+
129
+ def count(self):
130
+ return Function(self, OP.COUNT)
131
+
132
+ def count_when(self, *arg):
133
+ """
134
+ input: count_when(A.field > 10 ,1 , 0) \n
135
+ output: count(case when A.field > 10 then 1 else 0 end)
136
+ """
137
+ return Function(self, OP.COUNT_WHEN, arg)
138
+
139
+ def max(self):
140
+ return Function(self, OP.MAX)
141
+
142
+ def max_when(self, *arg):
143
+ """
144
+ input: max_when(A.field > 10 ,A.field) \n
145
+ output: max(case when A.field > 10 then A.field end)
146
+ """
147
+ return Function(self, OP.MAX_WHEN, arg)
148
+
149
+ def min(self):
150
+ return Function(self, OP.MIN)
151
+
152
+ def min_when(self, *arg):
153
+ """
154
+ input: min_when(A.field > 10 ,A.field) \n
155
+ output: min(case when A.field > 10 then A.field end)
156
+ """
157
+ return Function(self, OP.MIN_WHEN, arg)
158
+
159
+ def sum(self):
160
+ return Function(self, OP.SUM)
161
+
162
+ def sum_when(self, *arg):
163
+ """
164
+ input: sum_when(A.field > 10 ,1 , 0)\n
165
+ output: sum(case when A.field > 10 then 1 else 0 end)
166
+ """
167
+ return Function(self, OP.SUM_WHEN, arg)
168
+
169
+ def avg(self):
170
+ return Function(self, OP.AVG)
171
+
172
+ def avg_when(self, *arg):
173
+ """
174
+ input: avg_when(A.field > 10 , A.field)\n
175
+ output: avg(case when A.field > 10 then A.field end)
176
+ """
177
+ return Function(self, OP.AVG_WHEN, arg)
178
+
179
+ def date_format(self, args):
180
+ return Function(self, OP.DATE_FORMAT, args)
181
+
182
+ def is_today(self):
183
+ return Function(self, OP.IS_TODAY)
184
+
185
+ def is_this_week(self):
186
+ return Function(self, OP.IS_THIS_WEEK)
187
+
188
+ def is_this_month(self):
189
+ return Function(self, OP.IS_THIS_MONTH)
190
+
191
+ def is_this_year(self):
192
+ return Function(self, OP.IS_THIS_YEAR)
193
+
194
+ def lasted_hours(self, args):
195
+ return Function(self, OP.LASTED_HOURS, args)
196
+
197
+ def lasted_minutes(self, args):
198
+ return Function(self, OP.LASTED_MINUTES, args)
199
+
200
+ def lasted_seconds(self, args):
201
+ return Function(self, OP.LASTED_SECONDS, args)
202
+
203
+ def lasted_years(self, args):
204
+ return Function(self, OP.LASTED_YEARS, args)
205
+
206
+ def lasted_months(self, args):
207
+ return Function(self, OP.LASTED_MONTHS, args)
208
+
209
+ def lasted_days(self, args):
210
+ return Function(self, OP.LASTED_DAYS, args)
211
+
212
+ def before_months(self, args):
213
+ return Function(self, OP.BEFORE_MONTHS, args)
214
+
215
+ def before_years(self, args):
216
+ return Function(self, OP.BEFORE_YEARS, args)
217
+
218
+ def before_days(self, args):
219
+ return Function(self, OP.BEFORE_DAYS, args)
220
+
221
+ def before_hours(self, args):
222
+ return Function(self, OP.BEFORE_HOURS, args)
223
+
224
+ def before_minutes(self, args):
225
+ return Function(self, OP.BEFORE_MINUTES, args)
226
+
227
+ def before_seconds(self, args):
228
+ return Function(self, OP.BEFORE_SECOBDS, args)
229
+
230
+ def json_contains_object(self, key, value):
231
+ return Function(self, OP.JSON_CONTAINS_OBJECT, (key, value))
232
+
233
+ def json_contains_array(self, args):
234
+ return Function(self, OP.JSON_CONTAINS_ARRAY, args)
235
+
236
+ def contains(self, args):
237
+ return Function(self, OP.CONTAINS, args)
238
+ # return AO(f"contains({self.full_name},?)", args)
239
+
240
+ def As(self, args):
241
+ return Expression(self, OP.AS, args)
242
+
243
+ def is_null(self):
244
+ return Expression(self, OP.IS_NULL, None)
245
+
246
+ def not_null(self):
247
+ return Expression(self, OP.IS_NOT_NULL, None)
248
+
249
+ def between(self, h1, h2):
250
+ return Expression(self, OP.BETWEEN, ExpList(h1, OP.AND, h2))
251
+
252
+ def not_between(self, h1, h2):
253
+ return Expression(self, OP.NOT_BETWEEN, ExpList(h1, OP.AND, h2))
254
+
255
+
256
+ class ExpList(FieldBase):
257
+ def __init__(self, lpt, op, rpt):
258
+ self.lpt = lpt
259
+ self.op = op
260
+ self.rpt = rpt
261
+
262
+ def sql(self):
263
+ lpt = self.lpt
264
+ rpt = self.rpt
265
+
266
+ p = []
267
+ q = []
268
+ if isinstance(lpt, Exception):
269
+ _q, _p = lpt.sql()
270
+ q = q + _q
271
+ p = p + _p
272
+ else:
273
+ q.append("?")
274
+ p.append(lpt)
275
+ q.append(f" {self.op} ")
276
+ if isinstance(rpt, Exception):
277
+ _q, _p = lpt.sql()
278
+ q = q + _q
279
+ p = p + _p
280
+ else:
281
+ q.append("?")
282
+ p.append(lpt)
283
+
284
+ return "".join(q), p
285
+ # return f"{lpt.sql() if isinstance(lpt,Expression) else lpt} {self.op} {rpt.sql() if isinstance(rpt,Expression) else rpt}"
286
+
287
+
288
+ def deconstruct(args):
289
+ f = args[0] if len(args) > 0 else None
290
+ v1 = args[1] if len(args) > 1 else 1
291
+ v2 = args[2] if len(args) > 2 and args[2] is not None else 'NULL'
292
+ c = None
293
+ v = None
294
+ if isinstance(f, FieldBase):
295
+ c = f"{f.lhs.full_name} {f.op} ?"
296
+ v = f.rhs
297
+ if isinstance(v1, FieldBase):
298
+ v1 = v1.name
299
+ return c, v, v1, v2
300
+
301
+
302
+ class Function(FieldBase):
303
+ def __init__(self, col, op, rpt=None):
304
+ self.col = col
305
+ self.op = op
306
+ self.rpt = rpt
307
+
308
+ def sql(self):
309
+ op = self.op
310
+ col_name = self.col.full_name
311
+ is_field = isinstance(self.rpt, Field)
312
+ # todo:
313
+ if op == OP.DATE_FORMAT:
314
+ return f"{op}({col_name},?)", [self.rpt]
315
+ elif op == OP.IS_TODAY:
316
+ return f"DATE({col_name}) = CURDATE()", None
317
+ elif op == OP.IS_THIS_WEEK:
318
+ return f"WEEK({col_name}, 1) = WEEK(CURDATE(), 1)", None
319
+ elif op == OP.IS_THIS_MONTH:
320
+ return f"MONTH({col_name}) = MONTH(CURDATE())", None
321
+ elif op == OP.IS_THIS_YEAR:
322
+ return f"YEAR({col_name}) = YEAR(CURDATE())", None
323
+
324
+ elif op == OP.LASTED_SECONDS:
325
+ return f"{col_name} >= NOW() - INTERVAL {self.rpt} SECOND", None
326
+ elif op == OP.LASTED_MINUTES:
327
+ return f"{col_name} >= NOW() - INTERVAL {self.rpt} MINUTE", None
328
+ elif op == OP.LASTED_HOURS:
329
+ return f"{col_name} >= NOW() - INTERVAL {self.rpt} HOUR", None
330
+ elif op == OP.LASTED_YEARS:
331
+ return f"{col_name} >= NOW() - INTERVAL {self.rpt} YEAR", None
332
+ elif op == OP.LASTED_MONTHS:
333
+ return f"{col_name} >= NOW() - INTERVAL {self.rpt} MONTH", None
334
+ elif op == OP.LASTED_DAYS:
335
+ return f"DATE({col_name}) >= CURDATE() - INTERVAL {self.rpt} DAY", None
336
+
337
+ elif op == OP.BEFORE_YEARS:
338
+ return f"{col_name} < NOW() - INTERVAL {self.rpt} YEAR", None
339
+ elif op == OP.BEFORE_MONTHS:
340
+ return f"{col_name} < NOW() - INTERVAL {self.rpt} MONTH", None
341
+ elif op == OP.BEFORE_DAYS:
342
+ return f"{col_name} < NOW() - INTERVAL {self.rpt} DAY", None
343
+ elif op == OP.BEFORE_HOURS:
344
+ return f"{col_name} < NOW() - INTERVAL {self.rpt} HOUR", None
345
+ elif op == OP.BEFORE_MINUTES:
346
+ return f"{col_name} < NOW() - INTERVAL {self.rpt} MINUTE", None
347
+ elif op == OP.BEFORE_SECONDS:
348
+ return f"{col_name} < NOW() - INTERVAL {self.rpt} SECOND", None
349
+ elif op == OP.CONTAINS:
350
+ return f"{col_name} LIKE CONCAT('%%',?,'%%')", [self.rpt]
351
+ # return f"CONTAINS({col_name},?)", [self.rpt]
352
+ elif op == OP.JSON_CONTAINS_OBJECT:
353
+ _k, _v = self.rpt
354
+ key = _k.full_name if isinstance(_k, Field) else f"'{_k}'"
355
+ return f"json_contains({col_name},json_object({key},?))", [_v]
356
+ elif op == OP.JSON_CONTAINS_ARRAY:
357
+ if is_field:
358
+ return f"json_contains({col_name},json_array({self.rpt.full_name}))", None
359
+ return f"json_contains({col_name},json_array(?))", [self.rpt]
360
+ elif op == OP.COUNT:
361
+ return f"COUNT({col_name})", None
362
+ elif op == OP.COUNT_WHEN:
363
+ c, v, v1, v2 = deconstruct(self.rpt)
364
+ return f"COUNT(CASE WHEN {c} THEN {v1} ELSE {v2} END)", [v]
365
+ elif op == OP.SUM:
366
+ return f"SUM({col_name})", None
367
+ elif op == OP.SUM_WHEN:
368
+ c, v, v1, v2 = deconstruct(self.rpt)
369
+ return f"SUM(CASE WHEN {c} THEN {v1} ELSE {v2} END)", [v]
370
+ elif op == OP.AVG:
371
+ return f"AVG({col_name})", None
372
+ elif op == OP.AVG_WHEN:
373
+ c, v, v1, v2 = deconstruct(self.rpt)
374
+ return f"AVG(CASE WHEN {c} THEN {v1} ELSE {v2} END)", [v]
375
+ elif op == OP.MAX:
376
+ return f"MAX({col_name})", None
377
+ elif op == OP.MAX_WHEN:
378
+ c, v, v1, v2 = deconstruct(self.rpt)
379
+ return f"MAX(CASE WHEN {c} THEN {v1} ELSE {v2} END)", [v]
380
+ elif op == OP.MIN:
381
+ return f"MIN({col_name})", None
382
+ elif op == OP.MIN_WHEN:
383
+ c, v, v1, v2 = deconstruct(self.rpt)
384
+ return f"MIN(CASE WHEN {c} THEN {v1} ELSE {v2} END)", [v]
385
+ elif op == OP.GROUP_CONCAT:
386
+ arg = self.rpt
387
+ extra = None
388
+ if len(arg) == 0:
389
+ extra = col_name
390
+ elif len(arg) == 1 and isinstance(arg[0], FieldBase):
391
+ extra = f"{arg[0].op} {arg[0].col.name}"
392
+ else:
393
+ # todo : DISTINCT name ORDER BY name ASC SEPARATOR '; '
394
+ extra = col_name
395
+
396
+ return f"GROUP_CONCAT({extra})", None
397
+ elif op == OP.DISTINCT:
398
+ return f"DISTINCT {col_name}", None
399
+
400
+
401
+ class Expression(FieldBase):
402
+ def __init__(self, lhs, op, rhs):
403
+ self.lhs = lhs
404
+ self.op = op
405
+ self.rhs = rhs
406
+ # self.__value = ""
407
+ # if op in "+-*/|&~" and lhs._value:
408
+ # cal = f"{lhs._value}{op}"
409
+ # if isinstance(rhs, FieldBase):
410
+ # self.__value = str(eval(f"{cal}{rhs._value}"))
411
+ # else:
412
+ # self.__value = str(eval(f"{cal}{rhs}"))
413
+
414
+ def sql(self):
415
+ l = self.lhs
416
+ r = self.rhs
417
+ is_fun = isinstance(l, Function)
418
+ p = []
419
+ q = []
420
+ if not is_fun:
421
+ q.append("(")
422
+ if isinstance(l, Field):
423
+ q.append(l.full_name)
424
+ elif isinstance(l, Expression):
425
+ _q, _p = l.sql()
426
+ q.append(_q)
427
+ p = p + _p
428
+ elif is_fun:
429
+ _q, _p = l.sql()
430
+ q.append(_q)
431
+ if _p:
432
+ p = p + _p
433
+
434
+ q.append(f" {self.op} ")
435
+
436
+ if isinstance(r, Field):
437
+ if r._value is not None:
438
+ q.append("?")
439
+ p.append(r._value)
440
+ else:
441
+ q.append(r.full_name)
442
+ elif isinstance(r, FieldBase):
443
+ _q, _p = r.sql()
444
+ q.append(_q)
445
+ if _p:
446
+ p = p + _p
447
+ elif self.op == OP.AS:
448
+ q.append(r)
449
+ elif r is not None:
450
+ q.append("?")
451
+ p.append(r)
452
+ if not is_fun:
453
+ q.append(")")
454
+ q = [str(num) for num in q]
455
+ return "".join(q), p
456
+
457
+ # def __str__(self):
458
+ # return self.__value
459
+ # cal = f"{self.lhs._value}{self.op}"
460
+ # if isinstance(self.rhs, FieldBase):
461
+ # return str(eval(f"{cal}{self.rhs._value}"))
462
+ # return str(eval(f"{cal}{self.rhs}"))
463
+
464
+ def __repr__(self):
465
+ cal = f"{self.lhs.value}{self.op}"
466
+ if isinstance(self.rhs, FieldBase):
467
+ return str(eval(f"{cal}{self.rhs.value}"))
468
+ return str(eval(f"{cal}{self.rhs}"))
469
+
470
+
471
+ class Field(FieldBase):
472
+ def __init__(
473
+ self,
474
+ name, # 列名
475
+ column_type, # 类型
476
+ default=None, # 默认值
477
+ primary_key=False, # 主键
478
+ charset=None, # 编码
479
+ max_length=None, # 长度
480
+ scale_length=None, # 精度
481
+ auto_increment=False, # 自增
482
+ NOT_NULL=False, # 非空
483
+ created_generated=False, # 创建时for datetime
484
+ update_generated=False, # 更新时for datetime
485
+ unsigned=False, # 无符号,没有负数
486
+ comment=None, # 备注
487
+ **kwargs,
488
+ ):
489
+ super().__init__()
490
+ self.full_name = None
491
+ self._value = None
492
+ self.name = name
493
+ self.column_type = column_type
494
+ self.primary_key = primary_key
495
+ self.charset = charset
496
+ self.default = default
497
+ self.max_length = max_length
498
+ self.scale_length = scale_length
499
+ self.auto_increment = auto_increment
500
+ self.NOT_NULL = NOT_NULL
501
+ self.created_generated = created_generated
502
+ self.update_generated = update_generated
503
+ self.comment = comment
504
+ self.unsigned = unsigned
505
+
506
+ def __str__(self):
507
+ return str(self._value)
508
+ # "<%s, %s:%s>" % (self.__class__.__name__, self.column_type, self.name)
509
+ # return self.name
510
+
511
+ def __repr__(self):
512
+ return str(self._value)
513
+
514
+ # def __getattr__(self, item):
515
+ # return self[item]
516
+ @property
517
+ def value(self):
518
+ return self._value
519
+
520
+ @value.setter
521
+ def value(self, value):
522
+ self._value = value