Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch '1407-data-provider' of git://github.com/resurtm/yii int…

…o resurtm-1407-data-provider

Conflicts:
	CHANGELOG
  • Loading branch information...
commit d6f92eaf5107f8d936ad0d4663d51d16294cd4fc 2 parents 15b6028 + fc66677
@samdark samdark authored
View
1  CHANGELOG
@@ -22,6 +22,7 @@ Version 1.1.13 work in progress
- Bug #1347: CDbTestCase: table name in fixtures list enclosed into double curly brackets (e.g. 'tasks'=>':{{task}}') didn't worked properly (resurtm)
- Bug #1351: CClientScript::registerMetaTag() now allows to register multiple meta tags with the same set of attributes (klimov-paul)
- Bug #1364: Empty CHtml::$errorCss cause class attribute rendering errors (creocoder)
+- Bug #1407: CDbCommandBuilder::createCountCommand() used to bind parameters for unused ORDER clause and unused SELECT part (resurtm)
- Bug #1444: Fixed CGoogleApi::register call to registerScriptFile (mdomba)
- Bug #1465: Fixed CHtml::beginForm() when CActiveForm with method GET and ajaxButton is used (mdomba)
- Bug #1485 CSort does not quote table alias when using CDbCriteria (undsoft)
View
22 framework/db/schema/CDbCommandBuilder.php
@@ -151,6 +151,28 @@ public function createCountCommand($table,$criteria,$alias='t')
$sql=$this->applyCondition($sql,$criteria->condition);
}
+ // Suppress binding of parameters belonging to the ORDER clause. Issue #1407.
+ if($criteria->order && $criteria->params)
+ {
+ $params1=array();
+ preg_match_all('/(:\w+)/',$sql,$params1);
+ $params2=array();
+ preg_match_all('/(:\w+)/',$this->applyOrder($sql,$criteria->order),$params2);
+ foreach(array_diff($params2[0],$params1[0]) as $param)
+ unset($criteria->params[$param]);
+ }
+
+ // Do the same for SELECT part.
+ if($criteria->select && $criteria->params)
+ {
+ $params1=array();
+ preg_match_all('/(:\w+)/',$sql,$params1);
+ $params2=array();
+ preg_match_all('/(:\w+)/',$sql.' '.(is_array($criteria->select) ? implode(', ',$criteria->select) : $criteria->select),$params2);
+ foreach(array_diff($params2[0],$params1[0]) as $param)
+ unset($criteria->params[$param]);
+ }
+
$command=$this->_connection->createCommand($sql);
$this->bindValues($command,$criteria->params);
return $command;
View
170 tests/framework/db/CDbCommandBuilderTest.php
@@ -0,0 +1,170 @@
+<?php
+
+Yii::import('system.db.CDbConnection');
+Yii::import('system.db.schema.mysql.CMysqlSchema');
+
+class CDbCommandBuilderTest extends CTestCase
+{
+ /**
+ * @var CDbConnection
+ */
+ private $db;
+
+ public function setUp()
+ {
+ if(!extension_loaded('pdo') || !extension_loaded('pdo_mysql'))
+ $this->markTestSkipped('PDO and MySQL extensions are required.');
+
+ $this->db=new CDbConnection('mysql:host=127.0.0.1;dbname=yii','test','test');
+ $this->db->charset='UTF8';
+ $this->db->enableParamLogging=true;
+ try
+ {
+ $this->db->active=true;
+ }
+ catch(Exception $e)
+ {
+ $schemaFile=realpath(dirname(__FILE__).'/data/mysql.sql');
+ $this->markTestSkipped("Please read $schemaFile for details on setting up the test environment for MySQL test case.");
+ }
+
+ $tables=array('comments','post_category','posts','categories','profiles','users','items','orders','types');
+ foreach($tables as $table)
+ $this->db->createCommand("DROP TABLE IF EXISTS $table CASCADE")->execute();
+
+ $sqls=file_get_contents(dirname(__FILE__).'/data/mysql.sql');
+ foreach(explode(';',$sqls) as $sql)
+ {
+ if(trim($sql)!=='')
+ $this->db->createCommand($sql)->execute();
+ }
+ }
+
+ public function tearDown()
+ {
+ $this->db->active=false;
+ }
+
+ public function testIssue1407_1()
+ {
+ // :parameter1 and :parameter2 should be removed inside CDbCommandBuilder::createCountCommand()
+ $tableSchema=$this->db->getSchema()->getTable('users');
+ $builder=$this->db->getSchema()->getCommandBuilder();
+
+ $criteria1=new CDbCriteria();
+ $criteria1->select=array('t.*',':parameter1 AS test');
+ $criteria1->params[':parameter1']='testingValue';
+ $criteria1->order='IF (t.username=:parameter2,t.username,t.email) DESC';
+ $criteria1->params[':parameter2']='user2';
+ $criteria1->addCondition('t.email LIKE :parameter4');
+ $criteria1->params[':parameter4']='email%';
+ $criteria1->addInCondition('t.id',array(1,2,3));
+
+ $criteria2=clone $criteria1;
+
+ $this->assertEquals(3,$builder->createCountCommand($tableSchema,$criteria1)->queryScalar());
+
+ $result=$builder->createFindCommand($tableSchema,$criteria2)->queryAll();
+ $this->assertCount(3,$result);
+ $this->assertEquals(array(
+ array(
+ 'id'=>'2',
+ 'username'=>'user2',
+ 'email'=>'email2',
+ 'test'=>'testingValue',
+ 'password'=>'pass2',
+ ),
+ array(
+ 'id'=>'3',
+ 'username'=>'user3',
+ 'email'=>'email3',
+ 'test'=>'testingValue',
+ 'password'=>'pass3',
+ ),
+ array(
+ 'id'=>'1',
+ 'username'=>'user1',
+ 'email'=>'email1',
+ 'test'=>'testingValue',
+ 'password'=>'pass1',
+ ),
+ ),$result);
+ }
+
+ public function testIssue1407_2()
+ {
+ // :parameter1 is not used in SQL, thus exception should be thrown
+ $tableSchema=$this->db->getSchema()->getTable('users');
+ $builder=$this->db->getSchema()->getCommandBuilder();
+
+ $criteria=new CDbCriteria();
+ $criteria->select=array('t.*');
+ $criteria->params[':parameter1']='testingValue';
+ $criteria->order='IF (t.username=:parameter2,t.username,t.email) DESC';
+ $criteria->params[':parameter2']='user2';
+ $criteria->addCondition('t.email LIKE :parameter4');
+ $criteria->params[':parameter4']='email%';
+ $criteria->addInCondition('t.id',array(1,2,3));
+
+ $this->setExpectedException('CDbException');
+ $builder->createCountCommand($tableSchema,$criteria)->queryScalar();
+ }
+
+ public function testIssue1407_3()
+ {
+ // :parameter2 is not used in SQL, thus exception should be thrown
+ $tableSchema=$this->db->getSchema()->getTable('users');
+ $builder=$this->db->getSchema()->getCommandBuilder();
+
+ $criteria=new CDbCriteria();
+ $criteria->select=array('t.*',':parameter1 AS test');
+ $criteria->params[':parameter1']='testingValue';
+ $criteria->order='IF (t.username="user2",t.username,t.email) DESC';
+ $criteria->params[':parameter2']='user2';
+ $criteria->addCondition('t.email LIKE :parameter4');
+ $criteria->params[':parameter4']='email%';
+ $criteria->addInCondition('t.id',array(1,2,3));
+
+ $this->setExpectedException('CDbException');
+ $builder->createCountCommand($tableSchema,$criteria)->queryScalar();
+ }
+
+ public function testIssue1407_4()
+ {
+ // both :parameter1 and :parameter2 are not used in SQL, thus exception should be thrown
+ $tableSchema=$this->db->getSchema()->getTable('users');
+ $builder=$this->db->getSchema()->getCommandBuilder();
+
+ $criteria=new CDbCriteria();
+ $criteria->select=array('t.*');
+ $criteria->params[':parameter1']='testingValue';
+ $criteria->order='IF (t.username="user2",t.username,t.email) DESC';
+ $criteria->params[':parameter2']='user2';
+ $criteria->addCondition('t.email LIKE :parameter4');
+ $criteria->params[':parameter4']='email%';
+ $criteria->addInCondition('t.id',array(1,2,3));
+
+ $this->setExpectedException('CDbException');
+ $builder->createCountCommand($tableSchema,$criteria)->queryScalar();
+ }
+
+ public function testIssue1407_5()
+ {
+ // :parameter3 is not used
+ $tableSchema=$this->db->getSchema()->getTable('users');
+ $builder=$this->db->getSchema()->getCommandBuilder();
+
+ $criteria=new CDbCriteria();
+ $criteria->select=array('t.*',':parameter1 AS test');
+ $criteria->params[':parameter1']='testingValue';
+ $criteria->order='IF (t.username=:parameter2,t.username,t.email) DESC';
+ $criteria->params[':parameter2']='user2';
+ $criteria->params[':parameter3']='parameter3Value';
+ $criteria->addCondition('t.email LIKE :parameter4');
+ $criteria->params[':parameter4']='email%';
+ $criteria->addInCondition('t.id',array(1,2,3));
+
+ $this->setExpectedException('CDbException');
+ $builder->createCountCommand($tableSchema,$criteria)->queryScalar();
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.