reydb 1.1.48__py3-none-any.whl → 1.1.49__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/rdb.py CHANGED
@@ -9,107 +9,42 @@
9
9
  """
10
10
 
11
11
 
12
- from typing import Any, Literal, overload
13
- from collections.abc import Iterable, Generator, Container
14
- from enum import EnumType
15
12
  from urllib.parse import quote as urllib_quote
16
13
  from pymysql.constants.CLIENT import MULTI_STATEMENTS
17
- from sqlalchemy import create_engine as sqlalchemy_create_engine, text as sqlalchemy_text
18
- from sqlalchemy.engine.base import Engine, Connection
19
- from sqlalchemy.sql.elements import TextClause
20
- from reykit.rbase import throw, get_first_notnone
21
- from reykit.rdata import Generator, to_json
22
- from reykit.rmonkey import monkey_sqlalchemy_result_more_fetch, monkey_sqlalchemy_row_index_field
23
- from reykit.rre import search, findall
24
- from reykit.rstdout import echo
25
- from reykit.rtable import TableData, Table
14
+ from sqlalchemy import create_engine as sqlalchemy_create_engine
15
+ from sqlalchemy.engine.base import Engine
26
16
  from reykit.rtext import join_data_text
27
- from reykit.rwrap import wrap_runtime
28
17
 
29
18
  from .rbase import DatabaseBase, extract_url
30
19
 
31
20
 
32
21
  __all__ = (
33
- 'Result',
34
- 'Database'
22
+ 'Database',
35
23
  )
36
24
 
37
25
 
38
- # Monkey path.
39
- Result_ = monkey_sqlalchemy_result_more_fetch()
40
- Result = Result_
41
- monkey_sqlalchemy_row_index_field()
42
-
43
-
44
26
  class Database(DatabaseBase):
45
27
  """
46
28
  Database type.
47
- Based `MySQL` or `SQLite`.
48
-
49
- Examples
50
- --------
51
- >>> rdb = Database()
52
- >>> result = rdb.execute('SELECT 1 as `a`')
53
- >>> result.to_table()
54
- [{'a': 1}]
29
+ Based `MySQL`.
55
30
  """
56
31
 
57
- # Default value.
32
+ # Whether default to report execution.
58
33
  default_report: bool = False
59
34
 
60
35
 
61
- @overload
62
36
  def __init__(
63
37
  self,
64
38
  host: str,
65
39
  port: int | str,
66
40
  username: str,
67
41
  password: str,
68
- database: str | None = None,
69
- *,
70
- pool_size: int = 5,
71
- max_overflow: int = 10,
72
- pool_timeout: float = 30.0,
73
- pool_recycle: int | None = None,
74
- **query: str
75
- ) -> None: ...
76
-
77
- @overload
78
- def __init__(
79
- self,
80
- *,
81
42
  database: str,
82
43
  pool_size: int = 5,
83
44
  max_overflow: int = 10,
84
45
  pool_timeout: float = 30.0,
85
46
  pool_recycle: int | None = None,
86
47
  **query: str
87
- ) -> None: ...
88
-
89
- @overload
90
- def __init__(
91
- self,
92
- *,
93
- pool_size: int = 5,
94
- max_overflow: int = 10,
95
- pool_timeout: float = 30.0,
96
- pool_recycle: int | None = None,
97
- **query: str
98
- ) -> None: ...
99
-
100
-
101
- def __init__(
102
- self,
103
- host: str | None = None,
104
- port: int | str | None = None,
105
- username: str | None = None,
106
- password: str | None = None,
107
- database: str | None = None,
108
- pool_size: int = 5,
109
- max_overflow: int = 10,
110
- pool_timeout: float = 30.0,
111
- pool_recycle: int | None = None,
112
- **query: str
113
48
  ) -> None:
114
49
  """
115
50
  Build instance attributes.
@@ -120,8 +55,7 @@ class Database(DatabaseBase):
120
55
  port : Remote server database port.
121
56
  username : Remote server database username.
122
57
  password : Remote server database password.
123
- database : Remote server database name or local database file path.
124
- - `None`: When parameters `host`, `port`, `username`, `password`, `database` are all `None`, then using memory store.
58
+ database : Remote server database name.
125
59
  pool_size : Number of connections `keep open`.
126
60
  max_overflow : Number of connections `allowed overflow`.
127
61
  pool_timeout : Number of seconds `wait create` connection.
@@ -158,94 +92,12 @@ class Database(DatabaseBase):
158
92
 
159
93
  # Server recycle time.
160
94
  if pool_recycle is None:
161
- if self.mode == 'server':
162
- wait_timeout = self.variables['wait_timeout']
163
- if wait_timeout is not None:
164
- self.pool_recycle = int(wait_timeout)
95
+ wait_timeout = self.variables['wait_timeout']
96
+ if wait_timeout is not None:
97
+ self.pool_recycle = int(wait_timeout)
165
98
  self.engine.pool._recycle = self.pool_recycle
166
99
 
167
100
 
168
- @overload
169
- def extract_path(
170
- self,
171
- path: str,
172
- main: Literal['table', 'database'] = 'table'
173
- ) -> tuple[str, str, str | None]: ...
174
-
175
- @overload
176
- def extract_path(
177
- self,
178
- path: tuple[str | None, str | None] | tuple[str | None, str | None, str | None],
179
- main: Literal['table', 'database'] = 'table'
180
- ) -> tuple[str, str | None, str | None]: ...
181
-
182
- def extract_path(
183
- self,
184
- path: str | tuple[str | None, str | None] | tuple[str | None, str | None, str | None],
185
- main: Literal['table', 'database'] = 'table'
186
- ) -> tuple[str, str | None, str | None]:
187
- """
188
- Extract table name and database name and column name from path.
189
-
190
- Parameters
191
- ----------
192
- path : Table name, can contain database name, otherwise use `self.rdatabase.database`.
193
- - `str`: Automatic extract database name and table name.
194
- Not contain '.' or contain '`': Main name.
195
- Contain '.': Database name and table name, column name is optional. Example 'database.table[.column]'.
196
- - `tuple[str, str]`: Database name and table name.
197
- - `tuple[str, str | None, str | None]`: Database name and table name and column name.
198
- path : Automatic extract.
199
- main : Priority main name, 'table' or 'database'.
200
-
201
- Returns
202
- -------
203
- Database name and table name and column name.
204
- """
205
-
206
- # Type str.
207
- if type(path) == str:
208
-
209
- ## Single.
210
- if (
211
- '.' not in path
212
- or '`' in path
213
- ):
214
- name = path.replace('`', '')
215
- match main:
216
- case 'table':
217
- names = (self.database, name, None)
218
- case 'database':
219
- names = (name, None, None)
220
- case _:
221
- throw(ValueError, main)
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) == 2:
233
- path += (None,)
234
- if path[0] is None:
235
- path = (self.database,) + names[1:]
236
- names = path
237
-
238
- # SQLite.
239
- if self.backend == 'sqlite':
240
- names = ('main',) + names[1:]
241
-
242
- # Check.
243
- if names[0] is None:
244
- throw(ValueError, names)
245
-
246
- return names
247
-
248
-
249
101
  @property
250
102
  def backend(self) -> str:
251
103
  """
@@ -280,32 +132,6 @@ class Database(DatabaseBase):
280
132
  return driver
281
133
 
282
134
 
283
- @property
284
- def mode(self) -> Literal['server', 'file', 'memory']:
285
- """
286
- Database store mode.
287
-
288
- Returns
289
- -------
290
- Mode.
291
- """
292
-
293
- # Judge.
294
- if (
295
- self.username is not None
296
- and self.password is not None
297
- and self.host is not None
298
- and self.port is not None
299
- ):
300
- value = 'server'
301
- elif self.database not in (None, ':memory:'):
302
- value = 'file'
303
- else:
304
- value = 'memory'
305
-
306
- return value
307
-
308
-
309
135
  @property
310
136
  def url(self) -> str:
311
137
  """
@@ -317,21 +143,8 @@ class Database(DatabaseBase):
317
143
  """
318
144
 
319
145
  # Generate URL.
320
-
321
- ## Server.
322
- if self.mode == 'server':
323
- password = urllib_quote(self.password)
324
- url_ = f'mysql+pymysql://{self.username}:{password}@{self.host}:{self.port}'
325
- if self.database is not None:
326
- url_ = f'{url_}/{self.database}'
327
-
328
- ## File.
329
- elif self.mode == 'file':
330
- url_ = f'sqlite:///{self.database}'
331
-
332
- ## Memory.
333
- else:
334
- url_ = f'sqlite:///:memory:'
146
+ password = urllib_quote(self.password)
147
+ url_ = f'mysql+pymysql://{self.username}:{password}@{self.host}:{self.port}/{self.database}'
335
148
 
336
149
  # Add Server parameter.
337
150
  if self.query != {}:
@@ -356,20 +169,14 @@ class Database(DatabaseBase):
356
169
  """
357
170
 
358
171
  # Handle parameter.
359
- if self.mode == 'memory':
360
- engine_params = {
361
- 'url': self.url,
362
- 'pool_recycle': self.pool_recycle
363
- }
364
- else:
365
- engine_params = {
366
- 'url': self.url,
367
- 'pool_size': self.pool_size,
368
- 'max_overflow': self.max_overflow,
369
- 'pool_timeout': self.pool_timeout,
370
- 'pool_recycle': self.pool_recycle,
371
- 'connect_args': {'client_flag': MULTI_STATEMENTS}
372
- }
172
+ engine_params = {
173
+ 'url': self.url,
174
+ 'pool_size': self.pool_size,
175
+ 'max_overflow': self.max_overflow,
176
+ 'pool_timeout': self.pool_timeout,
177
+ 'pool_recycle': self.pool_recycle,
178
+ 'connect_args': {'client_flag': MULTI_STATEMENTS}
179
+ }
373
180
 
374
181
  # Create Engine.
375
182
  engine = sqlalchemy_create_engine(**engine_params)
@@ -378,7 +185,7 @@ class Database(DatabaseBase):
378
185
 
379
186
 
380
187
  @property
381
- def count(self) -> tuple[int, int]:
188
+ def count_conn(self) -> tuple[int, int]:
382
189
  """
383
190
  Count number of keep open and allowed overflow connection.
384
191
 
@@ -387,1090 +194,25 @@ class Database(DatabaseBase):
387
194
  Number of keep open and allowed overflow connection.
388
195
  """
389
196
 
390
- # Handle parameter.
391
- if hasattr(self, 'engine'):
392
- rdatabase = self
393
- else:
394
- rdatabase: Database = self.rdatabase
395
-
396
197
  # Count.
397
- _overflow = rdatabase.engine.pool._overflow
198
+ _overflow = self.engine.pool._overflow
398
199
  if _overflow < 0:
399
- keep_n = rdatabase.pool_size + _overflow
200
+ keep_n = self.pool_size + _overflow
400
201
  overflow_n = 0
401
202
  else:
402
- keep_n = rdatabase.pool_size
203
+ keep_n = self.pool_size
403
204
  overflow_n = _overflow
404
205
 
405
206
  return keep_n, overflow_n
406
207
 
407
208
 
408
- def handle_sql(self, sql: str | TextClause) -> TextClause:
409
- """
410
- Handle SQL.
411
-
412
- Parameters
413
- ----------
414
- sql : SQL in method `sqlalchemy.text` format, or TextClause object.
415
-
416
- Returns
417
- -------
418
- TextClause instance.
419
- """
420
-
421
- # Handle parameter.
422
- if type(sql) == TextClause:
423
- sql = sql.text
424
-
425
- # Handle.
426
- sql = sql.strip()
427
- if sql[-1] != ';':
428
- sql += ';'
429
- sql = sqlalchemy_text(sql)
430
-
431
- return sql
432
-
433
-
434
- def handle_data(
435
- self,
436
- data: list[dict],
437
- sql: str | TextClause,
438
- ) -> list[dict]:
209
+ def connect(self, autocommit: bool = False):
439
210
  """
440
- Handle data based on the content of SQL.
441
-
442
- Parameters
443
- ----------
444
- data : Data set for filling.
445
- sql : SQL in method `sqlalchemy.text` format, or TextClause object.
446
-
447
- Returns
448
- -------
449
- Filled data.
450
- """
451
-
452
- # Handle parameter.
453
- if type(sql) == TextClause:
454
- sql = sql.text
455
-
456
- # Extract keys.
457
- pattern = '(?<!\\\\):(\\w+)'
458
- sql_keys = findall(pattern, sql)
459
-
460
- # Extract keys of syntax "in".
461
- pattern = '[iI][nN]\\s+(?<!\\\\):(\\w+)'
462
- sql_keys_in = findall(pattern, sql)
463
-
464
- # Loop.
465
- for row in data:
466
- if row == {}:
467
- continue
468
- for key in sql_keys:
469
- value = row.get(key)
470
-
471
- # Empty string.
472
- if value == '':
473
- value = None
474
-
475
- # Convert.
476
- elif (
477
- type(value) in (list, dict)
478
- and key not in sql_keys_in
479
- ):
480
- value = to_json(value)
481
-
482
- # Enum.
483
- elif isinstance(type(value), EnumType):
484
- value = value.value
485
-
486
- row[key] = value
487
-
488
- return data
489
-
490
-
491
- def get_syntax(self, sql: str | TextClause) -> list[str]:
492
- """
493
- Extract SQL syntax type for each segment form SQL.
494
-
495
- Parameters
496
- ----------
497
- sql : SQL text or TextClause object.
498
-
499
- Returns
500
- -------
501
- SQL syntax type for each segment.
502
- """
503
-
504
- # Handle parameter.
505
- if type(sql) == TextClause:
506
- sql = sql.text
507
-
508
- # Extract.
509
- syntax = [
510
- search('[a-zA-Z]+', sql_part).upper()
511
- for sql_part in sql.split(';')
512
- if sql_part != ''
513
- ]
514
-
515
- return syntax
516
-
517
-
518
- def is_multi_sql(self, sql: str | TextClause) -> bool:
519
- """
520
- Judge whether it is multi segment SQL.
521
-
522
- Parameters
523
- ----------
524
- sql : SQL text or TextClause object.
525
-
526
- Returns
527
- -------
528
- Judgment result.
529
- """
530
-
531
- # Handle parameter.
532
- if type(sql) == TextClause:
533
- sql = sql.text
534
-
535
- # Judge.
536
- if ';' in sql.rstrip()[:-1]:
537
- return True
538
- return False
539
-
540
-
541
- def executor_report(
542
- self,
543
- connection: Connection,
544
- sql: TextClause,
545
- data: list[dict]
546
- ) -> Result:
547
- """
548
- SQL executor and report SQL execute information
549
-
550
- Parameters
551
- ----------
552
- connection : Connection object.
553
- sql : TextClause object.
554
- data : Data set for filling.
555
-
556
- Returns
557
- -------
558
- Result object.
559
- """
560
-
561
- # Execute.
562
- execute = wrap_runtime(connection.execute, to_return=True)
563
- result, report_runtime, *_ = execute(sql, data)
564
-
565
- # Report.
566
- report_info = (
567
- f'{report_runtime}\n'
568
- f'Row Count: {result.rowcount}'
569
- )
570
- sqls = [
571
- sql_part.strip()
572
- for sql_part in sql.text.split(';')
573
- if sql_part != ''
574
- ]
575
- if data == []:
576
- echo(report_info, *sqls, title='SQL')
577
- else:
578
- echo(report_info, *sqls, data, title='SQL')
579
-
580
- return result
581
-
582
-
583
- def executor(
584
- self,
585
- sql: TextClause,
586
- data: list[dict],
587
- report: bool
588
- ) -> Result:
589
- """
590
- SQL executor.
591
-
592
- Parameters
593
- ----------
594
- sql : TextClause object.
595
- data : Data set for filling.
596
- report : Whether report SQL execute information.
597
-
598
- Returns
599
- -------
600
- Result object.
601
- """
602
-
603
- # Create connection.
604
- with self.engine.connect() as connection:
605
-
606
- # Create transaction.
607
- with connection.begin():
608
-
609
- # Execute.
610
-
611
- ## Report.
612
- if report:
613
- result = self.executor_report(connection, sql, data)
614
-
615
- ## Not report.
616
- else:
617
- result = connection.execute(sql, data)
618
-
619
- return result
620
-
621
-
622
- def execute(
623
- self,
624
- sql: str | TextClause,
625
- data: TableData | None = None,
626
- report: bool | None = None,
627
- **kwdata: Any
628
- ) -> Result:
629
- """
630
- Execute SQL.
631
-
632
- Parameters
633
- ----------
634
- sql : SQL in method `sqlalchemy.text` format, or `TextClause` object.
635
- data : Data set for filling.
636
- report : Whether report SQL execute information.
637
- - `None`: Use attribute `default_report`.
638
- - `bool`: Use this value.
639
- kwdata : Keyword parameters for filling.
640
-
641
- Returns
642
- -------
643
- Result object.
644
- """
645
-
646
- # Handle parameter by priority.
647
- report = get_first_notnone(report, self.default_report)
648
-
649
- # Handle parameter.
650
- sql = self.handle_sql(sql)
651
- if data is None:
652
- if kwdata == {}:
653
- data = []
654
- else:
655
- data = [kwdata]
656
- else:
657
- data_table = Table(data)
658
- data = data_table.to_table()
659
- for row in data:
660
- row.update(kwdata)
661
- data = self.handle_data(data, sql)
662
-
663
- # Execute.
664
- result = self.executor(sql, data, report)
665
-
666
- return result
667
-
668
-
669
- def execute_select(
670
- self,
671
- path: str | tuple[str, str],
672
- fields: str | Iterable[str] | None = None,
673
- where: str | None = None,
674
- group: str | None = None,
675
- having: str | None = None,
676
- order: str | None = None,
677
- limit: int | str | tuple[int, int] | None = None,
678
- report: bool | None = None,
679
- **kwdata: Any
680
- ) -> Result:
681
- """
682
- Execute select SQL.
683
-
684
- Parameters
685
- ----------
686
- path : Table name, can contain database name, otherwise use `self.database`.
687
- - `str`: Automatic extract database name and table name.
688
- - `tuple[str, str]`: Database name and table name.
689
- fields : Select clause content.
690
- - `None`: Is `SELECT *`.
691
- - `str`: Join as `SELECT str`.
692
- - `Iterable[str]`, Join as `SELECT ``str``: ...`.
693
- `str and first character is ':'`: Use this syntax.
694
- `str`: Use this field.
695
- where : Clause `WHERE` content, join as `WHERE str`.
696
- group : Clause `GROUP BY` content, join as `GROUP BY str`.
697
- having : Clause `HAVING` content, join as `HAVING str`.
698
- order : Clause `ORDER BY` content, join as `ORDER BY str`.
699
- limit : Clause `LIMIT` content.
700
- - `int | str`: Join as `LIMIT int/str`.
701
- - `tuple[int, int]`: Join as `LIMIT int, int`.
702
- report : Whether report SQL execute information.
703
- - `None`, Use attribute `report_execute_info`: of object `ROption`.
704
- - `int`: Use this value.
705
- kwdata : Keyword parameters for filling.
706
-
707
- Returns
708
- -------
709
- Result object.
710
-
711
- Examples
712
- --------
713
- Parameter `fields`.
714
- >>> fields = ['id', ':`id` + 1 AS `id_`']
715
- >>> result = Database.execute_select('database.table', fields)
716
- >>> print(result.to_table())
717
- [{'id': 1, 'id_': 2}, ...]
718
-
719
- Parameter `kwdata`.
720
- >>> fields = '`id`, `id` + :value AS `id_`'
721
- >>> result = Database.execute_select('database.table', fields, value=1)
722
- >>> print(result.to_table())
723
- [{'id': 1, 'id_': 2}, ...]
724
- """
725
-
726
- # Handle parameter.
727
- database, table, _ = self.extract_path(path)
728
-
729
- # Generate SQL.
730
- sql_list = []
731
-
732
- ## Part 'SELECT' syntax.
733
- if fields is None:
734
- fields = '*'
735
- elif type(fields) != str:
736
- fields = ', '.join(
737
- [
738
- field[1:]
739
- if (
740
- field.startswith(':')
741
- and field != ':'
742
- )
743
- else f'`{field}`'
744
- for field in fields
745
- ]
746
- )
747
- sql_select = f'SELECT {fields}'
748
- sql_list.append(sql_select)
749
-
750
- ## Part 'FROM' syntax.
751
- sql_from = f'FROM `{database}`.`{table}`'
752
- sql_list.append(sql_from)
753
-
754
- ## Part 'WHERE' syntax.
755
- if where is not None:
756
- sql_where = f'WHERE {where}'
757
- sql_list.append(sql_where)
758
-
759
- ## Part 'GROUP BY' syntax.
760
- if group is not None:
761
- sql_group = f'GROUP BY {group}'
762
- sql_list.append(sql_group)
763
-
764
- ## Part 'GROUP BY' syntax.
765
- if having is not None:
766
- sql_having = f'HAVING {having}'
767
- sql_list.append(sql_having)
768
-
769
- ## Part 'ORDER BY' syntax.
770
- if order is not None:
771
- sql_order = f'ORDER BY {order}'
772
- sql_list.append(sql_order)
773
-
774
- ## Part 'LIMIT' syntax.
775
- if limit is not None:
776
- if type(limit) in (str, int):
777
- sql_limit = f'LIMIT {limit}'
778
- else:
779
- if len(limit) == 2:
780
- sql_limit = f'LIMIT {limit[0]}, {limit[1]}'
781
- else:
782
- throw(ValueError, limit)
783
- sql_list.append(sql_limit)
784
-
785
- ## Join sql part.
786
- sql = '\n'.join(sql_list)
787
-
788
- # Execute SQL.
789
- result = self.execute(sql, report=report, **kwdata)
790
-
791
- return result
792
-
793
-
794
- def execute_insert(
795
- self,
796
- path: str | tuple[str, str],
797
- data: TableData,
798
- duplicate: Literal['ignore', 'update'] | Container[str] | None = None,
799
- report: bool | None = None,
800
- **kwdata: Any
801
- ) -> Result:
802
- """
803
- Insert the data of table in the datebase.
804
-
805
- Parameters
806
- ----------
807
- path : Table name, can contain database name, otherwise use `self.database`.
808
- - `str`: Automatic extract database name and table name.
809
- - `tuple[str, str]`: Database name and table name.
810
- data : Insert data.
811
- duplicate : Handle method when constraint error.
812
- - `None`: Not handled.
813
- - `ignore`: Use `UPDATE IGNORE INTO` clause.
814
- - `update`: Use `ON DUPLICATE KEY UPDATE` clause and update all fields.
815
- - `Container[str]`: Use `ON DUPLICATE KEY UPDATE` clause and update this fields.
816
- report : Whether report SQL execute information.
817
- - `None`, Use attribute `report_execute_info`: of object `ROption`.
818
- - `int`: Use this value.
819
- kwdata : Keyword parameters for filling.
820
- - `str and first character is ':'`: Use this syntax.
821
- - `Any`: Use this value.
822
-
823
- Returns
824
- -------
825
- Result object.
826
-
827
- Examples
828
- --------
829
- Parameter `data` and `kwdata`.
830
- >>> data = [{'key': 'a'}, {'key': 'b'}]
831
- >>> kwdata = {'value1': 1, 'value2': ':(SELECT 2)'}
832
- >>> result = Database.execute_insert('database.table', data, **kwdata)
833
- >>> print(result.rowcount)
834
- 2
835
- >>> result = Database.execute_select('database.table')
836
- >>> print(result.to_table())
837
- [{'key': 'a', 'value1': 1, 'value2': 2}, {'key': 'b', 'value1': 1, 'value2': 2}]
838
- """
839
-
840
- # Handle parameter.
841
- database, table, _ = self.extract_path(path)
842
-
843
- # Handle parameter.
844
-
845
- ## Data.
846
- data_table = Table(data)
847
- data = data_table.to_table()
848
-
849
- ## Check.
850
- if data in ([], [{}]):
851
- throw(ValueError, data)
852
-
853
- ## Keyword data.
854
- kwdata_method = {}
855
- kwdata_replace = {}
856
- for key, value in kwdata.items():
857
- if (
858
- type(value) == str
859
- and value.startswith(':')
860
- and value != ':'
861
- ):
862
- kwdata_method[key] = value[1:]
863
- else:
864
- kwdata_replace[key] = value
865
-
866
- # Generate SQL.
867
-
868
- ## Part 'fields' syntax.
869
- fields_replace = {
870
- field
871
- for row in data
872
- for field in row
873
- }
874
- fields_replace = {
875
- field
876
- for field in fields_replace
877
- if field not in kwdata
878
- }
879
- sql_fields_list = (
880
- *kwdata_method,
881
- *kwdata_replace,
882
- *fields_replace
883
- )
884
- sql_fields = ', '.join(
885
- [
886
- f'`{field}`'
887
- for field in sql_fields_list
888
- ]
889
- )
890
-
891
- ## Part 'values' syntax.
892
- sql_values_list = (
893
- *kwdata_method.values(),
894
- *[
895
- ':' + field
896
- for field in (
897
- *kwdata_replace,
898
- *fields_replace
899
- )
900
- ]
901
- )
902
- sql_values = ', '.join(sql_values_list)
903
-
904
- ## Join sql part.
905
- match duplicate:
906
-
907
- ### Not handle.
908
- case None:
909
- sql = (
910
- f'INSERT INTO `{database}`.`{table}`({sql_fields})\n'
911
- f'VALUES({sql_values})'
912
- )
913
-
914
- ### Ignore.
915
- case 'ignore':
916
- sql = (
917
- f'INSERT IGNORE INTO `{database}`.`{table}`({sql_fields})\n'
918
- f'VALUES({sql_values})'
919
- )
920
-
921
- ### Update.
922
- case _:
923
- sql_fields_list_update = sql_fields_list
924
- if duplicate != 'update':
925
- sql_fields_list_update = [
926
- field
927
- for field in sql_fields_list
928
- if field in duplicate
929
- ]
930
- update_content = ',\n '.join(
931
- [
932
- f'`{field}` = VALUES(`{field}`)'
933
- for field in sql_fields_list_update
934
- ]
935
- )
936
- sql = (
937
- f'INSERT INTO `{database}`.`{table}`({sql_fields})\n'
938
- f'VALUES({sql_values})\n'
939
- 'ON DUPLICATE KEY UPDATE\n'
940
- f' {update_content}'
941
- )
942
-
943
- # Execute SQL.
944
- result = self.execute(sql, data, report, **kwdata_replace)
945
-
946
- return result
947
-
948
-
949
- def execute_update(
950
- self,
951
- path: str | tuple[str, str],
952
- data: TableData,
953
- where_fields: str | Iterable[str] | None = None,
954
- report: bool | None = None,
955
- **kwdata: Any
956
- ) -> Result:
957
- """
958
- Update the data of table in the datebase.
959
-
960
- Parameters
961
- ----------
962
- path : Table name, can contain database name, otherwise use `self.database`.
963
- - `str`: Automatic extract database name and table name.
964
- - `tuple[str, str]`: Database name and table name.
965
- data : Update data, clause `SET` and `WHERE` and `ORDER BY` and `LIMIT` content.
966
- - `Key`: Table field.
967
- `literal['order']`: Clause `ORDER BY` content, join as `ORDER BY str`.
968
- `literal['limit']`: Clause `LIMIT` content, join as `LIMIT str`.
969
- `Other`: Clause `SET` and `WHERE` content.
970
- - `Value`: Table value.
971
- `list | tuple`: Join as `field IN :str`.
972
- `Any`: Join as `field = :str`.
973
- where_fields : Clause `WHERE` content fields.
974
- - `None`: The first key value pair of each item is judged.
975
- - `str`: This key value pair of each item is judged.
976
- - `Iterable[str]`: Multiple judged, `and`: relationship.
977
- report : Whether report SQL execute information.
978
- - `None`, Use attribute `report_execute_info`: of object `ROption`.
979
- - `int`: Use this value.
980
- kwdata : Keyword parameters for filling.
981
- - `str and first character is ':'`: Use this syntax.
982
- - `Any`: Use this value.
983
-
984
- Returns
985
- -------
986
- Result object.
987
-
988
- Examples
989
- --------
990
- Parameter `data` and `kwdata`.
991
- >>> data = [{'key': 'a'}, {'key': 'b'}]
992
- >>> kwdata = {'value': 1, 'name': ':`key`'}
993
- >>> result = Database.execute_update('database.table', data, **kwdata)
994
- >>> print(result.rowcount)
995
- 2
996
- >>> result = Database.execute_select('database.table')
997
- >>> print(result.to_table())
998
- [{'key': 'a', 'value': 1, 'name': 'a'}, {'key': 'b', 'value': 1, 'name': 'b'}]
999
- """
1000
-
1001
- # Handle parameter.
1002
- database, table, _ = self.extract_path(path)
1003
-
1004
- # Handle parameter.
1005
-
1006
- ## Data.
1007
- data_table = Table(data)
1008
- data = data_table.to_table()
1009
-
1010
- ## Check.
1011
- if data in ([], [{}]):
1012
- throw(ValueError, data)
1013
-
1014
- ## Keyword data.
1015
- kwdata_method = {}
1016
- kwdata_replace = {}
1017
- for key, value in kwdata.items():
1018
- if (
1019
- type(value) == str
1020
- and value.startswith(':')
1021
- and value != ':'
1022
- ):
1023
- kwdata_method[key] = value[1:]
1024
- else:
1025
- kwdata_replace[key] = value
1026
- sql_set_list_kwdata = [
1027
- f'`{key}` = {value}'
1028
- for key, value in kwdata_method.items()
1029
- ]
1030
- sql_set_list_kwdata.extend(
1031
- [
1032
- f'`{key}` = :{key}'
1033
- for key in kwdata_replace
1034
- ]
1035
- )
1036
-
1037
- # Generate SQL.
1038
- data_flatten = kwdata_replace
1039
- if where_fields is None:
1040
- no_where = True
1041
- else:
1042
- no_where = False
1043
- if type(where_fields) == str:
1044
- where_fields = [where_fields]
1045
- sqls_list = []
1046
- sql_update = f'UPDATE `{database}`.`{table}`'
1047
- for index, row in enumerate(data):
1048
- sql_parts = [sql_update]
1049
- for key, value in row.items():
1050
- if key in ('order', 'limit'):
1051
- continue
1052
- index_key = f'{index}_{key}'
1053
- data_flatten[index_key] = value
1054
- if no_where:
1055
- for key in row:
1056
- where_fields = [key]
1057
- break
1058
-
1059
- ## Part 'SET' syntax.
1060
- sql_set_list = sql_set_list_kwdata.copy()
1061
- sql_set_list.extend(
1062
- [
1063
- f'`{key}` = :{index}_{key}'
1064
- for key in row
1065
- if (
1066
- key not in where_fields
1067
- and key not in kwdata
1068
- and key not in ('order', 'limit')
1069
- )
1070
- ]
1071
- )
1072
- sql_set = 'SET ' + ',\n '.join(sql_set_list)
1073
- sql_parts.append(sql_set)
1074
-
1075
- ## Part 'WHERE' syntax.
1076
- sql_where_list = []
1077
- for field in where_fields:
1078
- index_field = f'{index}_{field}'
1079
- index_value = data_flatten[index_field]
1080
- if type(index_value) in (list, tuple):
1081
- sql_where_part = f'`{field}` IN :{index_field}'
1082
- else:
1083
- sql_where_part = f'`{field}` = :{index_field}'
1084
- sql_where_list.append(sql_where_part)
1085
- sql_where = 'WHERE ' + '\n AND '.join(sql_where_list)
1086
- sql_parts.append(sql_where)
1087
-
1088
- ## Part 'ORDER BY' syntax.
1089
- order = row.get('order')
1090
- if order is not None:
1091
- sql_order = f'ORDER BY {order}'
1092
- sql_parts.append(sql_order)
1093
-
1094
- ## Part 'LIMIT' syntax.
1095
- limit = row.get('limit')
1096
- if limit is not None:
1097
- sql_limit = f'LIMIT {limit}'
1098
- sql_parts.append(sql_limit)
1099
-
1100
- ## Join sql part.
1101
- sql = '\n'.join(sql_parts)
1102
- sqls_list.append(sql)
1103
-
1104
- ## Join sqls.
1105
- sqls = ';\n'.join(sqls_list)
1106
-
1107
- # Execute SQL.
1108
- result = self.execute(sqls, data_flatten, report)
1109
-
1110
- return result
1111
-
1112
-
1113
- def execute_delete(
1114
- self,
1115
- path: str | tuple[str, str],
1116
- where: str | None = None,
1117
- order: str | None = None,
1118
- limit: int | str | None = None,
1119
- report: bool | None = None,
1120
- **kwdata: Any
1121
- ) -> Result:
1122
- """
1123
- Delete the data of table in the datebase.
1124
-
1125
- Parameters
1126
- ----------
1127
- path : Table name, can contain database name, otherwise use `self.database`.
1128
- - `str`: Automatic extract database name and table name.
1129
- - `tuple[str, str]`: Database name and table name.
1130
- where : Clause `WHERE` content, join as `WHERE str`.
1131
- order : Clause `ORDER BY` content, join as `ORDER BY str`.
1132
- limit : Clause `LIMIT` content, join as `LIMIT int/str`.
1133
- report : Whether report SQL execute information.
1134
- - `None`, Use attribute `report_execute_info`: of object `ROption`.
1135
- - `int`: Use this value.
1136
- kwdata : Keyword parameters for filling.
1137
-
1138
- Returns
1139
- -------
1140
- Result object.
1141
-
1142
- Examples
1143
- --------
1144
- Parameter `where` and `kwdata`.
1145
- >>> where = '`id` IN :ids'
1146
- >>> ids = (1, 2)
1147
- >>> result = Database.execute_delete('database.table', where, ids=ids)
1148
- >>> print(result.rowcount)
1149
- 2
1150
- """
1151
-
1152
- # Handle parameter.
1153
- database, table, _ = self.extract_path(path)
1154
-
1155
- # Generate SQL.
1156
- sqls = []
1157
-
1158
- ## Part 'DELETE' syntax.
1159
- sql_delete = f'DELETE FROM `{database}`.`{table}`'
1160
- sqls.append(sql_delete)
1161
-
1162
- ## Part 'WHERE' syntax.
1163
- if where is not None:
1164
- sql_where = f'WHERE {where}'
1165
- sqls.append(sql_where)
1166
-
1167
- ## Part 'ORDER BY' syntax.
1168
- if order is not None:
1169
- sql_order = f'ORDER BY {order}'
1170
- sqls.append(sql_order)
1171
-
1172
- ## Part 'LIMIT' syntax.
1173
- if limit is not None:
1174
- sql_limit = f'LIMIT {limit}'
1175
- sqls.append(sql_limit)
1176
-
1177
- ## Join sqls.
1178
- sqls = '\n'.join(sqls)
1179
-
1180
- # Execute SQL.
1181
- result = self.execute(sqls, report=report, **kwdata)
1182
-
1183
- return result
1184
-
1185
-
1186
- def execute_copy(
1187
- self,
1188
- path: str | tuple[str, str],
1189
- where: str | None = None,
1190
- limit: int | str | tuple[int, int] | None = None,
1191
- report: bool | None = None,
1192
- **kwdata: Any
1193
- ) -> Result:
1194
- """
1195
- Copy record of table in the datebase.
1196
-
1197
- Parameters
1198
- ----------
1199
- path : Table name, can contain database name, otherwise use `self.database`.
1200
- - `str`: Automatic extract database name and table name.
1201
- - `tuple[str, str]`: Database name and table name.
1202
- where : Clause `WHERE` content, join as `WHERE str`.
1203
- limit : Clause `LIMIT` content.
1204
- - `int | str`: Join as `LIMIT int/str`.
1205
- - `tuple[int, int]`: Join as `LIMIT int, int`.
1206
- report : Whether report SQL execute information.
1207
- - `None`, Use attribute `report_execute_info`: of object `ROption`.
1208
- - `int`: Use this value.
1209
- kwdata : Keyword parameters for filling.
1210
- - `In 'WHERE' syntax`: Fill 'WHERE' syntax.
1211
- - `Not in 'WHERE' syntax`: Fill 'INSERT' and 'SELECT' syntax.
1212
- `str and first character is ':'`: Use this syntax.
1213
- `Any`: Use this value.
1214
-
1215
- Returns
1216
- -------
1217
- Result object.
1218
-
1219
- Examples
1220
- --------
1221
- Parameter `where` and `kwdata`.
1222
- >>> where = '`id` IN :ids'
1223
- >>> ids = (1, 2, 3)
1224
- >>> result = Database.execute_copy('database.table', where, 2, ids=ids, id=None, time=':NOW()')
1225
- >>> print(result.rowcount)
1226
- 2
1227
- """
1228
-
1229
- # Handle parameter.
1230
- database, table, _ = self.extract_path(path)
1231
- table_info: list[dict] = self.info(database)(table)()
1232
-
1233
- ## SQLite.
1234
- if self.backend == 'sqlite':
1235
- field_key = 'name'
1236
-
1237
- ## Other.
1238
- else:
1239
- field_key = 'COLUMN_NAME'
1240
-
1241
- fields = [
1242
- row[field_key]
1243
- for row in table_info
1244
- ]
1245
- pattern = '(?<!\\\\):(\\w+)'
1246
- if type(where) == str:
1247
- where_keys = findall(pattern, where)
1248
- else:
1249
- where_keys = ()
1250
-
1251
- # Generate SQL.
1252
- sqls = []
1253
-
1254
- ## Part 'INSERT' syntax.
1255
- sql_fields = ', '.join(
1256
- f'`{field}`'
1257
- for field in fields
1258
- if field not in kwdata
1259
- )
1260
- if kwdata != {}:
1261
- sql_fields_kwdata = ', '.join(
1262
- f'`{field}`'
1263
- for field in kwdata
1264
- if field not in where_keys
1265
- )
1266
- sql_fields_filter = filter(
1267
- lambda sql: sql != '',
1268
- (
1269
- sql_fields,
1270
- sql_fields_kwdata
1271
- )
1272
- )
1273
- sql_fields = ', '.join(sql_fields_filter)
1274
- sql_insert = f'INSERT INTO `{database}`.`{table}`({sql_fields})'
1275
- sqls.append(sql_insert)
1276
-
1277
- ## Part 'SELECT' syntax.
1278
- sql_values = ', '.join(
1279
- f'`{field}`'
1280
- for field in fields
1281
- if field not in kwdata
1282
- )
1283
- if kwdata != {}:
1284
- sql_values_kwdata = ', '.join(
1285
- value[1:]
1286
- if (
1287
- type(value) == str
1288
- and value.startswith(':')
1289
- and value != ':'
1290
- )
1291
- else f':{field}'
1292
- for field, value in kwdata.items()
1293
- if field not in where_keys
1294
- )
1295
- sql_values_filter = filter(
1296
- lambda sql: sql != '',
1297
- (
1298
- sql_values,
1299
- sql_values_kwdata
1300
- )
1301
- )
1302
- sql_values = ', '.join(sql_values_filter)
1303
- sql_select = (
1304
- f'SELECT {sql_values}\n'
1305
- f'FROM `{database}`.`{table}`'
1306
- )
1307
- sqls.append(sql_select)
1308
-
1309
- ## Part 'WHERE' syntax.
1310
- if where is not None:
1311
- sql_where = f'WHERE {where}'
1312
- sqls.append(sql_where)
1313
-
1314
- ## Part 'LIMIT' syntax.
1315
- if limit is not None:
1316
- if type(limit) in (str, int):
1317
- sql_limit = f'LIMIT {limit}'
1318
- else:
1319
- if len(limit) == 2:
1320
- sql_limit = f'LIMIT {limit[0]}, {limit[1]}'
1321
- else:
1322
- throw(ValueError, limit)
1323
- sqls.append(sql_limit)
1324
-
1325
- ## Join.
1326
- sql = '\n'.join(sqls)
1327
-
1328
- # Execute SQL.
1329
- result = self.execute(sql, report=report, **kwdata)
1330
-
1331
- return result
1332
-
1333
-
1334
- def execute_count(
1335
- self,
1336
- path: str | tuple[str, str],
1337
- where: str | None = None,
1338
- report: bool | None = None,
1339
- **kwdata: Any
1340
- ) -> int:
1341
- """
1342
- Count records.
1343
-
1344
- Parameters
1345
- ----------
1346
- path : Table name, can contain database name, otherwise use `self.database`.
1347
- - `str`: Automatic extract database name and table name.
1348
- - `tuple[str, str]`: Database name and table name.
1349
- where : Match condition, `WHERE` clause content, join as `WHERE str`.
1350
- - `None`: Match all.
1351
- - `str`: Match condition.
1352
- report : Whether report SQL execute information.
1353
- - `None`, Use attribute `report_execute_info`: of object `ROption`.
1354
- - `int`: Use this value.
1355
- kwdata : Keyword parameters for filling.
1356
-
1357
- Returns
1358
- -------
1359
- Record count.
1360
-
1361
- Examples
1362
- --------
1363
- Parameter `where` and `kwdata`.
1364
- >>> where = '`id` IN :ids'
1365
- >>> ids = (1, 2)
1366
- >>> result = Database.execute_count('database.table', where, ids=ids)
1367
- >>> print(result)
1368
- 2
1369
- """
1370
-
1371
- # Handle parameter.
1372
- database, table, _ = self.extract_path(path)
1373
-
1374
- # Execute.
1375
- result = self.execute_select((database, table), '1', where=where, report=report, **kwdata)
1376
- count = len(tuple(result))
1377
-
1378
- return count
1379
-
1380
-
1381
- def execute_exist(
1382
- self,
1383
- path: str | tuple[str, str],
1384
- where: str | None = None,
1385
- report: bool | None = None,
1386
- **kwdata: Any
1387
- ) -> bool:
1388
- """
1389
- Judge the exist of record.
1390
-
1391
- Parameters
1392
- ----------
1393
- path : Table name, can contain database name, otherwise use `self.database`.
1394
- - `str`: Automatic extract database name and table name.
1395
- - `tuple[str, str]`: Database name and table name.
1396
- where : Match condition, `WHERE` clause content, join as `WHERE str`.
1397
- - `None`: Match all.
1398
- - `str`: Match condition.
1399
- report : Whether report SQL execute information.
1400
- - `None`, Use attribute `report_execute_info`: of object `ROption`.
1401
- - `int`: Use this value.
1402
- kwdata : Keyword parameters for filling.
1403
-
1404
- Returns
1405
- -------
1406
- Judged result.
1407
-
1408
- Examples
1409
- --------
1410
- Parameter `where` and `kwdata`.
1411
- >>> data = [{'id': 1}]
1412
- >>> Database.execute_insert('database.table', data)
1413
- >>> where = '`id` = :id_'
1414
- >>> id_ = 1
1415
- >>> result = Database.execute_exist('database.table', where, id_=id_)
1416
- >>> print(result)
1417
- True
1418
- """
1419
-
1420
- # Handle parameter.
1421
- database, table, _ = self.extract_path(path)
1422
-
1423
- # Execute.
1424
- result = self.execute_count(path, where, report, **kwdata)
1425
-
1426
- # Judge.
1427
- judge = result != 0
1428
-
1429
- return judge
1430
-
1431
-
1432
- def execute_generator(
1433
- self,
1434
- sql: str | TextClause,
1435
- data: TableData,
1436
- report: bool | None = None,
1437
- **kwdata: Any
1438
- ) -> Generator[Result, Any, None]:
1439
- """
1440
- Return a generator that can execute SQL.
211
+ Build `DatabaseConnection` instance.
1441
212
 
1442
213
  Parameters
1443
214
  ----------
1444
- sql : SQL in method `sqlalchemy.text` format, or `TextClause` object.
1445
- data : Data set for filling.
1446
- report : Whether report SQL execute information.
1447
- - `None`: Use attribute `default_report`.
1448
- - `bool`: Use this value.
1449
- kwdata : Keyword parameters for filling.
1450
-
1451
- Returns
1452
- -------
1453
- Generator.
1454
- """
1455
-
1456
- # Instance.
1457
- generator = Generator(
1458
- self.execute,
1459
- sql=sql,
1460
- report=report,
1461
- **kwdata
1462
- )
1463
-
1464
- # Add.
1465
- for row in data:
1466
- generator(**row)
1467
-
1468
- return generator.generator
1469
-
1470
-
1471
- def connect(self):
1472
- """
1473
- Build `DatabaseConnection` instance.
215
+ autocommit: Whether automatic commit connection.
1474
216
 
1475
217
  Returns
1476
218
  -------
@@ -1481,86 +223,26 @@ class Database(DatabaseBase):
1481
223
  from .rconn import DatabaseConnection
1482
224
 
1483
225
  # Build.
1484
- dbconnection = DatabaseConnection(
1485
- self.engine.connect(),
1486
- self
1487
- )
226
+ conn = DatabaseConnection(self, autocommit)
1488
227
 
1489
- return dbconnection
228
+ return conn
1490
229
 
1491
230
 
1492
231
  @property
1493
- def exe(self):
232
+ def execute(self):
1494
233
  """
1495
- Build `database path` instance.
234
+ Build `database execute` instance.
1496
235
 
1497
236
  Returns
1498
237
  -------
1499
238
  Instance.
1500
-
1501
- Examples
1502
- --------
1503
- Execute.
1504
- >>> sql = 'select :value'
1505
- >>> result = DatabaseExecute(sql, value=1)
1506
-
1507
- Select.
1508
- >>> field = ['id', 'value']
1509
- >>> where = '`id` = ids'
1510
- >>> ids = (1, 2)
1511
- >>> result = DatabaseExecute.database.table(field, where, ids=ids)
1512
-
1513
- Insert.
1514
- >>> data = [{'id': 1}, {'id': 2}]
1515
- >>> duplicate = 'ignore'
1516
- >>> result = DatabaseExecute.database.table + data
1517
- >>> result = DatabaseExecute.database.table + (data, duplicate)
1518
- >>> result = DatabaseExecute.database.table + {'data': data, 'duplicate': duplicate}
1519
-
1520
- Update.
1521
- >>> data = [{'name': 'a', 'id': 1}, {'name': 'b', 'id': 2}]
1522
- >>> where_fields = 'id'
1523
- >>> result = DatabaseExecute.database.table & data
1524
- >>> result = DatabaseExecute.database.table & (data, where_fields)
1525
- >>> result = DatabaseExecute.database.table & {'data': data, 'where_fields': where_fields}
1526
-
1527
- Delete.
1528
- >>> where = '`id` IN (1, 2)'
1529
- >>> report = True
1530
- >>> result = DatabaseExecute.database.table - where
1531
- >>> result = DatabaseExecute.database.table - (where, report)
1532
- >>> result = DatabaseExecute.database.table - {'where': where, 'report': report}
1533
-
1534
- Copy.
1535
- >>> where = '`id` IN (1, 2)'
1536
- >>> limit = 1
1537
- >>> result = DatabaseExecute.database.table * where
1538
- >>> result = DatabaseExecute.database.table * (where, limit)
1539
- >>> result = DatabaseExecute.database.table * {'where': where, 'limit': limit}
1540
-
1541
- Exist.
1542
- >>> where = '`id` IN (1, 2)'
1543
- >>> report = True
1544
- >>> result = where in DatabaseExecute.database.table
1545
- >>> result = (where, report) in DatabaseExecute.database.table
1546
- >>> result = {'where': where, 'report': report} in DatabaseExecute.database.table
1547
-
1548
- Count.
1549
- >>> result = len(DatabaseExecute.database.table)
1550
-
1551
- Default database.
1552
- >>> field = ['id', 'value']
1553
- >>> engine = Database(**server, database)
1554
- >>> result = engine.exe.table()
1555
239
  """
1556
240
 
1557
- # Import.
1558
- from .rexec import DatabaseExecute
1559
-
1560
241
  # Build.
1561
- dbexecute = DatabaseExecute(self)
242
+ dbconn = self.connect(True)
243
+ exec = dbconn.execute
1562
244
 
1563
- return dbexecute
245
+ return exec
1564
246
 
1565
247
 
1566
248
  def schema(self, filter_default: bool = True) -> dict[str, dict[str, list[str]]]:
@@ -1576,11 +258,6 @@ class Database(DatabaseBase):
1576
258
  Schemata of databases and tables and columns.
1577
259
  """
1578
260
 
1579
- # Check.
1580
- if self.backend == 'sqlite':
1581
- text = 'not suitable for SQLite databases'
1582
- throw(AssertionError, text=text)
1583
-
1584
261
  # Handle parameter.
1585
262
  filter_db = (
1586
263
  'information_schema',
@@ -1645,7 +322,7 @@ class Database(DatabaseBase):
1645
322
 
1646
323
  Returns
1647
324
  -------
1648
- Database schema information instance.
325
+ Instance.
1649
326
 
1650
327
  Examples
1651
328
  --------
@@ -1684,7 +361,7 @@ class Database(DatabaseBase):
1684
361
 
1685
362
  Returns
1686
363
  -------
1687
- Database build instance.
364
+ Instance.
1688
365
  """
1689
366
 
1690
367
  # Import.
@@ -1703,7 +380,7 @@ class Database(DatabaseBase):
1703
380
 
1704
381
  Returns
1705
382
  -------
1706
- Database file instance.
383
+ Instance.
1707
384
  """
1708
385
 
1709
386
  # Import.
@@ -1722,7 +399,7 @@ class Database(DatabaseBase):
1722
399
 
1723
400
  Returns
1724
401
  -------
1725
- Database file instance.
402
+ Instance.
1726
403
  """
1727
404
 
1728
405
  # Import.
@@ -1741,7 +418,7 @@ class Database(DatabaseBase):
1741
418
 
1742
419
  Returns
1743
420
  -------
1744
- Database file instance.
421
+ Instance.
1745
422
  """
1746
423
 
1747
424
  # Import.
@@ -1756,108 +433,79 @@ class Database(DatabaseBase):
1756
433
  @property
1757
434
  def status(self):
1758
435
  """
1759
- Build `DatabaseParametersStatus` or `DatabaseParametersPragma` instance.
436
+ Build `DatabaseParametersStatus` instance.
1760
437
 
1761
438
  Returns
1762
439
  -------
1763
- Database status parameters instance.
440
+ Instance.
1764
441
  """
1765
442
 
1766
443
  # Import.
1767
- from .rparam import DatabaseParametersStatus, DatabaseParametersPragma
444
+ from .rparam import DatabaseParametersStatus
1768
445
 
1769
446
  # Build.
447
+ dbps = DatabaseParametersStatus(self, False)
1770
448
 
1771
- ## SQLite.
1772
- if self.backend == 'sqlite':
1773
- dbp = DatabaseParametersPragma(self)
1774
-
1775
- ## Other.
1776
- else:
1777
- dbp = DatabaseParametersStatus(self, False)
1778
-
1779
- return dbp
449
+ return dbps
1780
450
 
1781
451
 
1782
452
  @property
1783
453
  def global_status(self):
1784
454
  """
1785
- Build `DatabaseParametersStatus` or `DatabaseParametersPragma` instance.
455
+ Build global `DatabaseParametersStatus` instance.
1786
456
 
1787
457
  Returns
1788
458
  -------
1789
- Global database status parameters instance.
459
+ Instance.
1790
460
  """
1791
461
 
1792
462
  # Import.
1793
- from .rparam import DatabaseParametersStatus, DatabaseParametersPragma
463
+ from .rparam import DatabaseParametersStatus
1794
464
 
1795
465
  # Build.
466
+ dbps = DatabaseParametersStatus(self, True)
1796
467
 
1797
- ## SQLite.
1798
- if self.backend == 'sqlite':
1799
- dbp = DatabaseParametersPragma(self)
1800
-
1801
- ## Other.
1802
- else:
1803
- dbp = DatabaseParametersStatus(self, True)
1804
-
1805
- return dbp
468
+ return dbps
1806
469
 
1807
470
 
1808
471
  @property
1809
472
  def variables(self):
1810
473
  """
1811
- Build `DatabaseParametersVariable` or `DatabaseParametersPragma` instance.
474
+ Build `DatabaseParametersVariable` instance.
1812
475
 
1813
476
  Returns
1814
477
  -------
1815
- Database variable parameters instance.
478
+ Instance.
1816
479
  """
1817
480
 
1818
481
  # Import.
1819
- from .rparam import DatabaseParametersVariable, DatabaseParametersPragma
482
+ from .rparam import DatabaseParametersVariable
1820
483
 
1821
484
  # Build.
485
+ dbpv = DatabaseParametersVariable(self, False)
1822
486
 
1823
- ## SQLite.
1824
- if self.backend == 'sqlite':
1825
- dbp = DatabaseParametersPragma(self)
1826
-
1827
- ## Other.
1828
- else:
1829
- dbp = DatabaseParametersVariable(self, False)
1830
-
1831
- return dbp
487
+ return dbpv
1832
488
 
1833
489
 
1834
490
  @property
1835
491
  def global_variables(self):
1836
492
  """
1837
- Build global `database variable parameters` instance.
493
+ Build global `DatabaseParametersVariable` instance.
1838
494
 
1839
495
  Returns
1840
496
  -------
1841
- Global database variable parameters instance.
497
+ Instance.
1842
498
  """
1843
499
 
1844
500
  # Import.
1845
- from .rparam import DatabaseParametersVariable, DatabaseParametersPragma
501
+ from .rparam import DatabaseParametersVariable
1846
502
 
1847
503
  # Build.
1848
504
 
1849
505
  ## SQLite.
1850
- if self.backend == 'sqlite':
1851
- dbp = DatabaseParametersPragma(self)
1852
-
1853
- ## Other.
1854
- else:
1855
- dbp = DatabaseParametersVariable(self, True)
1856
-
1857
- return dbp
1858
-
506
+ dbpv = DatabaseParametersVariable(self, True)
1859
507
 
1860
- __call__ = execute
508
+ return dbpv
1861
509
 
1862
510
 
1863
511
  def __str__(self) -> str:
@@ -1865,16 +513,6 @@ class Database(DatabaseBase):
1865
513
  Return connection information text.
1866
514
  """
1867
515
 
1868
- # Handle parameter.
1869
- if hasattr(self, 'engine'):
1870
- attr_dict = self.__dict__
1871
- else:
1872
- rdatabase: Database = self.rdatabase
1873
- attr_dict = {
1874
- **self.__dict__,
1875
- **rdatabase.__dict__
1876
- }
1877
-
1878
516
  # Generate.
1879
517
  filter_key = (
1880
518
  'engine',
@@ -1884,10 +522,10 @@ class Database(DatabaseBase):
1884
522
  )
1885
523
  info = {
1886
524
  key: value
1887
- for key, value in attr_dict.items()
525
+ for key, value in self.__dict__.items()
1888
526
  if key not in filter_key
1889
527
  }
1890
- info['count'] = self.count
528
+ info['count'] = self.count_conn
1891
529
  text = join_data_text(info)
1892
530
 
1893
531
  return text