The insert of {actions_aid} don't use useDefaults() in db_insert().
Detail
Original legacy INSERT query is now update as TNGDB syntax (check CVS log message), from:
db_query('INSERT INTO {actions_aid} VALUES (default)');
$aid = db_last_insert_id('actions_aid', 'aid');
To:
$aid = db_insert('actions_aid')->execute();
BTW, according to the query builder of db_insert(), the above command will translate as:
INSERT INTO {actions_aid} () VALUES ()
Which is potentially buggy in SQL syntax.
Bug reproduction
When combine test with #371: resolve ANSI SQL-92/99/2003 reserved words conflict in query statements DB's patch, PDOException is happened with following message:
PDOException: INSERT INTO [{actions_aid}] ([]) VALUES () SQLSTATE[21S01]: Insert value list does not match column list:...
Patch effect
After patch, the final SQL will become:
INSERT INTO [{actions_aid}] ([aid]) VALUES (DEFAULT)
Which is safe for SQL syntax restriction.
Tested platform
Both MySQL and PostgreSQL pass simpletest "System => Actions configuration"; combine test with #371: resolve ANSI SQL-92/99/2003 reserved words conflict in query statements is also passed in both cases.
| Comment | File | Size | Author |
|---|---|---|---|
| #8 | testDefaultInsertWithNone-D7.patch | 2.69 KB | dave reid |
| #2 | dbtng-actions_save-1223991760.patch | 721 bytes | hswong3i |
| tngdb-actions_save-1223986797.patch | 705 bytes | hswong3i |
Comments
Comment #1
dave reidThat's my bad on the original patch for DBTNG & actions.inc. :) Since this is no longer just a short DB command, we should maybe chain everything down so it looks like:
Also, I hate to be nit-picky, but please use the already-coined term 'DBTNG' and not 'TNGDB' so that issues searches for 'DBTNG' can find your patches. Thanks!
Other than those two small issues, patch applies cleanly and actions/trigger tests are at 100% pass with 476 passes. Should be RTBC after a quick revision.
Comment #2
hswong3i commentedComment #3
damien tournoud commentedThis was not caught by our tests? ==> we need to extend them
Comment #4
dave reidNo, as currently it does not fail. This patch depends on another patch.
Comment #5
hswong3i commentedI am wonder about how to catch this bug... Existing code is function but just potentially buggy in final SQL syntax, where MySQL and PostgreSQL still accept it.
Maybe we can add some checking within db_insert() and so warning that there is none of field defined for INSERT? Check it though runtime seems to be more logic. Patch for this is submit to #321100: Empty insert statements should fail gracefully.
Comment #6
dave reidAfter a little more investigating, the actions_aid is a table with one auto-increment field, that's it. What's buggy about not specifying the value for an auto-increment field? It does not need to have ->useDefaults(array('id')). Since there are no other fields so db_insert('actions_aid') should be valid. We don't use ->useDefaults(array('id')) in our database tests:
Comment #7
dave reidWhat would be a safe SQL way to insert a blank row for a table that has defaults for all fields?
INSERT INTO mytable VALUES ()? Maybe the db_insert should check if there are no fields specified, then use that syntax. I'll stop chiming in until I get a more authoritative answer.Comment #8
dave reidSo, summary so far: Steps to reproduce the problem:
- Go to admin/settings/actions
- Create a custom action like 'Redirect to URL' and save it
- Following warnings should show on the result page:
* warning: array_fill() [function.array-fill]: Number of elements must be positive in /home/davereid/Projects/drupal-head/includes/database/mysql/query.inc on line 66.
* warning: implode() [function.implode]: Bad arguments. in /home/davereid/Projects/drupal-head/includes/database/mysql/query.inc on line 67.
We have two alternatives to fix this:
1. Use
db_insert('actions_aid')->useDefaults(array('aid'))->execute()2. Fix the database insert query to work around an insert query with no specific or default fields defined, but on a table that has default values for all it's fields
3. Cause error if no fields are defined as proposed in #321100: Empty insert statements should fail gracefully
Doing solution #2 seems the most reasonable to me since this can help avoid the problem in the future with little to no change to the database API. We shouldn't have to specifically have to use ->useDefaults(...) on an auto-increment field. Ideally, I'd like to finish my work on integrating the aid back into the actions table and remove the one-field actions_aid table, but we should have a fix in case this comes up in the future.
Attached is a patch that does a quick count() check on the InsertQuery->defaultFields in InsertQuery_driver::__toString() exactly like we already do with InsertQuery->insertValues. It also includes a test (thanks hwong3i) for the
db_insert('mytable')->execute()statement in the Database Insert, default fields tests.Comment #9
drewish commentedlooks like #329223: Notices in ActionsConfigurationTestCase might be a duplicate of this.
Comment #10
hswong3i commentedYes, it is already get fixed in #329223: Notices in ActionsConfigurationTestCase. Mark this issue as duplicated.