Closed (fixed)
Project:
Drupal core
Version:
7.x-dev
Component:
database system
Priority:
Critical
Category:
Bug report
Assigned:
Reporter:
Created:
14 Oct 2008 at 14:28 UTC
Updated:
27 Nov 2008 at 21:12 UTC
Jump to comment: Most recent file
Comments
Comment #1
dave reidFrom the new DBTNG insert query docs:
As I understand, using db_insert('tablename') should be perfectly valid if there are defaults assigned to each field in the 'tablename' schema. That's not the case with the actions_aid table, but this probably shouldn't be applied globally as you're proposing. I'll let someone else chime in as well.
Comment #2
hswong3i commentedThe document is talking about:
But for the case of actions_aid insert, we do not specify ANY field (so there is no "given field"), and so db_insert() will not able to fill in default value for us. It should be something not included in the document and so should handle as exceptional case :S
Comment #3
dave reidThat's why I said "That's not the case with the actions_aid table". This should be fixed in those special cases where we should be using ->useDefaults, and not be throwing errors when it could be a potentially valid scenario. For example, we have a table
In this case,
db_insert('mytable')->execute()should be valid and not throw an exception as you're proposing.Comment #4
hswong3i commentedSorry that if your assumption is truth, the patch attached should pass correctly :S
Try to apply the patch, run simpletest "Database => Insert tests, default fields", and you should have "17 passes, 1 fail, 2 exceptions".
According to existing test cases, even {test} is coming with fields with all default value defined, we only use db_insert() with following syntax:
Therefore using
$query = db_insert('test');shouldn't be a valid syntax.Comment #5
dave reidUsing db_insert('test') should work just fine. There is an auto-increment field, and two fields with default vaules. I'd like input from db layer maintainers that we need a check for an auto-increment field default value before I continue this more.
Comment #6
hswong3i commented@Dava: One question. What is your testing result when apply patch from #4?
I hope to know if my additional test case is written correctly with expected result. This can even help DB layer maintainers to figure out the problem and patch it as you expected correctly :D
Comment #7
dave reidAfter patch in #4, running Database Insert Defaults test: 18 passes 0 fail, 2 exceptions.
array_fill() [function.array-fill]: Number of elements must be positive Warning query.inc 66 InsertQuery_mysql->__toString()
implode() [function.implode]: Bad arguments. Warning query.inc 67 InsertQuery_mysql->__toString()
Looks like the DB layer should check if there are default fields specified. Attached patch checks count($this->defaultFields) in InsertQuery_driver::__toString(). With new patch, test passes without errors or exceptions.
Comment #8
hswong3i commented@Dava: Sorry again that your patch can't really help the case. After apply your patch and combine test with #371: resolve ANSI SQL-92/99/2003 reserved words conflict in query statements, running simpletest under PostgreSQL:
Which means the INSERT query is still buggy with incorrect syntax. The hidden bug declared in #321056: PHP warnings using db_insert('actions_aid')->execute() in actions_save() is still existing.
Comment #9
Crell commentedMoving to the database component, as it relates to the API itself.
useDefaults() is the correct way to handle this sort of pseudo-sequence. It was added specifically because simpletest required that behavior. Check simpletest for the string "useDefaults" to see how it worked there.
Comment #10
Crell commentedRe #5, no, if you specify no fields at all then you get a syntax error currently, I think. :-) How we should behave in those cases that there are no fields defined (no-op, exception, etc.) is another matter. I'm a bit confused in this issue if we're discussing how to handle that case or how to avoid hitting that case in the first place. Both should be addressed.
Comment #11
hswong3i commentedCrell: Need more hints:
db_insert('test')become valid?db_insert('test')as syntax error, should we add additional run time checking as error report?Comment #12
dries commentedI'll let Crell make this decision, but it looks to me that the current behavior is non-trivial to grok. Is there anything we can do to make this _easier_ to understand (in addition to fixing the problem)?
Comment #13
Crell commentedWell, I see two possible options:
db_insert('test')->execute()should:1) Throw an exception. You're doing something dumb here that would create invalid code in the first place, so check for it, thrown an exception, and let the caller sort it out since he created the problem in the first place.
2) Do nothing and return NULL. An "empty" insert then becomes a NO-OP. On the one hand this is kinda what you'd expect: Insert nothing into {test}. It also means that looping for a multi-insert becomes safer, as the query object checks for empty arrays for you. Right now you must do:
Making an InsertQuery with no fields into an internal NO-OP removes the outer if statement, since it happens inside the execute() method instead.
I can see valid arguments to both approaches. (#1 is "don't babysit broken code", #2 is "the code should do the hard work for you; that's why we write code.) Thoughts? I think I am somewhat leaning toward #2.
Comment #14
hswong3i commentedHmm... I have no preference :-)
Patch attached for case 2. For case 1, please refer to original patch submitted on October 14, 2008.
Comment #15
Crell commentedSo after sleeping on it, I think there are no good cases where a merge query should be missing key fields, so that should throw an exception, but there is a valid use case for no-op insert statements, so those should be handled gracefully.
I think in this case that is equivalent to
count($this->insertFields) + count($this->defaultFields), but can we confirm that? I think I'd be more comfortable with the latter as it's a bit clearer what we're doing.The code comment doesn't flow in English. Try this: "If no fields are specified, this method will do nothing and return NULL. That makes it safe to use in multi-insert loops."
Can we have a test case to confirm this behavior?
Comment #16
Crell commentedBetter title.
Comment #17
hswong3i commentedPatch reroll with:
Hmm... I hate my poor english :S
Comment #18
Crell commentedMuch better. Thanks!
Comment #19
dries commentedCommitted to CVS HEAD. Thanks!