views:

49

answers:

3

I have a CakePHP app that is being moved to Sql Server from MySql. There is one query that does not seem to transfer correctly:

$this->Model->find('all', array(
        'conditions' => array(
            'Model.column' => array(1, 2, 3)
        )
    )
);

When I use this syntax with mysql, it seems to 'unpack' the array correctly, and the query generated is something like

"...WHERE 'Model.column' IN (1, 2, 3)..."

When I use sql server, the query generated is

"...WHERE 'Model.column' IN 'Array'"...

which obviously generates an error. I posted this question on the CakePHP Google Group yesterday, but have not received a reponse, so I thought I would try SO. If anyone has any ideas/suggestions I would appreciate it.

+1  A: 

The code that generates this is in dbo_source.php (function conditionKeysToString) and while specific database drivers can override this, I have never seen that done.

I have 1.2.5, 1.2.6 and 1.3.0-RC1 on my system and they all append ' IN (' and nothing overides that function. There is no instance of just appending ' IN ' and then deciding if it is an array or scalar value. The word Array is what happens when an array variable is evaluated in a string context. EG: php -r '$a = array(1,2,3); echo $a;' will output Array.

Check the cake/VERSION.txt file in both. If they are different, back up the cake directory on the SQL Server instance and replace it with the one from MySQL.

If they are the same try going to the cake/libs/model/datasources directory. Hopefully you have Unix or Linux because "grep -r ' IN ' *" will help you out immensely. Otherwise compare dbo_soures.php and dbo/dbo_mssql.php between both installs of cake and see if there are any differences in conditionKeysToString.

Ultimately I would upgrade to 1.2.6 just so that you get any and all fixes.

Erik Nedwidek
Just adding: It's correct that the `'Array'` appears to be an automatic array to string cast done by PHP. It *should* throw a NOTICE if it does so. That *should* help find *where* the cast is being done.
deceze
I'm sorry that I wasn't clear, but there are not two installs of cake. My app was developed using MySQL as the DB, but now management wants it to use SQL Server, so I am trying to debug any inconsistencies in the generated queries. I am using 1.2.6 on a linux machine. I don't see anything in cake/libs/model/datasources/dbo/dbo_mssql.php that would override the default behavior, so I am going to try to find more info about where exactly the cast is being done.
W_P
Just checking back in to see if you had made any progress. I'm guessing this is even the same machine so the PHP version would be the same.PHP and debuggers can be a pain. An easy way to trace the code would be to edit dbo_mssql.php and find:function _execute($sql) { return mssql_query($sql, $this->connection);}and change it to:function _execute($sql) { $this->log(debug_backtrace()); return mssql_query($sql, $this->connection);}It'll dump a lot of data in your log, but you'll get a lot of state info.
Erik Nedwidek
unfortunately no answer yet...will get back to you when there is.
W_P
so my original question was a little off...the generated query is actually 'Where Model.column IS Array' not '... IN Array ...'
W_P
A: 

Try passing that condition as a string:

$this->Model->find('all', array(
        'conditions' => array(
            'Model.column in (1, 2, 3)'
        )
    )
);
inkedmn
That's fine if you are hard coding the 1,2,3. If these are from the user, you defeat the purpose of using something like Cake. The point to RoR, Cake, etc. is that the developer shouldn't need to worry about the injection attacks.
Erik Nedwidek
A: 

Try it like this:

$this->Model->find('all', array(
        'conditions' => array(
            'Model.column' => array(
                'OR' => array(1, 2, 3)
            )
        )
    )
);
sibidiba