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

fix(sqlite): fix returning sqlite and add tests for support sqlite #59

Merged
merged 4 commits into from Jul 18, 2022

Conversation

jhomarolo
Copy link
Contributor

@jhomarolo jhomarolo commented Jul 17, 2022

fix #58

Fixes #

Readiness Checklist

Author/Contributor

  • If documentation is needed for this change, has that been included in this pull request
  • Remember to check if code coverage decrease, if so, please implement the necessary tests

Reviewing Maintainer

  • Label as breaking if this is a large fundamental change
  • Label as either automation, bug, documentation, enhancement, infrastructure, or performance

@codecov
Copy link

codecov bot commented Jul 17, 2022

Codecov Report

Merging #59 (269360f) into master (c9eb0f5) will decrease coverage by 1.31%.
The diff coverage is 50.00%.

❗ Current head 269360f differs from pull request most recent head c0f5eda. Consider uploading reports for the commit c0f5eda to get more accurate results

@@            Coverage Diff             @@
##           master      #59      +/-   ##
==========================================
- Coverage   99.31%   98.00%   -1.32%     
==========================================
  Files           3        3              
  Lines         147      150       +3     
==========================================
+ Hits          146      147       +1     
- Misses          1        3       +2     
Impacted Files Coverage Δ
src/repository.js 96.42% <50.00%> (-2.34%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d23b0b6...c0f5eda. Read the comment docs.

@jhomarolo jhomarolo added the bug Something isn't working label Jul 18, 2022
@jhomarolo jhomarolo merged commit dc85a89 into herbsjs:master Jul 18, 2022
@herbsjs-robot
Copy link

🎉 This PR is included in version 1.5.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

@herbsjs-robot herbsjs-robot added the released Already in production label Jul 18, 2022
@@ -187,6 +187,12 @@ module.exports = class Repository {
.returning(fields)
.insert(payload)

//.returning() is not supported by sqlite3 and will not have any effect, so we have to get last inserted row
if (this.runner().client && this.runner().client.driverName && (this.runner().client.driverName.includes('sqlite3'))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to abstract this to a HasReturningRowSupport method or something similar? Does Knex has something like this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No there is'not. (https://github.com/knex/knex/blob/49ea2b5fa9068cc15aae94258fae673379127d9d/lib/dialects/sqlite3/index.js#L196
)

But SQLLite now supports returning and should be included in knex soon. (knex/knex#4370)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#64 now we can remove this line with this update.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -187,6 +187,12 @@ module.exports = class Repository {
.returning(fields)
.insert(payload)

//.returning() is not supported by sqlite3 and will not have any effect, so we have to get last inserted row
if (this.runner().client && this.runner().client.driverName && (this.runner().client.driverName.includes('sqlite3'))) {
const lastInsertedID = await this.knex.raw(`SELECT last_insert_rowid();`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the async nature of the queries (.insert(payload) and knex.raw('SELECT last_insert_rowid();') ) it seems it could happen a race condition here: the returned value for last_insert_rowid() would be from a different insert, from a different event loop.

Event Loop A: Insert X
Event Loop B: Insert Y
Event Loop A: get last_insert_rowid = Y, but should be X

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right.

We should isolate this in some kind of transaction (http://knexjs.org/guide/transactions.html). I`ll open an issue about this.

//.returning() is not supported by sqlite3 and will not have any effect, so we have to get last inserted row
if (this.runner().client && this.runner().client.driverName && (this.runner().client.driverName.includes('sqlite3'))) {
const lastInsertedID = await this.knex.raw(`SELECT last_insert_rowid();`)
return await this.findByID(lastInsertedID[0]["last_insert_rowid()"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.findByID expect a id(s) from the entity. A "domain" ID.

last_insert_rowid return the PK only if (1) it exists a PK, (2) if it is a integer [1] and (3) if it is not composed PK. Otherwise it returns a number not related to a "domain" ID.

So, the current implementation seems very error-prone. Is this the only method to return the entity?

Suggestion:
If the insertion does not return a error, use the known IDs of the inserted record to retrieve the record.

[1] from doc: If the table has a column of type INTEGER PRIMARY KEY then that column is another alias for the rowid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm aware (also working on it) of this possible bug and will fix it ASAP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working released Already in production
Projects
None yet
Development

Successfully merging this pull request may close these issues.

node-sqlite3 does not currently support RETURNING clause
3 participants