fakesnow 0.9.16__tar.gz → 0.9.18__tar.gz
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-0.9.16 → fakesnow-0.9.18}/PKG-INFO +3 -3
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow/fakes.py +4 -2
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow/transforms.py +38 -4
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow.egg-info/PKG-INFO +3 -3
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow.egg-info/requires.txt +2 -2
- {fakesnow-0.9.16 → fakesnow-0.9.18}/pyproject.toml +3 -3
- {fakesnow-0.9.16 → fakesnow-0.9.18}/tests/test_fakes.py +54 -5
- {fakesnow-0.9.16 → fakesnow-0.9.18}/tests/test_transforms.py +48 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/LICENSE +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/README.md +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow/__init__.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow/__main__.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow/checks.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow/cli.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow/expr.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow/fixtures.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow/global_database.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow/info_schema.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow/macros.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow/py.typed +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow.egg-info/SOURCES.txt +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow.egg-info/dependency_links.txt +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow.egg-info/entry_points.txt +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/fakesnow.egg-info/top_level.txt +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/setup.cfg +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/tests/test_checks.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/tests/test_cli.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/tests/test_expr.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/tests/test_info_schema.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/tests/test_patch.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/tests/test_sqlalchemy.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/tests/test_users.py +0 -0
- {fakesnow-0.9.16 → fakesnow-0.9.18}/tests/test_write_pandas.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fakesnow
|
3
|
-
Version: 0.9.
|
3
|
+
Version: 0.9.18
|
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.
|
213
|
+
Requires-Dist: duckdb~=1.0.0
|
214
214
|
Requires-Dist: pyarrow
|
215
215
|
Requires-Dist: snowflake-connector-python
|
216
|
-
Requires-Dist: sqlglot~=
|
216
|
+
Requires-Dist: sqlglot~=25.3.0
|
217
217
|
Provides-Extra: dev
|
218
218
|
Requires-Dist: build~=1.0; extra == "dev"
|
219
219
|
Requires-Dist: pandas-stubs; extra == "dev"
|
@@ -158,6 +158,7 @@ class FakeSnowflakeCursor:
|
|
158
158
|
.transform(transforms.tag)
|
159
159
|
.transform(transforms.semi_structured_types)
|
160
160
|
.transform(transforms.try_parse_json)
|
161
|
+
.transform(transforms.split)
|
161
162
|
# NOTE: trim_cast_varchar must be before json_extract_cast_as_varchar
|
162
163
|
.transform(transforms.trim_cast_varchar)
|
163
164
|
# indices_to_json_extract must be before regex_substr
|
@@ -165,6 +166,7 @@ class FakeSnowflakeCursor:
|
|
165
166
|
.transform(transforms.json_extract_cast_as_varchar)
|
166
167
|
.transform(transforms.json_extract_cased_as_varchar)
|
167
168
|
.transform(transforms.json_extract_precedence)
|
169
|
+
.transform(transforms.flatten_value_cast_as_varchar)
|
168
170
|
.transform(transforms.flatten)
|
169
171
|
.transform(transforms.regex_replace)
|
170
172
|
.transform(transforms.regex_substr)
|
@@ -184,7 +186,7 @@ class FakeSnowflakeCursor:
|
|
184
186
|
.transform(transforms.random)
|
185
187
|
.transform(transforms.identifier)
|
186
188
|
.transform(transforms.array_agg_within_group)
|
187
|
-
.transform(transforms.
|
189
|
+
.transform(transforms.array_agg)
|
188
190
|
.transform(transforms.dateadd_date_cast)
|
189
191
|
.transform(transforms.dateadd_string_literal_timestamp_cast)
|
190
192
|
.transform(transforms.datediff_string_literal_timestamp_cast)
|
@@ -609,7 +611,7 @@ class FakeSnowflakeConnection:
|
|
609
611
|
cursors = [
|
610
612
|
self.cursor(cursor_class).execute(e.sql(dialect="snowflake"))
|
611
613
|
for e in sqlglot.parse(sql_text, read="snowflake")
|
612
|
-
if e
|
614
|
+
if e and not isinstance(e, exp.Semicolon) # ignore comments
|
613
615
|
]
|
614
616
|
return cursors if return_cursors else []
|
615
617
|
|
@@ -41,8 +41,11 @@ def array_size(expression: exp.Expression) -> exp.Expression:
|
|
41
41
|
return expression
|
42
42
|
|
43
43
|
|
44
|
-
def
|
45
|
-
if isinstance(expression, exp.ArrayAgg):
|
44
|
+
def array_agg(expression: exp.Expression) -> exp.Expression:
|
45
|
+
if isinstance(expression, exp.ArrayAgg) and not isinstance(expression.parent, exp.Window):
|
46
|
+
return exp.Anonymous(this="TO_JSON", expressions=[expression])
|
47
|
+
|
48
|
+
if isinstance(expression, exp.Window) and isinstance(expression.this, exp.ArrayAgg):
|
46
49
|
return exp.Anonymous(this="TO_JSON", expressions=[expression])
|
47
50
|
|
48
51
|
return expression
|
@@ -116,9 +119,11 @@ def create_database(expression: exp.Expression, db_path: Path | None = None) ->
|
|
116
119
|
db_name = ident.this
|
117
120
|
db_file = f"{db_path/db_name}.db" if db_path else ":memory:"
|
118
121
|
|
122
|
+
if_not_exists = "IF NOT EXISTS " if expression.args.get("exists") else ""
|
123
|
+
|
119
124
|
return exp.Command(
|
120
125
|
this="ATTACH",
|
121
|
-
expression=exp.Literal(this=f"DATABASE '{db_file}' AS {db_name}", is_string=True),
|
126
|
+
expression=exp.Literal(this=f"{if_not_exists}DATABASE '{db_file}' AS {db_name}", is_string=True),
|
122
127
|
create_db_name=db_name,
|
123
128
|
)
|
124
129
|
|
@@ -436,7 +441,7 @@ def flatten(expression: exp.Expression) -> exp.Expression:
|
|
436
441
|
isinstance(expression, exp.Lateral)
|
437
442
|
and isinstance(expression.this, exp.Explode)
|
438
443
|
and (alias := expression.args.get("alias"))
|
439
|
-
# always true; when no explicit alias provided this will be
|
444
|
+
# always true; when no explicit alias provided this will be flattened
|
440
445
|
and isinstance(alias, exp.TableAlias)
|
441
446
|
):
|
442
447
|
explode_expression = expression.this.this.expression
|
@@ -460,6 +465,25 @@ def flatten(expression: exp.Expression) -> exp.Expression:
|
|
460
465
|
return expression
|
461
466
|
|
462
467
|
|
468
|
+
def flatten_value_cast_as_varchar(expression: exp.Expression) -> exp.Expression:
|
469
|
+
"""Return raw unquoted string when flatten VALUE is cast to varchar.
|
470
|
+
|
471
|
+
Returns a raw string using the Duckdb ->> operator, aka the json_extract_string function, see
|
472
|
+
https://duckdb.org/docs/extensions/json#json-extraction-functions
|
473
|
+
"""
|
474
|
+
if (
|
475
|
+
isinstance(expression, exp.Cast)
|
476
|
+
and isinstance(expression.this, exp.Column)
|
477
|
+
and expression.this.name.upper() == "VALUE"
|
478
|
+
and expression.to.this in [exp.DataType.Type.VARCHAR, exp.DataType.Type.TEXT]
|
479
|
+
and (select := expression.find_ancestor(exp.Select))
|
480
|
+
and select.find(exp.Explode)
|
481
|
+
):
|
482
|
+
return exp.JSONExtractScalar(this=expression.this, expression=exp.JSONPath(expressions=[exp.JSONPathRoot()]))
|
483
|
+
|
484
|
+
return expression
|
485
|
+
|
486
|
+
|
463
487
|
def float_to_double(expression: exp.Expression) -> exp.Expression:
|
464
488
|
"""Convert float to double for 64 bit precision.
|
465
489
|
|
@@ -931,6 +955,16 @@ def show_schemas(expression: exp.Expression, current_database: str | None = None
|
|
931
955
|
return expression
|
932
956
|
|
933
957
|
|
958
|
+
def split(expression: exp.Expression) -> exp.Expression:
|
959
|
+
"""
|
960
|
+
Convert output of duckdb str_split from varchar[] to JSON array to match Snowflake.
|
961
|
+
"""
|
962
|
+
if isinstance(expression, exp.Split):
|
963
|
+
return exp.Anonymous(this="to_json", expressions=[expression])
|
964
|
+
|
965
|
+
return expression
|
966
|
+
|
967
|
+
|
934
968
|
def tag(expression: exp.Expression) -> exp.Expression:
|
935
969
|
"""Handle tags. Transfer tags into upserts of the tag table.
|
936
970
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fakesnow
|
3
|
-
Version: 0.9.
|
3
|
+
Version: 0.9.18
|
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.
|
213
|
+
Requires-Dist: duckdb~=1.0.0
|
214
214
|
Requires-Dist: pyarrow
|
215
215
|
Requires-Dist: snowflake-connector-python
|
216
|
-
Requires-Dist: sqlglot~=
|
216
|
+
Requires-Dist: sqlglot~=25.3.0
|
217
217
|
Provides-Extra: dev
|
218
218
|
Requires-Dist: build~=1.0; extra == "dev"
|
219
219
|
Requires-Dist: pandas-stubs; extra == "dev"
|
@@ -1,17 +1,17 @@
|
|
1
1
|
[project]
|
2
2
|
name = "fakesnow"
|
3
3
|
description = "Fake Snowflake Connector for Python. Run, mock and test Snowflake DB locally."
|
4
|
-
version = "0.9.
|
4
|
+
version = "0.9.18"
|
5
5
|
readme = "README.md"
|
6
6
|
license = { file = "LICENSE" }
|
7
7
|
classifiers = ["License :: OSI Approved :: MIT License"]
|
8
8
|
keywords = ["snowflake", "snowflakedb", "fake", "local", "mock", "testing"]
|
9
9
|
requires-python = ">=3.9"
|
10
10
|
dependencies = [
|
11
|
-
"duckdb~=0.
|
11
|
+
"duckdb~=1.0.0",
|
12
12
|
"pyarrow",
|
13
13
|
"snowflake-connector-python",
|
14
|
-
"sqlglot~=
|
14
|
+
"sqlglot~=25.3.0",
|
15
15
|
]
|
16
16
|
|
17
17
|
[project.urls]
|
@@ -15,6 +15,7 @@ import snowflake.connector.cursor
|
|
15
15
|
import snowflake.connector.pandas_tools
|
16
16
|
from pandas.testing import assert_frame_equal
|
17
17
|
from snowflake.connector.cursor import ResultMetadata
|
18
|
+
from snowflake.connector.errors import ProgrammingError
|
18
19
|
|
19
20
|
import fakesnow
|
20
21
|
from tests.utils import dindent, indent
|
@@ -54,7 +55,7 @@ def test_array_size(cur: snowflake.connector.cursor.SnowflakeCursor):
|
|
54
55
|
assert cur.fetchall() == [(None,)]
|
55
56
|
|
56
57
|
|
57
|
-
def
|
58
|
+
def test_array_agg(dcur: snowflake.connector.cursor.DictCursor):
|
58
59
|
dcur.execute("create table table1 (id number, name varchar)")
|
59
60
|
values = [(1, "foo"), (2, "bar"), (1, "baz"), (2, "qux")]
|
60
61
|
|
@@ -63,6 +64,24 @@ def test_array_agg_to_json(dcur: snowflake.connector.cursor.DictCursor):
|
|
63
64
|
dcur.execute("select array_agg(name) as names from table1")
|
64
65
|
assert dindent(dcur.fetchall()) == [{"NAMES": '[\n "foo",\n "bar",\n "baz",\n "qux"\n]'}]
|
65
66
|
|
67
|
+
# using over
|
68
|
+
|
69
|
+
dcur.execute(
|
70
|
+
"""
|
71
|
+
SELECT DISTINCT
|
72
|
+
ID
|
73
|
+
, ANOTHER
|
74
|
+
, ARRAY_AGG(DISTINCT COL) OVER(PARTITION BY ID) AS COLS
|
75
|
+
FROM (select column1 as ID, column2 as COL, column3 as ANOTHER from
|
76
|
+
(VALUES (1, 's1', 'c1'),(1, 's2', 'c1'),(1, 's3', 'c1'),(2, 's1', 'c2'), (2,'s2','c2')))
|
77
|
+
ORDER BY ID
|
78
|
+
"""
|
79
|
+
)
|
80
|
+
assert dindent(dcur.fetchall()) == [
|
81
|
+
{"ID": 1, "ANOTHER": "c1", "COLS": '[\n "s1",\n "s2",\n "s3"\n]'},
|
82
|
+
{"ID": 2, "ANOTHER": "c2", "COLS": '[\n "s1",\n "s2"\n]'},
|
83
|
+
]
|
84
|
+
|
66
85
|
|
67
86
|
def test_array_agg_within_group(dcur: snowflake.connector.cursor.DictCursor):
|
68
87
|
dcur.execute("CREATE TABLE table1 (ID INT, amount INT)")
|
@@ -324,6 +343,17 @@ def test_connect_with_non_existent_db_or_schema(_fakesnow_no_auto_create: None):
|
|
324
343
|
assert conn.schema == "JAFFLES"
|
325
344
|
|
326
345
|
|
346
|
+
def test_create_database_respects_if_not_exists() -> None:
|
347
|
+
with tempfile.TemporaryDirectory(prefix="fakesnow-test") as db_path, fakesnow.patch(db_path=db_path):
|
348
|
+
cursor = snowflake.connector.connect().cursor()
|
349
|
+
cursor.execute("CREATE DATABASE db2")
|
350
|
+
|
351
|
+
with pytest.raises(ProgrammingError, match='Database "DB2" is already attached with path'):
|
352
|
+
cursor.execute("CREATE DATABASE db2") # Fails as db already exists.
|
353
|
+
|
354
|
+
cursor.execute("CREATE DATABASE IF NOT EXISTS db2")
|
355
|
+
|
356
|
+
|
327
357
|
def test_dateadd_date_cast(dcur: snowflake.connector.DictCursor):
|
328
358
|
q = """
|
329
359
|
SELECT
|
@@ -678,11 +708,14 @@ def test_executemany(cur: snowflake.connector.cursor.SnowflakeCursor):
|
|
678
708
|
|
679
709
|
|
680
710
|
def test_execute_string(conn: snowflake.connector.SnowflakeConnection):
|
681
|
-
|
682
|
-
"""
|
683
|
-
|
711
|
+
*_, cur = conn.execute_string(
|
712
|
+
"""
|
713
|
+
create table customers (ID int, FIRST_NAME varchar, LAST_NAME varchar);
|
714
|
+
-- test comments are ignored
|
715
|
+
select count(*) customers
|
716
|
+
"""
|
684
717
|
)
|
685
|
-
assert
|
718
|
+
assert cur.fetchall() == [(1,)]
|
686
719
|
|
687
720
|
|
688
721
|
def test_fetchall(conn: snowflake.connector.SnowflakeConnection):
|
@@ -796,6 +829,18 @@ def test_flatten(cur: snowflake.connector.cursor.SnowflakeCursor):
|
|
796
829
|
assert cur.fetchall() == [(1, '"banana"'), (2, '"coconut"'), (2, '"durian"')]
|
797
830
|
|
798
831
|
|
832
|
+
def test_flatten_value_cast_as_varchar(cur: snowflake.connector.cursor.SnowflakeCursor):
|
833
|
+
cur.execute(
|
834
|
+
"""
|
835
|
+
select id, f.value::varchar as v
|
836
|
+
from (select column1 as id, column2 as col from (values (1, 's1,s2,s3'), (2, 's1,s2'))) as t
|
837
|
+
, lateral flatten(input => split(t.col, ',')) as f order by id
|
838
|
+
"""
|
839
|
+
)
|
840
|
+
# should be raw string not json string with double quotes
|
841
|
+
assert cur.fetchall() == [(1, "s1"), (1, "s2"), (1, "s3"), (2, "s1"), (2, "s2")]
|
842
|
+
|
843
|
+
|
799
844
|
def test_floats_are_64bit(cur: snowflake.connector.cursor.SnowflakeCursor):
|
800
845
|
cur.execute("create or replace table example (f float, f4 float4, f8 float8, d double, r real)")
|
801
846
|
cur.execute("insert into example values (1.23, 1.23, 1.23, 1.23, 1.23)")
|
@@ -1329,6 +1374,10 @@ def test_show_primary_keys(dcur: snowflake.connector.cursor.SnowflakeCursor):
|
|
1329
1374
|
assert result3 == []
|
1330
1375
|
|
1331
1376
|
|
1377
|
+
def test_split(cur: snowflake.connector.cursor.SnowflakeCursor):
|
1378
|
+
assert indent(cur.execute("select split('a,b,c', ',')").fetchall()) == [('[\n "a",\n "b",\n "c"\n]',)]
|
1379
|
+
|
1380
|
+
|
1332
1381
|
def test_sqlglot_regression(cur: snowflake.connector.cursor.SnowflakeCursor):
|
1333
1382
|
assert cur.execute(
|
1334
1383
|
"""with SOURCE_TABLE AS (SELECT '2024-01-01' AS start_date)
|
@@ -8,6 +8,7 @@ from fakesnow.transforms import (
|
|
8
8
|
SUCCESS_NOP,
|
9
9
|
_get_to_number_args,
|
10
10
|
alias_in_join,
|
11
|
+
array_agg,
|
11
12
|
array_agg_within_group,
|
12
13
|
array_size,
|
13
14
|
create_clone,
|
@@ -21,6 +22,7 @@ from fakesnow.transforms import (
|
|
21
22
|
extract_comment_on_table,
|
22
23
|
extract_text_length,
|
23
24
|
flatten,
|
25
|
+
flatten_value_cast_as_varchar,
|
24
26
|
float_to_double,
|
25
27
|
identifier,
|
26
28
|
indices_to_json_extract,
|
@@ -40,6 +42,7 @@ from fakesnow.transforms import (
|
|
40
42
|
sha256,
|
41
43
|
show_objects_tables,
|
42
44
|
show_schemas,
|
45
|
+
split,
|
43
46
|
tag,
|
44
47
|
timestamp_ntz,
|
45
48
|
to_date,
|
@@ -78,6 +81,22 @@ def test_array_size() -> None:
|
|
78
81
|
)
|
79
82
|
|
80
83
|
|
84
|
+
def test_array_agg() -> None:
|
85
|
+
assert (
|
86
|
+
sqlglot.parse_one("SELECT ARRAY_AGG(name) AS names FROM table1").transform(array_agg).sql(dialect="duckdb")
|
87
|
+
== "SELECT TO_JSON(ARRAY_AGG(name)) AS names FROM table1"
|
88
|
+
)
|
89
|
+
|
90
|
+
assert (
|
91
|
+
sqlglot.parse_one(
|
92
|
+
"SELECT DISTINCT ID, ANOTHER, ARRAY_AGG(DISTINCT COL) OVER(PARTITION BY ID) AS COLS FROM TEST"
|
93
|
+
)
|
94
|
+
.transform(array_agg)
|
95
|
+
.sql(dialect="duckdb")
|
96
|
+
== "SELECT DISTINCT ID, ANOTHER, TO_JSON(ARRAY_AGG(DISTINCT COL) OVER (PARTITION BY ID)) AS COLS FROM TEST"
|
97
|
+
)
|
98
|
+
|
99
|
+
|
81
100
|
def test_array_agg_within_group() -> None:
|
82
101
|
assert (
|
83
102
|
sqlglot.parse_one(
|
@@ -125,6 +144,13 @@ def test_create_database() -> None:
|
|
125
144
|
== "ATTACH DATABASE '.databases/foobar.db' AS foobar"
|
126
145
|
)
|
127
146
|
|
147
|
+
assert (
|
148
|
+
sqlglot.parse_one("create database if not exists foobar")
|
149
|
+
.transform(create_database, db_path=Path(".databases/"))
|
150
|
+
.sql()
|
151
|
+
== "ATTACH IF NOT EXISTS DATABASE '.databases/foobar.db' AS foobar"
|
152
|
+
)
|
153
|
+
|
128
154
|
|
129
155
|
def test_describe_table() -> None:
|
130
156
|
assert "SELECT" in sqlglot.parse_one("describe table db1.schema1.table1").transform(describe_table).sql()
|
@@ -400,6 +426,22 @@ def test_flatten() -> None:
|
|
400
426
|
)
|
401
427
|
|
402
428
|
|
429
|
+
def test_flatten_value_cast_as_varchar() -> None:
|
430
|
+
assert (
|
431
|
+
sqlglot.parse_one(
|
432
|
+
"""
|
433
|
+
SELECT ID , F.VALUE::varchar as V
|
434
|
+
FROM TEST AS T
|
435
|
+
, LATERAL FLATTEN(input => SPLIT(T.COL, ',')) AS F;
|
436
|
+
""",
|
437
|
+
read="snowflake",
|
438
|
+
)
|
439
|
+
.transform(flatten_value_cast_as_varchar)
|
440
|
+
.sql(dialect="duckdb")
|
441
|
+
== """SELECT ID, F.VALUE ->> '$' AS V FROM TEST AS T, LATERAL UNNEST(input => STR_SPLIT(T.COL, ',')) AS F(SEQ, KEY, PATH, INDEX, VALUE, THIS)""" # noqa: E501
|
442
|
+
)
|
443
|
+
|
444
|
+
|
403
445
|
def test_float_to_double() -> None:
|
404
446
|
assert (
|
405
447
|
sqlglot.parse_one("create table example (f float, f4 float4, f8 float8, d double, r real)")
|
@@ -610,6 +652,12 @@ def test_show_schemas() -> None:
|
|
610
652
|
)
|
611
653
|
|
612
654
|
|
655
|
+
def test_split() -> None:
|
656
|
+
assert (
|
657
|
+
sqlglot.parse_one("SELECT split('a,b,c', ',')").transform(split).sql() == "SELECT TO_JSON(SPLIT('a,b,c', ','))"
|
658
|
+
)
|
659
|
+
|
660
|
+
|
613
661
|
def test_tag() -> None:
|
614
662
|
assert sqlglot.parse_one("ALTER TABLE table1 SET TAG foo='bar'", read="snowflake").transform(tag) == SUCCESS_NOP
|
615
663
|
assert (
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|