fakesnow 0.9.18__py3-none-any.whl → 0.9.19__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 +7 -0
- fakesnow/transforms.py +11 -0
- fakesnow/variables.py +57 -0
- {fakesnow-0.9.18.dist-info → fakesnow-0.9.19.dist-info}/METADATA +1 -1
- {fakesnow-0.9.18.dist-info → fakesnow-0.9.19.dist-info}/RECORD +9 -8
- {fakesnow-0.9.18.dist-info → fakesnow-0.9.19.dist-info}/LICENSE +0 -0
- {fakesnow-0.9.18.dist-info → fakesnow-0.9.19.dist-info}/WHEEL +0 -0
- {fakesnow-0.9.18.dist-info → fakesnow-0.9.19.dist-info}/entry_points.txt +0 -0
- {fakesnow-0.9.18.dist-info → fakesnow-0.9.19.dist-info}/top_level.txt +0 -0
fakesnow/fakes.py
CHANGED
@@ -33,6 +33,7 @@ import fakesnow.info_schema as info_schema
|
|
33
33
|
import fakesnow.macros as macros
|
34
34
|
import fakesnow.transforms as transforms
|
35
35
|
from fakesnow.global_database import create_global_database
|
36
|
+
from fakesnow.variables import Variables
|
36
37
|
|
37
38
|
SCHEMA_UNSET = "schema_unset"
|
38
39
|
SQL_SUCCESS = "SELECT 'Statement executed successfully.' as 'status'"
|
@@ -134,6 +135,7 @@ class FakeSnowflakeCursor:
|
|
134
135
|
if os.environ.get("FAKESNOW_DEBUG") == "snowflake":
|
135
136
|
print(f"{command};{params=}" if params else f"{command};", file=sys.stderr)
|
136
137
|
|
138
|
+
command = self._inline_variables(command)
|
137
139
|
command, params = self._rewrite_with_params(command, params)
|
138
140
|
if self._conn.nop_regexes and any(re.match(p, command, re.IGNORECASE) for p in self._conn.nop_regexes):
|
139
141
|
transformed = transforms.SUCCESS_NOP
|
@@ -148,6 +150,7 @@ class FakeSnowflakeCursor:
|
|
148
150
|
def _transform(self, expression: exp.Expression) -> exp.Expression:
|
149
151
|
return (
|
150
152
|
expression.transform(transforms.upper_case_unquoted_identifiers)
|
153
|
+
.transform(transforms.update_variables, variables=self._conn.variables)
|
151
154
|
.transform(transforms.set_schema, current_database=self._conn.database)
|
152
155
|
.transform(transforms.create_database, db_path=self._conn.db_path)
|
153
156
|
.transform(transforms.extract_comment_on_table)
|
@@ -501,6 +504,9 @@ class FakeSnowflakeCursor:
|
|
501
504
|
|
502
505
|
return command, params
|
503
506
|
|
507
|
+
def _inline_variables(self, sql: str) -> str:
|
508
|
+
return self._conn.variables.inline_variables(sql)
|
509
|
+
|
504
510
|
|
505
511
|
class FakeSnowflakeConnection:
|
506
512
|
def __init__(
|
@@ -525,6 +531,7 @@ class FakeSnowflakeConnection:
|
|
525
531
|
self.db_path = Path(db_path) if db_path else None
|
526
532
|
self.nop_regexes = nop_regexes
|
527
533
|
self._paramstyle = snowflake.connector.paramstyle
|
534
|
+
self.variables = Variables()
|
528
535
|
|
529
536
|
create_global_database(duck_conn)
|
530
537
|
|
fakesnow/transforms.py
CHANGED
@@ -8,6 +8,7 @@ import sqlglot
|
|
8
8
|
from sqlglot import exp
|
9
9
|
|
10
10
|
from fakesnow.global_database import USERS_TABLE_FQ_NAME
|
11
|
+
from fakesnow.variables import Variables
|
11
12
|
|
12
13
|
MISSING_DATABASE = "missing_database"
|
13
14
|
SUCCESS_NOP = sqlglot.parse_one("SELECT 'Statement executed successfully.'")
|
@@ -1407,6 +1408,16 @@ def show_keys(
|
|
1407
1408
|
return expression
|
1408
1409
|
|
1409
1410
|
|
1411
|
+
def update_variables(
|
1412
|
+
expression: exp.Expression,
|
1413
|
+
variables: Variables,
|
1414
|
+
) -> exp.Expression:
|
1415
|
+
if Variables.is_variable_modifier(expression):
|
1416
|
+
variables.update_variables(expression)
|
1417
|
+
return SUCCESS_NOP # Nothing further to do if its a SET/UNSET operation.
|
1418
|
+
return expression
|
1419
|
+
|
1420
|
+
|
1410
1421
|
class SHA256(exp.Func):
|
1411
1422
|
_sql_names: ClassVar = ["SHA256"]
|
1412
1423
|
arg_types: ClassVar = {"this": True}
|
fakesnow/variables.py
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
import re
|
2
|
+
|
3
|
+
import snowflake.connector.errors
|
4
|
+
from sqlglot import exp
|
5
|
+
|
6
|
+
|
7
|
+
# Implements snowflake variables: https://docs.snowflake.com/en/sql-reference/session-variables#using-variables-in-sql
|
8
|
+
class Variables:
|
9
|
+
@classmethod
|
10
|
+
def is_variable_modifier(cls, expr: exp.Expression) -> bool:
|
11
|
+
return isinstance(expr, exp.Set) or cls._is_unset_expression(expr)
|
12
|
+
|
13
|
+
@classmethod
|
14
|
+
def _is_unset_expression(cls, expr: exp.Expression) -> bool:
|
15
|
+
if isinstance(expr, exp.Alias):
|
16
|
+
this_expr = expr.this.args.get("this")
|
17
|
+
return isinstance(this_expr, exp.Expression) and this_expr.this == "UNSET"
|
18
|
+
return False
|
19
|
+
|
20
|
+
def __init__(self) -> None:
|
21
|
+
self._variables = {}
|
22
|
+
|
23
|
+
def update_variables(self, expr: exp.Expression) -> None:
|
24
|
+
if isinstance(expr, exp.Set):
|
25
|
+
unset = expr.args.get("unset")
|
26
|
+
if not unset: # SET varname = value;
|
27
|
+
unset_expressions = expr.args.get("expressions")
|
28
|
+
assert unset_expressions, "SET without values in expression(s) is unexpected."
|
29
|
+
eq = unset_expressions[0].this
|
30
|
+
name = eq.this.sql()
|
31
|
+
value = eq.args.get("expression").sql()
|
32
|
+
self._set(name, value)
|
33
|
+
else:
|
34
|
+
# Haven't been able to produce this in tests yet due to UNSET being parsed as an Alias expression.
|
35
|
+
raise NotImplementedError("UNSET not supported yet")
|
36
|
+
elif self._is_unset_expression(expr): # Unfortunately UNSET varname; is parsed as an Alias expression :(
|
37
|
+
alias = expr.args.get("alias")
|
38
|
+
assert alias, "UNSET without value in alias attribute is unexpected."
|
39
|
+
name = alias.this
|
40
|
+
self._unset(name)
|
41
|
+
|
42
|
+
def _set(self, name: str, value: str) -> None:
|
43
|
+
self._variables[name] = value
|
44
|
+
|
45
|
+
def _unset(self, name: str) -> None:
|
46
|
+
self._variables.pop(name)
|
47
|
+
|
48
|
+
def inline_variables(self, sql: str) -> str:
|
49
|
+
for name, value in self._variables.items():
|
50
|
+
sql = re.sub(rf"\${name}", value, sql, flags=re.IGNORECASE)
|
51
|
+
|
52
|
+
remaining_variables = re.search(r"\$\w+", sql)
|
53
|
+
if remaining_variables:
|
54
|
+
raise snowflake.connector.errors.ProgrammingError(
|
55
|
+
msg=f"Session variable '{remaining_variables.group().upper()}' does not exist"
|
56
|
+
)
|
57
|
+
return sql
|
@@ -3,16 +3,17 @@ 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=cTPjOaFZJbyLOJgh7yGRKxUVXM_MYQbBj9NiK2bkhSs,30881
|
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
|
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=7L7hWg98wrscsIV2-BrTaEhJHhSc9mtroxy-SJkpCnA,52994
|
13
|
+
fakesnow/variables.py,sha256=I7kVVlqttJ_XlYK4fZ-WTSJgGVdvq_DLX3GZR6QoxN8,2361
|
14
|
+
fakesnow-0.9.19.dist-info/LICENSE,sha256=kW-7NWIyaRMQiDpryfSmF2DObDZHGR1cJZ39s6B1Svg,11344
|
15
|
+
fakesnow-0.9.19.dist-info/METADATA,sha256=p4tC5MVPyi6Ud33RZaTBHeYwbYu-Xwu7vNvtWafvkHk,17839
|
16
|
+
fakesnow-0.9.19.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
17
|
+
fakesnow-0.9.19.dist-info/entry_points.txt,sha256=2riAUgu928ZIHawtO8EsfrMEJhi-EH-z_Vq7Q44xKPM,47
|
18
|
+
fakesnow-0.9.19.dist-info/top_level.txt,sha256=500evXI1IFX9so82cizGIEMHAb_dJNPaZvd2H9dcKTA,24
|
19
|
+
fakesnow-0.9.19.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|