1
0
mirror of https://github.com/dg/dibi.git synced 2025-02-24 02:43:09 +01:00
php-dibi/dibi/dibi.php

519 lines
12 KiB
PHP
Raw Normal View History

2006-06-04 23:06:33 +00:00
<?php
/**
* dibi - Database Abstraction Layer according to dgx
* --------------------------------------------------
*
2007-06-19 21:12:28 +00:00
* Copyright (c) 2005-2007 David Grudl aka -dgx- (http://www.dgx.cz)
2006-06-07 11:48:20 +00:00
*
2007-04-11 18:30:30 +00:00
* for PHP 5.0.3 and newer
2006-06-04 23:06:33 +00:00
*
2007-06-24 23:49:57 +00:00
* This source file is subject to the new BSD license that is bundled
2007-06-19 21:12:28 +00:00
* with this package in the file license.txt.
*
2007-06-24 23:49:57 +00:00
* @author David Grudl
2007-06-25 17:02:12 +00:00
* @copyright Copyright (c) 2005-2007 David Grudl aka -dgx- (http://www.dgx.cz)
2007-06-24 23:49:57 +00:00
* @license New BSD License
* @version 0.9a (Revision: $WCREV$, Date: $WCDATE$)
2007-06-24 23:49:57 +00:00
* @category Database
* @package Dibi
* @link http://php7.org/dibi/
2007-04-11 18:30:30 +00:00
*/
/**
* This file is part of the "dibi" project (http://php7.org/dibi/)
2007-04-11 18:30:30 +00:00
*
2007-06-24 23:49:57 +00:00
* @version $Revision$ $Date$
2006-06-04 23:06:33 +00:00
*/
if (version_compare(PHP_VERSION , '5.0.3', '<')) {
2006-06-04 23:06:33 +00:00
die('dibi needs PHP 5.0.3 or newer');
}
2006-06-04 23:06:33 +00:00
// libraries
require_once dirname(__FILE__).'/libs/driver.php';
require_once dirname(__FILE__).'/libs/resultset.php';
require_once dirname(__FILE__).'/libs/translator.php';
2006-06-04 23:06:33 +00:00
require_once dirname(__FILE__).'/libs/exception.php';
require_once dirname(__FILE__).'/libs/logger.php';
2006-06-04 23:06:33 +00:00
/**
* Interface for user variable, used for generating SQL
*/
2007-08-20 22:17:52 +00:00
interface DibiVariableInterface
2006-06-04 23:06:33 +00:00
{
/**
* Format for SQL
*
* @param object destination DibiDriver
* @param string optional modifier
* @return string SQL code
*/
public function toSQL($driver, $modifier = NULL);
}
/**
* Interface for database drivers
*
* This class is static container class for creating DB objects and
* store connections info.
2006-06-04 23:06:33 +00:00
*
*/
class dibi
{
2006-06-08 01:35:44 +00:00
/**
* Column type in relation to PHP native type
*/
const
FIELD_TEXT = 's', // as 'string'
2006-06-08 02:02:05 +00:00
FIELD_BINARY = 'S',
FIELD_BOOL = 'b',
2006-06-08 01:35:44 +00:00
FIELD_INTEGER = 'i',
FIELD_FLOAT = 'f',
FIELD_DATE = 'd',
FIELD_DATETIME = 't',
FIELD_UNKNOWN = '?',
// special
FIELD_COUNTER = 'c', // counter or autoincrement, is integer
// dibi version
VERSION = '0.9a (Revision: $WCREV$, Date: $WCDATE$)';
2006-06-08 01:35:44 +00:00
2006-06-04 23:06:33 +00:00
/**
* Connection registry storage for DibiDriver objects
* @var DibiDriver[]
2006-06-04 23:06:33 +00:00
*/
2007-06-25 23:47:05 +00:00
private static $registry = array();
2006-06-04 23:06:33 +00:00
/**
* Current connection
* @var DibiDriver
2006-06-04 23:06:33 +00:00
*/
2007-06-25 23:47:05 +00:00
private static $connection;
2006-06-04 23:06:33 +00:00
/**
* Substitutions for identifiers
* @var array
2006-06-04 23:06:33 +00:00
*/
private static $substs = array();
2006-06-04 23:06:33 +00:00
/**
* @see addHandler
* @var array
2006-06-04 23:06:33 +00:00
*/
private static $handlers = array();
/**
* Last SQL command @see dibi::query()
* @var string
*/
public static $sql;
2006-06-04 23:06:33 +00:00
/**
* Elapsed time for last query
* @var int
*/
public static $elapsedTime;
2006-06-04 23:06:33 +00:00
/**
* Elapsed time for all queries
* @var int
*/
public static $totalTime;
/**
* Number or queries
* @var int
*/
public static $numOfQueries = 0;
/**
* Default dibi driver
* @var string
*/
public static $defaultDriver = 'mysql';
/**
* Start time
* @var int
*/
private static $time;
2006-06-04 23:06:33 +00:00
/**
* Monostate class
*/
2007-08-27 22:38:14 +00:00
final private function __construct()
{}
2006-06-04 23:06:33 +00:00
/**
* Creates a new DibiDriver object and connects it to specified database
*
2006-07-19 01:40:29 +00:00
* @param array|string connection parameters
2006-06-04 23:06:33 +00:00
* @param string connection name
2007-05-30 00:01:10 +00:00
* @return DibiDriver
2007-06-24 23:49:57 +00:00
* @throws DibiException
2006-06-04 23:06:33 +00:00
*/
public static function connect($config = array(), $name = 0)
2006-06-04 23:06:33 +00:00
{
2006-07-19 01:40:29 +00:00
// DSN string
if (is_string($config)) {
2006-07-19 01:40:29 +00:00
parse_str($config, $config);
}
2006-06-04 23:06:33 +00:00
if (!isset($config['driver'])) {
$config['driver'] = self::$defaultDriver;
}
2006-06-04 23:06:33 +00:00
2007-08-27 22:38:14 +00:00
$class = "Dibi$config[driver]Driver";
if (!class_exists($class)) {
2006-09-13 12:02:38 +00:00
include_once dirname(__FILE__) . "/drivers/$config[driver].php";
2006-06-04 23:06:33 +00:00
2007-08-27 22:38:14 +00:00
if (!class_exists($class)) {
throw new DibiException("Unable to create instance of dibi driver class '$class'.");
}
2006-09-13 12:02:38 +00:00
}
2006-06-04 23:06:33 +00:00
// create connection object and store in list; like $connection = $class::connect($config);
return self::$connection = self::$registry[$name] = new $class($config);
2006-06-04 23:06:33 +00:00
}
/**
* Returns TRUE when connection was established
*
* @return bool
*/
2007-06-25 23:47:05 +00:00
public static function isConnected()
2006-06-04 23:06:33 +00:00
{
2007-06-25 17:02:12 +00:00
return (bool) self::$connection;
2006-06-04 23:06:33 +00:00
}
2007-08-23 00:57:28 +00:00
2006-06-04 23:06:33 +00:00
/**
* Retrieve active connection
*
* @param string connection registy name
2006-06-04 23:06:33 +00:00
* @return object DibiDriver object.
2007-06-24 23:49:57 +00:00
* @throws DibiException
2006-06-04 23:06:33 +00:00
*/
public static function getConnection($name = NULL)
2006-06-04 23:06:33 +00:00
{
if ($name === NULL) {
if (!self::$connection) {
throw new DibiException('Dibi is not connected to database');
}
2007-06-25 17:02:12 +00:00
return self::$connection;
}
2006-11-13 06:32:16 +00:00
if (!isset(self::$registry[$name])) {
throw new DibiException("There is no connection named '$name'.");
}
return self::$registry[$name];
2006-06-04 23:06:33 +00:00
}
2006-06-04 23:06:33 +00:00
/**
* Change active connection
*
* @param string connection registy name
* @return void
2007-06-24 23:49:57 +00:00
* @throws DibiException
2006-06-04 23:06:33 +00:00
*/
2007-06-25 23:47:05 +00:00
public static function activate($name)
2006-06-04 23:06:33 +00:00
{
2007-06-25 17:02:12 +00:00
self::$connection = self::getConnection($name);
2006-06-04 23:06:33 +00:00
}
/**
2007-04-25 06:44:38 +00:00
* Generates and executes SQL query - Monostate for DibiDriver::query()
2006-06-04 23:06:33 +00:00
*
2006-07-19 01:40:29 +00:00
* @param array|mixed one or more arguments
* @return DibiResult|TRUE
2007-06-24 23:49:57 +00:00
* @throws DibiException
2006-06-04 23:06:33 +00:00
*/
2007-06-25 23:47:05 +00:00
public static function query($args)
2006-06-04 23:06:33 +00:00
{
if (!is_array($args)) $args = func_get_args();
return self::getConnection()->query($args);
2006-06-04 23:06:33 +00:00
}
/**
* Executes the SQL query - Monostate for DibiDriver::nativeQuery()
*
* @param string SQL statement.
* @return DibiResult|TRUE
*/
public static function nativeQuery($sql)
{
return self::getConnection()->nativeQuery($sql);
}
/**
* Generates and prints SQL query - Monostate for DibiDriver::test()
2006-06-04 23:06:33 +00:00
*
2006-07-19 01:40:29 +00:00
* @param array|mixed one or more arguments
* @return bool
2006-06-04 23:06:33 +00:00
*/
2007-06-25 23:47:05 +00:00
public static function test($args)
2006-06-04 23:06:33 +00:00
{
if (!is_array($args)) $args = func_get_args();
2006-06-04 23:06:33 +00:00
return self::getConnection()->test($args);
2006-06-04 23:06:33 +00:00
}
/**
2007-04-25 06:44:38 +00:00
* Retrieves the ID generated for an AUTO_INCREMENT column by the previous INSERT query
2006-06-04 23:06:33 +00:00
* Monostate for DibiDriver::insertId()
*
* @param string optional sequence name for DibiPostgreDriver
* @return int|FALSE int on success or FALSE on failure
2006-06-04 23:06:33 +00:00
*/
public static function insertId($sequence=NULL)
2006-06-04 23:06:33 +00:00
{
return self::getConnection()->insertId($sequence);
2006-06-04 23:06:33 +00:00
}
/**
2007-04-25 06:44:38 +00:00
* Gets the number of affected rows
2006-06-04 23:06:33 +00:00
* Monostate for DibiDriver::affectedRows()
*
2007-04-25 06:44:38 +00:00
* @return int number of rows or FALSE on error
2006-06-04 23:06:33 +00:00
*/
2007-06-25 23:47:05 +00:00
public static function affectedRows()
2006-06-04 23:06:33 +00:00
{
2006-11-13 06:32:16 +00:00
return self::getConnection()->affectedRows();
2006-08-25 15:17:40 +00:00
}
2006-06-04 23:06:33 +00:00
/**
* Begins a transaction - Monostate for DibiDriver::begin()
*/
public static function begin()
{
self::getConnection()->begin();
}
/**
* Commits statements in a transaction - Monostate for DibiDriver::commit()
*/
public static function commit()
{
self::getConnection()->commit();
}
/**
* Rollback changes in a transaction - Monostate for DibiDriver::rollback()
*/
public static function rollback()
{
self::getConnection()->rollback();
2006-06-04 23:06:33 +00:00
}
/**
* Create a new substitution pair for indentifiers
*
* @param string from
* @param string to
* @return void
*/
2007-06-25 23:47:05 +00:00
public static function addSubst($expr, $subst)
{
self::$substs[':'.$expr.':'] = $subst;
}
2006-06-04 23:06:33 +00:00
2007-08-23 00:57:28 +00:00
/**
* Remove substitution pair
*
* @param mixed from or TRUE
* @return void
*/
2007-06-25 23:47:05 +00:00
public static function removeSubst($expr)
{
if ($expr === TRUE) {
self::$substs = array();
} else {
unset(self::$substs[':'.$expr.':']);
}
}
2006-06-04 23:06:33 +00:00
2007-08-23 00:57:28 +00:00
/**
* Returns substitution pairs
*
* @return array
*/
public static function getSubst()
{
return self::$substs;
}
2007-08-23 00:57:28 +00:00
2006-11-13 06:32:16 +00:00
/**
* Add new event handler
*
* @param callback
* @return void
*/
public static function addHandler($callback)
{
if (!is_callable($callback)) {
throw new DibiException("Invalid callback");
}
self::$handlers[] = $callback;
}
/**
* Event notification (events: exception, connected, beforeQuery, afterQuery, begin, commit, rollback)
*
* @param string event name
* @param DibiDriver
* @param mixed
* @return void
*/
public static function notify($event, DibiDriver $driver = NULL, $arg = NULL)
{
if ($event === 'beforeQuery') {
self::$numOfQueries++;
self::$elapsedTime = FALSE;
self::$time = -microtime(TRUE);
self::$sql = $arg;
} elseif ($event === 'afterQuery') {
self::$elapsedTime = self::$time + microtime(TRUE);
self::$totalTime += self::$elapsedTime;
}
foreach (self::$handlers as $handler) {
call_user_func($handler, $event, $driver, $arg);
}
}
/**
* Enable profiler & logger
*
* @param string filename
* @param bool log all queries?
* @return DibiProfiler
*/
public static function startLogger($file, $logQueries = FALSE)
{
$logger = new DibiLogger($file);
$logger->logQueries = $logQueries;
self::addHandler(array($logger, 'handler'));
return $logger;
}
/**
* Prints out a syntax highlighted version of the SQL command or DibiResult
*
* @param string|DibiResult
* @param bool return or print?
* @return string
*/
public static function dump($sql = NULL, $return = FALSE)
{
ob_start();
if ($sql instanceof DibiResult) {
$sql->dump();
} else {
if ($sql === NULL) $sql = self::$sql;
static $keywords2 = 'ALL|DISTINCT|AS|ON|INTO|AND|OR|AS';
static $keywords1 = 'SELECT|UPDATE|INSERT|DELETE|FROM|WHERE|HAVING|GROUP\s+BY|ORDER\s+BY|LIMIT|SET|VALUES|LEFT\s+JOIN|INNER\s+JOIN';
// insert new lines
$sql = preg_replace("#\\b(?:$keywords1)\\b#", "\n\$0", $sql);
$sql = trim($sql);
// reduce spaces
$sql = preg_replace('# {2,}#', ' ', $sql);
$sql = wordwrap($sql, 100);
$sql = htmlSpecialChars($sql);
$sql = preg_replace("#\n{2,}#", "\n", $sql);
// syntax highlight
$sql = preg_replace_callback("#(/\\*.+?\\*/)|(\\*\\*.+?\\*\\*)|\\b($keywords1)\\b|\\b($keywords2)\\b#", array('dibi', 'highlightCallback'), $sql);
echo '<pre class="dump">', $sql, "</pre>\n";
}
if ($return) {
return ob_get_clean();
} else {
ob_end_flush();
}
}
private static function highlightCallback($matches)
2006-11-13 06:32:16 +00:00
{
if (!empty($matches[1])) // comment
return '<em style="color:gray">'.$matches[1].'</em>';
2006-06-04 23:06:33 +00:00
if (!empty($matches[2])) // error
return '<strong style="color:red">'.$matches[2].'</strong>';
2006-06-04 23:06:33 +00:00
if (!empty($matches[3])) // most important keywords
return '<strong style="color:blue">'.$matches[3].'</strong>';
if (!empty($matches[4])) // other keywords
return '<strong style="color:green">'.$matches[4].'</strong>';
}
} // class dibi