Databázový layer

Představuji k volnému použití (licence GNU GPL) jednoduchý dababázový layer, který je určen pro MySQL 3.23 až 4.0 (mysql), MySQL 4.1 (mysqli), SQLite a PostgreSQL.

Tento layer je záměrně psán neobjektově. Proč? Je určen pro úpravu starých skriptů, které jsou natvrdo psány pro MySQL 4.0, aby co nejdříve fungovaly s DB-layerem (na libovolné open-source databázi).

Názvy funkcí layeru jsou navrženy tak, aby byly shodné se syntaxí MySQL funkcí, jen místo mysql budete psát sql, tedy například místo mysql_connect budete psát sql_connect. Teoreticky je tak možné na Vašem skriptu udělat hromadný search-and-replace slov mysql_ na sql_, a Vaše aplikace by měla fungovat s DB-layerem.

Pro nový vývoj je samozřejmě vhodnější použít DB-layer objektový, uvedu jej zde zítra.

Zdrojové kódy layeru jsou zde.

Použití layeru pro MySQL:

Typické použití pro MySQL 4.1 bude spočívat ve vytvoření souboru config.php s tímto obsahem:

Příklad pro SQLite:

Prefix tabulek:

Uvedený skript počítá rovněž s prefixem tabulek. Ten je velice důležitý, typicky máte na web-hostingu povolenou jen jednu MySQL/PGSQL databázi, a potom je nezbytně nutné jednotlivé instalace stejné aplikace odlišit právě prefixem v názvech tabulek.

Použití tohoto skriptu?

Náš index.php může vypadat například takto, a bude fungovat na MySQL 4.0, MySQL 4.1, SQLite a PostgreSQL:

Komentáře 18

  1. #1 stv@seznam.cz

    Tvuj strukturalne programovany db layer me konecne prinutil, abych si naprogramoval vlastni db layer objektovy.
    Tak schvalne, jestli je lepsi, nez ten tvuj, co uverejnis zitra 😉 Pak hodim linky.

  2. #2 Vašek

    Z manualu:
    mysql_fetch_assoc() is equivalent to calling mysql_fetch_array() with MYSQL_ASSOC for the optional second parameter.

    Nevidim u tebe potom rozdil ve funkcich
    sql_fetch_array a sql_fetch_assoc

    Dale kdyz uz tam mas escapovani, nema sqlite escapovane apostrofy?

    Opravdu chces uzivatelum pri chybe v query vypisovat, jaky dotaz se nepovedl? 🙂

  3. #3 Radek Hulán autor webu ▲10 ▼0

    [2] sql_fetch_array udělá asociativní pol epodle názvů položek v SELECTu a sql_fetch_assoc podle názvů i podle čísel.. Chce to číst lépe dokumentaci.

    Ohledně chyb v SQL - není důvod, aby aplikace dělala při běhu chyby v SQL, takže ano, je tam výpis natvrdo, a může se objevit jen tehdy, když to programuji..

  4. #4 Michal Tuláček

    Hmm... kdybych nemel se svym projektem komercni zamery, hned bych to bral, ale ta GNU me odrazuje... takze si budu muset napsat vlastni 😄

    Btw: jaky mate kdo nazor na GNU/GPL? Pomaha svobodne tvorbe programu jak byl jeji zamer a nebo skodi? Pac muj nazor je takovy (a nemam ho sam), ze firmy si stejne musi ta reseni napsat samy, pokud nechteji porusit ty licence, takze to trosku ztraci smysl...

  5. #5 Vašek

    [3] Nemůžu si pomoct, ale v manuálu php pro mysql funkce to čtu přesně obráceně, než to říkáš.

    To escapování sglite tam máš, toho jsem si nevšim, promiň.

  6. #6 Radek Hulán autor webu ▲10 ▼0

    [5] máš pravdu, moje chyba, děkuji, opravil jsem to

  7. #7 Marek Fábry

    Chtěl bych doporučit ADODB - něco podobného, podpora větší sady databází. Používám již několik let a díky tomu že pracuji s různými databázemi jsem si ušetřil dost času, přemýšlením nad názvy potřebných funkcí 🙂 Cache výsledků dotazů také není od věci.

    Díky licenci je možné vkládat do komerčních projektů bez nutnosti zveřejnit zdrojové kódy.

    http://adodb.sourceforge.net/

  8. #8 msw

    [3] Chyba je treba i poruseni IO treba UNIQUE (no na MySQL asi nic jinyho ne) a to se imo stavat muze a mela by to zpracovat aplikace (takhle nemuze). Ten SELECT navic by byl casto zbitecny.

    [7] ADODB je pekny ale trochu jinde uz jen tech ~400kB kodu 🙂

    fetch_field by alespon priblizne slo i posgres

    function sql_fetch_field(&$resource, $field_number=0){
    //pgsql $i = pg_num_fields($resource);
    if($field_number<$i)
    {
    $field = array();
    $field['name'] = $name = pg_field_name($resource, $j);
    $field['type'] = pg_field_type($resource, $j);
    $field['max_length'] = pg_field_size($resource, $j); //priblizne ;) return $field;
    }
    else
    {
    return array();
    }

    a pouzivat pro indexy OID mi prijde min prakticke nez tohle 🙂

    sql_insert_id()
    _PGSQL:
    $result = @pg_query($activedb,$query)
    or
    die ("Invalid query: ".htmlspecialchars($query)." <br><br>Error: <b>".sql_error()."</b>");
    if(preg_match("/^\s*INSERT\s+INTO\s+(\w*)/i",$query, $matches))
    {
    global $_pg;
    $_pg = $matches[ 1 ];
    }
    break;
    sql_insert_id(){
    _PGSQL:
    global $_pg; if(!empty($_pg))
    { $result = @pg_query('SELECT currval(\''.$_pg.'_id_'.$_pg.'_seq\')');
    if(empty($result)) return 0;
    else
    {
    $row=pg_fetch_row($result);
    return $row[ 0 ];
    }
    }
    break;

  9. #9 egli

    mysql_fetch_array() je i s parametrem MYSQL_ASSOC o 40% pomalejší než mysql_fetch_assoc()

    Takže používejte pouze mysql_fetch_row() nebo mysql_fetch_assoc()

    Benchmark on a table with 38567 rows:
    mysql_fetch_array:
    MYSQL_BOTH: 6.01940000057 secs
    MYSQL_NUM: 3.22173595428 secs
    MYSQL_ASSOC: 3.92950594425 secs

    mysql_fetch_row: 2.35096800327 secs

    mysql_fetch_assoc: 2.92349803448 secs

  10. #10 Radek Hulán autor webu ▲10 ▼0

    [9] ale ta čísla neříkají naprosto nic..

  11. #11 egli

    V PHP 5 jsou ty rozdíly už menší, když budeme brát mysql_fetch_row jako 100%:

    mysql_fetch_row - 100%
    mysql_fetch_array(MYSQL_NUM) - 113%
    mysql_fetch_assoc - 118%
    mysql_fetch_array(MYSQL_ASSOC) - 127%
    mysql_fetch_array - 150%

    Čili není to už tak výrazné, ale proč nepoužít rychlejší funkci...

  12. #12 Radek Hulán autor webu ▲10 ▼0

    [11] chtěl jsem říci, že alespoň bez znalosti STD a testovacího skriptu, jsou ta čísla jen "vycucaná z prstu"...

  13. #13 Tomáš Kubát

    Upozorňuji na drobnost v ukázkovém config.php souboru. Je zde uvedeno: $SQL_USERNAME;

    Kdežto v definovaných funkcích se používá global $SQL_USER;

  14. #14 Špéťa

    Zdravim,

    jen jsem se chtel zeptat, jak to vypada s tim objektovym resenim DB layer😉? Najek jsem ho nenasel.

    Diky

  15. #15 Vašek

    [14] chytrý student si dodělá za domácí úkol 😉

  16. #16 Jer

    Mohl bych se zeptat, kde je ten slibovany objektovy layer? Nejak ho nemuzu mezi novejsimi clanky najit...

  17. #17 Radek Hulán autor webu ▲10 ▼0

    [16] udělat z toho objekt je práce na 10 minut, proto se mi do toho moc nechce, to zvládne každý sám..

  18. #18 Jakub Bouček

    Tak jsem si to zkušebně převedl a teď bych se chtel podívat, ja to udělá profík, abych zjistil, co musím ještě dohnat... Jinak by to chtělo odstranit ten slib: ", uvedu jej zde zítra".