Added Kohana v3.0.9
This commit is contained in:
3
includes/kohana/modules/database/classes/database.php
Normal file
3
includes/kohana/modules/database/classes/database.php
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
abstract class Database extends Kohana_Database {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Database_Exception extends Kohana_Database_Exception {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Database_Expression extends Kohana_Database_Expression {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Database_MySQL extends Kohana_Database_MySQL {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Database_MySQL_Result extends Kohana_Database_MySQL_Result {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Database_PDO extends Kohana_Database_PDO {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Database_Query extends Kohana_Database_Query {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
abstract class Database_Query_Builder extends Kohana_Database_Query_Builder {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Database_Query_Builder_Delete extends Kohana_Database_Query_Builder_Delete {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Database_Query_Builder_Insert extends Kohana_Database_Query_Builder_Insert {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Database_Query_Builder_Join extends Kohana_Database_Query_Builder_Join {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Database_Query_Builder_Select extends Kohana_Database_Query_Builder_Select {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Database_Query_Builder_Update extends Kohana_Database_Query_Builder_Update {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
abstract class Database_Query_Builder_Where extends Kohana_Database_Query_Builder_Where {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
abstract class Database_Result extends Kohana_Database_Result {}
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Database_Result_Cached extends Kohana_Database_Result_Cached {}
|
3
includes/kohana/modules/database/classes/db.php
Normal file
3
includes/kohana/modules/database/classes/db.php
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class DB extends Kohana_DB {}
|
@@ -0,0 +1,97 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database-based configuration loader.
|
||||
*
|
||||
* Schema for configuration table:
|
||||
*
|
||||
* group_name varchar(128)
|
||||
* config_key varchar(128)
|
||||
* config_value text
|
||||
* primary key (group_name, config_key)
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Configuration
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Config_Database extends Kohana_Config_Reader {
|
||||
|
||||
protected $_database_instance = 'default';
|
||||
|
||||
protected $_database_table = 'config';
|
||||
|
||||
public function __construct(array $config = NULL)
|
||||
{
|
||||
if (isset($config['instance']))
|
||||
{
|
||||
$this->_database_instance = $config['instance'];
|
||||
}
|
||||
|
||||
if (isset($config['table']))
|
||||
{
|
||||
$this->_database_table = $config['table'];
|
||||
}
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the configuration table for all values for this group and
|
||||
* unserialize each of the values.
|
||||
*
|
||||
* @param string group name
|
||||
* @param array configuration array
|
||||
* @return $this clone of the current object
|
||||
*/
|
||||
public function load($group, array $config = NULL)
|
||||
{
|
||||
if ($config === NULL AND $group !== 'database')
|
||||
{
|
||||
// Load all of the configuration values for this group
|
||||
$query = DB::select('config_key', 'config_value')
|
||||
->from($this->_database_table)
|
||||
->where('group_name', '=', $group)
|
||||
->execute($this->_database_instance);
|
||||
|
||||
if (count($query) > 0)
|
||||
{
|
||||
// Unserialize the configuration values
|
||||
$config = array_map('unserialize', $query->as_array('config_key', 'config_value'));
|
||||
}
|
||||
}
|
||||
|
||||
return parent::load($group, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload setting offsets to insert or update the database values as
|
||||
* changes occur.
|
||||
*
|
||||
* @param string array key
|
||||
* @param mixed new value
|
||||
* @return mixed
|
||||
*/
|
||||
public function offsetSet($key, $value)
|
||||
{
|
||||
if ( ! $this->offsetExists($key))
|
||||
{
|
||||
// Insert a new value
|
||||
DB::insert($this->_database_table, array('group_name', 'config_key', 'config_value'))
|
||||
->values(array($this->_configuration_group, $key, serialize($value)))
|
||||
->execute($this->_database_instance);
|
||||
}
|
||||
elseif ($this->offsetGet($key) !== $value)
|
||||
{
|
||||
// Update the value
|
||||
DB::update($this->_database_table)
|
||||
->value('config_value', serialize($value))
|
||||
->where('group_name', '=', $this->_configuration_group)
|
||||
->where('config_key', '=', $key)
|
||||
->execute($this->_database_instance);
|
||||
}
|
||||
|
||||
return parent::offsetSet($key, $value);
|
||||
}
|
||||
|
||||
} // End Kohana_Config_Database
|
600
includes/kohana/modules/database/classes/kohana/database.php
Normal file
600
includes/kohana/modules/database/classes/kohana/database.php
Normal file
@@ -0,0 +1,600 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database connection wrapper/helper.
|
||||
*
|
||||
* You may get a database instance using `Database::instance('name')` where
|
||||
* name is the [config](database/config) group.
|
||||
*
|
||||
* This class provides connection instance management via Database Drivers, as
|
||||
* well as quoting, escaping and other related functions. Querys are done using
|
||||
* [Database_Query] and [Database_Query_Builder] objects, which can be easily
|
||||
* created using the [DB] helper class.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Base
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
abstract class Kohana_Database {
|
||||
|
||||
// Query types
|
||||
const SELECT = 1;
|
||||
const INSERT = 2;
|
||||
const UPDATE = 3;
|
||||
const DELETE = 4;
|
||||
|
||||
/**
|
||||
* @var string default instance name
|
||||
*/
|
||||
public static $default = 'default';
|
||||
|
||||
/**
|
||||
* @var array Database instances
|
||||
*/
|
||||
public static $instances = array();
|
||||
|
||||
/**
|
||||
* Get a singleton Database instance. If configuration is not specified,
|
||||
* it will be loaded from the database configuration file using the same
|
||||
* group as the name.
|
||||
*
|
||||
* // Load the default database
|
||||
* $db = Database::instance();
|
||||
*
|
||||
* // Create a custom configured instance
|
||||
* $db = Database::instance('custom', $config);
|
||||
*
|
||||
* @param string instance name
|
||||
* @param array configuration parameters
|
||||
* @return Database
|
||||
*/
|
||||
public static function instance($name = NULL, array $config = NULL)
|
||||
{
|
||||
if ($name === NULL)
|
||||
{
|
||||
// Use the default instance name
|
||||
$name = Database::$default;
|
||||
}
|
||||
|
||||
if ( ! isset(Database::$instances[$name]))
|
||||
{
|
||||
if ($config === NULL)
|
||||
{
|
||||
// Load the configuration for this database
|
||||
$config = Kohana::config('database')->$name;
|
||||
}
|
||||
|
||||
if ( ! isset($config['type']))
|
||||
{
|
||||
throw new Kohana_Exception('Database type not defined in :name configuration',
|
||||
array(':name' => $name));
|
||||
}
|
||||
|
||||
// Set the driver class name
|
||||
$driver = 'Database_'.ucfirst($config['type']);
|
||||
|
||||
// Create the database connection instance
|
||||
new $driver($name, $config);
|
||||
}
|
||||
|
||||
return Database::$instances[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* @var string the last query executed
|
||||
*/
|
||||
public $last_query;
|
||||
|
||||
// Character that is used to quote identifiers
|
||||
protected $_identifier = '"';
|
||||
|
||||
// Instance name
|
||||
protected $_instance;
|
||||
|
||||
// Raw server connection
|
||||
protected $_connection;
|
||||
|
||||
// Configuration array
|
||||
protected $_config;
|
||||
|
||||
/**
|
||||
* Stores the database configuration locally and name the instance.
|
||||
*
|
||||
* [!!] This method cannot be accessed directly, you must use [Database::instance].
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function __construct($name, array $config)
|
||||
{
|
||||
// Set the instance name
|
||||
$this->_instance = $name;
|
||||
|
||||
// Store the config locally
|
||||
$this->_config = $config;
|
||||
|
||||
// Store the database instance
|
||||
Database::$instances[$name] = $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the database when the object is destroyed.
|
||||
*
|
||||
* // Destroy the database instance
|
||||
* unset(Database::instances[(string) $db], $db);
|
||||
*
|
||||
* [!!] Calling `unset($db)` is not enough to destroy the database, as it
|
||||
* will still be stored in `Database::$instances`.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
final public function __destruct()
|
||||
{
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the database instance name.
|
||||
*
|
||||
* echo (string) $db;
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final public function __toString()
|
||||
{
|
||||
return $this->_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the database. This is called automatically when the first
|
||||
* query is executed.
|
||||
*
|
||||
* $db->connect();
|
||||
*
|
||||
* @throws Database_Exception
|
||||
* @return void
|
||||
*/
|
||||
abstract public function connect();
|
||||
|
||||
/**
|
||||
* Disconnect from the database. This is called automatically by [Database::__destruct].
|
||||
*
|
||||
* $db->disconnect();
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function disconnect();
|
||||
|
||||
/**
|
||||
* Set the connection character set. This is called automatically by [Database::connect].
|
||||
*
|
||||
* $db->set_charset('utf8');
|
||||
*
|
||||
* @throws Database_Exception
|
||||
* @param string character set name
|
||||
* @return void
|
||||
*/
|
||||
abstract public function set_charset($charset);
|
||||
|
||||
/**
|
||||
* Perform an SQL query of the given type.
|
||||
*
|
||||
* // Make a SELECT query and use objects for results
|
||||
* $db->query(Database::SELECT, 'SELECT * FROM groups', TRUE);
|
||||
*
|
||||
* // Make a SELECT query and use "Model_User" for the results
|
||||
* $db->query(Database::SELECT, 'SELECT * FROM users LIMIT 1', 'Model_User');
|
||||
*
|
||||
* @param integer Database::SELECT, Database::INSERT, etc
|
||||
* @param string SQL query
|
||||
* @param mixed result object class string, TRUE for stdClass, FALSE for assoc array
|
||||
* @param array object construct parameters for result class
|
||||
* @return object Database_Result for SELECT queries
|
||||
* @return array list (insert id, row count) for INSERT queries
|
||||
* @return integer number of affected rows for all other queries
|
||||
*/
|
||||
abstract public function query($type, $sql, $as_object = FALSE, array $params = NULL);
|
||||
|
||||
/**
|
||||
* Count the number of records in the last query, without LIMIT or OFFSET applied.
|
||||
*
|
||||
* // Get the total number of records that match the last query
|
||||
* $count = $db->count_last_query();
|
||||
*
|
||||
* @deprecated since v3.0.9
|
||||
* @return integer
|
||||
*/
|
||||
public function count_last_query()
|
||||
{
|
||||
if ($sql = $this->last_query)
|
||||
{
|
||||
$sql = trim($sql);
|
||||
if (stripos($sql, 'SELECT') !== 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (stripos($sql, 'LIMIT') !== FALSE)
|
||||
{
|
||||
// Remove LIMIT from the SQL
|
||||
$sql = preg_replace('/\sLIMIT\s+[^a-z]+/i', ' ', $sql);
|
||||
}
|
||||
|
||||
if (stripos($sql, 'OFFSET') !== FALSE)
|
||||
{
|
||||
// Remove OFFSET from the SQL
|
||||
$sql = preg_replace('/\sOFFSET\s+\d+/i', '', $sql);
|
||||
}
|
||||
|
||||
// Get the total rows from the last query executed
|
||||
$result = $this->query
|
||||
(
|
||||
Database::SELECT,
|
||||
'SELECT COUNT(*) AS '.$this->quote_identifier('total_rows').' '
|
||||
.'FROM ('.$sql.') AS '.$this->quote_table('counted_results'),
|
||||
TRUE
|
||||
);
|
||||
|
||||
// Return the total number of rows from the query
|
||||
return (int) $result->current()->total_rows;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of records in a table.
|
||||
*
|
||||
* // Get the total number of records in the "users" table
|
||||
* $count = $db->count_records('users');
|
||||
*
|
||||
* @param mixed table name string or array(query, alias)
|
||||
* @return integer
|
||||
*/
|
||||
public function count_records($table)
|
||||
{
|
||||
// Quote the table name
|
||||
$table = $this->quote_identifier($table);
|
||||
|
||||
return $this->query(Database::SELECT, 'SELECT COUNT(*) AS total_row_count FROM '.$table, FALSE)
|
||||
->get('total_row_count');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a normalized array describing the SQL data type
|
||||
*
|
||||
* $db->datatype('char');
|
||||
*
|
||||
* @param string SQL data type
|
||||
* @return array
|
||||
*/
|
||||
public function datatype($type)
|
||||
{
|
||||
static $types = array
|
||||
(
|
||||
// SQL-92
|
||||
'bit' => array('type' => 'string', 'exact' => TRUE),
|
||||
'bit varying' => array('type' => 'string'),
|
||||
'char' => array('type' => 'string', 'exact' => TRUE),
|
||||
'char varying' => array('type' => 'string'),
|
||||
'character' => array('type' => 'string', 'exact' => TRUE),
|
||||
'character varying' => array('type' => 'string'),
|
||||
'date' => array('type' => 'string'),
|
||||
'dec' => array('type' => 'float', 'exact' => TRUE),
|
||||
'decimal' => array('type' => 'float', 'exact' => TRUE),
|
||||
'double precision' => array('type' => 'float'),
|
||||
'float' => array('type' => 'float'),
|
||||
'int' => array('type' => 'int', 'min' => '-2147483648', 'max' => '2147483647'),
|
||||
'integer' => array('type' => 'int', 'min' => '-2147483648', 'max' => '2147483647'),
|
||||
'interval' => array('type' => 'string'),
|
||||
'national char' => array('type' => 'string', 'exact' => TRUE),
|
||||
'national char varying' => array('type' => 'string'),
|
||||
'national character' => array('type' => 'string', 'exact' => TRUE),
|
||||
'national character varying' => array('type' => 'string'),
|
||||
'nchar' => array('type' => 'string', 'exact' => TRUE),
|
||||
'nchar varying' => array('type' => 'string'),
|
||||
'numeric' => array('type' => 'float', 'exact' => TRUE),
|
||||
'real' => array('type' => 'float'),
|
||||
'smallint' => array('type' => 'int', 'min' => '-32768', 'max' => '32767'),
|
||||
'time' => array('type' => 'string'),
|
||||
'time with time zone' => array('type' => 'string'),
|
||||
'timestamp' => array('type' => 'string'),
|
||||
'timestamp with time zone' => array('type' => 'string'),
|
||||
'varchar' => array('type' => 'string'),
|
||||
|
||||
// SQL:1999
|
||||
'binary large object' => array('type' => 'string', 'binary' => TRUE),
|
||||
'blob' => array('type' => 'string', 'binary' => TRUE),
|
||||
'boolean' => array('type' => 'bool'),
|
||||
'char large object' => array('type' => 'string'),
|
||||
'character large object' => array('type' => 'string'),
|
||||
'clob' => array('type' => 'string'),
|
||||
'national character large object' => array('type' => 'string'),
|
||||
'nchar large object' => array('type' => 'string'),
|
||||
'nclob' => array('type' => 'string'),
|
||||
'time without time zone' => array('type' => 'string'),
|
||||
'timestamp without time zone' => array('type' => 'string'),
|
||||
|
||||
// SQL:2003
|
||||
'bigint' => array('type' => 'int', 'min' => '-9223372036854775808', 'max' => '9223372036854775807'),
|
||||
|
||||
// SQL:2008
|
||||
'binary' => array('type' => 'string', 'binary' => TRUE, 'exact' => TRUE),
|
||||
'binary varying' => array('type' => 'string', 'binary' => TRUE),
|
||||
'varbinary' => array('type' => 'string', 'binary' => TRUE),
|
||||
);
|
||||
|
||||
if (isset($types[$type]))
|
||||
return $types[$type];
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* List all of the tables in the database. Optionally, a LIKE string can
|
||||
* be used to search for specific tables.
|
||||
*
|
||||
* // Get all tables in the current database
|
||||
* $tables = $db->list_tables();
|
||||
*
|
||||
* // Get all user-related tables
|
||||
* $tables = $db->list_tables('user%');
|
||||
*
|
||||
* @param string table to search for
|
||||
* @return array
|
||||
*/
|
||||
abstract public function list_tables($like = NULL);
|
||||
|
||||
/**
|
||||
* Lists all of the columns in a table. Optionally, a LIKE string can be
|
||||
* used to search for specific fields.
|
||||
*
|
||||
* // Get all columns from the "users" table
|
||||
* $columns = $db->list_columns('users');
|
||||
*
|
||||
* // Get all name-related columns
|
||||
* $columns = $db->list_columns('users', '%name%');
|
||||
*
|
||||
* // Get the columns from a table that doesn't use the table prefix
|
||||
* $columns = $db->list_columns('users', NULL, FALSE);
|
||||
*
|
||||
* @param string table to get columns from
|
||||
* @param string column to search for
|
||||
* @param boolean whether to add the table prefix automatically or not
|
||||
* @return array
|
||||
*/
|
||||
abstract public function list_columns($table, $like = NULL, $add_prefix = TRUE);
|
||||
|
||||
/**
|
||||
* Extracts the text between parentheses, if any.
|
||||
*
|
||||
* // Returns: array('CHAR', '6')
|
||||
* list($type, $length) = $db->_parse_type('CHAR(6)');
|
||||
*
|
||||
* @param string
|
||||
* @return array list containing the type and length, if any
|
||||
*/
|
||||
protected function _parse_type($type)
|
||||
{
|
||||
if (($open = strpos($type, '(')) === FALSE)
|
||||
{
|
||||
// No length specified
|
||||
return array($type, NULL);
|
||||
}
|
||||
|
||||
// Closing parenthesis
|
||||
$close = strpos($type, ')', $open);
|
||||
|
||||
// Length without parentheses
|
||||
$length = substr($type, $open + 1, $close - 1 - $open);
|
||||
|
||||
// Type without the length
|
||||
$type = substr($type, 0, $open).substr($type, $close + 1);
|
||||
|
||||
return array($type, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the table prefix defined in the current configuration.
|
||||
*
|
||||
* $prefix = $db->table_prefix();
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function table_prefix()
|
||||
{
|
||||
return $this->_config['table_prefix'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote a value for an SQL query.
|
||||
*
|
||||
* $db->quote(NULL); // 'NULL'
|
||||
* $db->quote(10); // 10
|
||||
* $db->quote('fred'); // 'fred'
|
||||
*
|
||||
* Objects passed to this function will be converted to strings.
|
||||
* [Database_Expression] objects will use the value of the expression.
|
||||
* [Database_Query] objects will be compiled and converted to a sub-query.
|
||||
* All other objects will be converted using the `__toString` method.
|
||||
*
|
||||
* @param mixed any value to quote
|
||||
* @return string
|
||||
* @uses Database::escape
|
||||
*/
|
||||
public function quote($value)
|
||||
{
|
||||
if ($value === NULL)
|
||||
{
|
||||
return 'NULL';
|
||||
}
|
||||
elseif ($value === TRUE)
|
||||
{
|
||||
return "'1'";
|
||||
}
|
||||
elseif ($value === FALSE)
|
||||
{
|
||||
return "'0'";
|
||||
}
|
||||
elseif (is_object($value))
|
||||
{
|
||||
if ($value instanceof Database_Query)
|
||||
{
|
||||
// Create a sub-query
|
||||
return '('.$value->compile($this).')';
|
||||
}
|
||||
elseif ($value instanceof Database_Expression)
|
||||
{
|
||||
// Use a raw expression
|
||||
return $value->value();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert the object to a string
|
||||
return $this->quote( (string) $value);
|
||||
}
|
||||
}
|
||||
elseif (is_array($value))
|
||||
{
|
||||
return '('.implode(', ', array_map(array($this, __FUNCTION__), $value)).')';
|
||||
}
|
||||
elseif (is_int($value))
|
||||
{
|
||||
return (int) $value;
|
||||
}
|
||||
elseif (is_float($value))
|
||||
{
|
||||
// Convert to non-locale aware float to prevent possible commas
|
||||
return sprintf('%F', $value);
|
||||
}
|
||||
|
||||
return $this->escape($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote a database table name and adds the table prefix if needed.
|
||||
*
|
||||
* $table = $db->quote_table($table);
|
||||
*
|
||||
* @param mixed table name or array(table, alias)
|
||||
* @return string
|
||||
* @uses Database::quote_identifier
|
||||
* @uses Database::table_prefix
|
||||
*/
|
||||
public function quote_table($value)
|
||||
{
|
||||
// Assign the table by reference from the value
|
||||
if (is_array($value))
|
||||
{
|
||||
$table =& $value[0];
|
||||
|
||||
// Attach table prefix to alias
|
||||
$value[1] = $this->table_prefix().$value[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
$table =& $value;
|
||||
}
|
||||
|
||||
if (is_string($table) AND strpos($table, '.') === FALSE)
|
||||
{
|
||||
// Add the table prefix for tables
|
||||
$table = $this->table_prefix().$table;
|
||||
}
|
||||
|
||||
return $this->quote_identifier($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote a database identifier, such as a column name. Adds the
|
||||
* table prefix to the identifier if a table name is present.
|
||||
*
|
||||
* $column = $db->quote_identifier($column);
|
||||
*
|
||||
* You can also use SQL methods within identifiers.
|
||||
*
|
||||
* // The value of "column" will be quoted
|
||||
* $column = $db->quote_identifier('COUNT("column")');
|
||||
*
|
||||
* Objects passed to this function will be converted to strings.
|
||||
* [Database_Expression] objects will use the value of the expression.
|
||||
* [Database_Query] objects will be compiled and converted to a sub-query.
|
||||
* All other objects will be converted using the `__toString` method.
|
||||
*
|
||||
* @param mixed any identifier
|
||||
* @return string
|
||||
* @uses Database::table_prefix
|
||||
*/
|
||||
public function quote_identifier($value)
|
||||
{
|
||||
if ($value === '*')
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
elseif (is_object($value))
|
||||
{
|
||||
if ($value instanceof Database_Query)
|
||||
{
|
||||
// Create a sub-query
|
||||
return '('.$value->compile($this).')';
|
||||
}
|
||||
elseif ($value instanceof Database_Expression)
|
||||
{
|
||||
// Use a raw expression
|
||||
return $value->value();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert the object to a string
|
||||
return $this->quote_identifier( (string) $value);
|
||||
}
|
||||
}
|
||||
elseif (is_array($value))
|
||||
{
|
||||
// Separate the column and alias
|
||||
list ($value, $alias) = $value;
|
||||
|
||||
return $this->quote_identifier($value).' AS '.$this->quote_identifier($alias);
|
||||
}
|
||||
|
||||
if (strpos($value, '"') !== FALSE)
|
||||
{
|
||||
// Quote the column in FUNC("ident") identifiers
|
||||
return preg_replace('/"(.+?)"/e', '$this->quote_identifier("$1")', $value);
|
||||
}
|
||||
elseif (strpos($value, '.') !== FALSE)
|
||||
{
|
||||
// Split the identifier into the individual parts
|
||||
$parts = explode('.', $value);
|
||||
|
||||
if ($prefix = $this->table_prefix())
|
||||
{
|
||||
// Get the offset of the table name, 2nd-to-last part
|
||||
// This works for databases that can have 3 identifiers (Postgre)
|
||||
$offset = count($parts) - 2;
|
||||
|
||||
// Add the table prefix to the table name
|
||||
$parts[$offset] = $prefix.$parts[$offset];
|
||||
}
|
||||
|
||||
// Quote each of the parts
|
||||
return implode('.', array_map(array($this, __FUNCTION__), $parts));
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->_identifier.$value.$this->_identifier;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize a string by escaping characters that could cause an SQL
|
||||
* injection attack.
|
||||
*
|
||||
* $value = $db->escape('any string');
|
||||
*
|
||||
* @param string value to quote
|
||||
* @return string
|
||||
*/
|
||||
abstract public function escape($value);
|
||||
|
||||
} // End Database_Connection
|
@@ -0,0 +1,11 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database exceptions.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Exceptions
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Database_Exception extends Kohana_Exception {}
|
@@ -0,0 +1,62 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database expressions can be used to add unescaped SQL fragments to a
|
||||
* [Database_Query_Builder] object.
|
||||
*
|
||||
* For example, you can use an expression to generate a column alias:
|
||||
*
|
||||
* // SELECT CONCAT(first_name, last_name) AS full_name
|
||||
* $query = DB::select(array(DB::expr('CONCAT(first_name, last_name)'), 'full_name')));
|
||||
*
|
||||
* More examples are available on the [Query Builder](database/query/builder#database-expressions) page
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Base
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Database_Expression {
|
||||
|
||||
// Raw expression string
|
||||
protected $_value;
|
||||
|
||||
/**
|
||||
* Sets the expression string.
|
||||
*
|
||||
* $expression = new Database_Expression('COUNT(users.id)');
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($value)
|
||||
{
|
||||
// Set the expression string
|
||||
$this->_value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the expression value as a string.
|
||||
*
|
||||
* $sql = $expression->value();
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function value()
|
||||
{
|
||||
return (string) $this->_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of the expression as a string.
|
||||
*
|
||||
* echo $expression;
|
||||
*
|
||||
* @return string
|
||||
* @uses Database_Expression::value
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->value();
|
||||
}
|
||||
|
||||
} // End Database_Expression
|
@@ -0,0 +1,379 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* MySQL database connection.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Drivers
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Database_MySQL extends Database {
|
||||
|
||||
// Database in use by each connection
|
||||
protected static $_current_databases = array();
|
||||
|
||||
// Use SET NAMES to set the character set
|
||||
protected static $_set_names;
|
||||
|
||||
// Identifier for this connection within the PHP driver
|
||||
protected $_connection_id;
|
||||
|
||||
// MySQL uses a backtick for identifiers
|
||||
protected $_identifier = '`';
|
||||
|
||||
public function connect()
|
||||
{
|
||||
if ($this->_connection)
|
||||
return;
|
||||
|
||||
if (Database_MySQL::$_set_names === NULL)
|
||||
{
|
||||
// Determine if we can use mysql_set_charset(), which is only
|
||||
// available on PHP 5.2.3+ when compiled against MySQL 5.0+
|
||||
Database_MySQL::$_set_names = ! function_exists('mysql_set_charset');
|
||||
}
|
||||
|
||||
// Extract the connection parameters, adding required variabels
|
||||
extract($this->_config['connection'] + array(
|
||||
'database' => '',
|
||||
'hostname' => '',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'persistent' => FALSE,
|
||||
));
|
||||
|
||||
// Prevent this information from showing up in traces
|
||||
unset($this->_config['connection']['username'], $this->_config['connection']['password']);
|
||||
|
||||
try
|
||||
{
|
||||
if ($persistent)
|
||||
{
|
||||
// Create a persistent connection
|
||||
$this->_connection = mysql_pconnect($hostname, $username, $password);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a connection and force it to be a new link
|
||||
$this->_connection = mysql_connect($hostname, $username, $password, TRUE);
|
||||
}
|
||||
}
|
||||
catch (ErrorException $e)
|
||||
{
|
||||
// No connection exists
|
||||
$this->_connection = NULL;
|
||||
|
||||
throw new Database_Exception(':error', array(
|
||||
':error' => mysql_error(),
|
||||
),
|
||||
mysql_errno());
|
||||
}
|
||||
|
||||
// \xFF is a better delimiter, but the PHP driver uses underscore
|
||||
$this->_connection_id = sha1($hostname.'_'.$username.'_'.$password);
|
||||
|
||||
$this->_select_db($database);
|
||||
|
||||
if ( ! empty($this->_config['charset']))
|
||||
{
|
||||
// Set the character set
|
||||
$this->set_charset($this->_config['charset']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the database
|
||||
*
|
||||
* @param string Database
|
||||
* @return void
|
||||
*/
|
||||
protected function _select_db($database)
|
||||
{
|
||||
if ( ! mysql_select_db($database, $this->_connection))
|
||||
{
|
||||
// Unable to select database
|
||||
throw new Database_Exception(':error',
|
||||
array(':error' => mysql_error($this->_connection)),
|
||||
mysql_errno($this->_connection));
|
||||
}
|
||||
|
||||
Database_MySQL::$_current_databases[$this->_connection_id] = $database;
|
||||
}
|
||||
|
||||
public function disconnect()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Database is assumed disconnected
|
||||
$status = TRUE;
|
||||
|
||||
if (is_resource($this->_connection))
|
||||
{
|
||||
if ($status = mysql_close($this->_connection))
|
||||
{
|
||||
// Clear the connection
|
||||
$this->_connection = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Database is probably not disconnected
|
||||
$status = ! is_resource($this->_connection);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
public function set_charset($charset)
|
||||
{
|
||||
// Make sure the database is connected
|
||||
$this->_connection or $this->connect();
|
||||
|
||||
if (Database_MySQL::$_set_names === TRUE)
|
||||
{
|
||||
// PHP is compiled against MySQL 4.x
|
||||
$status = (bool) mysql_query('SET NAMES '.$this->quote($charset), $this->_connection);
|
||||
}
|
||||
else
|
||||
{
|
||||
// PHP is compiled against MySQL 5.x
|
||||
$status = mysql_set_charset($charset, $this->_connection);
|
||||
}
|
||||
|
||||
if ($status === FALSE)
|
||||
{
|
||||
throw new Database_Exception(':error',
|
||||
array(':error' => mysql_error($this->_connection)),
|
||||
mysql_errno($this->_connection));
|
||||
}
|
||||
}
|
||||
|
||||
public function query($type, $sql, $as_object = FALSE, array $params = NULL)
|
||||
{
|
||||
// Make sure the database is connected
|
||||
$this->_connection or $this->connect();
|
||||
|
||||
if ( ! empty($this->_config['profiling']))
|
||||
{
|
||||
// Benchmark this query for the current instance
|
||||
$benchmark = Profiler::start("Database ({$this->_instance})", $sql);
|
||||
}
|
||||
|
||||
if ( ! empty($this->_config['connection']['persistent']) AND $this->_config['connection']['database'] !== Database_MySQL::$_current_databases[$this->_connection_id])
|
||||
{
|
||||
// Select database on persistent connections
|
||||
$this->_select_db($this->_config['connection']['database']);
|
||||
}
|
||||
|
||||
// Execute the query
|
||||
if (($result = mysql_query($sql, $this->_connection)) === FALSE)
|
||||
{
|
||||
if (isset($benchmark))
|
||||
{
|
||||
// This benchmark is worthless
|
||||
Profiler::delete($benchmark);
|
||||
}
|
||||
|
||||
throw new Database_Exception(':error [ :query ]',
|
||||
array(':error' => mysql_error($this->_connection), ':query' => $sql),
|
||||
mysql_errno($this->_connection));
|
||||
}
|
||||
|
||||
if (isset($benchmark))
|
||||
{
|
||||
Profiler::stop($benchmark);
|
||||
}
|
||||
|
||||
// Set the last query
|
||||
$this->last_query = $sql;
|
||||
|
||||
if ($type === Database::SELECT)
|
||||
{
|
||||
// Return an iterator of results
|
||||
return new Database_MySQL_Result($result, $sql, $as_object, $params);
|
||||
}
|
||||
elseif ($type === Database::INSERT)
|
||||
{
|
||||
// Return a list of insert id and rows created
|
||||
return array(
|
||||
mysql_insert_id($this->_connection),
|
||||
mysql_affected_rows($this->_connection),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return the number of rows affected
|
||||
return mysql_affected_rows($this->_connection);
|
||||
}
|
||||
}
|
||||
|
||||
public function datatype($type)
|
||||
{
|
||||
static $types = array
|
||||
(
|
||||
'blob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '65535'),
|
||||
'bool' => array('type' => 'bool'),
|
||||
'bigint unsigned' => array('type' => 'int', 'min' => '0', 'max' => '18446744073709551615'),
|
||||
'datetime' => array('type' => 'string'),
|
||||
'decimal unsigned' => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
|
||||
'double' => array('type' => 'float'),
|
||||
'double precision unsigned' => array('type' => 'float', 'min' => '0'),
|
||||
'double unsigned' => array('type' => 'float', 'min' => '0'),
|
||||
'enum' => array('type' => 'string'),
|
||||
'fixed' => array('type' => 'float', 'exact' => TRUE),
|
||||
'fixed unsigned' => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
|
||||
'float unsigned' => array('type' => 'float', 'min' => '0'),
|
||||
'int unsigned' => array('type' => 'int', 'min' => '0', 'max' => '4294967295'),
|
||||
'integer unsigned' => array('type' => 'int', 'min' => '0', 'max' => '4294967295'),
|
||||
'longblob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '4294967295'),
|
||||
'longtext' => array('type' => 'string', 'character_maximum_length' => '4294967295'),
|
||||
'mediumblob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '16777215'),
|
||||
'mediumint' => array('type' => 'int', 'min' => '-8388608', 'max' => '8388607'),
|
||||
'mediumint unsigned' => array('type' => 'int', 'min' => '0', 'max' => '16777215'),
|
||||
'mediumtext' => array('type' => 'string', 'character_maximum_length' => '16777215'),
|
||||
'national varchar' => array('type' => 'string'),
|
||||
'numeric unsigned' => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
|
||||
'nvarchar' => array('type' => 'string'),
|
||||
'point' => array('type' => 'string', 'binary' => TRUE),
|
||||
'real unsigned' => array('type' => 'float', 'min' => '0'),
|
||||
'set' => array('type' => 'string'),
|
||||
'smallint unsigned' => array('type' => 'int', 'min' => '0', 'max' => '65535'),
|
||||
'text' => array('type' => 'string', 'character_maximum_length' => '65535'),
|
||||
'tinyblob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '255'),
|
||||
'tinyint' => array('type' => 'int', 'min' => '-128', 'max' => '127'),
|
||||
'tinyint unsigned' => array('type' => 'int', 'min' => '0', 'max' => '255'),
|
||||
'tinytext' => array('type' => 'string', 'character_maximum_length' => '255'),
|
||||
'year' => array('type' => 'string'),
|
||||
);
|
||||
|
||||
$type = str_replace(' zerofill', '', $type);
|
||||
|
||||
if (isset($types[$type]))
|
||||
return $types[$type];
|
||||
|
||||
return parent::datatype($type);
|
||||
}
|
||||
|
||||
public function list_tables($like = NULL)
|
||||
{
|
||||
if (is_string($like))
|
||||
{
|
||||
// Search for table names
|
||||
$result = $this->query(Database::SELECT, 'SHOW TABLES LIKE '.$this->quote($like), FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find all table names
|
||||
$result = $this->query(Database::SELECT, 'SHOW TABLES', FALSE);
|
||||
}
|
||||
|
||||
$tables = array();
|
||||
foreach ($result as $row)
|
||||
{
|
||||
$tables[] = reset($row);
|
||||
}
|
||||
|
||||
return $tables;
|
||||
}
|
||||
|
||||
public function list_columns($table, $like = NULL, $add_prefix = TRUE)
|
||||
{
|
||||
// Quote the table name
|
||||
$table = ($add_prefix === TRUE) ? $this->quote_table($table) : $table;
|
||||
|
||||
if (is_string($like))
|
||||
{
|
||||
// Search for column names
|
||||
$result = $this->query(Database::SELECT, 'SHOW FULL COLUMNS FROM '.$table.' LIKE '.$this->quote($like), FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find all column names
|
||||
$result = $this->query(Database::SELECT, 'SHOW FULL COLUMNS FROM '.$table, FALSE);
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
$columns = array();
|
||||
foreach ($result as $row)
|
||||
{
|
||||
list($type, $length) = $this->_parse_type($row['Type']);
|
||||
|
||||
$column = $this->datatype($type);
|
||||
|
||||
$column['column_name'] = $row['Field'];
|
||||
$column['column_default'] = $row['Default'];
|
||||
$column['data_type'] = $type;
|
||||
$column['is_nullable'] = ($row['Null'] == 'YES');
|
||||
$column['ordinal_position'] = ++$count;
|
||||
|
||||
switch ($column['type'])
|
||||
{
|
||||
case 'float':
|
||||
if (isset($length))
|
||||
{
|
||||
list($column['numeric_precision'], $column['numeric_scale']) = explode(',', $length);
|
||||
}
|
||||
break;
|
||||
case 'int':
|
||||
if (isset($length))
|
||||
{
|
||||
// MySQL attribute
|
||||
$column['display'] = $length;
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
switch ($column['data_type'])
|
||||
{
|
||||
case 'binary':
|
||||
case 'varbinary':
|
||||
$column['character_maximum_length'] = $length;
|
||||
break;
|
||||
case 'char':
|
||||
case 'varchar':
|
||||
$column['character_maximum_length'] = $length;
|
||||
case 'text':
|
||||
case 'tinytext':
|
||||
case 'mediumtext':
|
||||
case 'longtext':
|
||||
$column['collation_name'] = $row['Collation'];
|
||||
break;
|
||||
case 'enum':
|
||||
case 'set':
|
||||
$column['collation_name'] = $row['Collation'];
|
||||
$column['options'] = explode('\',\'', substr($length, 1, -1));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// MySQL attributes
|
||||
$column['comment'] = $row['Comment'];
|
||||
$column['extra'] = $row['Extra'];
|
||||
$column['key'] = $row['Key'];
|
||||
$column['privileges'] = $row['Privileges'];
|
||||
|
||||
$columns[$row['Field']] = $column;
|
||||
}
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
public function escape($value)
|
||||
{
|
||||
// Make sure the database is connected
|
||||
$this->_connection or $this->connect();
|
||||
|
||||
if (($value = mysql_real_escape_string( (string) $value, $this->_connection)) === FALSE)
|
||||
{
|
||||
throw new Database_Exception(':error',
|
||||
array(':error' => mysql_errno($this->_connection)),
|
||||
mysql_error($this->_connection));
|
||||
}
|
||||
|
||||
// SQL standard is to use single-quotes for all values
|
||||
return "'$value'";
|
||||
}
|
||||
|
||||
} // End Database_MySQL
|
@@ -0,0 +1,71 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* MySQL database result. See [Results](/database/results) for usage and examples.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Query/Result
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Database_MySQL_Result extends Database_Result {
|
||||
|
||||
protected $_internal_row = 0;
|
||||
|
||||
public function __construct($result, $sql, $as_object = FALSE, array $params = NULL)
|
||||
{
|
||||
parent::__construct($result, $sql, $as_object, $params);
|
||||
|
||||
// Find the number of rows in the result
|
||||
$this->_total_rows = mysql_num_rows($result);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_resource($this->_result))
|
||||
{
|
||||
mysql_free_result($this->_result);
|
||||
}
|
||||
}
|
||||
|
||||
public function seek($offset)
|
||||
{
|
||||
if ($this->offsetExists($offset) AND mysql_data_seek($this->_result, $offset))
|
||||
{
|
||||
// Set the current row to the offset
|
||||
$this->_current_row = $this->_internal_row = $offset;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
public function current()
|
||||
{
|
||||
if ($this->_current_row !== $this->_internal_row AND ! $this->seek($this->_current_row))
|
||||
return FALSE;
|
||||
|
||||
// Increment internal row for optimization assuming rows are fetched in order
|
||||
$this->_internal_row++;
|
||||
|
||||
if ($this->_as_object === TRUE)
|
||||
{
|
||||
// Return an stdClass
|
||||
return mysql_fetch_object($this->_result);
|
||||
}
|
||||
elseif (is_string($this->_as_object))
|
||||
{
|
||||
// Return an object of given class name
|
||||
return mysql_fetch_object($this->_result, $this->_as_object, $this->_object_params);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return an array of the row
|
||||
return mysql_fetch_assoc($this->_result);
|
||||
}
|
||||
}
|
||||
|
||||
} // End Database_MySQL_Result_Select
|
186
includes/kohana/modules/database/classes/kohana/database/pdo.php
Normal file
186
includes/kohana/modules/database/classes/kohana/database/pdo.php
Normal file
@@ -0,0 +1,186 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* PDO database connection.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Drivers
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Database_PDO extends Database {
|
||||
|
||||
// PDO uses no quoting for identifiers
|
||||
protected $_identifier = '';
|
||||
|
||||
protected function __construct($name, array $config)
|
||||
{
|
||||
parent::__construct($name, $config);
|
||||
|
||||
if (isset($this->_config['identifier']))
|
||||
{
|
||||
// Allow the identifier to be overloaded per-connection
|
||||
$this->_identifier = (string) $this->_config['identifier'];
|
||||
}
|
||||
}
|
||||
|
||||
public function connect()
|
||||
{
|
||||
if ($this->_connection)
|
||||
return;
|
||||
|
||||
// Extract the connection parameters, adding required variabels
|
||||
extract($this->_config['connection'] + array(
|
||||
'dsn' => '',
|
||||
'username' => NULL,
|
||||
'password' => NULL,
|
||||
'persistent' => FALSE,
|
||||
));
|
||||
|
||||
// Clear the connection parameters for security
|
||||
unset($this->_config['connection']);
|
||||
|
||||
// Force PDO to use exceptions for all errors
|
||||
$attrs = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
if ( ! empty($persistent))
|
||||
{
|
||||
// Make the connection persistent
|
||||
$attrs[PDO::ATTR_PERSISTENT] = TRUE;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Create a new PDO connection
|
||||
$this->_connection = new PDO($dsn, $username, $password, $attrs);
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Database_Exception(':error', array(
|
||||
':error' => $e->getMessage(),
|
||||
),
|
||||
$e->getCode(),
|
||||
$e);
|
||||
}
|
||||
|
||||
if ( ! empty($this->_config['charset']))
|
||||
{
|
||||
// Set the character set
|
||||
$this->set_charset($this->_config['charset']);
|
||||
}
|
||||
}
|
||||
|
||||
public function disconnect()
|
||||
{
|
||||
// Destroy the PDO object
|
||||
$this->_connection = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function set_charset($charset)
|
||||
{
|
||||
// Make sure the database is connected
|
||||
$this->_connection or $this->connect();
|
||||
|
||||
// Execute a raw SET NAMES query
|
||||
$this->_connection->exec('SET NAMES '.$this->quote($charset));
|
||||
}
|
||||
|
||||
public function query($type, $sql, $as_object = FALSE, array $params = NULL)
|
||||
{
|
||||
// Make sure the database is connected
|
||||
$this->_connection or $this->connect();
|
||||
|
||||
if ( ! empty($this->_config['profiling']))
|
||||
{
|
||||
// Benchmark this query for the current instance
|
||||
$benchmark = Profiler::start("Database ({$this->_instance})", $sql);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$result = $this->_connection->query($sql);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
if (isset($benchmark))
|
||||
{
|
||||
// This benchmark is worthless
|
||||
Profiler::delete($benchmark);
|
||||
}
|
||||
|
||||
// Convert the exception in a database exception
|
||||
throw new Database_Exception(':error [ :query ]', array(
|
||||
':error' => $e->getMessage(),
|
||||
':query' => $sql
|
||||
),
|
||||
$e->getCode(),
|
||||
$e);
|
||||
}
|
||||
|
||||
if (isset($benchmark))
|
||||
{
|
||||
Profiler::stop($benchmark);
|
||||
}
|
||||
|
||||
// Set the last query
|
||||
$this->last_query = $sql;
|
||||
|
||||
if ($type === Database::SELECT)
|
||||
{
|
||||
// Convert the result into an array, as PDOStatement::rowCount is not reliable
|
||||
if ($as_object === FALSE)
|
||||
{
|
||||
$result->setFetchMode(PDO::FETCH_ASSOC);
|
||||
}
|
||||
elseif (is_string($as_object))
|
||||
{
|
||||
$result->setFetchMode(PDO::FETCH_CLASS, $as_object, $params);
|
||||
}
|
||||
else
|
||||
{
|
||||
$result->setFetchMode(PDO::FETCH_CLASS, 'stdClass');
|
||||
}
|
||||
|
||||
$result = $result->fetchAll();
|
||||
|
||||
// Return an iterator of results
|
||||
return new Database_Result_Cached($result, $sql, $as_object, $params);
|
||||
}
|
||||
elseif ($type === Database::INSERT)
|
||||
{
|
||||
// Return a list of insert id and rows created
|
||||
return array(
|
||||
$this->_connection->lastInsertId(),
|
||||
$result->rowCount(),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return the number of rows affected
|
||||
return $result->rowCount();
|
||||
}
|
||||
}
|
||||
|
||||
public function list_tables($like = NULL)
|
||||
{
|
||||
throw new Kohana_Exception('Database method :method is not supported by :class',
|
||||
array(':method' => __FUNCTION__, ':class' => __CLASS__));
|
||||
}
|
||||
|
||||
public function list_columns($table, $like = NULL, $add_prefix = TRUE)
|
||||
{
|
||||
throw new Kohana_Exception('Database method :method is not supported by :class',
|
||||
array(':method' => __FUNCTION__, ':class' => __CLASS__));
|
||||
}
|
||||
|
||||
public function escape($value)
|
||||
{
|
||||
// Make sure the database is connected
|
||||
$this->_connection or $this->connect();
|
||||
|
||||
return $this->_connection->quote($value);
|
||||
}
|
||||
|
||||
} // End Database_PDO
|
@@ -0,0 +1,236 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database query wrapper. See [Prepared Statements](database/query/prepared) for usage and examples.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Query
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Database_Query {
|
||||
|
||||
// Query type
|
||||
protected $_type;
|
||||
|
||||
// Cache lifetime
|
||||
protected $_lifetime;
|
||||
|
||||
// SQL statement
|
||||
protected $_sql;
|
||||
|
||||
// Quoted query parameters
|
||||
protected $_parameters = array();
|
||||
|
||||
// Return results as associative arrays or objects
|
||||
protected $_as_object = FALSE;
|
||||
|
||||
// Parameters for __construct when using object results
|
||||
protected $_object_params = array();
|
||||
|
||||
/**
|
||||
* Creates a new SQL query of the specified type.
|
||||
*
|
||||
* @param integer query type: Database::SELECT, Database::INSERT, etc
|
||||
* @param string query string
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($type, $sql)
|
||||
{
|
||||
$this->_type = $type;
|
||||
$this->_sql = $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SQL query string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final public function __toString()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Return the SQL string
|
||||
return $this->compile(Database::instance());
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
return Kohana::exception_text($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the query.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function type()
|
||||
{
|
||||
return $this->_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the query to be cached for a specified amount of time.
|
||||
*
|
||||
* @param integer number of seconds to cache or null for default
|
||||
* @return $this
|
||||
* @uses Kohana::$cache_life
|
||||
*/
|
||||
public function cached($lifetime = NULL)
|
||||
{
|
||||
if ($lifetime === NULL)
|
||||
{
|
||||
// Use the global setting
|
||||
$lifetime = Kohana::$cache_life;
|
||||
}
|
||||
|
||||
$this->_lifetime = $lifetime;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns results as associative arrays
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function as_assoc()
|
||||
{
|
||||
$this->_as_object = FALSE;
|
||||
|
||||
$this->_object_params = array();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns results as objects
|
||||
*
|
||||
* @param string classname or TRUE for stdClass
|
||||
* @return $this
|
||||
*/
|
||||
public function as_object($class = TRUE, array $params = NULL)
|
||||
{
|
||||
$this->_as_object = $class;
|
||||
|
||||
if ($params)
|
||||
{
|
||||
// Add object parameters
|
||||
$this->_object_params = $params;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a parameter in the query.
|
||||
*
|
||||
* @param string parameter key to replace
|
||||
* @param mixed value to use
|
||||
* @return $this
|
||||
*/
|
||||
public function param($param, $value)
|
||||
{
|
||||
// Add or overload a new parameter
|
||||
$this->_parameters[$param] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind a variable to a parameter in the query.
|
||||
*
|
||||
* @param string parameter key to replace
|
||||
* @param mixed variable to use
|
||||
* @return $this
|
||||
*/
|
||||
public function bind($param, & $var)
|
||||
{
|
||||
// Bind a value to a variable
|
||||
$this->_parameters[$param] =& $var;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add multiple parameters to the query.
|
||||
*
|
||||
* @param array list of parameters
|
||||
* @return $this
|
||||
*/
|
||||
public function parameters(array $params)
|
||||
{
|
||||
// Merge the new parameters in
|
||||
$this->_parameters = $params + $this->_parameters;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the SQL query and return it. Replaces any parameters with their
|
||||
* given values.
|
||||
*
|
||||
* @param object Database instance
|
||||
* @return string
|
||||
*/
|
||||
public function compile(Database $db)
|
||||
{
|
||||
// Import the SQL locally
|
||||
$sql = $this->_sql;
|
||||
|
||||
if ( ! empty($this->_parameters))
|
||||
{
|
||||
// Quote all of the values
|
||||
$values = array_map(array($db, 'quote'), $this->_parameters);
|
||||
|
||||
// Replace the values in the SQL
|
||||
$sql = strtr($sql, $values);
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the current query on the given database.
|
||||
*
|
||||
* @param mixed Database instance or name of instance
|
||||
* @return object Database_Result for SELECT queries
|
||||
* @return mixed the insert id for INSERT queries
|
||||
* @return integer number of affected rows for all other queries
|
||||
*/
|
||||
public function execute($db = NULL)
|
||||
{
|
||||
if ( ! is_object($db))
|
||||
{
|
||||
// Get the database instance
|
||||
$db = Database::instance($db);
|
||||
}
|
||||
|
||||
// Compile the SQL query
|
||||
$sql = $this->compile($db);
|
||||
|
||||
if ( ! empty($this->_lifetime) AND $this->_type === Database::SELECT)
|
||||
{
|
||||
// Set the cache key based on the database instance name and SQL
|
||||
$cache_key = 'Database::query("'.$db.'", "'.$sql.'")';
|
||||
|
||||
if ($result = Kohana::cache($cache_key, NULL, $this->_lifetime))
|
||||
{
|
||||
// Return a cached result
|
||||
return new Database_Result_Cached($result, $sql, $this->_as_object, $this->_object_params);
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the query
|
||||
$result = $db->query($this->_type, $sql, $this->_as_object, $this->_object_params);
|
||||
|
||||
if (isset($cache_key))
|
||||
{
|
||||
// Cache the result array
|
||||
Kohana::cache($cache_key, $result->as_array(), $this->_lifetime);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
} // End Database_Query
|
@@ -0,0 +1,211 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database query builder. See [Query Builder](/database/query/builder) for usage and examples.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Query
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
abstract class Kohana_Database_Query_Builder extends Database_Query {
|
||||
|
||||
/**
|
||||
* Compiles an array of JOIN statements into an SQL partial.
|
||||
*
|
||||
* @param object Database instance
|
||||
* @param array join statements
|
||||
* @return string
|
||||
*/
|
||||
protected function _compile_join(Database $db, array $joins)
|
||||
{
|
||||
$statements = array();
|
||||
|
||||
foreach ($joins as $join)
|
||||
{
|
||||
// Compile each of the join statements
|
||||
$statements[] = $join->compile($db);
|
||||
}
|
||||
|
||||
return implode(' ', $statements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles an array of conditions into an SQL partial. Used for WHERE
|
||||
* and HAVING.
|
||||
*
|
||||
* @param object Database instance
|
||||
* @param array condition statements
|
||||
* @return string
|
||||
*/
|
||||
protected function _compile_conditions(Database $db, array $conditions)
|
||||
{
|
||||
$last_condition = NULL;
|
||||
|
||||
$sql = '';
|
||||
foreach ($conditions as $group)
|
||||
{
|
||||
// Process groups of conditions
|
||||
foreach ($group as $logic => $condition)
|
||||
{
|
||||
if ($condition === '(')
|
||||
{
|
||||
if ( ! empty($sql) AND $last_condition !== '(')
|
||||
{
|
||||
// Include logic operator
|
||||
$sql .= ' '.$logic.' ';
|
||||
}
|
||||
|
||||
$sql .= '(';
|
||||
}
|
||||
elseif ($condition === ')')
|
||||
{
|
||||
$sql .= ')';
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ! empty($sql) AND $last_condition !== '(')
|
||||
{
|
||||
// Add the logic operator
|
||||
$sql .= ' '.$logic.' ';
|
||||
}
|
||||
|
||||
// Split the condition
|
||||
list($column, $op, $value) = $condition;
|
||||
|
||||
if ($value === NULL)
|
||||
{
|
||||
if ($op === '=')
|
||||
{
|
||||
// Convert "val = NULL" to "val IS NULL"
|
||||
$op = 'IS';
|
||||
}
|
||||
elseif ($op === '!=')
|
||||
{
|
||||
// Convert "val != NULL" to "valu IS NOT NULL"
|
||||
$op = 'IS NOT';
|
||||
}
|
||||
}
|
||||
|
||||
// Database operators are always uppercase
|
||||
$op = strtoupper($op);
|
||||
|
||||
if ($op === 'BETWEEN' AND is_array($value))
|
||||
{
|
||||
// BETWEEN always has exactly two arguments
|
||||
list($min, $max) = $value;
|
||||
|
||||
if (is_string($min) AND array_key_exists($min, $this->_parameters))
|
||||
{
|
||||
// Set the parameter as the minimum
|
||||
$min = $this->_parameters[$min];
|
||||
}
|
||||
|
||||
if (is_string($max) AND array_key_exists($max, $this->_parameters))
|
||||
{
|
||||
// Set the parameter as the maximum
|
||||
$max = $this->_parameters[$max];
|
||||
}
|
||||
|
||||
// Quote the min and max value
|
||||
$value = $db->quote($min).' AND '.$db->quote($max);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_string($value) AND array_key_exists($value, $this->_parameters))
|
||||
{
|
||||
// Set the parameter as the value
|
||||
$value = $this->_parameters[$value];
|
||||
}
|
||||
|
||||
// Quote the entire value normally
|
||||
$value = $db->quote($value);
|
||||
}
|
||||
|
||||
if ($column)
|
||||
{
|
||||
// Apply proper quoting to the column
|
||||
$column = $db->quote_identifier($column);
|
||||
}
|
||||
|
||||
// Append the statement to the query
|
||||
$sql .= trim($column.' '.$op.' '.$value);
|
||||
}
|
||||
|
||||
$last_condition = $condition;
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles an array of set values into an SQL partial. Used for UPDATE.
|
||||
*
|
||||
* @param object Database instance
|
||||
* @param array updated values
|
||||
* @return string
|
||||
*/
|
||||
protected function _compile_set(Database $db, array $values)
|
||||
{
|
||||
$set = array();
|
||||
foreach ($values as $group)
|
||||
{
|
||||
// Split the set
|
||||
list ($column, $value) = $group;
|
||||
|
||||
// Quote the column name
|
||||
$column = $db->quote_identifier($column);
|
||||
|
||||
if (is_string($value) AND array_key_exists($value, $this->_parameters))
|
||||
{
|
||||
// Use the parameter value
|
||||
$value = $this->_parameters[$value];
|
||||
}
|
||||
|
||||
$set[$column] = $column.' = '.$db->quote($value);
|
||||
}
|
||||
|
||||
return implode(', ', $set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles an array of ORDER BY statements into an SQL partial.
|
||||
*
|
||||
* @param object Database instance
|
||||
* @param array sorting columns
|
||||
* @return string
|
||||
*/
|
||||
protected function _compile_order_by(Database $db, array $columns)
|
||||
{
|
||||
$sort = array();
|
||||
foreach ($columns as $group)
|
||||
{
|
||||
list ($column, $direction) = $group;
|
||||
|
||||
if ($direction)
|
||||
{
|
||||
// Make the direction uppercase
|
||||
$direction = strtoupper($direction);
|
||||
}
|
||||
|
||||
if ($column)
|
||||
{
|
||||
// Quote the column, if it has a value
|
||||
$column = $db->quote_identifier($column);
|
||||
}
|
||||
|
||||
$sort[] = trim($column.' '.$direction);
|
||||
}
|
||||
|
||||
return 'ORDER BY '.implode(', ', $sort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the current builder status.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
abstract public function reset();
|
||||
|
||||
} // End Database_Query_Builder
|
@@ -0,0 +1,89 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database query builder for DELETE statements. See [Query Builder](/database/query/builder) for usage and examples.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Query
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Database_Query_Builder_Delete extends Database_Query_Builder_Where {
|
||||
|
||||
// DELETE FROM ...
|
||||
protected $_table;
|
||||
|
||||
/**
|
||||
* Set the table for a delete.
|
||||
*
|
||||
* @param mixed table name or array($table, $alias) or object
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($table = NULL)
|
||||
{
|
||||
if ($table)
|
||||
{
|
||||
// Set the inital table name
|
||||
$this->_table = $table;
|
||||
}
|
||||
|
||||
// Start the query with no SQL
|
||||
return parent::__construct(Database::DELETE, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the table to delete from.
|
||||
*
|
||||
* @param mixed table name or array($table, $alias) or object
|
||||
* @return $this
|
||||
*/
|
||||
public function table($table)
|
||||
{
|
||||
$this->_table = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the SQL query and return it.
|
||||
*
|
||||
* @param object Database instance
|
||||
* @return string
|
||||
*/
|
||||
public function compile(Database $db)
|
||||
{
|
||||
// Start a deletion query
|
||||
$query = 'DELETE FROM '.$db->quote_table($this->_table);
|
||||
|
||||
if ( ! empty($this->_where))
|
||||
{
|
||||
// Add deletion conditions
|
||||
$query .= ' WHERE '.$this->_compile_conditions($db, $this->_where);
|
||||
}
|
||||
|
||||
if ( ! empty($this->_order_by))
|
||||
{
|
||||
// Add sorting
|
||||
$query .= ' '.$this->_compile_order_by($db, $this->_order_by);
|
||||
}
|
||||
|
||||
if ($this->_limit !== NULL)
|
||||
{
|
||||
// Add limiting
|
||||
$query .= ' LIMIT '.$this->_limit;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->_table = NULL;
|
||||
$this->_where = array();
|
||||
|
||||
$this->_parameters = array();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
} // End Database_Query_Builder_Delete
|
@@ -0,0 +1,171 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database query builder for INSERT statements. See [Query Builder](/database/query/builder) for usage and examples.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Query
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
|
||||
|
||||
// INSERT INTO ...
|
||||
protected $_table;
|
||||
|
||||
// (...)
|
||||
protected $_columns = array();
|
||||
|
||||
// VALUES (...)
|
||||
protected $_values = array();
|
||||
|
||||
/**
|
||||
* Set the table and columns for an insert.
|
||||
*
|
||||
* @param mixed table name or array($table, $alias) or object
|
||||
* @param array column names
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($table = NULL, array $columns = NULL)
|
||||
{
|
||||
if ($table)
|
||||
{
|
||||
// Set the inital table name
|
||||
$this->_table = $table;
|
||||
}
|
||||
|
||||
if ($columns)
|
||||
{
|
||||
// Set the column names
|
||||
$this->_columns = $columns;
|
||||
}
|
||||
|
||||
// Start the query with no SQL
|
||||
return parent::__construct(Database::INSERT, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the table to insert into.
|
||||
*
|
||||
* @param mixed table name or array($table, $alias) or object
|
||||
* @return $this
|
||||
*/
|
||||
public function table($table)
|
||||
{
|
||||
$this->_table = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the columns that will be inserted.
|
||||
*
|
||||
* @param array column names
|
||||
* @return $this
|
||||
*/
|
||||
public function columns(array $columns)
|
||||
{
|
||||
$this->_columns = $columns;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or overwrites values. Multiple value sets can be added.
|
||||
*
|
||||
* @param array values list
|
||||
* @param ...
|
||||
* @return $this
|
||||
*/
|
||||
public function values(array $values)
|
||||
{
|
||||
if ( ! is_array($this->_values))
|
||||
{
|
||||
throw new Kohana_Exception('INSERT INTO ... SELECT statements cannot be combined with INSERT INTO ... VALUES');
|
||||
}
|
||||
|
||||
// Get all of the passed values
|
||||
$values = func_get_args();
|
||||
|
||||
$this->_values = array_merge($this->_values, $values);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a sub-query to for the inserted values.
|
||||
*
|
||||
* @param object Database_Query of SELECT type
|
||||
* @return $this
|
||||
*/
|
||||
public function select(Database_Query $query)
|
||||
{
|
||||
if ($query->type() !== Database::SELECT)
|
||||
{
|
||||
throw new Kohana_Exception('Only SELECT queries can be combined with INSERT queries');
|
||||
}
|
||||
|
||||
$this->_values = $query;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the SQL query and return it.
|
||||
*
|
||||
* @param object Database instance
|
||||
* @return string
|
||||
*/
|
||||
public function compile(Database $db)
|
||||
{
|
||||
// Start an insertion query
|
||||
$query = 'INSERT INTO '.$db->quote_table($this->_table);
|
||||
|
||||
// Add the column names
|
||||
$query .= ' ('.implode(', ', array_map(array($db, 'quote_identifier'), $this->_columns)).') ';
|
||||
|
||||
if (is_array($this->_values))
|
||||
{
|
||||
// Callback for quoting values
|
||||
$quote = array($db, 'quote');
|
||||
|
||||
$groups = array();
|
||||
foreach ($this->_values as $group)
|
||||
{
|
||||
foreach ($group as $i => $value)
|
||||
{
|
||||
if (is_string($value) AND isset($this->_parameters[$value]))
|
||||
{
|
||||
// Use the parameter value
|
||||
$group[$i] = $this->_parameters[$value];
|
||||
}
|
||||
}
|
||||
|
||||
$groups[] = '('.implode(', ', array_map($quote, $group)).')';
|
||||
}
|
||||
|
||||
// Add the values
|
||||
$query .= 'VALUES '.implode(', ', $groups);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add the sub-query
|
||||
$query .= (string) $this->_values;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->_table = NULL;
|
||||
|
||||
$this->_columns =
|
||||
$this->_values = array();
|
||||
|
||||
$this->_parameters = array();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
} // End Database_Query_Builder_Insert
|
@@ -0,0 +1,107 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database query builder for JOIN statements. See [Query Builder](/database/query/builder) for usage and examples.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Query
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Database_Query_Builder_Join extends Database_Query_Builder {
|
||||
|
||||
// Type of JOIN
|
||||
protected $_type;
|
||||
|
||||
// JOIN ...
|
||||
protected $_table;
|
||||
|
||||
// ON ...
|
||||
protected $_on = array();
|
||||
|
||||
/**
|
||||
* Creates a new JOIN statement for a table. Optionally, the type of JOIN
|
||||
* can be specified as the second parameter.
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param string type of JOIN: INNER, RIGHT, LEFT, etc
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($table, $type = NULL)
|
||||
{
|
||||
// Set the table to JOIN on
|
||||
$this->_table = $table;
|
||||
|
||||
if ($type !== NULL)
|
||||
{
|
||||
// Set the JOIN type
|
||||
$this->_type = (string) $type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new condition for joining.
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param string logic operator
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @return $this
|
||||
*/
|
||||
public function on($c1, $op, $c2)
|
||||
{
|
||||
$this->_on[] = array($c1, $op, $c2);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the SQL partial for a JOIN statement and return it.
|
||||
*
|
||||
* @param object Database instance
|
||||
* @return string
|
||||
*/
|
||||
public function compile(Database $db)
|
||||
{
|
||||
if ($this->_type)
|
||||
{
|
||||
$sql = strtoupper($this->_type).' JOIN';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = 'JOIN';
|
||||
}
|
||||
|
||||
// Quote the table name that is being joined
|
||||
$sql .= ' '.$db->quote_table($this->_table).' ON ';
|
||||
|
||||
$conditions = array();
|
||||
foreach ($this->_on as $condition)
|
||||
{
|
||||
// Split the condition
|
||||
list($c1, $op, $c2) = $condition;
|
||||
|
||||
if ($op)
|
||||
{
|
||||
// Make the operator uppercase and spaced
|
||||
$op = ' '.strtoupper($op);
|
||||
}
|
||||
|
||||
// Quote each of the identifiers used for the condition
|
||||
$conditions[] = $db->quote_identifier($c1).$op.' '.$db->quote_identifier($c2);
|
||||
}
|
||||
|
||||
// Concat the conditions "... AND ..."
|
||||
$sql .= '('.implode(' AND ', $conditions).')';
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->_type =
|
||||
$this->_table = NULL;
|
||||
|
||||
$this->_on = array();
|
||||
}
|
||||
|
||||
} // End Database_Query_Builder_Join
|
@@ -0,0 +1,388 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database query builder for SELECT statements. See [Query Builder](/database/query/builder) for usage and examples.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Query
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where {
|
||||
|
||||
// SELECT ...
|
||||
protected $_select = array();
|
||||
|
||||
// DISTINCT
|
||||
protected $_distinct = FALSE;
|
||||
|
||||
// FROM ...
|
||||
protected $_from = array();
|
||||
|
||||
// JOIN ...
|
||||
protected $_join = array();
|
||||
|
||||
// GROUP BY ...
|
||||
protected $_group_by = array();
|
||||
|
||||
// HAVING ...
|
||||
protected $_having = array();
|
||||
|
||||
// OFFSET ...
|
||||
protected $_offset = NULL;
|
||||
|
||||
// The last JOIN statement created
|
||||
protected $_last_join;
|
||||
|
||||
/**
|
||||
* Sets the initial columns to select from.
|
||||
*
|
||||
* @param array column list
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $columns = NULL)
|
||||
{
|
||||
if ( ! empty($columns))
|
||||
{
|
||||
// Set the initial columns
|
||||
$this->_select = $columns;
|
||||
}
|
||||
|
||||
// Start the query with no actual SQL statement
|
||||
parent::__construct(Database::SELECT, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables selecting only unique columns using "SELECT DISTINCT"
|
||||
*
|
||||
* @param boolean enable or disable distinct columns
|
||||
* @return $this
|
||||
*/
|
||||
public function distinct($value)
|
||||
{
|
||||
$this->_distinct = (bool) $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose the columns to select from.
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param ...
|
||||
* @return $this
|
||||
*/
|
||||
public function select($columns = NULL)
|
||||
{
|
||||
$columns = func_get_args();
|
||||
|
||||
$this->_select = array_merge($this->_select, $columns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose the columns to select from, using an array.
|
||||
*
|
||||
* @param array list of column names or aliases
|
||||
* @return $this
|
||||
*/
|
||||
public function select_array(array $columns)
|
||||
{
|
||||
$this->_select = array_merge($this->_select, $columns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose the tables to select "FROM ..."
|
||||
*
|
||||
* @param mixed table name or array($table, $alias) or object
|
||||
* @param ...
|
||||
* @return $this
|
||||
*/
|
||||
public function from($tables)
|
||||
{
|
||||
$tables = func_get_args();
|
||||
|
||||
$this->_from = array_merge($this->_from, $tables);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds addition tables to "JOIN ...".
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param string join type (LEFT, RIGHT, INNER, etc)
|
||||
* @return $this
|
||||
*/
|
||||
public function join($table, $type = NULL)
|
||||
{
|
||||
$this->_join[] = $this->_last_join = new Database_Query_Builder_Join($table, $type);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds "ON ..." conditions for the last created JOIN statement.
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param string logic operator
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @return $this
|
||||
*/
|
||||
public function on($c1, $op, $c2)
|
||||
{
|
||||
$this->_last_join->on($c1, $op, $c2);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a "GROUP BY ..." filter.
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param ...
|
||||
* @return $this
|
||||
*/
|
||||
public function group_by($columns)
|
||||
{
|
||||
$columns = func_get_args();
|
||||
|
||||
$this->_group_by = array_merge($this->_group_by, $columns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of and_having()
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param string logic operator
|
||||
* @param mixed column value
|
||||
* @return $this
|
||||
*/
|
||||
public function having($column, $op, $value = NULL)
|
||||
{
|
||||
return $this->and_having($column, $op, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new "AND HAVING" condition for the query.
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param string logic operator
|
||||
* @param mixed column value
|
||||
* @return $this
|
||||
*/
|
||||
public function and_having($column, $op, $value = NULL)
|
||||
{
|
||||
$this->_having[] = array('AND' => array($column, $op, $value));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new "OR HAVING" condition for the query.
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param string logic operator
|
||||
* @param mixed column value
|
||||
* @return $this
|
||||
*/
|
||||
public function or_having($column, $op, $value = NULL)
|
||||
{
|
||||
$this->_having[] = array('OR' => array($column, $op, $value));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of and_having_open()
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function having_open()
|
||||
{
|
||||
return $this->and_having_open();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a new "AND HAVING (...)" grouping.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function and_having_open()
|
||||
{
|
||||
$this->_having[] = array('AND' => '(');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a new "OR HAVING (...)" grouping.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function or_having_open()
|
||||
{
|
||||
$this->_having[] = array('OR' => '(');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes an open "AND HAVING (...)" grouping.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function having_close()
|
||||
{
|
||||
return $this->and_having_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes an open "AND HAVING (...)" grouping.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function and_having_close()
|
||||
{
|
||||
$this->_having[] = array('AND' => ')');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes an open "OR HAVING (...)" grouping.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function or_having_close()
|
||||
{
|
||||
$this->_having[] = array('OR' => ')');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start returning results after "OFFSET ..."
|
||||
*
|
||||
* @param integer starting result number
|
||||
* @return $this
|
||||
*/
|
||||
public function offset($number)
|
||||
{
|
||||
$this->_offset = (int) $number;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the SQL query and return it.
|
||||
*
|
||||
* @param object Database instance
|
||||
* @return string
|
||||
*/
|
||||
public function compile(Database $db)
|
||||
{
|
||||
// Callback to quote identifiers
|
||||
$quote_ident = array($db, 'quote_identifier');
|
||||
|
||||
// Callback to quote tables
|
||||
$quote_table = array($db, 'quote_table');
|
||||
|
||||
// Start a selection query
|
||||
$query = 'SELECT ';
|
||||
|
||||
if ($this->_distinct === TRUE)
|
||||
{
|
||||
// Select only unique results
|
||||
$query .= 'DISTINCT ';
|
||||
}
|
||||
|
||||
if (empty($this->_select))
|
||||
{
|
||||
// Select all columns
|
||||
$query .= '*';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Select all columns
|
||||
$query .= implode(', ', array_unique(array_map($quote_ident, $this->_select)));
|
||||
}
|
||||
|
||||
if ( ! empty($this->_from))
|
||||
{
|
||||
// Set tables to select from
|
||||
$query .= ' FROM '.implode(', ', array_unique(array_map($quote_table, $this->_from)));
|
||||
}
|
||||
|
||||
if ( ! empty($this->_join))
|
||||
{
|
||||
// Add tables to join
|
||||
$query .= ' '.$this->_compile_join($db, $this->_join);
|
||||
}
|
||||
|
||||
if ( ! empty($this->_where))
|
||||
{
|
||||
// Add selection conditions
|
||||
$query .= ' WHERE '.$this->_compile_conditions($db, $this->_where);
|
||||
}
|
||||
|
||||
if ( ! empty($this->_group_by))
|
||||
{
|
||||
// Add sorting
|
||||
$query .= ' GROUP BY '.implode(', ', array_map($quote_ident, $this->_group_by));
|
||||
}
|
||||
|
||||
if ( ! empty($this->_having))
|
||||
{
|
||||
// Add filtering conditions
|
||||
$query .= ' HAVING '.$this->_compile_conditions($db, $this->_having);
|
||||
}
|
||||
|
||||
if ( ! empty($this->_order_by))
|
||||
{
|
||||
// Add sorting
|
||||
$query .= ' '.$this->_compile_order_by($db, $this->_order_by);
|
||||
}
|
||||
|
||||
if ($this->_limit !== NULL)
|
||||
{
|
||||
// Add limiting
|
||||
$query .= ' LIMIT '.$this->_limit;
|
||||
}
|
||||
|
||||
if ($this->_offset !== NULL)
|
||||
{
|
||||
// Add offsets
|
||||
$query .= ' OFFSET '.$this->_offset;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->_select =
|
||||
$this->_from =
|
||||
$this->_join =
|
||||
$this->_where =
|
||||
$this->_group_by =
|
||||
$this->_having =
|
||||
$this->_order_by = array();
|
||||
|
||||
$this->_distinct = FALSE;
|
||||
|
||||
$this->_limit =
|
||||
$this->_offset =
|
||||
$this->_last_join = NULL;
|
||||
|
||||
$this->_parameters = array();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
} // End Database_Query_Select
|
@@ -0,0 +1,130 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database query builder for UPDATE statements. See [Query Builder](/database/query/builder) for usage and examples.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Query
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Database_Query_Builder_Update extends Database_Query_Builder_Where {
|
||||
|
||||
// UPDATE ...
|
||||
protected $_table;
|
||||
|
||||
// SET ...
|
||||
protected $_set = array();
|
||||
|
||||
/**
|
||||
* Set the table for a update.
|
||||
*
|
||||
* @param mixed table name or array($table, $alias) or object
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($table = NULL)
|
||||
{
|
||||
if ($table)
|
||||
{
|
||||
// Set the inital table name
|
||||
$this->_table = $table;
|
||||
}
|
||||
|
||||
// Start the query with no SQL
|
||||
return parent::__construct(Database::UPDATE, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the table to update.
|
||||
*
|
||||
* @param mixed table name or array($table, $alias) or object
|
||||
* @return $this
|
||||
*/
|
||||
public function table($table)
|
||||
{
|
||||
$this->_table = $table;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the values to update with an associative array.
|
||||
*
|
||||
* @param array associative (column => value) list
|
||||
* @return $this
|
||||
*/
|
||||
public function set(array $pairs)
|
||||
{
|
||||
foreach ($pairs as $column => $value)
|
||||
{
|
||||
$this->_set[] = array($column, $value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a single column.
|
||||
*
|
||||
* @param mixed table name or array($table, $alias) or object
|
||||
* @param mixed column value
|
||||
* @return $this
|
||||
*/
|
||||
public function value($column, $value)
|
||||
{
|
||||
$this->_set[] = array($column, $value);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the SQL query and return it.
|
||||
*
|
||||
* @param object Database instance
|
||||
* @return string
|
||||
*/
|
||||
public function compile(Database $db)
|
||||
{
|
||||
// Start an update query
|
||||
$query = 'UPDATE '.$db->quote_table($this->_table);
|
||||
|
||||
// Add the columns to update
|
||||
$query .= ' SET '.$this->_compile_set($db, $this->_set);
|
||||
|
||||
if ( ! empty($this->_where))
|
||||
{
|
||||
// Add selection conditions
|
||||
$query .= ' WHERE '.$this->_compile_conditions($db, $this->_where);
|
||||
}
|
||||
|
||||
if ( ! empty($this->_order_by))
|
||||
{
|
||||
// Add sorting
|
||||
$query .= ' '.$this->_compile_order_by($db, $this->_order_by);
|
||||
}
|
||||
|
||||
if ($this->_limit !== NULL)
|
||||
{
|
||||
// Add limiting
|
||||
$query .= ' LIMIT '.$this->_limit;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->_table = NULL;
|
||||
|
||||
$this->_set =
|
||||
$this->_where = array();
|
||||
|
||||
$this->_limit = NULL;
|
||||
|
||||
$this->_parameters = array();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
} // End Database_Query_Builder_Update
|
@@ -0,0 +1,160 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database query builder for WHERE statements. See [Query Builder](/database/query/builder) for usage and examples.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Query
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
abstract class Kohana_Database_Query_Builder_Where extends Database_Query_Builder {
|
||||
|
||||
// WHERE ...
|
||||
protected $_where = array();
|
||||
|
||||
// ORDER BY ...
|
||||
protected $_order_by = array();
|
||||
|
||||
// LIMIT ...
|
||||
protected $_limit = NULL;
|
||||
|
||||
/**
|
||||
* Alias of and_where()
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param string logic operator
|
||||
* @param mixed column value
|
||||
* @return $this
|
||||
*/
|
||||
public function where($column, $op, $value)
|
||||
{
|
||||
return $this->and_where($column, $op, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new "AND WHERE" condition for the query.
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param string logic operator
|
||||
* @param mixed column value
|
||||
* @return $this
|
||||
*/
|
||||
public function and_where($column, $op, $value)
|
||||
{
|
||||
$this->_where[] = array('AND' => array($column, $op, $value));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new "OR WHERE" condition for the query.
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param string logic operator
|
||||
* @param mixed column value
|
||||
* @return $this
|
||||
*/
|
||||
public function or_where($column, $op, $value)
|
||||
{
|
||||
$this->_where[] = array('OR' => array($column, $op, $value));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of and_where_open()
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function where_open()
|
||||
{
|
||||
return $this->and_where_open();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a new "AND WHERE (...)" grouping.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function and_where_open()
|
||||
{
|
||||
$this->_where[] = array('AND' => '(');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a new "OR WHERE (...)" grouping.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function or_where_open()
|
||||
{
|
||||
$this->_where[] = array('OR' => '(');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes an open "AND WHERE (...)" grouping.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function where_close()
|
||||
{
|
||||
return $this->and_where_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes an open "AND WHERE (...)" grouping.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function and_where_close()
|
||||
{
|
||||
$this->_where[] = array('AND' => ')');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes an open "OR WHERE (...)" grouping.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function or_where_close()
|
||||
{
|
||||
$this->_where[] = array('OR' => ')');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies sorting with "ORDER BY ..."
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param string direction of sorting
|
||||
* @return $this
|
||||
*/
|
||||
public function order_by($column, $direction = NULL)
|
||||
{
|
||||
$this->_order_by[] = array($column, $direction);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return up to "LIMIT ..." results
|
||||
*
|
||||
* @param integer maximum results to return
|
||||
* @return $this
|
||||
*/
|
||||
public function limit($number)
|
||||
{
|
||||
$this->_limit = (int) $number;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
} // End Database_Query_Builder_Where
|
@@ -0,0 +1,331 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database result wrapper. See [Results](/database/results) for usage and examples.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Query/Result
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
abstract class Kohana_Database_Result implements Countable, Iterator, SeekableIterator, ArrayAccess {
|
||||
|
||||
// Executed SQL for this result
|
||||
protected $_query;
|
||||
|
||||
// Raw result resource
|
||||
protected $_result;
|
||||
|
||||
// Total number of rows and current row
|
||||
protected $_total_rows = 0;
|
||||
protected $_current_row = 0;
|
||||
|
||||
// Return rows as an object or associative array
|
||||
protected $_as_object;
|
||||
|
||||
// Parameters for __construct when using object results
|
||||
protected $_object_params = NULL;
|
||||
|
||||
/**
|
||||
* Sets the total number of rows and stores the result locally.
|
||||
*
|
||||
* @param mixed query result
|
||||
* @param string SQL query
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($result, $sql, $as_object = FALSE, array $params = NULL)
|
||||
{
|
||||
// Store the result locally
|
||||
$this->_result = $result;
|
||||
|
||||
// Store the SQL locally
|
||||
$this->_query = $sql;
|
||||
|
||||
if (is_object($as_object))
|
||||
{
|
||||
// Get the object class name
|
||||
$as_object = get_class($as_object);
|
||||
}
|
||||
|
||||
// Results as objects or associative arrays
|
||||
$this->_as_object = $as_object;
|
||||
|
||||
if ($params)
|
||||
{
|
||||
// Object constructor params
|
||||
$this->_object_params = $params;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Result destruction cleans up all open result sets.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function __destruct();
|
||||
|
||||
/**
|
||||
* Get a cached database result from the current result iterator.
|
||||
*
|
||||
* $cachable = serialize($result->cached());
|
||||
*
|
||||
* @return Database_Result_Cached
|
||||
* @since 3.0.5
|
||||
*/
|
||||
public function cached()
|
||||
{
|
||||
return new Database_Result_Cached($this->as_array(), $this->_query, $this->_as_object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all of the rows in the result as an array.
|
||||
*
|
||||
* // Indexed array of all rows
|
||||
* $rows = $result->as_array();
|
||||
*
|
||||
* // Associative array of rows by "id"
|
||||
* $rows = $result->as_array('id');
|
||||
*
|
||||
* // Associative array of rows, "id" => "name"
|
||||
* $rows = $result->as_array('id', 'name');
|
||||
*
|
||||
* @param string column for associative keys
|
||||
* @param string column for values
|
||||
* @return array
|
||||
*/
|
||||
public function as_array($key = NULL, $value = NULL)
|
||||
{
|
||||
$results = array();
|
||||
|
||||
if ($key === NULL AND $value === NULL)
|
||||
{
|
||||
// Indexed rows
|
||||
|
||||
foreach ($this as $row)
|
||||
{
|
||||
$results[] = $row;
|
||||
}
|
||||
}
|
||||
elseif ($key === NULL)
|
||||
{
|
||||
// Indexed columns
|
||||
|
||||
if ($this->_as_object)
|
||||
{
|
||||
foreach ($this as $row)
|
||||
{
|
||||
$results[] = $row->$value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($this as $row)
|
||||
{
|
||||
$results[] = $row[$value];
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($value === NULL)
|
||||
{
|
||||
// Associative rows
|
||||
|
||||
if ($this->_as_object)
|
||||
{
|
||||
foreach ($this as $row)
|
||||
{
|
||||
$results[$row->$key] = $row;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($this as $row)
|
||||
{
|
||||
$results[$row[$key]] = $row;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Associative columns
|
||||
|
||||
if ($this->_as_object)
|
||||
{
|
||||
foreach ($this as $row)
|
||||
{
|
||||
$results[$row->$key] = $row->$value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($this as $row)
|
||||
{
|
||||
$results[$row[$key]] = $row[$value];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->rewind();
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the named column from the current row.
|
||||
*
|
||||
* // Get the "id" value
|
||||
* $id = $result->get('id');
|
||||
*
|
||||
* @param string column to get
|
||||
* @param mixed default value if the column does not exist
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name, $default = NULL)
|
||||
{
|
||||
$row = $this->current();
|
||||
|
||||
if ($this->_as_object)
|
||||
{
|
||||
if (isset($row->$name))
|
||||
return $row->$name;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isset($row[$name]))
|
||||
return $row[$name];
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements [Countable::count], returns the total number of rows.
|
||||
*
|
||||
* echo count($result);
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return $this->_total_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements [ArrayAccess::offsetExists], determines if row exists.
|
||||
*
|
||||
* if (isset($result[10]))
|
||||
* {
|
||||
* // Row 10 exists
|
||||
* }
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return ($offset >= 0 AND $offset < $this->_total_rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements [ArrayAccess::offsetGet], gets a given row.
|
||||
*
|
||||
* $row = $result[10];
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if ( ! $this->seek($offset))
|
||||
return NULL;
|
||||
|
||||
return $this->current();
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements [ArrayAccess::offsetSet], throws an error.
|
||||
*
|
||||
* [!!] You cannot modify a database result.
|
||||
*
|
||||
* @return void
|
||||
* @throws Kohana_Exception
|
||||
*/
|
||||
final public function offsetSet($offset, $value)
|
||||
{
|
||||
throw new Kohana_Exception('Database results are read-only');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements [ArrayAccess::offsetUnset], throws an error.
|
||||
*
|
||||
* [!!] You cannot modify a database result.
|
||||
*
|
||||
* @return void
|
||||
* @throws Kohana_Exception
|
||||
*/
|
||||
final public function offsetUnset($offset)
|
||||
{
|
||||
throw new Kohana_Exception('Database results are read-only');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements [Iterator::key], returns the current row number.
|
||||
*
|
||||
* echo key($result);
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return $this->_current_row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements [Iterator::next], moves to the next row.
|
||||
*
|
||||
* next($result);
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
++$this->_current_row;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements [Iterator::prev], moves to the previous row.
|
||||
*
|
||||
* prev($result);
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function prev()
|
||||
{
|
||||
--$this->_current_row;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements [Iterator::rewind], sets the current row to zero.
|
||||
*
|
||||
* rewind($result);
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
$this->_current_row = 0;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements [Iterator::valid], checks if the current row exists.
|
||||
*
|
||||
* [!!] This method is only used internally.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return $this->offsetExists($this->_current_row);
|
||||
}
|
||||
|
||||
} // End Database_Result
|
@@ -0,0 +1,51 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Object used for caching the results of select queries. See [Results](/database/results#select-cached) for usage and examples.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Query/Result
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Database_Result_Cached extends Database_Result {
|
||||
|
||||
public function __construct(array $result, $sql, $as_object = NULL)
|
||||
{
|
||||
parent::__construct($result, $sql, $as_object);
|
||||
|
||||
// Find the number of rows in the result
|
||||
$this->_total_rows = count($result);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
// Cached results do not use resources
|
||||
}
|
||||
|
||||
public function cached()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function seek($offset)
|
||||
{
|
||||
if ($this->offsetExists($offset))
|
||||
{
|
||||
$this->_current_row = $offset;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
public function current()
|
||||
{
|
||||
// Return an array of the row
|
||||
return $this->valid() ? $this->_result[$this->_current_row] : FALSE;
|
||||
}
|
||||
|
||||
} // End Database_Result_Cached
|
139
includes/kohana/modules/database/classes/kohana/db.php
Normal file
139
includes/kohana/modules/database/classes/kohana/db.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Provides a shortcut to get Database related objects for [making queries](../database/query).
|
||||
*
|
||||
* Shortcut | Returned Object
|
||||
* -------------|---------------
|
||||
* [`DB::query()`](#query) | [Database_Query]
|
||||
* [`DB::insert()`](#insert) | [Database_Query_Builder_Insert]
|
||||
* [`DB::select()`](#select),<br />[`DB::select_array()`](#select_array) | [Database_Query_Builder_Select]
|
||||
* [`DB::update()`](#update) | [Database_Query_Builder_Update]
|
||||
* [`DB::delete()`](#delete) | [Database_Query_Builder_Delete]
|
||||
* [`DB::expr()`](#expr) | [Database_Expression]
|
||||
*
|
||||
* You pass the same parameters to these functions as you pass to the objects they return.
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Base
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_DB {
|
||||
|
||||
/**
|
||||
* Create a new [Database_Query] of the given type.
|
||||
*
|
||||
* // Create a new SELECT query
|
||||
* $query = DB::query(Database::SELECT, 'SELECT * FROM users');
|
||||
*
|
||||
* // Create a new DELETE query
|
||||
* $query = DB::query(Database::DELETE, 'DELETE FROM users WHERE id = 5');
|
||||
*
|
||||
* Specifying the type changes the returned result. When using
|
||||
* `Database::SELECT`, a [Database_Query_Result] will be returned.
|
||||
* `Database::INSERT` queries will return the insert id and number of rows.
|
||||
* For all other queries, the number of affected rows is returned.
|
||||
*
|
||||
* @param integer type: Database::SELECT, Database::UPDATE, etc
|
||||
* @param string SQL statement
|
||||
* @return Database_Query
|
||||
*/
|
||||
public static function query($type, $sql)
|
||||
{
|
||||
return new Database_Query($type, $sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new [Database_Query_Builder_Select]. Each argument will be
|
||||
* treated as a column. To generate a `foo AS bar` alias, use an array.
|
||||
*
|
||||
* // SELECT id, username
|
||||
* $query = DB::select('id', 'username');
|
||||
*
|
||||
* // SELECT id AS user_id
|
||||
* $query = DB::select(array('id', 'user_id'));
|
||||
*
|
||||
* @param mixed column name or array($column, $alias) or object
|
||||
* @param ...
|
||||
* @return Database_Query_Builder_Select
|
||||
*/
|
||||
public static function select($columns = NULL)
|
||||
{
|
||||
return new Database_Query_Builder_Select(func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new [Database_Query_Builder_Select] from an array of columns.
|
||||
*
|
||||
* // SELECT id, username
|
||||
* $query = DB::select_array(array('id', 'username'));
|
||||
*
|
||||
* @param array columns to select
|
||||
* @return Database_Query_Builder_Select
|
||||
*/
|
||||
public static function select_array(array $columns = NULL)
|
||||
{
|
||||
return new Database_Query_Builder_Select($columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new [Database_Query_Builder_Insert].
|
||||
*
|
||||
* // INSERT INTO users (id, username)
|
||||
* $query = DB::insert('users', array('id', 'username'));
|
||||
*
|
||||
* @param string table to insert into
|
||||
* @param array list of column names or array($column, $alias) or object
|
||||
* @return Database_Query_Builder_Insert
|
||||
*/
|
||||
public static function insert($table = NULL, array $columns = NULL)
|
||||
{
|
||||
return new Database_Query_Builder_Insert($table, $columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new [Database_Query_Builder_Update].
|
||||
*
|
||||
* // UPDATE users
|
||||
* $query = DB::update('users');
|
||||
*
|
||||
* @param string table to update
|
||||
* @return Database_Query_Builder_Update
|
||||
*/
|
||||
public static function update($table = NULL)
|
||||
{
|
||||
return new Database_Query_Builder_Update($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new [Database_Query_Builder_Delete].
|
||||
*
|
||||
* // DELETE FROM users
|
||||
* $query = DB::delete('users');
|
||||
*
|
||||
* @param string table to delete from
|
||||
* @return Database_Query_Builder_Delete
|
||||
*/
|
||||
public static function delete($table = NULL)
|
||||
{
|
||||
return new Database_Query_Builder_Delete($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new [Database_Expression] which is not escaped. An expression
|
||||
* is the only way to use SQL functions within query builders.
|
||||
*
|
||||
* $expression = DB::expr('COUNT(users.id)');
|
||||
* $query = DB::update('users')->set(array('login_count' => DB::expr('login_count + 1')))->where('id', '=', $id);
|
||||
* $users = ORM::factory('user')->where(DB::expr("BINARY `hash`"), '=', $hash)->find();
|
||||
*
|
||||
* @param string expression
|
||||
* @return Database_Expression
|
||||
*/
|
||||
public static function expr($string)
|
||||
{
|
||||
return new Database_Expression($string);
|
||||
}
|
||||
|
||||
} // End DB
|
@@ -0,0 +1,229 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database-based session class.
|
||||
*
|
||||
* Sample schema:
|
||||
*
|
||||
* CREATE TABLE `sessions` (
|
||||
* `session_id` VARCHAR( 24 ) NOT NULL,
|
||||
* `last_active` INT UNSIGNED NOT NULL,
|
||||
* `contents` TEXT NOT NULL,
|
||||
* PRIMARY KEY ( `session_id` ),
|
||||
* INDEX ( `last_active` )
|
||||
* ) ENGINE = MYISAM ;
|
||||
*
|
||||
* @package Kohana/Database
|
||||
* @category Session
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Session_Database extends Session {
|
||||
|
||||
// Database instance
|
||||
protected $_db;
|
||||
|
||||
// Database table name
|
||||
protected $_table = 'sessions';
|
||||
|
||||
// Database column names
|
||||
protected $_columns = array(
|
||||
'session_id' => 'session_id',
|
||||
'last_active' => 'last_active',
|
||||
'contents' => 'contents'
|
||||
);
|
||||
|
||||
// Garbage collection requests
|
||||
protected $_gc = 500;
|
||||
|
||||
// The current session id
|
||||
protected $_session_id;
|
||||
|
||||
// The old session id
|
||||
protected $_update_id;
|
||||
|
||||
public function __construct(array $config = NULL, $id = NULL)
|
||||
{
|
||||
if ( ! isset($config['group']))
|
||||
{
|
||||
// Use the default group
|
||||
$config['group'] = 'default';
|
||||
}
|
||||
|
||||
// Load the database
|
||||
$this->_db = Database::instance($config['group']);
|
||||
|
||||
if (isset($config['table']))
|
||||
{
|
||||
// Set the table name
|
||||
$this->_table = (string) $config['table'];
|
||||
}
|
||||
|
||||
if (isset($config['gc']))
|
||||
{
|
||||
// Set the gc chance
|
||||
$this->_gc = (int) $config['gc'];
|
||||
}
|
||||
|
||||
if (isset($config['columns']))
|
||||
{
|
||||
// Overload column names
|
||||
$this->_columns = $config['columns'];
|
||||
}
|
||||
|
||||
parent::__construct($config, $id);
|
||||
|
||||
if (mt_rand(0, $this->_gc) === $this->_gc)
|
||||
{
|
||||
// Run garbage collection
|
||||
// This will average out to run once every X requests
|
||||
$this->_gc();
|
||||
}
|
||||
}
|
||||
|
||||
public function id()
|
||||
{
|
||||
return $this->_session_id;
|
||||
}
|
||||
|
||||
protected function _read($id = NULL)
|
||||
{
|
||||
if ($id OR $id = Cookie::get($this->_name))
|
||||
{
|
||||
$result = DB::select(array($this->_columns['contents'], 'contents'))
|
||||
->from($this->_table)
|
||||
->where($this->_columns['session_id'], '=', ':id')
|
||||
->limit(1)
|
||||
->param(':id', $id)
|
||||
->execute($this->_db);
|
||||
|
||||
if ($result->count())
|
||||
{
|
||||
// Set the current session id
|
||||
$this->_session_id = $this->_update_id = $id;
|
||||
|
||||
// Return the contents
|
||||
return $result->get('contents');
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new session id
|
||||
$this->_regenerate();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
protected function _regenerate()
|
||||
{
|
||||
// Create the query to find an ID
|
||||
$query = DB::select($this->_columns['session_id'])
|
||||
->from($this->_table)
|
||||
->where($this->_columns['session_id'], '=', ':id')
|
||||
->limit(1)
|
||||
->bind(':id', $id);
|
||||
|
||||
do
|
||||
{
|
||||
// Create a new session id
|
||||
$id = str_replace('.', '-', uniqid(NULL, TRUE));
|
||||
|
||||
// Get the the id from the database
|
||||
$result = $query->execute($this->_db);
|
||||
}
|
||||
while ($result->count());
|
||||
|
||||
return $this->_session_id = $id;
|
||||
}
|
||||
|
||||
protected function _write()
|
||||
{
|
||||
if ($this->_update_id === NULL)
|
||||
{
|
||||
// Insert a new row
|
||||
$query = DB::insert($this->_table, $this->_columns)
|
||||
->values(array(':new_id', ':active', ':contents'));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update the row
|
||||
$query = DB::update($this->_table)
|
||||
->value($this->_columns['last_active'], ':active')
|
||||
->value($this->_columns['contents'], ':contents')
|
||||
->where($this->_columns['session_id'], '=', ':old_id');
|
||||
|
||||
if ($this->_update_id !== $this->_session_id)
|
||||
{
|
||||
// Also update the session id
|
||||
$query->value($this->_columns['session_id'], ':new_id');
|
||||
}
|
||||
}
|
||||
|
||||
$query
|
||||
->param(':new_id', $this->_session_id)
|
||||
->param(':old_id', $this->_update_id)
|
||||
->param(':active', $this->_data['last_active'])
|
||||
->param(':contents', $this->__toString());
|
||||
|
||||
// Execute the query
|
||||
$query->execute($this->_db);
|
||||
|
||||
// The update and the session id are now the same
|
||||
$this->_update_id = $this->_session_id;
|
||||
|
||||
// Update the cookie with the new session id
|
||||
Cookie::set($this->_name, $this->_session_id, $this->_lifetime);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
protected function _destroy()
|
||||
{
|
||||
if ($this->_update_id === NULL)
|
||||
{
|
||||
// Session has not been created yet
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Delete the current session
|
||||
$query = DB::delete($this->_table)
|
||||
->where($this->_columns['session_id'], '=', ':id')
|
||||
->param(':id', $this->_update_id);
|
||||
|
||||
try
|
||||
{
|
||||
// Execute the query
|
||||
$query->execute($this->_db);
|
||||
|
||||
// Delete the cookie
|
||||
Cookie::delete($this->_name);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// An error occurred, the session has not been deleted
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
protected function _gc()
|
||||
{
|
||||
if ($this->_lifetime)
|
||||
{
|
||||
// Expire sessions when their lifetime is up
|
||||
$expires = $this->_lifetime;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Expire sessions after one month
|
||||
$expires = Date::MONTH;
|
||||
}
|
||||
|
||||
// Delete all sessions that have expired
|
||||
DB::delete($this->_table)
|
||||
->where($this->_columns['last_active'], '<', ':time')
|
||||
->param(':time', time() - $expires)
|
||||
->execute($this->_db);
|
||||
}
|
||||
|
||||
} // End Session_Database
|
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Session_Database extends Kohana_Session_Database {}
|
Reference in New Issue
Block a user