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 returning clause to avoid database hits #183

Closed
marlon-sousa opened this issue Sep 21, 2021 · 5 comments · Fixed by #292
Closed

Support returning clause to avoid database hits #183

marlon-sousa opened this issue Sep 21, 2021 · 5 comments · Fixed by #292
Assignees

Comments

@marlon-sousa
Copy link

Hello,

I took a look at discussions and haven't found nothing, so I am opening this issue to discuss something important.

We need to support returning clauses in updates and insert clauses.

Rationale

Sometimes, we need to perform batch operations, by means of multiple inserts or updates which affect more than one record and, at the same time, have the newly inserted / the updated records back in the same database operation.

This is needed, for example, when you need to insert records and have their auto incremented generated ids back to store somewhere for latter use, or when you need to update one or more records and, at the same time, get back columns you didn't have when you performed the update operation.

The way sql handles this is by using a returning clause on the query, making the database, in one operation, perform inserts / updates and also returning information you need instead of forcing you to make a latter select.

Proposal

We propose an extension to the current sea-orm api.

update_many

The UpdateMany struct should have another method, called returning.

Kind of code below

pub fn returning<T>(mut self, record_info: RecordInfo) -> Self

RecordInfo should be an enum like

pub enum RecordInfo {
  Columns(Vec<Entity::Columns>,
  FullRecord,
  PrimaryKey,
}

The returning function would generate a returning sql clause, as follows:

let returning_sql = match RecordInfo {
  Columns(c) => c.map(| col | col.to_string()).join(", "),
FullRecord => "*".into(),
  PrimaryKey: // build list of columns making part of the primary key
}

The insert_many would go the very same path.

The ExecResult would need to ave a vector of ActiveModels with the appropriate columns set for each returned record.

What do you think?

I could try to implement that, I would need some mentoring but I am now more focused in stablishing the api, latter we can think in the implementation.

@billy1624
Copy link
Member

Sounds good to me! But note that only Postgres support returning syntax. We have to take account of that.

@marlon-sousa
Copy link
Author

To deal with that we have some options:

  1. Enable the returning only when postgres is being used with features.
  2. For non postgresql databases, investigate a way of producing the same results either by using transactions where we can update and then select / insert and then select or issue more than one connection if we don't want to use transactions.

I would first implement strategy one and then with more time implement strategy 2.

Why?

Because postgres users like me are likely to need it soon and we can give the bonus to non postgres users latter.

What do you think?

@nicoulaj
Copy link

related: #148

@billy1624
Copy link
Member

Reasonable!! @marlon-sousa

@billy1624
Copy link
Member

Just to summarise the support of RETURNING syntax across various databases...

Postgres

  • All versions

MySQL

  • Not supported

MariaDB

SQLite

  • Supported since version 3.35.0 (2021-03-12)
  • RETURNING

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

Successfully merging a pull request may close this issue.

4 participants