reydb 1.1.48__py3-none-any.whl → 1.1.50__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/__init__.py CHANGED
@@ -19,5 +19,6 @@ rerror : Database error methods.
19
19
  rexec : Database execute methods.
20
20
  rfile : Database file methods.
21
21
  rinfo : Database information methods.
22
+ rorm : Database ORM methods.
22
23
  rparam : Database parameter methods.
23
24
  """
reydb/rall.py CHANGED
@@ -18,4 +18,5 @@ from .rerror import *
18
18
  from .rexec import *
19
19
  from .rfile import *
20
20
  from .rinfo import *
21
+ from .rorm import *
21
22
  from .rparam import *
reydb/rbase.py CHANGED
@@ -9,9 +9,10 @@
9
9
  """
10
10
 
11
11
 
12
- from typing import Any, TypedDict, Literal
12
+ from typing import Any, TypedDict, Literal, overload
13
13
  from sqlalchemy.engine.base import Engine, Connection
14
14
  from sqlalchemy.engine.url import URL
15
+ from sqlalchemy.sql.elements import TextClause
15
16
  from reykit.rbase import Base, throw
16
17
  from reykit.rre import search
17
18
 
@@ -19,7 +20,8 @@ from reykit.rre import search
19
20
  __all__ = (
20
21
  'DatabaseBase',
21
22
  'extract_url',
22
- 'extract_engine'
23
+ 'extract_engine',
24
+ 'extract_path'
23
25
  )
24
26
 
25
27
 
@@ -187,3 +189,100 @@ def extract_engine(engine: Engine | Connection) -> dict[
187
189
  }
188
190
 
189
191
  return params
192
+
193
+
194
+ def extract_path(
195
+ path: str | tuple[str] | tuple[str, str] | tuple[str, str, str]
196
+ ) -> tuple[str, str | None, str | None]:
197
+ """
198
+ Extract table name and database name and column name from path.
199
+
200
+ Parameters
201
+ ----------
202
+ path : Path.
203
+ - `str` and not contain '.' or contain '`': Database name.
204
+ - `str` and contain '.': Database name and table name, column name is optional. Format is 'database.table[.column]'.
205
+ - `tuple`: Format is `(database[, table, column])`.
206
+
207
+ Returns
208
+ -------
209
+ Names.
210
+ """
211
+
212
+ # Type str.
213
+ if type(path) == str:
214
+
215
+ ## Single.
216
+ if (
217
+ '.' not in path
218
+ or '`' in path
219
+ ):
220
+ name = path.replace('`', '')
221
+ names = (name, None, None)
222
+
223
+ ## Multiple.
224
+ else:
225
+ names = path.split('.', 2)
226
+ if len(names) == 2:
227
+ names.append(None)
228
+ names = tuple(names)
229
+
230
+ # Type tuple.
231
+ else:
232
+ if len(path) == 1:
233
+ path += (None, None)
234
+ if len(path) == 2:
235
+ path += (None,)
236
+ names = path
237
+
238
+ return names
239
+
240
+
241
+ def get_syntax(self, sql: str | TextClause) -> list[str]:
242
+ """
243
+ Extract SQL syntax type for each segment form SQL.
244
+
245
+ Parameters
246
+ ----------
247
+ sql : SQL text or TextClause object.
248
+
249
+ Returns
250
+ -------
251
+ SQL syntax type for each segment.
252
+ """
253
+
254
+ # Handle parameter.
255
+ if type(sql) == TextClause:
256
+ sql = sql.text
257
+
258
+ # Extract.
259
+ syntax = [
260
+ search('[a-zA-Z]+', sql_part).upper()
261
+ for sql_part in sql.split(';')
262
+ if sql_part != ''
263
+ ]
264
+
265
+ return syntax
266
+
267
+
268
+ def is_multi_sql(self, sql: str | TextClause) -> bool:
269
+ """
270
+ Judge whether it is multi segment SQL.
271
+
272
+ Parameters
273
+ ----------
274
+ sql : SQL text or TextClause object.
275
+
276
+ Returns
277
+ -------
278
+ Judgment result.
279
+ """
280
+
281
+ # Handle parameter.
282
+ if type(sql) == TextClause:
283
+ sql = sql.text
284
+
285
+ # Judge.
286
+ if ';' in sql.rstrip()[:-1]:
287
+ return True
288
+ return False
reydb/rbuild.py CHANGED
@@ -14,8 +14,7 @@ from copy import deepcopy
14
14
  from reykit.rbase import throw
