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

Request: Data-Modifying CTEs #60

Open
successfulmike opened this issue May 26, 2022 · 4 comments
Open

Request: Data-Modifying CTEs #60

successfulmike opened this issue May 26, 2022 · 4 comments

Comments

@successfulmike
Copy link

Request:
I'd like to request the connection.execute_query function permit CTEs (Common Table Expressions) with DML operations as noted in below examples on Postgre's main webpage (see section 7.8.2. Data-Modifying Statements in WITH)
https://www.postgresql.org/docs/13/queries-with.html#QUERIES-WITH-MODIFYING

Purpose:
We'd like to have the ability to persist the original records before they're updated or deleted within the same query using the RETURNING clause. This seems to also be allowed in existing Tableau Hyper API document (https://help.tableau.com/current/api/hyper_api/en-us/reference/sql/sql-delete.html); trying this today (tableauhyperapi 0.0.14265) throws an exception

tableauhyperapi.hyperexception.HyperException: syntax error: got "delete", expected "explain", "select", "table", "values", "with", "with ", '(:'

Alternative (in case of technical limitation):
First call the connection.execute_query function that returns the rows that will be updated or deleted and persist them in a Results object (dataframe), then call the connection.execute_command function that performs the update or delete operation (using same filter from step one above).

@rferraton
Copy link

MS SQL OUTPUT Clause is an équivalent of RETURNING postgresql clause.
It is often use for SCD loading in combinaison with the MERGE statement : https://www.mssqltips.com/sqlservertip/1704/using-merge-in-sql-server-to-insert-update-and-delete-at-the-same-time/

I agree with you, this kind of clause (RETURNING or OUTPUT) can be usefull

@vogelsgesang
Copy link
Contributor

This seems to also be allowed in existing Tableau Hyper API document (https://help.tableau.com/current/api/hyper_api/en-us/reference/sql/sql-delete.html); trying this today (tableauhyperapi 0.0.14265) throws an exception

Both the RETURNING clause and the WITH clause can definitely be combined with a DELETE statement in Hyper.

The queries below are part of our test suite, and Hyper is able to execute them succesfully:

Can you please provide a complete, self-contained repro of your issue?


RETURNING clause:

CREATE TABLE FOO ( A INT, B INT, C INT, D INT);

INSERT INTO FOO SELECT INDEX, INDEX + 1, INDEX + 2, INDEX + 3 FROM SEQUENCE(1,100);

DELETE FROM FOO WHERE A = 1 RETURNING A;

DELETE FROM FOO WHERE A = 11 RETURNING A,B,C;

WITH clause and RETURNING clause:

CREATE TABLE t1 AS SELECT i AS a FROM generate_series(1,7) s(i)

--- We can refer to a CTE defined by a WITH clause in the WHERE clause
WITH v(x) AS (VALUES(1),(3))
DELETE FROM t1
WHERE EXISTS(SELECT * FROM v WHERE x = a)
RETURNING a
-- result: 1, 3

-- We can also refer to it from the RETURNING clause
query tsv XX rowsort
WITH v(x) AS (VALUES(2),(3))
DELETE FROM t1
WHERE a > 5
RETURNING a, (SELECT MAX(x) FROM v WHERE a%x = 0)
-- result:
-- 6   3
-- 7   NULL

-- We can even use recursive CTEs
WITH RECURSIVE v(x) AS (SELECT 4 UNION ALL SELECT x+1 FROM v WHERE x < 5)
DELETE FROM t1
WHERE EXISTS(SELECT * FROM v WHERE x = a)
RETURNING a
-- result: 4, 5

@successfulmike
Copy link
Author

@vogelsgesang , can you specify which version of the API you confirmed this with? I'm also specifically creating endpoint requests via Python so I'm leveraging the connection.execute_query method. Does your test do the same?

@vogelsgesang
Copy link
Contributor

vogelsgesang commented May 31, 2022

I verified this using the latest internal HyperAPI-build, but the test case in question was unmodified for a couple of years already, so the HyperAPI version doesn't matter. I am using execute_query through C++ instead of Python, but that doesn't change how Hyper interprets SQL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants