Skip to content

Multiple query enhanced feedback #429

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

Merged
merged 13 commits into from
Oct 19, 2020
Merged

Multiple query enhanced feedback #429

merged 13 commits into from
Oct 19, 2020

Conversation

cpainterwakefield
Copy link
Contributor

Added ability to iterate over statements in a multi-statement SQL string. Also added Statement methods accessing SQLite's sqlite3_sql() and sqlite3_normalized_sql() functions.

Copy link
Member

@lovasoa lovasoa left a comment

Choose a reason for hiding this comment

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

Great ! I think this is close to what we want. Ideally we would be able to have client code be as simple as :

for (const stmt of db.iterateStatements(txt))
    console.log(stmt.getAsObject())

This would require adding an @@iterator method to the returned object (if the iterator symbol is available in the current runtime.

We need to either automatically free the statements after the iteration is over or make it very explicit in the documentation that we don't. Maybe add an example in the jsdoc, to show how this is supposed to be used.

@cpainterwakefield
Copy link
Contributor Author

Comments above. I will do my best to address your points, but there are aspects of Javascript, and particularly Javascript + emscripten, that I am not well versed in. Long time programmer, but self-taught in Javascript.

@lovasoa
Copy link
Member

lovasoa commented Oct 15, 2020

I just made some testing with your implementation. It looks like db.iterateStatements("\\") returns an infinite iterator (instead of an iterator that raises an error and then finishes).

@cpainterwakefield
Copy link
Contributor Author

Yes, that is because I didn't actually implement the iterable protocols - I wasn't sure that was what was wanted/needed. I used the iterable protocols as an inspiration, but tested it manually (not with for .. of).

@cpainterwakefield
Copy link
Contributor Author

cpainterwakefield commented Oct 15, 2020

OK, so if we want something that works only in a for...of loop and then gets invalidated on exception or when done, that gives me 95% of what I want, which is better than what I have now. The 5% is that I won't have any access to the part of the query that caused an exception when there is an error, because, if I understand correctly, I will have deallocated the memory storing the sql that any pointers I have point into, in the iterator.

I.e., I want to be able to do something like:

let it = db.iterateStatements(sql);
let results = [];
try {
    for (stmt of it) {
        // gather column names, data, rowcount, normalized SQL, etc.
        // add an object to my results collection
    }
} except {
   let lastSql = it.getLastSql();  <--- this I cannot do?
   // add an object with error message and last sql to my results collection
}

Maybe there's a workaround where I copy the tail pointer into a string in the iterator object when there's an exception? Would that make sense to you?

@cpainterwakefield
Copy link
Contributor Author

NVM, I think I have it working. I should be able to push an update tomorrow.

@lovasoa
Copy link
Member

lovasoa commented Oct 16, 2020

If you want to access your "lastSql" after an error, you can attach it to the error type you are throwing... But I don't see the interest, since SQLite doesn't make any guarantee concerning where pzTail is going to end after an invalid SQL statement. What do you want to do with that string ?

@cpainterwakefield
Copy link
Contributor Author

I was never using pzTail itself as the lastSql value, I was trying to subtract pzTail from the nextSql string.

My new code doesn't use pzTail at all, and I don't call it "lastSql" now, as that is confusing (you helped my clarify my thinking on this). Instead, the iterator now has a method "getRemainingSql()", which simply reports the value pointed to by the nextSql pointer. This works, and makes more sense; if a user wants to see the remaining SQL after each statement is prepared, they can do so (not sure why they would, but it is there). In my case, if there is an exception, I can access the remaining SQL to report that "the error occurred in here somewhere".

@lovasoa
Copy link
Member

lovasoa commented Oct 16, 2020

My new code doesn't use pzTail at all, and I don't call it "lastSql" now, as that is confusing (you helped my clarify my thinking on this). Instead, the iterator now has a method "getRemainingSql()", which simply reports the value pointed to by the nextSql pointer. This works, and makes more sense; if a user wants to see the remaining SQL after each statement is prepared, they can do so (not sure why they would, but it is there). In my case, if there is an exception, I can access the remaining SQL to report that "the error occurred in here somewhere".

Perfect, this sounds like what we want

@lovasoa
Copy link
Member

lovasoa commented Oct 16, 2020

I marked everything that was resolved as such. Once the remaining open points are fixed, we can merge.

@cpainterwakefield
Copy link
Contributor Author

I think I've addressed all the change requests... do you want me to resolve the open conversations, or do you prefer to do that?

src/api.js Outdated
Comment on lines 652 to 654
* **Warning**: When you close a database (using db.close()),
* using any statement iterators created by the database will
* result in undefined behavior.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* **Warning**: When you close a database (using db.close()),
* using any statement iterators created by the database will
* result in undefined behavior.

src/api.js Outdated

/**
* @typedef {{
value:Statement,
Copy link
Member

Choose a reason for hiding this comment

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

When the iterator is done, we return { done: true } which doesn't match this definition. I think the most useful type definition we can give is {done : true, value: undefined} | {done: false, value: Statement}.

Copy link
Member

@lovasoa lovasoa left a comment

Choose a reason for hiding this comment

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

We are almost done !

@lovasoa
Copy link
Member

lovasoa commented Oct 19, 2020

I marked all the github conversations that you addressed as resolved.

@cpainterwakefield
Copy link
Contributor Author

Fixed those two documentation issues. I'm very excited to see these changes merged (and hopefully released soon)!

Copy link
Member

@lovasoa lovasoa left a comment

Choose a reason for hiding this comment

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

🎉

@lovasoa lovasoa merged commit e20bb74 into sql-js:master Oct 19, 2020
@lovasoa
Copy link
Member

lovasoa commented Oct 19, 2020

It's on NPM : https://www.npmjs.com/package/sql.js 😃

@cpainterwakefield
Copy link
Contributor Author

Sweet!

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 this pull request may close these issues.

2 participants