Bug #45370 | IF() values are evaluated differently in a regular SQL vs Prepared Statements | ||
---|---|---|---|
Submitted: | 8 Jun 2009 12:13 | Modified: | 28 Mar 2013 16:11 |
Reporter: | Leandro Morgado | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Prepared statements | Severity: | S3 (Non-critical) |
Version: | 5.0.56, 5.1.35 | OS: | Any |
Assigned to: | CPU Architecture: | Any |
[8 Jun 2009 12:13]
Leandro Morgado
[8 Jun 2009 12:15]
Leandro Morgado
Here are some more tests/workaround that might help: 1) Things work fine is @var1 is not declared as a string: ============================================================================== master [localhost] {msandbox} ((none)) > set @var1=0.038687 ;Query OK, 0 rows affected (0.00 sec) master [localhost] {msandbox} ((none)) > select @var1 , if( @var1 = 0 , 1 , @var1 ) as sqlif ;Field 1: `@var1` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: binary (63) Length: 83 Max_length: 8 Decimals: 30 Flags: BINARY Field 2: `sqlif` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: binary (63) Length: 83 Max_length: 8 Decimals: 30 Flags: BINARY +----------+----------+ | @var1 | sqlif | +----------+----------+ | 0.038687 | 0.038687 | +----------+----------+ 1 row in set (0.00 sec) master [localhost] {msandbox} ((none)) > prepare fail_stmt from "select ? , if( ? = 0 , 1 , ? ) as ps_if_fail" ; Query OK, 0 rows affected (0.00 sec) Statement prepared master [localhost] {msandbox} ((none)) > execute fail_stmt using @var1 , @var1 , @var1 ; Field 1: `?` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: binary (63) Length: 9 Max_length: 8 Decimals: 6 Flags: BINARY Field 2: `ps_if_fail` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: binary (63) Length: 9 Max_length: 8 Decimals: 6 Flags: BINARY +----------+------------+ | ? | ps_if_fail | +----------+------------+ | 0.038687 | 0.038687 | +----------+------------+ 1 row in set (0.00 sec) ============================================================================== 2) Things works if we compare against 0.00 in the IF(). Note that 0.0 does not work. ============================================================================== master [localhost] {msandbox} ((none)) > set @var1='0.038687' ; Query OK, 0 rows affected (0.00 sec) master [localhost] {msandbox} ((none)) > select @var1 , if( @var1 = 0 , 1 , @var1 ) as sqlif ; Field 1: `@var1` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: latin1_swedish_ci (8) Length: 8192 Max_length: 8 Decimals: 31 Flags: Field 2: `sqlif` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: latin1_swedish_ci (8) Length: 8192 Max_length: 8 Decimals: 31 Flags: +----------+----------+ | @var1 | sqlif | +----------+----------+ | 0.038687 | 0.038687 | +----------+----------+ 1 row in set (0.00 sec) master [localhost] {msandbox} ((none)) > prepare fail_stmt from "select ? , if( ? = 0.0 , 1 , ? ) as ps_if_fail" ; Query OK, 0 rows affected (0.00 sec) Statement prepared master [localhost] {msandbox} ((none)) > execute fail_stmt using @var1 , @var1 , @var1 ; Field 1: `?` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: latin1_swedish_ci (8) Length: 8 Max_length: 8 Decimals: 0 Flags: NOT_NULL Field 2: `ps_if_fail` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: binary (63) Length: 8 Max_length: 1 Decimals: 0 Flags: NOT_NULL BINARY +----------+------------+ | ? | ps_if_fail | +----------+------------+ | 0.038687 | 1 | +----------+------------+ 1 row in set (0.00 sec) master [localhost] {msandbox} ((none)) > prepare fail_stmt from "select ? , if( ? = 0.00 , 1 , ? ) as ps_if_fail" ; Query OK, 0 rows affected (0.00 sec) Statement prepared master [localhost] {msandbox} ((none)) > execute fail_stmt using @var1 , @var1 , @var1 ; Field 1: `?` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: latin1_swedish_ci (8) Length: 8 Max_length: 8 Decimals: 0 Flags: NOT_NULL Field 2: `ps_if_fail` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: binary (63) Length: 8 Max_length: 8 Decimals: 0 Flags: NOT_NULL BINARY +----------+------------+ | ? | ps_if_fail | +----------+------------+ | 0.038687 | 0.038687 | +----------+------------+ 1 row in set (0.00 sec) master [localhost] {msandbox} ((none)) > ==============================================================================
[8 Jun 2009 12:16]
Leandro Morgado
Last test 3) If we cast the ? parameter in the IF() to a CHAR the comparison fails as expected. ============================================================================== master [localhost] {msandbox} ((none)) > set @var1='0.038687' ; Query OK, 0 rows affected (0.00 sec) master [localhost] {msandbox} ((none)) > select @var1 , if( @var1 = 0 , 1 , @var1 ) as sqlif ; Field 1: `@var1` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: latin1_swedish_ci (8) Length: 8192 Max_length: 8 Decimals: 31 Flags: Field 2: `sqlif` Catalog: `def` Database: `` Table: `` Org_table: `` Type: VAR_STRING Collation: latin1_swedish_ci (8) Length: 8192 Max_length: 8 Decimals: 31 Flags: +----------+----------+ | @var1 | sqlif | +----------+----------+ | 0.038687 | 0.038687 | +----------+----------+ 1 row in set (0.00 sec) master [localhost] {msandbox} ((none)) > prepare fail_stmt from "select ? , if( CAST(? AS SIGNED) = 0 , 1 , ? ) as ps_if_fail" ; Query OK, 0 rows affected (0.00 sec) Statement prepared master [localhost] {msandbox} ((none)) > execute fail_stmt using @var1 , @var1 , @var1 ;Field 1: `?` Catalog: `def` Database: `` Table: ``
[8 Jun 2009 15:49]
John Dzilvelis
Another variation on a work-around is to cast as decimal with the desired precision. prepare pass_stmt from "select if( cast(? as decimal(10,6)) = 0 , 1 , cast( ? as decimal(15,6)) ) as ps_if_pass" ; execute pass_stmt using @var1 , @var1 ;
[28 Mar 2013 16:11]
Paul DuBois
Noted in 5.1.70, 5.5.32, 5.6.12, 5.7.2 changelogs. IF() function evaluations could produce different results when executed in a prepared versus nonprepared statement.