1
0
mirror of https://github.com/dg/dibi.git synced 2025-08-13 01:24:06 +02:00

code formatting: 4 spaces -> tabs

This commit is contained in:
David Grudl
2008-05-12 00:30:59 +00:00
parent fd22c55639
commit 7bb5684d71
37 changed files with 5309 additions and 5309 deletions

View File

@@ -29,434 +29,434 @@
*/
class DibiConnection extends /*Nette::*/Object
{
/**
* Current connection configuration.
* @var array
*/
private $config;
/**
* IDibiDriver.
* @var array
*/
private $driver;
/**
* Is connected?
* @var bool
*/
private $connected = FALSE;
/**
* Is in transaction?
* @var bool
*/
private $inTxn = FALSE;
/**
* Creates object and (optionally) connects to a database.
*
* @param array|string|Nette::Collections::IMap connection parameters
* @param string connection name
* @throws DibiException
*/
public function __construct($config, $name = NULL)
{
// DSN string
if (is_string($config)) {
parse_str($config, $config);
} elseif ($config instanceof /*Nette::Collections::*/IMap) {
$config = $config->toArray();
} elseif (!is_array($config)) {
throw new InvalidArgumentException('Configuration must be array, string or Nette::Collections::IMap.');
}
if (!isset($config['driver'])) {
$config['driver'] = dibi::$defaultDriver;
}
$driver = preg_replace('#[^a-z0-9_]#', '_', $config['driver']);
$class = "Dibi" . $driver . "Driver";
if (!class_exists($class, FALSE)) {
include_once __FILE__ . "/../../drivers/$driver.php";
if (!class_exists($class, FALSE)) {
throw new DibiException("Unable to create instance of dibi driver class '$class'.");
}
}
$config['name'] = $name;
$this->config = $config;
$this->driver = new $class;
if (empty($config['lazy'])) {
$this->connect();
}
}
/**
* Automatically frees the resources allocated for this result set.
*
* @return void
*/
public function __destruct()
{
// disconnects and rolls back transaction - do not rely on auto-disconnect and rollback!
$this->disconnect();
}
/**
* Connects to a database.
*
* @return void
*/
final protected function connect()
{
if (!$this->connected) {
$this->driver->connect($this->config);
$this->connected = TRUE;
dibi::notify($this, 'connected');
}
}
/**
* Disconnects from a database.
*
* @return void
*/
final public function disconnect()
{
if ($this->connected) {
if ($this->inTxn) {
$this->rollback();
}
$this->driver->disconnect();
$this->connected = FALSE;
dibi::notify($this, 'disconnected');
}
}
/**
* Returns configuration variable. If no $key is passed, returns the entire array.
*
* @see self::__construct
* @param string
* @param mixed default value to use if key not found
* @return mixed
*/
final public function getConfig($key = NULL, $default = NULL)
{
if ($key === NULL) {
return $this->config;
} elseif (isset($this->config[$key])) {
return $this->config[$key];
} else {
return $default;
}
}
/**
* Apply configuration alias or default values.
*
* @param array connect configuration
* @param string key
* @param string alias key
* @return void
*/
public static function alias(&$config, $key, $alias=NULL)
{
if (isset($config[$key])) return;
if ($alias !== NULL && isset($config[$alias])) {
$config[$key] = $config[$alias];
unset($config[$alias]);
} else {
$config[$key] = NULL;
}
}
/**
* Returns the connection resource.
*
* @return resource
*/
final public function getResource()
{
return $this->driver->getResource();
}
/**
* Generates (translates) and executes SQL query.
*
* @param array|mixed one or more arguments
* @return DibiResult Result set object (if any)
* @throws DibiException
*/
final public function query($args)
{
$args = func_get_args();
$this->connect();
$trans = new DibiTranslator($this->driver);
if ($trans->translate($args)) {
return $this->nativeQuery($trans->sql);
} else {
throw new DibiException('SQL translate error: ' . $trans->sql);
}
}
/**
* Generates and prints SQL query.
*
* @param array|mixed one or more arguments
* @return bool
*/
final public function test($args)
{
$args = func_get_args();
$this->connect();
$trans = new DibiTranslator($this->driver);
$ok = $trans->translate($args);
dibi::dump($trans->sql);
return $ok;
}
/**
* Executes the SQL query.
*
* @param string SQL statement.
* @return DibiResult Result set object (if any)
* @throws DibiException
*/
final public function nativeQuery($sql)
{
$this->connect();
dibi::$numOfQueries++;
dibi::$sql = $sql;
dibi::$elapsedTime = FALSE;
$time = -microtime(TRUE);
dibi::notify($this, 'beforeQuery', $sql);
$res = $this->driver->query($sql) ? new DibiResult(clone $this->driver, $this->config) : TRUE; // backward compatibility - will be changed to NULL
$time += microtime(TRUE);
dibi::$elapsedTime = $time;
dibi::$totalTime += $time;
dibi::notify($this, 'afterQuery', $res);
return $res;
}
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
*
* @return int number of rows
* @throws DibiException
*/
public function affectedRows()
{
$rows = $this->driver->affectedRows();
if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows.');
return $rows;
}
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
*
* @param string optional sequence name
* @return int
* @throws DibiException
*/
public function insertId($sequence = NULL)
{
$id = $this->driver->insertId($sequence);
if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.');
return (int) $id;
}
/**
* Begins a transaction (if supported).
* @return void
*/
public function begin()
{
$this->connect();
if ($this->inTxn) {
throw new DibiException('There is already an active transaction.');
}
$this->driver->begin();
$this->inTxn = TRUE;
dibi::notify($this, 'begin');
}
/**
* Commits statements in a transaction.
* @return void
*/
public function commit()
{
if (!$this->inTxn) {
throw new DibiException('There is no active transaction.');
}
$this->driver->commit();
$this->inTxn = FALSE;
dibi::notify($this, 'commit');
}
/**
* Rollback changes in a transaction.
* @return void
*/
public function rollback()
{
if (!$this->inTxn) {
throw new DibiException('There is no active transaction.');
}
$this->driver->rollback();
$this->inTxn = FALSE;
dibi::notify($this, 'rollback');
}
/**
* Escapes the string.
*
* @param string unescaped string
* @return string escaped and optionally quoted string
*/
public function escape($value)
{
$this->connect(); // MySQL & PDO require connection
return $this->driver->format($value, dibi::FIELD_TEXT);
}
/**
* Delimites identifier (table's or column's name, etc.).
*
* @param string identifier
* @return string delimited identifier
*/
public function delimite($value)
{
return $this->driver->format($value, dibi::IDENTIFIER);
}
/**
* Injects LIMIT/OFFSET to the SQL query.
*
* @param string &$sql The SQL query that will be modified.
* @param int $limit
* @param int $offset
* @return void
*/
public function applyLimit(&$sql, $limit, $offset)
{
$this->driver->applyLimit($sql, $limit, $offset);
}
/**
* Import SQL dump from file - extreme fast!
*
* @param string filename
* @return int count of sql commands
*/
public function loadFile($file)
{
$this->connect();
@set_time_limit(0);
$handle = @fopen($file, 'r');
if (!$handle) {
throw new FileNotFoundException("Cannot open file '$file'.");
}
$count = 0;
$sql = '';
while (!feof($handle)) {
$s = fgets($handle);
$sql .= $s;
if (substr(rtrim($s), -1) === ';') {
$this->driver->query($sql);
$sql = '';
$count++;
}
}
fclose($handle);
return $count;
}
/**
* Gets a information of the current database.
*
* @return DibiReflection
*/
public function getDibiReflection()
{
throw new NotImplementedException;
}
/**
* Prevents unserialization.
*/
public function __wakeup()
{
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.');
}
/**
* Prevents serialization.
*/
public function __sleep()
{
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.');
}
/**
* Current connection configuration.
* @var array
*/
private $config;
/**
* IDibiDriver.
* @var array
*/
private $driver;
/**
* Is connected?
* @var bool
*/
private $connected = FALSE;
/**
* Is in transaction?
* @var bool
*/
private $inTxn = FALSE;
/**
* Creates object and (optionally) connects to a database.
*
* @param array|string|Nette::Collections::IMap connection parameters
* @param string connection name
* @throws DibiException
*/
public function __construct($config, $name = NULL)
{
// DSN string
if (is_string($config)) {
parse_str($config, $config);
} elseif ($config instanceof /*Nette::Collections::*/IMap) {
$config = $config->toArray();
} elseif (!is_array($config)) {
throw new InvalidArgumentException('Configuration must be array, string or Nette::Collections::IMap.');
}
if (!isset($config['driver'])) {
$config['driver'] = dibi::$defaultDriver;
}
$driver = preg_replace('#[^a-z0-9_]#', '_', $config['driver']);
$class = "Dibi" . $driver . "Driver";
if (!class_exists($class, FALSE)) {
include_once __FILE__ . "/../../drivers/$driver.php";
if (!class_exists($class, FALSE)) {
throw new DibiException("Unable to create instance of dibi driver class '$class'.");
}
}
$config['name'] = $name;
$this->config = $config;
$this->driver = new $class;
if (empty($config['lazy'])) {
$this->connect();
}
}
/**
* Automatically frees the resources allocated for this result set.
*
* @return void
*/
public function __destruct()
{
// disconnects and rolls back transaction - do not rely on auto-disconnect and rollback!
$this->disconnect();
}
/**
* Connects to a database.
*
* @return void
*/
final protected function connect()
{
if (!$this->connected) {
$this->driver->connect($this->config);
$this->connected = TRUE;
dibi::notify($this, 'connected');
}
}
/**
* Disconnects from a database.
*
* @return void
*/
final public function disconnect()
{
if ($this->connected) {
if ($this->inTxn) {
$this->rollback();
}
$this->driver->disconnect();
$this->connected = FALSE;
dibi::notify($this, 'disconnected');
}
}
/**
* Returns configuration variable. If no $key is passed, returns the entire array.
*
* @see self::__construct
* @param string
* @param mixed default value to use if key not found
* @return mixed
*/
final public function getConfig($key = NULL, $default = NULL)
{
if ($key === NULL) {
return $this->config;
} elseif (isset($this->config[$key])) {
return $this->config[$key];
} else {
return $default;
}
}
/**
* Apply configuration alias or default values.
*
* @param array connect configuration
* @param string key
* @param string alias key
* @return void
*/
public static function alias(&$config, $key, $alias=NULL)
{
if (isset($config[$key])) return;
if ($alias !== NULL && isset($config[$alias])) {
$config[$key] = $config[$alias];
unset($config[$alias]);
} else {
$config[$key] = NULL;
}
}
/**
* Returns the connection resource.
*
* @return resource
*/
final public function getResource()
{
return $this->driver->getResource();
}
/**
* Generates (translates) and executes SQL query.
*
* @param array|mixed one or more arguments
* @return DibiResult Result set object (if any)
* @throws DibiException
*/
final public function query($args)
{
$args = func_get_args();
$this->connect();
$trans = new DibiTranslator($this->driver);
if ($trans->translate($args)) {
return $this->nativeQuery($trans->sql);
} else {
throw new DibiException('SQL translate error: ' . $trans->sql);
}
}
/**
* Generates and prints SQL query.
*
* @param array|mixed one or more arguments
* @return bool
*/
final public function test($args)
{
$args = func_get_args();
$this->connect();
$trans = new DibiTranslator($this->driver);
$ok = $trans->translate($args);
dibi::dump($trans->sql);
return $ok;
}
/**
* Executes the SQL query.
*
* @param string SQL statement.
* @return DibiResult Result set object (if any)
* @throws DibiException
*/
final public function nativeQuery($sql)
{
$this->connect();
dibi::$numOfQueries++;
dibi::$sql = $sql;
dibi::$elapsedTime = FALSE;
$time = -microtime(TRUE);
dibi::notify($this, 'beforeQuery', $sql);
$res = $this->driver->query($sql) ? new DibiResult(clone $this->driver, $this->config) : TRUE; // backward compatibility - will be changed to NULL
$time += microtime(TRUE);
dibi::$elapsedTime = $time;
dibi::$totalTime += $time;
dibi::notify($this, 'afterQuery', $res);
return $res;
}
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
*
* @return int number of rows
* @throws DibiException
*/
public function affectedRows()
{
$rows = $this->driver->affectedRows();
if (!is_int($rows) || $rows < 0) throw new DibiException('Cannot retrieve number of affected rows.');
return $rows;
}
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
*
* @param string optional sequence name
* @return int
* @throws DibiException
*/
public function insertId($sequence = NULL)
{
$id = $this->driver->insertId($sequence);
if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.');
return (int) $id;
}
/**
* Begins a transaction (if supported).
* @return void
*/
public function begin()
{
$this->connect();
if ($this->inTxn) {
throw new DibiException('There is already an active transaction.');
}
$this->driver->begin();
$this->inTxn = TRUE;
dibi::notify($this, 'begin');
}
/**
* Commits statements in a transaction.
* @return void
*/
public function commit()
{
if (!$this->inTxn) {
throw new DibiException('There is no active transaction.');
}
$this->driver->commit();
$this->inTxn = FALSE;
dibi::notify($this, 'commit');
}
/**
* Rollback changes in a transaction.
* @return void
*/
public function rollback()
{
if (!$this->inTxn) {
throw new DibiException('There is no active transaction.');
}
$this->driver->rollback();
$this->inTxn = FALSE;
dibi::notify($this, 'rollback');
}
/**
* Escapes the string.
*
* @param string unescaped string
* @return string escaped and optionally quoted string
*/
public function escape($value)
{
$this->connect(); // MySQL & PDO require connection
return $this->driver->format($value, dibi::FIELD_TEXT);
}
/**
* Delimites identifier (table's or column's name, etc.).
*
* @param string identifier
* @return string delimited identifier
*/
public function delimite($value)
{
return $this->driver->format($value, dibi::IDENTIFIER);
}
/**
* Injects LIMIT/OFFSET to the SQL query.
*
* @param string &$sql The SQL query that will be modified.
* @param int $limit
* @param int $offset
* @return void
*/
public function applyLimit(&$sql, $limit, $offset)
{
$this->driver->applyLimit($sql, $limit, $offset);
}
/**
* Import SQL dump from file - extreme fast!
*
* @param string filename
* @return int count of sql commands
*/
public function loadFile($file)
{
$this->connect();
@set_time_limit(0);
$handle = @fopen($file, 'r');
if (!$handle) {
throw new FileNotFoundException("Cannot open file '$file'.");
}
$count = 0;
$sql = '';
while (!feof($handle)) {
$s = fgets($handle);
$sql .= $s;
if (substr(rtrim($s), -1) === ';') {
$this->driver->query($sql);
$sql = '';
$count++;
}
}
fclose($handle);
return $count;
}
/**
* Gets a information of the current database.
*
* @return DibiReflection
*/
public function getDibiReflection()
{
throw new NotImplementedException;
}
/**
* Prevents unserialization.
*/
public function __wakeup()
{
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.');
}
/**
* Prevents serialization.
*/
public function __sleep()
{
throw new NotSupportedException('You cannot serialize or unserialize ' . $this->getClass() . ' instances.');
}
}

