1) Trying to write the DB API equivalent of: DELETE FROM {node_revisions} WHERE nid IN (SELECT nid FROM {node} WHERE type = 'my_type')

Tried the following:

  // Create subselect for use in condition.
  $query = db_select('node', 'n')
    ->fields('n', array('nid'))
    ->condition('type', 'my_type');

  // Delete any existing records.
  db_delete('node_revision')
    ->condition('nid', $query, 'IN')
    ->execute();

The error returns with delete query equal to: DELETE FROM {node_revision} WHERE (nid IN ()) - Array ( [:db_condition_placeholder_16] => my_type )

2) Per the comments in 'subselects' section of Conditional clauses, a join would be preferable to a subselect in the where clause. However the API does not currently support such a statement. See issue #369253: Add alias parameter to other db_ functions.

3) Also, I did not notice a subselect in the unit tests. If this is confirmed as a bug, then an issue about adding subselect tests can be added.

4) If this is a bug for delete, it may also exist for the other statement types: select, insert, update, merge.

CommentFileSizeAuthor
#4 condition_select.patch2.52 KBberdir

Comments

dave reid’s picture

You're misusing the condition function. In your example code, it would work if $query was an array, but you are passing an database query object. Also you're using db_select() for a very simple query, so the use of db_query() is preferred. This is the proper way to do it:

$nids = db_query("SELECT nid FROM {node} WHERE type = :type", array(':type' => 'my_type'))->fetchCol();
db_delete('node_revision')
  ->condition('nid', $nids, 'IN')
  ->execute();
solotandem’s picture

1) The db_select code was tried per the comments in the documentation at Conditional clauses which indicates placing the db_select object in the $variables position. To quote:

condition() also supports subselects as the $value. To use a subselect, first construct a SelectQuery object created by db_select(). Then, instead of executing the Select query pass it into the value parameter of the condition() method of another query. It will automatically get integrated into the main query when it is executed.

2) If $nids has lots of values, then I would think it preferable to have the database excecute the subselect as part of the delete query instead of sorting through 500 ids inside the IN clause. Hence the reason for trying a subselect.

dave reid’s picture

My mistake. Interesting...

berdir’s picture

Title: Subselects do not work with delete query » Subselects don't work in DB conditions...
Status: Active » Needs review
StatusFileSize
new2.52 KB

Another nice bug... :)

The subquery is added to $parameters and after that, it's overwritten because the variable is initalized to to an empty array().

The fix is easy, I also added a simple test case for that..

Status: Needs review » Needs work

The last submitted patch failed testing.

berdir’s picture

Status: Needs work » Needs review

Testbot, I don't believe you :)

Crell’s picture

Status: Needs review » Reviewed & tested by the community

Dead simple patch, and it passes my tests on my system. So there, bot.

webchick’s picture

This looks good to go, but need testing bot to confirm. :(

dries’s picture

Status: Reviewed & tested by the community » Fixed

I ran the tests locally, and everything passes. Committed to CVS HEAD. Thanks.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.