tiny ‘n’ smart
database layer

Odkazy: dibi | API reference

Oznámení

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

Fatal Error: Wrong parameters for Exception([string $exception … při chybném SQL (Dibi)

před 8 lety

mr.mac
Člen | 87

Při nesprávně vygenerovaném SQL příkazu se objevuje v laděnce chyba (zvýrazněný řádek 43):

Fatal Error

Wrong parameters for Exception([string $exception [, long $code [, Exception $previous = NULL]]]) search►

Source fileFile: C:\xamlite\htdocs\_Libs\Dibi\libs\DibiException.php   Line: 43

36:         * Construct a dibi exception.
37:         * @param  string  Message describing the exception
38:         * @param  int     Some code
39:         * @param  string SQL command
40:         */
41:        public function __construct($message = NULL, $code = 0, $sql = NULL)
42:        {
43:            parent::__construct($message, (int) $code);
44:            $this->sql = $sql;
45:            // TODO: add $profiler->exception($this);
46:        }
47:
48:
49:
50:

Myslím si, že to je nedostatečně ošetřená výjímka při nesprávném SQL, která se objevuje vždy při chybném dotazu. Používám Dibi 1.5rc.
Bohužel v chybné SQL není vidět při použití fireBug profileru.

před 8 lety

Milo
Nette Core | 1119

Uprav si řádek 43 na

parent::__construct($message, (int) $code, NULL);

a zkus.

Edit: Ikdyž je to asi blbost.

Editoval Milo (20. 10. 2011 14:29)

před 8 lety

mr.mac
Člen | 87

Milo napsal(a):

Uprav si řádek 43 na

Měl jsi pravdu, nepomohlo to.

Any idea?

před 8 lety

Milo
Nette Core | 1119

A na jaké databázi a verze PHP? Dej sem kus kódu s tím špatným SQL dotazem…

před 8 lety

mr.mac
Člen | 87

Milo napsal(a):

A na jaké databázi a verze PHP?

Používám MS SQL 2008R2 Express a PHP 5.3. Původní driver mssql.php v dibi mi nechodil, neboť funkce driveru mssql jako např. mssql_query() a podbné nejsou asi už podporovány pro tuto veri SQL DB. Upravil jsem si tedy mssql.php dibi driver na sqlsrv.php driver, který podporuje sqlrv_xxx() funkce PHP 5.3. Vcelku mi vše šlape až asi na nějaké drobnosti (např. teď ladím metodu applyLimit – parametr offset (s vnořeným SELECTem a funkcí ROW_NUMBER()). Asi všechno ale není úplně ok, neboť jakákoli chyba v nette nakonec skočí do chyby exception a debugger mi vypíše mi SQL přílak a za ním chybovou hlášku (výše zníněnou), pokud chyba v běhu programu nenastane, nic se neprojeví.
Příklad takové chyby detailněji vypsané debuggerem:

EXPLAIN SELECT * FROM ( SELECT f.*, d.zkratka [dzkratka], a.ulice [a_ulice], a.cp [a_cp], o.id [a_id_obce],
o.nazev [m_obec], o.psc [m_psc], k.nazev [m_kraj], k.zkratka [m_zkraj], s.nazev [m_stat], s.zkratka [m_zstat],
a.id_kraje [a_id_kraje], a.id_staty [a_id_staty] FROM firmy f LEFT JOIN druhy_firem d ON f.id_druhy_firem=d.id
LEFT JOIN adresy a ON f.id_adresy=a.id
LEFT JOIN obce o ON a.id_obce=o.id
LEFT JOIN kraje k ON a.id_kraje=k.id
LEFT JOIN staty s ON a.id_staty=s.id WHERE f.id=1) t
Fatal error: Wrong parameters for Exception([string $exception [, long $code [, Exception $previous = NULL]]]) in C:\xamlite\htdocs\_Libs\Dibi\libs\DibiException.php on line 45 Call Stack: 0.0012 343432
1. {main}() C:\xamlite\htdocs\nx\www\index.php:0 0.0027 365752
2. require('C:\xamlite\htdocs\nx\app\bootstrap.php') C:\xamlite\htdocs\nx\www\index.php:20 0.0547 6214064
3. Nette\Application\Application->run() C:\xamlite\htdocs\nx\app\bootstrap.php:51 0.0648 7017816
4. Nette\Application\UI\Presenter->run() C:\xamlite\htdocs\_Libs\Nette\Application\Application.php:135 0.0894 8094416
5. Nette\Application\UI\PresenterComponent->tryCall() C:\xamlite\htdocs\_Libs\Nette\Application\UI\Presenter.php:185 0.0897 8095512
6. Nette\Reflection\Method->invokeNamedArgs() C:\xamlite\htdocs\_Libs\Nette\Application\UI\PresenterComponent.php:98 0.0897 8095744
7. ReflectionMethod->invokeArgs() C:\xamlite\htdocs\_Libs\Nette\Reflection\Method.php:57 0.0897 8095760
8. FirmaPresenter->renderDetail() C:\xamlite\htdocs\_Libs\Nette\Reflection\Method.php:57 0.0940 8141720
9. Nette\Diagnostics\Debugger::_errorHandler() C:\xamlite\htdocs\_Libs\Nette\Reflection\Method.php:85 0.0940 8150896
10. Nette\Diagnostics\Debugger::_exceptionHandler() C:\xamlite\htdocs\_Libs\Nette\Diagnostics\Debugger.php:471 0.3915 8265768
11. Nette\Diagnostics\Bar->render() C:\xamlite\htdocs\_Libs\Nette\Diagnostics\Debugger.php:415 0.3927 8271472
12. DibiProfiler->getPanel() C:\xamlite\htdocs\_Libs\Nette\Diagnostics\Bar.php:62 0.3927 8272296
...

Ještě se v tom tak moc neorientuji, abych z toho něco vyčetl. O konkrétní SQl příkaz asi nejde.

Editoval mr.mac (22. 11. 2011 17:44)

před 8 lety

Milo
Nette Core | 1119

Pastni sem řádek z DibiSqlSrvDriver->query() tam kde je throw ± 10 řádků okolo. Resp. zkus upravit:

// DibiExeption:43
parent::__construct($message, (int) $code);
// na
parent::__construct((string) $message, (int) $code);

před 8 lety

mr.mac
Člen | 87

Milo napsal(a):
zkus upravit:

// DibiExeption:43
parent::__construct($message, (int) $code);
// na
parent::__construct((string) $message, (int) $code);

Díky moc Milo za radu – POMOHLO TO – přetypování $message na (string) je to správné řešení, teď mi laděnka krásně vypíše SQL příkaz a hnedle snáz mohu najít chybu. Doporučuji implementovat.

před 8 lety

Milo
Nette Core | 1119

Fajn že jsme k tomu doiterovali. Ona v ostatních drivers chyba není. Tipnul bych si, že do throw new DibiDriverException ve svém driveru předáváš sqlsrv_errors() což vrací pole nebo NULL a ne string ;)

před 8 lety

mr.mac
Člen | 87

Je to přesně tak, moje metoda query vypadá následovně:

public function query($sql){
    $res = @sqlsrv_query($this->connection, $sql);

    if ($res === FALSE) {

        throw new DibiDriverException(sqlsrv_errors(), 0, $sql);

    } elseif (is_resource($res)) {
        return $this->createResultDriver($res);
    }
}

A jak se píše v dokmentaci krom errors sqlsrv_errors()vrací při bezchybném provedení SQL NULL.

Editoval mr.mac (9. 11. 2011 21:05)

před 8 lety

mr.mac
Člen | 87

Ještě jsem sqlsrv.php driver dovylepšil, aby mi laděnka vypisovala úplné info o chybě (psalo to jen slovo Array):

public function query($sql)
{
    $res = @sqlsrv_query($this->connection, $sql);

    if ($res === FALSE) {

        if( ($errors = sqlsrv_errors() ) != null) {
            $msg = '';
            foreach( $errors as $error ) {
                $msg .= "SQLSTATE: ".$error[ 'SQLSTATE'].' >> ';
                $msg .= "code: ".$error[ 'code']." >> ";
                $msg .= "message: ".$error[ 'message']." << ";
            }
        }

        throw new DibiDriverException($msg, 0, $sql);

    } elseif (is_resource($res)) {
        return $this->createResultDriver($res);
    }
}