Odkazy: dibi | API reference

Forum: [česky] [english]

dibi fórum

tiny ‘n’ smart
database layer

Nejste přihlášen(a)

#1 před 2 lety

krajaac
Člen
Registrovaný: 9. 10. 2008
Příspěvky: 48

Feature request – loadFile a nepovinný paramater $delimiter

Jelikož je někdy i v MySQL nutné používat rutiny (a to jak funkce tak procedůry), hodilo by se nějakým způsobem zautomatizovat jejich vytváření/úpravu/likvidaci.

Standartně se rutiny v MySQL dají vytvářet tímto způsobem (přes cli):

delimiter //

CREATE PROCEDURE simpleproc1 (OUT param1 INT)
  BEGIN
  SELECT COUNT(*) INTO param1 FROM t1;
END//

CREATE PROCEDURE simpleproc2 (OUT param1 INT)
  BEGIN
  SELECT COUNT(*) INTO param1 FROM t2;
END//

Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;

V API php ovšem není možné používat příkaz DELIMITER a tak nelze výše uvedený kód přímo importovat do DB přes dibi::loadFile() ani přes phpMyAdmina. Nadruhou stranu, když se celý kód vytváření rutiny provede v jednom query příkazu, není delimiter potřeba a rutina se úspěšne vytvoří:

<?php
dibi::query("
        CREATE PROCEDURE simpleproc (OUT param1 INT)
        BEGIN
                SELECT COUNT(*) INTO param1 FROM t;
        END
");
?>

Čímž se dostáváme k možnosti podpory importu rutin přes dibi::loadFile. Aby import proběhl správně, je nutné sql skript správně rozparsovat, a jednotlivé části provést. V současnosti se parsování provádí pomocí napevno nastaveného oddělovače ;, takže se samotný příkaz pro vytvoření rutiny rozseká a nešťastná MySQL to vůbec nepobere. Se středníky v těle rutiny se sice nic dělat nedá, ale s těmi mimo tělo ano – můžeme je nahradit jiným znakem/znaky a podle něj v dibi::loadFile skript parsovat. Samozřejmě, ja pak nutné tento nestandartní oddělovač z sql query vynechat. Po úpravách by samotná funkce loadFile mohla vypadat nějak takto:

<?php
        public function loadFile($file, $delimiter = ';')
        {
                $this->connect();

                @set_time_limit(0); // intentionally @

                $handle = @fopen($file, 'r'); // intentionally @
                if (!$handle) {
                        throw new FileNotFoundException("Cannot open file '$file'.");
                }

                $count = 0;
                $sql = '';
                while (!feof($handle)) {
                        $s = fgets($handle);
                        $sql .= $s;
                        if (substr(rtrim($s), -strlen($delimiter)) === $delimiter) {
                                $sql = substr(rtrim($sql), 0, -strlen($delimiter)); // delimiter se vynecha
                                $this->driver->query($sql);
                                $sql = '';
                                $count++;
                        }
                }
                fclose($handle);
                return $count;
        }
?>

Myslím si, že by nebylo od věci tuhle funkčnost implmenetovat přímo do dibi, opravdu hodně to import procedůr a funkcí usnadní :) Nicméně si nejsem jistý tím, jak je to v případě databází jiných než MySQL a jak se jim bude líbit vynechání delimiteru (;). Výše uvedený kód jsem testoval s MySQL 5.0.51 a byl plně funkční.

Co vy na to?

 

Zápatí