<?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 DatajarEngineMysql 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 = $this->parse_conn_string($conn_string);
// OK, trying to open the file.
$this->db = mysql_connect($conn['host'].':'.$conn['port'],
$conn['username'], $conn['password']);
if(!$this->db) {
throw new DatajarException(sprintf("Couldn't connect to database server."));
}
if(!mysql_select_db($conn['database'], $this->db)) {
throw new DatajarException(sprintf("Couldn't open database %s.", $database));
}
$this->errors();
}
public function __destruct()
{
//$this->close();
}
public function close()
{
if($this->db) {
mysql_close($this->db);
$this->db = NULL;
}
}
public static function escape($data)
{
$escaped = mysql_real_escape_string($data);
if($escaped === false) {
return $data;
} else {
return $escaped;
}
}
/**
* Checks MySQL errors. Throws a DatajarException if there was an error
* during the last query.
*/
protected function errors()
{
$error = mysql_errno($this->db);
if($error != 0) {
throw new DatajarException(
mysql_error($this->db),
mysql_error($this->db),
$error);
}
}
/**
* SQLite-specific routine with error check included.
*/
protected function query($statement)
{
$ret = null;
$this->log($statement);
$res = mysql_query($statement, $this->db);
$this->errors();
$table = array();
if(strtoupper(substr(trim($statement), 0, 6)) == "SELECT") {
while($row = mysql_fetch_assoc($res))
{
$table[] = $row;
}
return $table;
}
return true;
}
protected function lastId()
{
return mysql_insert_id($this->db);
}
/**
* 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.= 'DOUBLE';
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 AUTO_INCREMENT, ";
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.= "'" . mysql_real_escape_string ($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.= "'" . mysql_real_escape_string ($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();
$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 $where, $order = false,
$desc = false, array $limit = null)
{
$stmt = "SELECT * FROM `" . $objecttype . '`';
if(is_array($where) && count($where) > 0) {
$stmt.= ' WHERE ' . DatajarSQL::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 function_exists('mysql_connect');
}
}
?>