find() method shouldn't use intval() when primary key is int

View: New views
16 Messages — Rating Filter:   Alert me  

find() method shouldn't use intval() when primary key is int

by Dimitri van Hees :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I posted this on the issue tracker to verify that it's not a bug, so hereby I want to make my statement that I don't agree with the find() method using intval (or something like that) when my primary key is an integer. Let's say I have the following record in my database:

id (PK)  = 2
title = Lorem
text = Lorem ipsum

In my code, I use $this->find(2) to retrieve this record. This works great, however $this->find('2abc') also retrieves this record. In my opinion, this doesn't make any sense as "SELECT * FROM myTable WHERE id = '2abc'" wouldn't return it either. Instead, the fact that ZF knows whether my primary key is an integer, perhaps in this case $this->find('2abc') should return an error saying that the provided key doesn't match the data type of my primary key.

I am looking forward to hearing your opinions about this.

Dimitri
--


Met vriendelijke groet,

Dimitri van Hees

- -

Dimitri van Hees
dimitri@...

freshheads grafisch ontwerp en internet applicaties
Dunantstraat 1c | 5017 KC Tilburg | Nederland
tel. +31 (0)13 5448761 | fax. +31 (0)13 5448762
info@... | www.freshheads.com

Re: find() method shouldn't use intval() when primary key is int

by JDempster :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I think to some extent it comes down to data validation before you use the find() method. So if your working with user input data and expect an ID you should be validating that the data is an int.

/James Dempster

On Fri, Jun 13, 2008 at 9:13 AM, Dimitri van Hees <dimitri@...> wrote:
I posted this on the issue tracker to verify that it's not a bug, so hereby I want to make my statement that I don't agree with the find() method using intval (or something like that) when my primary key is an integer. Let's say I have the following record in my database:

id (PK)  = 2
title = Lorem
text = Lorem ipsum

In my code, I use $this->find(2) to retrieve this record. This works great, however $this->find('2abc') also retrieves this record. In my opinion, this doesn't make any sense as "SELECT * FROM myTable WHERE id = '2abc'" wouldn't return it either. Instead, the fact that ZF knows whether my primary key is an integer, perhaps in this case $this->find('2abc') should return an error saying that the provided key doesn't match the data type of my primary key.

I am looking forward to hearing your opinions about this.

Dimitri
--


Met vriendelijke groet,

Dimitri van Hees

- -

Dimitri van Hees
dimitri@...

freshheads grafisch ontwerp en internet applicaties
Dunantstraat 1c | 5017 KC Tilburg | Nederland
tel. +31 (0)13 5448761 | fax. +31 (0)13 5448762
info@... | www.freshheads.com


Parent Message unknown Re: find() method shouldn't use intval() when primary key is int

by Dimitri van Hees :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I agree that input validation should happen before, however the find() method should return the record where the primary key equals the given parameter (if I am already wrong on this point, I understand your opinion). Just like find(5) won't give me a result because there is no record with primary key '5', find ('2abc') shouldnt return the record with primary key '2' because there is no record with primary key '2abc'.

Joakim Nygård wrote:
On 13/06/2008, at 10.13, Dimitri van Hees wrote:

I posted this on the issue tracker to verify that it's not a bug, so hereby I want to make my statement that I don't agree with the find() method using intval (or something like that) when my primary key is an integer. Let's say I have the following record in my database:

id (PK)  = 2
title = Lorem
text = Lorem ipsum

In my code, I use $this->find(2) to retrieve this record. This works great, however $this->find('2abc') also retrieves this record. In my opinion, this doesn't make any sense as "SELECT * FROM myTable WHERE id = '2abc'" wouldn't return it either. Instead, the fact that ZF knows whether my primary key is an integer, perhaps in this case $this->find('2abc') should return an error saying that the provided key doesn't match the data type of my primary key.

I am looking forward to hearing your opinions about this.


I believe it makes sense to do it this way. The fact that the primary key is an int is exactly the reason it makes sense to cast the parameter.

That you are getting a record back from '2abc' should be considered purely random since any validation of the (user input) parameter should happen before you pass it to the Db classes (or any where else in the app).

Kind regards,

Joakim Nygård
--
http://jokke.dk

