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

Support multiple rows for DML RETURNING #6815

Closed
mrotteveel opened this issue May 17, 2021 · 14 comments
Closed

Support multiple rows for DML RETURNING #6815

mrotteveel opened this issue May 17, 2021 · 14 comments

Comments

@mrotteveel
Copy link
Member

mrotteveel commented May 17, 2021

Currently, DML RETURNING only supports singleton inserts/updates/deletes. This restriction should be relaxed so that the following statements can return multiple rows:

  • INSERT ... SELECT ...
  • Searched UPDATE
  • Searched DELETE
  • MERGE
  • UPDATE OR INSERT

The following can remain as-is (though maybe a unified implementation makes more sense?):

  • INSERT ... DEFAULT VALUES / INSERT ... VALUES (...) (at least, until Firebird supports table value constructors)
  • Positioned UPDATE (with WHERE CURRENT OF ...)
  • Positioned DELETE (with WHERE CURRENT OF ...)

I suggest the implementation describes itself as isc_info_sql_stmt_select; this should make it compatible with most libraries and tools that rely on the statement type to decide on how to execute. The alternative is to introduce a new type (or types), for example isc_info_sql_stmt_dml_returning or something, but I think that makes things harder because tools and libraries would need to be updated to support this.

When such a statement is executed, Firebird should execute the statement to completion and collect all requested data in a type of temporary table, once execution is complete, fetches are done against this temporary table. In other words, even if no rows are fetched, all DML changes have been performed.

In PSQL, these statements should use the current singleton behaviour.

Non-singleton FOR ... RETURNING in PSQL is tracked in #6925.

@asfernandes
Copy link
Member

Should we have some option (config / DPB / SET) to maintain DSQL compatibility?

@AlexPeshkoff
Copy link
Member

AlexPeshkoff commented May 17, 2021 via email

@dyemanov
Copy link
Member

I don't think it should be configurable.

@asfernandes
Copy link
Member

I don't think it should be configurable.

I don't remember exact reason for why it was done as singleton.

Was it due to extra remote protocol roundtrip?

@aafemt
Copy link
Contributor

aafemt commented May 17, 2021

Problem with partially fetched result set.

@dyemanov
Copy link
Member

I don't think it should be configurable.

I don't remember exact reason for why it was done as singleton.

Was it due to extra remote protocol roundtrip?

Exactly. And RETURNING was primarily intended for a INSERT ... VALUES statement which is singular anyway.

@asfernandes asfernandes self-assigned this May 18, 2021
@mrotteveel
Copy link
Member Author

To address the roundtrip thing, we could consider introducing a new execute method which will stream all rows without requiring fetches, but that could be overkill.

@mrotteveel
Copy link
Member Author

Problem with partially fetched result set.

I specifically address that in my proposal:

When such a statement is executed, Firebird should execute the statement to completion and collect all requested data in a type of temporary table, once execution is complete, fetches are done against this temporary table. In other words, even if no rows are fetched, all DML changes have been performed.

@asfernandes
Copy link
Member

When such a statement is executed, Firebird should execute the statement to completion and collect all requested data in a type of temporary table, once execution is complete, fetches are done against this temporary table. In other words, even if no rows are fetched, all DML changes have been performed.

I want more opinions on this.

I understand the problem you want to avoid, specially in remote protocol which things can be buffered.

But it will make DSQL and PSQL with very different behavior.

Assuming we have a procedure P2 doing FOR UPDATE ... RETURNING ... SUSPEND and P1 calling it (with FOR SELECT) and interrupting before all rows are selected, it will do partial update and seems ok.

But with an EXECUTE BLOCK doing FOR UPDATE ... RETURNING ... SUSPEND and client interrupting it, it will still have undefined behavior on how many records were updated.

@hvlad
Copy link
Member

hvlad commented Jul 15, 2021

FOR UPDATE\DELETE ... RETURNING could (should?) also buffer all returned rows before getting them out

@mrotteveel
Copy link
Member Author

I think even in PSQL, a FOR UPDATE ... RETURNING ... should perform the entire update and cache/store the result set before emitting rows.

@asfernandes
Copy link
Member

I have split the PSQL FOR in #6925, so we can start with the DSQL changes.

asfernandes added a commit to FirebirdSQL/fbtcs that referenced this issue Aug 25, 2021
asfernandes added a commit that referenced this issue Aug 27, 2021
asfernandes added a commit that referenced this issue Aug 27, 2021
Failing test bugs.core_0501, noted by Vlad.
@pavel-zotov
Copy link

::: test details :::

Test verifies only basic issues related mostly to syntax and ability to get multiple rows.
Both DSQL and PSQL are tested.

Interruption of fetching process by client (and check number of affected rows) is NOT verified:
separate test will be made later (see ticket, comment by Adriano, date: 15-JUL-2021).

@asfernandes
Copy link
Member

::: test details :::

Test verifies only basic issues related mostly to syntax and ability to get multiple rows.
Both DSQL and PSQL are tested.

Interruption of fetching process by client (and check number of affected rows) is NOT verified:
separate test will be made later (see ticket, comment by Adriano, date: 15-JUL-2021).

@pavel-zotov to make things clear, the atomic changes, then returning, is already implemented for the DSQL case.

And for PSQL without FOR (tracked in #6925), things should work as before.

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

No branches or pull requests

7 participants