Our support for "INSERT ... SELECT" queries only works with "SELECT (an explicit list of fields)".
Queries like "INSERT INTO new SELECT * FROM old WHERE..." cannot be written, although they are supported, in that exact syntax, in MySQL, pgSQL & SQLite.
All our current uses of db_insert($table)->from($select)->execute();
in current core are done with a $select query that has an explicit list of fields - i.e. built with $select->fields('table', array('some', 'specific', 'fields'))
, not $select->fields('table')
. The latter fails with the exception below.
From /core/lib/Drupal/Core/Database/Query/Insert.php:
// Don't execute query without fields.
if (count($this->insertFields) + count($this->defaultFields) == 0) {
throw new NoFieldsException('There are no fields available to insert with.');
}
From /core/lib/Drupal/Core/Database/Query/Insert.php,
and present exactly as is in /core/lib/Drupal/Core/Database/Driver/*/Insert.php:
if (!empty($this->fromQuery)) {
return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $insert_fields) . ') ' . $this->fromQuery;
}
Reading through #481288: Add support for INSERT INTO ... SELECT FROM ..., though, I can't really convince myself that it's a deliberate restriction rather than simply an omission.
Supporting "copy rows as is, whatever the columns are", is needed for the upgrade path in #1497374: Switch from Field-based storage to Entity-based storage.
Comment | File | Size | Author |
---|---|---|---|
#15 | drupal-2056363.patch | 6.32 KB | Sweetchuck |
#9 | insert-select-all-2056363-9.patch | 7.52 KB | yched |
#8 | insert-select-all-2056363-8.patch | 35.41 KB | yched |
#8 | interdiff.txt | 1.68 KB | yched |
#4 | insert-select-all-2056363-4.patch | 6.99 KB | yched |
Comments
Comment #1
yched CreditAttribution: yched commentedTemptative patch.
Comment #1.0
yched CreditAttribution: yched commentedrephrase
Comment #2
chx CreditAttribution: chx commentedMinimal formatting fixes, assigning to Crell for review.
Comment #2.0
chx CreditAttribution: chx commentedrephrasse
Comment #2.1
yched CreditAttribution: yched commentedclarification
Comment #3
yched CreditAttribution: yched commentedBumping to 'critical', since it blocks #1497374: Switch from Field-based storage to Entity-based storage
Comment #4
yched CreditAttribution: yched commentedMinor - fix double spacing in the generated query if there is a list of fields.
Comment #5
Crell CreditAttribution: Crell commentedHow does this block #1497374: Switch from Field-based storage to Entity-based storage? I haven't looked at that patch. Readers' Digest version, please. :-)
Comment #6
yched CreditAttribution: yched commented@Crell:
The upgrade path for #1497374: Switch from Field-based storage to Entity-based storage needs to reshuffle field table storage, and move data rows from old to new tables.
But it doesn't know the column names in those tables, because those vary with the field type, and the info lies in a method in the various "field type" plugins, and plugins are out of reach during updates (#2055605: Disallow use of plugins during update).
We don't really need that info anyway, all we need is "take whatever's in here, put it over there" - aka "INSERT INTO new SELECT * FROM old WHERE ..."
Comment #7
Crell CreditAttribution: Crell commentedHm, I see. Fair enough. One comment on the code.
This belongs in a separate test method from the previous test. It's testing a different thing (explicit vs. implicit field specification).
Comment #8
yched CreditAttribution: yched commentedWorks for me.
Comment #9
yched CreditAttribution: yched commentedWhoops. Did not merge HEAD before diffing.
Correct patch attached, interdiff is the same.
Comment #10
Crell CreditAttribution: Crell commentedBot can object if it wants.
Comment #11
chx CreditAttribution: chx commented#6 is not correct, the situation is MUCH worse: the information about field tables are only available in Drupal 7 -- or by introspection. For example, file fields now use target_id and they used fid before. Someone might have added custom indexes to their field tables. And so on.
Comment #12
yched CreditAttribution: yched commentedWell, #6 is correct, but right, on top of that, asking for the field schema through the API would return an info that is not yet in sync with the state of the db at the time this specific update runs.
So field schema is doubly unusable here, and we do need to just SELECT *
Comment #13
Dries CreditAttribution: Dries commentedCommitted to 8.x. Thanks all. I'm excited about the Entity-based storage.
Comment #14
chx CreditAttribution: chx commentedComment #15
SweetchuckBackport to D7
Comment #16
chx CreditAttribution: chx commentedYeah this is the same as D8, thanks!
Comment #16.0
chx CreditAttribution: chx commentedbla bla
Comment #17
David_Rothstein CreditAttribution: David_Rothstein commentedCommitted to 7.x - thanks! http://drupalcode.org/project/drupal.git/commit/cbabb1a