I've seen other discussion on how to make variable_del() more useful for uninstalls. One patch attempted to implement wildcard functionality (http://drupal.org/node/93528), but you may as well just use your own query then. However, it would be nice to feed variable_del() an array of variable names instead of just one at a time. I've got some modules settings a few dozen variables, and could envision the function looking like so:
function variable_del($name) {
global $conf;
if (!is_array($name)) {
$name = array($name);
}
foreach ($name as $match) {
db_query("DELETE FROM {variable} WHERE name = '%s'", $match);
cache_clear_all('variables', 'cache');
unset($conf[$match]);
}
}
Forgive me I don't have a way to make a patch right now... I was just making a looong uninstall function and thought this would be handy. Granted, it's not terrible to have to call variable_del() many times over. (And perhaps it's been kept intentionally to 1 variable at a time for reasons I haven't heard.)
If this is kosher and someone else can generate a patch, that'd be awesome.
Comment | File | Size | Author |
---|---|---|---|
#63 | 138544.patch | 11.5 KB | RobLoach |
#60 | 138544.patch | 11.5 KB | RobLoach |
#54 | drupal_variable_functions.patch | 7.54 KB | larowlan |
#42 | 138544-variable-del-v6.patch | 21.47 KB | joshmiller |
#40 | 138544-variable-del-v5.patch | 21.4 KB | joshmiller |
Comments
Comment #1
fgmHere is the patch.
I took
cache_clear_all()
out of the loop, though: I don't see what the point is in keeping it within.Comment #2
moshe weitzman CreditAttribution: moshe weitzman commentedths is much needed - variable_del is quite expensive we definately should batch them like this. you can rewrite so we only execute one delete query WHERE name IN (x,.z,...).
Comment #3
fgmHere is the patch rerolled with just one query.
I seem to remember someone mentioning an issue with security an SELECT .. IN queries, though, but can't remember what it was.
Comment #4
moshe weitzman CreditAttribution: moshe weitzman commentedwell done.
for symetry with variable_get(), i think variable_del() should also handle a string as a param. just check is_string($names) and if true, $names = array($names).
Comment #5
profix898 CreditAttribution: profix898 commented@moshe: The code to handle a string is already in the patch ...
Comment #6
fgmWhile we're at it, why not go further and add array syntax to the other two functions:
In each of these cases, the existing syntax using just strings can be maintained, so existing code would not be affected, but new code could take advantage of this mechanism to reduce the overall number of queries.
With
variable_get
using a static array, changing it would just be a matter of symmetry, not performance, butvariable_set
would also benefit from this change by reducing the number of queries being submitted.Comment #7
webchickNice idea, but we're far past code-freeze at this point.
Comment #8
birdmanx35 CreditAttribution: birdmanx35 commentedThis still works against head, although there is some offset.
$ patch -p0 < bootstrap.inc__6.patch
(Stripping trailing CRs from patch.)
patching file includes/bootstrap.inc
Hunk #1 succeeded at 474 (offset 5 lines).
Comment #9
fgmRerolled against today's HEAD.
Should I add equivalent code to variable_set / variable_get ?
Comment #10
rszrama CreditAttribution: rszrama commentedPersonally, I think it could do with a little bit of white space to separate the different actions in the function... don't know how to better write that. Also, I think the comments could profit from removing the "array of such" language. Perhaps something like so:
Comment #11
Susurrus CreditAttribution: Susurrus commentedRegarding patch in #9, the implode within the query should be db_placeholders instead.
I would update the patch, but I don't have my dev environment setup right now.
Comment #12
Crell CreditAttribution: Crell commentedI would also advise against using the array syntax for variable_get(). It's just very confusing, and not really necessary due to caching.
For variable_set(), if you wanted to use an array syntax for performance I would recommend using an associative array format:
Comment #13
fgmNew patch version replaces the manual expansion by db_placeholders as per #11. Thanks for the suggestion.
Added some vertical spacing and reworded the comments as per #10.
Comment #14
moshe weitzman CreditAttribution: moshe weitzman commentedI encourage you to add support for variable_set() and not add for variable_get(). multiple variable_set() calls have same problem as delete - a cache clear happens for each one.
Comment #15
fgmRegarding
variable_set
, a decision has to be taken regarding the API. There are basically at least three choices:variable_set(array(VAR1, VAR2, VAR3), array(VAL1, VAL2, VAL3))
. This is a natural extension of the scalar syntax:variable_set(VAR1, VAL1)
variable_set(array(VAR1 => VAL1, VAR2 => VAL2, VAR3 => VAL3))
, as suggested by Crellvariable_set(VAR1, VAL1, VAR2, VAL2, VAR3, VAL3)
The second syntax is probably simpler and a better overall fit with most uses of the function, but it is really unnatural and error-prone due to the difference it exhibits with the scalar case. Which would be better ?
Comment #16
webchick#2 is by far easiest for humans to parse. It also matches well with syntax in other areas like t(), FAPI, Menu system....
I would be very -1 to any of the other proposed changes.
Comment #17
dmitrig01 CreditAttribution: dmitrig01 commentedI agree with #2 - and I would be happy to write a regular expression to change all instances to use it.
In the mean time, I changed around variable_del to add a little safeguard for un-necessary queries, and I updated all calls to variable_del to use this new syntax.
Comment #18
Crell CreditAttribution: Crell commentedJust to clarify, you can quite easily support both old and new style variable_set() syntax, and both should be kept. The array syntax is nice if you are doing multiple operations, while the traditional syntax is frequently all you need.
Comment #19
stella CreditAttribution: stella commentedsubscribing
I'd be very interested in variable_del() wildcard functionality. For modules with a lot of configuration settings it's easy to miss a variable or forget to add it to the uninstall function.
Cheers,
Stella
Comment #20
Crell CreditAttribution: Crell commentedFor variable_set(), I've split that off to a separate issue: #317930: Allow multiple values in a single variable_set() call
Comment #21
Anonymous (not verified) CreditAttribution: Anonymous commentedsubscribe
Comment #22
agentrickardIf some form of hook_variables gets in -- #145164: DX: Use hook_variable_info to declare variables and defaults then we can use hook_modules_uninstalled() to clear variables and module developers will no longer need to clear their own variables during hook_uninstall().
I would prefer to see concentration on hook_variables() than a wildcard delete. Because with hook_variables, you can then just call the variables hook, get the array, and run a DBTNG delete statement if you need to batch delete vars outside of the uninstall.
Comment #23
Anonymous (not verified) CreditAttribution: Anonymous commentedThe last submitted patch failed testing.
Comment #24
stokito CreditAttribution: stokito commented:-/ THIS IS VERY VERY VERY STUPID IDEA!
Your bunny wrote!
The only real useful usage of this proposal is when we delete many variables at uninstall module process. Another using isn't important in life.
At first, there is not symmetric with
variable_set
andvariable_get
. Using arrays in parameters ofvariable_set
andvariable_get
is incorrect: not intuitive and confuse lumers like me. Pandora's box.All yours variables must have suffix with module name for escape namespace conflict:
As you suggest if we want delete them we must enumerate ALL variables in parameters:
Code is swelled. It's too many lines (mnogo bukav).
If all variables begins from 'your_module_name' so we can delete them just make query
This solution is very well implemented in #93528: Improve variable_del() by adding another function: variable_del_prefix().
It's short and beautiful!
Patch #93528: Improve variable_del() by adding another function: variable_del_prefix() is more powerful, simplest, quickly, and don't require change another functions.
P.S.
Otherwise if you have many variables you can just do union their to the object an write to one variable:
KISS!
Comment #25
rszrama CreditAttribution: rszrama commented@stokito: That's all fine and dandy, but I've come to realize that you can't count on your module being the only one using your "soft" namespace. Doing that delete query (which is what I've been doing in some Ubercart modules) might wipe data from other modules and you'd never know about it.
Comment #26
Anonymous (not verified) CreditAttribution: Anonymous commented@rszrama: You are correct but the soft namespace could be minimized by requiring a registering of variables from the module and only registered variables are allowed to be stored in the DB. Then variable_del would only delete from the DB the registered variables of the module; variable_del would delete from the cached variable value any variable set with variable_get/set.
Comment #27
rszrama CreditAttribution: rszrama commented@earnie: That would rock. : )
Comment #28
webchickVariable registry is at #145164: DX: Use hook_variable_info to declare variables and defaults. Needs some help. :)
Comment #29
joshmillerWhile the note up at #24 makes some really good points, I thought I would go ahead and re-apply this patch to head. I caught one syntax error (didn't close an array correctly) while fixing the amazing amount of fuzz in the most recent patch. It now applies cleanly.
The code is simply taking the variable_del() function and making it handle (and expect?) arrays for deletion. After going through and reading every line and fixing the patch where it was broken, it almost always seemed to add about three or four lines of code, but it made long recurring statments of "variable_del" ancient history. A lot of modules got around this problem by implementing foreach loops.
I'm not absolutely positive about the DBTNG syntax for the "IN" clause, but I tried my best. Perhaps the test bot will tell us more.
Comment #31
Crell CreditAttribution: Crell commentedDelete queries should always use the query builder. I think what you're after is:
I'm not sure about making the array form required. Available, sure, but like my earlier variable_set() multi-value patch the array can be an extra complication when you don't need it.
Comment #32
joshmillerCrell! Thanks for the tips and the DBTNG magic -- I looked for documentation on using things like "IN" but to no avail. Well, actually I was trying to figure out the syntax to use for the condition function. api.d.o wasn't much help in that department.
I have made your suggestions and re-rolled the patch. Arrays are not required. If you hand it a simple string, it will deal with it just fine.
Josh
Comment #34
joshmillerI've got some ideas on how to really clean this patch up. And apparently I need to actually run an *AMP stack and make sure the PHP syntax doesn't fail... ;-)
Comment #35
Crell CreditAttribution: Crell commentedComment #36
joshmillerCrell - guess that was a bad use of a status?
Attached is a newly optimized patch that good rid of a lot of the unnecessary changes to core modules. As I said before, the function does not require an array for it to work. Thus, I removed all instances where the previous programmer added extra array()s around single values. I think it cut the patch down considerably.
Hopefully the community will see this as a very simple addition to a very simple function. It's just deleting variables, but as you can see when you look at the patch, there was a very a real need for it to handle multiple values.
For the robot who will be checking this for me -- I guarantee that I could not find ANY php invalid syntax in the patch. Though, even after installing MAMP, setting up a database and going through a Drupal install, I still managed to miss syntax issue.
Question: Should I write a simpletest for this additional functionality? Where do I go to learn how to write a simpletest?
Comment #37
joshmillerchanging the status...
Comment #38
Anonymous (not verified) CreditAttribution: Anonymous commentedShould read:
You can delete as few as one and as many as the memory limits will allow so the ``several'' doesn't fit.
Comment #39
Crell CreditAttribution: Crell commented@#36: I'm fully in favor of this patch. For unit tests, have a look at the forked issue: #317930: Allow multiple values in a single variable_set() call. That one is about variable_set(), but includes some unit tests. You can use that as a model. Yes we do want unit tests for this. :-)
Comment #40
joshmiller@38 - fixed.
@39 - Your testing patch and the folks in #drupal helped me get the test function written.
Everything in this release has not been tested, including the new test function, because, while I can run php scripts with XAMPP and cygwin, I cannot seem to get any version of D7 to install without crashing apache. (another issue, i'm sure) I've also added the Performance tag to this issue, as this will increase performance in some fashion. I believe less function calls can result in all kinds of performance increases.
The new test function looks like thus:
Comment #42
joshmillerwhoops... forgot the "function" declaration...
Man, I need to get an IDE so these kind of errors are easier to find...
Comment #43
Damien Tournoud CreditAttribution: Damien Tournoud commentedI discussed with Josh on #drupal:
- I'm not sure this patch leads to any signifiant performance gain (the cache is cleared several times, but that's a quite cheap operation... we don't rebuilt it in that request)
- the only point is DX, and based on PHP syntax
unset($var1, $var2)
, we should supportvariable_del('var1', 'var2')
Comment #44
joshmillerThanks Damien... It is definitely more about DX than performance.
Comment #45
Crell CreditAttribution: Crell commentedI can see the argument for following unset(). However, there's a sister issue for variable_set (#317930: Allow multiple values in a single variable_set() call) for which an array is the only logical form. So we may want to follow that pattern as well.
Arguably I suppose we could support both forms without too much trouble. I'm open to that if others don't think that would cause too much confusion.
Comment #46
Anonymous (not verified) CreditAttribution: Anonymous commentedI can see the value for variable_del('var1', 'var2') instead of variable_del(array('var1', 'var2')). The variables_set(array('var1' => 'val1', 'var2' => 'val2')) is more logical than variables_set('var1', 'val1', 'var2', 'val2'). Since deleting a variable doesn't require a value; I think the proposal makes sense. It requires less typing for the lazy programmer and the line length is shorter. Of course if you're paid by the number of characters you type then the array is much nicer. ;D
Comment #47
RobLoachYup.
Comment #48
fgmIs there really any reason to reject either syntax ? After, it is just /extremely/ simple to improve DX by accepting both with something like:
Comment #49
rszrama CreditAttribution: rszrama commentedI don't think it's good DX to have two different ways to call the same function (even though my original post recommend a method to that effect). I don't think it'd be bad DX to support a variable number of arguments for deleting for reasons stated above (i.e. mimicking PHP's unset()), but it'd be a shame to add extra code to support either scalars or arrays as the first argument.
Inconsistent argument and return value data types is already problem enough. : )
Comment #50
fgmWe've had this in db_query() for years until DBTNG, and I don't think this was actually a problem. Of course PHP-level signature homogeneity would favor vdel(x, y, ..;), but overall Drupal signature homogeneity is screaming for arrays. And vdel(array(x, y, ...)) is not /that/ different from vdel(x, y, ...) but more consistent with Drupal in most respects.
And this little extra code handles a healthy (or not) mix of arrays and vars, not just for the first argument. It's a bit like PHP fundamental choices: if you can make sense of something the coder wrote, do so. More rigor may be valuable, and targeted by other languages, just not this one. Drupal is not written in Java or C#, why not got with the spirit of the language it was created in instead of fighting it ?
Comment #51
sunComment #52
RobLoachI'm actually against supporting the
unset($var1, $var2, $var3)
syntax. It becomes very unconventional in the cases where you actually do want to pass it an array. In addition,func_get_args()
does cause a slight performance hit, and gives us the same result anyway.For example, check this out:
The majority of core does not support this syntax, so we should probably stick with the array vs string argument.
Comment #53
larowlansee also #975118: Allow variable functions (variable_del, variable_get, variable_set) to receive an array of name/value pairs
Comment #54
larowlanhere is patch from #975118: Allow variable functions (variable_del, variable_get, variable_set) to receive an array of name/value pairs
Comment #55
Lars Toomre CreditAttribution: Lars Toomre commentedIssue #987768: [PP-1] Optimize variable caching is being developed to allow incremental variable caching. If that patch hits, it will require changes to the patches proposed here. I hope though that the multiple variable set()/del() functionality will be applied soon thereafter.
Reading through all of the comments above, it appears that the desired calling patterns should be:
* variable_set(string, $value) or variable_set(array)
* variable_del(string) or variable_del(array)
Is this correct? Or does it make sense to introduce plural functions variables_set(array) and variables_get(array) to handle bulk operations and leave the current singular format of variable_set()/get()/del() as is?
My hope is that we can reach agreement on what we want the function profiles to be and then quickly can implement an updated patch once #987768: [PP-1] Optimize variable caching has landed.
For reference, it appears that many agree that bulk variable operations are needed as indicated by the following issues:
#93528: Improve variable_del() by adding another function: variable_del_prefix()
#317930: Allow multiple values in a single variable_set() call
#975118: Allow variable functions (variable_del, variable_get, variable_set) to receive an array of name/value pairs
Comment #56
Lars Toomre CreditAttribution: Lars Toomre commentedAdjusting the title and issue tags
Comment #57
Lars Toomre CreditAttribution: Lars Toomre commented@Berdir over in comment #20 of #317930: Allow multiple values in a single variable_set() call suggests:
This is a much better suggestion than my variables_set(array) and variables_del(array) functions. The resulting function profiles would be:
* variable_get(string, default)
* variable_get_multiple(array)
* variable_set(string, value)
* variable_set_multiple(array)
* variable_del(string)
* variable_del_multiple(array)
There would be no need for a variable helper function to bulk load from data base to static cache as that now would be covered by variable_get_multiple().
In keeping with recent Drupal trend not to abbreviate, should the variable_del() functions be renamed to variable_delete()?
Thoughts?
Comment #58
RobLoachLet's keep having multiple variable_set() and multiple variable_del() as separate issues to keep the patches small. Larry originally created #317930: Allow multiple values in a single variable_set() call with that intent at #20.
Comment #59
Lars Toomre CreditAttribution: Lars Toomre commentedI have no problem with keeping the patches small by having a separate issues for variable_get()/variable_set()/variable_del(). My hope is that we can agree on what the function profiles should be and then get the patches promptly done once #987768: [PP-1] Optimize variable caching lands.
Does it make sense to rename the title to get that focus and then change to variable_del() once consensus is reached?
Comment #60
RobLoachvariable_del(array)
in all hook_uninstall callsWe should probably hit #987768: [PP-1] Optimize variable caching first, but let's see what testing bot says.
Comment #62
Josh The Geek CreditAttribution: Josh The Geek commentedcommas?
Powered by Dreditor.
Comment #63
RobLoachGood catch.
Comment #65
swentel CreditAttribution: swentel commentedvariable_* functions will not exist anymore in D8