Location: PHPKode > projects > Movim > movim-0.5/system/Datajar/drivers/DatajarEngineSqlite.php
<?php

/**
 * @file DatajarEngine.php
 *
 * @brief Implements a datajar driver for sqlite.
 *
 * Copyright © 2012 Guillaume Pasquet
 *
 * This file is part of Datajar.
 *
 * Datajar is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 *
 * Datajar is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Datajar.  If not, see <http://www.gnu.org/licenses/>.
 */

class DatajarEngineSqlite extends DatajarEngineBase
{
    protected $db;

    // Loading config and attempting to connect.
    public function __construct($conn = "")
    {
        $args = func_get_args();
        if($conn != "") {
            $this->init($conn);
        }
    }

    public function init($conn_string)
    {
        $conn_details = $this->parse_conn_string($conn_string);

        $db_file = $conn_details['database'];

        // Checking the file can be accessed.
        if($db_file == "") {
            throw new DatajarException(t("The database file must be specified."));
        }

        // OK, trying to open the file.
        $this->db = new SQLite3($db_file);

        if(!$this->db) {
            throw new DatajarException(t("The database %s couldn't be opened.", $db_file));
        }

        $this->db->busyTimeout(30000); // 30s lock timeout.
    }

    public static function escape($data) {
        return SQLite3::escapeString($data);
    }

    public function __destruct()
    {
        //$this->close();
    }

    public function close()
    {
        if($this->db) {
            $this->db->close();
            $this->db = NULL;
        }
    }

    /**
     * Checks SQLite errors. Throws a DatajarException if there was an error
     * during the last query.
     */
    protected function errors()
    {
        $error = $this->db->lastErrorCode();
        if($error != 0) {
            throw new DatajarException(
                t(" `%s'", $db_file),
                $this->db->lastErrorMsg(),
                $error);
        }
    }

    /**
     * SQLite-specific routine with error check included.
     */
    protected function query($statement)
    {
        $ret = null;

        $this->log($statement);

        if(strtoupper(substr(trim($statement), 0, 6)) == "SELECT") {
            $res = $this->db->query($statement);
            $this->errors();

            $table = array();
            while($row = $res->fetchArray(SQLITE3_ASSOC))
            {
                $table[] = $row;
            }
            return $table;
        } else {
            $answer = $this->db->exec($statement);
            $this->errors();
            return $answer;
        }
    }

    protected function lastId()
    {
        return $this->db->lastInsertRowId();
    }

    /**
     * Generates the creation statement.
     */
    protected function create_stmt(&$type)
    {
        $typename = $type['val']->gettype();
        $def = $type['name'] . ' ';
        switch($typename) {
        case 'DatajarTypeBigInt':
            $def.= 'BIGINT';
            break;
        case 'DatajarTypeBool':
            $def.= 'BOOLEAN';
            break;
        case 'DatajarTypeVarChar':
            $def.= 'VARCHAR('.$type['val']->length.')';
            break;
        case 'DatajarTypeDate':
            $def.= 'DATE';
            break;
        case 'DatajarTypeDateTime':
            $def.= 'DATETIME';
            break;
        case 'DatajarTypeDecimal':
            $def.= 'DECIMAL('.$type['val']->length.', '.$type['val']->decimal_places.')';
            break;
        case 'DatajarTypeFloat':
            $def.= 'FLOAT';
            break;
        case 'DatajarTypeInt':
            $def.= 'INTEGER';
            break;
        case 'DatajarTypeText':
            $def.= 'TEXT';
            break;
        case 'DatajarTypeBlob':
            $def.= 'BLOB';
            break;
        case 'DatajarTypeForeignKey':
            $def.= 'INTEGER NOT NULL REFERENCES '.$type['val']->model.'('.$type['val']->field.')';
            break;
        }

        return $def;
    }

    public function create($object)
    {
        $this->require_datajar($object);

        $proto = $object->prototype();

        $stmt = 'CREATE TABLE IF NOT EXISTS "'.$this->obj_name($object).'" ('.
            '"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ';
        foreach($proto as $prop) {
            $stmt .= $this->create_stmt($prop) . ', ';
        }

        // Stripping the extra ', ' and closing the statement.
        $stmt = substr($stmt, 0, -2) . ');';

        return $this->query($stmt);
    }

    public function save($object)
    {
        $this->require_datajar($object);

        $stmt = "";

        $props = $object->prototype();

        if(!$object->id) {
            $stmt = "INSERT INTO " . $this->obj_name($object);

            $cols = "";
            $vals = "";
            foreach($props as $prop) {
                $cols.= $prop['name'] . ', ';
                if(DatajarEngineBase::does_extend($prop['val'], "DatajarBase")) {
                    $vals.= '"' . $prop['val']->id . '", ';
                } else {
                    $vals.= '"' . $prop['val']->getval() . '", ';
                }
            }

            $stmt.= '(' . substr($cols, 0, -2) . ')';
            $stmt.= ' VALUES(' . substr($vals, 0, -2) . ');';

            $this->query($stmt);
            $object->setid($this->lastId());
        } else {
            $stmt = "UPDATE " . $this->obj_name($object) . " SET ";

            $cols = "";
            $vals = "";
            foreach($props as $prop) {
                $stmt.= $prop['name'] . '=';
                if(DatajarEngineBase::does_extend($prop['val'], "DatajarBase")) {
                    $stmt.= '"' . $prop['val']->id . '", ';
                } else {
                    $stmt.= '"' . $prop['val']->getval() . '", ';
                }
            }

            $stmt = substr($stmt, 0, -2) . ' WHERE id="' . $object->id . '"';

            return $this->query($stmt);
        }
    }

    public function delete($object)
    {
        $this->require_datajar($object);

        // Does the object exist in the datajar?
        if($object->id) {
            $stmt = "DELETE FROM " . $this->obj_name($object) . " WHERE id=\"" . $object->id . "\";";

            $result = $this->query($stmt);

            if($result) {
                $object->clearid();
            }

            return $result;
        }
    }

    public function drop($object)
    {
        $this->require_datajar($object);

        $stmt = 'DROP TABLE IF EXISTS '.$this->obj_name($object).';';

        $result = $this->query($stmt);

        if($result) {
            $object->clearid();
        }

        return $result;
    }

    /**
     * Returns data relative to an object as an array.
     */
    public function load($object, array $cond)
    {
        $stmt = "SELECT * FROM " . $this->obj_name($object);

        if(count($cond) > 0) {
            $stmt.= " WHERE ";

            foreach($cond as $col => $val) {
                $stmt.= "$col=\"$val\" AND ";
            }

            // Stripping the extra " AND "
            $stmt = substr($stmt, 0, -5) . ';';
        }

        $this->log($stmt);

        $data = $this->query($stmt);

        if(count($data) < 1) {
            return false;
        }

        $data = $data[0];

        // Populating the object.
        $props = $object->prototype();

        // Setting the id first.
        $object->setid($data['id']);

        foreach($props as $prop) {
            if(isset($data[$prop['name']])) {
                $object->__set($prop['name'], $data[$prop['name']]);
            }
        }

        return true;
    }

    public function run($query)
    {

        return $this->select($query->get_object(),
                             $query->get_cond(),
                             $query->get_orderby(),
                             $query->get_desc(),
                             $query->get_limit());
    }

    /**
     * Loads a bunch of objects of a given type.
     */
    public function select($objecttype, array $cond, $order = false,
                           $desc = false, array $limit = null)
    {
        $stmt = "SELECT * FROM " . $objecttype;

	if(is_array($where) && count($where) > 0) {
	    $stmt = ' WHERE ' . Datajar::gen_where($where, "'", "", array($this, 'escape'));
        }

        if($order) {
            $stmt .= " ORDER BY " . $order;
            if($desc) {
                $stmt .= " DESC";
            }
        }

        if(is_array($limit) && count($limit) == 2) {
            $stmt .= " LIMIT " . $limit[0] . ", " . $limit[1];
        }

        $this->log($stmt);

        $data = $this->query($stmt);

        if(count($data) < 1) {
            return false;
        }

        $objs = array();

        foreach($data as $row) {
            $object = new $objecttype();
            // Populating the object.
            $props = $object->prototype();

            $object->setid($row['id']);

            foreach($props as $prop) {
                if(isset($row[$prop['name']])) {
                    $object->__set($prop['name'], $row[$prop['name']]);
                }
            }

            $objs[] = $object;
        }

        return $objs;
    }

    function test_backend()
    {
        return class_exists('SQLite3');
    }
}

?>
Return current item: Movim