protected function excludeMany(DataQuery $query)
 {
     $this->model = $query->applyRelation($this->relation);
     $values = $this->getValue();
     $comparisonClause = DB::get_conn()->comparisonClause($this->getDbName(), null, false, true, $this->getCaseSensitive(), true);
     $parameters = array();
     foreach ($values as $value) {
         $parameters[] = $this->getMatchPattern($value);
     }
     // Since query connective is ambiguous, use AND explicitly here
     $count = count($values);
     $predicate = implode(' AND ', array_fill(0, $count, $comparisonClause));
     return $query->where(array($predicate => $parameters));
 }
 protected function excludeOne(DataQuery $query)
 {
     $this->model = $query->applyRelation($this->relation);
     $predicate = sprintf("NOT MATCH (%s) AGAINST (?)", $this->getDbName());
     return $query->where(array($predicate => $this->getValue()));
 }
 /**
  * Applies matches for several values, either as inclusive or exclusive
  *
  * @param DataQuery $query
  * @param bool $inclusive True if this is inclusive, or false if exclusive
  * @return DataQuery
  */
 protected function manyFilter(DataQuery $query, $inclusive)
 {
     $this->model = $query->applyRelation($this->relation);
     $caseSensitive = $this->getCaseSensitive();
     // Check values for null
     $field = $this->getDbName();
     $values = $this->getValue();
     if (empty($values)) {
         throw new \InvalidArgumentException("Cannot filter {$field} against an empty set");
     }
     $hasNull = in_array(null, $values, true);
     if ($hasNull) {
         $values = array_filter($values, function ($value) {
             return $value !== null;
         });
     }
     $connective = '';
     if (empty($values)) {
         $predicate = '';
     } elseif ($caseSensitive === null) {
         // For queries using the default collation (no explicit case) we can use the WHERE .. NOT IN .. syntax,
         // providing simpler SQL than many WHERE .. AND .. fragments.
         $column = $this->getDbName();
         $placeholders = DB::placeholders($values);
         if ($inclusive) {
             $predicate = "{$column} IN ({$placeholders})";
         } else {
             $predicate = "{$column} NOT IN ({$placeholders})";
         }
     } else {
         // Generate reusable comparison clause
         $comparisonClause = DB::get_conn()->comparisonClause($this->getDbName(), null, true, !$inclusive, $this->getCaseSensitive(), true);
         $count = count($values);
         if ($count > 1) {
             $connective = $inclusive ? ' OR ' : ' AND ';
             $conditions = array_fill(0, $count, $comparisonClause);
             $predicate = implode($connective, $conditions);
         } else {
             $predicate = $comparisonClause;
         }
     }
     // Always check for null when doing exclusive checks (either AND IS NOT NULL / OR IS NULL)
     // or when including the null value explicitly (OR IS NULL)
     if ($hasNull || !$inclusive) {
         // If excluding values which don't include null, or including
         // values which include null, we should do an `OR IS NULL`.
         // Otherwise we are excluding values that do include null, so `AND IS NOT NULL`.
         // Simplified from (!$inclusive && !$hasNull) || ($inclusive && $hasNull);
         $isNull = !$hasNull || $inclusive;
         $nullCondition = DB::get_conn()->nullCheckClause($field, $isNull);
         // Determine merge strategy
         if (empty($predicate)) {
             $predicate = $nullCondition;
         } else {
             // Merge null condition with predicate
             if ($isNull) {
                 $nullCondition = " OR {$nullCondition}";
             } else {
                 $nullCondition = " AND {$nullCondition}";
             }
             // If current predicate connective doesn't match the same as the null connective
             // make sure to group the prior condition
             if ($connective && ($connective === ' OR ') !== $isNull) {
                 $predicate = "({$predicate})";
             }
             $predicate .= $nullCondition;
         }
     }
     return $query->where(array($predicate => $values));
 }
 protected function excludeOne(DataQuery $query)
 {
     $this->model = $query->applyRelation($this->relation);
     $predicate = sprintf('%1$s < ? OR %1$s > ?', $this->getDbName());
     return $query->where(array($predicate => array($this->min, $this->max)));
 }
 /**
  * Applies a exclusion(inverse) filter to the query
  * Handles SQL escaping for both numeric and string values
  *
  * @param DataQuery $query
  * @return $this|DataQuery
  */
 protected function excludeOne(DataQuery $query)
 {
     $this->model = $query->applyRelation($this->relation);
     $predicate = sprintf("%s %s ?", $this->getDbName(), $this->getInverseOperator());
     return $query->where(array($predicate => $this->getDbFormattedValue()));
 }
 public function testRelationReturn()
 {
     $dq = new DataQuery('DataQueryTest_C');
     $this->assertEquals('DataQueryTest_A', $dq->applyRelation('TestA'), 'DataQuery::applyRelation should return the name of the related object.');
     $this->assertEquals('DataQueryTest_A', $dq->applyRelation('TestAs'), 'DataQuery::applyRelation should return the name of the related object.');
     $this->assertEquals('DataQueryTest_A', $dq->applyRelation('ManyTestAs'), 'DataQuery::applyRelation should return the name of the related object.');
     $this->assertEquals('DataQueryTest_B', $dq->applyRelation('TestB'), 'DataQuery::applyRelation should return the name of the related object.');
     $this->assertEquals('DataQueryTest_B', $dq->applyRelation('TestBs'), 'DataQuery::applyRelation should return the name of the related object.');
     $this->assertEquals('DataQueryTest_B', $dq->applyRelation('ManyTestBs'), 'DataQuery::applyRelation should return the name of the related object.');
     $newDQ = new DataQuery('DataQueryTest_E');
     $this->assertEquals('DataQueryTest_A', $newDQ->applyRelation('TestA'), 'DataQuery::applyRelation should return the name of the related object.');
 }