- Notifications
You must be signed in to change notification settings - Fork 59
Add insert_all #306
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
Add insert_all #306
Conversation
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
This looks good. |
Co-authored-by: Matthew Johnston <warmwaffles@gmail.com>
I do not like how often the windows test flaps. |
Ugh
|
475b2f7
to cf69cd5
Compare c_src/sqlite3_nif.c Outdated
| ||
// TODO: MSVC can't do VLA | ||
// int types_array[stmt_param_count]; | ||
int* types_array = (int*)malloc(stmt_param_count * sizeof(int)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use enif_alloc
for this. This way the VM will know about the memory allocated and will count it correctly. Also enif_free
to free the memory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I did it in the very next commit: cf69cd5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah I was walking the changes.
if (rc != SQLITE_DONE) { | ||
return make_sqlite3_error_tuple(env, rc, sqlite3_db_handle(statement->statement)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are missing cleanup code here. We need to enif_free(types_array)
before all of these error returns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right. And not just here, but for every return.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'll need to find another way to pass the types information. The current approach is getting complicated without VLA.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just the nature of C.
One way would be to use a common cleanup statement with goto
like this.
{ // ... if (!enif_get_list_cell(env, head, ¶m, &head)) { goto bad_arg_exception; } // .. enif_free(types_array); return am_done; bad_arg_exception: enif_free(types_array); return raise_badarg(env, param); }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just the nature of C.
I think it should be possible to implement insert_all
or a similar function for bulk inserts with no manual memory allocation. It's only used in a small part of the function -- just to know what types to insert -- but ends up affecting all control flow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder how often this feature would be used and if it is worth it to solve in the NIF.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All Repo.insert_all
calls would go through this NIF and the performance improvement is quite significant (seems close to x2 from my benchmarks, but potentially higher because it allows reusing a single prepared statement for all inserts into a table) so the I think it's worth it.
This PR adds a helper NIF that can be used to bulk-insert "unlimited" number of rows.
Should be enough to clоse #129 once it gets into
ecto_sqlite3
Regarding performance: XQLite uses this approach in
insert_all
benchmark in https://github.com/ruslandoga/elixir-sqlite-bench