View File

@@ -29,64 +29,64 @@
*/
class DibiDataSource extends /*Nette::*/Object implements IDataSource
{
/** @var DibiConnection */
private $connection;
/** @var DibiConnection */
private $connection;
/** @var string */
private $sql;
/** @var string */
private $sql;
/** @var int */
private $count;
/** @var int */
private $count;
/**
* @param string SQL command or table name, as data source
* @param DibiConnection connection
*/
public function __construct($sql, DibiConnection $connection = NULL)
{
if (strpos($sql, ' ') === FALSE) {
// table name
$this->sql = $sql;
} else {
// SQL command
$this->sql = '(' . $sql . ') AS [source]';
}
/**
* @param string SQL command or table name, as data source
* @param DibiConnection connection
*/
public function __construct($sql, DibiConnection $connection = NULL)
{
if (strpos($sql, ' ') === FALSE) {
// table name
$this->sql = $sql;
} else {
// SQL command
$this->sql = '(' . $sql . ') AS [source]';
}
$this->connection = $connection === NULL ? dibi::getConnection() : $connection;
}
$this->connection = $connection === NULL ? dibi::getConnection() : $connection;
}
/**
* @param int offset
* @param int limit
* @param array columns
* @return ArrayIterator
*/
public function getIterator($offset = NULL, $limit = NULL, $cols = NULL)
{
return $this->connection->query('
SELECT *
FROM', $this->sql, '
%ofs %lmt', $offset, $limit
);
}
/**
* @param int offset
* @param int limit
* @param array columns
* @return ArrayIterator
*/
public function getIterator($offset = NULL, $limit = NULL, $cols = NULL)
{
return $this->connection->query('
SELECT *
FROM', $this->sql, '
%ofs %lmt', $offset, $limit
);
}
/**
* @return int
*/
public function count()
{
if ($this->count === NULL) {
$this->count = $this->connection->query('
SELECT COUNT(*) FROM', $this->sql
)->fetchSingle();
}
return $this->count;
}
/**
* @return int
*/
public function count()
{
if ($this->count === NULL) {
$this->count = $this->connection->query('
SELECT COUNT(*) FROM', $this->sql
)->fetchSingle();
}
return $this->count;
}
}

