summaryrefslogtreecommitdiff
path: root/includes/database/mysql
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2010-06-26 01:40:05 +0000
committerDries Buytaert <dries@buytaert.net>2010-06-26 01:40:05 +0000
commit5ca8621ba40016315be9a081814b31586920ff30 (patch)
treec595fb557b61fa920b308aa6e0bc8b8e4dbd3bfb /includes/database/mysql
parent60883871aab067f13bd3411bfd2874b50cfe7978 (diff)
downloadbrdo-5ca8621ba40016315be9a081814b31586920ff30.tar.gz
brdo-5ca8621ba40016315be9a081814b31586920ff30.tar.bz2
- Patch #715108 by Damien Tournoud, Berdir, Josh Waihi, Crell, chx, justinrandell: Make merge queries more consistent and robust.
Diffstat (limited to 'includes/database/mysql')
-rw-r--r--includes/database/mysql/query.inc120
1 files changed, 9 insertions, 111 deletions
diff --git a/includes/database/mysql/query.inc b/includes/database/mysql/query.inc
index 63c0fe8e7..584a4a473 100644
--- a/includes/database/mysql/query.inc
+++ b/includes/database/mysql/query.inc
@@ -87,121 +87,19 @@ class InsertQuery_mysql extends InsertQuery {
}
}
-class MergeQuery_mysql extends MergeQuery {
-
- public function execute() {
-
- // A merge query without any key field is invalid.
- if (count($this->keyFields) == 0) {
- throw new InvalidMergeQueryException("You need to specify key fields before executing a merge query");
- }
-
- // Set defaults.
- if ($this->updateFields) {
- $update_fields = $this->updateFields;
- }
- else {
- // When update fields are derived from insert fields, we don't need
- // placeholders since we can tell MySQL to reuse insert supplied
- // values using the VALUES(col_name) function.
- $update_fields = array();
- }
-
- $insert_fields = $this->insertFields + $this->keyFields;
-
- $max_placeholder = 0;
- $values = array();
- // We assume that the order here is the same as in __toString(). If that's
- // not the case, then we have serious problems.
- foreach ($insert_fields as $value) {
- $values[':db_insert_placeholder_' . $max_placeholder++] = $value;
- }
-
- // Expressions take priority over literal fields, so we process those first
- // and remove any literal fields that conflict.
- foreach ($this->expressionFields as $field => $data) {
- if (!empty($data['arguments'])) {
- $values += $data['arguments'];
- }
- unset($update_fields[$field]);
- }
-
- // Because we filter $fields the same way here and in __toString(), the
- // placeholders will all match up properly.
- $max_placeholder = 0;
- foreach ($update_fields as $field => $value) {
- $values[':db_update_placeholder_' . ($max_placeholder++)] = $value;
- }
-
-
- // MySQL's INSERT ... ON DUPLICATE KEY UPDATE queries return 1
- // (MergeQuery::STATUS_INSERT) for an INSERT operation or 2
- // (MergeQuery::STATUS_UPDATE) for an UPDATE operation.
- //
- // @link http ://dev.mysql.com/doc/refman/5.0/en/mysql-affected-rows.html
- $this->queryOptions['return'] = Database::RETURN_AFFECTED;
- return $this->connection->query((string) $this, $values, $this->queryOptions);
- }
-
-
+class TruncateQuery_mysql extends TruncateQuery {
public function __toString() {
- // Create a comments string to prepend to the query.
- $comments = (!empty($this->comments)) ? '/* ' . implode('; ', $this->comments) . ' */ ' : '';
-
- // Set defaults.
- if ($this->updateFields) {
- $update_fields = $this->updateFields;
+ // TRUNCATE is actually a DDL statement on MySQL, and DDL statements are
+ // not transactional, and result in an implicit COMMIT. When we are in a
+ // transaction, fallback to the slower, but transactional, DELETE.
+ if ($this->connection->inTransaction()) {
+ // Create a comments string to prepend to the query.
+ $comments = (!empty($this->comments)) ? '/* ' . implode('; ', $this->comments) . ' */ ' : '';
+ return $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '}';
}
else {
- $update_fields = $this->insertFields;
- // If there are no exclude fields, this is a no-op.
- foreach ($this->excludeFields as $exclude_field) {
- unset($update_fields[$exclude_field]);
- }
- }
-
- // If the merge query has no fields to update, add the first key as an
- // update field so the query will not fail if a duplicate key is found.
- if (!$update_fields && !$this->expressionFields) {
- $update_fields = array_slice($this->keyFields, 0, 1, TRUE);
- }
-
- $insert_fields = $this->insertFields + $this->keyFields;
-
- $query = $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', array_keys($insert_fields)) . ') VALUES ';
-
- $max_placeholder = 0;
- $values = array();
- // We don't need the $field, but this is a convenient way to count.
- foreach ($insert_fields as $field) {
- $values[] = ':db_insert_placeholder_' . $max_placeholder++;
+ return parent::__toString();
}
-
- $query .= '(' . implode(', ', $values) . ') ON DUPLICATE KEY UPDATE ';
-
- // Expressions take priority over literal fields, so we process those first
- // and remove any literal fields that conflict.
- $max_placeholder = 0;
- $update = array();
- foreach ($this->expressionFields as $field => $data) {
- $update[] = $field . '=' . $data['expression'];
- unset($update_fields[$field]);
- }
-
- // Build update fields clauses based on caller supplied list, or derived
- // from insert supplied values using the VALUES(col_name) function.
- foreach ($update_fields as $field => $value) {
- if ($this->updateFields) {
- $update[] = ($field . '=:db_update_placeholder_' . $max_placeholder++);
- }
- else {
- $update[] = ($field . '=VALUES(' . $field . ')');
- }
- }
-
- $query .= implode(', ', $update);
-
- return $query;
}
}