reydb 1.1.58__py3-none-any.whl → 1.1.59__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.
reydb/rorm.py CHANGED
@@ -12,18 +12,31 @@
12
12
  from typing import Self, Any, Type, TypeVar, Generic, Final, overload
13
13
  from collections.abc import Callable
14
14
  from functools import wraps as functools_wraps
15
+ from inspect import iscoroutinefunction as inspect_iscoroutinefunction
15
16
  from pydantic import ConfigDict, field_validator as pydantic_field_validator, model_validator as pydantic_model_validator
16
17
  from sqlalchemy.orm import SessionTransaction
18
+ from sqlalchemy.ext.asyncio import AsyncSessionTransaction
17
19
  from sqlalchemy.sql import sqltypes
18
20
  from sqlalchemy.sql.sqltypes import TypeEngine
19
21
  from sqlalchemy.sql.dml import Insert, Update, Delete
20
22
  from sqlmodel import SQLModel, Session, Table
21
- from sqlmodel.main import SQLModelMetaclass, FieldInfo
23
+ from sqlmodel.ext.asyncio.session import AsyncSession
24
+ from sqlmodel.main import SQLModelMetaclass, FieldInfo, default_registry
22
25
  from sqlmodel.sql._expression_select_cls import SelectOfScalar as Select
23
- from reykit.rbase import CallableT, Null, is_instance
26
+ from reykit.rbase import CallableT, Null, throw, is_instance
24
27
 
25
28
  from . import rdb
26
- from .rbase import DatabaseBase
29
+ from .rbase import (
30
+ SessionT,
31
+ SessionTransactionT,
32
+ DatabaseT,
33
+ DatabaseORMT,
34
+ DatabaseORMStatementSelectT,
35
+ DatabaseORMStatementInsertT,
36
+ DatabaseORMStatementUpdateT,
37
+ DatabaseORMStatementDeleteT,
38
+ DatabaseBase
39
+ )
27
40
 
28
41
 