View File

@@ -44,116 +44,116 @@ class DibiException extends Exception
*/
class DibiDriverException extends DibiException implements /*Nette::*/IDebuggable
{
/** @var string */
private static $errorMsg;
/** @var string */
private static $errorMsg;
/** @var string */
private $sql;
/** @var string */
private $sql;
/**
* Construct an dibi driver exception.
/**
* Construct an dibi driver exception.
*
* @param string Message describing the exception
* @param int Some code
* @param string SQL command
* @param string SQL command
*/
public function __construct($message = NULL, $code = 0, $sql = NULL)
{
parent::__construct($message, (int) $code);
$this->sql = $sql;
dibi::notify(NULL, 'exception', $this);
}
public function __construct($message = NULL, $code = 0, $sql = NULL)
{
parent::__construct($message, (int) $code);
$this->sql = $sql;
dibi::notify(NULL, 'exception', $this);
}
/**
* @return string The SQL passed to the constructor
/**
* @return string The SQL passed to the constructor
*/
final public function getSql()
{
return $this->sql;
}
final public function getSql()
{
return $this->sql;
}
/**
* @return string string represenation of exception with SQL command
*/
public function __toString()
{
return parent::__toString() . ($this->sql ? "\nSQL: " . $this->sql : '');
}
/**
* @return string string represenation of exception with SQL command
*/
public function __toString()
{
return parent::__toString() . ($this->sql ? "\nSQL: " . $this->sql : '');
}
/********************* interface Nette::IDebuggable ****************d*g**/
/********************* interface Nette::IDebuggable ****************d*g**/
/**
* Returns custom panels.
* @return array
*/
public function getPanels()
{
$panels = array();
if ($this->sql !== NULL) {
$panels['SQL'] = array(
'expanded' => TRUE,
'content' => dibi::dump($this->sql, TRUE),
);
}
return $panels;
}
/**
* Returns custom panels.
* @return array
*/
public function getPanels()
{
$panels = array();
if ($this->sql !== NULL) {
$panels['SQL'] = array(
'expanded' => TRUE,
'content' => dibi::dump($this->sql, TRUE),
);
}
return $panels;
}
/********************* error catching ****************d*g**/
/********************* error catching ****************d*g**/
/**
* Starts catching potential errors/warnings
*
* @return void
*/
public static function tryError()
{
set_error_handler(array(__CLASS__, '_errorHandler'), E_ALL);
self::$errorMsg = NULL;
}
/**
* Starts catching potential errors/warnings
*
* @return void
*/
public static function tryError()
{
set_error_handler(array(__CLASS__, '_errorHandler'), E_ALL);
self::$errorMsg = NULL;
}
/**
* Returns catched error/warning message.
*
* @param string catched message
* @return bool
*/
public static function catchError(& $message)
{
restore_error_handler();
$message = self::$errorMsg;
self::$errorMsg = NULL;
return $message !== NULL;
}
/**
* Returns catched error/warning message.
*
* @param string catched message
* @return bool
*/
public static function catchError(& $message)
{
restore_error_handler();
$message = self::$errorMsg;
self::$errorMsg = NULL;
return $message !== NULL;
}
/**
* Internal error handler. Do not call directly.
*/
public static function _errorHandler($code, $message)
{
restore_error_handler();
/**
* Internal error handler. Do not call directly.
*/
public static function _errorHandler($code, $message)
{
restore_error_handler();
if (ini_get('html_errors')) {
$message = strip_tags($message);
$message = html_entity_decode($message);
}
if (ini_get('html_errors')) {
$message = strip_tags($message);
$message = html_entity_decode($message);
}
self::$errorMsg = $message;
}
self::$errorMsg = $message;
}
}

View File