"The biggest improvement in performance is the non-working-to-working" – John Ousterhout




--


Met vriendelijke groet,

Dimitri van Hees

- -

Dimitri van Hees
dimitri@...

freshheads grafisch ontwerp en internet applicaties
Dunantstraat 1c | 5017 KC Tilburg | Nederland
tel. +31 (0)13 5448761 | fax. +31 (0)13 5448762
info@... | www.freshheads.com

Re: find() method shouldn't use intval() when primary key is int

by Bill Karwin :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Dimitri van Hees wrote:
I agree that input validation should happen before, however the find()
method should return the record where the primary key equals the given
parameter (if I am already wrong on this point, I understand your
opinion). Just like find(5) won't give me a result because there is no
record with primary key '5', find ('2abc') shouldnt return the record
with primary key '2' because there is no record with primary key '2abc'.
Zend_Db is not doing this mapping.  The intval() function does not appear anywhere in Zend_Db_Table or related classes.  Furthermore, it's not even PHP or the database extension doing this mapping.

What you're seeing is standard behavior of MySQL (and perhaps other databases).  You can reproduce this behavior without using PHP at all, just use the MySQL command-line tool:

mysql> CREATE TABLE test.foo (i INTEGER);
mysql> INSERT INTO test.foo VALUES (1), (2), (3);
mysql> SELECT * FROM test.foo WHERE i = '2abc';
+------+
| i    |
+------+
|    2 |
+------+
1 row in set, 3 warnings (0.02 sec)

I don't know any way of changing this behavior of MySQL.

Regards,
Bill Karwin

Re: find() method shouldn't use intval() when primary key is int

by JDempster :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Not so sure about that Bill,
In trunk line 997 of Zend/Db/Table/Abstract.php

$type = $this->_metadata[$keyNames[$keyPosition]]['DATA_TYPE'];
$whereAndTerms[] = $this->_db->quoteInto(
    $this->_db->quoteIdentifier($keyNames[$keyPosition], true) . ' = ?',
    $keyValue, $type);


It's reading in the type and passing that type on to quoteInto of the db adapter which then passes it onto quote of the db adapter line 770 of Zend/Db/Adapter/Abstract.php

line 792
case Zend_Db::INT_TYPE: // 32-bit integer
    $quotedValue = (string) intval($value);
    break;

It also covers many other types.

I personally am much happier with it doing it this way. It allows for much cleaner sql queries with values that match the actual db types. Some dbs have problems with casting differencing values for columns types etc.

The real answer to this problem is validate, it's obviously impossible for a int column primary key to contain the required value.

As another solution you could always extend the class and overload the query method and deal with it differently.

/James Dempster

On Fri, Jun 13, 2008 at 4:00 PM, Bill Karwin <bill@...> wrote:



Dimitri van Hees wrote:
>
> I agree that input validation should happen before, however the find()
> method should return the record where the primary key equals the given
> parameter (if I am already wrong on this point, I understand your
> opinion). Just like find(5) won't give me a result because there is no
> record with primary key '5', find ('2abc') shouldnt return the record
> with primary key '2' because there is no record with primary key '2abc'.
>

Zend_Db is not doing this mapping.  The intval() function does not appear
anywhere in Zend_Db_Table or related classes.  Furthermore, it's not even
PHP or the database extension doing this mapping.

What you're seeing is standard behavior of MySQL (and perhaps other
databases).  You can reproduce this behavior without using PHP at all, just
use the MySQL command-line tool:

mysql> CREATE TABLE test.foo (i INTEGER);
mysql> INSERT INTO test.foo VALUES (1), (2), (3);
mysql> SELECT * FROM test.foo WHERE i = '2abc';
+------+
| i    |
+------+
|    2 |
+------+
1 row in set, 3 warnings (0.02 sec)

I don't know any way of changing this behavior of MySQL.

Regards,
Bill Karwin
--
View this message in context: http://www.nabble.com/find%28%29-method-shouldn%27t-use-intval%28%29-when-primary-key-is-int-tp17818272p17825454.html
Sent from the Zend DB mailing list archive at Nabble.com.



Re: find() method shouldn't use intval() when primary key is int

by JDempster :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

