Skip to content

Commit

Permalink
Fix recently-exposed bug in multiquery logic.
Browse files Browse the repository at this point in the history
Any call resets the errno, though it didn't formerly.
  • Loading branch information
kohler committed Jun 24, 2024
1 parent a948125 commit 2b3354a
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 22 deletions.
47 changes: 26 additions & 21 deletions lib/dbl.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,36 +73,38 @@ class Dbl_MultiResult {
private $dblink;
/** @var int */
private $flags;
/** @var 0|1|2|3 */
private $mstate;
/** @var string */
private $query_string;

/** @param int $flags
* @param string $qstr
* @param bool $result */
function __construct(mysqli $dblink, $flags, $qstr, $result) {
* @param bool $mqresult */
function __construct(mysqli $dblink, $flags, $qstr, $mqresult) {
assert(($flags & Dbl::F_MULTI) !== 0);
$this->dblink = $dblink;
$this->flags = $flags | Dbl::F_MULTI | ($result ? Dbl::F_MULTI_OK : 0);
$this->flags = $flags;
$this->mstate = $mqresult ? 2 : 1;
$this->query_string = $qstr;
}
/** @return false|Dbl_Result */
/** @return ?Dbl_Result */
function next() {
// XXX does processing stop at first error?
if ($this->flags & Dbl::F_MULTI_OK) {
$result = $this->dblink->store_result();
} else if ($this->flags & Dbl::F_MULTI) {
$result = false;
} else {
return false;
}
if ($this->dblink->more_results()) {
if ($this->dblink->next_result()) {
$this->flags |= Dbl::F_MULTI_OK;
// maybe load next result from connection
if ($this->mstate === 3) {
if ($this->dblink->more_results()) {
$this->mstate = $this->dblink->next_result() ? 2 : 1;
} else {
$this->flags &= ~Dbl::F_MULTI_OK;
$this->mstate = 0;
}
} else {
$this->flags &= ~(Dbl::F_MULTI | Dbl::F_MULTI_OK);
}
// maybe done
if ($this->mstate === 0) {
return null;
}
// process next result (which might be an error)
$result = $this->mstate === 2 ? $this->dblink->store_result() : false;
$this->mstate = 3;
return Dbl::do_result($this->dblink, $this->flags, $this->query_string, $result);
}
function free_all() {
Expand Down Expand Up @@ -208,7 +210,6 @@ class Dbl {
const F_ERROR = 8;
const F_ALLOWERROR = 16;
const F_MULTI = 32;
const F_MULTI_OK = 64; // internal
const F_ECHO = 128;
const F_NOEXEC = 256;
const F_THROW = 512;
Expand Down Expand Up @@ -605,8 +606,12 @@ static function do_query_on($dblink, $args, $flags) {
return self::do_query_with($dblink, $qstr, $argv, $flags);
}

/** @return Dbl_Result */
static public function do_result($dblink, $flags, $qstr, $result) {
/** @param \mysqli $dblink
* @param int $flags
* @param string $qstr
* @param null|bool|\mysqli_result|Dbl_Result $result
* @return Dbl_Result */
static function do_result($dblink, $flags, $qstr, $result) {
if (is_bool($result)) {
$result = Dbl_Result::make($dblink);
} else if ($result === null) {
Expand Down
18 changes: 17 additions & 1 deletion test/t_unit.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,23 @@ function test_dbl_multiquery() {
xassert_eqq($result->fetch_row(), null);
Dbl::free($result);
$result = $mresult->next();
xassert_eqq($result, false);
xassert(!$result);

$mresult = Dbl::multi_q("select 0 from dual; select 2, 3 from dual; select 1 from dual");
$result = $mresult->next();
xassert($result instanceof mysqli_result);
xassert_array_eqq($result->fetch_row(), ["0"]);
$result->close();
$result = $mresult->next();
xassert($result instanceof mysqli_result);
xassert_array_eqq($result->fetch_row(), ["2", "3"]);
$result->close();
$result = $mresult->next();
xassert($result instanceof mysqli_result);
xassert_array_eqq($result->fetch_row(), ["1"]);
$result->close();
$result = $mresult->next();
xassert(!$result);
}

function test_array_sort_unique() {
Expand Down

0 comments on commit 2b3354a

Please sign in to comment.