yiisoft / yii2

Yii 2: The Fast, Secure and Professional PHP Framework
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
14.24k stars 6.91k forks source link

CRIT DB: \yii\db\ColumnSchema::dbTypecast not called on SELECT (and WHERE on DELETE etc ?). #4686

Closed mcd-php closed 10 years ago

mcd-php commented 10 years ago

My new application works with UUID's, storing them in MySQL as binary(16) and displaying as dashed string.

I put conversion into overridden \acme\db\mysql\ColumnSchema::{db,php}Typecast and it was working (at least login), i was positively marking this achievement.

Now it's broken, and git bisect is helpless. I started my app at 2014-08-07 and it was working shortly after, but then i check out commit @6fab67d5 in my /vendor, just before August - it's still broken. And yes, i don't forget to re-apply patches every time.

Yii debugger reveals what UUID goes into SELECT as quoted dashed string, not as binary value.

I used xhprof profiler, and dbTypecast is not in the full call-graph, inserting die() in it proves it's never called.

What can i do from now ?

samdark commented 10 years ago

The best thing is to create a unit test to reproduce the problem.

mcd-php commented 10 years ago

For sure, but where's #4687 ... Test massively fail just on delivery, no way to fix quick by myself.

samdark commented 10 years ago

I'll deal with it. Meanwhile you can edit settings here: https://github.com/yiisoft/yii2/blob/master/tests/unit/data/config.php

mcd-php commented 10 years ago

I now deeply studied \yii\db\QueryBuilder and came to conclusion what it's not a one-line breakage, but \yii\db\ColumnSchema::dbTypecast was never called on query.

Will the core team (tag for it?) accept a massive patch introducing this, by modifcation of many build{Not,And,Between,In,Like,Exists,Hash,Simple}Condition methods ?

Or should i do this privately in my overridden \acme\db\mysql\QueryBuilder, transforming values before calling ::parent ?

P.S. Leaving this alone and transforming data in all controllers is the worst option i can think of ;(

samdark commented 10 years ago

@yiisoft/core-developers what do you think?

cebe commented 10 years ago

It is not easy to figure out to which table columns a parameter belongs in query so it is very hard to implement something that will call dbTypecast in case of Query and WHERE. Consider the following WHERE t.name = CONCAT(t.first, ?). In this case we have no column to call the typecast on because the value is given to an SQL function. Even if it may be possible to implement something like this it is too much and not really necessary for normal SQL dbms.

mcd-php commented 10 years ago

@cebe So you will likely not accept a patch like this - for general use it has to be thorough and pervasive, and for myself it's going to be just 'fix the breakages as i proceed'.

Yeah, i see how not easy is it, but i will give it a little more try before resorting to data conversion in controllers.

P.S. Being 'stringly typed' is one of the worst misfeatures of yii\db, as well as no-join, NoSQL capable relations are it's greatest strength. If only the query would be fully object 'Active AST' ...

basil-inc commented 10 years ago

@mcd-php you are aware that by using the MySQL native driver, query results have the right type (int, string, float,...)?

mcd-php commented 10 years ago

@docsolver But how can it help here ? Yii2 uses PDO ! If i would be in utter desperation, i could consider implementing PDO interface at top of mysqli or whatever known good adapter, or quoting binary UUID's right into SQL text hacking all build*Condition methods, but i already half-solved and not up for such severe creativity.

basil-inc commented 10 years ago

It is not on the PDO level, but on a lower level.

The MySQL database extensions MySQL extension, mysqli and PDO MYSQL
all communicate with the MySQL server. In the past, this was done by the
extension using the services provided by the MySQL Client Library.
The extensions were compiled against the MySQL Client Library in order to
use its client-server protocol.

http://php.net/manual/en/intro.mysqlnd.php

You can install it on Ubuntu using apt-get install php5-mysqlnd

mcd-php commented 10 years ago

@docsolver Installed. Still no way for minimal bug demo.

qiangxue commented 10 years ago

Based on the discussion, I think we couldn't do much here. Closed unless PR or further arguments are provided.