|
<?php |
|
|
|
namespace PicoDb; |
|
|
|
use Closure; |
|
use PDOException; |
|
use LogicException; |
|
use PicoDb\SQLException; |
|
use PicoDb\Driver\Mssql; |
|
use PicoDb\Driver\Sqlite; |
|
use PicoDb\Driver\Mysql; |
|
use PicoDb\Driver\Postgres; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Database |
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static $instances = array(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected $statementHandler; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private $logs = array(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
private $driver; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function __construct(array $settings = array()) |
|
{ |
|
$this->driver = DriverFactory::getDriver($settings); |
|
$this->statementHandler = new StatementHandler($this); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public function __destruct() |
|
{ |
|
$this->closeConnection(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function setInstance($name, Closure $callback) |
|
{ |
|
self::$instances[$name] = $callback; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static function getInstance($name) |
|
{ |
|
if (! isset(self::$instances[$name])) { |
|
throw new LogicException('No database instance created with that name'); |
|
} |
|
|
|
if (is_callable(self::$instances[$name])) { |
|
self::$instances[$name] = call_user_func(self::$instances[$name]); |
|
} |
|
|
|
return self::$instances[$name]; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function setLogMessage($message) |
|
{ |
|
$this->logs[] = is_array($message) ? var_export($message, true) : $message; |
|
return $this; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function setLogMessages(array $messages) |
|
{ |
|
foreach ($messages as $message) { |
|
$this->setLogMessage($message); |
|
} |
|
|
|
return $this; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function getLogMessages() |
|
{ |
|
return $this->logs; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function getConnection() |
|
{ |
|
return $this->driver->getConnection(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function getDriver() |
|
{ |
|
return $this->driver; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function getLastId() |
|
{ |
|
return (int) $this->driver->getLastId(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function getStatementHandler() |
|
{ |
|
return $this->statementHandler; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public function closeConnection() |
|
{ |
|
$this->driver->closeConnection(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function escapeIdentifier($value, $table = '') |
|
{ |
|
|
|
if (strpos($value, '.') !== false || strpos($value, ' ') !== false) { |
|
return $value; |
|
} |
|
|
|
|
|
if (preg_match('/^[a-z0-9_]+$/', $value) === 0) { |
|
throw new SQLException('Invalid identifier: '.$value); |
|
} |
|
|
|
if (! empty($table)) { |
|
return $this->driver->escape($table).'.'.$this->driver->escape($value); |
|
} |
|
|
|
return $this->driver->escape($value); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function escapeIdentifierList(array $identifiers, $table = '') |
|
{ |
|
foreach ($identifiers as $key => $value) { |
|
$identifiers[$key] = $this->escapeIdentifier($value, $table); |
|
} |
|
|
|
return $identifiers; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function execute($sql, array $values = array()) |
|
{ |
|
return $this->statementHandler |
|
->withSql($sql) |
|
->withPositionalParams($values) |
|
->execute(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function transaction(Closure $callback) |
|
{ |
|
try { |
|
|
|
$this->startTransaction(); |
|
$result = $callback($this); |
|
$this->closeTransaction(); |
|
|
|
return $result === null ? true : $result; |
|
} catch (PDOException $e) { |
|
return $this->statementHandler->handleSqlError($e); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public function startTransaction() |
|
{ |
|
if (! $this->getConnection()->inTransaction()) { |
|
$this->getConnection()->beginTransaction(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public function closeTransaction() |
|
{ |
|
if ($this->getConnection()->inTransaction()) { |
|
$this->getConnection()->commit(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
public function cancelTransaction() |
|
{ |
|
if ($this->getConnection()->inTransaction()) { |
|
$this->getConnection()->rollBack(); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function table($table) |
|
{ |
|
return new Table($this, $table); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function hashtable($table) |
|
{ |
|
return new Hashtable($this, $table); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function largeObject($table) |
|
{ |
|
return new LargeObject($this, $table); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public function schema($namespace = null) |
|
{ |
|
$schema = new Schema($this); |
|
|
|
if ($namespace !== null) { |
|
$schema->setNamespace($namespace); |
|
} |
|
|
|
return $schema; |
|
} |
|
} |
|
|