Skip to content
New issue

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

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

Already on GitHub? # to your account

Merge upsert support? #24

Closed
nolanbconaway opened this issue Nov 1, 2023 · 6 comments · Fixed by #136 or #129
Closed

Merge upsert support? #24

nolanbconaway opened this issue Nov 1, 2023 · 6 comments · Fixed by #136 or #129

Comments

@nolanbconaway
Copy link

Hi! Thanks for this awesome tool.

I'm (finally) writing some unit tests for some internal libraries, in which one of the main functions is completing an upsert using the merge feature.

sql= """
    merge into test as dst
    using TMP_TEST_1698864265 as src
        on dst.a = src.a
    when not matched then
        insert (a,b)
            values (src.a,src.b)
    when matched then
        update set a = src.a, b = src.b
"""

cur.execute(sql)

And i get an error like:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/.../3.9.10/envs/aqlib/lib/python3.9/site-packages/fakesnow/fakes.py", line 100, in execute
    return self._execute(command, params, *args, **kwargs)
  File "/home/.../3.9.10/envs/aqlib/lib/python3.9/site-packages/fakesnow/fakes.py", line 164, in _execute
    self._duck_conn.execute(sql, params)
duckdb.ParserException: Parser Error: syntax error at or near "MERGE"
LINE 1: MERGE INTO TEST AS DST USING TMP_TEST_1...

duckdb does not have a MERGE statement (it uses insert-on-conflict), which i presume is the source of this issue. Have you run into this/do you know how you might approach a solution?

For now I am writing out the same merge using INSERT ON CONFLICT depending on the test env, but would be charmed for this to "just work". :)

Info:

  • python 3.9
  • fakesnow==0.7.0
  • duckdb==0.8.1
@tekumara
Copy link
Owner

tekumara commented Nov 6, 2023

I think we could transform simple MERGE statements to INSERT ON CONFLICT, ie: when the clause is when not matched or when matched like in your example.

But if there is a case predicate, eg: when not matched and a < 100 I can't see how to express it in terms of INSERT ON CONFLICT. Likewise for the DELETE action.

We'd probably have to transform this into multiple individual INSERT, UPDATE and DELETE statements.

@sbouclier
Copy link

I have the same issue, would be great to support MERGE statements.

@tekumara
Copy link
Owner

@sbouclier do you have an example of the MERGE statements you'd like support for?

@ngullotta
Copy link

ngullotta commented Aug 22, 2024

Thank you so much for the awesome pytest plugin, this is a great help to testing without wasting a ton of resources.

I would also like to throw my hat in the ring for merge support. It's not that I can't make an upsert do the same as the below, but the aim of my test is to test the functionality of a statement that is pulled in from a different file. So altering the statement at runtime would be tricky

Example of a merge statement I use (excuse the poor formatting):

MERGE INTO 
LINE tgt 
USING (
    SELECT BATCH_NUMBER, ID, ACTIVE_STATUS FROM HEADER WHERE ACTIVE_STATUS = 1
) src
ON tgt.BATCH_NUMBER = src.BATCH_NUMBER
AND tgt.ID = src.ID
AND src.ACTIVE_STATUS IS NULL
WHEN MATCHED THEN UPDATE
   SET tgt.ACTIVE_STATUS = src.ACTIVE_STATUS, tgt.END_DATE = NULL

tekumara added a commit to jazzarati/fakesnow that referenced this issue Sep 8, 2024
This reverts commit dfa68e1.

because it doesn't work when the alias is for a select expression

eg: tekumara#24 (comment)
tekumara pushed a commit that referenced this issue Sep 16, 2024
🤖 I have created a release *beep* *boop*
---


##
[0.9.25](v0.9.24...v0.9.25)
(2024-09-16)


### Features

* Adds MERGE INTO transform
([#109](#109))
([d5e14a7](d5e14a7))
* close duckdb connection
([223f8e2](223f8e2))
* **server:** handle snowflake ProgrammingError
([9455a43](9455a43))
* **server:** support empty result set
([b967b69](b967b69))
* **server:** support FAKESNOW_DB_PATH
([af79f77](af79f77))
* **server:** support time & timestamp types
([1606a3e](1606a3e))
* support MERGE with multiple join columns and source subqueries
([#136](#136))
([9b5a7a0](9b5a7a0)),
closes [#24](#24)


### Chores

* **deps-dev:** bump pyright from 1.1.374 to 1.1.378
([#133](#133))
([593a420](593a420))
* **deps:** update ruff requirement from ~=0.5.1 to ~=0.6.3
([#130](#130))
([6b37d8b](6b37d8b))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: potatobot-prime[bot] <132267321+potatobot-prime[bot]@users.noreply.github.com>
@nolanbconaway
Copy link
Author

Heck yes! This was significant work and I really appreciate what you're doing here @tekumara

@tekumara
Copy link
Owner

Appreciate the support @nolanbconaway! Thanks must go to @jsibbison-square for pushing forward MERGE support. Do let us know if you find any edge cases that aren't supported.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
4 participants