@@ -29,78 +29,78 @@
*/
final class DibiLogger extends /*Nette::*/Object
{
/** @var string Name of the file where SQL errors should be logged */
private $file;
/** @var string Name of the file where SQL errors should be logged */
private $file;
/** @var bool */
public $logErrors = TRUE;
/** @var bool */
public $logErrors = TRUE;
/** @var bool */
public $logQueries = TRUE;
/** @var bool */
public $logQueries = TRUE;
/**
* @param string filename
*/
public function __construct($file)
{
$this->file = $file;
}
/**
* @param string filename
*/
public function __construct($file)
{
$this->file = $file;
}
/**
* Event handler (events: exception, connected, beforeQuery, afterQuery, begin, commit, rollback).
*
* @param DibiConnection
* @param string event name
* @param mixed
* @return void
*/
public function handler($connection, $event, $arg)
{
if ($event === 'afterQuery' && $this->logQueries) {
$this->write(
"OK: " . dibi::$sql
. ($arg instanceof DibiResult ? ";\n-- rows: " . count($arg) : '')
. "\n-- takes: " . sprintf('%0.3f', dibi::$elapsedTime * 1000) . ' ms'
. "\n-- driver: " . $connection->getConfig('driver')
. "\n-- " . date('Y-m-d H:i:s')
. "\n\n"
);
return;
}
/**
* Event handler (events: exception, connected, beforeQuery, afterQuery, begin, commit, rollback).
*
* @param DibiConnection
* @param string event name
* @param mixed
* @return void
*/
public function handler($connection, $event, $arg)
{
if ($event === 'afterQuery' && $this->logQueries) {
$this->write(
"OK: " . dibi::$sql
. ($arg instanceof DibiResult ? ";\n-- rows: " . count($arg) : '')
. "\n-- takes: " . sprintf('%0.3f', dibi::$elapsedTime * 1000) . ' ms'
. "\n-- driver: " . $connection->getConfig('driver')
. "\n-- " . date('Y-m-d H:i:s')
. "\n\n"
);
return;
}
if ($event === 'exception' && $this->logErrors) {
// $arg is DibiDriverException
$message = $arg->getMessage();
$code = $arg->getCode();
if ($code) {
$message = "[$code] $message";
}
if ($event === 'exception' && $this->logErrors) {
// $arg is DibiDriverException
$message = $arg->getMessage();
$code = $arg->getCode();
if ($code) {
$message = "[$code] $message";
}
$this->write(
"ERROR: $message"
. "\n-- SQL: " . dibi::$sql
. "\n-- driver: " //. $connection->getConfig('driver')
. ";\n-- " . date('Y-m-d H:i:s')
. "\n\n"
);
return;
}
}
$this->write(
"ERROR: $message"
. "\n-- SQL: " . dibi::$sql
. "\n-- driver: " //. $connection->getConfig('driver')
. ";\n-- " . date('Y-m-d H:i:s')
. "\n\n"
);
return;
}
}
private function write($message)
{
$handle = fopen($this->file, 'a');
if (!$handle) return; // or throw exception?
private function write($message)
{
$handle = fopen($this->file, 'a');
if (!$handle) return; // or throw exception?
flock($handle, LOCK_EX);
fwrite($handle, $message);
fclose($handle);
}
flock($handle, LOCK_EX);
fwrite($handle, $message);
fclose($handle);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -45,92 +45,92 @@
*/
final class DibiResultIterator implements Iterator
{
/** @var DibiResult */
private $result;
/** @var DibiResult */
private $result;
/** @var int */
private $offset;
/** @var int */
private $offset;
/** @var int */
private $limit;
/** @var int */
private $limit;
/** @var int */
private $row;
/** @var int */
private $row;
/** @var int */
private $pointer;
/** @var int */
private $pointer;
/**
* Required by the Iterator interface.
* @param int offset
* @param int limit
*/
public function __construct(DibiResult $result, $offset, $limit)
{
$this->result = $result;
$this->offset = (int) $offset;
$this->limit = $limit === NULL ? -1 : (int) $limit;
}
/**
* Rewinds the Iterator to the first element.
* @return void
/**
* Required by the Iterator interface.
* @param int offset
* @param int limit
*/
public function rewind()
{
$this->pointer = 0;
$this->result->seek($this->offset);
$this->row = $this->result->fetch();
}
public function __construct(DibiResult $result, $offset, $limit)
{
$this->result = $result;
$this->offset = (int) $offset;
$this->limit = $limit === NULL ? -1 : (int) $limit;
}
/**
* Returns the key of the current element.
* @return mixed
/**
* Rewinds the Iterator to the first element.
* @return void
*/
public function key()
{
return $this->pointer;
}
public function rewind()
{
$this->pointer = 0;
$this->result->seek($this->offset);
$this->row = $this->result->fetch();
}
/**
* Returns the current element.
* @return mixed
/**
* Returns the key of the current element.
* @return mixed
*/
public function current()
{
return $this->row;
}
public function key()
{
return $this->pointer;
}
/**
* Moves forward to next element.
* @return void
/**
* Returns the current element.
* @return mixed
*/
public function next()
{
//$this->result->seek($this->offset + $this->pointer + 1);
$this->row = $this->result->fetch();
$this->pointer++;
}
public function current()
{
return $this->row;
}
/**
* Checks if there is a current element after calls to rewind() or next().
* @return bool
/**
* Moves forward to next element.
* @return void
*/
public function valid()
{
return !empty($this->row) && ($this->limit < 0 || $this->pointer < $this->limit);
}
public function next()
{
//$this->result->seek($this->offset + $this->pointer + 1);
$this->row = $this->result->fetch();
$this->pointer++;
}
/**
* Checks if there is a current element after calls to rewind() or next().
* @return bool
*/
public function valid()
{
return !empty($this->row) && ($this->limit < 0 || $this->pointer < $this->limit);
}
}

View File

@@ -28,264 +28,264 @@
*/
abstract class DibiTable extends /*Nette::*/Object
{
/** @var string primary key mask */
public static $primaryMask = 'id';
/** @var string primary key mask */
public static $primaryMask = 'id';
/** @var bool */
public static $lowerCase = TRUE;
/** @var bool */
public static $lowerCase = TRUE;
/** @var DibiConnection */
private $connection;
/** @var DibiConnection */
private $connection;
/** @var array */
private $options;
/** @var array */
private $options;
/** @var string table name */
protected $name;
/** @var string table name */
protected $name;
/** @var string primary key name */
protected $primary;
/** @var string primary key name */
protected $primary;
/** @var string primary key type */
protected $primaryModifier = '%i';
/** @var string primary key type */
protected $primaryModifier = '%i';
/** @var array */
protected $blankRow = array();
/** @var array */
protected $blankRow = array();
/**
* Table constructor.
* @param array
* @return void
*/
public function __construct(array $options = array())
{
$this->options = $options;
/**
* Table constructor.
* @param array
* @return void
*/
public function __construct(array $options = array())
{
$this->options = $options;
$this->setup();
$this->setup();
if ($this->connection === NULL) {
$this->connection = dibi::getConnection();
}
}
if ($this->connection === NULL) {
$this->connection = dibi::getConnection();
}
}
/**
* Returns the table name.
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Returns the table name.
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Returns the primary key name.
* @return string
*/
public function getPrimary()
{
return $this->primary;
}
/**
* Returns the primary key name.
* @return string
*/
public function getPrimary()
{
return $this->primary;
}
/**
* Returns the dibi connection.
* @return DibiConnection
*/
public function getConnection()
{
return $this->connection;
}
/**
* Returns the dibi connection.
* @return DibiConnection
*/
public function getConnection()
{
return $this->connection;
}
/**
* Setup object.
* @return void
*/
protected function setup()
{
// autodetect table name
if ($this->name === NULL) {
$name = $this->getClass();
if (FALSE !== ($pos = strrpos($name, ':'))) {
$name = substr($name, $pos + 1);
}
if (self::$lowerCase) {
$name = strtolower($name);
}
$this->name = $name;
}
/**
* Setup object.
* @return void
*/
protected function setup()
{
// autodetect table name
if ($this->name === NULL) {
$name = $this->getClass();
if (FALSE !== ($pos = strrpos($name, ':'))) {
$name = substr($name, $pos + 1);
}
if (self::$lowerCase) {
$name = strtolower($name);
}
$this->name = $name;
}
// autodetect primary key name
if ($this->primary === NULL) {
$this->primary = str_replace(
array('%p', '%s'),
array($this->name, trim($this->name, 's')), // the simplest inflector in the world :-))
self::$primaryMask
);
}
}
// autodetect primary key name
if ($this->primary === NULL) {
$this->primary = str_replace(
array('%p', '%s'),
array($this->name, trim($this->name, 's')), // the simplest inflector in the world :-))
self::$primaryMask
);
}
}
/**
* Inserts row into a table.
* @param array|object
* @return int new primary key
*/
public function insert($data)
{
$this->connection->query(
'INSERT INTO %n', $this->name, '%v', $this->prepare($data)
);
return $this->connection->insertId();
}
/**
* Inserts row into a table.
* @param array|object
* @return int new primary key
*/
public function insert($data)
{
$this->connection->query(
'INSERT INTO %n', $this->name, '%v', $this->prepare($data)
);
return $this->connection->insertId();
}
/**
* Updates rows in a table.
* @param mixed primary key value(s)
* @param array|object
* @return int number of updated rows
*/
public function update($where, $data)
{
$this->connection->query(
'UPDATE %n', $this->name,
'SET %a', $this->prepare($data),
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
);
return $this->connection->affectedRows();
}
/**
* Updates rows in a table.
* @param mixed primary key value(s)
* @param array|object
* @return int number of updated rows
*/
public function update($where, $data)
{
$this->connection->query(
'UPDATE %n', $this->name,
'SET %a', $this->prepare($data),
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
);
return $this->connection->affectedRows();
}
/**
* Deletes rows from a table by primary key.
* @param mixed primary key value(s)
* @return int number of deleted rows
*/
public function delete($where)
{
$this->connection->query(
'DELETE FROM %n', $this->name,
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
);
return $this->connection->affectedRows();
}
/**
* Deletes rows from a table by primary key.
* @param mixed primary key value(s)
* @return int number of deleted rows
*/
public function delete($where)
{
$this->connection->query(
'DELETE FROM %n', $this->name,
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
);
return $this->connection->affectedRows();
}
/**
* Finds rows by primary key.
* @param mixed primary key value(s)
* @return DibiResult
*/
public function find($what)
{
if (!is_array($what)) {
$what = func_get_args();
}
return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name,
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $what, ')'
));
}
/**
* Finds rows by primary key.
* @param mixed primary key value(s)
* @return DibiResult
*/
public function find($what)
{
if (!is_array($what)) {
$what = func_get_args();
}
return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name,
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $what, ')'
));
}
/**
* Selects all rows.
* @param string column to order by
* @return DibiResult
*/
public function findAll($order = NULL)
{
if ($order === NULL) {
return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name
));
} else {
$order = func_get_args();
return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name,
'ORDER BY %n', $order
));
}
}
/**
* Selects all rows.
* @param string column to order by
* @return DibiResult
*/
public function findAll($order = NULL)
{
if ($order === NULL) {
return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name
));
} else {
$order = func_get_args();
return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name,
'ORDER BY %n', $order
));
}
}
/**
* Fetches single row.
* @param scalar|array primary key value
* @return array|object row
*/
public function fetch($conditions)
{
if (is_array($conditions)) {
return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name,
'WHERE %and', $conditions
))->fetch();
}
return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name,
'WHERE %n=' . $this->primaryModifier, $this->primary, $conditions
))->fetch();
}
/**
* Fetches single row.
* @param scalar|array primary key value
* @return array|object row
*/
public function fetch($conditions)
{
if (is_array($conditions)) {
return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name,
'WHERE %and', $conditions
))->fetch();
}
return $this->complete($this->connection->query(
'SELECT * FROM %n', $this->name,
'WHERE %n=' . $this->primaryModifier, $this->primary, $conditions
))->fetch();
}
/**
* Returns a blank row (not fetched from database).
* @return array|object
*/
public function createBlank()
{
$row = $this->blankRow;
$row[$this->primary] = NULL;
if ($this->connection->getConfig('result:objects')) {
$row = (object) $row;
}
return $row;
}
/**
* Returns a blank row (not fetched from database).
* @return array|object
*/
public function createBlank()
{
$row = $this->blankRow;
$row[$this->primary] = NULL;
if ($this->connection->getConfig('result:objects')) {
$row = (object) $row;
}
return $row;
}
/**
* User data pre-processing.
* @param array|object
* @return array
*/
protected function prepare($data)
{
if (is_object($data)) {
return (array) $data;
} elseif (is_array($data)) {
return $data;
}
/**
* User data pre-processing.
* @param array|object
* @return array
*/
protected function prepare($data)
{
if (is_object($data)) {
return (array) $data;
} elseif (is_array($data)) {
return $data;
}
throw new InvalidArgumentException('Dataset must be array or anonymous object.');
}
throw new InvalidArgumentException('Dataset must be array or anonymous object.');
}
/**
* User DibiResult post-processing.
* @param DibiResult
* @return DibiResult
*/
protected function complete($res)
{
return $res;
}
/**
* User DibiResult post-processing.
* @param DibiResult
* @return DibiResult
*/
protected function complete($res)
{
return $res;
}
}

