CRM_Utils_SQL_Select - Fix dedupe behavior for `select`, `groupBy`, `having`, `orderBy`.
authorCiviCRM <info@civicrm.org>
Wed, 6 Jan 2016 22:13:30 +0000 (14:13 -0800)
committerCiviCRM <info@civicrm.org>
Wed, 6 Jan 2016 22:51:08 +0000 (14:51 -0800)
The selected columns should not be deduped at all -- when using `insertInto()`, the selected
columns need to line up with the insertion columns, and it's perfectly reasonably to re-use
the same value in multipl columns.

For th others, it's semantically OK to dedupe, but we should dedupe based on
the evaluated query expression rather than the general formula.

CRM/Utils/SQL/Select.php
tests/phpunit/CRM/Utils/SQL/SelectTest.php

index f7e1777e646cc606a80ae7026d07cff79d32f290..a45bfa57291628aa127b1fe6b269577880353436 100644 (file)
@@ -223,7 +223,7 @@ class CRM_Utils_SQL_Select implements ArrayAccess {
   public function select($exprs, $args = NULL) {
     $exprs = (array) $exprs;
     foreach ($exprs as $expr) {
-      $this->selects[$expr] = $this->interpolate($expr, $args);
+      $this->selects[] = $this->interpolate($expr, $args);
     }
     return $this;
   }
@@ -254,7 +254,8 @@ class CRM_Utils_SQL_Select implements ArrayAccess {
   public function groupBy($exprs, $args = NULL) {
     $exprs = (array) $exprs;
     foreach ($exprs as $expr) {
-      $this->groupBys[$expr] = $this->interpolate($expr, $args);
+      $evaluatedExpr = $this->interpolate($expr, $args);
+      $this->groupBys[$evaluatedExpr] = $evaluatedExpr;
     }
     return $this;
   }
@@ -269,7 +270,8 @@ class CRM_Utils_SQL_Select implements ArrayAccess {
   public function having($exprs, $args = NULL) {
     $exprs = (array) $exprs;
     foreach ($exprs as $expr) {
-      $this->havings[$expr] = $this->interpolate($expr, $args);
+      $evaluatedExpr = $this->interpolate($expr, $args);
+      $this->havings[$evaluatedExpr] = $evaluatedExpr;
     }
     return $this;
   }
@@ -284,7 +286,8 @@ class CRM_Utils_SQL_Select implements ArrayAccess {
   public function orderBy($exprs, $args = NULL) {
     $exprs = (array) $exprs;
     foreach ($exprs as $expr) {
-      $this->orderBys[$expr] = $this->interpolate($expr, $args);
+      $evaluatedExpr = $this->interpolate($expr, $args);
+      $this->orderBys[$evaluatedExpr] = $evaluatedExpr;
     }
     return $this;
   }
index d241508e68e9db34bc1a9121e723b065fd4c753f..ecdc6abf9f98817b0736a9db1e9f4c0bd0ebd97e 100644 (file)
@@ -259,6 +259,22 @@ class CRM_Utils_SQL_SelectTest extends CiviUnitTestCase {
     $this->assertEquals('world', $select['hello']);
   }
 
+  public function testInsertInto_WithDupes() {
+    $select = CRM_Utils_SQL_Select::from('foo')
+      ->insertInto('bar', array('first', 'second', 'third', 'fourth'))
+      ->select('fid')
+      ->select('1')
+      ->select('fid')
+      ->select('1')
+      ->where('!field = #value', array('field' => 'zoo', 'value' => 3))
+      ->where('!field = #value', array('field' => 'aviary', 'value' => 3))
+      ->where('!field = #value', array('field' => 'zoo', 'value' => 3))
+      ->groupBy('!colName', array('colName' => 'noodle'))
+      ->groupBy('!colName', array('colName' => 'sauce'))
+      ->groupBy('!colName', array('colName' => 'noodle'));
+    $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());
+  }
+
   /**
    * @param $expected
    * @param $actual