29
42
  __all__ = (
@@ -31,17 +44,29 @@ __all__ = (
31
44
  'DatabaseORMModelMeta',
32
45
  'DatabaseORMModel',
33
46
  'DatabaseORMModelField',
47
+ 'DatabaseORMSuper',
34
48
  'DatabaseORM',
49
+ 'DatabaseORMAsync',
50
+ 'DatabaseORMSessionSuper',
35
51
  'DatabaseORMSession',
52
+ 'DatabaseORMSessionAsync',
53
+ 'DatabaseORMStatementSuper',
36
54
  'DatabaseORMStatement',
55
+ 'DatabaseORMStatementAsync',
37
56
  'DatabaseORMStatementSelect',
38
57
  'DatabaseORMStatementInsert',
39
58
  'DatabaseORMStatementUpdate',
40
- 'DatabaseORMStatementDelete'
59
+ 'DatabaseORMStatementDelete',
60
+ 'DatabaseORMStatementSelectAsync',
61
+ 'DatabaseORMStatementInsertAsync',
62
+ 'DatabaseORMStatementUpdateAsync',
63
+ 'DatabaseORMStatementDeleteAsync'
41
64
  )
42
65
 
43
66
 
44
- ModelT = TypeVar('ModelT', bound='DatabaseORMModel')
67
+ DatabaseORMModelT = TypeVar('DatabaseORMModelT', bound='DatabaseORMModel')
68
+ DatabaseORMSessionT = TypeVar('DatabaseORMSessionT', 'DatabaseORMSession', 'DatabaseORMSessionAsync')
69
+ DatabaseORMStatementReturn = TypeVar('DatabaseORMStatementReturn')
45
70
 
46
71
 
47
72
  class DatabaseORMBase(DatabaseBase):
@@ -351,25 +376,31 @@ class DatabaseORMModelField(DatabaseBase, FieldInfo):
351
376
  super().__init__(**kwargs)
352
377
 
353
378
 
354
- class DatabaseORM(DatabaseORMBase):
379
+ class DatabaseORMSuper(DatabaseORMBase, Generic[DatabaseT, DatabaseORMSessionT]):
355
380
  """
356
- Database ORM type.
381
+ Database ORM super type.
357
382
 
358
383
  Attributes
359
384
  ----------
385
+ metaData : Registry metadata instance.
360
386
  DatabaseModel : Database ORM model type.
361
- Field : Factory function of database ORM model field.
387
+ Field : Database ORM model field type.
388
+ Config : Database ORM model config type.
389
+ types : Database ORM model filed types module.
390
+ wrap_validate_model : Create decorator of validate database ORM model.
391
+ wrap_validate_filed : Create decorator of validate database ORM model field.
362
392
  """
363
393
 
394
+ metaData = default_registry.metadata
364
395
  Model = DatabaseORMModel
365
396
  Field = DatabaseORMModelField
366
397
  Config = ConfigDict
367
398
  tyeps = sqltypes
368
- wrap_validate_filed = pydantic_field_validator
369
399
  wrap_validate_model = pydantic_model_validator
400
+ wrap_validate_filed = pydantic_field_validator
370
401
 
371
402
 
372
- def __init__(self, db: 'rdb.Database') -> None:
403
+ def __init__(self, db: DatabaseT) -> None:
373
404
  """
374
405
  Build instance attributes.
375
406
 
@@ -380,16 +411,22 @@ class DatabaseORM(DatabaseORMBase):
380
411
 
381
412
  # Build.
382
413
  self.db = db
383
- self._session = self.session(True)
414
+ self.__sess = self.session(True)
384
415
 
385
416
  ## Method.
386
- self.get = self._session.get
387
- self.gets = self._session.gets
388
- self.all = self._session.all
389
- self.add = self._session.add
417
+ self.create = self.__sess.create
418
+ self.drop = self.__sess.drop
419
+ self.get = self.__sess.get
420
+ self.gets = self.__sess.gets
421
+ self.all = self.__sess.all
422
+ self.add = self.__sess.add
423
+ self.select = self.__sess.select
424
+ self.insert = self.__sess.insert
425
+ self.update = self.__sess.update
426
+ self.delete = self.__sess.delete
390
427
 
391
428
 
392
- def session(self, autocommit: bool = False):
429
+ def session(self, autocommit: bool = False) -> DatabaseORMSessionT:
393
430
  """
394
431
  Build DataBase ORM session instance.
395
432
 
@@ -403,68 +440,67 @@ class DatabaseORM(DatabaseORMBase):
403
440
  """
404
441
 
405
442
  # Build.
406
- sess = DatabaseORMSession(self, autocommit)
443
+ match self:
444
+ case DatabaseORM():
445
+ sess = DatabaseORMSession(self, autocommit)
446
+ case DatabaseORMAsync():
447
+ sess = DatabaseORMSessionAsync(self, autocommit)
407
448
 
408
449
  return sess
409
450
 
410
451
 
411
- def create(
412
- self,
413
- *models: Type[DatabaseORMModel] | DatabaseORMModel,
414
- skip: bool = False
415
- ) -> None:
416
- """
417
- Create table.
418
-
419
- Parameters
420
- ----------
421
- models : ORM model instances.
422
- check : Skip existing table and not mapping model.
423
- """
424
-
425
- # Create.
426
- for model in models:
427
- table = model.table()
428
- if (
429
- not skip
430
- or table is not None
431
- ):
432
- table.create(self.db.engine, checkfirst=skip)
452
+ class DatabaseORM(DatabaseORMSuper['rdb.Database', 'DatabaseORMSession']):
453
+ """
454
+ Database ORM type.
433
455
 
456
+ Attributes
457
+ ----------
458
+ metaData : Registry metadata instance.
459
+ DatabaseModel : Database ORM model type.
460
+ Field : Database ORM model field type.
461
+ Config : Database ORM model config type.
462
+ types : Database ORM model filed types module.
463
+ wrap_validate_model : Create decorator of validate database ORM model.
464
+ wrap_validate_filed : Create decorator of validate database ORM model field.
465
+ """
434
466
 
435
- def drop(
436
- self,
437
- *models: Type[DatabaseORMModel] | DatabaseORMModel,
438
- skip: bool = False
439
- ) -> None:
440
- """
441
- Delete table.
442
467
 
443
- Parameters
444
- ----------
445
- models : ORM model instances.
446
- check : Skip not exist table and not mapping model.
447
- """
468
+ class DatabaseORMAsync(DatabaseORMSuper['rdb.DatabaseAsync', 'DatabaseORMSessionAsync']):
469
+ """
470
+ Asynchronous database ORM type.
448
471
 
449
- # Create.
450
- for model in models:
451
- table = model.table()
452
- if (
453
- not skip
454
- or table is not None
455
- ):
456
- table.drop(self.db.engine, checkfirst=skip)
472
+ Attributes
473
+ ----------
474
+ metaData : Registry metadata instance.
475
+ DatabaseModel : Database ORM model type.
476
+ Field : Database ORM model field type.
477
+ Config : Database ORM model config type.
478
+ types : Database ORM model filed types module.
479
+ wrap_validate_model : Create decorator of validate database ORM model.
480
+ wrap_validate_filed : Create decorator of validate database ORM model field.
481
+ """
457
482
 
458
483
 
459
- class DatabaseORMSession(DatabaseORMBase):
484
+ class DatabaseORMSessionSuper(
485
+ DatabaseORMBase,
486
+ Generic[
487
+ DatabaseORMT,
488
+ SessionT,
489
+ SessionTransactionT,
490
+ DatabaseORMStatementSelectT,
491
+ DatabaseORMStatementInsertT,
492
+ DatabaseORMStatementUpdateT,
493
+ DatabaseORMStatementDeleteT
494
+ ]
495
+ ):
460
496
  """
461
- Database ORM session type, based ORM model.
497
+ Database ORM session super type.
462
498
  """
463
499
 
464
500
 
465
501
  def __init__(
466
502
  self,
467
- orm: 'DatabaseORM',
503
+ orm: DatabaseORMT,
468
504
  autocommit: bool = False
469
505
  ) -> None:
470
506
  """
@@ -479,41 +515,132 @@ class DatabaseORMSession(DatabaseORMBase):
479
515
  # Build.
480
516
  self.orm = orm
481
517
  self.autocommit = autocommit
482
- self.session: Session | None = None
483
- self.begin: SessionTransaction | None = None
518
+ self.sess: SessionT | None = None
519
+ self.begin: SessionTransactionT | None = None
484
520
 
485
521
 
486
- def commit(self) -> None:
522
+ def select(self, model: Type[DatabaseORMModelT] | DatabaseORMModelT) -> DatabaseORMStatementSelectT:
487
523
  """
488
- Commit cumulative executions.
524
+ Build database ORM select instance.
525
+
526
+ Parameters
527
+ ----------
528
+ model : ORM model instance.
529
+
530
+ Returns
531
+ -------
532
+ Instance.
489
533
  """
490
534
 
491
- # Commit.
492
- if self.begin is not None:
493
- self.begin.commit()
494
- self.begin = None
535
+ # Handle parameter.
536
+ if is_instance(model):
537
+ model = type(model)
495
538
 
539
+ # Build.
540
+ match self:
541
+ case DatabaseORMSession():
542
+ select = DatabaseORMStatementSelect[DatabaseORMModelT](self, model)
543
+ case DatabaseORMSessionAsync():
544
+ select = DatabaseORMStatementSelectAsync[DatabaseORMModelT](self, model)
496
545
 
497
- def rollback(self) -> None:
546
+ return select
547
+
548
+
549
+ def insert(self, model: Type[DatabaseORMModelT] | DatabaseORMModelT) -> DatabaseORMStatementInsertT:
498
550
  """
499
- Rollback cumulative executions.
551
+ Build database ORM insert instance.
552
+
553
+ Parameters
554
+ ----------
555
+ model : ORM model instance.
556
+
557
+ Returns
558
+ -------
559
+ Instance.
500
560
  """
561
+ print(model)
562
+ # Handle parameter.
563
+ if is_instance(model):
564
+ model = type(model)
501
565
 
502
- # Rollback.
503
- if self.begin is not None:
504
- self.begin.rollback()
505
- self.begin = None
566
+ # Build.
567
+ match self:
568
+ case DatabaseORMSession():
569
+ insert = DatabaseORMStatementInsert[DatabaseORMModelT](self, model)
570
+ case DatabaseORMSessionAsync():
571
+ insert = DatabaseORMStatementInsertAsync[DatabaseORMModelT](self, model)
506
572
 
573
+ return insert
507
574
 
508
- def close(self) -> None:
575
+
576
+ def update(self, model: Type[DatabaseORMModelT] | DatabaseORMModelT) -> DatabaseORMStatementUpdateT:
577
+ """
578
+ Build database ORM update instance.
579
+
580
+ Parameters
581
+ ----------
582
+ model : ORM model instance.
583
+
584
+ Returns
585
+ -------
586
+ Instance.
509
587
  """
510
- Close database connection.
588
+
589
+ # Handle parameter.
590
+ if is_instance(model):
591
+ model = type(model)
592
+
593
+ # Build.
594
+ match self:
595
+ case DatabaseORMSession():
596
+ update = DatabaseORMStatementUpdate[DatabaseORMModelT](self, model)
597
+ case DatabaseORMSessionAsync():
598
+ update = DatabaseORMStatementUpdateAsync[DatabaseORMModelT](self, model)
599
+
600
+ return update
601
+
602
+
603
+ def delete(self, model: Type[DatabaseORMModelT] | DatabaseORMModelT) -> DatabaseORMStatementDeleteT:
511
604
  """
605
+ Build database ORM delete instance.
512
606
 
513
- # Close.
514
- if self.session is not None:
515
- self.session.close()
516
- self.session = None
607
+ Parameters
608
+ ----------
609
+ model : ORM model instance.
610
+
611
+ Returns
612
+ -------
613
+ Instance.
614
+ """
615
+
616
+ # Handle parameter.
617
+ if is_instance(model):
618
+ model = type(model)
619
+
620
+ # Build.
621
+ match self:
622
+ case DatabaseORMSession():
623
+ delete = DatabaseORMStatementDelete[DatabaseORMModelT](self, model)
624
+ case DatabaseORMSessionAsync():
625
+ delete = DatabaseORMStatementDeleteAsync[DatabaseORMModelT](self, model)
626
+
627
+ return delete
628
+
629
+
630
+ class DatabaseORMSession(
631
+ DatabaseORMSessionSuper[
632
+ DatabaseORM,
633
+ Session,
634
+ SessionTransaction,
635
+ 'DatabaseORMStatementSelect',
636
+ 'DatabaseORMStatementInsert',
637
+ 'DatabaseORMStatementUpdate',
638
+ 'DatabaseORMStatementDelete'
639
+ ]
640
+ ):
641
+ """
642
+ Database ORM session type.
643
+ """
517
644
 
518
645
 
519
646
  def __enter__(self) -> Self:
@@ -546,11 +673,76 @@ class DatabaseORMSession(DatabaseORMBase):
546
673
  self.commit()
547
674
 
548
675
  # Close.
549
- else:
550
- self.close()
676
+ self.close()
551
677
 
552
678
 
553
- __del__ = close
679
+ def get_sess(self) -> Session:
680
+ """
681
+ Get `Session` instance.
682
+
683
+ Returns
684
+ -------
685
+ Instance.
686
+ """
687
+
688
+ # Create.
689
+ if self.sess is None:
690
+ self.sess = Session(self.orm.db.engine)
691
+
692
+ return self.sess
693
+
694
+
695
+ def get_begin(self) -> SessionTransaction:
696
+ """
697
+ Get `SessionTransaction` instance.
698
+
699
+ Returns
700
+ -------
701
+ Instance.
702
+ """
703
+
704
+ # Create.
705
+ if self.begin is None:
706
+ conn = self.get_sess()
707
+ self.begin = conn.begin()
708
+
709
+ return self.begin
710
+
711
+
712
+ def commit(self) -> None:
713
+ """
714
+ Commit cumulative executions.
715
+ """
716
+
717
+ # Commit.
718
+ if self.begin is not None:
719
+ self.begin.commit()
720
+ self.begin = None
721
+
722
+
723
+ def rollback(self) -> None:
724
+ """
725
+ Rollback cumulative executions.
726
+ """
727
+
728
+ # Rollback.
729
+ if self.begin is not None:
730
+ self.begin.rollback()
731
+ self.begin = None
732
+
733
+
734
+ def close(self) -> None:
735
+ """
736
+ Close database session.
737
+ """
738
+
739
+ # Close.
740
+ if self.begin is not None:
741
+ self.begin.close()
742
+ self.begin = None
743
+ if self.sess is not None:
744
+ self.sess.close()
745
+ self.sess = None
554
746
 
555
747
 
556
748
  def wrap_transact(method: CallableT) -> CallableT:
@@ -572,12 +764,12 @@ class DatabaseORMSession(DatabaseORMBase):
572
764
  def wrap(self: 'DatabaseORMSession', *args, **kwargs):
573
765
 
574
766
  # Session.
575
- if self.session is None:
576
- self.session = Session(self.orm.db.engine)
767
+ if self.sess is None:
768
+ self.sess = Session(self.orm.db.engine)
577
769
 
578
770
  # Begin.
579
771
  if self.begin is None:
580
- self.begin = self.session.begin()
772
+ self.begin = self.sess.begin()
581
773
 
582
774
  # Execute.
583
775
  result = method(self, *args, **kwargs)
@@ -605,13 +797,21 @@ class DatabaseORMSession(DatabaseORMBase):
605
797
  Parameters
606
798
  ----------
607
799
  models : ORM model instances.
608
- check : Skip existing table.
800
+ skip : Skip existing table.
609
801
  """
610
802
 
803
+ # Handle parameter.
804
+ tables = [
805
+ model.table()
806
+ for model in models
807
+ ]
808
+
809
+ ## Check.
810
+ if None in tables:
811
+ throw(ValueError, tables)
812
+
611
813
  # Create.
612
- for model in models:
613
- table = model.table()
614
- table.create(self.session.connection(), checkfirst=skip)
814
+ self.orm.metaData.create_all(self.orm.db.engine, tables, skip)
615
815
 
616
816
 
617
817
  @wrap_transact
@@ -626,17 +826,25 @@ class DatabaseORMSession(DatabaseORMBase):
626
826
  Parameters
627
827
  ----------
628
828
  models : ORM model instances.
629
- check : Skip not exist table.
829
+ skip : Skip not exist table.
630
830
  """
631
831
 
832
+ # Handle parameter.
833
+ tables = [
834
+ model.table()
835
+ for model in models
836
+ ]
837
+
838
+ ## Check.
839
+ if None in tables:
840
+ throw(ValueError, tables)
841
+
632
842
  # Create.
633
- for model in models:
634
- table = model.table()
635
- table.drop(self.session.connection(), checkfirst=skip)
843
+ self.orm.metaData.drop_all(self.orm.db.engine, tables, skip)
636
844
 
637
845
 
638
846
  @wrap_transact
639
- def get(self, model: Type[ModelT] | ModelT, key: Any | tuple[Any]) -> ModelT | None:
847
+ def get(self, model: Type[DatabaseORMModelT] | DatabaseORMModelT, key: Any | tuple[Any]) -> DatabaseORMModelT | None:
640
848
  """
641
849
  Select records by primary key.
642
850
 
@@ -657,20 +865,20 @@ class DatabaseORMSession(DatabaseORMBase):
657
865
  model = type(model)
658
866
 
659
867
  # Get.
660
- result = self.session.get(model, key)
868
+ result = self.sess.get(model, key)
661
869
 
662
870
  # Autucommit.
663
871
  if (
664
872
  self.autocommit
665
873
  and result is not None
666
874
  ):
667
- self.session.expunge(result)
875
+ self.sess.expunge(result)
668
876
 
669
877
  return result
670
878
 
671
879
 
672
880
  @wrap_transact
673
- def gets(self, model: Type[ModelT] | ModelT, *keys: Any | tuple[Any]) -> list[ModelT]:
881
+ def gets(self, model: Type[DatabaseORMModelT] | DatabaseORMModelT, *keys: Any | tuple[Any]) -> list[DatabaseORMModelT]:
674
882
  """
675
883
  Select records by primary key sequence.
676
884
 
@@ -694,14 +902,14 @@ class DatabaseORMSession(DatabaseORMBase):
694
902
  results = [
695
903
  result
696
904
  for key in keys
697
- if (result := self.session.get(model, key)) is not None
905
+ if (result := self.sess.get(model, key)) is not None
698
906
  ]
699
907
 
700
908
  return results
701
909
 
702
910
 
703
911
  @wrap_transact
704
- def all(self, model: Type[ModelT] | ModelT) -> list[ModelT]:
912
+ def all(self, model: Type[DatabaseORMModelT] | DatabaseORMModelT) -> list[DatabaseORMModelT]:
705
913
  """
706
914
  Select all records.
707
915
 
@@ -720,7 +928,7 @@ class DatabaseORMSession(DatabaseORMBase):
720
928
 
721
929
  # Get.
722
930
  select = Select(model)
723
- models = self.session.exec(select)
931
+ models = self.sess.exec(select)
724
932
  models = list(models)
725
933
 
726
934
  return models
@@ -737,7 +945,7 @@ class DatabaseORMSession(DatabaseORMBase):
737
945
  """
738
946
 
739
947
  # Add.
740
- self.session.add_all(models)
948
+ self.sess.add_all(models)
741
949
 
742
950
 
743
951
  @wrap_transact
@@ -752,7 +960,7 @@ class DatabaseORMSession(DatabaseORMBase):
752
960
 
753
961
  # Delete.
754
962
  for model in models:
755
- self.session.delete(model)
963
+ self.sess.delete(model)
756
964
 
757
965
 
758
966
  @wrap_transact
@@ -767,7 +975,7 @@ class DatabaseORMSession(DatabaseORMBase):
767
975
 
768
976
  # Refresh.
769
977
  for model in models:
770
- self.session.refresh(model)
978
+ self.sess.refresh(model)
771
979
 
772
980
 
773
981
  @wrap_transact
@@ -782,115 +990,387 @@ class DatabaseORMSession(DatabaseORMBase):
782
990
 
783
991
  # Refresh.
784
992
  for model in models:
785
- self.session.expire(model)
993
+ self.sess.expire(model)
994
+
995
+
996
+ class DatabaseORMSessionAsync(
997
+ DatabaseORMSessionSuper[
998
+ DatabaseORMAsync,
999
+ AsyncSession,
1000
+ AsyncSessionTransaction,
1001
+ 'DatabaseORMStatementSelectAsync',
1002
+ 'DatabaseORMStatementInsertAsync',
1003
+ 'DatabaseORMStatementUpdateAsync',
1004
+ 'DatabaseORMStatementDeleteAsync'
1005
+ ]
1006
+ ):
1007
+ """
1008
+ Asynchronous database ORM session type.
1009
+ """
786
1010
 
787
1011
 
788
- @wrap_transact
789
- def select(self, model: Type[ModelT] | ModelT):
1012
+ async def __aenter__(self) -> Self:
1013
+ """
1014
+ Asynchronous enter syntax `with`.
1015
+
1016
+ Returns
1017
+ -------
1018
+ Self.
1019
+ """
1020
+
1021
+ return self
1022
+
1023
+
1024
+ async def __aexit__(
1025
+ self,
1026
+ exc_type: type[BaseException] | None,
1027
+ *_
1028
+ ) -> None:
790
1029
  """
791
- Build `DatabaseORMSelect` instance.
1030
+ Asynchronous exit syntax `with`.
792
1031
 
793
1032
  Parameters
794
1033
  ----------
795
- model : ORM model instance.
1034
+ exc_type : Exception type.
1035
+ """
1036
+
1037
+ # Commit.
1038
+ if exc_type is None:
1039
+ await self.commit()
1040
+
1041
+ # Close.
1042
+ await self.close()
1043
+ await self.orm.db.dispose()
1044
+
1045
+
1046
+ def get_sess(self) -> AsyncSession:
1047
+ """
1048
+ Get `AsyncSession` instance.
796
1049
 
797
1050
  Returns
798
1051
  -------
799
1052
  Instance.
800
1053
  """
801
1054
 
1055
+ # Create.
1056
+ if self.sess is None:
1057
+ self.sess = AsyncSession(self.orm.db.engine)
1058
+
1059
+ return self.sess
1060
+
1061
+
1062
+ async def get_begin(self) -> AsyncSessionTransaction:
1063
+ """
1064
+ Asynchronous get `AsyncSessionTransaction` instance.
1065
+
1066
+ Returns
1067
+ -------
1068
+ Instance.
1069
+ """
1070
+
1071
+ # Create.
1072
+ if self.begin is None:
1073
+ sess = self.get_sess()
1074
+ self.begin = await sess.begin()
1075
+
1076
+ return self.begin
1077
+
1078
+
1079
+ async def commit(self) -> None:
1080
+ """
1081
+ Asynchronous commit cumulative executions.
1082
+ """
1083
+
1084
+ # Commit.
1085
+ if self.begin is not None:
1086
+ await self.begin.commit()
1087
+ self.begin = None
1088
+
1089
+
1090
+ async def rollback(self) -> None:
1091
+ """
1092
+ Asynchronous rollback cumulative executions.
1093
+ """
1094
+
1095
+ # Rollback.
1096
+ if self.begin is not None:
1097
+ await self.begin.rollback()
1098
+ self.begin = None
1099
+
1100
+
1101
+ async def close(self) -> None:
1102
+ """
1103
+ Asynchronous close database session.
1104
+ """
1105
+
1106
+ # Close.
1107
+ if self.begin is not None:
1108
+ await self.begin.rollback()
1109
+ self.begin = None
1110
+ if self.sess is not None:
1111
+ await self.sess.close()
1112
+ self.sess = None
1113
+
1114
+
1115
+ def wrap_transact(method: CallableT) -> CallableT:
1116
+ """
1117
+ Asynchronous decorator, automated transaction.
1118
+
1119
+ Parameters
1120
+ ----------
1121
+ method : Method.
1122
+
1123
+ Returns
1124
+ -------
1125
+ Decorated method.
1126
+ """
1127
+
1128
+
1129
+ # Define.
1130
+ @functools_wraps(method)
1131
+ async def wrap(self: 'DatabaseORMSessionAsync', *args, **kwargs):
1132
+
1133
+ # Transaction.
1134
+ await self.get_begin()
1135
+
1136
+ # Execute.
1137
+ if inspect_iscoroutinefunction(method):
1138
+ result = await method(self, *args, **kwargs)
1139
+ else:
1140
+ result = method(self, *args, **kwargs)
1141
+
1142
+ # Automatic commit.
1143
+ if self.autocommit:
1144
+ await self.commit()
1145
+ await self.close()
1146
+ await self.orm.db.dispose()
1147
+
1148
+ return result
1149
+
1150
+
1151
+ return wrap
1152
+
1153
+
1154
+ @wrap_transact
1155
+ async def create(
1156
+ self,
1157
+ *models: Type[DatabaseORMModel] | DatabaseORMModel,
1158
+ skip: bool = False
1159
+ ) -> None:
1160
+ """
1161
+ Asynchronous create table.
1162
+
1163
+ Parameters
1164
+ ----------
1165
+ models : ORM model instances.
1166
+ skip : Skip existing table.
1167
+ """
1168
+
802
1169
  # Handle parameter.
803
- if is_instance(model):
804
- model = type(model)
1170
+ tables = [
1171
+ model.table()
1172
+ for model in models
1173
+ ]
805
1174
 
806
- # Build.
807
- select = DatabaseORMStatementSelect[ModelT](self, model)
1175
+ ## Check.
1176
+ if None in tables:
1177
+ throw(ValueError, tables)
808
1178
 
809
- return select
1179
+ # Create.
1180
+ conn = await self.sess.connection()
1181
+ await conn.run_sync(self.orm.metaData.create_all, tables, skip)
810
1182
 
811
1183
 
812
1184
  @wrap_transact
813
- def insert(self, model: Type[ModelT] | ModelT):
1185
+ async def drop(
1186
+ self,
1187
+ *models: Type[DatabaseORMModel] | DatabaseORMModel,
1188
+ skip: bool = False
1189
+ ) -> None:
814
1190
  """
815
- Build `DatabaseORMInsert` instance.
1191
+ Asynchronous delete table.
816
1192
 
817
1193
  Parameters
818
1194
  ----------
819
- model : ORM model instance.
1195
+ models : ORM model instances.
1196
+ skip : Skip not exist table.
1197
+ """
1198
+
1199
+ # Handle parameter.
1200
+ tables = [
1201
+ model.table()
1202
+ for model in models
1203
+ ]
1204
+
1205
+ ## Check.
1206
+ if None in tables:
1207
+ throw(ValueError, tables)
1208
+
1209
+ # Create.
1210
+ conn = await self.sess.connection()
1211
+ await conn.run_sync(self.orm.metaData.drop_all, tables, skip)
1212
+
1213
+
1214
+ @wrap_transact
1215
+ async def get(self, model: Type[DatabaseORMModelT] | DatabaseORMModelT, key: Any | tuple[Any]) -> DatabaseORMModelT | None:
1216
+ """
1217
+ Asynchronous select records by primary key.
1218
+
1219
+ Parameters
1220
+ ----------
1221
+ model : ORM model type or instance.
1222
+ key : Primary key.
1223
+ - `Any`: Single primary key.
1224
+ - `tuple[Any]`: Composite primary key.
820
1225
 
821
1226
  Returns
822
1227
  -------
823
- Instance.
1228
+ With records ORM model instance or null.
824
1229
  """
825
1230
 
826
1231
  # Handle parameter.
827
1232
  if is_instance(model):
828
1233
  model = type(model)
829
1234
 
830
- # Build.
831
- select = DatabaseORMStatementInsert[ModelT](self, model)
1235
+ # Get.
1236
+ result = await self.sess.get(model, key)
832
1237
 
833
- return select
1238
+ # Autucommit.
1239
+ if (
1240
+ self.autocommit
1241
+ and result is not None
1242
+ ):
1243
+ self.sess.expunge(result)
1244
+
1245
+ return result
834
1246
 
835
1247
 
836
1248
  @wrap_transact
837
- def update(self, model: Type[ModelT] | ModelT):
1249
+ async def gets(self, model: Type[DatabaseORMModelT] | DatabaseORMModelT, *keys: Any | tuple[Any]) -> list[DatabaseORMModelT]:
838
1250
  """
839
- Build `DatabaseORMUpdate` instance.
1251
+ Asynchronous select records by primary key sequence.
840
1252
 
841
1253
  Parameters
842
1254
  ----------
843
- model : ORM model instance.
1255
+ model : ORM model type or instance.
1256
+ keys : Primary key sequence.
1257
+ - `Any`: Single primary key.
1258
+ - `tuple[Any]`: Composite primary key.
844
1259
 
845
1260
  Returns
846
1261
  -------
847
- Instance.
1262
+ With records ORM model instance list.
848
1263
  """
849
1264
 
850
1265
  # Handle parameter.
851
1266
  if is_instance(model):
852
1267
  model = type(model)
853
1268
 
854
- # Build.
855
- select = DatabaseORMStatementUpdate[ModelT](self, model)
1269
+ # Get.
1270
+ results = [
1271
+ result
1272
+ for key in keys
1273
+ if (result := await self.sess.get(model, key)) is not None
1274
+ ]
856
1275
 
857
- return select
1276
+ return results
858
1277
 
859
1278
 
860
1279
  @wrap_transact
861
- def delete(self, model: Type[ModelT] | ModelT):
1280
+ async def all(self, model: Type[DatabaseORMModelT] | DatabaseORMModelT) -> list[DatabaseORMModelT]:
862
1281
  """
863
- Build `DatabaseORMDelete` instance.
1282
+ Asynchronous select all records.
864
1283
 
865
1284
  Parameters
866
1285
  ----------
867
- model : ORM model instance.
1286
+ model : ORM model type or instance.
868
1287
 
869
1288
  Returns
870
1289
  -------
871
- Instance.
1290
+ With records ORM model instance list.
872
1291
  """
873
1292
 
874
1293
  # Handle parameter.
875
1294
  if is_instance(model):
876
1295
  model = type(model)
877
1296
 
878
- # Build.
879
- select = DatabaseORMStatementDelete[ModelT](self, model)
1297
+ # Get.
1298
+ select = Select(model)
1299
+ models = await self.sess.exec(select)
1300
+ models = list(models)
880
1301
 
881
- return select
1302
+ return models
1303
+
1304
+
1305
+ @wrap_transact
1306
+ async def add(self, *models: DatabaseORMModel) -> None:
1307
+ """
1308
+ Asynchronous insert records.
882
1309
 
1310
+ Parameters
1311
+ ----------
1312
+ models : ORM model instances.
1313
+ """
1314
+
1315
+ # Add.
1316
+ self.sess.add_all(models)
1317
+
1318
+
1319
+ @wrap_transact
1320
+ async def rm(self, *models: DatabaseORMModel) -> None:
1321
+ """
1322
+ Asynchronous delete records.
1323
+
1324
+ Parameters
1325
+ ----------
1326
+ models : ORM model instances.
1327
+ """
1328
+
1329
+ # Delete.
1330
+ for model in models:
1331
+ await self.sess.delete(model)
1332
+
1333
+
1334
+ @wrap_transact
1335
+ async def refresh(self, *models: DatabaseORMModel) -> None:
1336
+ """
1337
+ Asynchronous refresh records.
1338
+
1339
+ Parameters
1340
+ ----------
1341
+ models : ORM model instances.
1342
+ """
1343
+
1344
+ # Refresh.
1345
+ for model in models:
1346
+ await self.sess.refresh(model)
883
1347
 
884
- class DatabaseORMStatement(DatabaseORMBase):
1348
+
1349
+ @wrap_transact
1350
+ async def expire(self, *models: DatabaseORMModel) -> None:
1351
+ """
1352
+ Asynchronous mark records to expire, refresh on next call.
1353
+
1354
+ Parameters
1355
+ ----------
1356
+ models : ORM model instances.
1357
+ """
1358
+
1359
+ # Refresh.
1360
+ for model in models:
1361
+ self.sess.expire(model)
1362
+
1363
+
1364
+ class DatabaseORMStatementSuper(DatabaseORMBase, Generic[DatabaseORMSessionT]):
885
1365
  """
886
- Database ORM statement type.
1366
+ Database ORM statement super type.
887
1367
  """
888
1368
 
889
1369
 
890
1370
  def __init__(
891
1371
  self,
892
- sess: DatabaseORMSession,
893
- model: Type[ModelT]
1372
+ sess: DatabaseORMSessionT,
1373
+ model: Type[DatabaseORMModelT]
894
1374
  ) -> None:
895
1375
  """
896
1376
  Build instance attributes.
@@ -902,23 +1382,77 @@ class DatabaseORMStatement(DatabaseORMBase):
902
1382
  """
903
1383
 
904
1384
  # Super.
905
- super().__init__(self.model)
1385
+ super().__init__(model)
906
1386
 
907
1387
  # Build.
908
1388
  self.sess = sess
909
1389
  self.model = model
910
1390
 
911
1391
 
912
- def execute(self) -> None:
1392
+ class DatabaseORMStatement(DatabaseORMStatementSuper[DatabaseORMSession], Generic[DatabaseORMStatementReturn]):
1393
+ """
1394
+ Database ORM statement type.
1395
+ """
1396
+
1397
+
1398
+ def execute(self) -> DatabaseORMStatementReturn:
913
1399
  """
914
1400
  Execute statement.
915
1401
  """
916
1402
 
1403
+ # Transaction.
1404
+ self.sess.get_begin()
1405
+
917
1406
  # Execute.
918
- self.sess.session.exec(self)
1407
+ result = self.sess.sess.exec(self)
1408
+
1409
+ ## Select.
1410
+ if isinstance(self, Select):
1411
+ result = list(result)
1412
+ else:
1413
+ result = None
919
1414
 
1415
+ # Automatic commit.
1416
+ if self.sess.autocommit:
1417
+ self.sess.commit()
1418
+ self.sess.close()
920
1419
 
921
- class DatabaseORMStatementSelect(DatabaseORMStatement, Select, Generic[ModelT]):
1420
+ return result
1421
+
1422
+
1423
+ class DatabaseORMStatementAsync(DatabaseORMStatementSuper[DatabaseORMSessionAsync], Generic[DatabaseORMStatementReturn]):
1424
+ """
1425
+ Asynchronous dtabase ORM statement type.
1426
+ """
1427
+
1428
+
1429
+ async def execute(self) -> DatabaseORMStatementReturn:
1430
+ """
1431
+ Asynchronous execute statement.
1432
+ """
1433
+
1434
+ # Transaction.
1435
+ await self.sess.get_begin()
1436
+
1437
+ # Execute.
1438
+ result = await self.sess.sess.exec(self)
1439
+
1440
+ ## Select.
1441
+ if isinstance(self, Select):
1442
+ result = list(result)
1443
+ else:
1444
+ result = None
1445
+
1446
+ # Automatic commit.
1447
+ if self.sess.autocommit:
1448
+ await self.sess.commit()
1449
+ await self.sess.close()
1450
+ await self.sess.orm.db.dispose()
1451
+
1452
+ return result
1453
+
1454
+
1455
+ class DatabaseORMStatementSelect(DatabaseORMStatement[list[DatabaseORMModelT]], Select, Generic[DatabaseORMModelT]):
922
1456
  """
923
1457
  Database ORM `select` statement type.
924
1458
 
@@ -930,25 +1464,45 @@ class DatabaseORMStatementSelect(DatabaseORMStatement, Select, Generic[ModelT]):
930
1464
  inherit_cache: Final = True
931
1465
 
932
1466
 
933
- def execute(self) -> list[ModelT]:
934
- """
935
- Execute self statement.
1467
+ class DatabaseORMStatementInsert(DatabaseORMStatement[None], Insert, Generic[DatabaseORMModelT]):
1468
+ """
1469
+ Database ORM `insert` statement type.
936
1470
 
937
- Returns
938
- -------
939
- With records ORM model instance list.
940
- """
1471
+ Attributes
1472
+ ----------
1473
+ inherit_cache : Compatible `Select` type.
1474
+ """
941
1475
 
942
- # Execute.
943
- result = self.sess.session.exec(self)
944
- models = list(result)
1476
+ inherit_cache: Final = True
945
1477
 
946
- return models
947
1478
 
1479
+ class DatabaseORMStatementUpdate(DatabaseORMStatement[None], Update, Generic[DatabaseORMModelT]):
1480
+ """
1481
+ Database ORM `update` statement type.
948
1482
 
949
- class DatabaseORMStatementInsert(Generic[ModelT], DatabaseORMStatement, Insert):
1483
+ Attributes
1484
+ ----------
1485
+ inherit_cache : Compatible `Update` type.
950
1486
  """
951
- Database ORM `insert` statement type.
1487
+
1488
+ inherit_cache: Final = True
1489
+
1490
+
1491
+ class DatabaseORMStatementDelete(DatabaseORMStatement[None], Delete, Generic[DatabaseORMModelT]):
1492
+ """
1493
+ Database ORM `delete` statement type.
1494
+
1495
+ Attributes
1496
+ ----------
1497
+ inherit_cache : Compatible `Delete` type.
1498
+ """
1499
+
1500
+ inherit_cache: Final = True
1501
+
1502
+
1503
+ class DatabaseORMStatementSelectAsync(DatabaseORMStatementAsync[list[DatabaseORMModelT]], Select, Generic[DatabaseORMModelT]):
1504
+ """
1505
+ Asynchronous database ORM `select` statement type.
952
1506
 
953
1507
  Attributes
954
1508
  ----------
@@ -958,9 +1512,21 @@ class DatabaseORMStatementInsert(Generic[ModelT], DatabaseORMStatement, Insert):
958
1512
  inherit_cache: Final = True
959
1513
 
960
1514
 
961
- class DatabaseORMStatementUpdate(Generic[ModelT], DatabaseORMStatement, Update):
1515
+ class DatabaseORMStatementInsertAsync(DatabaseORMStatementAsync[None], Insert, Generic[DatabaseORMModelT]):
962
1516
  """
963
- Database ORM `update` statement type.
1517
+ Asynchronous database ORM `insert` statement type.
1518
+
1519
+ Attributes
1520
+ ----------
1521
+ inherit_cache : Compatible `Select` type.
1522
+ """
1523
+
1524
+ inherit_cache: Final = True
1525
+
1526
+
1527
+ class DatabaseORMStatementUpdateAsync(DatabaseORMStatementAsync[None], Update, Generic[DatabaseORMModelT]):
1528
+ """
1529
+ Asynchronous database ORM `update` statement type.
964
1530
 
965
1531
  Attributes
966
1532
  ----------
@@ -970,9 +1536,9 @@ class DatabaseORMStatementUpdate(Generic[ModelT], DatabaseORMStatement, Update):
970
1536
  inherit_cache: Final = True
971
1537
 
972
1538
 
973
- class DatabaseORMStatementDelete(Generic[ModelT], DatabaseORMStatement, Delete):
1539
+ class DatabaseORMStatementDeleteAsync(DatabaseORMStatementAsync[None], Delete, Generic[DatabaseORMModelT]):
974
1540
  """
975
- Database ORM `delete` statement type.
1541
+ Asynchronous database ORM `delete` statement type.
976
1542
 
977
1543
  Attributes
978
1544
  ----------