View File

@@ -29,432 +29,432 @@
*/
final class DibiTranslator extends /*Nette::*/Object
{
/** @var string */
public $sql;
/** @var string */
public $sql;
/** @var IDibiDriver */
private $driver;
/** @var IDibiDriver */
private $driver;
/** @var int */
private $cursor;
/** @var int */
private $cursor;
/** @var array */
private $args;
/** @var array */
private $args;
/** @var bool */
private $hasError;
/** @var bool */
private $hasError;
/** @var bool */
private $comment;
/** @var bool */
private $comment;
/** @var int */
private $ifLevel;
/** @var int */
private $ifLevel;
/** @var int */
private $ifLevelStart;
/** @var int */
private $ifLevelStart;
/** @var int */
private $limit;
/** @var int */
private $limit;
/** @var int */
private $offset;
/** @var int */
private $offset;
public function __construct(IDibiDriver $driver)
{
$this->driver = $driver;
}
public function __construct(IDibiDriver $driver)
{
$this->driver = $driver;
}
/**
* return IDibiDriver.
*/
public function getDriver()
{
return $this->driver;
}
/**
* return IDibiDriver.
*/
public function getDriver()
{
return $this->driver;
}
/**
* Generates SQL.
*
* @param array
* @return bool
*/
public function translate(array $args)
{
$this->limit = -1;
$this->offset = 0;
$this->hasError = FALSE;
$commandIns = NULL;
$lastArr = NULL;
// shortcuts
$cursor = & $this->cursor;
$cursor = 0;
$this->args = array_values($args);
$args = & $this->args;
/**
* Generates SQL.
*
* @param array
* @return bool
*/
public function translate(array $args)
{
$this->limit = -1;
$this->offset = 0;
$this->hasError = FALSE;
$commandIns = NULL;
$lastArr = NULL;
// shortcuts
$cursor = & $this->cursor;
$cursor = 0;
$this->args = array_values($args);
$args = & $this->args;
// conditional sql
$this->ifLevel = $this->ifLevelStart = 0;
$comment = & $this->comment;
$comment = FALSE;
// conditional sql
$this->ifLevel = $this->ifLevelStart = 0;
$comment = & $this->comment;
$comment = FALSE;
// iterate
$sql = array();
while ($cursor < count($args))
{
$arg = $args[$cursor];
$cursor++;
// iterate
$sql = array();
while ($cursor < count($args))
{
$arg = $args[$cursor];
$cursor++;
// simple string means SQL
if (is_string($arg)) {
// speed-up - is regexp required?
$toSkip = strcspn($arg, '`[\'"%');
// simple string means SQL
if (is_string($arg)) {
// speed-up - is regexp required?
$toSkip = strcspn($arg, '`[\'"%');
if (strlen($arg) === $toSkip) { // needn't be translated
$sql[] = $arg;
} else {
$sql[] = substr($arg, 0, $toSkip)
if (strlen($arg) === $toSkip) { // needn't be translated
$sql[] = $arg;
} else {
$sql[] = substr($arg, 0, $toSkip)
/*
. preg_replace_callback('/
(?=`|\[|\'|"|%) ## speed-up
(?:
`(.+?)`| ## 1) `identifier`
\[(.+?)\]| ## 2) [identifier]
(\')((?:\'\'|[^\'])*)\'| ## 3,4) string
(")((?:""|[^"])*)"| ## 5,6) "string"
(\'|") ## 7) lone-quote
%([a-zA-Z]{1,4})(?![a-zA-Z])|## 8) modifier
)/xs',
. preg_replace_callback('/
(?=`|\[|\'|"|%) ## speed-up
(?:
`(.+?)`| ## 1) `identifier`
\[(.+?)\]| ## 2) [identifier]
(\')((?:\'\'|[^\'])*)\'| ## 3,4) string
(")((?:""|[^"])*)"| ## 5,6) "string"
(\'|") ## 7) lone-quote
%([a-zA-Z]{1,4})(?![a-zA-Z])|## 8) modifier
)/xs',
*/ // note: this can change $this->args & $this->cursor & ...
. preg_replace_callback('/(?=`|\[|\'|"|%)(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|%([a-zA-Z]{1,4})(?![a-zA-Z]))/s',
array($this, 'cb'),
substr($arg, $toSkip)
);
. preg_replace_callback('/(?=`|\[|\'|"|%)(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"|(\'|")|%([a-zA-Z]{1,4})(?![a-zA-Z]))/s',
array($this, 'cb'),
substr($arg, $toSkip)
);
}
continue;
}
}
continue;
}
if ($comment) {
$sql[] = '...';
continue;
}
if ($comment) {
$sql[] = '...';
continue;
}
if (is_array($arg)) {
if (is_string(key($arg))) {
// associative array -> autoselect between SET or VALUES & LIST
if ($commandIns === NULL) {
$commandIns = strtoupper(substr(ltrim($args[0]), 0, 6));
$commandIns = $commandIns === 'INSERT' || $commandIns === 'REPLAC';
$sql[] = $this->formatValue($arg, $commandIns ? 'v' : 'a');
} else {
if ($lastArr === $cursor - 1) $sql[] = ',';
$sql[] = $this->formatValue($arg, $commandIns ? 'l' : 'a');
}
$lastArr = $cursor;
continue;
if (is_array($arg)) {
if (is_string(key($arg))) {
// associative array -> autoselect between SET or VALUES & LIST
if ($commandIns === NULL) {
$commandIns = strtoupper(substr(ltrim($args[0]), 0, 6));
$commandIns = $commandIns === 'INSERT' || $commandIns === 'REPLAC';
$sql[] = $this->formatValue($arg, $commandIns ? 'v' : 'a');
} else {
if ($lastArr === $cursor - 1) $sql[] = ',';
$sql[] = $this->formatValue($arg, $commandIns ? 'l' : 'a');
}
$lastArr = $cursor;
continue;
} elseif ($cursor === 1) {
// implicit array expansion
$cursor = 0;
array_splice($args, 0, 1, $arg);
continue;
}
}
} elseif ($cursor === 1) {
// implicit array expansion
$cursor = 0;
array_splice($args, 0, 1, $arg);
continue;
}
}
// default processing
$sql[] = $this->formatValue($arg, FALSE);
} // while
// default processing
$sql[] = $this->formatValue($arg, FALSE);
} // while
if ($comment) $sql[] = "*/";
if ($comment) $sql[] = "*/";
$sql = implode(' ', $sql);
$sql = implode(' ', $sql);
// apply limit
if ($this->limit > -1 || $this->offset > 0) {
$this->driver->applyLimit($sql, $this->limit, $this->offset);
}
// apply limit
if ($this->limit > -1 || $this->offset > 0) {
$this->driver->applyLimit($sql, $this->limit, $this->offset);
}
$this->sql = $sql;
return !$this->hasError;
}
$this->sql = $sql;
return !$this->hasError;
}
/**
* Apply modifier to single value.
* @param mixed
* @param string
* @return string
*/
public function formatValue($value, $modifier)
{
// array processing (with or without modifier)
if (is_array($value)) {
/**
* Apply modifier to single value.
* @param mixed
* @param string
* @return string
*/
public function formatValue($value, $modifier)
{
// array processing (with or without modifier)
if (is_array($value)) {
$vx = $kx = array();
$separator = ', ';
switch ($modifier) {
case 'and':
case 'or':
$separator = ' ' . strtoupper($modifier) . ' ';
if (!is_string(key($value))) {
foreach ($value as $v) {
$vx[] = $this->formatValue($v, 'sql');
}
return implode($separator, $vx);
}
// break intentionally omitted
case 'a': // SET key=val, key=val, ...
foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier
$vx[] = $this->delimite($pair[0]) . '='
. $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
}
return implode($separator, $vx);
$vx = $kx = array();
$separator = ', ';
switch ($modifier) {
case 'and':
case 'or':
$separator = ' ' . strtoupper($modifier) . ' ';
if (!is_string(key($value))) {
foreach ($value as $v) {
$vx[] = $this->formatValue($v, 'sql');
}
return implode($separator, $vx);
}
// break intentionally omitted
case 'a': // SET key=val, key=val, ...
foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier
$vx[] = $this->delimite($pair[0]) . '='
. $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
}
return implode($separator, $vx);
case 'l': // LIST val, val, ...
foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
}
return '(' . implode(', ', $vx) . ')';
case 'l': // LIST val, val, ...
foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
}
return '(' . implode(', ', $vx) . ')';
case 'v': // (key, key, ...) VALUES (val, val, ...)
foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier
$kx[] = $this->delimite($pair[0]);
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
}
return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
case 'v': // (key, key, ...) VALUES (val, val, ...)
foreach ($value as $k => $v) {
$pair = explode('%', $k, 2); // split into identifier & modifier
$kx[] = $this->delimite($pair[0]);
$vx[] = $this->formatValue($v, isset($pair[1]) ? $pair[1] : FALSE);
}
return '(' . implode(', ', $kx) . ') VALUES (' . implode(', ', $vx) . ')';
default:
foreach ($value as $v) {
$vx[] = $this->formatValue($v, $modifier);
}
return implode(', ', $vx);
}
}
default:
foreach ($value as $v) {
$vx[] = $this->formatValue($v, $modifier);
}
return implode(', ', $vx);
}
}
// with modifier procession
if ($modifier) {
if ($value === NULL) {
return 'NULL';
}
// with modifier procession
if ($modifier) {
if ($value === NULL) {
return 'NULL';
}
if ($value instanceof IDibiVariable) {
return $value->toSql($this, $modifier);
}
if ($value instanceof IDibiVariable) {
return $value->toSql($this, $modifier);
}
if (!is_scalar($value)) { // array is already processed
$this->hasError = TRUE;
return '**Unexpected type ' . gettype($value) . '**';
}
if (!is_scalar($value)) { // array is already processed
$this->hasError = TRUE;
return '**Unexpected type ' . gettype($value) . '**';
}
switch ($modifier) {
case 's': // string
return $this->driver->format($value, dibi::FIELD_TEXT);
switch ($modifier) {
case 's': // string
return $this->driver->format($value, dibi::FIELD_TEXT);
case 'sn': // string or NULL
return $value == '' ? 'NULL' : $this->driver->format($value, dibi::FIELD_TEXT); // notice two equal signs
case 'sn': // string or NULL
return $value == '' ? 'NULL' : $this->driver->format($value, dibi::FIELD_TEXT); // notice two equal signs
case 'b': // boolean
return $this->driver->format($value, dibi::FIELD_BOOL);
case 'b': // boolean
return $this->driver->format($value, dibi::FIELD_BOOL);
case 'i': // signed int
case 'u': // unsigned int, ignored
// support for numbers - keep them unchanged
if (is_string($value) && preg_match('#[+-]?\d+(e\d+)?$#A', $value)) {
return $value;
}
return (string) (int) ($value + 0);
case 'i': // signed int
case 'u': // unsigned int, ignored
// support for numbers - keep them unchanged
if (is_string($value) && preg_match('#[+-]?\d+(e\d+)?$#A', $value)) {
return $value;
}
return (string) (int) ($value + 0);
case 'f': // float
// support for numbers - keep them unchanged
if (is_numeric($value) && (!is_string($value) || strpos($value, 'x') === FALSE)) {
return $value; // something like -9E-005 is accepted by SQL, HEX values is not
}
return (string) ($value + 0);
case 'f': // float
// support for numbers - keep them unchanged
if (is_numeric($value) && (!is_string($value) || strpos($value, 'x') === FALSE)) {
return $value; // something like -9E-005 is accepted by SQL, HEX values is not
}
return (string) ($value + 0);
case 'd': // date
return $this->driver->format(is_string($value) ? strtotime($value) : $value, dibi::FIELD_DATE);
case 'd': // date
return $this->driver->format(is_string($value) ? strtotime($value) : $value, dibi::FIELD_DATE);
case 't': // datetime
return $this->driver->format(is_string($value) ? strtotime($value) : $value, dibi::FIELD_DATETIME);
case 't': // datetime
return $this->driver->format(is_string($value) ? strtotime($value) : $value, dibi::FIELD_DATETIME);
case 'n': // identifier name
return $this->delimite($value);
case 'n': // identifier name
return $this->delimite($value);
case 'sql':// preserve as SQL
$value = (string) $value;
// speed-up - is regexp required?
$toSkip = strcspn($value, '`[\'"');
if (strlen($value) === $toSkip) { // needn't be translated
return $value;
} else {
return substr($value, 0, $toSkip)
. preg_replace_callback('/(?=`|\[|\'|")(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"(\'|"))/s',
array($this, 'cb'),
substr($value, $toSkip)
);
}
case 'sql':// preserve as SQL
$value = (string) $value;
// speed-up - is regexp required?
$toSkip = strcspn($value, '`[\'"');
if (strlen($value) === $toSkip) { // needn't be translated
return $value;
} else {
return substr($value, 0, $toSkip)
. preg_replace_callback('/(?=`|\[|\'|")(?:`(.+?)`|\[(.+?)\]|(\')((?:\'\'|[^\'])*)\'|(")((?:""|[^"])*)"(\'|"))/s',
array($this, 'cb'),
substr($value, $toSkip)
);
}
case 'a':
case 'v':
$this->hasError = TRUE;
return '**Unexpected type ' . gettype($value) . '**';
case 'a':
case 'v':
$this->hasError = TRUE;
return '**Unexpected type ' . gettype($value) . '**';
default:
$this->hasError = TRUE;
return "**Unknown or invalid modifier %$modifier**";
}
}
default:
$this->hasError = TRUE;
return "**Unknown or invalid modifier %$modifier**";
}
}
// without modifier procession
if (is_string($value))
return $this->driver->format($value, dibi::FIELD_TEXT);
// without modifier procession
if (is_string($value))
return $this->driver->format($value, dibi::FIELD_TEXT);
if (is_int($value) || is_float($value))
return (string) $value; // something like -9E-005 is accepted by SQL
if (is_int($value) || is_float($value))
return (string) $value; // something like -9E-005 is accepted by SQL
if (is_bool($value))
return $this->driver->format($value, dibi::FIELD_BOOL);
if (is_bool($value))
return $this->driver->format($value, dibi::FIELD_BOOL);
if ($value === NULL)
return 'NULL';
if ($value === NULL)
return 'NULL';
if ($value instanceof IDibiVariable)
return $value->toSql($this, NULL);
if ($value instanceof IDibiVariable)
return $value->toSql($this, NULL);
$this->hasError = TRUE;
return '**Unexpected ' . gettype($value) . '**';
}
$this->hasError = TRUE;
return '**Unexpected ' . gettype($value) . '**';
}
/**
* PREG callback from translate() or formatValue().
* @param array
* @return string
*/
private function cb($matches)
{
// [1] => `ident`
// [2] => [ident]
// [3] => '
// [4] => string
// [5] => "
// [6] => string
// [7] => lone-quote
// [8] => modifier (when called from self::translate())
/**
* PREG callback from translate() or formatValue().
* @param array
* @return string
*/
private function cb($matches)
{
// [1] => `ident`
// [2] => [ident]
// [3] => '
// [4] => string
// [5] => "
// [6] => string
// [7] => lone-quote
// [8] => modifier (when called from self::translate())
if (!empty($matches[8])) { // modifier
$mod = $matches[8];
$cursor = & $this->cursor;
if (!empty($matches[8])) { // modifier
$mod = $matches[8];
$cursor = & $this->cursor;
if ($cursor >= count($this->args) && $mod !== 'else' && $mod !== 'end') {
$this->hasError = TRUE;
return "**Extra modifier %$mod**";
}
if ($cursor >= count($this->args) && $mod !== 'else' && $mod !== 'end') {
$this->hasError = TRUE;
return "**Extra modifier %$mod**";
}
if ($mod === 'if') {
$this->ifLevel++;
$cursor++;
if (!$this->comment && !$this->args[$cursor - 1]) {
// open comment
$this->ifLevelStart = $this->ifLevel;
$this->comment = TRUE;
return "/*";
}
return '';
if ($mod === 'if') {
$this->ifLevel++;
$cursor++;
if (!$this->comment && !$this->args[$cursor - 1]) {
// open comment
$this->ifLevelStart = $this->ifLevel;
$this->comment = TRUE;
return "/*";
}
return '';
} elseif ($mod === 'else') {
if ($this->ifLevelStart === $this->ifLevel) {
$this->ifLevelStart = 0;
$this->comment = FALSE;
return "*/";
} elseif (!$this->comment) {
$this->ifLevelStart = $this->ifLevel;
$this->comment = TRUE;
return "/*";
}
} elseif ($mod === 'else') {
if ($this->ifLevelStart === $this->ifLevel) {
$this->ifLevelStart = 0;
$this->comment = FALSE;
return "*/";
} elseif (!$this->comment) {
$this->ifLevelStart = $this->ifLevel;
$this->comment = TRUE;
return "/*";
}
} elseif ($mod === 'end') {
$this->ifLevel--;
if ($this->ifLevelStart === $this->ifLevel + 1) {
// close comment
$this->ifLevelStart = 0;
$this->comment = FALSE;
return "*/";
}
return '';
} elseif ($mod === 'end') {
$this->ifLevel--;
if ($this->ifLevelStart === $this->ifLevel + 1) {
// close comment
$this->ifLevelStart = 0;
$this->comment = FALSE;
return "*/";
}
return '';
} elseif ($mod === 'ex') { // array expansion
array_splice($this->args, $cursor, 1, $this->args[$cursor]);
return '';
} elseif ($mod === 'ex') { // array expansion
array_splice($this->args, $cursor, 1, $this->args[$cursor]);
return '';
} elseif ($mod === 'lmt') { // apply limit
if ($this->args[$cursor] !== NULL) $this->limit = (int) $this->args[$cursor];
$cursor++;
return '';
} elseif ($mod === 'lmt') { // apply limit
if ($this->args[$cursor] !== NULL) $this->limit = (int) $this->args[$cursor];
$cursor++;
return '';
} elseif ($mod === 'ofs') { // apply offset
if ($this->args[$cursor] !== NULL) $this->offset = (int) $this->args[$cursor];
$cursor++;
return '';
} elseif ($mod === 'ofs') { // apply offset
if ($this->args[$cursor] !== NULL) $this->offset = (int) $this->args[$cursor];
$cursor++;
return '';
} else { // default processing
$cursor++;
return $this->formatValue($this->args[$cursor - 1], $mod);
}
}
} else { // default processing
$cursor++;
return $this->formatValue($this->args[$cursor - 1], $mod);
}
}
if ($this->comment) return '...';
if ($this->comment) return '...';
if ($matches[1]) // SQL identifiers: `ident`
return $this->delimite($matches[1]);
if ($matches[1]) // SQL identifiers: `ident`
return $this->delimite($matches[1]);
if ($matches[2]) // SQL identifiers: [ident]
return $this->delimite($matches[2]);
if ($matches[2]) // SQL identifiers: [ident]
return $this->delimite($matches[2]);
if ($matches[3]) // SQL strings: '...'
return $this->driver->format( str_replace("''", "'", $matches[4]), dibi::FIELD_TEXT);
if ($matches[3]) // SQL strings: '...'
return $this->driver->format( str_replace("''", "'", $matches[4]), dibi::FIELD_TEXT);
if ($matches[5]) // SQL strings: "..."
return $this->driver->format( str_replace('""', '"', $matches[6]), dibi::FIELD_TEXT);
if ($matches[5]) // SQL strings: "..."
return $this->driver->format( str_replace('""', '"', $matches[6]), dibi::FIELD_TEXT);
if ($matches[7]) { // string quote
$this->hasError = TRUE;
return '**Alone quote**';
}
if ($matches[7]) { // string quote
$this->hasError = TRUE;
return '**Alone quote**';
}
die('this should be never executed');
}
die('this should be never executed');
}
/**
* Apply substitutions to indentifier and delimites it.
*
* @param string indentifier
* @return string
*/
private function delimite($value)
{
if (strpos($value, ':') !== FALSE) {
$value = strtr($value, dibi::getSubst());
}
return $this->driver->format($value, dibi::IDENTIFIER);
}
/**
* Apply substitutions to indentifier and delimites it.
*
* @param string indentifier
* @return string
*/
private function delimite($value)
{
if (strpos($value, ':') !== FALSE) {
$value = strtr($value, dibi::getSubst());
}
return $this->driver->format($value, dibi::IDENTIFIER);
}
} // class DibiTranslator

