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/model.py ADDED
@@ -0,0 +1,806 @@
1
+ from .field import Field, Function, Expression
2
+ from ..logging import warning
3
+ from functools import reduce
4
+ import operator
5
+ import copy
6
+ import re
7
+ import datetime
8
+ from ..utils.common import Object
9
+ from typing import Tuple
10
+
11
+ __ALL__ = ("models", "Model")
12
+
13
+
14
+ class ModelMetaclass(type):
15
+ # def __init__(self, **kw):
16
+ # pass
17
+ # def __call__(cls, *args, **kwargs):
18
+ # instance = super().__call__(*args, **kwargs)
19
+ # # 在元类中处理拷贝逻辑
20
+ # return copy.copy(instance)
21
+
22
+ def __new__(mcs, name, bases, attrs):
23
+ if name == "Model":
24
+ return type.__new__(mcs, name, bases, attrs)
25
+ # debug("Found model:%s" % name)
26
+ # 表名
27
+ table_name = attrs.get("__table__", None) or name
28
+ primary_key = None
29
+ fields = []
30
+ # mappings = dict()
31
+ for k, v in attrs.items():
32
+ if isinstance(v, Field):
33
+ v.name = k
34
+ v.full_name = f"`{table_name}`.{k}"
35
+ # mappings[k] = v
36
+ if v.primary_key:
37
+ if primary_key:
38
+ warning(f"Duplicate primary key for {table_name}")
39
+ primary_key = k
40
+ # else:
41
+ fields.append(k)
42
+
43
+ if not primary_key:
44
+ warning(f"{table_name} Missing primary key")
45
+
46
+ # for k in mappings.keys():
47
+ # attrs.pop(k)
48
+
49
+ # escaped_fields = list(map(lambda f: "`%s`" % f, fields))
50
+ # attrs["__mappings__"] = mappings
51
+ attrs["__table__"] = table_name
52
+ attrs["__primary_key__"] = primary_key
53
+ attrs["__fields__"] = fields
54
+ attrs["__pool__"] = None
55
+ attrs["__join__"] = None
56
+ attrs["__where__"] = None
57
+ attrs["__having__"] = None
58
+ attrs["__params__"] = None
59
+ attrs["__cols__"] = "*"
60
+ attrs["__order_by__"] = None
61
+ attrs["__group_by__"] = None
62
+ attrs["__limit__"] = None
63
+ attrs["__offset__"] = None
64
+
65
+ model = type.__new__(mcs, name, bases, attrs)
66
+ return model
67
+
68
+ def __repr__(self):
69
+ return "<Model: %s>" % self.__name__
70
+
71
+ # def __getattr__(self, name):
72
+ # return self.__fields__[name]
73
+
74
+
75
+ class Model(metaclass=ModelMetaclass):
76
+ def __init__(self, **kw):
77
+ for k in self.__fields__:
78
+ f = getattr(self, k, None)
79
+ f.value = None
80
+ for k, v in kw.items():
81
+ self[k] = v
82
+
83
+ # super().__init__(self, **kw)
84
+
85
+ def __str__(self):
86
+ return "<Model: %s>" % self.__class__.__name__
87
+
88
+ def __repr__(self):
89
+ return "<Model: %s>" % self.__class__.__name__
90
+
91
+ @property
92
+ def __dict__(self):
93
+ fields = self.__fields__
94
+ _dict = {}
95
+ for key in fields:
96
+ f = getattr(self, key)
97
+ _dict[key] = f.value
98
+ return _dict
99
+
100
+ # class to fun for cls(**)
101
+ def __call__(self, **kw):
102
+ self.__init__(**kw)
103
+
104
+ return self
105
+
106
+ def __getitem__(self, name):
107
+ return getattr(self, name)
108
+
109
+ # # .['x']
110
+ def __setitem__(self, name, value):
111
+ setattr(self, name, value)
112
+
113
+ def __setattr__(self, name, value):
114
+ if hasattr(self, name):
115
+ f = getattr(self, name)
116
+ if isinstance(f, Field):
117
+ s = copy.copy(f)
118
+ s.value = value
119
+ super().__setattr__(name, s)
120
+ else:
121
+ super().__setattr__(name, value)
122
+ else:
123
+ super().__setattr__(name, value)
124
+
125
+ # for get
126
+ def get(self, k, d=None):
127
+ f = getattr(self, k)
128
+ if isinstance(f, Field):
129
+ return f.value or d
130
+ return f or d
131
+
132
+ def _get_primary(self):
133
+ pk = self.__primary_key__
134
+ if pk is None:
135
+ return None, None
136
+ pkf = getattr(self, pk)
137
+ return pk, pkf.value
138
+
139
+ def _reset(self):
140
+ self.__join__ = None
141
+ self.__where__ = None
142
+ self.__having__ = None
143
+ self.__params__ = None
144
+ self.__cols__ = "*"
145
+ self.__order_by__ = None
146
+ self.__group_by__ = None
147
+ self.__limit__ = None
148
+ self.__offset__ = None
149
+
150
+ @classmethod
151
+ def use(cls, pool=None):
152
+ cls.__pool__ = pool
153
+ cls.__ispg = cls.__pool__.driver == "postgres" if pool else False
154
+ return cls()
155
+
156
+ def select(cls, *args):
157
+ cols = []
158
+ for col in args:
159
+ if isinstance(col, Field):
160
+ cols.append(col.name if cls.__ispg else col.full_name)
161
+ elif isinstance(col, Function):
162
+ q, p = col.sql()
163
+ cols.append(q)
164
+ elif isinstance(col, Expression):
165
+ q, p = col.sql()
166
+ cols.append(q)
167
+ cls._merge_params(p)
168
+ cls.__cols__ = ",".join(cols) if len(cols) else "*"
169
+ return cls
170
+
171
+ def join(cls, model, *exp):
172
+ ex = reduce(operator.and_, exp)
173
+ if isinstance(ex, Expression) or isinstance(ex, Function):
174
+ exp, q = ex.sql()
175
+ cls._merge_params(q)
176
+ else:
177
+ exp = ex
178
+ join = f"{model.__table__} ON " + exp
179
+ if cls.__join__ is None:
180
+ cls.__join__ = join
181
+ else:
182
+ cls.__join__ += join
183
+ return cls
184
+
185
+ def where(self, *exp):
186
+ if self.__where__ is not None:
187
+ exp = (self.__where__,) + exp
188
+ self.__where__ = reduce(operator.and_, exp)
189
+ return self
190
+
191
+ def having(self, *exp):
192
+ if self.__having__ is not None:
193
+ exp = (self.__having__,) + exp
194
+ self.__having__ = reduce(operator.and_, exp)
195
+ return self
196
+
197
+ def order_by(self, *args):
198
+ by = []
199
+ for f in args:
200
+ if isinstance(f, str):
201
+ by.append(f)
202
+ else:
203
+ by.append(f"{f.lhs.name if self.__ispg else f.lhs.full_name} {f.op}")
204
+ if self.__order_by__ is not None:
205
+ by = self.__order_by__ + by
206
+ self.__order_by__ = by
207
+ return self
208
+
209
+ def group_by(self, *args):
210
+ by = []
211
+ for f in args:
212
+ by.append(f.name if self.__ispg else f.full_name)
213
+ if self.__group_by__ is not None:
214
+ by = self.__group_by__ + by
215
+ self.__group_by__ = by
216
+ return self
217
+
218
+ def _format_data(self, action, args):
219
+ data = dict()
220
+ if args is None or not args:
221
+ for k in self.__fields__:
222
+ f = getattr(self, k)
223
+ x = f.value
224
+ data[k] = x
225
+ elif args and isinstance(args, dict):
226
+ data = args
227
+ else:
228
+ for item in args:
229
+ if isinstance(item, Model):
230
+ for k in item.__dict__:
231
+ if (
232
+ action == "u" and item[k].value is not None
233
+ ) or action == "i":
234
+ data[k] = item[k]
235
+
236
+ else: # for object
237
+ for k, v in item.items():
238
+ data[k] = v
239
+
240
+ return data
241
+
242
+ def _get_update_key_args(self, action, args):
243
+ data = self._format_data(action, args)
244
+ keys = []
245
+ params = []
246
+ for k, v in data.items():
247
+ if isinstance(v, Field):
248
+ value = v.value
249
+ if value is None:
250
+ if v.created_generated == True or v.update_generated == True:
251
+ value = datetime.datetime.now()
252
+ else:
253
+ value = v.default
254
+ if value is not None:
255
+ keys.append("`%s`=?" % k)
256
+ params.append(value)
257
+ elif v is not None: # fix sql format %s
258
+ keys.append("`%s`=?" % k)
259
+ params.append(v)
260
+ return ",".join(keys), params
261
+
262
+ def _get_insert_key_args(self, action, args):
263
+ data = self._format_data(action, args)
264
+ keys = []
265
+ params = []
266
+ for k, v in data.items():
267
+ if isinstance(v, Field):
268
+ value = v.value
269
+ if value is None:
270
+ if v.created_generated == True or v.update_generated == True:
271
+ value = datetime.datetime.now()
272
+ else:
273
+ value = v.default
274
+ if value is not None:
275
+ keys.append(k)
276
+ params.append(value)
277
+ elif v is not None: # fix sql format %s
278
+ keys.append(k)
279
+ params.append(v)
280
+ return keys, params
281
+
282
+ def _get_batch_keys_values(self, items: list):
283
+ keys = []
284
+ values = []
285
+ item = items[0]
286
+ if isinstance(item, Model):
287
+ keys = item.__dict__.keys()
288
+ elif isinstance(item, dict):
289
+ keys = item.keys()
290
+
291
+ for item in items:
292
+ value = []
293
+ if isinstance(item, Model):
294
+ for k in item.__dict__:
295
+ value.append(item[k].value)
296
+ elif isinstance(item, dict): # for object
297
+ for k, v in item.items():
298
+ value.append(v)
299
+ value = tuple(key for key in value)
300
+ values.append(value)
301
+ return keys, values
302
+
303
+ def _merge_params(self, p):
304
+ if p is not None:
305
+ if self.__params__ is not None:
306
+ p = self.__params__ + p
307
+ self.__params__ = p
308
+
309
+ def _literal(self, op, exp):
310
+ if exp is not None:
311
+ if isinstance(exp, list):
312
+ return f'{op} {",".join(exp)}'
313
+ elif isinstance(exp, Expression) or isinstance(exp, Function):
314
+ q, p = exp.sql()
315
+ self._merge_params(p)
316
+ return f"{op} {q}"
317
+ else:
318
+ # return exp
319
+ return f"{op} {exp}"
320
+ return ""
321
+
322
+ def _sql(self):
323
+ JOIN = self._literal("LEFT JOIN", self.__join__)
324
+ WHERE = self._literal("WHERE", self.__where__)
325
+ GROUPBY = self._literal("GROUP BY", self.__group_by__)
326
+ HAVING = self._literal("HAVING", self.__having__)
327
+ ORDERBY = self._literal("ORDER BY", self.__order_by__)
328
+ LIMIT = self._literal("LIMIT", self.__limit__)
329
+ OFFSET = self._literal("OFFSET", self.__offset__)
330
+ aft = " ".join([JOIN, WHERE, GROUPBY, HAVING, ORDERBY, LIMIT, OFFSET])
331
+ return f"SELECT {self.__cols__} FROM {self.__table__} {aft}"
332
+
333
+ def limit(self, limit: int):
334
+ self.__limit__ = f"{limit}"
335
+ return self
336
+
337
+ def offset(self, offset: int):
338
+ self.__offset__ = f"{offset}"
339
+ return self
340
+
341
+ def test(self):
342
+ return self._sql()
343
+
344
+ async def one(self):
345
+ self.limit(1)
346
+ sql = self._sql()
347
+ sql = self._exchange_sql(sql)
348
+ args = self.__params__
349
+ rs = await self.__pool__.one(sql, args)
350
+ if rs:
351
+ # join 时返回dict
352
+ result = Object(rs) if self.__join__ is not None else self(**rs)
353
+ self._reset()
354
+ return result
355
+ # return self(**rs)
356
+ # return Object(rs)
357
+ # return cls(**rs)
358
+ return None
359
+
360
+ async def all(self):
361
+ sql = self._sql()
362
+ sql = self._exchange_sql(sql)
363
+ args = self.__params__
364
+ self._reset()
365
+ return await self.__pool__.all(sql, args)
366
+
367
+ def _exchange_sql(self, sql: str):
368
+ if self.__ispg:
369
+ sql = sql.replace("CURDATE()", "CURRENT_DATE")
370
+ sql = sql.replace("NOW()", "CURRENT_TIMESTAMP")
371
+
372
+ pattern = r"INTERVAL\s+(\d+)\s+(DAY|MONTH|YEAR|HOUR|MINUTE|SECOND)"
373
+ matches = re.findall(pattern, sql)
374
+
375
+ def replacement(match):
376
+ number = match.group(1)
377
+ unit = match.group(2).lower() # 转换为小写
378
+ return f"INTERVAL '{number} {unit}'"
379
+
380
+ if matches:
381
+ sql = re.sub(pattern, replacement, sql)
382
+
383
+ return sql
384
+
385
+ async def update(self, *args, **kw) -> bool:
386
+ """
387
+ Update data
388
+ """
389
+ table = self.__table__
390
+ # where = self.__where__
391
+ where = self._literal("WHERE", self.__where__)
392
+
393
+ keys, params = self._get_update_key_args("u", args or kw)
394
+
395
+ sql = f"update `{table}` set {keys} {where}"
396
+
397
+ if where is not None and where != "":
398
+ if self.__params__:
399
+ params += self.__params__
400
+ else:
401
+ pk, pkv = self._get_primary()
402
+ if pkv is None:
403
+ for arg in args:
404
+ if isinstance(arg, dict) and pk in arg:
405
+ pkv = arg[pk]
406
+ elif isinstance(arg, Model):
407
+ pkv = arg.get(pk)
408
+
409
+ if pkv is not None:
410
+ sql += f" where `{pk}`=?"
411
+ params.append(pkv)
412
+ else:
413
+ raise "Need where or primary key"
414
+ self._reset()
415
+ sql = self._exchange_sql(sql)
416
+ return await self.__pool__.update(sql, params)
417
+
418
+ async def delete(self) -> bool:
419
+ """
420
+ Delete data
421
+ """
422
+ table = self.__table__
423
+ where = self._literal("WHERE", self.__where__)
424
+ args = self.__params__
425
+ sql = f"delete from `{table}` {where}"
426
+
427
+ if where is None or where == "":
428
+ pk, pkv = self._get_primary()
429
+ if pkv is not None:
430
+ sql += f" where `{pk}`=?"
431
+ args = [pkv]
432
+ else:
433
+ raise "need where or primary key"
434
+ self._reset()
435
+ sql = self._exchange_sql(sql)
436
+ return await self.__pool__.delete(sql, args)
437
+
438
+ async def insert(self, *args, **kw) -> Tuple[bool, int]:
439
+ table = self.__table__
440
+ keys, params = self._get_insert_key_args("i", args or kw)
441
+ escape_keys = [f"`{k}`" for k in keys]
442
+ sql = f"insert into `{table}` ({','.join(escape_keys)}) values ({','.join(['?' for k in keys])})"
443
+ self._reset()
444
+ params = tuple(key for key in params)
445
+ return await self.__pool__.create(sql, params)
446
+
447
+ async def insert_batch(self, items: list):
448
+ table = self.__table__
449
+ if len(items) == 0:
450
+ return 0
451
+ keys, params = self._get_batch_keys_values(items)
452
+ escape_keys = [f"`{k}`" for k in keys]
453
+ sql = f"insert into `{table}` ({','.join(escape_keys)}) values ({','.join(['?' for k in keys])})"
454
+ self._reset()
455
+ return await self.__pool__.create_batch(sql, params)
456
+
457
+ async def count(self) -> int:
458
+ __where__ = copy.copy(self.__where__)
459
+ __join__ = copy.copy(self.__join__)
460
+ cls = copy.deepcopy(self)
461
+ JOIN = cls._literal("LEFT JOIN", __join__)
462
+ WHERE = cls._literal("WHERE", __where__)
463
+ GROUPBY = self._literal("GROUP BY", self.__group_by__)
464
+ aft = " ".join([JOIN, WHERE, GROUPBY])
465
+ sql = f"SELECT COUNT(*) FROM {cls.__table__} {aft}"
466
+ args = cls.__params__
467
+ sql = self._exchange_sql(sql)
468
+ if GROUPBY is not None and GROUPBY != "":
469
+ return await cls.__pool__.group_count(sql, args)
470
+ return await cls.__pool__.count(sql, args)
471
+
472
+
473
+ class Models(object):
474
+ class CharField(Field):
475
+ def __init__(
476
+ self,
477
+ name=None,
478
+ primary_key=False,
479
+ default=None,
480
+ charset=None,
481
+ max_length=None,
482
+ not_null=False,
483
+ comment=None,
484
+ ):
485
+ super().__init__(
486
+ name,
487
+ "char",
488
+ default,
489
+ primary_key,
490
+ charset=charset,
491
+ max_length=max_length,
492
+ not_null=not_null,
493
+ comment=comment,
494
+ )
495
+
496
+ class VarCharField(Field):
497
+ def __init__(
498
+ self,
499
+ name=None,
500
+ primary_key=False,
501
+ default=None,
502
+ charset=None,
503
+ max_length=None,
504
+ not_null=False,
505
+ comment=None,
506
+ ):
507
+ super().__init__(
508
+ name,
509
+ "varchar",
510
+ default,
511
+ primary_key,
512
+ charset=charset,
513
+ max_length=max_length,
514
+ not_null=not_null,
515
+ comment=comment,
516
+ )
517
+
518
+ class BooleanField(Field):
519
+ def __init__(
520
+ self, name=None, default=False, not_null=False, comment=None, unsigned=False
521
+ ):
522
+ super().__init__(
523
+ name,
524
+ "boolean",
525
+ default,
526
+ not_null=not_null,
527
+ unsigned=unsigned,
528
+ comment=comment,
529
+ )
530
+
531
+ class IntegerField(Field):
532
+ def __init__(
533
+ self,
534
+ name=None,
535
+ primary_key=False,
536
+ default=None,
537
+ auto_increment=False,
538
+ not_null=False,
539
+ unsigned=False,
540
+ comment=None,
541
+ max_length=None,
542
+ ):
543
+ super().__init__(
544
+ name,
545
+ "int",
546
+ default,
547
+ primary_key,
548
+ auto_increment=auto_increment,
549
+ not_null=not_null,
550
+ unsigned=unsigned,
551
+ comment=comment,
552
+ max_length=max_length,
553
+ )
554
+
555
+ class BigIntegerField(Field):
556
+ def __init__(
557
+ self,
558
+ name=None,
559
+ primary_key=False,
560
+ default=None,
561
+ auto_increment=False,
562
+ not_null=False,
563
+ unsigned=False,
564
+ comment=None,
565
+ max_length=None,
566
+ ):
567
+ super().__init__(
568
+ name,
569
+ "bigint",
570
+ default,
571
+ primary_key,
572
+ auto_increment=auto_increment,
573
+ NOT_NULL=not_null,
574
+ unsigned=unsigned,
575
+ comment=comment,
576
+ max_length=max_length,
577
+ )
578
+
579
+ class DoubleField(Field):
580
+ def __init__(
581
+ self,
582
+ name=None,
583
+ default=None,
584
+ not_null=False,
585
+ max_length=None,
586
+ unsigned=False,
587
+ comment=None,
588
+ ):
589
+ super().__init__(
590
+ name,
591
+ "double",
592
+ default,
593
+ NOT_NULL=not_null,
594
+ max_length=max_length,
595
+ unsigned=unsigned,
596
+ comment=comment,
597
+ )
598
+
599
+ class FloatField(Field):
600
+ def __init__(
601
+ self,
602
+ name=None,
603
+ default=None,
604
+ not_null=False,
605
+ max_length=None,
606
+ scale_length=None,
607
+ unsigned=False,
608
+ comment=None,
609
+ ):
610
+ super().__init__(
611
+ name,
612
+ "float",
613
+ default,
614
+ NOT_NULL=not_null,
615
+ max_length=max_length,
616
+ scale_length=scale_length,
617
+ unsigned=unsigned,
618
+ comment=comment,
619
+ )
620
+
621
+ class NumericField(Field):
622
+ def __init__(
623
+ self,
624
+ name=None,
625
+ default=0.0,
626
+ not_null=False,
627
+ max_length=None,
628
+ scale_length=None,
629
+ unsigned=False,
630
+ comment=None,
631
+ ):
632
+ super().__init__(
633
+ name,
634
+ "numeric",
635
+ default,
636
+ NOT_NULL=not_null,
637
+ unsigned=unsigned,
638
+ max_length=max_length,
639
+ scale_length=scale_length,
640
+ comment=comment,
641
+ )
642
+
643
+ class DecimalField(Field):
644
+ def __init__(
645
+ self,
646
+ name=None,
647
+ default=0.0,
648
+ not_null=False,
649
+ max_length=None,
650
+ scale_length=None,
651
+ unsigned=False,
652
+ comment=None,
653
+ ):
654
+ super().__init__(
655
+ name,
656
+ "decimal",
657
+ default,
658
+ NOT_NULL=not_null,
659
+ unsigned=unsigned,
660
+ max_length=max_length,
661
+ scale_length=scale_length,
662
+ comment=comment,
663
+ )
664
+
665
+ class TextField(Field):
666
+ def __init__(
667
+ self,
668
+ name=None,
669
+ default=None,
670
+ charset=None,
671
+ max_length=None,
672
+ not_null=False,
673
+ comment=None,
674
+ ):
675
+ super().__init__(
676
+ name,
677
+ "text",
678
+ default,
679
+ charset=charset,
680
+ max_length=max_length,
681
+ NOT_NULL=not_null,
682
+ comment=comment,
683
+ )
684
+
685
+ class LongTextField(Field):
686
+ def __init__(
687
+ self,
688
+ name=None,
689
+ default=None,
690
+ charset=None,
691
+ max_length=None,
692
+ not_null=False,
693
+ comment=None,
694
+ ):
695
+ super().__init__(
696
+ name,
697
+ "longtext",
698
+ default,
699
+ charset=charset,
700
+ max_length=max_length,
701
+ NOT_NULL=not_null,
702
+ comment=comment,
703
+ )
704
+
705
+ class MediumTextField(Field):
706
+ def __init__(
707
+ self,
708
+ name=None,
709
+ default=None,
710
+ charset=None,
711
+ max_length=None,
712
+ not_null=False,
713
+ comment=None,
714
+ ):
715
+ super().__init__(
716
+ name,
717
+ "mediumtext",
718
+ default,
719
+ charset=charset,
720
+ max_length=max_length,
721
+ NOT_NULL=not_null,
722
+ comment=comment,
723
+ )
724
+
725
+ class DatetimeField(Field):
726
+ def __init__(
727
+ self,
728
+ name=None,
729
+ default=None,
730
+ max_length=None,
731
+ not_null=False,
732
+ created_generated=False,
733
+ update_generated=False,
734
+ comment=None,
735
+ ):
736
+ super().__init__(
737
+ name,
738
+ "datetime",
739
+ default,
740
+ max_length=max_length,
741
+ NOT_NULL=not_null,
742
+ created_generated=created_generated,
743
+ update_generated=update_generated,
744
+ comment=comment,
745
+ )
746
+
747
+ class DateField(Field):
748
+ def __init__(
749
+ self,
750
+ name=None,
751
+ default=None,
752
+ max_length=None,
753
+ not_null=False,
754
+ created_generated=False,
755
+ update_generated=False,
756
+ comment=None,
757
+ ):
758
+ super().__init__(
759
+ name,
760
+ "date",
761
+ default,
762
+ max_length=max_length,
763
+ NOT_NULL=not_null,
764
+ created_generated=created_generated,
765
+ update_generated=update_generated,
766
+ comment=comment,
767
+ )
768
+
769
+ class TimestampField(Field):
770
+ def __init__(
771
+ self,
772
+ name=None,
773
+ default=None,
774
+ max_length=None,
775
+ not_null=False,
776
+ created_generated=False,
777
+ update_generated=False,
778
+ comment=None,
779
+ ):
780
+ super().__init__(
781
+ name,
782
+ "timestamp",
783
+ default,
784
+ False,
785
+ max_length=max_length,
786
+ NOT_NULL=not_null,
787
+ created_generated=created_generated,
788
+ update_generated=update_generated,
789
+ comment=comment,
790
+ )
791
+
792
+ class JsonField(Field):
793
+ def __init__(
794
+ self, name=None, default=None, charset=None, not_null=False, comment=None
795
+ ):
796
+ super().__init__(
797
+ name,
798
+ "json",
799
+ default,
800
+ charset=charset,
801
+ NOT_NULL=not_null,
802
+ comment=comment,
803
+ )
804
+
805
+
806
+ models = Models()