php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #37671 MySQLi extension fails to recognize BIT colums
Submitted: 2006-06-02 05:01 UTC Modified: 2006-08-04 22:14 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: squasar at eternalviper dot net Assigned: iliaa (profile)
Status: Closed Package: MySQLi related
PHP Version: 5.2 CVS OS: *
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: squasar at eternalviper dot net
New email:
PHP Version: OS:

 

 [2006-06-02 05:01 UTC] squasar at eternalviper dot net
Description:
------------
When attempting to use MySQLi prepared statements with BIT 
columns, an "unrecognized column type" error is thrown. Here 
is a working patch. I do not know if this is an ideal 
implementation:
A working patch:
Index: ext/mysqli/mysqli_api.c
============================================================
=======
RCS file: /repository/php-src/ext/mysqli/mysqli_api.c,v
retrieving revision 1.118.2.22
diff -u -r1.118.2.22 mysqli_api.c
--- ext/mysqli/mysqli_api.c     5 Apr 2006 12:17:08 -0000       
1.118.2.22
+++ ext/mysqli/mysqli_api.c     2 Jun 2006 04:59:44 -0000
@@ -303,10 +303,13 @@
                                break;
 
                        case MYSQL_TYPE_LONGLONG:
+#ifdef FIELD_TYPE_BIT
+                       case MYSQL_TYPE_BIT:
+#endif
                                stmt->result.buf[ofs].type = 
IS_STRING; 
                                stmt->result.buf[ofs].buflen 
= sizeof(my_ulonglong); 
                                stmt->result.buf[ofs].val = 
(char *)emalloc(stmt->result.buf[ofs].buflen);
-                               bind[ofs].buffer_type = 
MYSQL_TYPE_LONGLONG;
+                               bind[ofs].buffer_type = 
col_type;
                                bind[ofs].buffer = stmt-
>result.buf[ofs].val;
                                bind[ofs].is_null = &stmt-
>result.is_null[ofs];
                                bind[ofs].buffer_length = 
stmt->result.buf[ofs].buflen;
@@ -713,6 +716,11 @@
                                                        } 
else {
                                                                
ZVAL_LONG(stmt->result.vars[i], llval);
                                                        }
+#ifdef FIELD_TYPE_BIT
+                                               } else if 
(stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT) {
+                                                       
llval = *(my_ulonglong *)stmt->result.buf[i].val;
+                                                       
ZVAL_BOOL(stmt->result.vars[i], llval == 0 ? 0 : 1);
+#endif
                                                } else {
                                                        
ZVAL_STRINGL(stmt->result.vars[i], stmt->result.buf[i].val, 
stmt->result.buf[i].buflen, 1);
                                                }


Reproduce code:
---------------
<?php
// Assume that $DATABASE is an open MySQLi connection to a MySQL 5.0.x database
$DATABASE->query( "CREATE TABLE test( test_col BIT NOT NULL )" );
$DATABASE->query( "INSERT INTO test VALUES ( 1, 0, 1, 0 )" );
$statement = $DATABASE->prepare( "SELECT test_col FROM test" );
$statement->execute();
$statement->bind_result( $bits );
while ( $statement->fetch() === TRUE )
 debug_zval_dump( $bits );
$statement->close();
?>

Expected result:
----------------
bool(true) refcount(1)
bool(false) refcount(1)
bool(true) refcount(1)
bool(false) refcount(1)

Actual result:
--------------
Warning: mysqli_stmt::bind_result(): Server returned unknown 
type 16. Probably your client library is incompatible with the 
server version you use! in - on line 8
NULL refcount(1)
NULL refcount(1)
NULL refcount(1)
NULL refcount(1)


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-06-02 05:03 UTC] squasar at eternalviper dot net
The pasted reproduce code is syntactically incorrect. Here 
is the correct version:
<?php
// Assume that $DATABASE is an open MySQLi connection to a 
MySQL 5.0.x database
$DATABASE->query( "CREATE TABLE IF NOT EXISTS test_me 
( test_col BIT NOT NULL )" );
$DATABASE->query( "INSERT INTO test_me VALUES ( 1 ), ( 0 ), 
( 1 ), ( 0 )" );
( $statement = $DATABASE->prepare( "SELECT test_col FROM 
test_me" ) );
$statement->execute();
$statement->bind_result( $bits );
while ( $statement->fetch() === TRUE )
 debug_zval_dump( $bits );
$statement->close();
?>
 [2006-06-02 19:48 UTC] squasar at eternalviper dot net
Further note: The given patch only applies to code which 
assumes that a BIT field is being used as a flag field (i.e. a 
BIT(1) column). For larger BIT fields the patch is 
insufficient.
 [2006-06-02 20:03 UTC] squasar at eternalviper dot net
With apologies for all the extra comments, here is a 
somewhat better patch that allows for arbitrary values in a 
BIT column. However, I do not believe this is ideal for a 
bitfield type.

Index: ext/mysqli/mysqli_api.c
============================================================
=======
RCS file: /repository/php-src/ext/mysqli/mysqli_api.c,v
retrieving revision 1.118.2.22
diff -u -r1.118.2.22 mysqli_api.c
--- ext/mysqli/mysqli_api.c     5 Apr 2006 12:17:08 -0000       
1.118.2.22
+++ ext/mysqli/mysqli_api.c     2 Jun 2006 20:02:17 -0000
@@ -303,10 +303,13 @@
                                break;
 
                        case MYSQL_TYPE_LONGLONG:
+#ifdef FIELD_TYPE_BIT
+                       case MYSQL_TYPE_BIT:
+#endif
                                stmt->result.buf[ofs].type = 
IS_STRING; 
                                stmt->result.buf[ofs].buflen 
= sizeof(my_ulonglong); 
                                stmt->result.buf[ofs].val = 
(char *)emalloc(stmt->result.buf[ofs].buflen);
-                               bind[ofs].buffer_type = 
MYSQL_TYPE_LONGLONG;
+                               bind[ofs].buffer_type = 
col_type;
                                bind[ofs].buffer = stmt-
>result.buf[ofs].val;
                                bind[ofs].is_null = &stmt-
>result.is_null[ofs];
                                bind[ofs].buffer_length = 
stmt->result.buf[ofs].buflen;
@@ -693,7 +696,11 @@
                                                ZVAL_DOUBLE
(stmt->result.vars[i], *(double *)stmt->result.buf[i].val);
                                                break;
                                        case IS_STRING:
-                                               if (stmt-
>stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG) {
+                                               if (stmt-
>stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG
+#ifdef FIELD_TYPE_BIT
+                                                               
|| stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT
+#endif
+                                                       ) {
                                                        
my_bool uns= (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? 
1:0;
                                                        
llval= *(my_ulonglong *) stmt->result.buf[i].val;
 #if SIZEOF_LONG==8
 [2006-06-04 14:57 UTC] iliaa@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 [2006-06-07 04:43 UTC] squasar at eternalviper dot net
The patch applied to CVS does NOT fix the bug. The CVS patch 
folds BIT handling into LONG types. This does not work; BIT 
columns take a 64-bit type, NOT a 32-bit type. Please re-
examine the patch I supplied, which folds BIT handling into 
LONGLONG types.
 [2006-06-07 13:08 UTC] iliaa@php.net
BIT[(M)]

A bit-field type. M indicates the number of bits per value, 
from 1 to 64. The default is 1 if M is omitted.

(From MySQL manual)
 [2006-06-08 06:27 UTC] squasar at eternalviper dot net
That sample from the manual is irrelevant. Re-examine the 
reproduce code I provided. It FAILS using the patch that was 
applied to CVS; the result is always zero regardless of the 
values in the column, even though it's a BIT(1).
 [2006-06-20 20:54 UTC] iliaa@php.net
With latest CVS your code returns the following results:

long(1) refcount(1)
long(0) refcount(1)
long(1) refcount(1)
long(0) refcount(1)
 [2006-06-25 10:25 UTC] squasar at eternalviper dot net
I updated to the latest 5.2 branch on CVS and run the exact 
test code I submitted again. The result:

long(0) refcount(1)
long(0) refcount(1)
long(0) refcount(1)
long(0) refcount(1)

I don't know what one of us is doing wrong. Tested on both 
big-endian and little-endian systems. Could it be a 32-bit 
vs. 64-bit issue?
 [2006-06-25 12:16 UTC] tony2001@php.net
With MySQL 5.0.21 & latest 5_2 CVS I get long(0)'s.

 [2006-07-03 06:55 UTC] judas dot iscariote at gmail dot com
long(0) refcount(1)
long(0) refcount(1)
long(0) refcount(1)
long(0) refcount(1)

Linux 64 bit, current 5_2 CVS, Mysql 5.0.22... 64 bit problem ?
 [2006-08-04 22:14 UTC] iliaa@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 10:01:29 2024 UTC