View File

@@ -25,24 +25,24 @@
*/
class DibiVariable extends /*Nette::*/Object implements IDibiVariable
{
/** @var mixed */
public $value;
/** @var mixed */
public $value;
/** @var string */
public $modifier;
/** @var string */
public $modifier;
public function __construct($value, $modifier)
{
$this->value = $value;
$this->modifier = $modifier;
}
public function __construct($value, $modifier)
{
$this->value = $value;
$this->modifier = $modifier;
}
public function toSql(DibiTranslator $translator, $modifier)
{
return $translator->formatValue($this->value, $this->modifier);
}
public function toSql(DibiTranslator $translator, $modifier)
{
return $translator->formatValue($this->value, $this->modifier);
}
}

View File

@@ -25,14 +25,14 @@
*/
interface IDibiVariable
{
/**
* Format for SQL.
*
* @param object DibiTranslator
* @param string optional modifier
* @return string SQL code
*/
public function toSql(DibiTranslator $translator, $modifier);
/**
* Format for SQL.
*
* @param object DibiTranslator
* @param string optional modifier
* @return string SQL code
*/
public function toSql(DibiTranslator $translator, $modifier);
}
@@ -45,8 +45,8 @@ interface IDibiVariable
*/
interface IDataSource extends Countable, IteratorAggregate
{
//function IteratorAggregate::getIterator();
//function Countable::count();
//function IteratorAggregate::getIterator();
//function Countable::count();
}
@@ -64,179 +64,179 @@ interface IDataSource extends Countable, IteratorAggregate
interface IDibiDriver
{
/**
* Internal: Connects to a database.
*
* @param array
* @return void
* @throws DibiException
*/
function connect(array &$config);
/**
* Internal: Connects to a database.
*
* @param array
* @return void
* @throws DibiException
*/
function connect(array &$config);
/**
* Internal: Disconnects from a database.
*
* @return void
* @throws DibiException
*/
function disconnect();
/**
* Internal: Disconnects from a database.
*
* @return void
* @throws DibiException
*/
function disconnect();
/**
* Internal: Executes the SQL query.
*
* @param string SQL statement.
* @return bool have resultset?
* @throws DibiDriverException
*/
function query($sql);
/**
* Internal: Executes the SQL query.
*
* @param string SQL statement.
* @return bool have resultset?
* @throws DibiDriverException
*/
function query($sql);
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
*
* @return int|FALSE number of rows or FALSE on error
*/
function affectedRows();
/**
* Gets the number of affected rows by the last INSERT, UPDATE or DELETE query.
*
* @return int|FALSE number of rows or FALSE on error
*/
function affectedRows();
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
*
* @return int|FALSE int on success or FALSE on failure
*/
function insertId($sequence);
/**
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query.
*
* @return int|FALSE int on success or FALSE on failure
*/
function insertId($sequence);
/**
* Begins a transaction (if supported).
* @return void
* @throws DibiDriverException
*/
function begin();
/**
* Begins a transaction (if supported).
* @return void
* @throws DibiDriverException
*/
function begin();
/**
* Commits statements in a transaction.
* @return void
* @throws DibiDriverException
*/
function commit();
/**
* Commits statements in a transaction.
* @return void
* @throws DibiDriverException
*/
function commit();
/**
* Rollback changes in a transaction.
* @return void
* @throws DibiDriverException
*/
function rollback();
/**
* Rollback changes in a transaction.
* @return void
* @throws DibiDriverException
*/
function rollback();
/**
* Format to SQL command.
*
* @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER)
* @return string formatted value
*/
function format($value, $type);
/**
* Format to SQL command.
*
* @param string value
* @param string type (dibi::FIELD_TEXT, dibi::FIELD_BOOL, dibi::FIELD_DATE, dibi::FIELD_DATETIME, dibi::IDENTIFIER)
* @return string formatted value
*/
function format($value, $type);
/**
* Injects LIMIT/OFFSET to the SQL query.
*
* @param string &$sql The SQL query that will be modified.
* @param int $limit
* @param int $offset
* @return void
*/
function applyLimit(&$sql, $limit, $offset);
/**
* Injects LIMIT/OFFSET to the SQL query.
*
* @param string &$sql The SQL query that will be modified.
* @param int $limit
* @param int $offset
* @return void
*/
function applyLimit(&$sql, $limit, $offset);
/**
* Returns the number of rows in a result set.
*
* @return int
*/
function rowCount();
/**
* Returns the number of rows in a result set.
*
* @return int
*/
function rowCount();
/**
* Moves cursor position without fetching row.
*
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException
*/
function seek($row);
/**
* Moves cursor position without fetching row.
*
* @param int the 0-based cursor pos to seek to
* @return boolean TRUE on success, FALSE if unable to seek to specified record
* @throws DibiException
*/
function seek($row);
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* internal usage only
*
* @param bool TRUE for associative array, FALSE for numeric
* @return array array on success, nonarray if no next record
*/
function fetch($type);
/**
* Fetches the row at current position and moves the internal cursor to the next position.
* internal usage only
*
* @param bool TRUE for associative array, FALSE for numeric
* @return array array on success, nonarray if no next record
*/
function fetch($type);
/**
* Frees the resources allocated for this result set.
*
* @param resource resultset resource
* @return void
*/
function free();
/**
* Frees the resources allocated for this result set.
*
* @param resource resultset resource
* @return void
*/
function free();
/**
* Returns metadata for all columns in a result set.
*
* @return array
* @throws DibiException
*/
function getColumnsMeta();
/**
* Returns metadata for all columns in a result set.
*
* @return array
* @throws DibiException
*/
function getColumnsMeta();
/**
* Returns the connection resource.
*
* @return mixed
*/
function getResource();
/**
* Returns the connection resource.
*
* @return mixed
*/
function getResource();
/**
* Returns the resultset resource.
*
* @return mixed
*/
function getResultResource();
/**
* Returns the resultset resource.
*
* @return mixed
*/
function getResultResource();
/**
* Gets a information of the current database.
*
* @return DibiReflection
*/
function getDibiReflection();
/**
* Gets a information of the current database.
*
* @return DibiReflection
*/
function getDibiReflection();
}