-
Notifications
You must be signed in to change notification settings - Fork 7.8k
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
Cannot "unregister" a function, collation or aggregate in SQLite3 extension #10726
Comments
Yeah it looks indeed like the PHP side for createFunction does not handle the NULL case at all, i.e. it's a little more work (but not too bad I think) than just adapting the parameter parsing code. |
@nielsdos if you fix it great, if not I might do it as part of the 'PDO subclasses RFC' which I'm meant to be working on. |
That would be great :) I don't have time to make a PR for this currently, but our non-profit can contribute a (small) bounty towards the fix if someone has time :) And yes, I would also prefer having
I had a look at the code, we should retrieve the function from the collation/function/aggregate dictionary, and un-register it. Please note that to "unregister" a function, we have to use the same encoding and number of arguments when calling sqlite3_create_function_v2, as noted here: https://www.mail-archive.com/[email protected]/msg100765.html |
I ran into a bit of a roadblock. First of all, changing the signature of those 3 functions from Second, using null to unregister creates some really awkward APIs: public SQLite3::createAggregate(
string $name,
?callable $stepCallback,
?callable $finalCallback,
int $argCount = -1
): bool In this case Since |
Yes @nielsdos I agree, for createFunction using NULL is straightforward, but createAggregate would be weird. Also the fact that you have to supply the same argCount could lead to weird behaviour. Creating deleteFunction/deleteAggregate/deleteCollation methods seems the right path then. It wouldn't be too off with setAuthorizer accepting NULL, as it's not called "createAuthorizer", so setAuthorizer(null) makes more sense. As for making the PHP API similar to the SQLite C API, I believe that having delete* methods in the documentation should be quite clear :) All good for me to go with delete* :) |
We can still choose between 3 delete functions versus 1 delete function as PHP can internally bookkeep what kind of function it is. Since @Danack is already doing an RFC it maybe makes more sense that he incorporates this into his work instead of me creating a separate RFC, if Danack's okay with that :) |
AFAIK the work @Danack is doing is only on PDO, not on the SQLite3 extension, so it would still be nice to implement it in SQLite3 :) Because driver-specific methods are forbidden in PDO currently ( sad ), I implemented missing SQLite features only in SQLite3 for now. If at some point we can get all missing features in PDO, and deprecate the SQLite3 extension, it would be great as we wouldn't have to maintain both, and as a PHP developer we wouldn't have to make the tough choice between PDO and SQLite3 depending on which features we need. But that's another topic. Hopefully @Danack RFC will pass and we will be able to catch up in pdo-sqlite. |
Okay, so. I had a look at implementing these and while they're easy to implement, I really don't like the current API for either PDO_SQLITE or Sqlite3 for creating these callbacks. Possibly that's because I don't understand them, but my concerns are: Charset not exposed.The charset that they functions work on isn't exposed. The constants SQLITE_UTF8, SQLITE_UTF16LE, SQLITE_UTF16BE and SQLITE_UTF16 should probably be exposed and be passable as a parameter for all of the callbacks, and SQLITE_UTF16_ALIGNED for collations. Having to pass argc is weird and annoyingThe delete functionality depends on having the name, argc and charset of the function to delete be the same as that of the created callback. If you call the delete function with the same name, but a different argc, it returns SQLITE_OK but doesn't actually delete anything. Having to 'remember' what you passed in as argc for a callback to be able to delete it sounds like an "ungood" API choice. It seems there are two cases:
I'm really tempted to split adding these methods to the PDOSqlite class into a separate RFC, so that the API can be thought about by themselves, rather than being lost in the inevitable opinions people are going to have about the capitalisation of the classes. Thoughts? Edit |
Agreed on the charset issue. About argc and
Yeah this needs some discussion. One idea could be to require the user to pass in the callback function when they delete a sqlite function, such that argc could be derived from that, just like how you suggested it for adding a callback function. But that might be more inconvenient in some cases than having an argc argument and passing in the right argc? |
I'm really leaning towards not including either the unregister or register functions in the Pdo subclasses RFC. They (imo) need to have the charset aka 'Text Rep" parameter exposed, but that means that someone who understands the following needs to say what the code needs to do internally:
Currently, there is a hard-coding of |
I think that the register and unregister should be exposed in PDO, and that we can continue defaulting to UTF-8, as I don't think we've had any request for supporting something else, so it seems "good enough" for me. But that doesn't fix the issue of missing unregister in SQLite3 :) As for argc, yes this is bad, we should be able to provide something simpler, like @nielsdos suggested, or maybe save the callback in an array and have the register method return a resource that can be used to unregister:
This is the same behaviour as used in Javascript for addEventListener/removeEventListener, but I'm not sure if this behavior exists somewhere else in PHP. Instead of returning a resource, an integer could be returned maybe. Not sure what's the best here. |
That was one of my gut instincts....but I'm not sure it actually helps. People using that would still need to track which functions are setup from which parameters, to know which one to unregister. i.e. they would be looking up the resource from an array, based on the function name, params and charset....but they can already track that themselves in userland based on the same parameters. Probably the most sensible API is just:
Though I'm even more convinced it needs a separate RFC to the PDO subclassing one. |
Description
The following code:
Resulted in this output:
But I expected to be able to unregister the custom like function, as documented in SQLite doc:
https://www.sqlite.org/c3ref/create_function.html
Passing NULL to SQLite3::create* methods should un-register the existing function.
PHP Version
Any
Operating System
No response
The text was updated successfully, but these errors were encountered: