meerschaum 2.5.1__py3-none-any.whl → 2.6.0.dev1__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.
- meerschaum/_internal/arguments/_parser.py +6 -1
- meerschaum/actions/edit.py +6 -6
- meerschaum/actions/sql.py +12 -11
- meerschaum/config/_edit.py +46 -19
- meerschaum/config/_read_config.py +20 -9
- meerschaum/config/_version.py +1 -1
- meerschaum/config/stack/__init__.py +1 -1
- meerschaum/connectors/sql/_pipes.py +80 -24
- meerschaum/connectors/sql/_sql.py +29 -10
- meerschaum/connectors/valkey/_pipes.py +1 -1
- meerschaum/core/Pipe/__init__.py +8 -9
- meerschaum/core/Pipe/_attributes.py +33 -11
- meerschaum/core/Pipe/_data.py +26 -7
- meerschaum/core/Pipe/_dtypes.py +4 -4
- meerschaum/core/Pipe/_fetch.py +1 -1
- meerschaum/core/Pipe/_sync.py +16 -4
- meerschaum/core/Pipe/_verify.py +1 -1
- meerschaum/utils/dataframe.py +56 -29
- meerschaum/utils/dtypes/__init__.py +16 -5
- meerschaum/utils/dtypes/sql.py +58 -28
- meerschaum/utils/misc.py +49 -16
- meerschaum/utils/sql.py +224 -40
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dev1.dist-info}/METADATA +1 -1
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dev1.dist-info}/RECORD +30 -30
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dev1.dist-info}/WHEEL +1 -1
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dev1.dist-info}/LICENSE +0 -0
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dev1.dist-info}/NOTICE +0 -0
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dev1.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dev1.dist-info}/top_level.txt +0 -0
- {meerschaum-2.5.1.dist-info → meerschaum-2.6.0.dev1.dist-info}/zip-safe +0 -0
meerschaum/utils/misc.py
CHANGED
@@ -214,20 +214,20 @@ def parse_config_substitution(
|
|
214
214
|
|
215
215
|
|
216
216
|
def edit_file(
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
217
|
+
path: Union['pathlib.Path', str],
|
218
|
+
default_editor: str = 'pyvim',
|
219
|
+
debug: bool = False
|
220
|
+
) -> bool:
|
221
221
|
"""
|
222
222
|
Open a file for editing.
|
223
|
-
|
223
|
+
|
224
224
|
Attempt to launch the user's defined `$EDITOR`, otherwise use `pyvim`.
|
225
225
|
|
226
226
|
Parameters
|
227
227
|
----------
|
228
228
|
path: Union[pathlib.Path, str]
|
229
229
|
The path to the file to be edited.
|
230
|
-
|
230
|
+
|
231
231
|
default_editor: str, default 'pyvim'
|
232
232
|
If `$EDITOR` is not set, use this instead.
|
233
233
|
If `pyvim` is not installed, it will install it from PyPI.
|
@@ -250,7 +250,7 @@ def edit_file(
|
|
250
250
|
rc = call([EDITOR, path])
|
251
251
|
except Exception as e: ### can't open with default editors
|
252
252
|
if debug:
|
253
|
-
dprint(e)
|
253
|
+
dprint(str(e))
|
254
254
|
dprint('Failed to open file with system editor. Falling back to pyvim...')
|
255
255
|
pyvim = attempt_import('pyvim', lazy=False)
|
256
256
|
rc = run_python_package('pyvim', [path], venv=package_venv(pyvim), debug=debug)
|
@@ -258,10 +258,10 @@ def edit_file(
|
|
258
258
|
|
259
259
|
|
260
260
|
def is_pipe_registered(
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
261
|
+
pipe: mrsm.Pipe,
|
262
|
+
pipes: PipesDict,
|
263
|
+
debug: bool = False
|
264
|
+
) -> bool:
|
265
265
|
"""
|
266
266
|
Check if a Pipe is inside the pipes dictionary.
|
267
267
|
|
@@ -269,10 +269,10 @@ def is_pipe_registered(
|
|
269
269
|
----------
|
270
270
|
pipe: meerschaum.Pipe
|
271
271
|
The pipe to see if it's in the dictionary.
|
272
|
-
|
272
|
+
|
273
273
|
pipes: PipesDict
|
274
274
|
The dictionary to search inside.
|
275
|
-
|
275
|
+
|
276
276
|
debug: bool, default False
|
277
277
|
Verbosity toggle.
|
278
278
|
|
@@ -1426,7 +1426,40 @@ def flatten_list(list_: List[Any]) -> List[Any]:
|
|
1426
1426
|
yield item
|
1427
1427
|
|
1428
1428
|
|
1429
|
-
def
|
1429
|
+
def parse_arguments_str(args_str: str) -> Tuple[Tuple[Any], Dict[str, Any]]:
|
1430
|
+
"""
|
1431
|
+
Parse a string containing the text to be passed into a function
|
1432
|
+
and return a tuple of args, kwargs.
|
1433
|
+
|
1434
|
+
Parameters
|
1435
|
+
----------
|
1436
|
+
args_str: str
|
1437
|
+
The contents of the function parameter (as a string).
|
1438
|
+
|
1439
|
+
Returns
|
1440
|
+
-------
|
1441
|
+
A tuple of args (tuple) and kwargs (dict[str, Any]).
|
1442
|
+
|
1443
|
+
Examples
|
1444
|
+
--------
|
1445
|
+
>>> parse_arguments_str('123, 456, foo=789, bar="baz"')
|
1446
|
+
(123, 456), {'foo': 789, 'bar': 'baz'}
|
1447
|
+
"""
|
1448
|
+
import ast
|
1449
|
+
args = []
|
1450
|
+
kwargs = {}
|
1451
|
+
|
1452
|
+
for part in args_str.split(','):
|
1453
|
+
if '=' in part:
|
1454
|
+
key, val = part.split('=', 1)
|
1455
|
+
kwargs[key.strip()] = ast.literal_eval(val)
|
1456
|
+
else:
|
1457
|
+
args.append(ast.literal_eval(part.strip()))
|
1458
|
+
|
1459
|
+
return tuple(args), kwargs
|
1460
|
+
|
1461
|
+
|
1462
|
+
def make_symlink(src_path: 'pathlib.Path', dest_path: 'pathlib.Path') -> SuccessTuple:
|
1430
1463
|
"""
|
1431
1464
|
Wrap around `pathlib.Path.symlink_to`, but add support for Windows.
|
1432
1465
|
|
@@ -1452,7 +1485,7 @@ def make_symlink(src_path: pathlib.Path, dest_path: pathlib.Path) -> SuccessTupl
|
|
1452
1485
|
msg = str(e)
|
1453
1486
|
if success:
|
1454
1487
|
return success, "Success"
|
1455
|
-
|
1488
|
+
|
1456
1489
|
### Failed to create a symlink.
|
1457
1490
|
### If we're not on Windows, return an error.
|
1458
1491
|
import platform
|
@@ -1477,7 +1510,7 @@ def make_symlink(src_path: pathlib.Path, dest_path: pathlib.Path) -> SuccessTupl
|
|
1477
1510
|
shutil.copy(src_path, dest_path)
|
1478
1511
|
except Exception as e:
|
1479
1512
|
return False, str(e)
|
1480
|
-
|
1513
|
+
|
1481
1514
|
return True, "Success"
|
1482
1515
|
|
1483
1516
|
|
meerschaum/utils/sql.py
CHANGED
@@ -16,6 +16,7 @@ from meerschaum.utils.dtypes.sql import (
|
|
16
16
|
PD_TO_DB_DTYPES_FLAVORS,
|
17
17
|
get_pd_type_from_db_type as get_pd_type,
|
18
18
|
get_db_type_from_pd_type as get_db_type,
|
19
|
+
TIMEZONE_NAIVE_FLAVORS,
|
19
20
|
)
|
20
21
|
from meerschaum.utils.warnings import warn
|
21
22
|
from meerschaum.utils.debug import dprint
|
@@ -186,8 +187,11 @@ columns_types_queries = {
|
|
186
187
|
COLUMN_NAME AS [column],
|
187
188
|
DATA_TYPE AS [type]
|
188
189
|
FROM {db_prefix}INFORMATION_SCHEMA.COLUMNS
|
189
|
-
WHERE TABLE_NAME
|
190
|
-
|
190
|
+
WHERE TABLE_NAME IN (
|
191
|
+
'{table}',
|
192
|
+
'{table_trunc}'
|
193
|
+
)
|
194
|
+
|
191
195
|
""",
|
192
196
|
'mysql': """
|
193
197
|
SELECT
|
@@ -349,9 +353,8 @@ def dateadd_str(
|
|
349
353
|
"CAST('2022-01-01 00:00:00' AS TIMESTAMP) + INTERVAL '1 day'"
|
350
354
|
|
351
355
|
"""
|
352
|
-
from meerschaum.utils.debug import dprint
|
353
356
|
from meerschaum.utils.packages import attempt_import
|
354
|
-
from meerschaum.utils.
|
357
|
+
from meerschaum.utils.dtypes.sql import get_db_type_from_pd_type
|
355
358
|
dateutil_parser = attempt_import('dateutil.parser')
|
356
359
|
if 'int' in str(type(begin)).lower():
|
357
360
|
return str(begin)
|
@@ -379,26 +382,32 @@ def dateadd_str(
|
|
379
382
|
begin = begin.astimezone(timezone.utc)
|
380
383
|
begin = (
|
381
384
|
f"'{begin.replace(tzinfo=None)}'"
|
382
|
-
if isinstance(begin, datetime)
|
385
|
+
if isinstance(begin, datetime) and flavor in TIMEZONE_NAIVE_FLAVORS
|
383
386
|
else f"'{begin}'"
|
384
387
|
)
|
385
388
|
|
389
|
+
dt_is_utc = begin_time.tzinfo is not None if begin_time is not None else '+' in str(begin)
|
390
|
+
db_type = get_db_type_from_pd_type(
|
391
|
+
('datetime64[ns, UTC]' if dt_is_utc else 'datetime64[ns]'),
|
392
|
+
flavor=flavor,
|
393
|
+
)
|
394
|
+
|
386
395
|
da = ""
|
387
396
|
if flavor in ('postgresql', 'timescaledb', 'cockroachdb', 'citus'):
|
388
397
|
begin = (
|
389
|
-
f"CAST({begin} AS
|
390
|
-
else "CAST(NOW() AT TIME ZONE 'utc' AS
|
398
|
+
f"CAST({begin} AS {db_type})" if begin != 'now'
|
399
|
+
else "CAST(NOW() AT TIME ZONE 'utc' AS {db_type})"
|
391
400
|
)
|
392
401
|
da = begin + (f" + INTERVAL '{number} {datepart}'" if number != 0 else '')
|
393
402
|
|
394
403
|
elif flavor == 'duckdb':
|
395
|
-
begin = f"CAST({begin} AS
|
404
|
+
begin = f"CAST({begin} AS {db_type})" if begin != 'now' else 'NOW()'
|
396
405
|
da = begin + (f" + INTERVAL '{number} {datepart}'" if number != 0 else '')
|
397
406
|
|
398
407
|
elif flavor in ('mssql',):
|
399
408
|
if begin_time and begin_time.microsecond != 0:
|
400
409
|
begin = begin[:-4] + "'"
|
401
|
-
begin = f"CAST({begin} AS
|
410
|
+
begin = f"CAST({begin} AS {db_type})" if begin != 'now' else 'GETUTCDATE()'
|
402
411
|
da = f"DATEADD({datepart}, {number}, {begin})" if number != 0 else begin
|
403
412
|
|
404
413
|
elif flavor in ('mysql', 'mariadb'):
|
@@ -425,9 +434,9 @@ def dateadd_str(
|
|
425
434
|
|
426
435
|
|
427
436
|
def test_connection(
|
428
|
-
|
429
|
-
|
430
|
-
|
437
|
+
self,
|
438
|
+
**kw: Any
|
439
|
+
) -> Union[bool, None]:
|
431
440
|
"""
|
432
441
|
Test if a successful connection to the database may be made.
|
433
442
|
|
@@ -454,11 +463,11 @@ def test_connection(
|
|
454
463
|
|
455
464
|
|
456
465
|
def get_distinct_col_count(
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
466
|
+
col: str,
|
467
|
+
query: str,
|
468
|
+
connector: Optional[mrsm.connectors.sql.SQLConnector] = None,
|
469
|
+
debug: bool = False
|
470
|
+
) -> Optional[int]:
|
462
471
|
"""
|
463
472
|
Returns the number of distinct items in a column of a SQL query.
|
464
473
|
|
@@ -624,10 +633,10 @@ def truncate_item_name(item: str, flavor: str) -> str:
|
|
624
633
|
|
625
634
|
|
626
635
|
def build_where(
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
636
|
+
params: Dict[str, Any],
|
637
|
+
connector: Optional[meerschaum.connectors.sql.SQLConnector] = None,
|
638
|
+
with_where: bool = True,
|
639
|
+
) -> str:
|
631
640
|
"""
|
632
641
|
Build the `WHERE` clause based on the input criteria.
|
633
642
|
|
@@ -769,7 +778,7 @@ def table_exists(
|
|
769
778
|
----------
|
770
779
|
table: str:
|
771
780
|
The name of the table in question.
|
772
|
-
|
781
|
+
|
773
782
|
connector: mrsm.connectors.sql.SQLConnector
|
774
783
|
The connector to the database which holds the table.
|
775
784
|
|
@@ -806,7 +815,7 @@ def get_sqlalchemy_table(
|
|
806
815
|
----------
|
807
816
|
table: str
|
808
817
|
The name of the table on the database. Does not need to be escaped.
|
809
|
-
|
818
|
+
|
810
819
|
connector: Optional[meerschaum.connectors.sql.SQLConnector], default None:
|
811
820
|
The connector to the database which holds the table.
|
812
821
|
|
@@ -822,7 +831,7 @@ def get_sqlalchemy_table(
|
|
822
831
|
|
823
832
|
Returns
|
824
833
|
-------
|
825
|
-
A `sqlalchemy.Table` object for the table.
|
834
|
+
A `sqlalchemy.Table` object for the table.
|
826
835
|
|
827
836
|
"""
|
828
837
|
if connector is None:
|
@@ -1325,35 +1334,48 @@ def get_rename_table_queries(
|
|
1325
1334
|
|
1326
1335
|
if_exists_str = "IF EXISTS" if flavor in DROP_IF_EXISTS_FLAVORS else ""
|
1327
1336
|
if flavor == 'duckdb':
|
1328
|
-
return
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1337
|
+
return (
|
1338
|
+
get_create_table_queries(
|
1339
|
+
f"SELECT * FROM {old_table_name}",
|
1340
|
+
tmp_table,
|
1341
|
+
'duckdb',
|
1342
|
+
schema,
|
1343
|
+
) + get_create_table_queries(
|
1344
|
+
f"SELECT * FROM {tmp_table_name}",
|
1345
|
+
new_table,
|
1346
|
+
'duckdb',
|
1347
|
+
schema,
|
1348
|
+
) + [
|
1349
|
+
f"DROP TABLE {if_exists_str} {tmp_table_name}",
|
1350
|
+
f"DROP TABLE {if_exists_str} {old_table_name}",
|
1351
|
+
]
|
1352
|
+
)
|
1334
1353
|
|
1335
1354
|
return [f"ALTER TABLE {old_table_name} RENAME TO {new_table_name}"]
|
1336
1355
|
|
1337
1356
|
|
1338
1357
|
def get_create_table_query(
|
1339
|
-
|
1358
|
+
query_or_dtypes: Union[str, Dict[str, str]],
|
1340
1359
|
new_table: str,
|
1341
1360
|
flavor: str,
|
1342
1361
|
schema: Optional[str] = None,
|
1343
1362
|
) -> str:
|
1344
1363
|
"""
|
1364
|
+
NOTE: This function is deprecated. Use `get_create_index_queries()` instead.
|
1365
|
+
|
1345
1366
|
Return a query to create a new table from a `SELECT` query.
|
1346
1367
|
|
1347
1368
|
Parameters
|
1348
1369
|
----------
|
1349
|
-
query: str
|
1370
|
+
query: Union[str, Dict[str, str]]
|
1350
1371
|
The select query to use for the creation of the table.
|
1372
|
+
If a dictionary is provided, return a `CREATE TABLE` query from the given `dtypes` columns.
|
1351
1373
|
|
1352
1374
|
new_table: str
|
1353
1375
|
The unquoted name of the new table.
|
1354
1376
|
|
1355
1377
|
flavor: str
|
1356
|
-
The database flavor to use for the query (e.g. `'mssql'`, `'postgresql'
|
1378
|
+
The database flavor to use for the query (e.g. `'mssql'`, `'postgresql'`).
|
1357
1379
|
|
1358
1380
|
schema: Optional[str], default None
|
1359
1381
|
The schema on which the table will reside.
|
@@ -1362,26 +1384,164 @@ def get_create_table_query(
|
|
1362
1384
|
-------
|
1363
1385
|
A `CREATE TABLE` (or `SELECT INTO`) query for the database flavor.
|
1364
1386
|
"""
|
1387
|
+
return get_create_table_queries(
|
1388
|
+
query_or_dtypes,
|
1389
|
+
new_table,
|
1390
|
+
flavor,
|
1391
|
+
schema=schema,
|
1392
|
+
primary_key=None,
|
1393
|
+
)[0]
|
1394
|
+
|
1395
|
+
|
1396
|
+
def get_create_table_queries(
|
1397
|
+
query_or_dtypes: Union[str, Dict[str, str]],
|
1398
|
+
new_table: str,
|
1399
|
+
flavor: str,
|
1400
|
+
schema: Optional[str] = None,
|
1401
|
+
primary_key: Optional[str] = None,
|
1402
|
+
) -> List[str]:
|
1403
|
+
"""
|
1404
|
+
Return a query to create a new table from a `SELECT` query or a `dtypes` dictionary.
|
1405
|
+
|
1406
|
+
Parameters
|
1407
|
+
----------
|
1408
|
+
query_or_dtypes: Union[str, Dict[str, str]]
|
1409
|
+
The select query to use for the creation of the table.
|
1410
|
+
If a dictionary is provided, return a `CREATE TABLE` query from the given `dtypes` columns.
|
1411
|
+
|
1412
|
+
new_table: str
|
1413
|
+
The unquoted name of the new table.
|
1414
|
+
|
1415
|
+
flavor: str
|
1416
|
+
The database flavor to use for the query (e.g. `'mssql'`, `'postgresql'`).
|
1417
|
+
|
1418
|
+
schema: Optional[str], default None
|
1419
|
+
The schema on which the table will reside.
|
1420
|
+
|
1421
|
+
primary_key: Optional[str], default None
|
1422
|
+
If provided, designate this column as the primary key in the new table.
|
1423
|
+
|
1424
|
+
Returns
|
1425
|
+
-------
|
1426
|
+
A `CREATE TABLE` (or `SELECT INTO`) query for the database flavor.
|
1427
|
+
"""
|
1428
|
+
if not isinstance(query_or_dtypes, (str, dict)):
|
1429
|
+
raise TypeError("`query_or_dtypes` must be a query or a dtypes dictionary.")
|
1430
|
+
|
1431
|
+
method = (
|
1432
|
+
_get_create_table_query_from_cte
|
1433
|
+
if isinstance(query_or_dtypes, str)
|
1434
|
+
else _get_create_table_query_from_dtypes
|
1435
|
+
)
|
1436
|
+
return method(
|
1437
|
+
query_or_dtypes,
|
1438
|
+
new_table,
|
1439
|
+
flavor,
|
1440
|
+
schema=schema,
|
1441
|
+
primary_key=primary_key,
|
1442
|
+
)
|
1443
|
+
|
1444
|
+
|
1445
|
+
def _get_create_table_query_from_dtypes(
|
1446
|
+
dtypes: Dict[str, str],
|
1447
|
+
new_table: str,
|
1448
|
+
flavor: str,
|
1449
|
+
schema: Optional[str] = None,
|
1450
|
+
primary_key: Optional[str] = None,
|
1451
|
+
) -> List[str]:
|
1452
|
+
"""
|
1453
|
+
Create a new table from a `dtypes` dictionary.
|
1454
|
+
"""
|
1455
|
+
from meerschaum.utils.dtypes.sql import get_db_type_from_pd_type, AUTO_INCREMENT_COLUMN_FLAVORS
|
1456
|
+
if not dtypes and not primary_key:
|
1457
|
+
raise ValueError(f"Expecting columns for table '{new_table}'.")
|
1458
|
+
|
1459
|
+
cols_types = (
|
1460
|
+
[(primary_key, get_db_type_from_pd_type(dtypes.get(primary_key, 'int')))]
|
1461
|
+
if primary_key
|
1462
|
+
else []
|
1463
|
+
) + [
|
1464
|
+
(col, get_db_type_from_pd_type(typ))
|
1465
|
+
for col, typ in dtypes.items()
|
1466
|
+
if col != primary_key
|
1467
|
+
]
|
1468
|
+
|
1469
|
+
table_name = sql_item_name(new_table, schema=schema, flavor=flavor)
|
1470
|
+
query = f"CREATE TABLE {table_name} ("
|
1471
|
+
if primary_key:
|
1472
|
+
col_db_type = cols_types[0][1]
|
1473
|
+
auto_increment = (' ' + AUTO_INCREMENT_COLUMN_FLAVORS.get(
|
1474
|
+
flavor,
|
1475
|
+
AUTO_INCREMENT_COLUMN_FLAVORS['default']
|
1476
|
+
)) if primary_key not in dtypes else ''
|
1477
|
+
col_name = sql_item_name(primary_key, flavor=flavor, schema=None)
|
1478
|
+
|
1479
|
+
if flavor == 'sqlite':
|
1480
|
+
query += f"\n {col_name} INTEGER PRIMARY KEY{auto_increment} NOT NULL,"
|
1481
|
+
else:
|
1482
|
+
query += f"\n {col_name} {col_db_type} PRIMARY KEY{auto_increment} NOT NULL,"
|
1483
|
+
|
1484
|
+
for col, db_type in cols_types:
|
1485
|
+
if col == primary_key:
|
1486
|
+
continue
|
1487
|
+
col_name = sql_item_name(col, schema=None, flavor=flavor)
|
1488
|
+
query += f"\n {col_name} {db_type},"
|
1489
|
+
query = query[:-1]
|
1490
|
+
query += "\n)"
|
1491
|
+
|
1492
|
+
return [query]
|
1493
|
+
|
1494
|
+
|
1495
|
+
def _get_create_table_query_from_cte(
|
1496
|
+
query: str,
|
1497
|
+
new_table: str,
|
1498
|
+
flavor: str,
|
1499
|
+
schema: Optional[str] = None,
|
1500
|
+
primary_key: Optional[str] = None,
|
1501
|
+
) -> List[str]:
|
1502
|
+
"""
|
1503
|
+
Create a new table from a CTE query.
|
1504
|
+
"""
|
1365
1505
|
import textwrap
|
1506
|
+
from meerschaum.utils.dtypes.sql import AUTO_INCREMENT_COLUMN_FLAVORS
|
1366
1507
|
create_cte = 'create_query'
|
1367
1508
|
create_cte_name = sql_item_name(create_cte, flavor, None)
|
1368
1509
|
new_table_name = sql_item_name(new_table, flavor, schema)
|
1510
|
+
primary_key_constraint_name = (
|
1511
|
+
sql_item_name(f'pk_{new_table}', flavor, None)
|
1512
|
+
if primary_key
|
1513
|
+
else None
|
1514
|
+
)
|
1515
|
+
primary_key_name = (
|
1516
|
+
sql_item_name(primary_key, flavor, None)
|
1517
|
+
if primary_key
|
1518
|
+
else None
|
1519
|
+
)
|
1520
|
+
auto_increment = AUTO_INCREMENT_COLUMN_FLAVORS.get(
|
1521
|
+
flavor,
|
1522
|
+
AUTO_INCREMENT_COLUMN_FLAVORS['default']
|
1523
|
+
)
|
1369
1524
|
if flavor in ('mssql',):
|
1370
1525
|
query = query.lstrip()
|
1371
1526
|
if 'with ' in query.lower():
|
1372
1527
|
final_select_ix = query.lower().rfind('select')
|
1373
|
-
|
1528
|
+
create_table_query = (
|
1374
1529
|
query[:final_select_ix].rstrip() + ',\n'
|
1375
1530
|
+ f"{create_cte_name} AS (\n"
|
1376
1531
|
+ query[final_select_ix:]
|
1377
1532
|
+ "\n)\n"
|
1378
1533
|
+ f"SELECT *\nINTO {new_table_name}\nFROM {create_cte_name}"
|
1379
1534
|
)
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1535
|
+
else:
|
1536
|
+
create_table_query = f"""
|
1537
|
+
SELECT *
|
1538
|
+
INTO {new_table_name}
|
1539
|
+
FROM ({query}) AS {create_cte_name}
|
1540
|
+
"""
|
1541
|
+
|
1542
|
+
alter_type_query = f"""
|
1543
|
+
ALTER TABLE {new_table_name}
|
1544
|
+
ADD CONSTRAINT {primary_key_constraint_name} PRIMARY KEY ({primary_key_name})
|
1385
1545
|
"""
|
1386
1546
|
elif flavor in (None,):
|
1387
1547
|
create_table_query = f"""
|
@@ -1390,12 +1550,22 @@ def get_create_table_query(
|
|
1390
1550
|
SELECT *
|
1391
1551
|
FROM {create_cte_name}
|
1392
1552
|
"""
|
1553
|
+
|
1554
|
+
alter_type_query = f"""
|
1555
|
+
ALTER TABLE {new_table_name}
|
1556
|
+
ADD PRIMARY KEY ({primary_key_name})
|
1557
|
+
"""
|
1393
1558
|
elif flavor in ('sqlite', 'mysql', 'mariadb', 'duckdb', 'oracle'):
|
1394
1559
|
create_table_query = f"""
|
1395
1560
|
CREATE TABLE {new_table_name} AS
|
1396
1561
|
SELECT *
|
1397
1562
|
FROM ({query})""" + (f""" AS {create_cte_name}""" if flavor != 'oracle' else '') + """
|
1398
1563
|
"""
|
1564
|
+
|
1565
|
+
alter_type_query = f"""
|
1566
|
+
ALTER TABLE {new_table_name}
|
1567
|
+
ADD PRIMARY KEY ({primary_key_name})
|
1568
|
+
"""
|
1399
1569
|
else:
|
1400
1570
|
create_table_query = f"""
|
1401
1571
|
SELECT *
|
@@ -1403,7 +1573,21 @@ def get_create_table_query(
|
|
1403
1573
|
FROM ({query}) AS {create_cte_name}
|
1404
1574
|
"""
|
1405
1575
|
|
1406
|
-
|
1576
|
+
alter_type_query = f"""
|
1577
|
+
ALTER TABLE {new_table_name}
|
1578
|
+
ADD PRIMARY KEY ({primary_key_name})
|
1579
|
+
"""
|
1580
|
+
|
1581
|
+
create_table_query = textwrap.dedent(create_table_query)
|
1582
|
+
if not primary_key:
|
1583
|
+
return [create_table_query]
|
1584
|
+
|
1585
|
+
alter_type_query = textwrap.dedent(alter_type_query)
|
1586
|
+
|
1587
|
+
return [
|
1588
|
+
create_table_query,
|
1589
|
+
alter_type_query,
|
1590
|
+
]
|
1407
1591
|
|
1408
1592
|
|
1409
1593
|
def wrap_query_with_cte(
|