15
15
  from reykit.rstdout import ask
16
16
 
17
- from .rbase import DatabaseBase
18
- from .rconn import DatabaseConnection
17
+ from .rbase import DatabaseBase, extract_path
19
18
  from .rdb import Database
20
19
 
21
20
 
@@ -52,22 +51,17 @@ class DatabaseBuild(DatabaseBase):
52
51
  """
53
52
 
54
53
 
55
- def __init__(self, database: Database | DatabaseConnection) -> None:
54
+ def __init__(self, db: Database) -> None:
56
55
  """
57
56
  Build instance attributes.
58
57
 
59
58
  Parameters
60
59
  ----------
61
- database : Database or DatabaseConnection instance.
60
+ db: Database instance.
62
61
  """
63
62
 
64
- # SQLite.
65
- if database.backend == 'sqlite':
66
- text = 'not suitable for SQLite databases'
67
- throw(AssertionError, text=text)
68
-
69
63
  # Set attribute.
70
- self.database = database
64
+ self.db = db
71
65
  self._schema: dict[str, dict[str, list[str]]] | None = None
72
66
 
73
67
 
@@ -98,7 +92,7 @@ class DatabaseBuild(DatabaseBase):
98
92
 
99
93
  # Execute.
100
94
  if execute:
101
- self.database.execute(sql)
95
+ self.db.execute(sql)
102
96
 
103
97
  return sql
104
98
 
@@ -285,7 +279,8 @@ class DatabaseBuild(DatabaseBase):
285
279
  """
286
280
 
287
281
  # Handle parameter.
288
- database, table, _ = self.database.extract_path(path)
282
+ if type(path) == str:
283
+ database, table, _ = extract_path(path)
289
284
  if fields.__class__ == dict:
290
285
  fields = [fields]
291
286
  if primary.__class__ == str:
@@ -347,7 +342,7 @@ class DatabaseBuild(DatabaseBase):
347
342
 
348
343
  # Execute.
349
344
  if execute:
350
- self.database.execute(sql)
345
+ self.db.execute(sql)
351
346
 
352
347
  return sql
353
348
 
@@ -375,7 +370,7 @@ class DatabaseBuild(DatabaseBase):
375
370
  """
376
371
 
377
372
  # Handle parameter.
378
- database, view, _ = self.database.extract_path(path)
373
+ database, view, _ = extract_path(path)
379
374
 
380
375
  # Generate SQL.
381
376
  select = select.replace('\n', '\n ')
@@ -383,7 +378,7 @@ class DatabaseBuild(DatabaseBase):
383
378
 
384
379
  # Execute.
385
380
  if execute:
386
- self.database.execute(sql)
381
+ self.db.execute(sql)
387
382
 
388
383
  return sql
389
384
 
@@ -476,7 +471,7 @@ class DatabaseBuild(DatabaseBase):
476
471
 
477
472
  # Execute.
478
473
  if execute:
479
- self.database.execute(sql)
474
+ self.db.execute(sql)
480
475
 
481
476
  return sql
482
477
 
@@ -502,14 +497,14 @@ class DatabaseBuild(DatabaseBase):
502
497
  """
503
498
 
504
499
  # Handle parameter.
505
- database, table, _ = self.database.extract_path(path)
500
+ database, table, _ = extract_path(path)
506
501
 
507
502
  # Generate.
508
503
  sql = f'DROP TABLE `{database}`.`{table}`'
509
504
 
510
505
  # Execute.
511
506
  if execute:
512
- self.database.execute(sql)
507
+ self.db.execute(sql)
513
508
 
514
509
  return sql
515
510
 