P.S.

Postgres will report an error with that SQL.
ERROR:  invalid input syntax for integer: "2abc"

where as MySQL does exactly as you said.

On Fri, Jun 13, 2008 at 4:00 PM, Bill Karwin <bill@...> wrote:



Dimitri van Hees wrote:
>
> I agree that input validation should happen before, however the find()
> method should return the record where the primary key equals the given
> parameter (if I am already wrong on this point, I understand your
> opinion). Just like find(5) won't give me a result because there is no
> record with primary key '5', find ('2abc') shouldnt return the record
> with primary key '2' because there is no record with primary key '2abc'.
>

Zend_Db is not doing this mapping.  The intval() function does not appear
anywhere in Zend_Db_Table or related classes.  Furthermore, it's not even
PHP or the database extension doing this mapping.

What you're seeing is standard behavior of MySQL (and perhaps other
databases).  You can reproduce this behavior without using PHP at all, just
use the MySQL command-line tool:

mysql> CREATE TABLE test.foo (i INTEGER);
mysql> INSERT INTO test.foo VALUES (1), (2), (3);
mysql> SELECT * FROM test.foo WHERE i = '2abc';
+------+
| i    |
+------+
|    2 |
+------+
1 row in set, 3 warnings (0.02 sec)

I don't know any way of changing this behavior of MySQL.

Regards,
Bill Karwin
--
View this message in context: http://www.nabble.com/find%28%29-method-shouldn%27t-use-intval%28%29-when-primary-key-is-int-tp17818272p17825454.html
Sent from the Zend DB mailing list archive at Nabble.com.



Re: find() method shouldn't use intval() when primary key is int

by Dimitri van Hees :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi all,

Thanks for your opinions, however I still don't agree, whether it's MySQL or Zend Framework itself ;-)
I guess I'll just have to extend the class to my appearantly strange opinion about this, but to me it's a pity that the following code doesn't work right now:

if($record = $db->find($this->id)) {
    var_dump($record);
} else {
    //404
}

In our case $this->id comes from the url, knowing that any security issues are already handled by the framework/find function itself, so SQL injections won't be possible (right?). As there is no record with PK = 5, there also isn't a record with PK = '2abc'. The only record I have should be PK = 2. I don't see why the find() method handles find(5) different than find('2abc') when both primary keys don't exist.

Thanks again,

Dimitri

James Dempster wrote:
Not so sure about that Bill,
In trunk line 997 of Zend/Db/Table/Abstract.php

$type = $this->_metadata[$keyNames[$keyPosition]]['DATA_TYPE'];
$whereAndTerms[] = $this->_db->quoteInto(
    $this->_db->quoteIdentifier($keyNames[$keyPosition], true) . ' = ?',
    $keyValue, $type);


It's reading in the type and passing that type on to quoteInto of the db adapter which then passes it onto quote of the db adapter line 770 of Zend/Db/Adapter/Abstract.php

line 792
case Zend_Db::INT_TYPE: // 32-bit integer
    $quotedValue = (string) intval($value);
    break;

It also covers many other types.

I personally am much happier with it doing it this way. It allows for much cleaner sql queries with values that match the actual db types. Some dbs have problems with casting differencing values for columns types etc.

The real answer to this problem is validate, it's obviously impossible for a int column primary key to contain the required value.

As another solution you could always extend the class and overload the query method and deal with it differently.

/James Dempster

On Fri, Jun 13, 2008 at 4:00 PM, Bill Karwin <bill@...> wrote:



Dimitri van Hees wrote:
>
> I agree that input validation should happen before, however the find()
> method should return the record where the primary key equals the given
> parameter (if I am already wrong on this point, I understand your
> opinion). Just like find(5) won't give me a result because there is no
> record with primary key '5', find ('2abc') shouldnt return the record
> with primary key '2' because there is no record with primary key '2abc'.
>

Zend_Db is not doing this mapping.  The intval() function does not appear
anywhere in Zend_Db_Table or related classes.  Furthermore, it's not even
PHP or the database extension doing this mapping.

What you're seeing is standard behavior of MySQL (and perhaps other
databases).  You can reproduce this behavior without using PHP at all, just
use the MySQL command-line tool:

mysql> CREATE TABLE test.foo (i INTEGER);
mysql> INSERT INTO test.foo VALUES (1), (2), (3);
mysql> SELECT * FROM test.foo WHERE i = '2abc';
+------+
| i    |
+------+
|    2 |
+------+
1 row in set, 3 warnings (0.02 sec)

I don't know any way of changing this behavior of MySQL.

Regards,
Bill Karwin
--
View this message in context: http://www.nabble.com/find%28%29-method-shouldn%27t-use-intval%28%29-when-primary-key-is-int-tp17818272p17825454.html
Sent from the Zend DB mailing list archive at Nabble.com.




--


Met vriendelijke groet,

Dimitri van Hees

- -

Dimitri van Hees
dimitri@...

freshheads grafisch ontwerp en internet applicaties
Dunantstraat 1c | 5017 KC Tilburg | Nederland
tel. +31 (0)13 5448761 | fax. +31 (0)13 5448762
info@... | www.freshheads.com

Re: find() method shouldn't use intval() when primary key is int

by Bill Karwin :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


JDempster wrote:
Not so sure about that Bill,

It's reading in the type and passing that type on to quoteInto of the db
adapter which then passes it onto quote of the db adapter line 770 of
Zend/Db/Adapter/Abstract.php
Aha, good catch.  I stand corrected.

Nevertheless, MySQL does do automatic string-to-intval mapping in its flavor of SQL.  Perhaps this isn't advisable, for the reasons Dimitri states, but the point is that even if Zend_Db weren't doing this, MySQL still would (if you use MySQL).

Now I remember, I had to do the intval() based on the datatype in quoteInto() because Oracle complains if you pass a string value to be compared to an integer column.   In other words, the following expression is a fatal error in Oracle:  WHERE id = '2'

Yet Oracle returns integer datatypes as strings (because 64-bit Oracle integers exceed the capacity of a 32-bit PHP integer).  Zend_Db_Table_Row uses that string when forming SQL queries for save() or findDependentRowset() etc., so the value must not have quotes around it.

In the quoteInto() method, one could simply take the argument verbatim, but not quote it if it's supposed to compare to an integer column.  But that would create a bad security flaw in an unexpected place, so a call to find('3 OR 1=1') would be a vector for SQL injection.  

Therefore the best thing I could do is use intval() to ensure the argument of quoteInto() is safe, if it mustn't be quoted because $type says it's an integer.  For BIGINT, a regular expression is used instead of intval(), so 64-bit integer values won't be truncated.

Regards,
Bill Karwin

Re: find() method shouldn't use intval() when primary key is int

by Bill Karwin :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Dimitri van Hees wrote:
I don't see why the find() method handles find(5)
different than find('2abc') when both primary keys don't exist.
The reason is that 5 is a valid integer and is passed through to the SQL executed by the database server, which finds no row with that PK value.  '2abc' is filtered to a valid integer, which is 2, and this PK value is found.  

If quoteInto() didn't do this filtering, it would be a SQL injection vulnerability, but if quoteInto() quoted the string to prevent SQL injection, this would be invalid SQL on database brands that require integer literals to be unquoted.

Regards,
Bill Karwin

Regards,
Bill Karwin

RE: find() method shouldn't use intval() when primary key is int

by Duncan, Craig :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

With regard to Oracle, I think you must be mistaken. Using the Oci8
driver, the following queries return the same result:


Query 1: select * from tst where id = '2'

Result 1: array ( 0 => '2', 'ID' => '2', )

Query 2: select * from tst where id = 2

Result 2: array ( 0 => '2', 'ID' => '2', )


Craig Duncan

-----Original Message-----
From: Bill Karwin [mailto:bill@...]
Sent: Friday, June 13, 2008 11:55 AM
To: fw-db@...
Subject: Re: [fw-db] find() method shouldn't use intval() when primary
key is int




JDempster wrote:
>
> Not so sure about that Bill,
>
> It's reading in the type and passing that type on to quoteInto of the
db
> adapter which then passes it onto quote of the db adapter line 770 of
> Zend/Db/Adapter/Abstract.php
>

Aha, good catch.  I stand corrected.

Nevertheless, MySQL does do automatic string-to-intval mapping in its
flavor
of SQL.  Perhaps this isn't advisable, for the reasons Dimitri states,
but
the point is that even if Zend_Db weren't doing this, MySQL still would
(if
you use MySQL).

Now I remember, I had to do the intval() based on the datatype in
quoteInto() because Oracle complains if you pass a string value to be
compared to an integer column.   In other words, the following
expression is
a fatal error in Oracle:  WHERE id = '2'

Yet Oracle returns integer datatypes as strings (because 64-bit Oracle
integers exceed the capacity of a 32-bit PHP integer).
Zend_Db_Table_Row
uses that string when forming SQL queries for save() or
findDependentRowset() etc., so the value must not have quotes around it.

In the quoteInto() method, one could simply take the argument verbatim,
but
not quote it if it's supposed to compare to an integer column.  But that
would create a bad security flaw in an unexpected place, so a call to
find('3 OR 1=1') would be a vector for SQL injection.  

Therefore the best thing I could do is use intval() to ensure the
argument
of quoteInto() is safe, if it mustn't be quoted because $type says it's
an
integer.  For BIGINT, a regular expression is used instead of intval(),
so
64-bit integer values won't be truncated.

Regards,
Bill Karwin
--
View this message in context:
http://www.nabble.com/find%28%29-method-shouldn%27t-use-intval%28%29-whe
n-primary-key-is-int-tp17818272p17826612.html
Sent from the Zend DB mailing list archive at Nabble.com.



RE: find() method shouldn't use intval() when primary key is int

by Bill Karwin :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Duncan, Craig wrote:
With regard to Oracle, I think you must be mistaken. Using the Oci8
driver, the following queries return the same result:
Well I'm not an Oracle expert, and I don't have it installed right now so I can't test.  The behavior might vary by version, by platform, or perhaps there's a config option with which one can change this behavior.  I don't know.

I tested with Oracle XE 10g on Windows XP.  I wrote hundreds of unit tests for Zend_Db, running identical SQL queries against multiple brands of database.  A query that compared a number column to a quoted integer literal worked on MySQL but threw an error on Oracle.

Take that as you will.

Regards,
Bill Karwin

Re: find() method shouldn't use intval() when primary key is int

by Gunter Sammet :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I didn't follow the whole conversation but here a suggestion. Would it help if we do something like this:

case Zend_Db::INT_TYPE: // 32-bit integer
    if($value != intval($value)){
        //throw error that this is not an int
    }
    $quotedValue = (string) intval($value);
    break;

Just a thought.

Gunter


On Fri, Jun 13, 2008 at 11:19 AM, Bill Karwin <bill@...> wrote:



Duncan, Craig wrote:
>
> With regard to Oracle, I think you must be mistaken. Using the Oci8
> driver, the following queries return the same result:
>

Well I'm not an Oracle expert, and I don't have it installed right now so I
can't test.  The behavior might vary by version, by platform, or perhaps
there's a config option with which one can change this behavior.  I don't
know.

I tested with Oracle XE 10g on Windows XP.  I wrote hundreds of unit tests
for Zend_Db, running identical SQL queries against multiple brands of
database.  A query that compared a number column to a quoted integer literal
worked on MySQL but threw an error on Oracle.

Take that as you will.

Regards,
Bill Karwin
--
View this message in context: http://www.nabble.com/find%28%29-method-shouldn%27t-use-intval%28%29-when-primary-key-is-int-tp17818272p17828305.html
Sent from the Zend DB mailing list archive at Nabble.com.



Re: find() method shouldn't use intval() when primary key is int

by JDempster :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

might be best to do something like

if((string)intval($this->id)) == (string)$this->id && $record = $db->find($this->id)) {
    var_dump($record);
} else {
    // 404
}

If you're using MySQL as a db or even Oracle it sounds like you don't have a choice, because it looks like the db will cast it for you in much the same way that Zend_Db does.
If you're using using Postgres (tested on 8.0) then it would have caused an Exception from an invalid SQL query.

I much prefer the way ZF deals with it. It's constant across all db's.

/James Dempster

On Fri, Jun 13, 2008 at 4:29 PM, Dimitri van Hees <dimitri@...> wrote:
Hi all,

Thanks for your opinions, however I still don't agree, whether it's MySQL or Zend Framework itself ;-)
I guess I'll just have to extend the class to my appearantly strange opinion about this, but to me it's a pity that the following code doesn't work right now:

if($record = $db->find($this->id)) {
    var_dump($record);
} else {
    //404
}

In our case $this->id comes from the url, knowing that any security issues are already handled by the framework/find function itself, so SQL injections won't be possible (right?). As there is no record with PK = 5, there also isn't a record with PK = '2abc'. The only record I have should be PK = 2. I don't see why the find() method handles find(5) different than find('2abc') when both primary keys don't exist.

Thanks again,

Dimitri


James Dempster wrote:
Not so sure about that Bill,
In trunk line 997 of Zend/Db/Table/Abstract.php

$type = $this->_metadata[$keyNames[$keyPosition]]['DATA_TYPE'];
$whereAndTerms[] = $this->_db->quoteInto(
    $this->_db->quoteIdentifier($keyNames[$keyPosition], true) . ' = ?',
    $keyValue, $type);


It's reading in the type and passing that type on to quoteInto of the db adapter which then passes it onto quote of the db adapter line 770 of Zend/Db/Adapter/Abstract.php

line 792
case Zend_Db::INT_TYPE: // 32-bit integer
    $quotedValue = (string) intval($value);
    break;

It also covers many other types.

I personally am much happier with it doing it this way. It allows for much cleaner sql queries with values that match the actual db types. Some dbs have problems with casting differencing values for columns types etc.

The real answer to this problem is validate, it's obviously impossible for a int column primary key to contain the required value.

As another solution you could always extend the class and overload the query method and deal with it differently.

/James Dempster

On Fri, Jun 13, 2008 at 4:00 PM, Bill Karwin <bill@...> wrote:



Dimitri van Hees wrote:
>
> I agree that input validation should happen before, however the find()
> method should return the record where the primary key equals the given
> parameter (if I am already wrong on this point, I understand your
> opinion). Just like find(5) won't give me a result because there is no
> record with primary key '5', find ('2abc') shouldnt return the record
> with primary key '2' because there is no record with primary key '2abc'.
>

Zend_Db is not doing this mapping.  The intval() function does not appear
anywhere in Zend_Db_Table or related classes.  Furthermore, it's not even
PHP or the database extension doing this mapping.

What you're seeing is standard behavior of MySQL (and perhaps other
databases).  You can reproduce this behavior without using PHP at all, just
use the MySQL command-line tool:

mysql> CREATE TABLE test.foo (i INTEGER);
mysql> INSERT INTO test.foo VALUES (1), (2), (3);
mysql> SELECT * FROM test.foo WHERE i = '2abc';
+------+
| i    |
+------+
|    2 |
+------+
1 row in set, 3 warnings (0.02 sec)

I don't know any way of changing this behavior of MySQL.

Regards,
Bill Karwin
--
View this message in context: http://www.nabble.com/find%28%29-method-shouldn%27t-use-intval%28%29-when-primary-key-is-int-tp17818272p17825454.html
Sent from the Zend DB mailing list archive at Nabble.com.




--


Met vriendelijke groet,

Dimitri van Hees

- -

Dimitri van Hees
dimitri@...

freshheads grafisch ontwerp en internet applicaties
Dunantstraat 1c | 5017 KC Tilburg | Nederland
tel. +31 (0)13 5448761 | fax. +31 (0)13 5448762
info@... | www.freshheads.com


Parent Message unknown Re: find() method shouldn't use intval() when primary key is int

by JDempster :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

That's exactly what it is doing.

/James Dempster

On Mon, Jun 16, 2008 at 8:27 AM, Coen Hyde <Coen.Hyde@...> wrote:

Maybe I'm missing something but why can't the ZF cast the primary id to its proper type? We already have the metadata for the table.

 


From: James Dempster [mailto:letssurf@...]
Sent: Saturday, 14 June 2008 4:43 AM
To: Dimitri van Hees
Cc: fw-db@...
Subject: Re: [fw-db] find() method shouldn't use intval() when primary key is int

 

might be best to do something like

if((string)intval($this->id)) == (string)$this->id && $record = $db->find($this->id)) {
    var_dump($record);
} else {
    // 404
}

If you're using MySQL as a db or even Oracle it sounds like you don't have a choice, because it looks like the db will cast it for you in much the same way that Zend_Db does.
If you're using using Postgres (tested on 8.0) then it would have caused an Exception from an invalid SQL query.

I much prefer the way ZF deals with it. It's constant across all db's.

/James Dempster

On Fri, Jun 13, 2008 at 4:29 PM, Dimitri van Hees <dimitri@...> wrote:

Hi all,

Thanks for your opinions, however I still don't agree, whether it's MySQL or Zend Framework itself ;-)
I guess I'll just have to extend the class to my appearantly strange opinion about this, but to me it's a pity that the following code doesn't work right now:

if($record = $db->find($this->id)) {
    var_dump($record);
} else {
    //404
}

In our case $this->id comes from the url, knowing that any security issues are already handled by the framework/find function itself, so SQL injections won't be possible (right?). As there is no record with PK = 5, there also isn't a record with PK = '2abc'. The only record I have should be PK = 2. I don't see why the find() method handles find(5) different than find('2abc') when both primary keys don't exist.

Thanks again,

Dimitri



James Dempster wrote:

Not so sure about that Bill,
In trunk line 997 of Zend/Db/Table/Abstract.php

$type = $this->_metadata[$keyNames[$keyPosition]]['DATA_TYPE'];
$whereAndTerms[] = $this->_db->quoteInto(
    $this->_db->quoteIdentifier($keyNames[$keyPosition], true) . ' = ?',
    $keyValue, $type);


It's reading in the type and passing that type on to quoteInto of the db adapter which then passes it onto quote of the db adapter line 770 of Zend/Db/Adapter/Abstract.php

line 792
case Zend_Db::INT_TYPE: // 32-bit integer
    $quotedValue = (string) intval($value);
    break;


It also covers many other types.

I personally am much happier with it doing it this way. It allows for much cleaner sql queries with values that match the actual db types. Some dbs have problems with casting differencing values for columns types etc.

The real answer to this problem is validate, it's obviously impossible for a int column primary key to contain the required value.

As another solution you could always extend the class and overload the query method and deal with it differently.

/James Dempster

On Fri, Jun 13, 2008 at 4:00 PM, Bill Karwin <bill@...> wrote:




Dimitri van Hees wrote:
>
> I agree that input validation should happen before, however the find()
> method should return the record where the primary key equals the given
> parameter (if I am already wrong on this point, I understand your
> opinion). Just like find(5) won't give me a result because there is no
> record with primary key '5', find ('2abc') shouldnt return the record
> with primary key '2' because there is no record with primary key '2abc'.
>

Zend_Db is not doing this mapping.  The intval() function does not appear
anywhere in Zend_Db_Table or related classes.  Furthermore, it's not even
PHP or the database extension doing this mapping.

What you're seeing is standard behavior of MySQL (and perhaps other
databases).  You can reproduce this behavior without using PHP at all, just
use the MySQL command-line tool:

mysql> CREATE TABLE test.foo (i INTEGER);
mysql> INSERT INTO test.foo VALUES (1), (2), (3);
mysql> SELECT * FROM test.foo WHERE i = '2abc';
+------+
| i    |
+------+
|    2 |
+------+
1 row in set, 3 warnings (0.02 sec)

I don't know any way of changing this behavior of MySQL.

Regards,
Bill Karwin
--
View this message in context: http://www.nabble.com/find%28%29-method-shouldn%27t-use-intval%28%29-when-primary-key-is-int-tp17818272p17825454.html
Sent from the Zend DB mailing list archive at Nabble.com.

 

 

--


Met vriendelijke groet,

Dimitri van Hees

- -

Dimitri van Hees
dimitri@...

freshheads grafisch ontwerp en internet applicaties
Dunantstraat 1c | 5017 KC Tilburg | Nederland
tel. +31 (0)13 5448761 | fax. +31 (0)13 5448762
info@... | www.freshheads.com

 



Re: find() method shouldn't use intval() when primary key is int

by Nick Lo-2 :: Rate this Message: