/** * Test that empty expressions don't emit invalid SQL. * * @return void */ public function testSqlWhenEmpty() { $expr = new QueryExpression(); $binder = new ValueBinder(); $result = $expr->sql($binder); $this->assertEquals('', $result); }
/** * Tests that the expression is correctly traversed * * @return void */ public function testTraverse() { $count = 0; $visitor = function () use(&$count) { $count++; }; $expr = new QueryExpression(); $expr->eq('test', 'true'); $expr2 = new QueryExpression(); $expr2->eq('test', 'false'); $caseExpression = new CaseExpression([$expr, $expr2]); $caseExpression->traverse($visitor); $this->assertSame(4, $count); }
/** * Tests that applying array options to a query will convert them * to equivalent function calls with the correspondent array values * * @return void */ public function testApplyOptions() { $options = ['fields' => ['field_a', 'field_b'], 'conditions' => ['field_a' => 1, 'field_b' => 'something'], 'limit' => 1, 'order' => ['a' => 'ASC'], 'offset' => 5, 'group' => ['field_a'], 'having' => ['field_a >' => 100], 'contain' => ['table_a' => ['table_b']], 'join' => ['table_a' => ['conditions' => ['a > b']]]]; $query = new Query($this->connection, $this->table); $query->applyOptions($options); $this->assertEquals(['field_a', 'field_b'], $query->clause('select')); $expected = new QueryExpression($options['conditions'], $this->fooTypeMap); $result = $query->clause('where'); $this->assertEquals($expected, $result); $this->assertEquals(1, $query->clause('limit')); $expected = new QueryExpression(['a > b']); $expected->typeMap($this->fooTypeMap); $result = $query->clause('join'); $this->assertEquals(['table_a' => ['alias' => 'table_a', 'type' => 'INNER', 'conditions' => $expected]], $result); $expected = new OrderByExpression(['a' => 'ASC']); $this->assertEquals($expected, $query->clause('order')); $this->assertEquals(5, $query->clause('offset')); $this->assertEquals(['field_a'], $query->clause('group')); $expected = new QueryExpression($options['having']); $expected->typeMap($this->fooTypeMap); $this->assertEquals($expected, $query->clause('having')); $expected = ['table_a' => ['table_b' => []]]; $this->assertEquals($expected, $query->contain()); }
/** * Constructor. Takes a name for the function to be invoked and a list of params * to be passed into the function. Optionally you can pass a list of types to * be used for each bound param. * * By default, all params that are passed will be quoted. If you wish to use * literal arguments, you need to explicitly hint this function. * * ### Examples: * * `$f = new FunctionExpression('CONCAT', ['CakePHP', ' rules']);` * * Previous line will generate `CONCAT('CakePHP', ' rules')` * * `$f = new FunctionExpression('CONCAT', ['name' => 'literal', ' rules']);` * * Will produce `CONCAT(name, ' rules')` * * @param string $name the name of the function to be constructed * @param array $params list of arguments to be passed to the function * If associative the key would be used as argument when value is 'literal' * @param array $types associative array of types to be associated with the * passed arguments * @param string $returnType The return type of this expression */ public function __construct($name, $params = [], $types = [], $returnType = 'string') { $this->_name = $name; $this->_returnType = $returnType; parent::__construct($params, $types, ','); }
/** * Returns a new QueryExpression object. This is a handy function when * building complex queries using a fluent interface. You can also override * this function in subclasses to use a more specialized QueryExpression class * if required. * * You can optionally pass a single raw SQL string or an array or expressions in * any format accepted by \Cake\Database\Expression\QueryExpression: * * ``` * $expression = $query->newExpr(); // Returns an empty expression object * $expression = $query->newExpr('Table.column = Table2.column'); // Return a raw SQL expression * ``` * * @param mixed $rawExpression A string, array or anything you want wrapped in an expression object * @return \Cake\Database\Expression\QueryExpression */ public function newExpr($rawExpression = null) { $expression = new QueryExpression([], $this->typeMap()); if ($rawExpression !== null) { $expression->add($rawExpression); } return $expression; }
/** * Constructor. Takes a name for the function to be invoked and a list of params * to be passed into the function. Optionally you can pass a list of types to * be used for each bound param. * * By default, all params that are passed will be quoted. If you wish to use * literal arguments, you need to explicitly hint this function. * * ### Examples: * * ``$f = new FunctionExpression('CONCAT', ['CakePHP', ' rules']);`` * * Previous line will generate ``CONCAT('CakePHP', ' rules')`` * * ``$f = new FunctionExpression('CONCAT', ['name' => 'literal', ' rules']);`` * * Will produce ``CONCAT(name, ' rules')`` * * @param string $name the name of the function to be constructed * @param array $params list of arguments to be passed to the function * If associative the key would be used as argument when value is 'literal' * @param array $types associative array of types to be associated with the * passed arguments */ public function __construct($name, $params = [], $types = []) { $this->_name = $name; parent::__construct($params, $types, ','); }
/** * Constructor * * @param array $conditions The sort columns * @param array $types The types for each column. * @param string $conjunction The glue used to join conditions together. */ public function __construct($conditions = [], $types = [], $conjunction = '') { parent::__construct($conditions, $types, $conjunction); }
/** * Test magic findAllByXX method. * * @return void */ public function testMagicFindAllOr() { $table = TableRegistry::get('Users'); $result = $table->findAllByAuthorIdOrPublished(1, 'Y'); $this->assertInstanceOf('Cake\\ORM\\Query', $result); $this->assertNull($result->clause('limit')); $expected = new QueryExpression(); $expected->typeMap()->defaults($this->usersTypeMap->toArray()); $expected->add(['or' => ['Users.author_id' => 1, 'Users.published' => 'Y']]); $this->assertEquals($expected, $result->clause('where')); $this->assertNull($result->clause('order')); }
/** * Test magic findAllByXX method. * * @return void */ public function testMagicFindAllOr() { $table = TableRegistry::get('Users'); $result = $table->findAllByAuthorIdOrPublished(1, 'Y'); $this->assertInstanceOf('Cake\\ORM\\Query', $result); $this->assertNull($result->clause('limit')); $expected = new QueryExpression(); $expected->typeMap()->defaults(['Users.id' => 'integer', 'id' => 'integer', 'Users.username' => 'string', 'username' => 'string', 'Users.password' => 'string', 'password' => 'string', 'Users.created' => 'timestamp', 'created' => 'timestamp', 'Users.updated' => 'timestamp', 'updated' => 'timestamp']); $expected->add(['or' => ['Users.author_id' => 1, 'Users.published' => 'Y']]); $this->assertEquals($expected, $result->clause('where')); $this->assertNull($result->clause('order')); }
/** * Tests the hasNestedExpression() function * * @return void */ public function testHasNestedExpression() { $expr = new QueryExpression(); $this->assertFalse($expr->hasNestedExpression()); $expr->add(['a' => 'b']); $this->assertTrue($expr->hasNestedExpression()); $expr = new QueryExpression(); $expr->add('a = b'); $this->assertFalse($expr->hasNestedExpression()); $expr->add(new QueryExpression('1 = 1')); $this->assertTrue($expr->hasNestedExpression()); }
/** * Test cloning * * @return void */ public function testClone() { $expr = new QueryExpression(); $expr->eq('test', 'true'); $expr2 = new QueryExpression(); $expr2->eq('test2', 'false'); $caseExpression = new CaseExpression([$expr, $expr2], 'foobar'); $dupe = clone $caseExpression; $dupe->elseValue('nope'); $this->assertNotEquals($caseExpression, $dupe); $this->assertNotSame($caseExpression, $dupe); }
/** * Tests that the query expression uses the type map when the * specific comparison functions are used. * * @dataProvider methodsProvider * @return void */ public function testTypeMapUsage($method) { $expr = new QueryExpression([], ['created' => 'date']); $expr->{$method}('created', 'foo'); $binder = new ValueBinder(); $expr->sql($binder); $bindings = $binder->bindings(); $type = current($bindings)['type']; $this->assertEquals('date', $type); }
/** * Deletes/sets null the related objects matching $conditions. * The action which is taken depends on the dependency between source and targets and also on foreign key nullability * * @param array $foreignKey array of foreign key properties * @param \Cake\ORM\Table $target The associated table * @param array $conditions The conditions that specifies what are the objects to be unlinked * @param array $options list of options accepted by `Table::delete()` * @return bool success */ protected function _unlink(array $foreignKey, Table $target, array $conditions = [], array $options = []) { $mustBeDependent = !$this->_foreignKeyAcceptsNull($target, $foreignKey) || $this->dependent(); if ($mustBeDependent) { if ($this->_cascadeCallbacks) { $conditions = new QueryExpression($conditions); $conditions->traverse(function ($entry) use($target) { if ($entry instanceof FieldInterface) { $entry->setField($target->aliasField($entry->getField())); } }); $query = $this->find('all')->where($conditions); $ok = true; foreach ($query as $assoc) { $ok = $ok && $target->delete($assoc, $options); } return $ok; } $target->deleteAll($conditions); return true; } $updateFields = array_fill_keys($foreignKey, null); $target->updateAll($updateFields, $conditions); return true; }
/** * Tests that it is possible to bind arguments to a query and it will return the right * results * * @return void */ public function testCustomBindings() { $table = TableRegistry::get('Articles'); $query = $table->find()->where(['id >' => 1]); $query->where(function ($exp) { $e = new QueryExpression(); return $exp->add($e->eq(new IdentifierExpression('author_id'), new IdentifierExpression(':author'))); }); $query->bind(':author', 1, 'integer'); $this->assertEquals(1, $query->count()); $this->assertEquals(3, $query->first()->id); }