private $insertInto = NULL;
private $insertVerb = 'INSERT INTO ';
private $insertIntoFields = [];
+ private $onDuplicates = [];
private $selects = [];
private $from;
private $joins = [];
return $this;
}
+ /**
+ * For INSERT INTO...SELECT...' queries, you may give an "ON DUPLICATE UPDATE" clause.
+ *
+ * @param string|array $exprs list of SQL expressions
+ * @param null|array $args use NULL to disable interpolation; use an array of variables to enable
+ * @return CRM_Utils_SQL_Select
+ */
+ public function onDuplicate($exprs, $args = NULL) {
+ $exprs = (array) $exprs;
+ foreach ($exprs as $expr) {
+ $evaluatedExpr = $this->interpolate($expr, $args);
+ $this->onDuplicates[$evaluatedExpr] = $evaluatedExpr;
+ }
+ return $this;
+ }
+
/**
* @param array|NULL $parts
* List of fields to check (e.g. 'selects', 'joins').
$sql .= 'OFFSET ' . $this->offset . "\n";
}
}
+ if ($this->onDuplicates) {
+ if ($this->insertVerb === 'INSERT INTO ') {
+ $sql .= ' ON DUPLICATE KEY UPDATE ' . implode(", ", $this->onDuplicates) . "\n";
+ }
+ else {
+ throw new \Exception("The ON DUPLICATE clause and only be used with INSERT INTO queries.");
+ }
+ }
+
if ($this->mode === self::INTERPOLATE_OUTPUT) {
$sql = $this->interpolate($sql, $this->params, self::INTERPOLATE_OUTPUT);
}
$this->assertLike('INSERT INTO bar (first, second, third, fourth) SELECT fid, 1, fid, 1 FROM foo WHERE (zoo = 3) AND (aviary = 3) GROUP BY noodle, sauce', $select->toSQL());
}
+ public function testInsertInto_OnDuplicateUpdate() {
+ $select = CRM_Utils_SQL_Select::from('foo')
+ ->insertInto('bar', ['first', 'second', 'third'])
+ ->select(['foo.one', 'foo.two', 'foo.three'])
+ ->onDuplicate('second = twiddle(foo.two)')
+ ->onDuplicate('third = twiddle(foo.three)');
+ $this->assertLike('INSERT INTO bar (first, second, third) SELECT foo.one, foo.two, foo.three FROM foo ON DUPLICATE KEY UPDATE second = twiddle(foo.two), third = twiddle(foo.three)', $select->toSQL());
+ }
+
/**
* @param $expected
* @param $actual