CDbCriteria->addSearchCondition being ignored

Hi,

I believe I might have found a bug in the


CDbCriteria->addSearchCondition()

method.

I have the following data:


ID (int) | NAME (varchar) | ACTIVE (int)

-----------------------------------------

1        | One            | 1

1        | Two            | 0

1        | Three          | 1

1        | Four           | 0

1        | Five           | 1

Test 1


$model = Bugtest::model()->findAll();

Query Generated:


SELECT * FROM `bugtest` `t`

Gives the correct results. The whole table.

Test 2


$criteria=new CDbCriteria;

$criteria->select='id, name, active';

$criteria->addSearchCondition('active', 1);

$searchone = Bugtest::model()->findAll($criteria);

Query Generated:


SELECT id, name, active FROM `bugtest` `t` WHERE active LIKE :ycp0

Where


:ycp0 = 1

Give the correct results. Only values where active is 1.

Test 3


$criteria=new CDbCriteria;

$criteria->select='id, name, active';

$criteria->addSearchCondition('active', 0);

$searchtwo = Bugtest::model()->findAll($criteria);

Query Generated:


SELECT * FROM `bugtest` `t`

Gives incorrect results. Returns the whole table like


findAll()

.

From what I can see,


$criteria->addSearchCondition('active', 0);

is just being ignored and dropped.

I am aware of other ways to do this search, but this behaviour was strange to me.

Any comments? Is it a bug or is it by design?

Info


OS: Windows 7

Server: Apache 2.2.17

PHP: 5.3.4

Yii: 1.1.8

MySQL: 5.5.8

Full sample project can be found here

dev.donovansolms.com/bugs/cdbcriteria-bugtest.zip

It includes the SQL for the table. All you need to do is set the database password in main config.

Looks like a little bug to me. API: http://www.yiiframework.com/doc/api/1.1/CDbCriteria#addSearchCondition-detail




if($keyword=='')

    return $this;



0 == ‘’ returns true, but 0 === ‘’ will return false.

You can pass ‘0’ instead of integer 0. But what you actually need in this particular situation is addColumnCondition.

addColumnCondition or addCondition would be more appropriate here…

as the active column is an INT makes not sense to search with LIKE.

Thanks for the input!

Agreed. A LIKE doesn’t make sense for this column.

If I use addSearchCondition(‘active’, ‘0’) it does return the expected values.

If I change




if($keyword=='')

    return $this;



to




if($keyword==='')

    return $this;



and use addSearchCondition(‘active’, 0) the expected result is returned.

For me the name of the method means that I can do search on any of my columns using it. Even though it is using a LIKE, my opinion is that it is a minor bug because it is not returning the expected result.

I would propose changing


$keyword==''

to


$keyword===''

as the solution.

Does anyone agree? or should it be left as is?

I agree to change it to:




if((string)$keyword=='')



So it won’t allow NULL and FALSE values (searching “LIKE NULL” is senseless, and false will be converted to the empty string, while integer 0 is converted to “0” string).

Actually I heard some people are always using LIKE instead of “=” (maybe some old school :D), and I don’t think a query with LIKE instead of “=” will be slower.

By SQL definition the LIKE operator does a pattern matching comparison… is defined to be used with strings… the patern should be a string - http://dev.mysql.com/doc/refman/5.0/en/string-comparison-functions.html#operator_like

As the doc. say, MySql as an extension to the standard SQL allows LIKE on numeric expressions (expressions not columns!), and it does not explain what happens if you use a numeric column (INT) so this is a bit undocumented and possibly can have some side effects.

On PostgreSql you cannot use LIKE on numeric columns at all, if you use it with a numeric column you get an error.

MS SQL has this documented and it say that any non-string values are converted to strings - http://msdn.microsoft.com/en-us/library/aa933232(v=sql.80).aspx

So is possible that mysql makes this conversion, too… and in fact when you say select 1 like 1, the actual search is select ‘1’ like ‘1’.

As for speed… LIKE is very slow compared to = as first it checks for string values and then makes a pattern matching algorithm as that is the main force of LIKE.

Btw

The documentation for addSearchCondition is clear… the second parameter $keyword should be a string.

Very well. Will leave it as is then.

Thanks for the feedback!