tiny ‘n’ smart
database layer

Odkazy: dibi | API reference

Oznámení

Omlouváme se, provoz fóra byl ukončen

Opakované volání procedur

před 10 lety

MartinJanda
Člen | 63

Dobrý den,
volám ve smyčce uloženou proceduru. První průchod v pořádku, druhý vyvolá:

DibiDriverException #2014
Commands out of sync; you can't run this command now

Proceduru volám klasicky:
dibi::query(„call jmeno_procedury()“);

V čem je přesně problém? Jak to vyřešit nebo obejít?

Díky za každou radu.

před 10 lety

MartinJanda
Člen | 63

Ještě doplním, že jde o database.driver = mysqli

před 10 lety

MartinJanda
Člen | 63

Zatím jsem to provizorně prasácky vyřešil dibi::disconnect() a znovu connect, ale správné řešení by mě zajímalo, protože v projektu, který dělám bude volání procedur časté v rámci jednoho připojení…

před 10 lety

LM
Člen | 206

Zkus to volat takhle:

dibi::query("call jmeno_procedury()")->free();

a koukni na http://dev.mysql.com/…of-sync.html.

před 10 lety

MartinJanda
Člen | 63

Díky za radu. Podívám se na to.

před 10 lety

MartinJanda
Člen | 63

Ten zápis dibi::query("call jmeno_procedury()")->free(); problém řeší u procedur, které nevracejí výsledky.

Jak to správně zapsat, když procedura vrací data? Zkoušel jsem:

$query = dibi::nativeQuery("call jmeno_procedury()");
$data = $query->fetchAll();
$query->free();

Ale při druhém průchodu se znovu objeví DibiDriverException #2014 Commands out of sync; you can't run this command now.

Jak v takovém případě zdroje správně uvolnit z paměti?

před 10 lety

MartinJanda
Člen | 63

Zkoušel jsem využít pdo driver, ale ten nemá implementováno docela dost věcí :-(

Asi budu muset použít samotné PDO.

Každopádně díky LM za pomoc.

před 10 lety

Jod
Člen | 703

Mne tam chýbalo cachovanie query resultov.

před 10 lety

MartinJanda
Člen | 63

No já bych nejraději zůstal u dibi s mysqli driverem, ale to opakované volání procedur (vracejících data) prostě potřebuju a nevím kde je problém/jak to vyřešit :(

před 10 lety

LM
Člen | 206

Ještě jeden odkaz: http://forums.mysql.com/read.php?… , podle všeho CALL v mysql vrací vždy jeden výsledek navíc, info. Což je nešťastné, chce to feature request.

před 10 lety

Ondřej Bouda
Člen | 2

Pro podporu získávání výsledků z volání procedur jsem si napsal rozšíření mysqli driveru, které první výsledek uloží a ostatní zahodí. Funguje docela dobře a i kód by byl docela krátký:

<?php
/**
 * MySqli driver with support for MySQL stored procedures producing result sets.
 *
 * Fetches only the first result set, throws away the others.
 *
 * @uses DibiMySqliDriver
 */
class DibiMySqliProcedureDriver extends DibiMySqliDriver {

    /**
     * Executes the SQL query.
     * If the query is a procedure call, uses mysqli_multi_query and throws away everything after
     * the first result set.
     * @param  string    SQL statement
     * @return DibiDriver|NULL
     * @throws DibiDriverException
     */
    public function query($sql)
    {
        if (!preg_match('#\s*CALL\s(.+)#i', $sql)) {
            return parent::query($sql);
        }

        @mysqli_multi_query($this->connection, $sql); // intentionally @

        if (mysqli_errno($this->connection)) {
            $this->trashMoreResults();
            throw new DibiDriverException(mysqli_error($this->connection), mysqli_errno($this->connection), $sql);
        }

        $this->resultSet = mysqli_store_result($this->connection);
        $this->trashMoreResults();

        return is_object($this->resultSet) ? clone $this : NULL;
    }

    /**
     * Throws away all the remaining results from the most recent query.
     */
    private function trashMoreResults()
    {
        if (mysqli_more_results($this->connection)) {
            while (mysqli_next_result($this->connection));
        }
    }
}

?>

jen kdyby v driveru DibiMySqliDriver atributy connection a resultSet nebyly private :(