@@ -535,14 +530,14 @@ class DatabaseBuild(DatabaseBase):
535
530
  """
536
531
 
537
532
  # Handle parameter.
538
- database, view, _ = self.database.extract_path(path)
533
+ database, view, _ = extract_path(path)
539
534
 
540
535
  # Generate SQL.
541
536
  sql = 'DROP VIEW `%s`.`%s`' % (database, view)
542
537
 
543
538
  # Execute.
544
539
  if execute:
545
- self.database.execute(sql)
540
+ self.db.execute(sql)
546
541
 
547
542
  return sql
548
543
 
@@ -592,7 +587,7 @@ class DatabaseBuild(DatabaseBase):
592
587
 
593
588
  # Execute.
594
589
  if execute:
595
- self.database.execute(sql)
590
+ self.db.execute(sql)
596
591
 
597
592
  return sql
598
593
 
@@ -649,7 +644,7 @@ class DatabaseBuild(DatabaseBase):
649
644
  """
650
645
 
651
646
  # Handle parameter.
652
- database, table, _ = self.database.extract_path(path)
647
+ database, table, _ = extract_path(path)
653
648
  if fields.__class__ == dict:
654
649
  fields = [fields]
655
650
  if primary.__class__ == str:
@@ -707,7 +702,7 @@ class DatabaseBuild(DatabaseBase):
707
702
 
708
703
  # Execute.
709
704
  if execute:
710
- self.database.execute(sql)
705
+ self.db.execute(sql)
711
706
 
712
707
  return sql
713
708
 
@@ -739,7 +734,7 @@ class DatabaseBuild(DatabaseBase):
739
734
  """
740
735
 
741
736
  # Handle parameter.
742
- database, table, _ = self.database.extract_path(path)
737
+ database, table, _ = extract_path(path)
743
738
  if fields.__class__ == str:
744
739
  fields = [fields]
745
740
  if indexes.__class__ == str:
@@ -778,7 +773,7 @@ class DatabaseBuild(DatabaseBase):
778
773
 
779
774
  # Execute.
780
775
  if execute:
781
- self.database.execute(sql)
776
+ self.db.execute(sql)
782
777
 
783
778
  return sql
784
779
 
@@ -829,7 +824,7 @@ class DatabaseBuild(DatabaseBase):
829
824
  """
830
825
 
831
826
  # Handle parameter.
832
- database, table, _ = self.database.extract_path(path)
827
+ database, table, _ = extract_path(path)
833
828
  if fields.__class__ == dict:
834
829
  fields = [fields]
835
830
 
@@ -897,7 +892,7 @@ class DatabaseBuild(DatabaseBase):
897
892
 
898
893
  # Execute.
899
894
  if execute:
900
- self.database.execute(sql)
895
+ self.db.execute(sql)
901
896
 
902
897
  return sql
903
898
 
@@ -925,14 +920,14 @@ class DatabaseBuild(DatabaseBase):
925
920
  """
926
921
 
927
922
  # Handle parameter.
928
- database, view, _ = self.database.extract_path(path)
923
+ database, view, _ = extract_path(path)
929
924
 
930
925
  # Generate SQL.
931
926
  sql = 'ALTER VIEW `%s`.`%s` AS\n%s' % (database, view, select)
932
927
 
933
928
  # Execute.
934
929
  if execute:
935
- self.database.execute(sql)
930
+ self.db.execute(sql)
936
931
 
937
932
  return sql
938
933
 
@@ -958,21 +953,21 @@ class DatabaseBuild(DatabaseBase):
958
953
  """
959
954
 
960
955
  # Handle parameter.
961
- database, table, _ = self.database.extract_path(path)
956
+ database, table, _ = extract_path(path)
962
957
 
963
958
  # Generate.
964
959
  sql = f'TRUNCATE TABLE `{database}`.`{table}`'
965
960
 
966
961
  # Execute.
967
962
  if execute:
968
- self.database.execute(sql)
963
+ self.db.execute(sql)
969
964
 
970
965
  return sql
971
966
 
972
967
 
973
968
  def exist(
974
969
  self,
975
- path: str | tuple[str, str | None, str | None]
970
+ path: str | tuple[str] | tuple[str, str] | tuple[str, str, str]
976
971
  ) -> bool:
977
972
  """
978
973
  Judge database or table or column exists.
@@ -981,7 +976,7 @@ class DatabaseBuild(DatabaseBase):
981
976
  ----------
982
977
  path : Database name and table name and column name.
983
978
  - `str`: Automatic extract.
984
- - `tuple[str, str | None, str | None]`: Database name, table name and column name is optional.
979
+ - `tuple`: Format is `(database[, table, column]).`
985
980
 
986
981
  Returns
987
982
  -------
@@ -989,9 +984,9 @@ class DatabaseBuild(DatabaseBase):
989
984
  """
990
985
 
991
986
  # Handle parameter.
992
- database, table, column = self.database.extract_path(path, 'database')
987
+ database, table, column = extract_path(path)
993
988
  if self._schema is None:
994
- self._schema = self.database.schema(False)
989
+ self._schema = self.db.schema(False)
995
990
 
996
991
  # Judge.
997
992
  judge = (
@@ -1081,7 +1076,7 @@ class DatabaseBuild(DatabaseBase):
1081
1076
  database = params['name']
1082
1077
 
1083
1078
  ## Exist.
1084
- exist = self.database.build.exist((database, None, None))
1079
+ exist = self.db.build.exist((database, None, None))
1085
1080
  if exist:
1086
1081
  continue
1087
1082
 
@@ -1092,7 +1087,7 @@ class DatabaseBuild(DatabaseBase):
1092
1087
  self.input_confirm_build(sql)
1093
1088
 
1094
1089
  ## Execute.
1095
- self.database.execute(sql)
1090
+ self.db.execute(sql)
1096
1091
 
1097
1092
  ## Report.
1098
1093
  text = f"Database '{database}' build completed."
@@ -1101,10 +1096,10 @@ class DatabaseBuild(DatabaseBase):
1101
1096
  # Table.
1102
1097
  for params in tables:
1103
1098
  path = params['path']
1104
- database, table, _ = self.database.extract_path(path)
1099
+ database, table, _ = extract_path(path)
1105
1100
 
1106
1101
  ## Exist.
1107
- exist = self.database.build.exist((database, table, None))
1102
+ exist = self.db.build.exist((database, table, None))
1108
1103
  if exist:
1109
1104
  continue
1110
1105
 
@@ -1115,7 +1110,7 @@ class DatabaseBuild(DatabaseBase):
1115
1110
  self.input_confirm_build(sql)
1116
1111
 
1117
1112
  ## Execute.
1118
- self.database.execute(sql)
1113
+ self.db.execute(sql)
1119
1114
 
1120
1115
  ## Report.
1121
1116
  text = f"Table '{table}' of database '{database}' build completed."
@@ -1124,10 +1119,10 @@ class DatabaseBuild(DatabaseBase):
1124
1119
  # View.
1125
1120
  for params in views:
1126
1121
  path = params['path']
1127
- database, view, _ = self.database.extract_path(path)
1122
+ database, view, _ = extract_path(path)
1128
1123
 
1129
1124
  ## Exist.
1130
- exist = self.database.build.exist((database, view, None))
1125
+ exist = self.db.build.exist((database, view, None))
1131
1126
  if exist:
1132
1127
  continue
1133
1128
 
@@ -1138,7 +1133,7 @@ class DatabaseBuild(DatabaseBase):
1138
1133
  self.input_confirm_build(sql)
1139
1134
 
1140
1135
  ## Execute.
1141
- self.database.execute(sql)
1136
+ self.db.execute(sql)
1142
1137
 
1143
1138
  ## Report.
1144
1139
  text = f"View '{view}' of database '{database}' build completed."
@@ -1147,10 +1142,10 @@ class DatabaseBuild(DatabaseBase):
1147
1142
  # View stats.
1148
1143
  for params in views_stats:
1149
1144
  path = params['path']
1150
- database, view, _ = self.database.extract_path(path)
1145
+ database, view, _ = extract_path(path)
1151
1146
 
1152
1147
  ## Exist.
1153
- exist = self.database.build.exist((database, view, None))
1148
+ exist = self.db.build.exist((database, view, None))
1154
1149
  if exist:
1155
1150
  continue
1156
1151
 
@@ -1161,7 +1156,7 @@ class DatabaseBuild(DatabaseBase):
1161
1156
  self.input_confirm_build(sql)
1162
1157
 
1163
1158
  ## Execute.
1164
- self.database.execute(sql)
1159
+ self.db.execute(sql)
1165
1160
 
1166
1161
  ## Report.
1167
1162
  text = f"View '{view}' of database '{database}' build completed."
reydb/rconfig.py CHANGED
@@ -19,7 +19,6 @@ from datetime import (
19
19
  )
20
20
  from reykit.rbase import null, throw
21
21
 
22
- from .rconn import DatabaseConnection
23
22
  from .rdb import Database
24
23
 
25
24
 
@@ -49,18 +48,17 @@ class DatabaseConfig(object):
49
48
  """
50
49
 
51
50
 
52
- def __init__(self, database: Database | DatabaseConnection) -> None:
51
+ def __init__(self, db: Database) -> None:
53
52
  """
54
53
  Build instance attributes.
55
- """
56
54
 
57
- # SQLite.
58
- if database.backend == 'sqlite':
59
- text = 'not suitable for SQLite databases'
60
- throw(AssertionError, text=text)
55
+ Parameters
56
+ ----------
57
+ db: Database instance.
58
+ """
61
59
 
62
60
  # Build.
63
- self.database = database
61
+ self.db = db
64
62
 
65
63
  ## Database path name.
66
64
  self.db_names = {
@@ -185,7 +183,7 @@ class DatabaseConfig(object):
185
183
  ]
186
184
 
187
185
  # Build.
188
- self.database.build.build(databases, tables, views_stats=views_stats)
186
+ self.db.build.build(databases, tables, views_stats=views_stats)
189
187
 
190
188
 
191
189
  @property
@@ -199,7 +197,7 @@ class DatabaseConfig(object):
199
197
  """
200
198
 
201
199
  # Get.
202
- result = self.database.execute_select(
200
+ result = self.db.execute.select(
203
201
  (self.db_names['base'], self.db_names['base.config']),
204
202
  ['key', 'value', 'type', 'note'],
205
203
  order='IFNULL(`update_time`, `create_time`) DESC'
@@ -235,7 +233,7 @@ class DatabaseConfig(object):
235
233
 
236
234
  # Get.
237
235
  where = '`key` = :key'
238
- result = self.database.execute_select(
236
+ result = self.db.execute.select(
239
237
  (self.db_names['base'], self.db_names['base.config']),
240
238
  '`value`',
241
239
  where,
@@ -281,7 +279,7 @@ class DatabaseConfig(object):
281
279
  'type': type(default).__name__,
282
280
  'note': default_note
283
281
  }
284
- result = self.database.execute_insert(
282
+ result = self.db.execute.insert(
285
283
  (self.db_names['base'], self.db_names['base.config']),
286
284
  data,
287
285
  'ignore'
@@ -322,7 +320,7 @@ class DatabaseConfig(object):
322
320
  row['type'] = type(row['value']).__name__
323
321
 
324
322
  # Update.
325
- self.database.execute_insert(
323
+ self.db.execute.insert(
326
324
  (self.db_names['base'], self.db_names['base.config']),
327
325
  data,
328
326
  'update'
@@ -345,7 +343,7 @@ class DatabaseConfig(object):
345
343
  else:
346
344
  where = '`key` in :key'
347
345
  limit = None
348
- result = self.database.execute_delete(
346
+ result = self.db.execute.delete(
349
347
  (self.db_names['base'], self.db_names['base.config']),
350
348
  where,
351
349
  limit=limit,
@@ -367,7 +365,7 @@ class DatabaseConfig(object):
367
365
  """
368
366
 
369
367
  # Get.
370
- result = self.database.execute_select(
368
+ result = self.db.execute.select(
371
369
  (self.db_names['base'], self.db_names['base.config']),
372
370
  ['key', 'value']
373
371
  )
@@ -393,7 +391,7 @@ class DatabaseConfig(object):
393
391
  """
394
392
 
395
393
  # Get.
396
- result = self.database.execute_select(
394
+ result = self.db.execute.select(
397
395
  (self.db_names['base'], self.db_names['base.config']),
398
396
  '`key`'
399
397
  )
@@ -418,7 +416,7 @@ class DatabaseConfig(object):
418
416
  """
419
417
 
420
418
  # Get.
421
- result = self.database.execute_select(
419
+ result = self.db.execute.select(
422
420
  (self.db_names['base'], self.db_names['base.config']),
423
421
  '`value`'
424
422
  )
@@ -480,7 +478,7 @@ class DatabaseConfig(object):
480
478
  'type': type(value).__name__,
481
479
  'note': note
482
480
  }
483
- self.database.execute_insert(
481
+ self.db.execute.insert(
484
482
  (self.db_names['base'], self.db_names['base.config']),
485
483
  data,
486
484
  'update'
reydb/rconn.py CHANGED
@@ -10,10 +10,9 @@
10
10
 
11
11
 
12
12
  from typing import Self
13
- from sqlalchemy.engine.base import Connection
14
- from sqlalchemy.sql.elements import TextClause
15
13
 
16
- from .rdb import Result, Database
14
+ from .rbase import DatabaseBase
15
+ from .rdb import Database
17
16
 
18
17
 
19
18
  __all__ = (
@@ -21,7 +20,7 @@ __all__ = (
21
20
  )
22
21
 
23
22
 
24
- class DatabaseConnection(Database):
23
+ class DatabaseConnection(DatabaseBase):
25
24
  """
26
25
  Database connection type.
27
26
  """
@@ -29,66 +28,46 @@ class DatabaseConnection(Database):
29
28
 
30
29
  def __init__(
31
30
  self,
32
- connection: Connection,
33
- rdatabase: Database
31
+ db: Database,
32
+ autocommit: bool
34
33
  ) -> None:
35
34
  """
36
35
  Build instance attributes.
37
36
 
38
37
  Parameters
39
38
  ----------
40
- connection : Connection object.
41
- rdatabase : Database object.
39
+ db : Database instance.
40
+ autocommit: Whether automatic commit connection.
42
41
  """
43
42
 
44
- # Set parameter.
45
- self.connection = connection
46
- self.rdatabase = rdatabase
43
+ # Build.
44
+ self.db = db
45
+ self.autocommit = autocommit
46
+ self.conn = db.engine.connect()
47
47
  self.begin = None
48
- self.username = rdatabase.username
49
- self.password = rdatabase.password
50
- self.host = rdatabase.host
51
- self.port = rdatabase.port
52
- self.database = rdatabase.database
53
- self.query = rdatabase.query
54
- self.pool_recycle = rdatabase.pool_recycle
55
48
 
56
49
 
57
- def executor(
58
- self,
59
- sql: TextClause,
60
- data: list[dict],
61
- report: bool
62
- ) -> Result:
50
+ @property
51
+ def execute(self):
63
52
  """
64
- SQL executor.
65
-
66
- Parameters
67
- ----------
68
- sql : TextClause object.
69
- data : Data set for filling.
70
- report : Whether report SQL execute information.
53
+ Build `database execute` instance.
71
54
 
72
55
  Returns
73
56
  -------
74
- Result object.
57
+ Instance.
75
58
  """
76
59
 
60
+ # Import.
61
+ from .rexec import DatabaseExecute
62
+
77
63
  # Create transaction.
78
64
  if self.begin is None:
79
- self.begin = self.connection.begin()
80
-
81
- # Execute.
65
+ self.begin = self.conn.begin()
82
66
 
83
- ## Report.
84
- if report:
85
- result = self.executor_report(self.connection, sql, data)
86
-
87
- ## Not report.
88
- else:
89
- result = self.connection.execute(sql, data)
67
+ # Build.
68
+ exec = DatabaseExecute(self)
90
69
 
91
- return result
70
+ return exec
92
71
 
93
72
 
94
73
  def commit(self) -> None:
@@ -119,7 +98,7 @@ class DatabaseConnection(Database):
119
98
  """
120
99
 
121
100
  # Close.
122
- self.connection.close()
101
+ self.conn.close()
123
102
 
124
103
 
125
104
  def __enter__(self) -> Self: