|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2011-04-01 16:13 UTC] peter dot colclough at toolstation dot com
Description:
------------
Hi, trying to build a generic DB object handler for mySqli, and have hit an issue where we can't have more than one open query on the same connection. Is this a bug or 'expected behaviour'?
Looking at the mysqli.c source code, it looks like it should have been possible, but it looks like the second object overwrites the first...
I have put a sample snippet below of what I am trying to achieve.... if this helps.
Any help greatly appreciated....
OS: 2.6.32-21-generic #32-Ubuntu SMP Fri Apr 16 08:09:38 UTC 2010 x86_64 GNU/Linux
PHP Version => 5.3.2-1ubuntu4.5
Test script:
---------------
-------------- Code Snippet -----------------------------
$sqlstock = 'select foo1 from bar1 where foo1 =?';
$sqltime = 'select foo2, foo3 from bar2 where foo4 =?';
$varinp = "XXXXXXXXXXXX";
$abindVars = array(0=>$varinp);
$varProd = '';
$conn = dbi->db_conn;
$sprod = '';
$timestart = microtime_float();
// Get a statement
$aRes = array();
$aRes2 = array();
// Init 2 Statements
$stmt = mysqli_stmt_init($conn);
$stmt2 = mysqli_stmt_init($conn);
// Prepare 2 statements
mysqli_stmt_prepare($stmt,$sqlstock);
mysqli_stmt_prepare($stmt2,$sqltime);
// Set the bind variable
$varinp = "PXX00019263";
// Bind the statements
mysqli_stmt_bind_param($stmt,'s', &$varinp);
mysqli_stmt_bind_param($stmt2,'s', &$varinp);
// Execute - Second one fails
mysqli_stmt_execute($stmt);
mysqli_stmt_execute($stmt2);
// Set up field Defs
$aFieldDefs = array();
$aFieldDefs2 = array();
// Get result Metadata
$result = mysqli_stmt_result_metadata($stmt);
$result2 = mysqli_stmt_result_metadata($stmt2);
$nCount = 0;
while($aFieldDefs[$nCount] = mysqli_fetch_field($result)){
echo('Field = '.print_r($aFieldDefs, true)."\r\n");
$aRes[$aFieldDefs[$nCount++]->name] = null;
}
$nCount = 0;
while($aFieldDefs2[$nCount] = mysqli_fetch_field($result2)){
echo('Field = '.print_r($aFieldDefs2, true)."\r\n");
$aRes2[$aFieldDefs2[$nCount++]->name] = null;
}
// Bind Results
mysqli_stmt_bind_result($stmt, &$aRes['foo1']);
mysqli_stmt_bind_result($stmt2, &$aRes2['foo2'], &$aRes2['foo3'])
// Fetch Results
mysqli_stmt_fetch($stmt);
mysqli_stmt_fetch($stmt2);
echo(print_r($aRes, true)."\r\n");
echo(print_r($aRes2, true)."\r\n");
--------------- End Code Snippet ----------------------
Expected result:
----------------
Array
(
[foo1] => 'PXX00019263'
)
Array
(
[foo2] => 2009-09-15 12:05:02
[foo3] => 0000-00-00 00:00:00
)
Actual result:
--------------
Array
(
[foo1] =>
)
Array
(
[foo2] => 2009-09-15 12:05:02
[foo3] => 0000-00-00 00:00:00
)
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 19:00:01 2025 UTC |
You can answer this question yourself by adding a bit of error handling to your script such as ... $mysqli = new mysqli("localhost", "root", "root", "test"); $stmt1 = $mysqli->prepare("SELECT 1 AS _one FROM DUAL"); $stmt2 = $mysqli->prepare("SELECT 2 AS _two FROM DUAL"); if (!$stmt1->execute() || !($meta1 = $stmt2->result_metadata())) printf("[001] [%d] %s\n", $stmt1->errno, $stmt1->error); if (!$stmt2->execute() || !($meta2 = $stmt2->result_metadata())) printf("[002] [%d] %s\n", $stmt2->errno, $stmt2->error); ... and the answer is: [002] [2014] Commands out of sync; you can't run this command nowHmm, you can prepare as many statements as you want per connection. But once you have executed a statement on a connection you must fetch its results before you can execute another statement. The result set "blocks" the line. You can, of course, do an implicit fetch on the C level upon execute but that's the exact opposite of the default fetch method (unbuffered) used for prepared statements by MySQL. Its a one-liner to do that fetch in user land. No need for changes on the C level. $mysqli = new mysqli("localhost", "root", "root", "test"); $stmt1 = $mysqli->prepare("SELECT 1 AS _one FROM DUAL"); $stmt2 = $mysqli->prepare("SELECT 2 AS _two FROM DUAL"); /* execute */ if (!$stmt1->execute()) printf("[001] [%d] %s\n", $stmt1->errno, $stmt1->error); /* clear line by fetching result set */ $res1 = $stmt1->get_result(); /* execute */ if (!$stmt2->execute()) printf("[002] [%d] %s\n", $stmt2->errno, $stmt2->error); /* clear line by fetching result set */ $res2 = $stmt2->get_result(); /* fetching second first */ while ($row = $res2->fetch_assoc()) var_dump($row); $res2->free(); while ($row = $res1->fetch_assoc()) var_dump($row); $res1->free();True... but it doesn't do this ($conn is a connection) ... and don't copy this code.. its not good.. but gets the point across: $basesql = 'SELECT SQL_NO_CACHE id from table1 '; $baseqry = bmysqli_query($basesql, $conn); $qry = bmysqli_query('Select SQL_NO_CACHE * from table2 where id2 = ? ',$conn); $qry1 = bmysqli_query('Select SQL_NO_CACHE * from table3 where id3 = ? ',$conn); $qry2 = bmysqli_query('Select SQL_NO_CACHE * from table4 where id4 = ? ',$conn); while(TRUE){ $nBaseRes = bmysqli_fetch($baseqry); if(empty($nBaseRes)){ break; } $aId = array(0 =>$nBaseRes['id']); // The first bound query bmysqli_execute($qry, $aId); $nRes = bmysqli_fetch($qry); $aVals = array(0=>$nRes['id2']); bmysqli_execute($qry1, $aVals); while(TRUE){ // careful Peter $nRes1 = bmysqli_fetch($qry1); if(empty($nRes1)){ break; } $aItems = array(0 => $nRes1['id3']); bmysqli_execute($qry2, $aItems); while(TRUE){ // careful Peter $nRes2 = bmysqli_fetch($qry2); if(empty($nRes2)){ break; } } }