meerschaum 2.4.7__py3-none-any.whl → 2.4.8__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/actions/sql.py +1 -1
- meerschaum/api/routes/_pipes.py +38 -38
- meerschaum/config/_version.py +1 -1
- meerschaum/connectors/api/_pipes.py +3 -3
- meerschaum/connectors/sql/_SQLConnector.py +1 -1
- meerschaum/connectors/sql/_instance.py +12 -12
- meerschaum/connectors/sql/_pipes.py +70 -49
- meerschaum/connectors/sql/_sql.py +3 -1
- meerschaum/core/Pipe/_sync.py +1 -1
- meerschaum/utils/dataframe.py +32 -21
- meerschaum/utils/dtypes/sql.py +32 -18
- meerschaum/utils/packages/_packages.py +2 -1
- meerschaum/utils/sql.py +11 -7
- {meerschaum-2.4.7.dist-info → meerschaum-2.4.8.dist-info}/METADATA +7 -4
- {meerschaum-2.4.7.dist-info → meerschaum-2.4.8.dist-info}/RECORD +21 -21
- {meerschaum-2.4.7.dist-info → meerschaum-2.4.8.dist-info}/LICENSE +0 -0
- {meerschaum-2.4.7.dist-info → meerschaum-2.4.8.dist-info}/NOTICE +0 -0
- {meerschaum-2.4.7.dist-info → meerschaum-2.4.8.dist-info}/WHEEL +0 -0
- {meerschaum-2.4.7.dist-info → meerschaum-2.4.8.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.4.7.dist-info → meerschaum-2.4.8.dist-info}/top_level.txt +0 -0
- {meerschaum-2.4.7.dist-info → meerschaum-2.4.8.dist-info}/zip-safe +0 -0
meerschaum/actions/sql.py
CHANGED
meerschaum/api/routes/_pipes.py
CHANGED
@@ -408,8 +408,8 @@ def get_pipe_data(
|
|
408
408
|
_params = None
|
409
409
|
if not isinstance(_params, dict):
|
410
410
|
raise fastapi.HTTPException(
|
411
|
-
status_code
|
412
|
-
detail
|
411
|
+
status_code=409,
|
412
|
+
detail="Params must be a valid JSON-encoded dictionary.",
|
413
413
|
)
|
414
414
|
|
415
415
|
_select_columns = []
|
@@ -422,8 +422,8 @@ def get_pipe_data(
|
|
422
422
|
_select_columns = None
|
423
423
|
if not isinstance(_select_columns, list):
|
424
424
|
raise fastapi.HTTPException(
|
425
|
-
status_code
|
426
|
-
detail
|
425
|
+
status_code=409,
|
426
|
+
detail="Selected columns must be a JSON-encoded list."
|
427
427
|
)
|
428
428
|
|
429
429
|
_omit_columns = []
|
@@ -436,35 +436,35 @@ def get_pipe_data(
|
|
436
436
|
_omit_columns = None
|
437
437
|
if _omit_columns is None:
|
438
438
|
raise fastapi.HTTPException(
|
439
|
-
status_code
|
440
|
-
detail
|
439
|
+
status_code=409,
|
440
|
+
detail="Omitted columns must be a JSON-encoded list.",
|
441
441
|
)
|
442
442
|
|
443
443
|
pipe = get_pipe(connector_keys, metric_key, location_key)
|
444
444
|
if not is_pipe_registered(pipe, pipes(refresh=True)):
|
445
445
|
raise fastapi.HTTPException(
|
446
|
-
status_code
|
447
|
-
detail
|
446
|
+
status_code=409,
|
447
|
+
detail="Pipe must be registered with the datetime column specified."
|
448
448
|
)
|
449
449
|
|
450
450
|
if pipe.target in ('users', 'plugins', 'pipes'):
|
451
451
|
raise fastapi.HTTPException(
|
452
|
-
status_code
|
453
|
-
detail
|
452
|
+
status_code=409,
|
453
|
+
detail=f"Cannot retrieve data from protected table '{pipe.target}'.",
|
454
454
|
)
|
455
455
|
|
456
456
|
df = pipe.get_data(
|
457
|
-
select_columns
|
458
|
-
omit_columns
|
459
|
-
begin
|
460
|
-
end
|
461
|
-
params
|
462
|
-
debug
|
457
|
+
select_columns=_select_columns,
|
458
|
+
omit_columns=_omit_columns,
|
459
|
+
begin=begin,
|
460
|
+
end=end,
|
461
|
+
params=_params,
|
462
|
+
debug=debug,
|
463
463
|
)
|
464
464
|
if df is None:
|
465
465
|
raise fastapi.HTTPException(
|
466
|
-
status_code
|
467
|
-
detail
|
466
|
+
status_code=400,
|
467
|
+
detail="Could not fetch data with the given parameters.",
|
468
468
|
)
|
469
469
|
|
470
470
|
### NaN cannot be JSON-serialized.
|
@@ -482,16 +482,16 @@ def get_pipe_data(
|
|
482
482
|
|
483
483
|
@app.get(pipes_endpoint + '/{connector_keys}/{metric_key}/{location_key}/csv', tags=['Pipes'])
|
484
484
|
def get_pipe_csv(
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
485
|
+
connector_keys: str,
|
486
|
+
metric_key: str,
|
487
|
+
location_key: str,
|
488
|
+
begin: Union[str, int, None] = None,
|
489
|
+
end: Union[str, int, None] = None,
|
490
|
+
params: Optional[str] = None,
|
491
|
+
curr_user = (
|
492
|
+
fastapi.Depends(manager) if not no_auth else None
|
493
|
+
),
|
494
|
+
) -> str:
|
495
495
|
"""
|
496
496
|
Get a Pipe's data as a CSV file. Optionally set query boundaries.
|
497
497
|
"""
|
@@ -518,8 +518,8 @@ def get_pipe_csv(
|
|
518
518
|
|
519
519
|
if not isinstance(_params, dict):
|
520
520
|
raise fastapi.HTTPException(
|
521
|
-
status_code
|
522
|
-
detail
|
521
|
+
status_code=409,
|
522
|
+
detail="Params must be a valid JSON-encoded dictionary.",
|
523
523
|
)
|
524
524
|
|
525
525
|
p = get_pipe(connector_keys, metric_key, location_key)
|
@@ -529,7 +529,7 @@ def get_pipe_csv(
|
|
529
529
|
detail = "Pipe must be registered with the datetime column specified."
|
530
530
|
)
|
531
531
|
|
532
|
-
dt_col =
|
532
|
+
dt_col = p.columns.get('datetime', None)
|
533
533
|
if dt_col:
|
534
534
|
if begin is None:
|
535
535
|
begin = p.get_sync_time(round_down=False, newest=False)
|
@@ -552,13 +552,13 @@ def get_pipe_csv(
|
|
552
552
|
|
553
553
|
@app.get(pipes_endpoint + '/{connector_keys}/{metric_key}/{location_key}/id', tags=['Pipes'])
|
554
554
|
def get_pipe_id(
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
555
|
+
connector_keys: str,
|
556
|
+
metric_key: str,
|
557
|
+
location_key: str,
|
558
|
+
curr_user = (
|
559
|
+
fastapi.Depends(manager) if not no_auth else None
|
560
|
+
),
|
561
|
+
) -> int:
|
562
562
|
"""
|
563
563
|
Get a Pipe's ID.
|
564
564
|
"""
|
meerschaum/config/_version.py
CHANGED
@@ -346,14 +346,14 @@ def get_pipe_data(
|
|
346
346
|
try:
|
347
347
|
response = self.get(
|
348
348
|
r_url + "/data",
|
349
|
-
params
|
349
|
+
params={
|
350
350
|
'select_columns': json.dumps(select_columns),
|
351
351
|
'omit_columns': json.dumps(omit_columns),
|
352
352
|
'begin': begin,
|
353
353
|
'end': end,
|
354
|
-
'params': json.dumps(params)
|
354
|
+
'params': json.dumps(params, default=str)
|
355
355
|
},
|
356
|
-
debug
|
356
|
+
debug=debug
|
357
357
|
)
|
358
358
|
if not response.ok:
|
359
359
|
return None
|
@@ -272,7 +272,7 @@ class SQLConnector(Connector):
|
|
272
272
|
"""
|
273
273
|
Return whether this connector may be multithreaded.
|
274
274
|
"""
|
275
|
-
if self.flavor
|
275
|
+
if self.flavor in ('duckdb', 'oracle'):
|
276
276
|
return False
|
277
277
|
if self.flavor == 'sqlite':
|
278
278
|
return ':memory:' not in self.URI
|
@@ -15,12 +15,12 @@ from meerschaum.utils.warnings import warn
|
|
15
15
|
|
16
16
|
_in_memory_temp_tables: Dict[str, bool] = {}
|
17
17
|
def _log_temporary_tables_creation(
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
self,
|
19
|
+
tables: Union[str, List[str]],
|
20
|
+
ready_to_drop: bool = False,
|
21
|
+
create: bool = True,
|
22
|
+
debug: bool = False,
|
23
|
+
) -> SuccessTuple:
|
24
24
|
"""
|
25
25
|
Log a temporary table's creation for later deletion.
|
26
26
|
"""
|
@@ -58,15 +58,15 @@ def _log_temporary_tables_creation(
|
|
58
58
|
|
59
59
|
|
60
60
|
def _drop_temporary_table(
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
self,
|
62
|
+
table: str,
|
63
|
+
debug: bool = False,
|
64
|
+
) -> SuccessTuple:
|
65
65
|
"""
|
66
66
|
Drop a temporary table and clear it from the internal table.
|
67
67
|
"""
|
68
|
-
from meerschaum.utils.sql import sql_item_name, table_exists,
|
69
|
-
if_exists = "IF EXISTS" if self.flavor
|
68
|
+
from meerschaum.utils.sql import sql_item_name, table_exists, DROP_IF_EXISTS_FLAVORS
|
69
|
+
if_exists = "IF EXISTS" if self.flavor in DROP_IF_EXISTS_FLAVORS else ""
|
70
70
|
if not if_exists:
|
71
71
|
if not table_exists(table, self, self.internal_schema, debug=debug):
|
72
72
|
return True, "Success"
|
@@ -459,6 +459,11 @@ def get_create_index_queries(
|
|
459
459
|
+ 'if_not_exists => true, '
|
460
460
|
+ "migrate_data => true);"
|
461
461
|
)
|
462
|
+
elif self.flavor == 'mssql':
|
463
|
+
dt_query = (
|
464
|
+
f"CREATE CLUSTERED INDEX {_datetime_index_name} "
|
465
|
+
f"ON {_pipe_name} ({_datetime_name})"
|
466
|
+
)
|
462
467
|
else: ### mssql, sqlite, etc.
|
463
468
|
dt_query = (
|
464
469
|
f"CREATE INDEX {_datetime_index_name} "
|
@@ -563,7 +568,12 @@ def get_drop_index_queries(
|
|
563
568
|
return {}
|
564
569
|
if not pipe.exists(debug=debug):
|
565
570
|
return {}
|
566
|
-
from meerschaum.utils.sql import
|
571
|
+
from meerschaum.utils.sql import (
|
572
|
+
sql_item_name,
|
573
|
+
table_exists,
|
574
|
+
hypertable_queries,
|
575
|
+
DROP_IF_EXISTS_FLAVORS,
|
576
|
+
)
|
567
577
|
drop_queries = {}
|
568
578
|
schema = self.get_pipe_schema(pipe)
|
569
579
|
schema_prefix = (schema + '_') if schema else ''
|
@@ -580,16 +590,17 @@ def get_drop_index_queries(
|
|
580
590
|
is_hypertable_query = hypertable_queries[self.flavor].format(table_name=pipe_name)
|
581
591
|
is_hypertable = self.value(is_hypertable_query, silent=True, debug=debug) is not None
|
582
592
|
|
593
|
+
if_exists_str = "IF EXISTS" if self.flavor in DROP_IF_EXISTS_FLAVORS else ""
|
583
594
|
if is_hypertable:
|
584
595
|
nuke_queries = []
|
585
596
|
temp_table = '_' + pipe.target + '_temp_migration'
|
586
597
|
temp_table_name = sql_item_name(temp_table, self.flavor, self.get_pipe_schema(pipe))
|
587
598
|
|
588
599
|
if table_exists(temp_table, self, schema=self.get_pipe_schema(pipe), debug=debug):
|
589
|
-
nuke_queries.append(f"DROP TABLE {temp_table_name}")
|
600
|
+
nuke_queries.append(f"DROP TABLE {if_exists_str} {temp_table_name}")
|
590
601
|
nuke_queries += [
|
591
602
|
f"SELECT * INTO {temp_table_name} FROM {pipe_name}",
|
592
|
-
f"DROP TABLE {pipe_name}",
|
603
|
+
f"DROP TABLE {if_exists_str} {pipe_name}",
|
593
604
|
f"ALTER TABLE {temp_table_name} RENAME TO {pipe_name_no_schema}",
|
594
605
|
]
|
595
606
|
nuke_ix_keys = ('datetime', 'id')
|
@@ -811,7 +822,7 @@ def get_pipe_data(
|
|
811
822
|
parse_df_datetimes(
|
812
823
|
c,
|
813
824
|
ignore_cols=ignore_dt_cols,
|
814
|
-
chunksize
|
825
|
+
chunksize=kw.get('chunksize', None),
|
815
826
|
debug=debug,
|
816
827
|
)
|
817
828
|
for c in df
|
@@ -1017,7 +1028,7 @@ def get_pipe_data_query(
|
|
1017
1028
|
if _dt and _dt in existing_cols:
|
1018
1029
|
order_by += dt + ' ' + order + ','
|
1019
1030
|
for key, quoted_col_name in quoted_indices.items():
|
1020
|
-
if
|
1031
|
+
if dt == quoted_col_name:
|
1021
1032
|
continue
|
1022
1033
|
order_by += ' ' + quoted_col_name + ' ' + order + ','
|
1023
1034
|
order_by = order_by[:-1]
|
@@ -1034,7 +1045,7 @@ def get_pipe_data_query(
|
|
1034
1045
|
)
|
1035
1046
|
else:
|
1036
1047
|
query += f"\nLIMIT {limit}"
|
1037
|
-
|
1048
|
+
|
1038
1049
|
if debug:
|
1039
1050
|
to_print = (
|
1040
1051
|
[]
|
@@ -1315,7 +1326,7 @@ def sync_pipe(
|
|
1315
1326
|
) if dt_col else None
|
1316
1327
|
|
1317
1328
|
transact_id = generate_password(3)
|
1318
|
-
temp_target = '
|
1329
|
+
temp_target = '##' + transact_id + '_' + pipe.target
|
1319
1330
|
self._log_temporary_tables_creation(temp_target, create=(not pipe.temporary), debug=debug)
|
1320
1331
|
temp_pipe = Pipe(
|
1321
1332
|
pipe.connector_keys.replace(':', '_') + '_', pipe.metric_key, pipe.location_key,
|
@@ -1721,7 +1732,7 @@ def sync_pipe_inplace(
|
|
1721
1732
|
|
1722
1733
|
delta_cols_types = get_table_cols_types(
|
1723
1734
|
temp_tables['delta'],
|
1724
|
-
connectable
|
1735
|
+
connectable=connectable,
|
1725
1736
|
flavor=self.flavor,
|
1726
1737
|
schema=internal_schema,
|
1727
1738
|
database=database,
|
@@ -1779,7 +1790,7 @@ def sync_pipe_inplace(
|
|
1779
1790
|
create_joined_success, create_joined_msg = session_execute(
|
1780
1791
|
session,
|
1781
1792
|
create_joined_query,
|
1782
|
-
debug
|
1793
|
+
debug=debug,
|
1783
1794
|
) if on_cols and not upsert else (True, "Success")
|
1784
1795
|
if not create_joined_success:
|
1785
1796
|
_ = clean_up_temp_tables()
|
@@ -1790,14 +1801,14 @@ def sync_pipe_inplace(
|
|
1790
1801
|
+ (', '.join([
|
1791
1802
|
(
|
1792
1803
|
"CASE\n WHEN " + sql_item_name(c + '_delta', self.flavor, None)
|
1793
|
-
+ " != " + get_null_replacement(typ, self.flavor)
|
1804
|
+
+ " != " + get_null_replacement(typ, self.flavor)
|
1794
1805
|
+ " THEN " + sql_item_name(c + '_delta', self.flavor, None)
|
1795
1806
|
+ "\n ELSE NULL\nEND "
|
1796
1807
|
+ " AS " + sql_item_name(c, self.flavor, None)
|
1797
1808
|
) for c, typ in delta_cols.items()
|
1798
1809
|
]))
|
1799
1810
|
+ f"\nFROM {temp_table_names['joined']}\n"
|
1800
|
-
+
|
1811
|
+
+ "WHERE "
|
1801
1812
|
+ '\nAND\n'.join([
|
1802
1813
|
(
|
1803
1814
|
sql_item_name(c + '_backtrack', self.flavor, None) + ' IS NULL'
|
@@ -1813,8 +1824,8 @@ def sync_pipe_inplace(
|
|
1813
1824
|
(create_unseen_success, create_unseen_msg), create_unseen_results = session_execute(
|
1814
1825
|
session,
|
1815
1826
|
create_unseen_query,
|
1816
|
-
with_results
|
1817
|
-
debug
|
1827
|
+
with_results=True,
|
1828
|
+
debug=debug
|
1818
1829
|
) if not upsert else (True, "Success"), None
|
1819
1830
|
if not create_unseen_success:
|
1820
1831
|
_ = clean_up_temp_tables()
|
@@ -1832,7 +1843,7 @@ def sync_pipe_inplace(
|
|
1832
1843
|
) for c, typ in delta_cols.items()
|
1833
1844
|
]))
|
1834
1845
|
+ f"\nFROM {temp_table_names['joined']}\n"
|
1835
|
-
+
|
1846
|
+
+ "WHERE "
|
1836
1847
|
+ '\nOR\n'.join([
|
1837
1848
|
(
|
1838
1849
|
sql_item_name(c + '_backtrack', self.flavor, None) + ' IS NOT NULL'
|
@@ -1849,8 +1860,8 @@ def sync_pipe_inplace(
|
|
1849
1860
|
(create_update_success, create_update_msg), create_update_results = session_execute(
|
1850
1861
|
session,
|
1851
1862
|
create_update_query,
|
1852
|
-
with_results
|
1853
|
-
debug
|
1863
|
+
with_results=True,
|
1864
|
+
debug=debug,
|
1854
1865
|
) if on_cols and not upsert else ((True, "Success"), [])
|
1855
1866
|
apply_update_queries = (
|
1856
1867
|
get_update_queries(
|
@@ -1858,12 +1869,12 @@ def sync_pipe_inplace(
|
|
1858
1869
|
temp_tables['update'],
|
1859
1870
|
session,
|
1860
1871
|
on_cols,
|
1861
|
-
upsert
|
1862
|
-
schema
|
1863
|
-
patch_schema
|
1864
|
-
datetime_col
|
1865
|
-
flavor
|
1866
|
-
debug
|
1872
|
+
upsert=upsert,
|
1873
|
+
schema=self.get_pipe_schema(pipe),
|
1874
|
+
patch_schema=internal_schema,
|
1875
|
+
datetime_col=pipe.columns.get('datetime', None),
|
1876
|
+
flavor=self.flavor,
|
1877
|
+
debug=debug,
|
1867
1878
|
)
|
1868
1879
|
if on_cols else []
|
1869
1880
|
)
|
@@ -1883,8 +1894,8 @@ def sync_pipe_inplace(
|
|
1883
1894
|
(apply_unseen_success, apply_unseen_msg), apply_unseen_results = session_execute(
|
1884
1895
|
session,
|
1885
1896
|
apply_unseen_queries,
|
1886
|
-
with_results
|
1887
|
-
debug
|
1897
|
+
with_results=True,
|
1898
|
+
debug=debug,
|
1888
1899
|
) if not upsert else (True, "Success"), None
|
1889
1900
|
if not apply_unseen_success:
|
1890
1901
|
_ = clean_up_temp_tables()
|
@@ -1894,8 +1905,8 @@ def sync_pipe_inplace(
|
|
1894
1905
|
(apply_update_success, apply_update_msg), apply_update_results = session_execute(
|
1895
1906
|
session,
|
1896
1907
|
apply_update_queries,
|
1897
|
-
with_results
|
1898
|
-
debug
|
1908
|
+
with_results=True,
|
1909
|
+
debug=debug,
|
1899
1910
|
)
|
1900
1911
|
if not apply_update_success:
|
1901
1912
|
_ = clean_up_temp_tables()
|
@@ -2198,7 +2209,7 @@ def get_pipe_rowcount(
|
|
2198
2209
|
else 'WHERE'
|
2199
2210
|
)
|
2200
2211
|
)
|
2201
|
-
|
2212
|
+
|
2202
2213
|
result = self.value(query, debug=debug, silent=True)
|
2203
2214
|
try:
|
2204
2215
|
return int(result)
|
@@ -2207,11 +2218,11 @@ def get_pipe_rowcount(
|
|
2207
2218
|
|
2208
2219
|
|
2209
2220
|
def drop_pipe(
|
2210
|
-
|
2211
|
-
|
2212
|
-
|
2213
|
-
|
2214
|
-
|
2221
|
+
self,
|
2222
|
+
pipe: mrsm.Pipe,
|
2223
|
+
debug: bool = False,
|
2224
|
+
**kw
|
2225
|
+
) -> SuccessTuple:
|
2215
2226
|
"""
|
2216
2227
|
Drop a pipe's tables but maintain its registration.
|
2217
2228
|
|
@@ -2219,30 +2230,36 @@ def drop_pipe(
|
|
2219
2230
|
----------
|
2220
2231
|
pipe: mrsm.Pipe
|
2221
2232
|
The pipe to drop.
|
2222
|
-
|
2233
|
+
|
2234
|
+
Returns
|
2235
|
+
-------
|
2236
|
+
A `SuccessTuple` indicated success.
|
2223
2237
|
"""
|
2224
|
-
from meerschaum.utils.sql import table_exists, sql_item_name
|
2238
|
+
from meerschaum.utils.sql import table_exists, sql_item_name, DROP_IF_EXISTS_FLAVORS
|
2225
2239
|
success = True
|
2226
2240
|
target = pipe.target
|
2227
2241
|
target_name = (
|
2228
2242
|
sql_item_name(target, self.flavor, self.get_pipe_schema(pipe))
|
2229
2243
|
)
|
2230
2244
|
if table_exists(target, self, debug=debug):
|
2231
|
-
|
2245
|
+
if_exists_str = "IF EXISTS" if self.flavor in DROP_IF_EXISTS_FLAVORS else ""
|
2246
|
+
success = self.exec(
|
2247
|
+
f"DROP TABLE {if_exists_str} {target_name}", silent=True, debug=debug
|
2248
|
+
) is not None
|
2232
2249
|
|
2233
2250
|
msg = "Success" if success else f"Failed to drop {pipe}."
|
2234
2251
|
return success, msg
|
2235
2252
|
|
2236
2253
|
|
2237
2254
|
def clear_pipe(
|
2238
|
-
|
2239
|
-
|
2240
|
-
|
2241
|
-
|
2242
|
-
|
2243
|
-
|
2244
|
-
|
2245
|
-
|
2255
|
+
self,
|
2256
|
+
pipe: mrsm.Pipe,
|
2257
|
+
begin: Union[datetime, int, None] = None,
|
2258
|
+
end: Union[datetime, int, None] = None,
|
2259
|
+
params: Optional[Dict[str, Any]] = None,
|
2260
|
+
debug: bool = False,
|
2261
|
+
**kw
|
2262
|
+
) -> SuccessTuple:
|
2246
2263
|
"""
|
2247
2264
|
Delete a pipe's data within a bounded or unbounded interval without dropping the table.
|
2248
2265
|
|
@@ -2535,7 +2552,7 @@ def get_alter_columns_queries(
|
|
2535
2552
|
"""
|
2536
2553
|
if not pipe.exists(debug=debug):
|
2537
2554
|
return []
|
2538
|
-
from meerschaum.utils.sql import sql_item_name
|
2555
|
+
from meerschaum.utils.sql import sql_item_name, DROP_IF_EXISTS_FLAVORS
|
2539
2556
|
from meerschaum.utils.dataframe import get_numeric_cols
|
2540
2557
|
from meerschaum.utils.dtypes import are_dtypes_equal
|
2541
2558
|
from meerschaum.utils.dtypes.sql import (
|
@@ -2691,7 +2708,9 @@ def get_alter_columns_queries(
|
|
2691
2708
|
f"\nFROM {sql_item_name(temp_table_name, self.flavor, self.get_pipe_schema(pipe))}"
|
2692
2709
|
)
|
2693
2710
|
|
2694
|
-
|
2711
|
+
if_exists_str = "IF EXISTS" if self.flavor in DROP_IF_EXISTS_FLAVORS else ""
|
2712
|
+
|
2713
|
+
drop_query = f"DROP TABLE {if_exists_str}" + sql_item_name(
|
2695
2714
|
temp_table_name, self.flavor, self.get_pipe_schema(pipe)
|
2696
2715
|
)
|
2697
2716
|
return [
|
@@ -2882,6 +2901,7 @@ def deduplicate_pipe(
|
|
2882
2901
|
NO_CTE_FLAVORS,
|
2883
2902
|
get_rename_table_queries,
|
2884
2903
|
NO_SELECT_INTO_FLAVORS,
|
2904
|
+
DROP_IF_EXISTS_FLAVORS,
|
2885
2905
|
get_create_table_query,
|
2886
2906
|
format_cte_subquery,
|
2887
2907
|
get_null_replacement,
|
@@ -3012,6 +3032,7 @@ def deduplicate_pipe(
|
|
3012
3032
|
) + f"""
|
3013
3033
|
ORDER BY {index_list_str_ordered}
|
3014
3034
|
"""
|
3035
|
+
if_exists_str = "IF EXISTS" if self.flavor in DROP_IF_EXISTS_FLAVORS else ""
|
3015
3036
|
alter_queries = flatten_list([
|
3016
3037
|
get_rename_table_queries(
|
3017
3038
|
pipe.target, temp_old_table, self.flavor, schema=self.get_pipe_schema(pipe)
|
@@ -3020,7 +3041,7 @@ def deduplicate_pipe(
|
|
3020
3041
|
dedup_table, pipe.target, self.flavor, schema=self.get_pipe_schema(pipe)
|
3021
3042
|
),
|
3022
3043
|
f"""
|
3023
|
-
DROP TABLE {temp_old_table_name}
|
3044
|
+
DROP TABLE {if_exists_str} {temp_old_table_name}
|
3024
3045
|
""",
|
3025
3046
|
])
|
3026
3047
|
|
@@ -3030,9 +3051,9 @@ def deduplicate_pipe(
|
|
3030
3051
|
|
3031
3052
|
results = self.exec_queries(
|
3032
3053
|
alter_queries,
|
3033
|
-
break_on_error
|
3034
|
-
rollback
|
3035
|
-
debug
|
3054
|
+
break_on_error=True,
|
3055
|
+
rollback=True,
|
3056
|
+
debug=debug,
|
3036
3057
|
)
|
3037
3058
|
|
3038
3059
|
fail_query = None
|
@@ -753,6 +753,7 @@ def to_sql(
|
|
753
753
|
table_exists,
|
754
754
|
json_flavors,
|
755
755
|
truncate_item_name,
|
756
|
+
DROP_IF_EXISTS_FLAVORS,
|
756
757
|
)
|
757
758
|
from meerschaum.utils.dataframe import get_json_cols, get_numeric_cols, get_uuid_cols
|
758
759
|
from meerschaum.utils.dtypes import are_dtypes_equal, quantize_decimal
|
@@ -827,12 +828,13 @@ def to_sql(
|
|
827
828
|
'parallel': True,
|
828
829
|
})
|
829
830
|
|
831
|
+
if_exists_str = "IF EXISTS" if self.flavor in DROP_IF_EXISTS_FLAVORS else ""
|
830
832
|
if self.flavor == 'oracle':
|
831
833
|
### For some reason 'replace' doesn't work properly in pandas,
|
832
834
|
### so try dropping first.
|
833
835
|
if if_exists == 'replace' and table_exists(name, self, schema=schema, debug=debug):
|
834
836
|
success = self.exec(
|
835
|
-
"DROP TABLE " + sql_item_name(name, 'oracle', schema)
|
837
|
+
f"DROP TABLE {if_exists_str}" + sql_item_name(name, 'oracle', schema)
|
836
838
|
) is not None
|
837
839
|
if not success:
|
838
840
|
warn(f"Unable to drop {name}")
|
meerschaum/core/Pipe/_sync.py
CHANGED
meerschaum/utils/dataframe.py
CHANGED
@@ -61,12 +61,10 @@ def add_missing_cols_to_df(
|
|
61
61
|
if set(df.columns) == set(dtypes):
|
62
62
|
return df
|
63
63
|
|
64
|
-
import
|
65
|
-
from meerschaum.utils.packages import import_pandas, attempt_import
|
66
|
-
from meerschaum.utils.warnings import warn
|
64
|
+
from meerschaum.utils.packages import attempt_import
|
67
65
|
from meerschaum.utils.dtypes import to_pandas_dtype
|
68
66
|
pandas = attempt_import('pandas')
|
69
|
-
|
67
|
+
|
70
68
|
def build_series(dtype: str):
|
71
69
|
return pandas.Series([], dtype=to_pandas_dtype(dtype))
|
72
70
|
|
@@ -75,7 +73,10 @@ def add_missing_cols_to_df(
|
|
75
73
|
for col, typ in dtypes.items()
|
76
74
|
if col not in df.columns
|
77
75
|
}
|
78
|
-
|
76
|
+
df_with_cols = df.assign(**assign_kwargs)
|
77
|
+
for col in assign_kwargs:
|
78
|
+
df_with_cols[col] = df_with_cols[col].fillna(pandas.NA)
|
79
|
+
return df_with_cols
|
79
80
|
|
80
81
|
|
81
82
|
def filter_unseen_df(
|
@@ -152,6 +153,7 @@ def filter_unseen_df(
|
|
152
153
|
is_dask = 'dask' in new_df.__module__
|
153
154
|
if is_dask:
|
154
155
|
pandas = attempt_import('pandas')
|
156
|
+
_ = attempt_import('partd', lazy=False)
|
155
157
|
dd = attempt_import('dask.dataframe')
|
156
158
|
merge = dd.merge
|
157
159
|
NA = pandas.NA
|
@@ -301,21 +303,28 @@ def filter_unseen_df(
|
|
301
303
|
lambda x: f'{x:f}' if isinstance(x, Decimal) else x
|
302
304
|
)
|
303
305
|
|
306
|
+
old_dt_cols = [
|
307
|
+
col
|
308
|
+
for col, typ in old_df.dtypes.items()
|
309
|
+
if are_dtypes_equal(str(typ), 'datetime')
|
310
|
+
]
|
311
|
+
for col in old_dt_cols:
|
312
|
+
old_df[col] = coerce_timezone(old_df[col])
|
313
|
+
|
314
|
+
new_dt_cols = [
|
315
|
+
col
|
316
|
+
for col, typ in old_df.dtypes.items()
|
317
|
+
if are_dtypes_equal(str(typ), 'datetime')
|
318
|
+
]
|
319
|
+
for col in new_dt_cols:
|
320
|
+
new_df[col] = coerce_timezone(new_df[col])
|
321
|
+
|
304
322
|
old_uuid_cols = get_uuid_cols(old_df)
|
305
323
|
new_uuid_cols = get_uuid_cols(new_df)
|
306
324
|
uuid_cols = set(new_uuid_cols + old_uuid_cols)
|
307
|
-
for uuid_col in old_uuid_cols:
|
308
|
-
old_df[uuid_col] = old_df[uuid_col].apply(
|
309
|
-
lambda x: f'{x}' if isinstance(x, UUID) else x
|
310
|
-
)
|
311
|
-
for uuid_col in new_uuid_cols:
|
312
|
-
new_df[uuid_col] = new_df[uuid_col].apply(
|
313
|
-
lambda x: f'{x}' if isinstance(x, UUID) else x
|
314
|
-
)
|
315
|
-
|
316
325
|
joined_df = merge(
|
317
|
-
new_df.fillna(NA),
|
318
|
-
old_df.fillna(NA),
|
326
|
+
new_df.infer_objects(copy=False).fillna(NA),
|
327
|
+
old_df.infer_objects(copy=False).fillna(NA),
|
319
328
|
how='left',
|
320
329
|
on=None,
|
321
330
|
indicator=True,
|
@@ -558,10 +567,10 @@ def get_json_cols(df: 'pd.DataFrame') -> List[str]:
|
|
558
567
|
-------
|
559
568
|
A list of columns to be encoded as JSON.
|
560
569
|
"""
|
561
|
-
is_dask = 'dask' in df.__module__
|
570
|
+
is_dask = 'dask' in df.__module__ if hasattr(df, '__module__') else False
|
562
571
|
if is_dask:
|
563
572
|
df = get_first_valid_dask_partition(df)
|
564
|
-
|
573
|
+
|
565
574
|
if len(df) == 0:
|
566
575
|
return []
|
567
576
|
|
@@ -699,6 +708,7 @@ def enforce_dtypes(
|
|
699
708
|
is_dtype_numeric,
|
700
709
|
attempt_cast_to_numeric,
|
701
710
|
attempt_cast_to_uuid,
|
711
|
+
coerce_timezone,
|
702
712
|
)
|
703
713
|
if safe_copy:
|
704
714
|
df = df.copy()
|
@@ -1065,6 +1075,7 @@ def get_first_valid_dask_partition(ddf: 'dask.dataframe.DataFrame') -> Union['pd
|
|
1065
1075
|
continue
|
1066
1076
|
if len(pdf) > 0:
|
1067
1077
|
return pdf
|
1078
|
+
_ = mrsm.attempt_import('partd', lazy=False)
|
1068
1079
|
return ddf.compute()
|
1069
1080
|
|
1070
1081
|
|
@@ -1171,9 +1182,9 @@ def query_df(
|
|
1171
1182
|
dtypes = {col: str(typ) for col, typ in df.dtypes.items()}
|
1172
1183
|
|
1173
1184
|
if inplace:
|
1174
|
-
df.fillna(NA, inplace=True)
|
1185
|
+
df.infer_objects(copy=False).fillna(NA, inplace=True)
|
1175
1186
|
else:
|
1176
|
-
df = df.fillna(NA)
|
1187
|
+
df = df.infer_objects(copy=False).fillna(NA)
|
1177
1188
|
|
1178
1189
|
if isinstance(begin, str):
|
1179
1190
|
begin = dateutil_parser.parse(begin)
|
@@ -1346,7 +1357,7 @@ def to_json(
|
|
1346
1357
|
df = df.copy()
|
1347
1358
|
for col in uuid_cols:
|
1348
1359
|
df[col] = df[col].astype(str)
|
1349
|
-
return df.fillna(pd.NA).to_json(
|
1360
|
+
return df.infer_objects(copy=False).fillna(pd.NA).to_json(
|
1350
1361
|
date_format=date_format,
|
1351
1362
|
date_unit=date_unit,
|
1352
1363
|
orient=orient,
|
meerschaum/utils/dtypes/sql.py
CHANGED
@@ -82,7 +82,10 @@ DB_TO_PD_DTYPES: Dict[str, Union[str, Dict[str, str]]] = {
|
|
82
82
|
'TIMESTAMPTZ': 'datetime64[ns, UTC]',
|
83
83
|
'DATE': 'datetime64[ns]',
|
84
84
|
'DATETIME': 'datetime64[ns]',
|
85
|
+
'DATETIME2': 'datetime64[ns]',
|
86
|
+
'DATETIMEOFFSET': 'datetime64[ns, UTC]',
|
85
87
|
'TEXT': 'string[pyarrow]',
|
88
|
+
'VARCHAR': 'string[pyarrow]',
|
86
89
|
'CLOB': 'string[pyarrow]',
|
87
90
|
'BOOL': 'bool[pyarrow]',
|
88
91
|
'BOOLEAN': 'bool[pyarrow]',
|
@@ -156,7 +159,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
|
|
156
159
|
'postgresql': 'TIMESTAMP',
|
157
160
|
'mariadb': 'DATETIME',
|
158
161
|
'mysql': 'DATETIME',
|
159
|
-
'mssql': '
|
162
|
+
'mssql': 'DATETIME2',
|
160
163
|
'oracle': 'DATE',
|
161
164
|
'sqlite': 'DATETIME',
|
162
165
|
'duckdb': 'TIMESTAMP',
|
@@ -169,7 +172,7 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
|
|
169
172
|
'postgresql': 'TIMESTAMP',
|
170
173
|
'mariadb': 'TIMESTAMP',
|
171
174
|
'mysql': 'TIMESTAMP',
|
172
|
-
'mssql': '
|
175
|
+
'mssql': 'DATETIMEOFFSET',
|
173
176
|
'oracle': 'TIMESTAMP',
|
174
177
|
'sqlite': 'TIMESTAMP',
|
175
178
|
'duckdb': 'TIMESTAMP',
|
@@ -245,13 +248,13 @@ PD_TO_DB_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
|
|
245
248
|
'uuid': {
|
246
249
|
'timescaledb': 'UUID',
|
247
250
|
'postgresql': 'UUID',
|
248
|
-
'mariadb': 'CHAR(
|
249
|
-
'mysql': 'CHAR(
|
251
|
+
'mariadb': 'CHAR(36)',
|
252
|
+
'mysql': 'CHAR(36)',
|
250
253
|
'mssql': 'UNIQUEIDENTIFIER',
|
251
254
|
### I know this is too much space, but erring on the side of caution.
|
252
255
|
'oracle': 'NVARCHAR(2000)',
|
253
256
|
'sqlite': 'TEXT',
|
254
|
-
'duckdb': '
|
257
|
+
'duckdb': 'VARCHAR',
|
255
258
|
'citus': 'UUID',
|
256
259
|
'cockroachdb': 'UUID',
|
257
260
|
'default': 'TEXT',
|
@@ -289,7 +292,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
|
|
289
292
|
'postgresql': 'DateTime',
|
290
293
|
'mariadb': 'DateTime',
|
291
294
|
'mysql': 'DateTime',
|
292
|
-
'mssql': '
|
295
|
+
'mssql': 'sqlalchemy.dialects.mssql.DATETIME2',
|
293
296
|
'oracle': 'DateTime',
|
294
297
|
'sqlite': 'DateTime',
|
295
298
|
'duckdb': 'DateTime',
|
@@ -302,7 +305,7 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
|
|
302
305
|
'postgresql': 'DateTime',
|
303
306
|
'mariadb': 'DateTime',
|
304
307
|
'mysql': 'DateTime',
|
305
|
-
'mssql': '
|
308
|
+
'mssql': 'sqlalchemy.dialects.mssql.DATETIMEOFFSET',
|
306
309
|
'oracle': 'DateTime',
|
307
310
|
'sqlite': 'DateTime',
|
308
311
|
'duckdb': 'DateTime',
|
@@ -350,16 +353,16 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
|
|
350
353
|
'default': 'UnicodeText',
|
351
354
|
},
|
352
355
|
'json': {
|
353
|
-
'timescaledb': 'JSONB',
|
354
|
-
'postgresql': 'JSONB',
|
356
|
+
'timescaledb': 'sqlalchemy.dialects.postgresql.JSONB',
|
357
|
+
'postgresql': 'sqlalchemy.dialects.postgresql.JSONB',
|
355
358
|
'mariadb': 'UnicodeText',
|
356
359
|
'mysql': 'UnicodeText',
|
357
360
|
'mssql': 'UnicodeText',
|
358
361
|
'oracle': 'UnicodeText',
|
359
362
|
'sqlite': 'UnicodeText',
|
360
363
|
'duckdb': 'TEXT',
|
361
|
-
'citus': 'JSONB',
|
362
|
-
'cockroachdb': 'JSONB',
|
364
|
+
'citus': 'sqlalchemy.dialects.postgresql.JSONB',
|
365
|
+
'cockroachdb': 'sqlalchemy.dialects.postgresql.JSONB',
|
363
366
|
'default': 'UnicodeText',
|
364
367
|
},
|
365
368
|
'numeric': {
|
@@ -378,12 +381,12 @@ PD_TO_SQLALCHEMY_DTYPES_FLAVORS: Dict[str, Dict[str, str]] = {
|
|
378
381
|
'uuid': {
|
379
382
|
'timescaledb': 'Uuid',
|
380
383
|
'postgresql': 'Uuid',
|
381
|
-
'mariadb': '
|
382
|
-
'mysql': '
|
384
|
+
'mariadb': 'sqlalchemy.dialects.mysql.CHAR(36)',
|
385
|
+
'mysql': 'sqlalchemy.dialects.mysql.CHAR(36)',
|
383
386
|
'mssql': 'Uuid',
|
384
387
|
'oracle': 'UnicodeText',
|
385
|
-
'sqlite': '
|
386
|
-
'duckdb': '
|
388
|
+
'sqlite': 'UnicodeText',
|
389
|
+
'duckdb': 'UnicodeText',
|
387
390
|
'citus': 'Uuid',
|
388
391
|
'cockroachdb': 'Uuid',
|
389
392
|
'default': 'Uuid',
|
@@ -453,6 +456,7 @@ def get_db_type_from_pd_type(
|
|
453
456
|
The database data type for the incoming Pandas data type.
|
454
457
|
If nothing can be found, a warning will be thrown and 'TEXT' will be returned.
|
455
458
|
"""
|
459
|
+
import ast
|
456
460
|
from meerschaum.utils.warnings import warn
|
457
461
|
from meerschaum.utils.packages import attempt_import
|
458
462
|
from meerschaum.utils.dtypes import are_dtypes_equal
|
@@ -505,9 +509,19 @@ def get_db_type_from_pd_type(
|
|
505
509
|
db_type = flavor_types.get(flavor, default_flavor_type)
|
506
510
|
if not as_sqlalchemy:
|
507
511
|
return db_type
|
508
|
-
|
509
|
-
|
510
|
-
|
512
|
+
|
513
|
+
if db_type.startswith('sqlalchemy.dialects'):
|
514
|
+
dialect, typ_class_name = db_type.replace('sqlalchemy.dialects.', '').split('.', maxsplit=2)
|
515
|
+
arg = None
|
516
|
+
if '(' in typ_class_name:
|
517
|
+
typ_class_name, arg_str = typ_class_name.split('(', maxsplit=1)
|
518
|
+
arg = ast.literal_eval(arg_str.rstrip(')'))
|
519
|
+
sqlalchemy_dialects_flavor_module = attempt_import(f'sqlalchemy.dialects.{dialect}')
|
520
|
+
cls = getattr(sqlalchemy_dialects_flavor_module, typ_class_name)
|
521
|
+
if arg is None:
|
522
|
+
return cls
|
523
|
+
return cls(arg)
|
524
|
+
|
511
525
|
if 'numeric' in db_type.lower():
|
512
526
|
numeric_type_str = PD_TO_DB_DTYPES_FLAVORS['numeric'].get(flavor, 'NUMERIC')
|
513
527
|
if flavor not in NUMERIC_PRECISION_FLAVORS:
|
@@ -128,7 +128,8 @@ packages['sql'] = {
|
|
128
128
|
'numpy' : 'numpy>=1.18.5',
|
129
129
|
'pandas' : 'pandas[parquet]>=2.0.1',
|
130
130
|
'pyarrow' : 'pyarrow>=16.1.0',
|
131
|
-
'dask' : 'dask[
|
131
|
+
'dask' : 'dask[complete]>=2024.5.1',
|
132
|
+
'partd' : 'partd>=1.4.2',
|
132
133
|
'pytz' : 'pytz',
|
133
134
|
'joblib' : 'joblib>=0.17.0',
|
134
135
|
'sqlalchemy' : 'SQLAlchemy>=2.0.5',
|
meerschaum/utils/sql.py
CHANGED
@@ -38,6 +38,9 @@ version_queries = {
|
|
38
38
|
'oracle': "SELECT version from PRODUCT_COMPONENT_VERSION WHERE rownum = 1",
|
39
39
|
}
|
40
40
|
SKIP_IF_EXISTS_FLAVORS = {'mssql', 'oracle'}
|
41
|
+
DROP_IF_EXISTS_FLAVORS = {
|
42
|
+
'timescaledb', 'postgresql', 'citus', 'mssql', 'mysql', 'mariadb', 'sqlite',
|
43
|
+
}
|
41
44
|
COALESCE_UNIQUE_INDEX_FLAVORS = {'timescaledb', 'postgresql', 'citus'}
|
42
45
|
update_queries = {
|
43
46
|
'default': """
|
@@ -1284,11 +1287,11 @@ def get_db_version(conn: 'SQLConnector', debug: bool = False) -> Union[str, None
|
|
1284
1287
|
|
1285
1288
|
|
1286
1289
|
def get_rename_table_queries(
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1290
|
+
old_table: str,
|
1291
|
+
new_table: str,
|
1292
|
+
flavor: str,
|
1293
|
+
schema: Optional[str] = None,
|
1294
|
+
) -> List[str]:
|
1292
1295
|
"""
|
1293
1296
|
Return queries to alter a table's name.
|
1294
1297
|
|
@@ -1317,12 +1320,13 @@ def get_rename_table_queries(
|
|
1317
1320
|
if flavor == 'mssql':
|
1318
1321
|
return [f"EXEC sp_rename '{old_table}', '{new_table}'"]
|
1319
1322
|
|
1323
|
+
if_exists_str = "IF EXISTS" if flavor in DROP_IF_EXISTS_FLAVORS else ""
|
1320
1324
|
if flavor == 'duckdb':
|
1321
1325
|
return [
|
1322
1326
|
get_create_table_query(f"SELECT * FROM {old_table_name}", tmp_table, 'duckdb', schema),
|
1323
1327
|
get_create_table_query(f"SELECT * FROM {tmp_table_name}", new_table, 'duckdb', schema),
|
1324
|
-
f"DROP TABLE {tmp_table_name}",
|
1325
|
-
f"DROP TABLE {old_table_name}",
|
1328
|
+
f"DROP TABLE {if_exists_str} {tmp_table_name}",
|
1329
|
+
f"DROP TABLE {if_exists_str} {old_table_name}",
|
1326
1330
|
]
|
1327
1331
|
|
1328
1332
|
return [f"ALTER TABLE {old_table_name} RENAME TO {new_table_name}"]
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: meerschaum
|
3
|
-
Version: 2.4.
|
3
|
+
Version: 2.4.8
|
4
4
|
Summary: Sync Time-Series Pipes with Meerschaum
|
5
5
|
Home-page: https://meerschaum.io
|
6
6
|
Author: Bennett Meares
|
@@ -44,7 +44,8 @@ Requires-Dist: valkey >=6.0.0 ; extra == 'api'
|
|
44
44
|
Requires-Dist: numpy >=1.18.5 ; extra == 'api'
|
45
45
|
Requires-Dist: pandas[parquet] >=2.0.1 ; extra == 'api'
|
46
46
|
Requires-Dist: pyarrow >=16.1.0 ; extra == 'api'
|
47
|
-
Requires-Dist: dask[
|
47
|
+
Requires-Dist: dask[complete] >=2024.5.1 ; extra == 'api'
|
48
|
+
Requires-Dist: partd >=1.4.2 ; extra == 'api'
|
48
49
|
Requires-Dist: pytz ; extra == 'api'
|
49
50
|
Requires-Dist: joblib >=0.17.0 ; extra == 'api'
|
50
51
|
Requires-Dist: SQLAlchemy >=2.0.5 ; extra == 'api'
|
@@ -237,7 +238,8 @@ Requires-Dist: pycparser >=2.21.0 ; extra == 'full'
|
|
237
238
|
Requires-Dist: numpy >=1.18.5 ; extra == 'full'
|
238
239
|
Requires-Dist: pandas[parquet] >=2.0.1 ; extra == 'full'
|
239
240
|
Requires-Dist: pyarrow >=16.1.0 ; extra == 'full'
|
240
|
-
Requires-Dist: dask[
|
241
|
+
Requires-Dist: dask[complete] >=2024.5.1 ; extra == 'full'
|
242
|
+
Requires-Dist: partd >=1.4.2 ; extra == 'full'
|
241
243
|
Requires-Dist: pytz ; extra == 'full'
|
242
244
|
Requires-Dist: joblib >=0.17.0 ; extra == 'full'
|
243
245
|
Requires-Dist: SQLAlchemy >=2.0.5 ; extra == 'full'
|
@@ -277,7 +279,8 @@ Provides-Extra: sql
|
|
277
279
|
Requires-Dist: numpy >=1.18.5 ; extra == 'sql'
|
278
280
|
Requires-Dist: pandas[parquet] >=2.0.1 ; extra == 'sql'
|
279
281
|
Requires-Dist: pyarrow >=16.1.0 ; extra == 'sql'
|
280
|
-
Requires-Dist: dask[
|
282
|
+
Requires-Dist: dask[complete] >=2024.5.1 ; extra == 'sql'
|
283
|
+
Requires-Dist: partd >=1.4.2 ; extra == 'sql'
|
281
284
|
Requires-Dist: pytz ; extra == 'sql'
|
282
285
|
Requires-Dist: joblib >=0.17.0 ; extra == 'sql'
|
283
286
|
Requires-Dist: SQLAlchemy >=2.0.5 ; extra == 'sql'
|
@@ -42,7 +42,7 @@ meerschaum/actions/restart.py,sha256=6ffp3-X9eTEgunVSdD41HnOwqp71yjuSAmXJ5j39ONI
|
|
42
42
|
meerschaum/actions/setup.py,sha256=KkAGWcgwzl_L6A19fTmTX1KtBjW2FwD8QenLjPy0mQQ,3205
|
43
43
|
meerschaum/actions/sh.py,sha256=fLfTJaacKu4sjLTRqEzzYlT2WbbdZBEczsKb6F-qAek,2026
|
44
44
|
meerschaum/actions/show.py,sha256=uNXOfh1Z44i6YpmAcE_uM_6s9r3lNh8CnstpvS6tTjE,28179
|
45
|
-
meerschaum/actions/sql.py,sha256=
|
45
|
+
meerschaum/actions/sql.py,sha256=8BSvlnccfEqLrscLq67Toa5D4FJ7I598IdxEe_yzmV8,4263
|
46
46
|
meerschaum/actions/stack.py,sha256=ZwrCTGJ0x3jjZkRieWcvqasQHYCqNtB1HYvTX-r3Z3g,5996
|
47
47
|
meerschaum/actions/start.py,sha256=7B6zLHh-DNWnJta1h_RV9ccGJ4EnbEDu3k-GdwAsU8M,19208
|
48
48
|
meerschaum/actions/stop.py,sha256=5fdUw70YN-yuUWrC-NhA88cxr9FZ5NbssbQ8xXO8nFU,4632
|
@@ -123,7 +123,7 @@ meerschaum/api/routes/_index.py,sha256=QI6CBo6pI2Zi0a6fJHDjZfiLa9f4okb0BGe3A_JD0
|
|
123
123
|
meerschaum/api/routes/_jobs.py,sha256=vO6CJYUme7bHIOy9gAv6VyEM1M8EKdJmtfw2nSnZ24Q,11639
|
124
124
|
meerschaum/api/routes/_login.py,sha256=ti2onNOemOGLHLoPubAQOYtD7eq7FA1jOlbOSVSjXVo,2466
|
125
125
|
meerschaum/api/routes/_misc.py,sha256=05--9ZVFeaCgZrHER2kA3SYdK4TyfkEXOCjLvPbum-w,2469
|
126
|
-
meerschaum/api/routes/_pipes.py,sha256=
|
126
|
+
meerschaum/api/routes/_pipes.py,sha256=g88AU_NUM6tlX3bFl4EOGiQWZYqvDxDFlaLIYbYn1c4,21397
|
127
127
|
meerschaum/api/routes/_plugins.py,sha256=vR6-uTJraY1YEJMuRvds1-xFLB2mexxnp2dJwN_0rVo,6216
|
128
128
|
meerschaum/api/routes/_users.py,sha256=SfAkZFKrKnGjpzj8SFIKzPemzQJOH3oB72h19EaUvcQ,7204
|
129
129
|
meerschaum/api/routes/_version.py,sha256=2t-nw_9IxCVZCNEar0LOwmut2zsClRVHjiOOUx16cu0,825
|
@@ -142,7 +142,7 @@ meerschaum/config/_preprocess.py,sha256=-AEA8m_--KivZwTQ1sWN6LTn5sio_fUr2XZ51BO6
|
|
142
142
|
meerschaum/config/_read_config.py,sha256=oxnLjuhy6JBBld886FkBX07wUdkpzEzTItYMUa9qw1Q,14688
|
143
143
|
meerschaum/config/_shell.py,sha256=46_m49Txc5q1rGfCgO49ca48BODx45DQJi8D0zz1R18,4245
|
144
144
|
meerschaum/config/_sync.py,sha256=jHcWRkxd82_BgX8Xo8agsWvf7BSbv3qHLWmYl6ehp_0,4242
|
145
|
-
meerschaum/config/_version.py,sha256=
|
145
|
+
meerschaum/config/_version.py,sha256=1oWpjLUymKmrkEXNSCmeb0HaJEmpVYs4n7VzxwE3Z6M,71
|
146
146
|
meerschaum/config/paths.py,sha256=JjibeGN3YAdSNceRwsd42aNmeUrIgM6ndzC8qZAmNI0,621
|
147
147
|
meerschaum/config/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
148
148
|
meerschaum/config/stack/__init__.py,sha256=gGVxXgNnGb9u25iF__IiNPlZt1BLUVmHmFJ0jvnJg3Q,10548
|
@@ -162,22 +162,22 @@ meerschaum/connectors/api/_fetch.py,sha256=Khq9AFr1nk8Dsmcedb77aWhAuHw0JGgVeahDG
|
|
162
162
|
meerschaum/connectors/api/_jobs.py,sha256=N5lpHFGG10jlVgaJeWAOTuLBQw3AdgjXsEPpp1YwZQE,11270
|
163
163
|
meerschaum/connectors/api/_login.py,sha256=5GsD-B214vr5EYfM3XrTUs1sTFApxZA-9dNxq8oNSyg,2050
|
164
164
|
meerschaum/connectors/api/_misc.py,sha256=OZRZBYOokKIEjmQaR8jUYgu6ZRn9VzXBChzR8CfDv_w,1092
|
165
|
-
meerschaum/connectors/api/_pipes.py,sha256=
|
165
|
+
meerschaum/connectors/api/_pipes.py,sha256=njBUzhX88EzZ0YJNBNepnTGcv1huXzAnnT0EwaABaBA,20549
|
166
166
|
meerschaum/connectors/api/_plugins.py,sha256=z04tPjfZZWwa7T60mogZH3X3wDmeLdnoN5Oh8m_YsU8,5217
|
167
167
|
meerschaum/connectors/api/_request.py,sha256=Wc4Y70t0VxEj3_ch5fAeeoSAeFMuRnyNLOV-aUFInjY,6996
|
168
168
|
meerschaum/connectors/api/_uri.py,sha256=HWxqGx4R1cHZ3ywy9Ro9ePbFxxusw4RLaC3hpGt9Z6I,1469
|
169
169
|
meerschaum/connectors/api/_users.py,sha256=kzb7ENgXwQ19OJYKOuuWzx2rwVuUZCly9dTnyvVuT2Q,5275
|
170
170
|
meerschaum/connectors/plugin/PluginConnector.py,sha256=aQ1QaB7MordCFimZqoGLb0R12PfDUN_nWks2J5mzeAs,2084
|
171
171
|
meerschaum/connectors/plugin/__init__.py,sha256=pwF7TGY4WNz2_HaVdmK4rPQ9ZwTOEuPHgzOqsGcoXJw,198
|
172
|
-
meerschaum/connectors/sql/_SQLConnector.py,sha256=
|
172
|
+
meerschaum/connectors/sql/_SQLConnector.py,sha256=QlC2Af7AM7bIlPHjUO57mTyzot3zU7o83jegADMxnBE,11829
|
173
173
|
meerschaum/connectors/sql/__init__.py,sha256=3cqYiDkVasn7zWdtOTAZbT4bo95AuvGOmDD2TkaAxtw,205
|
174
174
|
meerschaum/connectors/sql/_cli.py,sha256=1SgnWeMIAihoxp4FzbNrcq1npXf0dSOQnCntpU9hUXA,4405
|
175
175
|
meerschaum/connectors/sql/_create_engine.py,sha256=pZPjy-ne8DtVfu-wqMJopIGkgm8vul-y3E9d4tUyTgM,10215
|
176
176
|
meerschaum/connectors/sql/_fetch.py,sha256=NYYWDoEd-aGIS337KwH-D9_3KVWVCZOHAspGLfdEuUE,13086
|
177
|
-
meerschaum/connectors/sql/_instance.py,sha256=
|
178
|
-
meerschaum/connectors/sql/_pipes.py,sha256=
|
177
|
+
meerschaum/connectors/sql/_instance.py,sha256=zXPZnEqvOAeOUPMeh6CcfkB1pOjjwJxdUOwXccRbuwk,6465
|
178
|
+
meerschaum/connectors/sql/_pipes.py,sha256=m82E9GdBxdfcYCtFWECqmC3HjaZ7Y5ukhQ9LBlEymc4,100605
|
179
179
|
meerschaum/connectors/sql/_plugins.py,sha256=wbxcNxqTtjfDsxPvdVGTllasYf6NHHzODaQ72hEUSBQ,8135
|
180
|
-
meerschaum/connectors/sql/_sql.py,sha256=
|
180
|
+
meerschaum/connectors/sql/_sql.py,sha256=zEh6fbOLJhfLOF-4x9OTQ5Fi3NMSVES3oixmnGYcNG8,36381
|
181
181
|
meerschaum/connectors/sql/_uri.py,sha256=0BrhQtqQdzg9mR04gWBZINs_BbPFtSlTECXT_TCUwik,3460
|
182
182
|
meerschaum/connectors/sql/_users.py,sha256=FJjYeJGhr-TDHziNc6p_5mupGRtGjezKPIYgHFEVSnY,9956
|
183
183
|
meerschaum/connectors/sql/tools.py,sha256=jz8huOaRCwGlYdtGfAqAh7SoK8uydYBrasKQba9FT38,187
|
@@ -204,7 +204,7 @@ meerschaum/core/Pipe/_edit.py,sha256=HrKWe9vhqKaNOjOcJzW5BNbaUBPIbgNAhJEK8OMsy7c
|
|
204
204
|
meerschaum/core/Pipe/_fetch.py,sha256=LtYqZSN2kwc5Tl2gQ5kSmGN7Ombv86k1zDNTP3SUF1k,5417
|
205
205
|
meerschaum/core/Pipe/_register.py,sha256=Sd5xaAW8H7uLTIoommcKb-6kHPRuHJLWNSbPnt2UbvA,2240
|
206
206
|
meerschaum/core/Pipe/_show.py,sha256=nG50y8eBT9TVuKkRgAKtNDNIxysJvMNxfu__lkL1F9k,1352
|
207
|
-
meerschaum/core/Pipe/_sync.py,sha256=
|
207
|
+
meerschaum/core/Pipe/_sync.py,sha256=rEP6Ijs3PG_cTtffqijqxabyyhZFqJicQCNj5Ea3NHw,33042
|
208
208
|
meerschaum/core/Pipe/_verify.py,sha256=sPtY1DgUJ2E5FJp0hJ_IzrQQe1DmfAqJFWS24e2wr3w,14202
|
209
209
|
meerschaum/core/Plugin/__init__.py,sha256=UXg64EvJPgI1PCxkY_KM02-ZmBm4FZpLPIQR_uSJJDc,137
|
210
210
|
meerschaum/core/User/_User.py,sha256=JZ9Y1tsjZe-cgD24m9YfZ6ZwSOKn_sHc4rbQ7KblBz8,6592
|
@@ -218,7 +218,7 @@ meerschaum/plugins/__init__.py,sha256=trMQ53qgP7ikJhhV_uXzqJw6X1NDz2rPOGXFk40bb1
|
|
218
218
|
meerschaum/plugins/bootstrap.py,sha256=qg9MQ1YAU8ShwGqWDl38WjiXLIxDPl95pSIGDLN9rOw,11423
|
219
219
|
meerschaum/utils/__init__.py,sha256=QrK1K9hIbPCRCM5k2nZGFqGnrqhA0Eh-iSmCU7FG6Cs,612
|
220
220
|
meerschaum/utils/_get_pipes.py,sha256=tu4xKPoDn79Dz2kWM13cXTP4DSCkn-3G9M8KiLftopw,11073
|
221
|
-
meerschaum/utils/dataframe.py,sha256=
|
221
|
+
meerschaum/utils/dataframe.py,sha256=G5rD3998mYAVeTlIat7gTPZKvhlpHSMvLo9EHTXocgM,41946
|
222
222
|
meerschaum/utils/debug.py,sha256=GyIzJmunkoPnOcZNYVQdT4Sgd-aOb5MI2VbIgATOjIQ,3695
|
223
223
|
meerschaum/utils/interactive.py,sha256=t-6jWozXSqL7lYGDHuwiOjTgr-UKhdcg61q_eR5mikI,3196
|
224
224
|
meerschaum/utils/misc.py,sha256=ws-8v7gvD2uwmdIDDSRSUVL10XV7YZGUCEFBllC-xbY,46365
|
@@ -227,7 +227,7 @@ meerschaum/utils/pool.py,sha256=vkE42af4fjrTEJTxf6Ek3xGucm1MtEkpsSEiaVzNKHs,2655
|
|
227
227
|
meerschaum/utils/process.py,sha256=o7UtTQX87YGkg2dItPhlvN7gNQPkElXTYSzKf5Ro8Uc,7474
|
228
228
|
meerschaum/utils/prompt.py,sha256=0asF_ndumQIN7p5kEOzK-ldsdE4m8FFapcT3-4wgPi8,19010
|
229
229
|
meerschaum/utils/schedule.py,sha256=6I2TFGa1aPRU9wTdd3YFrJq-DCPpnl-sTWeFEnrINYA,10886
|
230
|
-
meerschaum/utils/sql.py,sha256=
|
230
|
+
meerschaum/utils/sql.py,sha256=vZx6HyvaFKrvWDMZYSzHZaSQWMMWQOUmK-LLW5Kx7Lg,47993
|
231
231
|
meerschaum/utils/threading.py,sha256=3N8JXPAnwqJiSjuQcbbJg3Rv9-CCUMJpeQRfKFR7MaA,2489
|
232
232
|
meerschaum/utils/typing.py,sha256=U3MC347sh1umpa3Xr1k71eADyDmk4LB6TnVCpq8dVzI,2830
|
233
233
|
meerschaum/utils/warnings.py,sha256=IDiwYspsfjIi1gtk3V9cSo9vNLckB9bCsHhRClpPJTc,6639
|
@@ -239,22 +239,22 @@ meerschaum/utils/daemon/StdinFile.py,sha256=J6tyUReM8NEp3bBQAxMfe8mjJG5mWi6CzHN4
|
|
239
239
|
meerschaum/utils/daemon/__init__.py,sha256=o9jWb4lRTIyny4EPt7fPXFgV_vIf1mUofsTwoE1ZecA,8751
|
240
240
|
meerschaum/utils/daemon/_names.py,sha256=d2ZwTxBoTAqXZkCfZ5LuX2XrkQmLNUq1OTlUqfoH5dA,4515
|
241
241
|
meerschaum/utils/dtypes/__init__.py,sha256=LawV4XrCLZRhyGquUen3i0HvK2IRHG-Ud4MYi3L4phA,7391
|
242
|
-
meerschaum/utils/dtypes/sql.py,sha256=
|
242
|
+
meerschaum/utils/dtypes/sql.py,sha256=K0pginy3U5UvgtM9af-HRoiqdvFlwiAmKNQBPGChIUA,16267
|
243
243
|
meerschaum/utils/formatting/__init__.py,sha256=GLx3fvTQi7EnC9fo31WggpMRpmR7yTWIuZmHdZgqvuM,15370
|
244
244
|
meerschaum/utils/formatting/_jobs.py,sha256=izsqPJhTtUkXUUtWnbXtReYsUYwulXtci3pBj72Ne64,6637
|
245
245
|
meerschaum/utils/formatting/_pipes.py,sha256=wy0iWJFsFl3X2VloaiA_gp9Yx9w6tD3FQZvAQAqef4A,19492
|
246
246
|
meerschaum/utils/formatting/_pprint.py,sha256=tgrT3FyGyu5CWJYysqK3kX1xdZYorlbOk9fcU_vt9Qg,3096
|
247
247
|
meerschaum/utils/formatting/_shell.py,sha256=OMFh3cSZNr83z8m265irkS_JtEWHwjkEY2ybnMIOllY,3774
|
248
248
|
meerschaum/utils/packages/__init__.py,sha256=m3HLTkKJxXco1g-h75q2l5skBwKXWaJtNmfQOsijchI,63965
|
249
|
-
meerschaum/utils/packages/_packages.py,sha256=
|
249
|
+
meerschaum/utils/packages/_packages.py,sha256=8Ox9fiQTVmmKAmlxZBV-7Wtq_jhPnnf3AMXvktGE-KY,8319
|
250
250
|
meerschaum/utils/packages/lazy_loader.py,sha256=VHnph3VozH29R4JnSSBfwtA5WKZYZQFT_GeQSShCnuc,2540
|
251
251
|
meerschaum/utils/venv/_Venv.py,sha256=sBnlmxHdAh2bx8btfVoD79-H9-cYsv5lP02IIXkyECs,3553
|
252
252
|
meerschaum/utils/venv/__init__.py,sha256=G3KXL4ByWNqVxBRLs_RaJbO3h3tOKXkazkAYuoUW568,24420
|
253
|
-
meerschaum-2.4.
|
254
|
-
meerschaum-2.4.
|
255
|
-
meerschaum-2.4.
|
256
|
-
meerschaum-2.4.
|
257
|
-
meerschaum-2.4.
|
258
|
-
meerschaum-2.4.
|
259
|
-
meerschaum-2.4.
|
260
|
-
meerschaum-2.4.
|
253
|
+
meerschaum-2.4.8.dist-info/LICENSE,sha256=jG2zQEdRNt88EgHUWPpXVWmOrOduUQRx7MnYV9YIPaw,11359
|
254
|
+
meerschaum-2.4.8.dist-info/METADATA,sha256=9y7GjQHhEDP9mdJWBFuIfZwZ7vtHV0N4Wk0MqF6xuDg,24819
|
255
|
+
meerschaum-2.4.8.dist-info/NOTICE,sha256=OTA9Fcthjf5BRvWDDIcBC_xfLpeDV-RPZh3M-HQBRtQ,114
|
256
|
+
meerschaum-2.4.8.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
257
|
+
meerschaum-2.4.8.dist-info/entry_points.txt,sha256=5YBVzibw-0rNA_1VjB16z5GABsOGf-CDhW4yqH8C7Gc,88
|
258
|
+
meerschaum-2.4.8.dist-info/top_level.txt,sha256=bNoSiDj0El6buocix-FRoAtJOeq1qOF5rRm2u9i7Q6A,11
|
259
|
+
meerschaum-2.4.8.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
260
|
+
meerschaum-2.4.8.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|