fakesnow 0.9.13__py3-none-any.whl → 0.9.14__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.
- fakesnow/fakes.py +2 -1
- fakesnow/transforms.py +38 -22
- {fakesnow-0.9.13.dist-info → fakesnow-0.9.14.dist-info}/METADATA +3 -3
- {fakesnow-0.9.13.dist-info → fakesnow-0.9.14.dist-info}/RECORD +8 -8
- {fakesnow-0.9.13.dist-info → fakesnow-0.9.14.dist-info}/LICENSE +0 -0
- {fakesnow-0.9.13.dist-info → fakesnow-0.9.14.dist-info}/WHEEL +0 -0
- {fakesnow-0.9.13.dist-info → fakesnow-0.9.14.dist-info}/entry_points.txt +0 -0
- {fakesnow-0.9.13.dist-info → fakesnow-0.9.14.dist-info}/top_level.txt +0 -0
fakesnow/fakes.py
CHANGED
@@ -175,7 +175,7 @@ class FakeSnowflakeCursor:
|
|
175
175
|
.transform(transforms.to_timestamp_ntz)
|
176
176
|
.transform(transforms.to_timestamp)
|
177
177
|
.transform(transforms.object_construct)
|
178
|
-
.transform(transforms.
|
178
|
+
.transform(transforms.timestamp_ntz)
|
179
179
|
.transform(transforms.float_to_double)
|
180
180
|
.transform(transforms.integer_precision)
|
181
181
|
.transform(transforms.extract_text_length)
|
@@ -198,6 +198,7 @@ class FakeSnowflakeCursor:
|
|
198
198
|
.transform(transforms.create_user)
|
199
199
|
.transform(transforms.sha256)
|
200
200
|
.transform(transforms.create_clone)
|
201
|
+
.transform(transforms.alias_in_join)
|
201
202
|
)
|
202
203
|
|
203
204
|
def _execute(
|
fakesnow/transforms.py
CHANGED
@@ -13,6 +13,25 @@ MISSING_DATABASE = "missing_database"
|
|
13
13
|
SUCCESS_NOP = sqlglot.parse_one("SELECT 'Statement executed successfully.'")
|
14
14
|
|
15
15
|
|
16
|
+
def alias_in_join(expression: exp.Expression) -> exp.Expression:
|
17
|
+
if (
|
18
|
+
isinstance(expression, exp.Select)
|
19
|
+
and (aliases := {e.args.get("alias"): e for e in expression.expressions if isinstance(e, exp.Alias)})
|
20
|
+
and (joins := expression.args.get("joins"))
|
21
|
+
):
|
22
|
+
j: exp.Join
|
23
|
+
for j in joins:
|
24
|
+
if (
|
25
|
+
(on := j.args.get("on"))
|
26
|
+
and (col := on.this)
|
27
|
+
and (isinstance(col, exp.Column))
|
28
|
+
and (alias := aliases.get(col.this))
|
29
|
+
):
|
30
|
+
col.args["this"] = alias.this
|
31
|
+
|
32
|
+
return expression
|
33
|
+
|
34
|
+
|
16
35
|
def array_size(expression: exp.Expression) -> exp.Expression:
|
17
36
|
if isinstance(expression, exp.ArraySize):
|
18
37
|
# case is used to convert 0 to null, because null is returned by duckdb when no case matches
|
@@ -350,17 +369,13 @@ def extract_comment_on_table(expression: exp.Expression) -> exp.Expression:
|
|
350
369
|
return new
|
351
370
|
elif (
|
352
371
|
isinstance(expression, exp.AlterTable)
|
353
|
-
and (sexp := expression.find(exp.
|
354
|
-
and
|
355
|
-
and (
|
356
|
-
and (eid := eq.find(exp.Identifier))
|
357
|
-
and isinstance(eid.this, str)
|
358
|
-
and eid.this.upper() == "COMMENT"
|
359
|
-
and (lit := eq.find(exp.Literal))
|
372
|
+
and (sexp := expression.find(exp.AlterSet))
|
373
|
+
and (scp := sexp.find(exp.SchemaCommentProperty))
|
374
|
+
and isinstance(scp.this, exp.Literal)
|
360
375
|
and (table := expression.find(exp.Table))
|
361
376
|
):
|
362
377
|
new = SUCCESS_NOP.copy()
|
363
|
-
new.args["table_comment"] = (table,
|
378
|
+
new.args["table_comment"] = (table, scp.this.this)
|
364
379
|
return new
|
365
380
|
|
366
381
|
return expression
|
@@ -596,15 +611,12 @@ def json_extract_cast_as_varchar(expression: exp.Expression) -> exp.Expression:
|
|
596
611
|
"""
|
597
612
|
if (
|
598
613
|
isinstance(expression, exp.Cast)
|
599
|
-
and (to := expression.to)
|
600
|
-
and isinstance(to, exp.DataType)
|
601
|
-
and to.this in {exp.DataType.Type.VARCHAR, exp.DataType.Type.TEXT}
|
602
614
|
and (je := expression.this)
|
603
615
|
and isinstance(je, exp.JSONExtract)
|
604
616
|
and (path := je.expression)
|
605
617
|
and isinstance(path, exp.JSONPath)
|
606
618
|
):
|
607
|
-
|
619
|
+
je.replace(exp.JSONExtractScalar(this=je.this, expression=path))
|
608
620
|
return expression
|
609
621
|
|
610
622
|
|
@@ -937,7 +949,7 @@ def tag(expression: exp.Expression) -> exp.Expression:
|
|
937
949
|
|
938
950
|
if isinstance(expression, exp.AlterTable) and (actions := expression.args.get("actions")):
|
939
951
|
for a in actions:
|
940
|
-
if isinstance(a, exp.
|
952
|
+
if isinstance(a, exp.AlterSet) and a.args.get("tag"):
|
941
953
|
return SUCCESS_NOP
|
942
954
|
elif (
|
943
955
|
isinstance(expression, exp.Command)
|
@@ -947,6 +959,13 @@ def tag(expression: exp.Expression) -> exp.Expression:
|
|
947
959
|
):
|
948
960
|
# alter table modify column set tag
|
949
961
|
return SUCCESS_NOP
|
962
|
+
elif (
|
963
|
+
isinstance(expression, exp.Create)
|
964
|
+
and (kind := expression.args.get("kind"))
|
965
|
+
and isinstance(kind, str)
|
966
|
+
and kind.upper() == "TAG"
|
967
|
+
):
|
968
|
+
return SUCCESS_NOP
|
950
969
|
|
951
970
|
return expression
|
952
971
|
|
@@ -1114,17 +1133,15 @@ def to_timestamp_ntz(expression: exp.Expression) -> exp.Expression:
|
|
1114
1133
|
return expression
|
1115
1134
|
|
1116
1135
|
|
1117
|
-
def
|
1118
|
-
"""Convert timestamp_ntz(
|
1136
|
+
def timestamp_ntz(expression: exp.Expression) -> exp.Expression:
|
1137
|
+
"""Convert timestamp_ntz (snowflake) to timestamp (duckdb).
|
1119
1138
|
|
1120
|
-
|
1139
|
+
NB: timestamp_ntz defaults to nanosecond precision (ie: NTZ(9)). The duckdb equivalent is TIMESTAMP_NS.
|
1140
|
+
However we use TIMESTAMP (ie: microsecond precision) here rather than TIMESTAMP_NS to avoid
|
1141
|
+
https://github.com/duckdb/duckdb/issues/7980 in test_write_pandas_timestamp_ntz.
|
1121
1142
|
"""
|
1122
1143
|
|
1123
|
-
if (
|
1124
|
-
isinstance(expression, exp.DataType)
|
1125
|
-
and expression.this == exp.DataType.Type.TIMESTAMPNTZ
|
1126
|
-
and exp.DataTypeParam(this=exp.Literal(this="9", is_string=False)) in expression.expressions
|
1127
|
-
):
|
1144
|
+
if isinstance(expression, exp.DataType) and expression.this == exp.DataType.Type.TIMESTAMPNTZ:
|
1128
1145
|
return exp.DataType(this=exp.DataType.Type.TIMESTAMP)
|
1129
1146
|
|
1130
1147
|
return expression
|
@@ -1173,7 +1190,6 @@ def try_parse_json(expression: exp.Expression) -> exp.Expression:
|
|
1173
1190
|
return expression
|
1174
1191
|
|
1175
1192
|
|
1176
|
-
# sqlglot.parse_one("create table example(date TIMESTAMP_NTZ(9));", read="snowflake")
|
1177
1193
|
def semi_structured_types(expression: exp.Expression) -> exp.Expression:
|
1178
1194
|
"""Convert OBJECT, ARRAY, and VARIANT types to duckdb compatible types.
|
1179
1195
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fakesnow
|
3
|
-
Version: 0.9.
|
3
|
+
Version: 0.9.14
|
4
4
|
Summary: Fake Snowflake Connector for Python. Run, mock and test Snowflake DB locally.
|
5
5
|
License: Apache License
|
6
6
|
Version 2.0, January 2004
|
@@ -210,10 +210,10 @@ Classifier: License :: OSI Approved :: MIT License
|
|
210
210
|
Requires-Python: >=3.9
|
211
211
|
Description-Content-Type: text/markdown
|
212
212
|
License-File: LICENSE
|
213
|
-
Requires-Dist: duckdb ~=0.10.
|
213
|
+
Requires-Dist: duckdb ~=0.10.3
|
214
214
|
Requires-Dist: pyarrow
|
215
215
|
Requires-Dist: snowflake-connector-python
|
216
|
-
Requires-Dist: sqlglot ~=
|
216
|
+
Requires-Dist: sqlglot ~=24.1.0
|
217
217
|
Provides-Extra: dev
|
218
218
|
Requires-Dist: build ~=1.0 ; extra == 'dev'
|
219
219
|
Requires-Dist: pandas-stubs ; extra == 'dev'
|
@@ -3,16 +3,16 @@ fakesnow/__main__.py,sha256=GDrGyNTvBFuqn_UfDjKs7b3LPtU6gDv1KwosVDrukIM,76
|
|
3
3
|
fakesnow/checks.py,sha256=-QMvdcrRbhN60rnzxLBJ0IkUBWyLR8gGGKKmCS0w9mA,2383
|
4
4
|
fakesnow/cli.py,sha256=9qfI-Ssr6mo8UmIlXkUAOz2z2YPBgDsrEVaZv9FjGFs,2201
|
5
5
|
fakesnow/expr.py,sha256=CAxuYIUkwI339DQIBzvFF0F-m1tcVGKEPA5rDTzmH9A,892
|
6
|
-
fakesnow/fakes.py,sha256=
|
6
|
+
fakesnow/fakes.py,sha256=JM3Tt4ivDC6ddrVioT66yK2irL-wPDDFIEjUBxTq6G8,30277
|
7
7
|
fakesnow/fixtures.py,sha256=G-NkVeruSQAJ7fvSS2fR2oysUn0Yra1pohHlOvacKEk,455
|
8
8
|
fakesnow/global_database.py,sha256=WTVIP1VhNvdCeX7TQncX1TRpGQU5rBf5Pbxim40zeSU,1399
|
9
9
|
fakesnow/info_schema.py,sha256=CdIcGXHEQ_kmEAzdQKvA-PX41LA6wlK-4p1J45qgKYA,6266
|
10
10
|
fakesnow/macros.py,sha256=pX1YJDnQOkFJSHYUjQ6ErEkYIKvFI6Ncz_au0vv1csA,265
|
11
11
|
fakesnow/py.typed,sha256=B-DLSjYBi7pkKjwxCSdpVj2J02wgfJr-E7B1wOUyxYU,80
|
12
|
-
fakesnow/transforms.py,sha256=
|
13
|
-
fakesnow-0.9.
|
14
|
-
fakesnow-0.9.
|
15
|
-
fakesnow-0.9.
|
16
|
-
fakesnow-0.9.
|
17
|
-
fakesnow-0.9.
|
18
|
-
fakesnow-0.9.
|
12
|
+
fakesnow/transforms.py,sha256=8DwHoJ09U2915DovAH_ul0_5WzlUkHYLLK1njyhER4s,51230
|
13
|
+
fakesnow-0.9.14.dist-info/LICENSE,sha256=kW-7NWIyaRMQiDpryfSmF2DObDZHGR1cJZ39s6B1Svg,11344
|
14
|
+
fakesnow-0.9.14.dist-info/METADATA,sha256=qbt6HAOnnIuoB3dZ-JayLpH-pHqVsCQ1l-Qu8lsxSP0,17840
|
15
|
+
fakesnow-0.9.14.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
16
|
+
fakesnow-0.9.14.dist-info/entry_points.txt,sha256=2riAUgu928ZIHawtO8EsfrMEJhi-EH-z_Vq7Q44xKPM,47
|
17
|
+
fakesnow-0.9.14.dist-info/top_level.txt,sha256=500evXI1IFX9so82cizGIEMHAb_dJNPaZvd2H9dcKTA,24
|
18
|
+
fakesnow-0.9.14.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|