Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support MERGE with multiple join columns and source subqueries #136

Merged
merged 47 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
c842900
feat: Adds MERGE INTO transform
jsibbison-square Jun 27, 2024
ab86bf1
Merge branch 'main' into jsibbison-20240627-merge-into
tekumara Jun 29, 2024
40ada94
add test_merge using test case from snowflake docs
tekumara Jun 29, 2024
13a64cb
Merge branch 'main' into jsibbison-20240627-merge-into
jsibbison-square Jul 11, 2024
2eecaea
WIP: working on merge
jsibbison-square Jul 11, 2024
d5d72a2
Merge branch 'main' into jsibbison-20240627-merge-into
jsibbison-square Jul 11, 2024
a580635
implements the return values for merge statement
jsibbison-square Jul 14, 2024
cd38095
Removes old merge implementation
jsibbison-square Jul 15, 2024
0cbeb50
Merge branch 'main' into jsibbison-20240627-merge-into
jsibbison-square Jul 22, 2024
4310802
Adds test for NOT MATCHED INSERT with an AND condition
jsibbison-square Jul 22, 2024
10aa014
Merge branch 'main' into jsibbison-20240627-merge-into
jsibbison-square Aug 28, 2024
2ded345
Ruff fixes
jsibbison-square Aug 28, 2024
71361fd
ruff format
jsibbison-square Aug 28, 2024
dd8923c
fix typos
jsibbison-square Aug 28, 2024
533ca68
Fix pyright in cursor.py
jsibbison-square Aug 28, 2024
8f19190
Extract merge transform to separate file for further refactoring
jsibbison-square Aug 30, 2024
d5c3e88
Extract some outer expressions
jsibbison-square Aug 30, 2024
de6385b
extract remove_table_alias helper
jsibbison-square Aug 30, 2024
d85a7b2
Extract temp merge insertion func
jsibbison-square Aug 30, 2024
b39e2e5
Merge branch 'main' into jsibbison-20240627-merge-into
jsibbison-square Sep 4, 2024
4cd831c
Extract merge tests from test_fakes
jsibbison-square Sep 4, 2024
71457e8
Add documentation to the contents of the merge transformation
jsibbison-square Sep 5, 2024
6905ac3
some ruff fixes
jsibbison-square Sep 5, 2024
7cf899a
more ruff fixes
jsibbison-square Sep 5, 2024
ac83fed
pyright fixes
jsibbison-square Sep 5, 2024
97f6e2d
ruff format fix
jsibbison-square Sep 5, 2024
6763398
remove todo
jsibbison-square Sep 5, 2024
0c71782
Remove debugging print
jsibbison-square Sep 5, 2024
3e3e9c3
add transform test
tekumara Sep 7, 2024
63948c1
refactor class to pure functions
tekumara Sep 7, 2024
dfa68e1
unalias
tekumara Sep 8, 2024
458b545
Revert "unalias"
tekumara Sep 8, 2024
ca19492
.
tekumara Sep 14, 2024
6d77181
.
tekumara Sep 14, 2024
bf24638
_create_merge_candidates passing
tekumara Sep 14, 2024
38e53a9
tidy
tekumara Sep 14, 2024
99cce20
handle many join keys
tekumara Sep 15, 2024
10287ef
wip mutations
tekumara Sep 15, 2024
50d2cb0
working
tekumara Sep 15, 2024
a1fdd4d
.
tekumara Sep 15, 2024
794efd2
support same named join keys
tekumara Sep 15, 2024
2d664f6
Merge branch 'main' of https://github.com/tekumara/fakesnow into merg…
tekumara Sep 15, 2024
1f26cf8
add counts query
tekumara Sep 16, 2024
0cba4ff
handle not matched condition
tekumara Sep 16, 2024
ae2ebf7
.
tekumara Sep 16, 2024
747e9b6
subquery working
tekumara Sep 16, 2024
7f4fd5b
refactor split_transform
tekumara Sep 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions fakesnow/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,11 @@ def is_unqualified_table_expression(expression: exp.Expression) -> tuple[bool, b
no_schema = not node.args.get("db")

return no_database, no_schema


def equal(left: exp.Identifier, right: exp.Identifier) -> bool:
# as per https://docs.snowflake.com/en/sql-reference/identifiers-syntax#label-identifier-casing
lid = left.this if left.quoted else left.this.upper()
rid = right.this if right.quoted else right.this.upper()

return lid == rid
25 changes: 10 additions & 15 deletions fakesnow/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ def execute(
) -> FakeSnowflakeCursor:
try:
self._sqlstate = None
last_execute_result = None

if os.environ.get("FAKESNOW_DEBUG") == "snowflake":
print(f"{command};{params=}" if params else f"{command};", file=sys.stderr)
Expand All @@ -140,15 +139,15 @@ def execute(
command, params = self._rewrite_with_params(command, params)
if self._conn.nop_regexes and any(re.match(p, command, re.IGNORECASE) for p in self._conn.nop_regexes):
transformed = transforms.SUCCESS_NOP
last_execute_result = self._execute(transformed, params)
else:
expression = parse_one(command, read="snowflake")
for exp in self._split_transform(expression):
transformed = self._transform(exp)
last_execute_result = self._execute(transformed, params)
self._execute(transformed, params)
return self

expression = parse_one(command, read="snowflake")
for exp in self._transform_explode(expression):
transformed = self._transform(exp)
self._execute(transformed, params)

assert last_execute_result is not None
return last_execute_result
return self
except snowflake.connector.errors.ProgrammingError as e:
self._sqlstate = e.sqlstate
raise e
Expand Down Expand Up @@ -213,14 +212,12 @@ def _transform(self, expression: exp.Expression) -> exp.Expression:
.transform(transforms.alter_table_strip_cluster_by)
)

def _split_transform(self, expression: exp.Expression) -> list[exp.Expression]:
def _transform_explode(self, expression: exp.Expression) -> list[exp.Expression]:
# Applies transformations that require splitting the expression into multiple expressions
# Split transforms have limited support at the moment.
return transforms.merge(expression)

def _execute(
self, transformed: exp.Expression, params: Sequence[Any] | dict[Any, Any] | None = None
) -> FakeSnowflakeCursor:
def _execute(self, transformed: exp.Expression, params: Sequence[Any] | dict[Any, Any] | None = None) -> None:
self._arrow_table = None
self._arrow_table_fetch_index = None
self._rowcount = None
Expand Down Expand Up @@ -356,8 +353,6 @@ def _execute(
self._last_sql = result_sql or sql
self._last_params = params

return self

def _log_sql(self, sql: str, params: Sequence[Any] | dict[Any, Any] | None = None) -> None:
if (fs_debug := os.environ.get("FAKESNOW_DEBUG")) and fs_debug != "snowflake":
print(f"{sql};{params=}" if params else f"{sql};", file=sys.stderr)
Expand Down
Loading