/** * Test deprecation of SQLQuery::getWhere working appropriately */ public function testDeprecatedGetWhere() { // Temporarily disable deprecation Deprecation::notification_version(null); $query = new SQLQuery(); $query->setSelect(array('"SQLQueryTest_DO"."Name"')); $query->setFrom('"SQLQueryTest_DO"'); $query->addWhere(array('"SQLQueryTest_DO"."Date" > ?' => '2012-08-08 12:00')); $query->addWhere('"SQLQueryTest_DO"."Name" = \'Richard\''); $query->addWhere(array('"SQLQueryTest_DO"."Meta" IN (?, \'Who?\', ?)' => array('Left', 'Right'))); $expectedSQL = <<<EOS SELECT "SQLQueryTest_DO"."Name" FROM "SQLQueryTest_DO" WHERE ("SQLQueryTest_DO"."Date" > ?) AND ("SQLQueryTest_DO"."Name" = 'Richard') AND ("SQLQueryTest_DO"."Meta" IN (?, 'Who?', ?)) EOS; $expectedParameters = array('2012-08-08 12:00', 'Left', 'Right'); // Check sql evaluation of this query maintains the parameters $sql = $query->sql($parameters); $this->assertSQLEquals($expectedSQL, $sql); $this->assertEquals($expectedParameters, $parameters); // Check that ->toAppropriateExpression()->setWhere doesn't modify the query $query->setWhere($query->toAppropriateExpression()->getWhere()); $sql = $query->sql($parameters); $this->assertSQLEquals($expectedSQL, $sql); $this->assertEquals($expectedParameters, $parameters); // Check that getWhere are all flattened queries $expectedFlattened = array('"SQLQueryTest_DO"."Date" > \'2012-08-08 12:00\'', '"SQLQueryTest_DO"."Name" = \'Richard\'', '"SQLQueryTest_DO"."Meta" IN (\'Left\', \'Who?\', \'Right\')'); $this->assertEquals($expectedFlattened, $query->getWhere()); }
public function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) { // Get locale and translation zone to use $default = Fluent::default_locale(); $locale = $dataQuery->getQueryParam('Fluent.Locale') ?: Fluent::current_locale(); // Get all tables to translate fields for, and their respective field names $includedTables = $this->getTranslatedTables(); // Iterate through each select clause, replacing each with the translated version foreach ($query->getSelect() as $alias => $select) { // Skip fields without table context if (!preg_match('/^"(?<class>\\w+)"\\."(?<field>\\w+)"$/i', $select, $matches)) { continue; } $class = $matches['class']; $field = $matches['field']; // If this table doesn't have translated fields then skip if (empty($includedTables[$class])) { continue; } // If this field shouldn't be translated, skip if (!in_array($field, $includedTables[$class])) { continue; } // Select visible field from translated fields (Title_fr_FR || Title => Title) $translatedField = Fluent::db_field_for_locale($field, $locale); $expression = $this->localiseSelect($class, $translatedField, $field); $query->selectField($expression, $alias); // At the same time, rewrite the selector for the default field to make sure that // (in the case it is blank, which happens if installing fluent for the first time) // that it also populated from the root field. $defaultField = Fluent::db_field_for_locale($field, $default); $defaultExpression = $this->localiseSelect($class, $defaultField, $field); $query->selectField($defaultExpression, $defaultField); } // Rewrite where conditions with parameterised query (3.2 +) $where = $query->toAppropriateExpression()->getWhere(); foreach ($where as $index => $condition) { // Extract parameters from condition if ($condition instanceof SQLConditionGroup) { $parameters = array(); $predicate = $condition->conditionSQL($parameters); } else { $parameters = array_values(reset($condition)); $predicate = key($condition); } // determine the table/column this condition is against $filterColumn = $this->detectFilterColumn($predicate, $includedTables, $locale); if (empty($filterColumn)) { continue; } // Duplicate the condition with all localisable fields replaced $localisedPredicate = $this->localiseFilterCondition($predicate, $includedTables, $locale); if ($localisedPredicate === $predicate) { continue; } // Generate new condition that conditionally executes one of the two conditions // depending on field nullability. // If the filterColumn is null or empty, then it's considered untranslated, and // thus the query should continue running on the default column unimpeded. $castColumn = "COALESCE(CAST({$filterColumn} AS CHAR), '')"; $newPredicate = "\n\t\t\t\t({$castColumn} != '' AND {$castColumn} != '0' AND ({$localisedPredicate}))\n\t\t\t\tOR (\n\t\t\t\t\t({$castColumn} = '' OR {$castColumn} = '0') AND ({$predicate})\n\t\t\t\t)"; // Duplicate this condition with parameters duplicated $where[$index] = array($newPredicate => array_merge($parameters, $parameters)); } $query->setWhere($where); // Augment search if applicable if ($adapter = Fluent::search_adapter()) { $adapter->augmentSearch($query, $dataQuery); } }
public function conditionSQL(&$parameters) { $parameters = array(); // Ignore empty conditions $query = $this->whereQuery->toAppropriateExpression(); $where = $query->getWhere(); if (empty($where)) { return null; } // Allow database to manage joining of conditions $sql = DB::get_conn()->getQueryBuilder()->buildWhereFragment($query, $parameters); return preg_replace('/^\\s*WHERE\\s*/i', '', $sql); }