summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2009-06-05 16:55:45 +0000
committerDries Buytaert <dries@buytaert.net>2009-06-05 16:55:45 +0000
commit9079d78481c6148b9aca36f90e8bf34ffb01f03d (patch)
tree6edee9c1a86773f3c0d6ea89d2170d375a8f1d18
parent41204a5a829d07a34305cf97a9a0bf3937b5ebb7 (diff)
downloadbrdo-9079d78481c6148b9aca36f90e8bf34ffb01f03d.tar.gz
brdo-9079d78481c6148b9aca36f90e8bf34ffb01f03d.tar.bz2
- Patch #481288 by Berdir: add support for INSERT INTO ... SELECT FROM ... queries.
-rw-r--r--includes/database/mysql/query.inc8
-rw-r--r--includes/database/pgsql/query.inc8
-rw-r--r--includes/database/query.inc20
-rw-r--r--includes/database/sqlite/query.inc9
-rw-r--r--modules/simpletest/tests/database_test.test15
5 files changed, 54 insertions, 6 deletions
diff --git a/includes/database/mysql/query.inc b/includes/database/mysql/query.inc
index b2dbae04c..84caf0386 100644
--- a/includes/database/mysql/query.inc
+++ b/includes/database/mysql/query.inc
@@ -22,12 +22,12 @@ class InsertQuery_mysql extends InsertQuery {
throw new PDOException('You may not specify the same field to have a value and a schema-default value.');
}
- if (count($this->insertFields) + count($this->defaultFields) == 0) {
+ if (count($this->insertFields) + count($this->defaultFields) == 0 && empty($this->fromQuery)) {
return NULL;
}
// Don't execute query without values.
- if (!isset($this->insertValues[0]) && count($this->insertFields) > 0) {
+ if (!isset($this->insertValues[0]) && count($this->insertFields) > 0 && empty($this->fromQuery)) {
return NULL;
}
@@ -56,6 +56,10 @@ class InsertQuery_mysql extends InsertQuery {
// Default fields are always placed first for consistency.
$insert_fields = array_merge($this->defaultFields, $this->insertFields);
+ if (!empty($this->fromQuery)) {
+ return "INSERT $delay INTO {" . $this->table . '} (' . implode(', ', $insert_fields) . ') ' . $this->fromQuery;
+ }
+
$query = "INSERT $delay INTO {" . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES ';
$max_placeholder = 0;
diff --git a/includes/database/pgsql/query.inc b/includes/database/pgsql/query.inc
index d17721221..489d57e65 100644
--- a/includes/database/pgsql/query.inc
+++ b/includes/database/pgsql/query.inc
@@ -22,12 +22,12 @@ class InsertQuery_pgsql extends InsertQuery {
throw new PDOException('You may not specify the same field to have a value and a schema-default value.');
}
- if (count($this->insertFields) + count($this->defaultFields) == 0) {
+ if (count($this->insertFields) + count($this->defaultFields) == 0 && empty($this->fromQuery)) {
return NULL;
}
// Don't execute query without values.
- if (!isset($this->insertValues[0]) && count($this->insertFields) > 0) {
+ if (!isset($this->insertValues[0]) && count($this->insertFields) > 0 && empty($this->fromQuery)) {
return NULL;
}
@@ -82,6 +82,10 @@ class InsertQuery_pgsql extends InsertQuery {
// Default fields are always placed first for consistency.
$insert_fields = array_merge($this->defaultFields, $this->insertFields);
+ if (!empty($this->fromQuery)) {
+ return "INSERT INTO {" . $this->table . '} (' . implode(', ', $insert_fields) . ') ' . $this->fromQuery;
+ }
+
$query = "INSERT INTO {" . $this->table . '} (' . implode(', ', $insert_fields) . ') VALUES ';
$max_placeholder = 0;
diff --git a/includes/database/query.inc b/includes/database/query.inc
index 8d614a0dd..ac14c4a2e 100644
--- a/includes/database/query.inc
+++ b/includes/database/query.inc
@@ -287,6 +287,12 @@ class InsertQuery extends Query {
*/
protected $insertValues = array();
+ /**
+ * A SelectQuery object to fetch the rows that should be inserted.
+ *
+ */
+ protected $fromQuery;
+
public function __construct($connection, $table, array $options = array()) {
if (!isset($options['return'])) {
$options['return'] = Database::RETURN_INSERT_ID;
@@ -410,6 +416,11 @@ class InsertQuery extends Query {
return $this;
}
+ public function from(SelectQueryInterface $query) {
+ $this->fromQuery = $query;
+ return $this;
+ }
+
/**
* Executes the insert query.
*
@@ -426,6 +437,11 @@ class InsertQuery extends Query {
$last_insert_id = 0;
+ // Check if a SelectQuery is passed in and use that.
+ if (!empty($this->fromQuery)) {
+ return $this->connection->query((string) $this, array(), $this->queryOptions);
+ }
+
// Confirm that the user did not try to specify an identical
// field and default field.
if (array_intersect($this->insertFields, $this->defaultFields)) {
@@ -463,6 +479,10 @@ class InsertQuery extends Query {
// Default fields are always placed first for consistency.
$insert_fields = array_merge($this->defaultFields, $this->insertFields);
+ if (!empty($this->fromQuery)) {
+ return "INSERT $delay INTO {" . $this->table . '} (' . implode(', ', $insert_fields) . ') ' . $this->fromQuery;
+ }
+
// For simplicity, we will use the $placeholders array to inject
// default keywords even though they are not, strictly speaking,
// placeholders for prepared statements.
diff --git a/includes/database/sqlite/query.inc b/includes/database/sqlite/query.inc
index 98fa80754..287fc9008 100644
--- a/includes/database/sqlite/query.inc
+++ b/includes/database/sqlite/query.inc
@@ -21,11 +21,11 @@
class InsertQuery_sqlite extends InsertQuery {
public function execute() {
- if (count($this->insertFields) + count($this->defaultFields) == 0) {
+ if (count($this->insertFields) + count($this->defaultFields) == 0 && empty($this->fromQuery)) {
return NULL;
}
// Don't execute query without values.
- if (!isset($this->insertValues[0]) && count($this->insertFields) > 0) {
+ if (!isset($this->insertValues[0]) && count($this->insertFields) > 0 && empty($this->fromQuery)) {
return NULL;
}
if (count($this->insertFields)) {
@@ -39,6 +39,11 @@ class InsertQuery_sqlite extends InsertQuery {
public function __toString() {
// Produce as many generic placeholders as necessary.
$placeholders = array_fill(0, count($this->insertFields), '?');
+
+ if (!empty($this->fromQuery)) {
+ return "INSERT INTO {" . $this->table . '} (' . implode(', ', $this->insertFields) . ') ' . $this->fromQuery;
+ }
+
return 'INSERT INTO {' . $this->table . '} (' . implode(', ', $this->insertFields) . ') VALUES (' . implode(', ', $placeholders) . ')';
}
diff --git a/modules/simpletest/tests/database_test.test b/modules/simpletest/tests/database_test.test
index 7084ccf7e..6256ff22c 100644
--- a/modules/simpletest/tests/database_test.test
+++ b/modules/simpletest/tests/database_test.test
@@ -513,6 +513,21 @@ class DatabaseInsertTestCase extends DatabaseTestCase {
$this->assertIdentical($id, '5', t('Auto-increment ID returned successfully.'));
}
+
+ /**
+ * Test that the INSERT INTO ... SELECT ... syntax works.
+ */
+ function testInsertSelect() {
+ $query = db_select('test_people', 'tp')->fields('tp', array('name', 'age', 'job'));
+
+ db_insert('test')
+ ->fields(array('name', 'age', 'job'))
+ ->from($query)
+ ->execute();
+
+ $saved_age = db_query('SELECT age FROM {test} WHERE name = :name', array(':name' => 'Meredith'))->fetchField();
+ $this->assertIdentical($saved_age, '30', t('Can retrieve after inserting.'));
+ }
}
/**