summaryrefslogtreecommitdiffstats
path: root/system/database/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'system/database/drivers')
-rw-r--r--system/database/drivers/cubrid/cubrid_driver.php145
-rw-r--r--system/database/drivers/cubrid/cubrid_forge.php264
-rw-r--r--system/database/drivers/cubrid/cubrid_result.php24
-rw-r--r--system/database/drivers/cubrid/cubrid_utility.php5
-rw-r--r--system/database/drivers/ibase/ibase_driver.php167
-rw-r--r--system/database/drivers/ibase/ibase_forge.php215
-rw-r--r--system/database/drivers/ibase/ibase_result.php7
-rw-r--r--system/database/drivers/ibase/ibase_utility.php7
-rw-r--r--system/database/drivers/mssql/mssql_driver.php247
-rw-r--r--system/database/drivers/mssql/mssql_forge.php164
-rw-r--r--system/database/drivers/mssql/mssql_result.php26
-rw-r--r--system/database/drivers/mssql/mssql_utility.php20
-rw-r--r--system/database/drivers/mysql/mysql_driver.php155
-rw-r--r--system/database/drivers/mysql/mysql_forge.php242
-rw-r--r--system/database/drivers/mysql/mysql_result.php17
-rw-r--r--system/database/drivers/mysql/mysql_utility.php26
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php158
-rw-r--r--system/database/drivers/mysqli/mysqli_forge.php242
-rw-r--r--system/database/drivers/mysqli/mysqli_result.php12
-rw-r--r--system/database/drivers/mysqli/mysqli_utility.php26
-rw-r--r--system/database/drivers/oci8/oci8_driver.php248
-rw-r--r--system/database/drivers/oci8/oci8_forge.php151
-rw-r--r--system/database/drivers/oci8/oci8_result.php93
-rw-r--r--system/database/drivers/oci8/oci8_utility.php14
-rw-r--r--system/database/drivers/odbc/odbc_driver.php106
-rw-r--r--system/database/drivers/odbc/odbc_forge.php131
-rw-r--r--system/database/drivers/odbc/odbc_result.php17
-rw-r--r--system/database/drivers/odbc/odbc_utility.php11
-rw-r--r--system/database/drivers/pdo/pdo_driver.php354
-rw-r--r--system/database/drivers/pdo/pdo_forge.php130
-rw-r--r--system/database/drivers/pdo/pdo_result.php62
-rw-r--r--system/database/drivers/pdo/pdo_utility.php11
-rw-r--r--system/database/drivers/pdo/subdrivers/index.html10
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_4d_driver.php192
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_4d_forge.php209
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php247
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php219
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php329
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php136
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php260
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php229
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php236
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php146
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_informix_driver.php301
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_informix_forge.php155
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php283
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php229
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_oci_driver.php291
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_oci_forge.php133
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php258
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php62
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php357
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php195
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php202
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php229
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php363
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php136
-rw-r--r--system/database/drivers/postgre/postgre_driver.php301
-rw-r--r--system/database/drivers/postgre/postgre_forge.php257
-rw-r--r--system/database/drivers/postgre/postgre_result.php12
-rw-r--r--system/database/drivers/postgre/postgre_utility.php22
-rw-r--r--system/database/drivers/sqlite/sqlite_driver.php82
-rw-r--r--system/database/drivers/sqlite/sqlite_forge.php195
-rw-r--r--system/database/drivers/sqlite/sqlite_result.php16
-rw-r--r--system/database/drivers/sqlite/sqlite_utility.php11
-rw-r--r--system/database/drivers/sqlite3/sqlite3_driver.php104
-rw-r--r--system/database/drivers/sqlite3/sqlite3_forge.php207
-rw-r--r--system/database/drivers/sqlite3/sqlite3_result.php38
-rw-r--r--system/database/drivers/sqlite3/sqlite3_utility.php13
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_driver.php246
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_forge.php164
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_result.php19
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_utility.php22
73 files changed, 8067 insertions, 2546 deletions
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
index a3d0287f5..21994b093 100644
--- a/system/database/drivers/cubrid/cubrid_driver.php
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 2.1
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CUBRID Database Adapter Class
@@ -40,20 +41,44 @@
*/
class CI_DB_cubrid_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'cubrid';
- // The character used for escaping - no need in CUBRID
- protected $_escape_char = '`';
+ /**
+ * Auto-commit flag
+ *
+ * @var bool
+ */
+ public $auto_commit = TRUE;
- // clause and character used for LIKE escape sequences - not used in CUBRID
- protected $_like_escape_str = '';
- protected $_like_escape_chr = '';
+ // --------------------------------------------------------------------
- protected $_random_keyword = ' RAND()'; // database specific random keyword
+ /**
+ * Identifier escape character
+ *
+ * @var string
+ */
+ protected $_escape_char = '`';
- // CUBRID-specific properties
- public $auto_commit = TRUE;
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RANDOM()', 'RANDOM(%d)');
+
+ // --------------------------------------------------------------------
+ /**
+ * Class constructor
+ *
+ * @param array $params
+ * @return void
+ */
public function __construct($params)
{
parent::__construct($params);
@@ -72,6 +97,8 @@ class CI_DB_cubrid_driver extends CI_DB {
}
}
+ // --------------------------------------------------------------------
+
/**
* Non-persistent database connection
*
@@ -109,7 +136,7 @@ class CI_DB_cubrid_driver extends CI_DB {
* Except for determining if a persistent connection should be used,
* the rest of the logic is the same for db_connect() and db_pconnect().
*
- * @param bool
+ * @param bool $persistent
* @return resource
*/
protected function _cubrid_connect($persistent = FALSE)
@@ -159,9 +186,18 @@ class CI_DB_cubrid_driver extends CI_DB {
*/
public function version()
{
- return isset($this->data_cache['version'])
- ? $this->data_cache['version']
- : $this->data_cache['version'] = cubrid_get_server_info($this->conn_id);
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+ elseif ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
+
+ return ( ! $this->conn_id OR ($version = cubrid_get_server_info($this->conn_id)) === FALSE)
+ ? FALSE
+ : $this->data_cache['version'] = $version;
}
// --------------------------------------------------------------------
@@ -169,7 +205,7 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
@@ -182,6 +218,7 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -260,8 +297,8 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -327,7 +364,7 @@ class CI_DB_cubrid_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
@@ -349,7 +386,7 @@ class CI_DB_cubrid_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
@@ -360,16 +397,40 @@ class CI_DB_cubrid_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return 'SELECT * FROM '.$table.' LIMIT 1';
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->Field;
+
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
+
+ $retval[$i]->default = $query[$i]->Default;
+ $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
@@ -394,12 +455,12 @@ class CI_DB_cubrid_driver extends CI_DB {
*
* Generates a platform-specific batch update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -423,9 +484,29 @@ class CI_DB_cubrid_driver extends CI_DB {
.'ELSE '.$k.' END, ';
}
- return 'UPDATE '.$table.' SET '.substr($cases, 0, -2)
- .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '')
- .$index.' IN ('.implode(',', $ids).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * FROM tables
+ *
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
+ *
+ * @return string
+ */
+ protected function _from_tables()
+ {
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
+ {
+ return '('.implode(', ', $this->qb_from).')';
+ }
+
+ return implode(', ', $this->qb_from);
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php
index d328aa241..db1ce5f70 100644
--- a/system/database/drivers/cubrid/cubrid_forge.php
+++ b/system/database/drivers/cubrid/cubrid_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 2.1
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CUBRID Forge Class
@@ -34,181 +35,182 @@
*/
class CI_DB_cubrid_forge extends CI_DB_forge {
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
protected $_create_database = FALSE;
- protected $_drop_database = FALSE;
/**
- * Process Fields
+ * CREATE TABLE keys flag
*
- * @param mixed the fields
- * @return string
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
*/
- protected function _process_fields($fields)
- {
- $current_field_count = 0;
- $sql = '';
+ protected $_create_table_keys = TRUE;
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field);
-
- empty($attributes['NAME']) OR $sql .= ' '.$this->db->escape_identifiers($attributes['NAME']).' ';
-
- if ( ! empty($attributes['TYPE']))
- {
- $sql .= ' '.$attributes['TYPE'];
-
- if ( ! empty($attributes['CONSTRAINT']))
- {
- switch (strtolower($attributes['TYPE']))
- {
- case 'decimal':
- case 'float':
- case 'numeric':
- $sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
- break;
- case 'enum':
- // Will be supported in the future as part a part of
- // MySQL compatibility features.
- break;
- case 'set':
- $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
- break;
- default:
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
- }
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
+ protected $_drop_database = FALSE;
- /* As of version 8.4.1 CUBRID does not support UNSIGNED INTEGER data type.
- * Will be supported in the next release as a part of MySQL Compatibility.
- *
- if (isset($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
- */
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = FALSE;
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SHORT' => 'INTEGER',
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'BIGINT' => 'NUMERIC',
+ 'FLOAT' => 'DOUBLE',
+ 'REAL' => 'DOUBLE'
+ );
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
+ // --------------------------------------------------------------------
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
- if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
- {
- $sql .= ' UNIQUE';
- }
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ $sqls[] = $sql.' CHANGE '.$field[$i]['_literal'];
}
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
+ else
{
- $sql .= ',';
+ $alter_type = empty($field[$i]['new_name']) ? ' MODIFY ' : ' CHANGE ';
+ $sqls[] = $sql.$alter_type.$this->_process_column($field[$i]);
}
}
- return $sql;
+ return $sqls;
}
// --------------------------------------------------------------------
/**
- * Create Table
+ * Process column
*
- * @param string the table name
- * @param mixed the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @param array $field
+ * @return string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _process_column($field)
{
- $sql = 'CREATE TABLE ';
+ $extra_clause = isset($field['after'])
+ ? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';
- /* As of version 8.4.1 CUBRID does not support this SQL syntax.
- if ($if_not_exists === TRUE)
+ if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)
{
- $sql .= 'IF NOT EXISTS ';
+ $extra_clause = ' FIRST';
}
- */
- $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields);
+ return $this->db->escape_identifiers($field['name'])
+ .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))
+ .' '.$field['type'].$field['length']
+ .$field['unsigned']
+ .$field['null']
+ .$field['default']
+ .$field['auto_increment']
+ .$field['unique']
+ .$extra_clause;
+ }
- // If there is a PK defined
- if (count($primary_keys) > 0)
- {
- $key_name = $this->db->escape_identifiers('pk_'.$table.'_'.implode('_', $primary_keys));
- $sql .= ",\n\tCONSTRAINT ".$key_name.' PRIMARY KEY('.implode(', ', $this->db->escape_identifiers($primary_keys)).')';
- }
+ // --------------------------------------------------------------------
- if (is_array($keys) && count($keys) > 0)
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
{
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key_name = $this->db->escape_identifiers('idx_'.$table.implode('_', $key));
- $key = $this->db->escape_identifiers($key);
- }
- else
- {
- $key_name = $this->db->escape_identifiers('idx_'.$table.$key);
- $key = array($key_name);
- }
-
- $sql .= ",\n\tKEY ".$key_name.' ('.implode(', ', $key).')';
- }
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
}
-
- return $sql."\n);";
}
// --------------------------------------------------------------------
/**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Process indexes
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param array fields
- * @param string the field after which we should add the new field
+ * @param string $table (ignored)
* @return string
*/
- protected function _alter_table($alter_type, $table, $fields, $after_field = '')
+ protected function _process_indexes($table)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' ';
+ $sql = '';
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- return $sql.$this->db->escape_identifiers($fields);
+ if (is_array($this->keys[$i]))
+ {
+ for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i][$i2]]))
+ {
+ unset($this->keys[$i][$i2]);
+ continue;
+ }
+ }
+ }
+ elseif ( ! isset($this->fields[$this->keys[$i]]))
+ {
+ unset($this->keys[$i]);
+ continue;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
- return $sql.$this->_process_fields($fields)
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ $this->keys = array();
+
+ return $sql;
}
}
diff --git a/system/database/drivers/cubrid/cubrid_result.php b/system/database/drivers/cubrid/cubrid_result.php
index 4a06a2d39..793b35b74 100644
--- a/system/database/drivers/cubrid/cubrid_result.php
+++ b/system/database/drivers/cubrid/cubrid_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 2.1
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CUBRID Result Class
@@ -87,20 +88,14 @@ class CI_DB_cubrid_result extends CI_DB_result {
public function field_data()
{
$retval = array();
- $i = 0;
- while ($field = cubrid_fetch_field($this->result_id))
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
$retval[$i] = new stdClass();
- $retval[$i]->name = $field->name;
- // CUBRID returns type as e.g. varchar(100),
- // so we need to remove all digits and brackets.
- $retval[$i]->type = preg_replace('/[\d()]/', '', $field->type);
- $retval[$i]->default = $field->def;
- // Use CUBRID's native API to obtain column's max_length,
- // otherwise $field->max_length has incorrect info
+ $retval[$i]->name = cubrid_field_name($this->result_id, $i);
+ $retval[$i]->type = cubrid_field_type($this->result_id, $i);
$retval[$i]->max_length = cubrid_field_len($this->result_id, $i);
- $retval[$i++]->primary_key = $field->primary_key;
+ $retval[$i]->primary_key = (int) (strpos(cubrid_field_flags($this->result_id, $i), 'primary_key') !== FALSE);
}
return $retval;
@@ -130,11 +125,12 @@ class CI_DB_cubrid_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n
* @return bool
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return cubrid_data_seek($this->result_id, $n);
}
@@ -160,7 +156,7 @@ class CI_DB_cubrid_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @param string
+ * @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
diff --git a/system/database/drivers/cubrid/cubrid_utility.php b/system/database/drivers/cubrid/cubrid_utility.php
index ea8feb4e2..d76eca432 100644
--- a/system/database/drivers/cubrid/cubrid_utility.php
+++ b/system/database/drivers/cubrid/cubrid_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 2.1
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CUBRID Utility Class
@@ -62,7 +63,7 @@ class CI_DB_cubrid_utility extends CI_DB_utility {
// No SQL based support in CUBRID as of version 8.4.0. Database or
// table backup can be performed using CUBRID Manager
// database administration tool.
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/ibase/ibase_driver.php b/system/database/drivers/ibase/ibase_driver.php
index c9027670d..15c2a4630 100644
--- a/system/database/drivers/ibase/ibase_driver.php
+++ b/system/database/drivers/ibase/ibase_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 3.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Firebird/Interbase Database Adapter Class
@@ -40,19 +41,30 @@
*/
class CI_DB_ibase_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'ibase';
- // The character used to escape with
- protected $_escape_char = '"';
+ // --------------------------------------------------------------------
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RAND()', 'RAND()');
- protected $_random_keyword = ' Random()'; // database specific random keyword
+ /**
+ * IBase Transaction status flag
+ *
+ * @var resource
+ */
+ protected $_ibase_trans;
- // Keeps track of the resource for the current transaction
- protected $trans;
+ // --------------------------------------------------------------------
/**
* Non-persistent database connection
@@ -107,7 +119,7 @@ class CI_DB_ibase_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
@@ -120,6 +132,7 @@ class CI_DB_ibase_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -135,7 +148,7 @@ class CI_DB_ibase_driver extends CI_DB {
// even if the queries produce a successful result.
$this->_trans_failure = ($test_mode === TRUE);
- $this->trans = @ibase_trans($this->conn_id);
+ $this->_ibase_trans = @ibase_trans($this->conn_id);
return TRUE;
}
@@ -155,7 +168,7 @@ class CI_DB_ibase_driver extends CI_DB {
return TRUE;
}
- return @ibase_commit($this->trans);
+ return @ibase_commit($this->_ibase_trans);
}
// --------------------------------------------------------------------
@@ -173,7 +186,7 @@ class CI_DB_ibase_driver extends CI_DB {
return TRUE;
}
- return @ibase_rollback($this->trans);
+ return @ibase_rollback($this->_ibase_trans);
}
// --------------------------------------------------------------------
@@ -181,8 +194,8 @@ class CI_DB_ibase_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -242,7 +255,7 @@ class CI_DB_ibase_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
@@ -265,7 +278,7 @@ class CI_DB_ibase_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
@@ -276,16 +289,46 @@ class CI_DB_ibase_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return $this->_limit('SELECT * FROM '.$this->protect_identifiers($table), 1, NULL);
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT "rfields"."RDB$FIELD_NAME" AS "name",
+ CASE "fields"."RDB$FIELD_TYPE"
+ WHEN 7 THEN \'SMALLINT\'
+ WHEN 8 THEN \'INTEGER\'
+ WHEN 9 THEN \'QUAD\'
+ WHEN 10 THEN \'FLOAT\'
+ WHEN 11 THEN \'DFLOAT\'
+ WHEN 12 THEN \'DATE\'
+ WHEN 13 THEN \'TIME\'
+ WHEN 14 THEN \'CHAR\'
+ WHEN 16 THEN \'INT64\'
+ WHEN 27 THEN \'DOUBLE\'
+ WHEN 35 THEN \'TIMESTAMP\'
+ WHEN 37 THEN \'VARCHAR\'
+ WHEN 40 THEN \'CSTRING\'
+ WHEN 261 THEN \'BLOB\'
+ ELSE NULL
+ END AS "type",
+ "fields"."RDB$FIELD_LENGTH" AS "max_length",
+ "rfields"."RDB$DEFAULT_VALUE" AS "default"
+ FROM "RDB$RELATION_FIELDS" "rfields"
+ JOIN "RDB$FIELDS" "fields" ON "rfields"."RDB$FIELD_SOURCE" = "fields"."RDB$FIELD_NAME"
+ WHERE "rfields"."RDB$RELATION_NAME" = '.$this->escape($table).'
+ ORDER BY "rfields"."RDB$FIELD_POSITION"';
+
+ return (($query = $this->query($sql)) !== FALSE)
+ ? $query->result_object()
+ : FALSE;
}
// --------------------------------------------------------------------
@@ -306,51 +349,18 @@ class CI_DB_ibase_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This public function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @param array the orderby clause
- * @param array the limit clause (ignored)
- * @param array the like clause
+ * @param string $table
+ * @param array $values
* @return string
*/
- protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array())
+ protected function _update($table, $values)
{
- foreach ($values as $key => $val)
- {
- $valstr[] = $key.' = '.$val;
- }
-
- $where = empty($where) ? '' : ' WHERE '.implode(' ', $where);
-
- if ( ! empty($like))
- {
- $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like);
- }
-
- return 'UPDATE '.$table.' SET '.implode(', ', $valstr)
- .$where
- .(count($orderby) > 0 ? ' ORDER BY '.implode(', ', $orderby) : '');
+ $this->qb_limit = FALSE;
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -360,10 +370,10 @@ class CI_DB_ibase_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
@@ -378,46 +388,37 @@ class CI_DB_ibase_driver extends CI_DB {
*
* Generates a platform-specific delete string from the supplied data
*
- * @param string the table name
- * @param array the where clause
- * @param array the like clause
- * @param string the limit clause (ignored)
+ * @param string $table
* @return string
*/
- protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '');
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * LIMIT
*
* Generates a platform-specific LIMIT clause
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
+ * @param string $sql SQL Query
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _limit($sql)
{
// Limit clause depends on if Interbase or Firebird
if (stripos($this->version(), 'firebird') !== FALSE)
{
- $select = 'FIRST '. (int) $limit
- .($offset ? ' SKIP '. (int) $offset : '');
+ $select = 'FIRST '.$this->qb_limit
+ .($this->qb_offset ? ' SKIP '.$this->qb_offset : '');
}
else
{
$select = 'ROWS '
- .($offset ? (int) $offset.' TO '.($limit + $offset) : (int) $limit);
+ .($this->qb_offset ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit);
}
return preg_replace('`SELECT`i', 'SELECT '.$select, $sql);
diff --git a/system/database/drivers/ibase/ibase_forge.php b/system/database/drivers/ibase/ibase_forge.php
index da75eb9c3..39c782816 100644
--- a/system/database/drivers/ibase/ibase_forge.php
+++ b/system/database/drivers/ibase/ibase_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 3.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Interbase/Firebird Forge Class
@@ -34,12 +35,51 @@
*/
class CI_DB_ibase_forge extends CI_DB_forge {
- protected $_drop_table = 'DROP TABLE %s';
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = FALSE;
+
+ /**
+ * RENAME TABLE statement
+ *
+ * @var string
+ */
+ protected $_rename_table = FALSE;
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SMALLINT' => 'INTEGER',
+ 'INTEGER' => 'INT64',
+ 'FLOAT' => 'DOUBLE PRECISION'
+ );
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
/**
* Create database
*
- * @param string the database name
+ * @param string $db_name
* @return string
*/
public function create_database($db_name)
@@ -57,8 +97,7 @@ class CI_DB_ibase_forge extends CI_DB_forge {
/**
* Drop database
*
- * @param string the database name
- * - not used in this driver, the current db is dropped
+ * @param string $db_name (ignored)
* @return bool
*/
public function drop_database($db_name = '')
@@ -82,110 +121,120 @@ class CI_DB_ibase_forge extends CI_DB_forge {
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return string
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
-
- $sql .= $this->db->escape_identifiers($table).'(';
- $current_field_count = 0;
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
- foreach ($fields as $field => $attributes)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
+ if ($field[$i]['_literal'] !== FALSE)
{
- $sql .= "\n\t".$attributes;
+ return FALSE;
}
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- empty($attributes['CONSTRAINT']) OR $sql .= '('.$attributes['CONSTRAINT'].')';
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
-
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
+ if (isset($field[$i]['type']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identififers($field[$i]['name'])
+ .' TYPE '.$field[$i]['type'].$field[$i]['length'];
}
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
+ if ( ! empty($field[$i]['default']))
{
- $sql .= ',';
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' SET DEFAULT '.$field[$i]['default'];
}
- }
- if (count($primary_keys) > 0)
- {
- $primary_keys = $this->db->escape_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $primary_keys).')';
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
+ if (isset($field[$i]['null']))
{
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
+ $sqls[] = 'UPDATE "RDB$RELATION_FIELDS" SET "RDB$NULL_FLAG" = '
+ .($field[$i]['null'] === TRUE ? 'NULL' : '1')
+ .' WHERE "RDB$FIELD_NAME" = '.$this->db->escape($field[$i]['name'])
+ .' AND "RDB$RELATION_NAME" = '.$this->db->escape($table);
+ }
- $sql .= ",\n\tUNIQUE (".implode(', ', $key).')';
+ if ( ! empty($field[$i]['new_name']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
}
}
- return $sql."\n)";
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type'].$field['length']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute TYPE
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Performs a data type mapping between different databases.
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INT':
+ $attributes['TYPE'] = 'INTEGER';
+ return;
+ case 'BIGINT':
+ $attributes['TYPE'] = 'INT64';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- return 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name)
- .' '.$column_definition
- .($default_value !== '' ? ' DEFAULT "'.$default_value.'"' : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ // Not supported
}
}
diff --git a/system/database/drivers/ibase/ibase_result.php b/system/database/drivers/ibase/ibase_result.php
index 95e55710b..4f5637a72 100644
--- a/system/database/drivers/ibase/ibase_result.php
+++ b/system/database/drivers/ibase/ibase_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Interbase/Firebird Result Class
@@ -88,8 +89,6 @@ class CI_DB_ibase_result extends CI_DB_result {
$retval[$i]->name = $info['name'];
$retval[$i]->type = $info['type'];
$retval[$i]->max_length = $info['length'];
- $retval[$i]->primary_key = 0;
- $retval[$i]->default = '';
}
return $retval;
@@ -128,7 +127,7 @@ class CI_DB_ibase_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @param string
+ * @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
diff --git a/system/database/drivers/ibase/ibase_utility.php b/system/database/drivers/ibase/ibase_utility.php
index d0e84a7b2..5eb209ae1 100644
--- a/system/database/drivers/ibase/ibase_utility.php
+++ b/system/database/drivers/ibase/ibase_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 3.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Interbase/Firebird Utility Class
@@ -34,10 +35,8 @@
*/
class CI_DB_ibase_utility extends CI_DB_utility {
- protected $_list_databases = FALSE;
-
/**
- * Interbase/Firebird Export
+ * Export
*
* @param string $filename
* @return mixed
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index 1714704a8..d3e439d69 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MS SQL Database Adapter Class
@@ -40,26 +41,40 @@
*/
class CI_DB_mssql_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'mssql';
- // The character used for escaping
- protected $_escape_char = '"';
-
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
+ // --------------------------------------------------------------------
- protected $_random_keyword = ' NEWID()';
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('NEWID()', 'RAND(%d)');
- // MSSQL-specific properties
+ /**
+ * Quoted identifier flag
+ *
+ * Whether to use SQL-92 standard quoted identifier
+ * (double quotes) or brackets for identifier escaping.
+ *
+ * @var bool
+ */
protected $_quoted_identifier = TRUE;
- /*
- * Constructor
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
*
* Appends the port number to the hostname, if needed.
*
- * @param array
+ * @param array $params
* @return void
*/
public function __construct($params)
@@ -77,7 +92,7 @@ class CI_DB_mssql_driver extends CI_DB {
/**
* Non-persistent database connection
*
- * @param bool
+ * @param bool $persistent
* @return resource
*/
public function db_connect($persistent = FALSE)
@@ -117,7 +132,7 @@ class CI_DB_mssql_driver extends CI_DB {
/**
* Select the database
*
- * @param string database name
+ * @param string $database
* @return bool
*/
public function db_select($database = '')
@@ -143,7 +158,7 @@ class CI_DB_mssql_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return mixed resource if rows are returned, bool otherwise
*/
protected function _execute($sql)
@@ -156,6 +171,7 @@ class CI_DB_mssql_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -215,8 +231,8 @@ class CI_DB_mssql_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -282,6 +298,19 @@ class CI_DB_mssql_driver extends CI_DB {
// --------------------------------------------------------------------
/**
+ * Set client character set
+ *
+ * @param string $charset
+ * @return bool
+ */
+ protected function _db_set_charset($charset)
+ {
+ return (@ini_set('mssql.charset', $charset) !== FALSE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Version number query string
*
* @return string
@@ -298,7 +327,7 @@ class CI_DB_mssql_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
@@ -323,27 +352,52 @@ class CI_DB_mssql_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
{
- return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$table."'";
+ return 'SELECT COLUMN_NAME
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
}
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table);
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
+ $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;
+ $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
@@ -366,49 +420,19 @@ class CI_DB_mssql_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @param array the orderby clause (ignored)
- * @param array the limit clause (ignored)
- * @param array the like clause
+ * @param string $table
+ * @param array $values
* @return string
*/
- protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array())
+ protected function _update($table, $values)
{
- foreach($values as $key => $val)
- {
- $valstr[] = $key.' = '.$val;
- }
-
- $where = empty($where) ? '' : ' WHERE '.implode(' ', $where);
-
- if ( ! empty($like))
- {
- $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like);
- }
-
- return 'UPDATE '.$table.' SET '.implode(', ', $valstr).' WHERE '.$where;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -418,10 +442,10 @@ class CI_DB_mssql_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
@@ -436,61 +460,65 @@ class CI_DB_mssql_driver extends CI_DB {
*
* Generates a platform-specific delete string from the supplied data
*
- * @param string the table name
- * @param array the where clause
- * @param array the like clause
- * @param string the limit clause
+ * @param string $table
* @return string
*/
- protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
+ if ($this->qb_limit)
+ {
+ return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';
+ }
- return ($limit)
- ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete'
- : 'DELETE FROM '.$table.$conditions;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * LIMIT
*
* Generates a platform-specific LIMIT clause
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
+ * @param string $sql SQL Query
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _limit($sql)
{
- // As of SQL Server 2012 (11.0.*) OFFSET is supported
- if (version_compare($this->version(), '11', '>='))
- {
- return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY';
- }
-
- $limit = $offset + $limit;
+ $limit = $this->qb_offset + $this->qb_limit;
// As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported,
// however an ORDER BY clause is required for it to work
- if (version_compare($this->version(), '9', '>=') && $offset && ! empty($this->qb_orderby))
+ if (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby))
{
- $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby);
+ $orderby = $this->_compile_order_by();
// We have to strip the ORDER BY clause
- $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby)));
+ $sql = trim(substr($sql, 0, strrpos($sql, $orderby)));
+
+ // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results
+ if (count($this->qb_select) === 0)
+ {
+ $select = '*'; // Inevitable
+ }
+ else
+ {
+ // Use only field names and their aliases, everything else is out of our scope.
+ $select = array();
+ $field_regexp = ($this->_quoted_identifier)
+ ? '("[^\"]+")' : '(\[[^\]]+\])';
+ for ($i = 0, $c = count($this->qb_select); $i < $c; $i++)
+ {
+ $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)
+ ? $m[1] : $this->qb_select[$i];
+ }
+ $select = implode(', ', $select);
+ }
- return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n"
- .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)
- ."\n) ".$this->escape_identifiers('CI_subquery')
- ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit;
+ return 'SELECT '.$select." FROM (\n\n"
+ .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)
+ ."\n\n) ".$this->escape_identifiers('CI_subquery')
+ ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
}
return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
@@ -499,6 +527,29 @@ class CI_DB_mssql_driver extends CI_DB {
// --------------------------------------------------------------------
/**
+ * Insert batch statement
+ *
+ * Generates a platform-specific insert string from the supplied data.
+ *
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string|bool
+ */
+ protected function _insert_batch($table, $keys, $values)
+ {
+ // Multiple-value inserts are only supported as of SQL Server 2008
+ if (version_compare($this->version(), '10', '>='))
+ {
+ return parent::_insert_batch($table, $keys, $values);
+ }
+
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Close DB Connection
*
* @return void
diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php
index 3a3528f7b..5eebedbf7 100644
--- a/system/database/drivers/mssql/mssql_forge.php
+++ b/system/database/drivers/mssql/mssql_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MS SQL Forge Class
@@ -34,124 +35,99 @@
*/
class CI_DB_mssql_forge extends CI_DB_forge {
- protected $_drop_table = 'DROP TABLE %s';
-
/**
- * Create Table
+ * CREATE TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return string
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = ($if_not_exists === TRUE)
- ? "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'".$table."') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\n"
- : '';
-
- $sql .= 'CREATE TABLE '.$this->db->escape_identifiers($table).' (';
-
- $current_field_count = 0;
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- if (stripos($attributes['TYPE'], 'INT') === FALSE && ! empty($attributes['CONSTRAINT']))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
+ protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ // --------------------------------------------------------------------
- if (count($primary_keys) > 0)
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
{
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')';
+ return parent::_alter_table($alter_type, $table, $field);
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')';
- }
+ $sqls[] = $sql.$this->_process_column($field[$i]);
}
- return $sql."\n)";
+ return $sqls;
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute TYPE
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Performs a data type mapping between different databases.
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_type(&$attributes)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
+ switch (strtoupper($attributes['TYPE']))
{
- return $sql;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
}
+ }
- return $sql.' '.$column_definition
- .($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field != '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' IDENTITY(1,1)';
+ }
}
}
diff --git a/system/database/drivers/mssql/mssql_result.php b/system/database/drivers/mssql/mssql_result.php
index aeede3f4b..ca222aed4 100644
--- a/system/database/drivers/mssql/mssql_result.php
+++ b/system/database/drivers/mssql/mssql_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MSSQL Result Class
@@ -93,16 +94,14 @@ class CI_DB_mssql_result extends CI_DB_result {
public function field_data()
{
$retval = array();
- while ($field = mssql_fetch_field($this->result_id))
+ for ($i = 0, $c = $this->num_field(); $i < $c; $i++)
{
- $F = new stdClass();
- $F->name = $field->name;
- $F->type = $field->type;
- $F->max_length = $field->max_length;
- $F->primary_key = 0;
- $F->default = '';
-
- $retval[] = $F;
+ $field = mssql_fetch_field($this->result_id, $i);
+
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $field->name;
+ $retval[$i]->type = $field->type;
+ $retval[$i]->max_length = $field->max_length;
}
return $retval;
@@ -131,11 +130,12 @@ class CI_DB_mssql_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n
* @return bool
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return mssql_data_seek($this->result_id, $n);
}
@@ -161,7 +161,7 @@ class CI_DB_mssql_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @param string
+ * @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
diff --git a/system/database/drivers/mssql/mssql_utility.php b/system/database/drivers/mssql/mssql_utility.php
index 69fcec5f6..76c7cb9c2 100644
--- a/system/database/drivers/mssql/mssql_utility.php
+++ b/system/database/drivers/mssql/mssql_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MS SQL Utility Class
@@ -34,19 +35,30 @@
*/
class CI_DB_mssql_utility extends CI_DB_utility {
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases
+
+ /**
+ * OPTIMIZE TABLE statement
+ *
+ * @var string
+ */
protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE';
/**
- * MSSQL Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return bool
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index 29db90408..5af44371c 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQL Database Adapter Class
@@ -40,28 +41,46 @@
*/
class CI_DB_mysql_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'mysql';
- // The character used for escaping
- protected $_escape_char = '`';
-
- // clause and character used for LIKE escape sequences - not used in MySQL
- protected $_like_escape_str = '';
- protected $_like_escape_chr = '\\';
-
- protected $_random_keyword = ' RAND()'; // database specific random keyword
+ /**
+ * Compression flag
+ *
+ * @var bool
+ */
+ public $compress = FALSE;
/**
+ * DELETE hack flag
+ *
* Whether to use the MySQL "delete hack" which allows the number
* of affected rows to be shown. Uses a preg_replace when enabled,
* adding a bit more processing to all queries.
+ *
+ * @var bool
*/
public $delete_hack = TRUE;
+ // --------------------------------------------------------------------
+
+ /**
+ * Identifier escape character
+ *
+ * @var string
+ */
+ protected $_escape_char = '`';
+
+ // --------------------------------------------------------------------
+
/**
- * Constructor
+ * Class constructor
*
- * @param array
+ * @param array $params
* @return void
*/
public function __construct($params)
@@ -79,11 +98,21 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Non-persistent database connection
*
+ * @param bool $persistent
* @return resource
*/
- public function db_connect()
+ public function db_connect($persistent = FALSE)
{
- return @mysql_connect($this->hostname, $this->username, $this->password, TRUE);
+ $client_flags = ($this->compress === FALSE) ? 0 : MYSQL_CLIENT_COMPRESS;
+
+ if ($this->encrypt === TRUE)
+ {
+ $client_flags = $client_flags | MYSQL_CLIENT_SSL;
+ }
+
+ return ($persistent === TRUE)
+ ? @mysql_pconnect($this->hostname, $this->username, $this->password, $client_flags)
+ : @mysql_connect($this->hostname, $this->username, $this->password, TRUE, $client_flags);
}
// --------------------------------------------------------------------
@@ -95,7 +124,7 @@ class CI_DB_mysql_driver extends CI_DB {
*/
public function db_pconnect()
{
- return @mysql_pconnect($this->hostname, $this->username, $this->password);
+ return $this->db_connect(TRUE);
}
// --------------------------------------------------------------------
@@ -121,7 +150,7 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Select the database
*
- * @param string database name
+ * @param string $database
* @return bool
*/
public function db_select($database = '')
@@ -145,7 +174,7 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Set client character set
*
- * @param string
+ * @param string $charset
* @return bool
*/
protected function _db_set_charset($charset)
@@ -162,9 +191,21 @@ class CI_DB_mysql_driver extends CI_DB {
*/
public function version()
{
- return isset($this->data_cache['version'])
- ? $this->data_cache['version']
- : $this->data_cache['version'] = @mysql_get_server_info($this->conn_id);
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+ elseif ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
+
+ if ( ! $this->conn_id OR ($version = @mysql_get_server_info($this->conn_id)) === FALSE)
+ {
+ return FALSE;
+ }
+
+ return $this->data_cache['version'] = $version;
}
// --------------------------------------------------------------------
@@ -172,7 +213,7 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return mixed
*/
protected function _execute($sql)
@@ -187,7 +228,7 @@ class CI_DB_mysql_driver extends CI_DB {
*
* If needed, each database adapter can prep the query string
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return string
*/
protected function _prep_query($sql)
@@ -207,6 +248,7 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -272,8 +314,8 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -281,12 +323,12 @@ class CI_DB_mysql_driver extends CI_DB {
if (is_array($str))
{
foreach ($str as $key => $val)
- {
+ {
$str[$key] = $this->escape_str($val, $like);
- }
+ }
- return $str;
- }
+ return $str;
+ }
$str = is_resource($this->conn_id) ? mysql_real_escape_string($str, $this->conn_id) : addslashes($str);
@@ -332,7 +374,7 @@ class CI_DB_mysql_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
@@ -354,7 +396,7 @@ class CI_DB_mysql_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
@@ -367,8 +409,8 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Returns an object with field data
*
- * @param string the table name
- * @return object
+ * @param string $table
+ * @return array
*/
public function field_data($table = '')
{
@@ -377,19 +419,24 @@ class CI_DB_mysql_driver extends CI_DB {
return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
}
- $query = $this->query('DESCRIBE '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
+ {
+ return FALSE;
+ }
$query = $query->result_object();
$retval = array();
for ($i = 0, $c = count($query); $i < $c; $i++)
{
- preg_match('/([a-z]+)(\(\d+\))?/', $query[$i]->Type, $matches);
-
$retval[$i] = new stdClass();
$retval[$i]->name = $query[$i]->Field;
- $retval[$i]->type = empty($matches[1]) ? NULL : $matches[1];
+
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
+
$retval[$i]->default = $query[$i]->Default;
- $retval[$i]->max_length = empty($matches[2]) ? NULL : preg_replace('/[^\d]/', '', $matches[2]);
$retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
}
@@ -418,12 +465,12 @@ class CI_DB_mysql_driver extends CI_DB {
*
* Generates a platform-specific batch update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -434,7 +481,7 @@ class CI_DB_mysql_driver extends CI_DB {
{
if ($field !== $index)
{
- $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
}
}
}
@@ -447,9 +494,29 @@ class CI_DB_mysql_driver extends CI_DB {
.'ELSE '.$k.' END, ';
}
- return 'UPDATE '.$table.' SET '.substr($cases, 0, -2)
- .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '')
- .$index.' IN('.implode(',', $ids).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * FROM tables
+ *
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
+ *
+ * @return string
+ */
+ protected function _from_tables()
+ {
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
+ {
+ return '('.implode(', ', $this->qb_from).')';
+ }
+
+ return implode(', ', $this->qb_from);
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php
index 2ac75bad2..f4394c685 100644
--- a/system/database/drivers/mysql/mysql_forge.php
+++ b/system/database/drivers/mysql/mysql_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQL Forge Class
@@ -34,165 +35,178 @@
*/
class CI_DB_mysql_forge extends CI_DB_forge {
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';
/**
- * Process Fields
+ * CREATE TABLE keys flag
*
- * @param mixed the fields
- * @return string
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
*/
- protected function _process_fields($fields)
- {
- $current_field_count = 0;
- $sql = '';
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field);
-
- empty($attributes['NAME']) OR $sql .= ' '.$this->db->escape_identifiers($attributes['NAME']).' ';
-
- if ( ! empty($attributes['TYPE']))
- {
- $sql .= ' '.$attributes['TYPE'];
-
- if ( ! empty($attributes['CONSTRAINT']))
- {
- switch (strtolower($attributes['TYPE']))
- {
- case 'decimal':
- case 'float':
- case 'numeric':
- $sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
- break;
- case 'enum':
- case 'set':
- $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
- break;
- default:
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
- }
+ protected $_create_table_keys = TRUE;
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT',
+ 'SMALLINT',
+ 'MEDIUMINT',
+ 'INT',
+ 'INTEGER',
+ 'BIGINT',
+ 'REAL',
+ 'DOUBLE',
+ 'DOUBLE PRECISION',
+ 'FLOAT',
+ 'DECIMAL',
+ 'NUMERIC'
+ );
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ // --------------------------------------------------------------------
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
+ {
+ parent::__construct($db);
- return $sql;
+ $this->_create_table .= ' DEFAULT CHARSET '.$this->db->char_set.' COLLATE '.$this->db->dbcollat;
}
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param mixed the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields);
-
- if (count($primary_keys) > 0)
+ if ($alter_type === 'DROP')
{
- $key_name = $this->db->escape_identifiers(implode('_', $primary_keys));
- $sql .= ",\n\tPRIMARY KEY ".$key_name.' ('.implode(', ', $this->db->escape_identifiers($primary_keys)).')';
+ return parent::_alter_table($alter_type, $table, $field);
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
+ if ($field[$i]['_literal'] !== FALSE)
{
- if (is_array($key))
+ $field[$i] = ($alter_type === 'ADD')
+ ? "\n\tADD ".$field[$i]['_literal']
+ : "\n\tMODIFY ".$field[$i]['_literal'];
+ }
+ else
+ {
+ if ($alter_type === 'ADD')
{
- $key_name = $this->db->escape_identifiers(implode('_', $key));
- $key = $this->db->escape_identifiers($key);
+ $field[$i]['_literal'] = "\n\tADD ";
}
else
{
- $key_name = $this->db->escape_identifiers($key);
- $key = array($key_name);
+ $field[$i]['_literal'] = empty($field[$i]['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE ";
}
- $sql .= ",\n\tKEY ".$key_name.' ('.implode(', ', $key).')';
+ $field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]);
}
}
- return $sql."\n) DEFAULT CHARACTER SET ".$this->db->char_set.' COLLATE '.$this->db->dbcollat.';';
+ return array($sql.implode(',', $field));
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Process column
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column() and column_alter()
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ $extra_clause = isset($field['after'])
+ ? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';
+
+ if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)
+ {
+ $extra_clause = ' FIRST';
+ }
+
+ return $this->db->escape_identifiers($field['name'])
+ .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))
+ .' '.$field['type'].$field['length']
+ .$field['unsigned']
+ .$field['null']
+ .$field['default']
+ .$field['auto_increment']
+ .$field['unique']
+ .$extra_clause;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param array fields
- * @param string the field after which we should add the new field
+ * @param string $table (ignored)
* @return string
*/
- protected function _alter_table($alter_type, $table, $fields, $after_field = '')
+ protected function _process_indexes($table)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' ';
+ $sql = '';
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- return $sql.$this->db->escape_identifiers($fields);
+ if (is_array($this->keys[$i]))
+ {
+ for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i][$i2]]))
+ {
+ unset($this->keys[$i][$i2]);
+ continue;
+ }
+ }
+ }
+ elseif ( ! isset($this->fields[$this->keys[$i]]))
+ {
+ unset($this->keys[$i]);
+ continue;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
- return $sql.$this->_process_fields($fields)
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ $this->keys = array();
+
+ return $sql;
}
}
diff --git a/system/database/drivers/mysql/mysql_result.php b/system/database/drivers/mysql/mysql_result.php
index 7fbb65496..293980e97 100644
--- a/system/database/drivers/mysql/mysql_result.php
+++ b/system/database/drivers/mysql/mysql_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQL Result Class
@@ -38,9 +39,9 @@
class CI_DB_mysql_result extends CI_DB_result {
/**
- * Constructor
+ * Class constructor
*
- * @param object
+ * @param object &$driver_object
* @return void
*/
public function __construct(&$driver_object)
@@ -114,8 +115,7 @@ class CI_DB_mysql_result extends CI_DB_result {
$retval[$i]->name = mysql_field_name($this->result_id, $i);
$retval[$i]->type = mysql_field_type($this->result_id, $i);
$retval[$i]->max_length = mysql_field_len($this->result_id, $i);
- $retval[$i]->primary_key = (strpos(mysql_field_flags($this->result_id, $i), 'primary_key') === FALSE) ? 0 : 1;
- $retval[$i]->default = '';
+ $retval[$i]->primary_key = (int) (strpos(mysql_field_flags($this->result_id, $i), 'primary_key') !== FALSE);
}
return $retval;
@@ -144,11 +144,12 @@ class CI_DB_mysql_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n
* @return bool
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return $this->num_rows
? @mysql_data_seek($this->result_id, $n)
@@ -176,7 +177,7 @@ class CI_DB_mysql_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @param string
+ * @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
diff --git a/system/database/drivers/mysql/mysql_utility.php b/system/database/drivers/mysql/mysql_utility.php
index f0bbc665e..8aa051755 100644
--- a/system/database/drivers/mysql/mysql_utility.php
+++ b/system/database/drivers/mysql/mysql_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQL Utility Class
@@ -34,14 +35,33 @@
*/
class CI_DB_mysql_utility extends CI_DB_utility {
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
protected $_list_databases = 'SHOW DATABASES';
+
+ /**
+ * OPTIMIZE TABLE statement
+ *
+ * @var string
+ */
protected $_optimize_table = 'OPTIMIZE TABLE %s';
+
+ /**
+ * REPAIR TABLE statement
+ *
+ * @var string
+ */
protected $_repair_table = 'REPAIR TABLE %s';
+ // --------------------------------------------------------------------
+
/**
- * MySQL Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index be61aab20..17f025f61 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQLi Database Adapter Class
@@ -40,34 +41,60 @@
*/
class CI_DB_mysqli_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'mysqli';
- // The character used for escaping
- protected $_escape_char = '`';
-
- // clause and character used for LIKE escape sequences - not used in MySQL
- protected $_like_escape_str = '';
- protected $_like_escape_chr = '\\';
-
- protected $_random_keyword = ' RAND()'; // database specific random keyword
+ /**
+ * Compression flag
+ *
+ * @var bool
+ */
+ public $compress = FALSE;
/**
+ * DELETE hack flag
+ *
* Whether to use the MySQL "delete hack" which allows the number
* of affected rows to be shown. Uses a preg_replace when enabled,
* adding a bit more processing to all queries.
+ *
+ * @var bool
*/
public $delete_hack = TRUE;
+ // --------------------------------------------------------------------
+
/**
- * Non-persistent database connection
+ * Identifier escape character
*
+ * @var string
+ */
+ protected $_escape_char = '`';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database connection
+ *
+ * @param bool $persistent
* @return object
+ * @todo SSL support
*/
- public function db_connect()
+ public function db_connect($persistent = FALSE)
{
- return empty($this->port)
- ? @new mysqli($this->hostname, $this->username, $this->password, $this->database)
- : @new mysqli($this->hostname, $this->username, $this->password, $this->database, $this->port);
+ // Persistent connection support was added in PHP 5.3.0
+ $hostname = ($persistent === TRUE && is_php('5.3'))
+ ? 'p:'.$this->hostname : $this->hostname;
+ $port = empty($this->port) ? NULL : $this->port;
+ $client_flags = ($this->compress === TRUE) ? MYSQLI_CLIENT_COMPRESS : 0;
+ $mysqli = mysqli_init();
+
+ return @$mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, NULL, $client_flags)
+ ? $mysqli : FALSE;
}
// --------------------------------------------------------------------
@@ -79,15 +106,7 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
public function db_pconnect()
{
- // Persistent connection support was added in PHP 5.3.0
- if ( ! is_php('5.3'))
- {
- return $this->db_connect();
- }
-
- return empty($this->port)
- ? @new mysqli('p:'.$this->hostname, $this->username, $this->password, $this->database)
- : @new mysqli('p:'.$this->hostname, $this->username, $this->password, $this->database, $this->port);
+ return $this->db_connect(TRUE);
}
// --------------------------------------------------------------------
@@ -113,7 +132,7 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Select the database
*
- * @param string database name
+ * @param string $database
* @return bool
*/
public function db_select($database = '')
@@ -137,7 +156,7 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Set client character set
*
- * @param string
+ * @param string $charset
* @return bool
*/
protected function _db_set_charset($charset)
@@ -154,9 +173,16 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
public function version()
{
- return isset($this->data_cache['version'])
- ? $this->data_cache['version']
- : $this->data_cache['version'] = $this->conn_id->server_info;
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+ elseif ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
+
+ return $this->data_cache['version'] = $this->conn_id->server_info;
}
// --------------------------------------------------------------------
@@ -164,7 +190,7 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return mixed
*/
protected function _execute($sql)
@@ -179,7 +205,7 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* If needed, each database adapter can prep the query string
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return string
*/
protected function _prep_query($sql)
@@ -199,6 +225,7 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -264,8 +291,8 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -324,7 +351,7 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
@@ -346,7 +373,7 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
@@ -359,8 +386,8 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Returns an object with field data
*
- * @param string the table name
- * @return object
+ * @param string $table
+ * @return array
*/
public function field_data($table = '')
{
@@ -369,19 +396,24 @@ class CI_DB_mysqli_driver extends CI_DB {
return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
}
- $query = $this->query('DESCRIBE '.$this->protect_identifiers($table, TRUE, NULL, FALSE));
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
+ {
+ return FALSE;
+ }
$query = $query->result_object();
$retval = array();
for ($i = 0, $c = count($query); $i < $c; $i++)
{
- preg_match('/([a-z]+)(\(\d+\))?/', $query[$i]->Type, $matches);
-
$retval[$i] = new stdClass();
$retval[$i]->name = $query[$i]->Field;
- $retval[$i]->type = empty($matches[1]) ? NULL : $matches[1];
+
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
+
$retval[$i]->default = $query[$i]->Default;
- $retval[$i]->max_length = empty($matches[2]) ? NULL : preg_replace('/[^\d]/', '', $matches[2]);
$retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
}
@@ -400,6 +432,14 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
public function error()
{
+ if ( ! empty($this->conn_id->connect_errno))
+ {
+ return array(
+ 'code' => $this->conn_id->connect_errno,
+ 'message' => is_php('5.2.9') ? $this->conn_id->connect_error : mysqli_connect_error()
+ );
+ }
+
return array('code' => $this->conn_id->errno, 'message' => $this->conn_id->error);
}
@@ -410,12 +450,12 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* Generates a platform-specific batch update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -426,7 +466,7 @@ class CI_DB_mysqli_driver extends CI_DB {
{
if ($field !== $index)
{
- $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
}
}
}
@@ -439,11 +479,29 @@ class CI_DB_mysqli_driver extends CI_DB {
.'ELSE '.$k.' END, ';
}
- $where = ($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * FROM tables
+ *
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
+ *
+ * @return string
+ */
+ protected function _from_tables()
+ {
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
+ {
+ return '('.implode(', ', $this->qb_from).')';
+ }
- return 'UPDATE '.$table.' SET '.substr($cases, 0, -2)
- .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '')
- .$index.' IN('.implode(',', $ids).')';
+ return implode(', ', $this->qb_from);
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysqli/mysqli_forge.php b/system/database/drivers/mysqli/mysqli_forge.php
index b74c775b2..f29ea5ade 100644
--- a/system/database/drivers/mysqli/mysqli_forge.php
+++ b/system/database/drivers/mysqli/mysqli_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQLi Forge Class
@@ -34,165 +35,178 @@
*/
class CI_DB_mysqli_forge extends CI_DB_forge {
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';
/**
- * Process Fields
+ * CREATE TABLE keys flag
*
- * @param mixed the fields
- * @return string
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
*/
- protected function _process_fields($fields)
- {
- $current_field_count = 0;
- $sql = '';
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field);
-
- empty($attributes['NAME']) OR $sql .= ' '.$this->db->escape_identifiers($attributes['NAME']).' ';
-
- if ( ! empty($attributes['TYPE']))
- {
- $sql .= ' '.$attributes['TYPE'];
-
- if ( ! empty($attributes['CONSTRAINT']))
- {
- switch (strtolower($attributes['TYPE']))
- {
- case 'decimal':
- case 'float':
- case 'numeric':
- $sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
- break;
- case 'enum':
- case 'set':
- $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
- break;
- default:
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
- }
+ protected $_create_table_keys = TRUE;
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT',
+ 'SMALLINT',
+ 'MEDIUMINT',
+ 'INT',
+ 'INTEGER',
+ 'BIGINT',
+ 'REAL',
+ 'DOUBLE',
+ 'DOUBLE PRECISION',
+ 'FLOAT',
+ 'DECIMAL',
+ 'NUMERIC'
+ );
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ // --------------------------------------------------------------------
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
+ {
+ parent::__construct($db);
- return $sql;
+ $this->_create_table .= ' DEFAULT CHARSET '.$this->db->char_set.' COLLATE '.$this->db->dbcollat;
}
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param mixed the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields);
-
- if (count($primary_keys) > 0)
+ if ($alter_type === 'DROP')
{
- $key_name = $this->db->escape_identifiers(implode('_', $primary_keys));
- $sql .= ",\n\tPRIMARY KEY ".$key_name.' ('.implode(', ', $this->db->escape_identifiers($primary_keys)).')';
+ return parent::_alter_table($alter_type, $table, $field);
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
+ if ($field[$i]['_literal'] !== FALSE)
{
- if (is_array($key))
+ $field[$i] = ($alter_type === 'ADD')
+ ? "\n\tADD ".$field[$i]['_literal']
+ : "\n\tMODIFY ".$field[$i]['_literal'];
+ }
+ else
+ {
+ if ($alter_type === 'ADD')
{
- $key_name = $this->db->escape_identifiers(implode('_', $key));
- $key = $this->db->escape_identifiers($key);
+ $field[$i]['_literal'] = "\n\tADD ";
}
else
{
- $key_name = $this->db->escape_identifiers($key);
- $key = array($key_name);
+ $field[$i]['_literal'] = empty($field[$i]['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE ";
}
- $sql .= ",\n\tKEY ".$key_name.' ('.implode(', ', $key).')';
+ $field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]);
}
}
- return $sql."\n) DEFAULT CHARACTER SET ".$this->db->char_set.' COLLATE '.$this->db->dbcollat.';';
+ return array($sql.implode(',', $field));
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Process column
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ $extra_clause = isset($field['after'])
+ ? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';
+
+ if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)
+ {
+ $extra_clause = ' FIRST';
+ }
+
+ return $this->db->escape_identifiers($field['name'])
+ .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))
+ .' '.$field['type'].$field['length']
+ .$field['unsigned']
+ .$field['null']
+ .$field['default']
+ .$field['auto_increment']
+ .$field['unique']
+ .$extra_clause;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param array fields
- * @param string the field after which we should add the new field
+ * @param string $table (ignored)
* @return string
*/
- protected function _alter_table($alter_type, $table, $fields, $after_field = '')
+ protected function _process_indexes($table)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' ';
+ $sql = '';
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- return $sql.$this->db->escape_identifiers($fields);
+ if (is_array($this->keys[$i]))
+ {
+ for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i][$i2]]))
+ {
+ unset($this->keys[$i][$i2]);
+ continue;
+ }
+ }
+ }
+ elseif ( ! isset($this->fields[$this->keys[$i]]))
+ {
+ unset($this->keys[$i]);
+ continue;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
- return $sql.$this->_process_fields($fields)
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ $this->keys = array();
+
+ return $sql;
}
}
diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php
index c1ec4da76..ac0f1a8d1 100644
--- a/system/database/drivers/mysqli/mysqli_result.php
+++ b/system/database/drivers/mysqli/mysqli_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQLi Result Class
@@ -101,7 +102,7 @@ class CI_DB_mysqli_result extends CI_DB_result {
$retval[$i]->type = $field_data[$i]->type;
$retval[$i]->max_length = $field_data[$i]->max_length;
$retval[$i]->primary_key = (int) ($field_data[$i]->flags & 2);
- $retval[$i]->default = '';
+ $retval[$i]->default = $field_data[$i]->def;
}
return $retval;
@@ -130,11 +131,12 @@ class CI_DB_mysqli_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n
* @return bool
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return $this->result_id->data_seek($n);
}
@@ -160,7 +162,7 @@ class CI_DB_mysqli_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @param string
+ * @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
diff --git a/system/database/drivers/mysqli/mysqli_utility.php b/system/database/drivers/mysqli/mysqli_utility.php
index 5d2bdbce0..345691e84 100644
--- a/system/database/drivers/mysqli/mysqli_utility.php
+++ b/system/database/drivers/mysqli/mysqli_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQLi Utility Class
@@ -34,14 +35,33 @@
*/
class CI_DB_mysqli_utility extends CI_DB_utility {
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
protected $_list_databases = 'SHOW DATABASES';
+
+ /**
+ * OPTIMIZE TABLE statement
+ *
+ * @var string
+ */
protected $_optimize_table = 'OPTIMIZE TABLE %s';
+
+ /**
+ * REPAIR TABLE statement
+ *
+ * @var string
+ */
protected $_repair_table = 'REPAIR TABLE %s';
+ // --------------------------------------------------------------------
+
/**
- * MySQLi Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index 691247fee..706211a01 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* oci8 Database Adapter Class
@@ -49,36 +50,80 @@
*/
class CI_DB_oci8_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'oci8';
- // The character used for excaping
- protected $_escape_char = '"';
+ /**
+ * Statement ID
+ *
+ * @var resource
+ */
+ public $stmt_id;
+
+ /**
+ * Cursor ID
+ *
+ * @var resource
+ */
+ public $curs_id;
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
+ /**
+ * Commit mode flag
+ *
+ * @var int
+ */
+ public $commit_mode = OCI_COMMIT_ON_SUCCESS;
/**
- * The syntax to count rows is slightly different across different
- * database engines, so this string appears in each driver and is
- * used for the count_all() and count_all_results() functions.
+ * Limit used flag
+ *
+ * If we use LIMIT, we'll add a field that will
+ * throw off num_fields later.
+ *
+ * @var bool
*/
- protected $_count_string = 'SELECT COUNT(1) AS ';
- protected $_random_keyword = ' ASC'; // not currently supported
+ public $limit_used;
+
+ // --------------------------------------------------------------------
+ /**
+ * List of reserved identifiers
+ *
+ * Identifiers that must NOT be escaped.
+ *
+ * @var string[]
+ */
protected $_reserved_identifiers = array('*', 'rownum');
- // Set "auto commit" by default
- public $commit_mode = OCI_COMMIT_ON_SUCCESS;
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('ASC', 'ASC'); // not currently supported
- // need to track statement id and cursor id
- public $stmt_id;
- public $curs_id;
+ /**
+ * COUNT string
+ *
+ * @used-by CI_DB_driver::count_all()
+ * @used-by CI_DB_query_builder::count_all_results()
+ *
+ * @var string
+ */
+ protected $_count_string = 'SELECT COUNT(1) AS ';
- // if we use a limit, we will add a field that will
- // throw off num_fields later
- public $limit_used;
+ // --------------------------------------------------------------------
+ /**
+ * Class constructor
+ *
+ * @param array $params
+ * @return void
+ */
public function __construct($params)
{
parent::__construct($params);
@@ -195,9 +240,21 @@ class CI_DB_oci8_driver extends CI_DB {
*/
public function version()
{
- return isset($this->data_cache['version'])
- ? $this->data_cache['version']
- : $this->data_cache['version'] = oci_server_version($this->conn_id);
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+ elseif ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
+
+ if ( ! $this->conn_id OR ($version = oci_server_version($this->conn_id)) === FALSE)
+ {
+ return FALSE;
+ }
+
+ return $this->data_cache['version'] = $version;
}
// --------------------------------------------------------------------
@@ -205,7 +262,7 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
@@ -224,7 +281,7 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Generate a statement ID
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return void
*/
protected function _set_stmt_id($sql)
@@ -304,7 +361,7 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Bind parameters
*
- * @param array
+ * @param array $params
* @return void
*/
protected function _bind_params($params)
@@ -333,7 +390,7 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -406,8 +463,8 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -467,7 +524,7 @@ class CI_DB_oci8_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
@@ -490,27 +547,83 @@ class CI_DB_oci8_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
{
- return 'SELECT "COLUMN_NAME" FROM "all_tab_columns" WHERE "TABLE_NAME" = '.$this->escape($table);
+ if (strpos($table, '.') !== FALSE)
+ {
+ sscanf($table, '%[^.].%s', $owner, $table);
+ }
+ else
+ {
+ $owner = $this->username;
+ }
+
+ return 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS
+ WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
+ AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
}
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return 'SELECT * FROM '.$this->protect_identifiers($table).' WHERE rownum = 1';
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+ elseif (strpos($table, '.') !== FALSE)
+ {
+ sscanf($table, '%[^.].%s', $owner, $table);
+ }
+ else
+ {
+ $owner = $this->username;
+ }
+
+ $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHAR_LENGTH, DATA_PRECISION, DATA_LENGTH, DATA_DEFAULT, NULLABLE
+ FROM ALL_TAB_COLUMNS
+ WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
+ AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
+
+ $length = ($query[$i]->CHAR_LENGTH > 0)
+ ? $query[$i]->CHAR_LENGTH : $query[$i]->DATA_PRECISION;
+ if ($length === NULL)
+ {
+ $length = $query[$i]->DATA_LENGTH;
+ }
+ $retval[$i]->max_length = $length;
+
+ $default = $query[$i]->DATA_DEFAULT;
+ if ($default === NULL && $query[$i]->NULLABLE === 'N')
+ {
+ $default = '';
+ }
+ $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
@@ -547,29 +660,13 @@ class CI_DB_oci8_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Insert_batch statement
+ * Insert batch statement
*
* Generates a platform-specific insert string from the supplied data
*
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
* @return string
*/
protected function _insert_batch($table, $keys, $values)
@@ -592,10 +689,10 @@ class CI_DB_oci8_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
@@ -610,40 +707,35 @@ class CI_DB_oci8_driver extends CI_DB {
*
* Generates a platform-specific delete string from the supplied data
*
- * @param string the table name
- * @param array the where clause
- * @param array the like clause
- * @param string the limit clause
+ * @param string $table
* @return string
*/
- protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
- empty($limit) OR $conditions[] = 'rownum <= '.$limit;
+ if ($this->qb_limit)
+ {
+ $this->where('rownum <= ',$this->qb_limit, FALSE);
+ $this->qb_limit = FALSE;
+ }
- return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '');
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * LIMIT
*
* Generates a platform-specific LIMIT clause
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
+ * @param string $sql SQL Query
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _limit($sql)
{
$this->limit_used = TRUE;
- return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit + 1).')'
- .($offset ? ' WHERE rnum >= '.($offset + 1): '');
+ return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')'
+ .($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1): '');
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php
index 92e8c02ed..a0efa95ea 100644
--- a/system/database/drivers/oci8/oci8_forge.php
+++ b/system/database/drivers/oci8/oci8_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Oracle Forge Class
@@ -34,122 +35,96 @@
*/
class CI_DB_oci8_forge extends CI_DB_forge {
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
protected $_create_database = FALSE;
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
protected $_drop_database = FALSE;
- protected $_drop_table = 'DROP TABLE %s';
/**
- * Create Table
+ * DROP TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return string
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
+ protected $_drop_table_if = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
- if ($if_not_exists === TRUE)
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'DROP')
{
- $sql .= 'IF NOT EXISTS ';
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+ elseif ($alter_type === 'CHANGE')
+ {
+ $alter_type = 'MODIFY';
}
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
+ if ($field[$i]['_literal'] !== FALSE)
{
- $sql .= "\n\t".$attributes;
+ $field[$i] = "\n\t".$field[$i]['_literal'];
}
else
{
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- if (isset($attributes['UNSINGED']) && $attributes['UNSIGNED'] === TRUE)
+ $field[$i]['_literal'] = "\n\t".$this->_process_column($field[$i]);
+ if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name']))
{
- $sql .= ' UNSIGNED';
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' '.$this->db->escape_identifiers($field[$i]['new_name']);
}
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= (isset($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? '' : ' NOT NULL';
-
- empty($attributes['CONSTRAINT']) OR ' CONSTRAINT '.$attributes['CONSTRAINT'];
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
}
}
- if (count($primary_keys) > 0)
- {
- $sql .= ",\n\tCONSTRAINT ".$table.' PRIMARY KEY ('.implode(', ', $this->db->escape_identifiers($primary_keys)).')';
- }
+ $sql .= ' '.$alter_type.' ';
+ $sql .= (count($field) === 1)
+ ? $field[0]
+ : '('.implode(',', $field).')';
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- $sql .= ",\n\tUNIQUE COLUMNS (".implode(', ', $key).')';
- }
- }
-
- return $sql."\n)";
+ // RENAME COLUMN must be executed after MODIFY
+ array_unshift($sqls, $sql);
+ return $sql;
}
// --------------------------------------------------------------------
/**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Field attribute AUTO_INCREMENT
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
- {
- return $sql;
- }
-
- return $sql.' '.$column_definition
- .($default_value !== '' ? ' DEFAULT "'.$default_value.'"' : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
-
+ // Not supported - sequences and triggers must be used instead
}
}
diff --git a/system/database/drivers/oci8/oci8_result.php b/system/database/drivers/oci8/oci8_result.php
index a2b600e6c..84d46f82a 100644
--- a/system/database/drivers/oci8/oci8_result.php
+++ b/system/database/drivers/oci8/oci8_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* oci8 Result Class
@@ -37,15 +38,40 @@
*/
class CI_DB_oci8_result extends CI_DB_result {
+ /**
+ * Statement ID
+ *
+ * @var resource
+ */
public $stmt_id;
+
+ /**
+ * Cursor ID
+ *
+ * @var resource
+ */
public $curs_id;
+
+ /**
+ * Limit used flag
+ *
+ * @var bool
+ */
public $limit_used;
+
+ /**
+ * Commit mode flag
+ *
+ * @var int
+ */
public $commit_mode;
+ // --------------------------------------------------------------------
+
/**
- * Constructor
+ * Class constructor
*
- * @param object
+ * @param object &$driver_object
* @return void
*/
public function __construct(&$driver_object)
@@ -157,7 +183,7 @@ class CI_DB_oci8_result extends CI_DB_result {
protected function _fetch_assoc()
{
$id = ($this->curs_id) ? $this->curs_id : $this->stmt_id;
- return oci_fetch_assoc($id);
+ return @oci_fetch_assoc($id);
}
// --------------------------------------------------------------------
@@ -167,7 +193,7 @@ class CI_DB_oci8_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @param string
+ * @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
@@ -190,63 +216,6 @@ class CI_DB_oci8_result extends CI_DB_result {
return $class_name;
}
- // --------------------------------------------------------------------
-
- /**
- * Data Seek
- *
- * Moves the internal pointer to the desired offset. We call
- * this internally before fetching results to make sure the
- * result set starts at zero.
- *
- * Oracle's PHP extension doesn't have an easy way of doing this
- * and the only workaround is to (re)execute the statement or cursor
- * in order to go to the first (zero) index of the result set.
- * Then, we would need to "dummy" fetch ($n - 1) rows to get to the
- * right one.
- *
- * This is as ridiculous as it sounds and it's the reason why every
- * other method that is fetching data tries to use an already "cached"
- * result set. Keeping this just in case it becomes needed at
- * some point in the future, but it will only work for resetting the
- * pointer to zero.
- *
- * @return bool
- */
- protected function _data_seek()
- {
- /* The PHP manual says that if OCI_NO_AUTO_COMMIT mode
- * is used, and oci_rollback() and/or oci_commit() are
- * not subsequently called - this will cause an unnecessary
- * rollback to be triggered at the end of the script execution.
- *
- * Therefore we'll try to avoid using that mode flag
- * if we're not currently in the middle of a transaction.
- */
- if ($this->commit_mode !== OCI_COMMIT_ON_SUCCESS)
- {
- $result = @oci_execute($this->stmt_id, $this->commit_mode);
- }
- else
- {
- $result = @oci_execute($this->stmt_id);
- }
-
- if ($result && $this->curs_id)
- {
- if ($this->commit_mode !== OCI_COMMIT_ON_SUCCESS)
- {
- return @oci_execute($this->curs_id, $this->commit_mode);
- }
- else
- {
- return @oci_execute($this->curs_id);
- }
- }
-
- return $result;
- }
-
}
/* End of file oci8_result.php */
diff --git a/system/database/drivers/oci8/oci8_utility.php b/system/database/drivers/oci8/oci8_utility.php
index 0183eda26..d15537fdf 100644
--- a/system/database/drivers/oci8/oci8_utility.php
+++ b/system/database/drivers/oci8/oci8_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Oracle Utility Class
@@ -34,18 +35,23 @@
*/
class CI_DB_oci8_utility extends CI_DB_utility {
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
protected $_list_databases = 'SELECT username FROM dba_users'; // Schemas are actual usernames
/**
- * Oracle Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index 8f0a474b0..29b2281cc 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* ODBC Database Adapter Class
@@ -40,23 +41,57 @@
*/
class CI_DB_odbc_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'odbc';
- // the character used to excape - not necessary for ODBC
+ /**
+ * Database schema
+ *
+ * @var string
+ */
+ public $schema = 'public';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Identifier escape character
+ *
+ * Must be empty for ODBC.
+ *
+ * @var string
+ */
protected $_escape_char = '';
- // clause and character used for LIKE escape sequences
+ /**
+ * ESCAPE statement string
+ *
+ * @var string
+ */
protected $_like_escape_str = " {escape '%s'} ";
- protected $_like_escape_chr = '!';
- protected $_random_keyword;
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RND()', 'RND(%d)');
+
+ // --------------------------------------------------------------------
+ /**
+ * Class constructor
+ *
+ * @param array $params
+ * @return void
+ */
public function __construct($params)
{
parent::__construct($params);
- $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
-
// Legacy support for DSN in the hostname field
if (empty($this->dsn))
{
@@ -64,6 +99,8 @@ class CI_DB_odbc_driver extends CI_DB {
}
}
+ // --------------------------------------------------------------------
+
/**
* Non-persistent database connection
*
@@ -91,7 +128,7 @@ class CI_DB_odbc_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
@@ -104,6 +141,7 @@ class CI_DB_odbc_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -167,8 +205,8 @@ class CI_DB_odbc_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -217,7 +255,7 @@ class CI_DB_odbc_driver extends CI_DB {
*/
public function insert_id()
{
- return ($this->db->db_debug) ? $this->db->display_error('db_unsuported_feature') : FALSE;
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
}
// --------------------------------------------------------------------
@@ -227,17 +265,17 @@ class CI_DB_odbc_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = 'SHOW TABLES FROM '.$this->database;
+ $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = '".$this->schema."'";
if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
- return FALSE; // not currently supported
+ return $sql." AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
return $sql;
@@ -250,7 +288,7 @@ class CI_DB_odbc_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
@@ -265,7 +303,7 @@ class CI_DB_odbc_driver extends CI_DB {
*
* Generates a platform-specific query so that the column data can be retrieved
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _field_data($table)
@@ -291,17 +329,19 @@ class CI_DB_odbc_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
+ * Update statement
*
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
+ * Generates a platform-specific update string from the supplied data
*
- * @param array
+ * @param string $table
+ * @param array $values
* @return string
*/
- protected function _from_tables($tables)
+ protected function _update($table, $values)
{
- return is_array($tables) ? implode(', ', $tables) : $tables;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -311,10 +351,10 @@ class CI_DB_odbc_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
@@ -325,6 +365,22 @@ class CI_DB_odbc_driver extends CI_DB {
// --------------------------------------------------------------------
/**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Close DB Connection
*
* @return void
diff --git a/system/database/drivers/odbc/odbc_forge.php b/system/database/drivers/odbc/odbc_forge.php
index b074c5884..fb16ca5cf 100644
--- a/system/database/drivers/odbc/odbc_forge.php
+++ b/system/database/drivers/odbc/odbc_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* ODBC Forge Class
@@ -34,125 +35,39 @@
*/
class CI_DB_odbc_forge extends CI_DB_forge {
- protected $_drop_database = 'DROP DATABASE %s';
- protected $_drop_table = 'DROP TABLE %s';
-
/**
- * Create Table
+ * CREATE TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- empty($attributes['CONSTRAINT']) OR $sql .= '('.$attributes['CONSTRAINT'].')';
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
-
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ protected $_create_table_if = FALSE;
- if (count($primary_keys) > 0)
- {
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->escape_identifiers($primary_keys)).')';
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')';
- }
- }
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = FALSE;
- return $sql."\n)";
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute AUTO_INCREMENT
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
- *
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
- {
- return $sql;
- }
-
- return $sql.' '.$column_definition
- .($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field != '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ // Not supported (in most databases at least)
}
}
diff --git a/system/database/drivers/odbc/odbc_result.php b/system/database/drivers/odbc/odbc_result.php
index 48dc48dd9..2c50c255b 100644
--- a/system/database/drivers/odbc/odbc_result.php
+++ b/system/database/drivers/odbc/odbc_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* ODBC Result Class
@@ -165,7 +166,7 @@ class CI_DB_odbc_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @param string
+ * @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
@@ -198,11 +199,11 @@ if ( ! function_exists('odbc_fetch_array'))
* Emulates the native odbc_fetch_array() function when
* it is not available (odbc_fetch_array() requires unixODBC)
*
- * @param resource
- * @param int
+ * @param resource &$result
+ * @param int $rownumber
* @return array
*/
- function odbc_fetch_array(& $result, $rownumber = 1)
+ function odbc_fetch_array(&$result, $rownumber = 1)
{
$rs = array();
if ( ! odbc_fetch_into($result, $rs, $rownumber))
@@ -231,11 +232,11 @@ if ( ! function_exists('odbc_fetch_object'))
* Emulates the native odbc_fetch_object() function when
* it is not available.
*
- * @param resource
- * @param int
+ * @param resource &$result
+ * @param int $rownumber
* @return object
*/
- function odbc_fetch_object(& $result, $rownumber = 1)
+ function odbc_fetch_object(&$result, $rownumber = 1)
{
$rs = array();
if ( ! odbc_fetch_into($result, $rs, $rownumber))
diff --git a/system/database/drivers/odbc/odbc_utility.php b/system/database/drivers/odbc/odbc_utility.php
index 224d48d2b..908674a9d 100644
--- a/system/database/drivers/odbc/odbc_utility.php
+++ b/system/database/drivers/odbc/odbc_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* ODBC Utility Class
@@ -34,18 +35,16 @@
*/
class CI_DB_odbc_utility extends CI_DB_utility {
- protected $_list_databases = FALSE;
-
/**
- * ODBC Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index 38a9fec80..d2dfa8bf0 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 2.1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Database Adapter Class
@@ -40,21 +41,37 @@
*/
class CI_DB_pdo_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'pdo';
- // the character used to excape - not necessary for PDO
- protected $_escape_char = '';
-
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
-
- protected $_random_keyword;
+ /**
+ * Transaction enabled flag
+ *
+ * @var bool
+ */
+ public $trans_enabled = FALSE;
- // need to track the pdo driver and options
- public $pdodriver;
+ /**
+ * PDO Options
+ *
+ * @var array
+ */
public $options = array();
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Validates the DSN string and/or detects the subdriver.
+ *
+ * @param array $params
+ * @return void
+ */
public function __construct($params)
{
parent::__construct($params);
@@ -63,172 +80,54 @@ class CI_DB_pdo_driver extends CI_DB {
{
// If there is a minimum valid dsn string pattern found, we're done
// This is for general PDO users, who tend to have a full DSN string.
- $this->pdodriver = end($match);
+ $this->subdriver = $match[1];
+ return;
}
- else
+ // Legacy support for DSN specified in the hostname field
+ elseif (preg_match('/([^;]+):/', $this->hostname, $match) && count($match) === 2)
{
- // Try to build a complete DSN string from params
- $this->_connect_string($params);
+ $this->dsn = $this->hostname;
+ $this->hostname = NULL;
+ $this->subdriver = $match[1];
+ return;
}
-
- // clause and character used for LIKE escape sequences
- // this one depends on the driver being used
- if ($this->pdodriver === 'mysql')
+ elseif (in_array($this->subdriver, array('mssql', 'sybase'), TRUE))
{
- $this->_escape_char = '`';
- $this->_like_escape_str = '';
- $this->_like_escape_chr = '\\';
+ $this->subdriver = 'dblib';
}
- elseif ($this->pdodriver === 'odbc')
+ elseif ($this->subdriver === '4D')
{
- $this->_like_escape_str = " {escape '%s'} ";
+ $this->subdriver = '4d';
}
- elseif ( ! in_array($this->pdodriver, array('sqlsrv', 'mssql', 'dblib', 'sybase')))
+ elseif ( ! in_array($this->subdriver, array('4d', 'cubrid', 'dblib', 'firebird', 'ibm', 'informix', 'mysql', 'oci', 'odbc', 'sqlite', 'sqlsrv'), TRUE))
{
- $this->_escape_char = '"';
- }
-
- $this->trans_enabled = FALSE;
- $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
- }
+ log_message('error', 'PDO: Invalid or non-existent subdriver');
- /**
- * Connection String
- *
- * @param array
- * @return void
- */
- protected function _connect_string($params)
- {
- if (strpos($this->hostname, ':'))
- {
- // hostname generally would have this prototype
- // $db['hostname'] = 'pdodriver:host(/Server(/DSN))=hostname(/DSN);';
- // We need to get the prefix (pdodriver used by PDO).
- $dsnarray = explode(':', $this->hostname);
- $this->pdodriver = $dsnarray[0];
-
- // End dsn with a semicolon for extra backward compability
- // if database property was not empty.
- if ( ! empty($this->database))
+ if ($this->db_debug)
{
- $this->dsn .= rtrim($this->hostname, ';').';';
+ show_error('Invalid or non-existent PDO subdriver');
}
}
- else
- {
- // Invalid DSN, display an error
- if ( ! array_key_exists('pdodriver', $params))
- {
- show_error('Invalid DB Connection String for PDO');
- }
- // Assuming that the following DSN string format is used:
- // $dsn = 'pdo://username:password@hostname:port/database?pdodriver=pgsql';
- $this->dsn = $this->pdodriver.':';
-
- // Add hostname to the DSN for databases that need it
- if ( ! empty($this->hostname)
- && strpos($this->hostname, ':') === FALSE
- && in_array($this->pdodriver, array('informix', 'mysql', 'pgsql', 'sybase', 'mssql', 'dblib', 'cubrid')))
- {
- $this->dsn .= 'host='.$this->hostname.';';
- }
-
- // Add a port to the DSN for databases that can use it
- if ( ! empty($this->port) && in_array($this->pdodriver, array('informix', 'mysql', 'pgsql', 'ibm', 'cubrid')))
- {
- $this->dsn .= 'port='.$this->port.';';
- }
- }
-
- // Add the database name to the DSN, if needed
- if (stripos($this->dsn, 'dbname') === FALSE
- && in_array($this->pdodriver, array('4D', 'pgsql', 'mysql', 'firebird', 'sybase', 'mssql', 'dblib', 'cubrid')))
- {
- $this->dsn .= 'dbname='.$this->database.';';
- }
- elseif (stripos($this->dsn, 'database') === FALSE && in_array($this->pdodriver, array('ibm', 'sqlsrv')))
- {
- if (stripos($this->dsn, 'dsn') === FALSE)
- {
- $this->dsn .= 'database='.$this->database.';';
- }
- }
- elseif ($this->pdodriver === 'sqlite' && $this->dsn === 'sqlite:')
- {
- if ($this->database !== ':memory')
- {
- if ( ! file_exists($this->database))
- {
- show_error('Invalid DB Connection string for PDO SQLite');
- }
-
- $this->dsn .= (strpos($this->database, DIRECTORY_SEPARATOR) !== 0) ? DIRECTORY_SEPARATOR : '';
- }
-
- $this->dsn .= $this->database;
- }
-
- // Add charset to the DSN, if needed
- if ( ! empty($this->char_set) && in_array($this->pdodriver, array('4D', 'mysql', 'sybase', 'mssql', 'dblib', 'oci')))
- {
- $this->dsn .= 'charset='.$this->char_set.';';
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Non-persistent database connection
- *
- * @return object
- */
- public function db_connect()
- {
- return $this->_pdo_connect();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Persistent database connection
- *
- * @return object
- */
- public function db_pconnect()
- {
- return $this->_pdo_connect(TRUE);
+ $this->dsn = NULL;
}
// --------------------------------------------------------------------
/**
- * PDO connection
+ * Database connection
*
- * @param bool
+ * @param bool $persistent
* @return object
*/
- protected function _pdo_connect($persistent = FALSE)
+ public function db_connect($persistent = FALSE)
{
- $this->options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_SILENT;
- $persistent === FALSE OR $this->options[PDO::ATTR_PERSISTENT] = TRUE;
-
- /* Prior to PHP 5.3.6, even if the charset was supplied in the DSN
- * on connect - it was ignored. This is a work-around for the issue.
- *
- * Reference: http://www.php.net/manual/en/ref.pdo-mysql.connection.php
- */
- if ($this->pdodriver === 'mysql' && ! is_php('5.3.6') && ! empty($this->char_set))
- {
- $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES '.$this->char_set
- .( ! empty($this->db_collat) ? " COLLATE '".$this->dbcollat."'" : '');
- }
+ $this->options[PDO::ATTR_PERSISTENT] = $persistent;
// Connecting...
try
{
- return new PDO($this->dsn, $this->username, $this->password, $this->options);
+ return @new PDO($this->dsn, $this->username, $this->password, $this->options);
}
catch (PDOException $e)
{
@@ -244,6 +143,18 @@ class CI_DB_pdo_driver extends CI_DB {
// --------------------------------------------------------------------
/**
+ * Persistent database connection
+ *
+ * @return object
+ */
+ public function db_pconnect()
+ {
+ return $this->db_connect(TRUE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Database version number
*
* @return string
@@ -254,6 +165,10 @@ class CI_DB_pdo_driver extends CI_DB {
{
return $this->data_cache['version'];
}
+ elseif ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
// Not all subdrivers support the getAttribute() method
try
@@ -271,7 +186,7 @@ class CI_DB_pdo_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql SQL query
* @return mixed
*/
protected function _execute($sql)
@@ -284,6 +199,7 @@ class CI_DB_pdo_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -343,8 +259,8 @@ class CI_DB_pdo_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -363,7 +279,7 @@ class CI_DB_pdo_driver extends CI_DB {
$str = $this->conn_id->quote($str);
// If there are duplicated quotes, trim them away
- if (strpos($str, "'") === 0)
+ if ($str[0] === "'")
{
$str = substr($str, 1, -1);
}
@@ -396,100 +312,27 @@ class CI_DB_pdo_driver extends CI_DB {
/**
* Insert ID
*
- * @param string
+ * @param string $name
* @return int
*/
public function insert_id($name = NULL)
{
- if ($this->pdodriver === 'pgsql' && $name === NULL && $this->version() >= '8.1')
- {
- $query = $this->query('SELECT LASTVAL() AS ins_id');
- $query = $query->row();
- return $query->ins_id;
- }
-
return $this->conn_id->lastInsertId($name);
}
// --------------------------------------------------------------------
/**
- * Show table query
- *
- * Generates a platform-specific query string so that the table names can be fetched
- *
- * @param bool
- * @return string
- */
- protected function _list_tables($prefix_limit = FALSE)
- {
- if ($this->pdodriver === 'pgsql')
- {
- // Analog function to show all tables in postgre
- $sql = "SELECT * FROM information_schema.tables WHERE table_schema = 'public'";
- }
- elseif ($this->pdodriver === 'sqlite')
- {
- // Analog function to show all tables in sqlite
- $sql = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'";
- }
- else
- {
- $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
- }
-
- if ($prefix_limit !== FALSE AND $this->dbprefix !== '')
- {
- return FALSE;
- }
-
- return $sql;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Show column query
- *
- * Generates a platform-specific query string so that the column names can be fetched
- *
- * @param string the table name
- * @return string
- */
- protected function _list_columns($table = '')
- {
- return 'SHOW COLUMNS FROM '.$this->escape_identifiers($table);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Field data query
*
* Generates a platform-specific query so that the column data can be retrieved
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _field_data($table)
{
- if ($this->pdodriver === 'mysql' or $this->pdodriver === 'pgsql')
- {
- // Analog function for mysql and postgre
- return 'SELECT * FROM '.$this->escape_identifiers($table).' LIMIT 1';
- }
- elseif ($this->pdodriver === 'oci')
- {
- // Analog function for oci
- return 'SELECT * FROM '.$this->escape_identifiers($table).' WHERE ROWNUM <= 1';
- }
- elseif ($this->pdodriver === 'sqlite')
- {
- // Analog function for sqlite
- return 'PRAGMA table_info('.$this->escape_identifiers($table).')';
- }
-
- return 'SELECT TOP 1 FROM '.$this->escape_identifiers($table);
+ return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table);
}
// --------------------------------------------------------------------
@@ -528,16 +371,14 @@ class CI_DB_pdo_driver extends CI_DB {
*
* Generates a platform-specific batch update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
- $ids = array();
- $where = ($where !== '' && count($where) >=1) ? implode(" ", $where).' AND ' : '';
-
+ $ids = array();
foreach ($values as $key => $val)
{
$ids[] = $val[$index];
@@ -546,14 +387,12 @@ class CI_DB_pdo_driver extends CI_DB {
{
if ($field !== $index)
{
- $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
}
}
}
- $sql = 'UPDATE '.$table.' SET ';
$cases = '';
-
foreach ($final as $k => $v)
{
$cases .= $k.' = CASE '."\n";
@@ -566,10 +405,9 @@ class CI_DB_pdo_driver extends CI_DB {
$cases .= 'ELSE '.$k.' END, ';
}
- $sql .= substr($cases, 0, -2);
- $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
- return $sql;
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
@@ -579,37 +417,15 @@ class CI_DB_pdo_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
{
- return 'DELETE FROM '.$table;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Limit string
- *
- * Generates a platform-specific LIMIT clause
- *
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
- * @return string
- */
- protected function _limit($sql, $limit, $offset)
- {
- if ($this->pdodriver === 'pgsql')
- {
- return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : '');
- }
-
- return $sql.' LIMIT '.($offset ? $offset.', ' : '').$limit;
+ return 'TRUNCATE TABLE '.$table;
}
}
diff --git a/system/database/drivers/pdo/pdo_forge.php b/system/database/drivers/pdo/pdo_forge.php
index 02ceb74fe..130d3667e 100644
--- a/system/database/drivers/pdo/pdo_forge.php
+++ b/system/database/drivers/pdo/pdo_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 2.1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Forge Class
@@ -34,134 +35,19 @@
*/
class CI_DB_pdo_forge extends CI_DB_forge {
- protected $_drop_database = 'DROP DATABASE %s';
- protected $_drop_table = 'DROP TABLE %s';
-
/**
- * Create Table
+ * CREATE TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
- $numeric = array('SERIAL', 'INTEGER');
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- if ( ! empty($attributes['CONSTRAINT']))
- {
- // Exception for Postgre numeric which not too happy with constraint within those type
- if ( ! ($this->db->pdodriver === 'pgsql' && in_array($attributes['TYPE'], $numeric)))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
-
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
-
- if (count($primary_keys) > 0)
- {
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')';
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')';
- }
- }
-
- return $sql."\n)";
- }
-
- // --------------------------------------------------------------------
+ protected $_create_table_if = FALSE;
/**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * DROP TABLE IF statement
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @var string
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
- {
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
- {
- return $sql;
- }
-
- return $sql .' '.$column_definition
- .($default_value !== '' ? " DEFAULT '".$default_value."'" : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
- }
+ protected $_drop_table_if = FALSE;
}
diff --git a/system/database/drivers/pdo/pdo_result.php b/system/database/drivers/pdo/pdo_result.php
index 444406986..25cf87be8 100644
--- a/system/database/drivers/pdo/pdo_result.php
+++ b/system/database/drivers/pdo/pdo_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Result Class
@@ -108,61 +109,28 @@ class CI_DB_pdo_result extends CI_DB_result {
*/
public function field_data()
{
- $data = array();
-
try
{
- if (strpos($this->result_id->queryString, 'PRAGMA') !== FALSE)
- {
- foreach ($this->result_array() as $field)
- {
- preg_match('/([a-zA-Z]+)(\(\d+\))?/', $field['type'], $matches);
-
- $F = new stdClass();
- $F->name = $field['name'];
- $F->type = ( ! empty($matches[1])) ? $matches[1] : NULL;
- $F->default = NULL;
- $F->max_length = ( ! empty($matches[2])) ? preg_replace('/[^\d]/', '', $matches[2]) : NULL;
- $F->primary_key = (int) $field['pk'];
- $F->pdo_type = NULL;
-
- $data[] = $F;
- }
- }
- else
+ $retval = array();
+
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
- for($i = 0, $max = $this->num_fields(); $i < $max; $i++)
- {
- $field = $this->result_id->getColumnMeta($i);
-
- $F = new stdClass();
- $F->name = $field['name'];
- $F->type = $field['native_type'];
- $F->default = NULL;
- $F->pdo_type = $field['pdo_type'];
-
- if ($field['precision'] < 0)
- {
- $F->max_length = NULL;
- $F->primary_key = 0;
- }
- else
- {
- $F->max_length = ($field['len'] > 255) ? 0 : $field['len'];
- $F->primary_key = (int) ( ! empty($field['flags']) && in_array('primary_key', $field['flags']));
- }
-
- $data[] = $F;
- }
+ $field = $this->result_id->getColumnMeta($i);
+
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $field['name'];
+ $retval[$i]->type = $field['native_type'];
+ $retval[$i]->max_length = ($field['len'] > 0) ? $field['len'] : NULL;
+ $retval[$i]->primary_key = (int) ( ! empty($field['flags']) && in_array('primary_key', $field['flags'], TRUE));
}
- return $data;
+ return $retval;
}
catch (Exception $e)
{
if ($this->db->db_debug)
{
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
return FALSE;
@@ -205,7 +173,7 @@ class CI_DB_pdo_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @param string
+ * @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
diff --git a/system/database/drivers/pdo/pdo_utility.php b/system/database/drivers/pdo/pdo_utility.php
index 930842118..86f2b120a 100644
--- a/system/database/drivers/pdo/pdo_utility.php
+++ b/system/database/drivers/pdo/pdo_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 2.1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Utility Class
@@ -34,18 +35,16 @@
*/
class CI_DB_pdo_utility extends CI_DB_utility {
- protected $_list_databases = FALSE;
-
/**
- * PDO Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/pdo/subdrivers/index.html b/system/database/drivers/pdo/subdrivers/index.html
new file mode 100644
index 000000000..c942a79ce
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/index.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+ <title>403 Forbidden</title>
+</head>
+<body>
+
+<p>Directory access is forbidden.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
new file mode 100644
index 000000000..6ebd92a9b
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
@@ -0,0 +1,192 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO 4D Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_4d_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = '4d';
+
+ /**
+ * Identifier escape character
+ *
+ * @var string[]
+ */
+ protected $_escape_char = array('[', ']');
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = '4D:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ';port='.$this->port;
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ }
+ elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 3) === FALSE)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT '.$this->escape_identifiers('TABLE_NAME').' FROM '.$this->escape_identifiers('_USER_TABLES');
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' WHERE '.$this->escape_identifiers('TABLE_NAME')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT '.$this->escape_identifiers('COLUMN_NAME').' FROM '.$this->escape_identifiers('_USER_COLUMNS')
+ .' WHERE '.$this->escape_identifiers('TABLE_NAME').' = '.$this->escape($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data query
+ *
+ * Generates a platform-specific query so that the column data can be retrieved
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _field_data($table)
+ {
+ return 'SELECT * FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE).' LIMIT 1';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');
+ }
+
+}
+
+/* End of file pdo_4d_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_4d_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php b/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php
new file mode 100644
index 000000000..231ad53a4
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php
@@ -0,0 +1,209 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO 4D Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_4d_forge extends CI_DB_4d_forge {
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
+ protected $_create_database = 'CREATE SCHEMA %s';
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
+ protected $_drop_database = 'DROP SCHEMA %s';
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * RENAME TABLE statement
+ *
+ * @var string
+ */
+ protected $_rename_table = FALSE;
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'INT16' => 'INT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'INT64',
+ 'INT32' => 'INT64'
+ );
+
+ /**
+ * DEFAULT value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_default = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
+ {
+ return parent::_alter_table($alter_table, $table, $field);
+ }
+
+ // No method of modifying columns is supported
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type'].$field['length']
+ .$field['null']
+ .$field['unique']
+ .$field['auto_increment'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ case 'BIGINT':
+ $attribites['TYPE'] = 'INT64';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute UNIQUE
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_unique(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ {
+ $field['unique'] = ' UNIQUE';
+
+ // UNIQUE must be used with NOT NULL
+ $field['null'] = ' NOT NULL';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
+ {
+ if (stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' AUTO_INCREMENT';
+ }
+ elseif (strcasecmp($field['type'], 'UUID') === 0)
+ {
+ $field['auto_increment'] = ' AUTO_GENERATE';
+ }
+ }
+ }
+
+}
+
+/* End of file pdo_4d_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_4d_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
new file mode 100644
index 000000000..7e703e7b5
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
@@ -0,0 +1,247 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO CUBRID Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'cubrid';
+
+ /**
+ * Identifier escape character
+ *
+ * @var string
+ */
+ protected $_escape_char = '`';
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RANDOM()', 'RANDOM(%d)');
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'cubrid:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ';port='.$this->port;
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SHOW TABLES';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->Field;
+
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
+
+ $retval[$i]->default = $query[$i]->Default;
+ $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update_Batch statement
+ *
+ * Generates a platform-specific batch update string from the supplied data
+ *
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
+ * @return string
+ */
+ protected function _update_batch($table, $values, $index)
+ {
+ $ids = array();
+ foreach ($values as $key => $val)
+ {
+ $ids[] = $val[$index];
+
+ foreach (array_keys($val) as $field)
+ {
+ if ($field !== $index)
+ {
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ }
+ }
+ }
+
+ $cases = '';
+ foreach ($final as $k => $v)
+ {
+ $cases .= $k." = CASE \n"
+ .implode("\n", $v)."\n"
+ .'ELSE '.$k.' END), ';
+ }
+
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ *
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'TRUNCATE '.$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * FROM tables
+ *
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
+ *
+ * @return string
+ */
+ protected function _from_tables()
+ {
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
+ {
+ return '('.implode(', ', $this->qb_from).')';
+ }
+
+ return implode(', ', $this->qb_from);
+ }
+
+}
+
+/* End of file pdo_cubrid_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php
new file mode 100644
index 000000000..ebf4b15d6
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php
@@ -0,0 +1,219 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO CUBRID Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_cubrid_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
+ protected $_create_database = FALSE;
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
+ protected $_drop_database = FALSE;
+
+ /**
+ * CREATE TABLE keys flag
+ *
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
+ */
+ protected $_create_table_keys = TRUE;
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SHORT' => 'INTEGER',
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'BIGINT' => 'NUMERIC',
+ 'FLOAT' => 'DOUBLE',
+ 'REAL' => 'DOUBLE'
+ );
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ $sqls[] = $sql.' CHANGE '.$field[$i]['_literal'];
+ }
+ else
+ {
+ $alter_type = empty($field[$i]['new_name']) ? ' MODIFY ' : ' CHANGE ';
+ $sqls[] = $sql.$alter_type.$this->_process_column($field[$i]);
+ }
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ $extra_clause = isset($field['after'])
+ ? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';
+
+ if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)
+ {
+ $extra_clause = ' FIRST';
+ }
+
+ return $this->db->escape_identifiers($field['name'])
+ .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))
+ .' '.$field['type'].$field['length']
+ .$field['unsigned']
+ .$field['null']
+ .$field['default']
+ .$field['auto_increment']
+ .$field['unique']
+ .$extra_clause;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
+ *
+ * @param string $table (ignored)
+ * @return string
+ */
+ protected function _process_indexes($table)
+ {
+ $sql = '';
+
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
+ {
+ if (is_array($this->keys[$i]))
+ {
+ for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i][$i2]]))
+ {
+ unset($this->keys[$i][$i2]);
+ continue;
+ }
+ }
+ }
+ elseif ( ! isset($this->fields[$this->keys[$i]]))
+ {
+ unset($this->keys[$i]);
+ continue;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
+ }
+
+ $this->keys = array();
+
+ return $sql;
+ }
+
+}
+
+/* End of file pdo_cubrid_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
new file mode 100644
index 000000000..cf049b61d
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
@@ -0,0 +1,329 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO DBLIB Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'dblib';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('NEWID()', 'RAND(%d)');
+
+ /**
+ * Quoted identifier flag
+ *
+ * Whether to use SQL-92 standard quoted identifier
+ * (double quotes) or brackets for identifier escaping.
+ *
+ * @var bool
+ */
+ protected $_quoted_identifier;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = $params['subdriver'].':host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ if ( ! empty($this->port))
+ {
+ $this->dsn .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port;
+ }
+
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ empty($this->appname) OR $this->dsn .= ';appname='.$this->appname;
+ }
+ else
+ {
+ if ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 6) === FALSE)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+
+ $this->subdriver = 'dblib';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database connection
+ *
+ * @param bool $persistent
+ * @return object
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ $this->conn_id = parent::db_connect($persistent);
+
+ if ( ! is_object($this->conn_id))
+ {
+ return $this->conn_id;
+ }
+
+ // Determine how identifiers are escaped
+ $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
+ $query = $query->row_array();
+ $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
+ $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
+
+ return $this->conn_id;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ return 'SELECT '.$this->escape_identifiers('name')
+ .' FROM '.$this->escape_identifiers('sysobjects')
+ .' WHERE '.$this->escape_identifiers('type')." = 'U'";
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql.' ORDER BY '.$this->escape_identifiers('name');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT COLUMN_NAME
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
+ $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;
+ $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ if ($this->qb_limit)
+ {
+ return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';
+ }
+
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ $limit = $this->qb_offset + $this->qb_limit;
+
+ // As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported,
+ // however an ORDER BY clause is required for it to work
+ if (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby))
+ {
+ $orderby = $this->_compile_order_by();
+
+ // We have to strip the ORDER BY clause
+ $sql = trim(substr($sql, 0, strrpos($sql, $orderby)));
+
+ // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results
+ if (count($this->qb_select) === 0)
+ {
+ $select = '*'; // Inevitable
+ }
+ else
+ {
+ // Use only field names and their aliases, everything else is out of our scope.
+ $select = array();
+ $field_regexp = ($this->_quoted_identifier)
+ ? '("[^\"]+")' : '(\[[^\]]+\])';
+ for ($i = 0, $c = count($this->qb_select); $i < $c; $i++)
+ {
+ $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)
+ ? $m[1] : $this->qb_select[$i];
+ }
+ $select = implode(', ', $select);
+ }
+
+ return 'SELECT '.$select." FROM (\n\n"
+ .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)
+ ."\n\n) ".$this->escape_identifiers('CI_subquery')
+ ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
+ }
+
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert batch statement
+ *
+ * Generates a platform-specific insert string from the supplied data.
+ *
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string|bool
+ */
+ protected function _insert_batch($table, $keys, $values)
+ {
+ // Multiple-value inserts are only supported as of SQL Server 2008
+ if (version_compare($this->version(), '10', '>='))
+ {
+ return parent::_insert_batch($table, $keys, $values);
+ }
+
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
+ }
+
+}
+
+/* End of file pdo_dblib_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php
new file mode 100644
index 000000000..236e1cce2
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO DBLIB Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_dblib_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ $sqls[] = $sql.$this->_process_column($field[$i]);
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' IDENTITY(1,1)';
+ }
+ }
+
+}
+
+/* End of file pdo_dblib_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
new file mode 100644
index 000000000..adac03880
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
@@ -0,0 +1,260 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Firebird Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'firebird';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RAND()', 'RAND()');
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'firebird:';
+
+ if ( ! empty($this->database))
+ {
+ $this->dsn .= 'dbname='.$this->database;
+ }
+ elseif ( ! empty($this->hostname))
+ {
+ $this->dsn .= 'dbname='.$this->hostname;
+ }
+
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ empty($this->role) OR $this->dsn .= ';role='.$this->role;
+ }
+ elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 9) === FALSE)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT "RDB$RELATION_NAME" FROM "RDB$RELATIONS" WHERE "RDB$RELATION_NAME" NOT LIKE \'RDB$%\' AND "RDB$RELATION_NAME" NOT LIKE \'MON$%\'';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql.' AND "RDB$RELATION_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT "RDB$FIELD_NAME" FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = '.$this->escape($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT "rfields"."RDB$FIELD_NAME" AS "name",
+ CASE "fields"."RDB$FIELD_TYPE"
+ WHEN 7 THEN \'SMALLINT\'
+ WHEN 8 THEN \'INTEGER\'
+ WHEN 9 THEN \'QUAD\'
+ WHEN 10 THEN \'FLOAT\'
+ WHEN 11 THEN \'DFLOAT\'
+ WHEN 12 THEN \'DATE\'
+ WHEN 13 THEN \'TIME\'
+ WHEN 14 THEN \'CHAR\'
+ WHEN 16 THEN \'INT64\'
+ WHEN 27 THEN \'DOUBLE\'
+ WHEN 35 THEN \'TIMESTAMP\'
+ WHEN 37 THEN \'VARCHAR\'
+ WHEN 40 THEN \'CSTRING\'
+ WHEN 261 THEN \'BLOB\'
+ ELSE NULL
+ END AS "type",
+ "fields"."RDB$FIELD_LENGTH" AS "max_length",
+ "rfields"."RDB$DEFAULT_VALUE" AS "default"
+ FROM "RDB$RELATION_FIELDS" "rfields"
+ JOIN "RDB$FIELDS" "fields" ON "rfields"."RDB$FIELD_SOURCE" = "fields"."RDB$FIELD_NAME"
+ WHERE "rfields"."RDB$RELATION_NAME" = '.$this->escape($table).'
+ ORDER BY "rfields"."RDB$FIELD_POSITION"';
+
+ return (($query = $this->query($sql)) !== FALSE)
+ ? $query->result_object()
+ : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ *
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'DELETE FROM '.$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ // Limit clause depends on if Interbase or Firebird
+ if (stripos($this->version(), 'firebird') !== FALSE)
+ {
+ $select = 'FIRST '.$this->qb_limit
+ .($this->qb_offset > 0 ? ' SKIP '.$this->qb_offset : '');
+ }
+ else
+ {
+ $select = 'ROWS '
+ .($this->qb_offset > 0 ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit);
+ }
+
+ return preg_replace('`SELECT`i', 'SELECT '.$select, $sql);
+ }
+
+}
+
+/* End of file pdo_firebird_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php
new file mode 100644
index 000000000..7b86de97f
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php
@@ -0,0 +1,229 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Firebird Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_firebird_forge extends CI_DB_pdo_forge {
+
+ /**
+ * RENAME TABLE statement
+ *
+ * @var string
+ */
+ protected $_rename_table = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SMALLINT' => 'INTEGER',
+ 'INTEGER' => 'INT64',
+ 'FLOAT' => 'DOUBLE PRECISION'
+ );
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create database
+ *
+ * @param string $db_name
+ * @return string
+ */
+ public function create_database($db_name)
+ {
+ // Firebird databases are flat files, so a path is required
+
+ // Hostname is needed for remote access
+ empty($this->db->hostname) OR $db_name = $this->hostname.':'.$db_name;
+
+ return parent::create_database('"'.$db_name.'"');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Drop database
+ *
+ * @param string $db_name (ignored)
+ * @return bool
+ */
+ public function drop_database($db_name = '')
+ {
+ if ( ! ibase_drop_db($this->conn_id))
+ {
+ return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;
+ }
+ elseif ( ! empty($this->db->data_cache['db_names']))
+ {
+ $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
+ if ($key !== FALSE)
+ {
+ unset($this->db->data_cache['db_names'][$key]);
+ }
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ return FALSE;
+ }
+
+ if (isset($field[$i]['type']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TYPE '.$field[$i]['type'].$field[$i]['length'];
+ }
+
+ if ( ! empty($field[$i]['default']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' SET DEFAULT '.$field[$i]['default'];
+ }
+
+ if (isset($field[$i]['null']))
+ {
+ $sqls[] = 'UPDATE "RDB$RELATION_FIELDS" SET "RDB$NULL_FLAG" = '
+ .($field[$i]['null'] === TRUE ? 'NULL' : '1')
+ .' WHERE "RDB$FIELD_NAME" = '.$this->db->escape($field[$i]['name'])
+ .' AND "RDB$RELATION_NAME" = '.$this->db->escape($table);
+ }
+
+ if ( ! empty($field[$i]['new_name']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
+ }
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type'].$field['length']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INT':
+ $attributes['TYPE'] = 'INTEGER';
+ return;
+ case 'BIGINT':
+ $attributes['TYPE'] = 'INT64';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported
+ }
+
+}
+
+/* End of file pdo_firebird_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
new file mode 100644
index 000000000..2ef97cd6e
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
@@ -0,0 +1,236 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO IBM DB2 Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_ibm_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'ibm';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'ibm:';
+
+ // Pre-defined DSN
+ if (empty($this->hostname) && empty($this->HOSTNAME) && empty($this->port) && empty($this->PORT))
+ {
+ if (isset($this->DSN))
+ {
+ $this->dsn .= 'DSN='.$this->DSN;
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DSN='.$this->database;
+ }
+
+ return;
+ }
+
+ $this->dsn .= 'DRIVER='.(isset($this->DRIVER) ? '{'.$this->DRIVER.'}' : '{IBM DB2 ODBC DRIVER}').';';
+
+ if (isset($this->DATABASE))
+ {
+ $this->dsn .= 'DATABASE='.$this->DATABASE.';';
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DATABASE='.$this->database.';';
+ }
+
+ if (isset($this->HOSTNAME))
+ {
+ $this->dsn .= 'HOSTNAME='.$this->HOSTNAME.';';
+ }
+ else
+ {
+ $this->dsn .= 'HOSTNAME='.(empty($this->hostname) ? '127.0.0.1;' : $this->hostname.';');
+ }
+
+ if (isset($this->PORT))
+ {
+ $this->dsn .= 'PORT='.$this->port.';';
+ }
+ elseif ( ! empty($this->port))
+ {
+ $this->dsn .= ';PORT='.$this->port.';';
+ }
+
+ $this->dsn .= 'PROTOCOL='.(isset($this->PROTOCOL) ? $this->PROTOCOL.';' : 'TCPIP;');
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT "tabname" FROM "syscat"."tables"
+ WHERE "type" = \'T\' AND LOWER("tabschema") = '.$this->escape(strtolower($this->database));
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND "tabname" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return array
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT "colname" FROM "syscat"."columns"
+ WHERE LOWER("tabschema") = '.$this->escape(strtolower($this->database)).'
+ AND LOWER("tabname") = '.$this->escape(strtolower($table));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ $sql = 'SELECT "colname" AS "name", "typename" AS "type", "default" AS "default", "length" AS "max_length",
+ CASE "keyseq" WHEN NULL THEN 0 ELSE 1 END AS "primary_key"
+ FROM "syscat"."columns"
+ WHERE LOWER("tabschema") = '.$this->escape(strtolower($this->database)).'
+ AND LOWER("tabname") = '.$this->escape(strtolower($table)).'
+ ORDER BY "colno"';
+
+ return (($query = $this->query($sql)) !== FALSE)
+ ? $query->result_object()
+ : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ $sql .= ' FETCH FIRST '.($this->qb_limit + $this->qb_offset).' ROWS ONLY';
+
+ return ($this->qb_offset)
+ ? 'SELECT * FROM ('.$sql.') WHERE rownum > '.$this->qb_offset
+ : $sql;
+ }
+
+}
+
+/* End of file pdo_ibm_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php b/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php
new file mode 100644
index 000000000..f095c717a
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php
@@ -0,0 +1,146 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO IBM DB2 Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_ibm_forge extends CI_DB_pdo_forge {
+
+ /**
+ * RENAME TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_rename_table = 'RENAME TABLE %s TO %s';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INTEGER' => 'BIGINT'
+ );
+
+ /**
+ * DEFAULT value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_default = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'CHANGE')
+ {
+ $alter_type = 'MODIFY';
+ }
+
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute UNIQUE
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_unique(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ {
+ $field['unique'] = ' UNIQUE';
+
+ // UNIQUE must be used with NOT NULL
+ $field['null'] = ' NOT NULL';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported
+ }
+
+}
+
+/* End of file pdo_ibm_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
new file mode 100644
index 000000000..cfb474eec
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
@@ -0,0 +1,301 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Informix Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_informix_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'informix';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('ASC', 'ASC'); // Currently not supported
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'informix:';
+
+ // Pre-defined DSN
+ if (empty($this->hostname) && empty($this->host) && empty($this->port) && empty($this->service))
+ {
+ if (isset($this->DSN))
+ {
+ $this->dsn .= 'DSN='.$this->DSN;
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DSN='.$this->database;
+ }
+
+ return;
+ }
+
+ if (isset($this->host))
+ {
+ $this->dsn .= 'host='.$this->host;
+ }
+ else
+ {
+ $this->dsn .= 'host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+ }
+
+ if (isset($this->service))
+ {
+ $this->dsn .= '; service='.$this->service;
+ }
+ elseif ( ! empty($this->port))
+ {
+ $this->dsn .= '; service='.$this->port;
+ }
+
+ empty($this->database) OR $this->dsn .= '; database='.$this->database;
+ empty($this->server) OR $this->dsn .= '; server='.$this->server;
+
+ $this->dsn .= '; protocol='.(isset($this->protocol) ? $this->protocol : 'onsoctcp')
+ .'; EnableScrollableCursors=1';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT "tabname" FROM "systables"
+ WHERE "tabid" > 99 AND "tabtype" = \'T\' AND LOWER("owner") = '.$this->escape(strtolower($this->username));
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND "tabname" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ if (strpos($table, '.') !== FALSE)
+ {
+ sscanf($table, '%[^.].%s', $owner, $table);
+ }
+ else
+ {
+ $owner = $this->username;
+ }
+
+ return 'SELECT "colname" FROM "systables", "syscolumns"
+ WHERE "systables"."tabid" = "syscolumns"."tabid"
+ AND "systables"."tabtype" = \'T\'
+ AND LOWER("systables"."owner") = '.$this->escape(strtolower($owner)).'
+ AND LOWER("systables"."tabname") = '.$this->escape(strtolower($table));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ $sql = 'SELECT "syscolumns"."colname" AS "name",
+ CASE "syscolumns"."coltype"
+ WHEN 0 THEN \'CHAR\'
+ WHEN 1 THEN \'SMALLINT\'
+ WHEN 2 THEN \'INTEGER\'
+ WHEN 3 THEN \'FLOAT\'
+ WHEN 4 THEN \'SMALLFLOAT\'
+ WHEN 5 THEN \'DECIMAL\'
+ WHEN 6 THEN \'SERIAL\'
+ WHEN 7 THEN \'DATE\'
+ WHEN 8 THEN \'MONEY\'
+ WHEN 9 THEN \'NULL\'
+ WHEN 10 THEN \'DATETIME\'
+ WHEN 11 THEN \'BYTE\'
+ WHEN 12 THEN \'TEXT\'
+ WHEN 13 THEN \'VARCHAR\'
+ WHEN 14 THEN \'INTERVAL\'
+ WHEN 15 THEN \'NCHAR\'
+ WHEN 16 THEN \'NVARCHAR\'
+ WHEN 17 THEN \'INT8\'
+ WHEN 18 THEN \'SERIAL8\'
+ WHEN 19 THEN \'SET\'
+ WHEN 20 THEN \'MULTISET\'
+ WHEN 21 THEN \'LIST\'
+ WHEN 22 THEN \'Unnamed ROW\'
+ WHEN 40 THEN \'LVARCHAR\'
+ WHEN 41 THEN \'BLOB/CLOB/BOOLEAN\'
+ WHEN 4118 THEN \'Named ROW\'
+ ELSE "syscolumns"."coltype"
+ END AS "type",
+ "syscolumns"."collength" as "max_length",
+ CASE "sysdefaults"."type"
+ WHEN \'L\' THEN "sysdefaults"."default"
+ ELSE NULL
+ END AS "default"
+ FROM "syscolumns", "systables", "sysdefaults"
+ WHERE "syscolumns"."tabid" = "systables"."tabid"
+ AND "systables"."tabid" = "sysdefaults"."tabid"
+ AND "syscolumns"."colno" = "sysdefaults"."colno"
+ AND "systables"."tabtype" = \'T\'
+ AND LOWER("systables"."owner") = '.$this->escape(strtolower($this->username)).'
+ AND LOWER("systables"."tabname") = '.$this->escape(strtolower($table)).'
+ ORDER BY "syscolumns"."colno"';
+
+ return (($query = $this->query($sql)) !== FALSE)
+ ? $query->result_object()
+ : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ *
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'TRUNCATE TABLE ONLY '.$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql $SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ $select = 'SELECT '.($this->qb_offset ? 'SKIP '.$this->qb_offset : '').'FIRST '.$this->qb_limit.' ';
+ return preg_replace('/^(SELECT\s)/i', $select, $sql, 1);
+ }
+
+}
+
+/* End of file pdo_informix_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_informix_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php b/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php
new file mode 100644
index 000000000..8722dd200
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php
@@ -0,0 +1,155 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Informix Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_informix_forge extends CI_DB_pdo_forge {
+
+ /**
+ * RENAME TABLE statement
+ *
+ * @var string
+ */
+ protected $_rename_table = 'RENAME TABLE %s TO %s';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'REAL' => 'DOUBLE PRECISION',
+ 'SMALLFLOAT' => 'DOUBLE PRECISION'
+ );
+
+ /**
+ * DEFAULT value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_default = ', ';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'CHANGE')
+ {
+ $alter_type = 'MODIFY';
+ }
+
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'BYTE':
+ case 'TEXT':
+ case 'BLOB':
+ case 'CLOB':
+ $attributes['UNIQUE'] = FALSE;
+ if (isset($attributes['DEFAULT']))
+ {
+ unset($attributes['DEFAULT']);
+ }
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute UNIQUE
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_unique(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ {
+ $field['unique'] = ' UNIQUE CONSTRAINT '.$this->db->escape_identifiers($field['name']);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported
+ }
+
+}
+
+/* End of file pdo_informix_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_informix_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
new file mode 100644
index 000000000..a29397205
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
@@ -0,0 +1,283 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO MySQL Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'mysql';
+
+ /**
+ * Compression flag
+ *
+ * @var bool
+ */
+ public $compress = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Identifier escape character
+ *
+ * @var string
+ */
+ protected $_escape_char = '`';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'mysql:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ';port='.$this->port;
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ }
+ elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 6) === FALSE && is_php('5.3.6'))
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database connection
+ *
+ * @param bool $persistent
+ * @return object
+ * @todo SSL support
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ /* Prior to PHP 5.3.6, even if the charset was supplied in the DSN
+ * on connect - it was ignored. This is a work-around for the issue.
+ *
+ * Reference: http://www.php.net/manual/en/ref.pdo-mysql.connection.php
+ */
+ if ( ! is_php('5.3.6') && ! empty($this->char_set))
+ {
+ $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES '.$this->char_set
+ .(empty($this->dbcollat) ? '' : ' COLLATE '.$this->dbcollat);
+ }
+
+ if ($this->compress === TRUE)
+ {
+ $this->options[PDO::MYSQL_ATTR_COMPRESS] = TRUE;
+ }
+
+ return parent::db_connect($persistent);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SHOW TABLES';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->Field;
+
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
+
+ $retval[$i]->default = $query[$i]->Default;
+ $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update_Batch statement
+ *
+ * Generates a platform-specific batch update string from the supplied data
+ *
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index UPDATE key
+ * @return string
+ */
+ protected function _update_batch($table, $values, $index)
+ {
+ $ids = array();
+ foreach ($values as $key => $val)
+ {
+ $ids[] = $val[$index];
+
+ foreach (array_keys($val) as $field)
+ {
+ if ($field !== $index)
+ {
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ }
+ }
+ }
+
+ $cases = '';
+ foreach ($final as $k => $v)
+ {
+ $cases .= $k." = CASE \n"
+ .implode("\n", $v)."\n"
+ .'ELSE '.$k.' END), ';
+ }
+
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ *
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'TRUNCATE '.$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * FROM tables
+ *
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
+ *
+ * @return string
+ */
+ protected function _from_tables()
+ {
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
+ {
+ return '('.implode(', ', $this->qb_from).')';
+ }
+
+ return implode(', ', $this->qb_from);
+ }
+
+}
+
+/* End of file pdo_mysql_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php
new file mode 100644
index 000000000..5a6de6b2d
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php
@@ -0,0 +1,229 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO MySQL Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_mysql_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
+ protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * CREATE TABLE keys flag
+ *
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
+ */
+ protected $_create_table_keys = TRUE;
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT',
+ 'SMALLINT',
+ 'MEDIUMINT',
+ 'INT',
+ 'INTEGER',
+ 'BIGINT',
+ 'REAL',
+ 'DOUBLE',
+ 'DOUBLE PRECISION',
+ 'FLOAT',
+ 'DECIMAL',
+ 'NUMERIC'
+ );
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
+ {
+ parent::__construct($db);
+
+ $this->_create_table .= ' DEFAULT CHARSET '.$this->db->char_set.' COLLATE '.$this->db->dbcollat;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'DROP')
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ $field[$i] = ($alter_type === 'ADD')
+ ? "\n\tADD ".$field[$i]['_literal']
+ : "\n\tMODIFY ".$field[$i]['_literal'];
+ }
+ else
+ {
+ if ($alter_type === 'ADD')
+ {
+ $field[$i]['_literal'] = "\n\tADD ";
+ }
+ else
+ {
+ $field[$i]['_literal'] = empty($field[$i]['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE ";
+ }
+
+ $field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]);
+ }
+ }
+
+ return array($sql.implode(',', $field));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ $extra_clause = isset($field['after'])
+ ? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';
+
+ if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)
+ {
+ $extra_clause = ' FIRST';
+ }
+
+ return $this->db->escape_identifiers($field['name'])
+ .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))
+ .' '.$field['type'].$field['length']
+ .$field['unsigned']
+ .$field['null']
+ .$field['default']
+ .$field['auto_increment']
+ .$field['unique']
+ .$extra_clause;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
+ *
+ * @param string $table (ignored)
+ * @return string
+ */
+ protected function _process_indexes($table)
+ {
+ $sql = '';
+
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
+ {
+ if (is_array($this->keys[$i]))
+ {
+ for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i][$i2]]))
+ {
+ unset($this->keys[$i][$i2]);
+ continue;
+ }
+ }
+ }
+ elseif ( ! isset($this->fields[$this->keys[$i]]))
+ {
+ unset($this->keys[$i]);
+ continue;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
+ }
+
+ $this->keys = array();
+
+ return $sql;
+ }
+
+}
+
+/* End of file pdo_mysql_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
new file mode 100644
index 000000000..57df558ad
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
@@ -0,0 +1,291 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Oracle Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_oci_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'oci';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * List of reserved identifiers
+ *
+ * Identifiers that must NOT be escaped.
+ *
+ * @var string[]
+ */
+ protected $_reserved_identifiers = array('*', 'rownum');
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('ASC', 'ASC'); // Currently not supported
+
+ /**
+ * COUNT string
+ *
+ * @used-by CI_DB_driver::count_all()
+ * @used-by CI_DB_query_builder::count_all_results()
+ *
+ * @var string
+ */
+ protected $_count_string = 'SELECT COUNT(1) AS ';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'oci:dbname=';
+
+ // Oracle has a slightly different PDO DSN format (Easy Connect),
+ // which also supports pre-defined DSNs.
+ if (empty($this->hostname) && empty($this->port))
+ {
+ $this->dsn .= $this->database;
+ }
+ else
+ {
+ $this->dsn .= '//'.(empty($this->hostname) ? '127.0.0.1' : $this->hostname)
+ .(empty($this->port) ? '' : ':'.$this->port).'/';
+
+ empty($this->database) OR $this->dsn .= $this->database;
+ }
+
+ empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;
+ }
+ elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 4) === FALSE)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT "TABLE_NAME" FROM "ALL_TABLES"';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql.' WHERE "TABLE_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ if (strpos($table, '.') !== FALSE)
+ {
+ sscanf($table, '%[^.].%s', $owner, $table);
+ }
+ else
+ {
+ $owner = $this->username;
+ }
+
+ return 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS
+ WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
+ AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+ elseif (strpos($table, '.') !== FALSE)
+ {
+ sscanf($table, '%[^.].%s', $owner, $table);
+ }
+ else
+ {
+ $owner = $this->username;
+ }
+
+ $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHAR_LENGTH, DATA_PRECISION, DATA_LENGTH, DATA_DEFAULT, NULLABLE
+ FROM ALL_TAB_COLUMNS
+ WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
+ AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
+
+ $length = ($query[$i]->CHAR_LENGTH > 0)
+ ? $query[$i]->CHAR_LENGTH : $query[$i]->DATA_PRECISION;
+ if ($length === NULL)
+ {
+ $length = $query[$i]->DATA_LENGTH;
+ }
+ $retval[$i]->max_length = $length;
+
+ $default = $query[$i]->DATA_DEFAULT;
+ if ($default === NULL && $query[$i]->NULLABLE === 'N')
+ {
+ $default = '';
+ }
+ $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert batch statement
+ *
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string
+ */
+ protected function _insert_batch($table, $keys, $values)
+ {
+ $keys = implode(', ', $keys);
+ $sql = "INSERT ALL\n";
+
+ for ($i = 0, $c = count($values); $i < $c; $i++)
+ {
+ $sql .= ' INTO '.$table.' ('.$keys.') VALUES '.$values[$i]."\n";
+ }
+
+ return $sql.'SELECT * FROM dual';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ if ($this->qb_limit)
+ {
+ $this->where('rownum <= ',$this->qb_limit, FALSE);
+ $this->qb_limit = FALSE;
+ }
+
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')'
+ .($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1): '');
+ }
+
+}
+
+/* End of file pdo_oci_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_oci_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php
new file mode 100644
index 000000000..6d51a14b1
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Oracle Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_oci_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
+ protected $_create_database = FALSE;
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
+ protected $_drop_database = FALSE;
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'DROP')
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+ elseif ($alter_type === 'CHANGE')
+ {
+ $alter_type = 'MODIFY';
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ $field[$i] = "\n\t".$field[$i]['_literal'];
+ }
+ else
+ {
+ $field[$i]['_literal'] = "\n\t".$this->_process_column($field[$i]);
+ if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name']))
+ {
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' '.$this->db->escape_identifiers($field[$i]['new_name']);
+ }
+ }
+ }
+
+ $sql .= ' '.$alter_type.' ';
+ $sql .= (count($field) === 1)
+ ? $field[0]
+ : '('.implode(',', $field).')';
+
+ // RENAME COLUMN must be executed after MODIFY
+ array_unshift($sqls, $sql);
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported - sequences and triggers must be used instead
+ }
+
+}
+
+/* End of file pdo_oci_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_oci_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
new file mode 100644
index 000000000..c940a7b1f
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
@@ -0,0 +1,258 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO ODBC Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'odbc';
+
+ /**
+ * Database schema
+ *
+ * @var string
+ */
+ public $schema = 'public';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Identifier escape character
+ *
+ * Must be empty for ODBC.
+ *
+ * @var string
+ */
+ protected $_escape_char = '';
+
+ /**
+ * ESCAPE statement string
+ *
+ * @var string
+ */
+ protected $_like_escape_str = " {escape '%s'} ";
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RND()', 'RND(%d)');
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'odbc:';
+
+ // Pre-defined DSN
+ if (empty($this->hostname) && empty($this->HOSTNAME) && empty($this->port) && empty($this->PORT))
+ {
+ if (isset($this->DSN))
+ {
+ $this->dsn .= 'DSN='.$this->DSN;
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DSN='.$this->database;
+ }
+
+ return;
+ }
+
+ // If the DSN is not pre-configured - try to build an IBM DB2 connection string
+ $this->dsn .= 'DRIVER='.(isset($this->DRIVER) ? '{'.$this->DRIVER.'}' : '{IBM DB2 ODBC DRIVER}').';';
+
+ if (isset($this->DATABASE))
+ {
+ $this->dsn .= 'DATABASE='.$this->DATABASE.';';
+ }
+ elseif ( ! empty($this->database))
+ {
+ $this->dsn .= 'DATABASE='.$this->database.';';
+ }
+
+ if (isset($this->HOSTNAME))
+ {
+ $this->dsn .= 'HOSTNAME='.$this->HOSTNAME.';';
+ }
+ else
+ {
+ $this->dsn .= 'HOSTNAME='.(empty($this->hostname) ? '127.0.0.1;' : $this->hostname.';');
+ }
+
+ if (isset($this->PORT))
+ {
+ $this->dsn .= 'PORT='.$this->port.';';
+ }
+ elseif ( ! empty($this->port))
+ {
+ $this->dsn .= ';PORT='.$this->port.';';
+ }
+
+ $this->dsn .= 'PROTOCOL='.(isset($this->PROTOCOL) ? $this->PROTOCOL.';' : 'TCPIP;');
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = '".$this->schema."'";
+
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
+ {
+ return $sql." AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT column_name FROM information_schema.columns WHERE table_name = '.$this->escape($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ *
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'DELETE FROM '.$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string the table name
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$this->qb_limit.' ', $sql);
+ }
+
+}
+
+/* End of file pdo_odbc_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php
new file mode 100644
index 000000000..ab4d2bf84
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO ODBC Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/database/
+ */
+class CI_DB_pdo_odbc_forge extends CI_DB_pdo_forge {
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported (in most databases at least)
+ }
+
+}
+
+/* End of file pdo_odbc_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
new file mode 100644
index 000000000..2eb0606b3
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
@@ -0,0 +1,357 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO PostgreSQL Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'pgsql';
+
+ /**
+ * Database schema
+ *
+ * @var string
+ */
+ public $schema = 'public';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RANDOM()', 'RANDOM()');
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'pgsql:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ';port='.$this->port;
+ empty($this->database) OR $this->dsn .= ';dbname='.$this->database;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database connection
+ *
+ * @param bool $persistent
+ * @return object
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ $this->conn_id = parent::db_connect($persistent);
+
+ if (is_object($this->conn_id) && ! empty($this->schema))
+ {
+ $this->simple_query('SET search_path TO '.$this->schema.',public');
+ }
+
+ return $this->conn_id;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @param string $name
+ * @return int
+ */
+ public function insert_id($name = NULL)
+ {
+ if ($name === NULL && version_compare($this->version(), '8.1', '>='))
+ {
+ $query = $this->query('SELECT LASTVAL() AS ins_id');
+ $query = $query->row();
+ return $query->ins_id;
+ }
+
+ return $this->conn_id->lastInsertId($name);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Smart" Escape String
+ *
+ * Escapes data based on type
+ *
+ * @param string $str
+ * @return mixed
+ */
+ public function escape($str)
+ {
+ if (is_bool($str))
+ {
+ return ($str) ? 'TRUE' : 'FALSE';
+ }
+
+ return parent::escape($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY
+ *
+ * @param string $orderby
+ * @param string $direction ASC or DESC
+ * @param bool $escape
+ * @return object
+ */
+ public function order_by($orderby, $direction = '', $escape = NULL)
+ {
+ $direction = strtoupper(trim($direction));
+ if ($direction === 'RANDOM')
+ {
+ if ( ! is_float($orderby) && ctype_digit((string) $orderby))
+ {
+ $orderby = ($orderby > 1)
+ ? (float) '0.'.$orderby
+ : (float) $orderby;
+ }
+
+ if (is_float($orderby))
+ {
+ $this->simple_query('SET SEED '.$orderby);
+ }
+
+ $orderby = $this->_random_keyword[0];
+ $direction = '';
+ $escape = FALSE;
+ }
+
+ return parent::order_by($orderby, $direction, $escape);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \''.$this->schema."'";
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql.' AND "table_name" LIKE \''
+ .$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * List column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT "column_name"
+ FROM "information_schema"."columns"
+ WHERE LOWER("table_name") = '.$this->escape(strtolower($table));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT "column_name", "data_type", "character_maximum_length", "numeric_precision", "column_default"
+ FROM "information_schema"."columns"
+ WHERE LOWER("table_name") = '.$this->escape(strtolower($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->column_name;
+ $retval[$i]->type = $query[$i]->data_type;
+ $retval[$i]->max_length = ($query[$i]->character_maximum_length > 0) ? $query[$i]->character_maximum_length : $query[$i]->numeric_precision;
+ $retval[$i]->default = $query[$i]->column_default;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update_Batch statement
+ *
+ * Generates a platform-specific batch update string from the supplied data
+ *
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
+ * @return string
+ */
+ protected function _update_batch($table, $values, $index)
+ {
+ $ids = array();
+ foreach ($values as $key => $val)
+ {
+ $ids[] = $val[$index];
+
+ foreach (array_keys($val) as $field)
+ {
+ if ($field !== $index)
+ {
+ $final[$field][] = 'WHEN '.$val[$index].' THEN '.$val[$field];
+ }
+ }
+ }
+
+ $cases = '';
+ foreach ($final as $k => $v)
+ {
+ $cases .= $k.' = (CASE '.$index."\n"
+ .implode("\n", $v)."\n"
+ .'ELSE '.$k.' END), ';
+ }
+
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');
+ }
+
+}
+
+/* End of file pdo_pgsql_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php
new file mode 100644
index 000000000..a24c898af
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php
@@ -0,0 +1,195 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO PostgreSQL Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_pgsql_forge extends CI_DB_pdo_forge {
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'INT2' => 'INTEGER',
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INT4' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'INT8' => 'NUMERIC',
+ 'BIGINT' => 'NUMERIC',
+ 'REAL' => 'DOUBLE PRECISION',
+ 'FLOAT' => 'DOUBLE PRECISION'
+ );
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
+ {
+ parent::__construct($db);
+
+ if (version_compare($this->db->version(), '9.0', '>'))
+ {
+ $this->create_table_if = 'CREATE TABLE IF NOT EXISTS';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ return FALSE;
+ }
+
+ if (version_compare($this->db->version(), '8', '>=') && isset($field[$i]['type']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TYPE '.$field[$i]['type'].$field[$i]['length'];
+ }
+
+ if ( ! empty($field[$i]['default']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' SET DEFAULT '.$field[$i]['default'];
+ }
+
+ if (isset($field[$i]['null']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .($field[$i]['null'] === TRUE ? ' DROP NOT NULL' : ' SET NOT NULL');
+ }
+
+ if ( ! empty($field[$i]['new_name']))
+ {
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
+ }
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ // Reset field lenghts for data types that don't support it
+ if (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE)
+ {
+ $attributes['CONSTRAINT'] = NULL;
+ }
+
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
+ {
+ $field['type'] = ($field['type'] === 'NUMERIC')
+ ? 'BIGSERIAL'
+ : 'SERIAL';
+ }
+ }
+
+}
+
+/* End of file pdo_pgsql_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php
new file mode 100644
index 000000000..568044e2d
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php
@@ -0,0 +1,202 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO SQLite Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_sqlite_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'sqlite';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = ' RANDOM()';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'sqlite:';
+
+ if (empty($this->database) && empty($this->hostname))
+ {
+ $this->database = ':memory:';
+ }
+
+ $this->database = empty($this->database) ? $this->hostname : $this->database;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = 'SELECT "NAME" FROM "SQLITE_MASTER" WHERE "TYPE" = \'table\'';
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ return $sql.' AND "NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ // Not supported
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ if (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
+ {
+ return FALSE;
+ }
+
+ $query = $query->result_array();
+ if (empty($query))
+ {
+ return FALSE;
+ }
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]['name'];
+ $retval[$i]->type = $query[$i]['type'];
+ $retval[$i]->max_length = NULL;
+ $retval[$i]->default = $query[$i]['dflt_value'];
+ $retval[$i]->primary_key = isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Replace statement
+ *
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string
+ */
+ protected function _replace($table, $keys, $values)
+ {
+ return 'INSERT OR '.parent::_replace($table, $keys, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ *
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _truncate($table)
+ {
+ return 'DELETE FROM '.$table;
+ }
+
+}
+
+/* End of file pdo_sqlite_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php b/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php
new file mode 100644
index 000000000..da098df31
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php
@@ -0,0 +1,229 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO SQLite Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_sqlite_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
+ {
+ parent::__construct($db);
+
+ if (version_compare($this->db->version(), '3.3', '<'))
+ {
+ $this->_create_table_if = FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create database
+ *
+ * @param string $db_name (ignored)
+ * @return bool
+ */
+ public function create_database($db_name = '')
+ {
+ // In SQLite, a database is created when you connect to the database.
+ // We'll return TRUE so that an error isn't generated
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Drop database
+ *
+ * @param string $db_name (ignored)
+ * @return bool
+ */
+ public function drop_database($db_name = '')
+ {
+ // In SQLite, a database is dropped when we delete a file
+ if (@file_exists($this->db->database))
+ {
+ // We need to close the pseudo-connection first
+ $this->db->close();
+ if ( ! @unlink($this->db->database))
+ {
+ return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;
+ }
+ elseif ( ! empty($this->db->data_cache['db_names']))
+ {
+ $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
+ if ($key !== FALSE)
+ {
+ unset($this->db->data_cache['db_names'][$key]);
+ }
+ }
+
+ return TRUE;
+ }
+
+ return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'DROP' OR $alter_type === 'CHANGE')
+ {
+ // drop_column():
+ // BEGIN TRANSACTION;
+ // CREATE TEMPORARY TABLE t1_backup(a,b);
+ // INSERT INTO t1_backup SELECT a,b FROM t1;
+ // DROP TABLE t1;
+ // CREATE TABLE t1(a,b);
+ // INSERT INTO t1 SELECT a,b FROM t1_backup;
+ // DROP TABLE t1_backup;
+ // COMMIT;
+
+ return FALSE;
+ }
+
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type']
+ .$field['auto_increment']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'ENUM':
+ case 'SET':
+ $attributes['TYPE'] = 'TEXT';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['type'] = 'INTEGER PRIMARY KEY';
+ $field['default'] = '';
+ $field['null'] = '';
+ $field['unique'] = '';
+ $field['auto_increment'] = ' AUTOINCREMENT';
+
+ $this->primary_keys = array();
+ }
+ }
+
+}
+
+/* End of file pdo_sqlite_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
new file mode 100644
index 000000000..ec0252613
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
@@ -0,0 +1,363 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO SQLSRV Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the query builder
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver {
+
+ /**
+ * Sub-driver
+ *
+ * @var string
+ */
+ public $subdriver = 'sqlsrv';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('NEWID()', 'RAND(%d)');
+
+ /**
+ * Quoted identifier flag
+ *
+ * Whether to use SQL-92 standard quoted identifier
+ * (double quotes) or brackets for identifier escaping.
+ *
+ * @var bool
+ */
+ protected $_quoted_identifier;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * Builds the DSN if not already set.
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
+ {
+ parent::__construct($params);
+
+ if (empty($this->dsn))
+ {
+ $this->dsn = 'sqlsrv:Server='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);
+
+ empty($this->port) OR $this->dsn .= ','.$this->port;
+ empty($this->database) OR $this->dsn .= ';Database='.$this->database;
+
+ // Some custom options
+
+ if (isset($this->QuotedId))
+ {
+ $this->dsn .= ';QuotedId='.$this->QuotedId;
+ $this->_quoted_identifier = (bool) $this->QuotedId;
+ }
+
+ if (isset($this->ConnectionPooling))
+ {
+ $this->dsn .= ';ConnectionPooling='.$this->ConnectionPooling;
+ }
+
+ if ($this->encrypt === TRUE)
+ {
+ $this->dsn .= ';Encrypt=1';
+ }
+
+ if (isset($this->TraceOn))
+ {
+ $this->dsn .= ';TraceOn='.$this->TraceOn;
+ }
+
+ if (isset($this->TrustServerCertificate))
+ {
+ $this->dsn .= ';TrustServerCertificate='.$this->TrustServerCertificate;
+ }
+
+ empty($this->APP) OR $this->dsn .= ';APP='.$this->APP;
+ empty($this->Failover_Partner) OR $this->dsn .= ';Failover_Partner='.$this->Failover_Partner;
+ empty($this->LoginTimeout) OR $this->dsn .= ';LoginTimeout='.$this->LoginTimeout;
+ empty($this->MultipleActiveResultSets) OR $this->dsn .= ';MultipleActiveResultSets='.$this->MultipleActiveResultSets;
+ empty($this->TraceFile) OR $this->dsn .= ';TraceFile='.$this->TraceFile;
+ empty($this->WSID) OR $this->dsn .= ';WSID='.$this->WSID;
+ }
+ elseif (preg_match('/QuotedId=(0|1)/', $this->dsn, $match))
+ {
+ $this->_quoted_identifier = (bool) $match[1];
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database connection
+ *
+ * @param bool $persistent
+ * @return object
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ if ( ! empty($this->char_set) && preg_match('/utf[^8]*8/i', $this->char_set))
+ {
+ $this->options[PDO::SQLSRV_ENCODING_UTF8] = 1;
+ }
+
+ $this->conn_id = parent::db_connect($persistent);
+
+ if ( ! is_object($this->conn_id) OR is_bool($this->_quoted_identifier))
+ {
+ return $this->conn_id;
+ }
+
+ // Determine how identifiers are escaped
+ $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
+ $query = $query->row_array();
+ $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
+ $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
+
+ return $this->conn_id;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @param bool $prefix_limit
+ * @return string
+ */
+ protected function _list_tables($prefix_limit = FALSE)
+ {
+ return 'SELECT '.$this->escape_identifiers('name')
+ .' FROM '.$this->escape_identifiers('sysobjects')
+ .' WHERE '.$this->escape_identifiers('type')." = 'U'";
+
+ if ($prefix_limit === TRUE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
+
+ return $sql.' ORDER BY '.$this->escape_identifiers('name');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _list_columns($table = '')
+ {
+ return 'SELECT COLUMN_NAME
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table = '')
+ {
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
+ $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;
+ $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @param string $table
+ * @param array $values
+ * @return string
+ */
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @param string $table
+ * @return string
+ */
+ protected function _delete($table)
+ {
+ if ($this->qb_limit)
+ {
+ return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';
+ }
+
+ return parent::_delete($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * LIMIT
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @param string $sql SQL Query
+ * @return string
+ */
+ protected function _limit($sql)
+ {
+ // As of SQL Server 2012 (11.0.*) OFFSET is supported
+ if (version_compare($this->version(), '11', '>='))
+ {
+ return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';
+ }
+
+ $limit = $this->qb_offset + $this->qb_limit;
+
+ // An ORDER BY clause is required for ROW_NUMBER() to work
+ if ($this->qb_offset && ! empty($this->qb_orderby))
+ {
+ $orderby = $this->_compile_order_by();
+
+ // We have to strip the ORDER BY clause
+ $sql = trim(substr($sql, 0, strrpos($sql, $orderby)));
+
+ // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results
+ if (count($this->qb_select) === 0)
+ {
+ $select = '*'; // Inevitable
+ }
+ else
+ {
+ // Use only field names and their aliases, everything else is out of our scope.
+ $select = array();
+ $field_regexp = ($this->_quoted_identifier)
+ ? '("[^\"]+")' : '(\[[^\]]+\])';
+ for ($i = 0, $c = count($this->qb_select); $i < $c; $i++)
+ {
+ $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)
+ ? $m[1] : $this->qb_select[$i];
+ }
+ $select = implode(', ', $select);
+ }
+
+ return 'SELECT '.$select." FROM (\n\n"
+ .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)
+ ."\n\n) ".$this->escape_identifiers('CI_subquery')
+ ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
+ }
+
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert batch statement
+ *
+ * Generates a platform-specific insert string from the supplied data.
+ *
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string|bool
+ */
+ protected function _insert_batch($table, $keys, $values)
+ {
+ // Multiple-value inserts are only supported as of SQL Server 2008
+ if (version_compare($this->version(), '10', '>='))
+ {
+ return parent::_insert_batch($table, $keys, $values);
+ }
+
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
+ }
+
+}
+
+/* End of file pdo_sqlsrv_driver.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php
new file mode 100644
index 000000000..e4b669f6e
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO SQLSRV Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_sqlsrv_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ $sqls[] = $sql.$this->_process_column($field[$i]);
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' IDENTITY(1,1)';
+ }
+ }
+
+}
+
+/* End of file pdo_sqlsrv_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index 20b78673e..44cd0ce9b 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Postgre Database Adapter Class
@@ -40,21 +41,37 @@
*/
class CI_DB_postgre_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'postgre';
- protected $_escape_char = '"';
+ /**
+ * Database schema
+ *
+ * @var string
+ */
+ public $schema = 'public';
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
+ // --------------------------------------------------------------------
- protected $_random_keyword = ' RANDOM()'; // database specific random keyword
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RANDOM()', 'RANDOM()');
+
+ // --------------------------------------------------------------------
/**
- * Constructor
+ * Class constructor
*
* Creates a DSN string to be used for db_connect() and db_pconnect()
*
+ * @param array $params
* @return void
*/
public function __construct($params)
@@ -114,13 +131,32 @@ class CI_DB_postgre_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Non-persistent database connection
+ * Database connection
*
+ * @param bool $persistent
* @return resource
*/
- public function db_connect()
+ public function db_connect($persistent = FALSE)
{
- return @pg_connect($this->dsn);
+ if ($persistent === TRUE
+ && ($this->conn_id = @pg_pconnect($this->dsn))
+ && pg_connection_status($this->conn_id) === PGSQL_CONNECTION_BAD
+ && pg_ping($this->conn_id) === FALSE
+ )
+ {
+ return FALSE;
+ }
+ else
+ {
+ $this->conn_id = @pg_connect($this->dsn);
+ }
+
+ if ($this->conn_id && ! empty($this->schema))
+ {
+ $this->simple_query('SET search_path TO '.$this->schema.',public');
+ }
+
+ return $this->conn_id;
}
// --------------------------------------------------------------------
@@ -132,7 +168,7 @@ class CI_DB_postgre_driver extends CI_DB {
*/
public function db_pconnect()
{
- return @pg_pconnect($this->dsn);
+ return $this->db_connect(TRUE);
}
// --------------------------------------------------------------------
@@ -158,7 +194,7 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Set client character set
*
- * @param string
+ * @param string $charset
* @return bool
*/
protected function _db_set_charset($charset)
@@ -179,8 +215,12 @@ class CI_DB_postgre_driver extends CI_DB {
{
return $this->data_cache['version'];
}
+ elseif ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
- if (($pg_version = pg_version($this->conn_id)) === FALSE)
+ if ( ! $this->conn_id OR ($pg_version = pg_version($this->conn_id)) === FALSE)
{
return FALSE;
}
@@ -200,7 +240,7 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
@@ -213,7 +253,7 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Begin Transaction
*
- * @param bool
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -273,8 +313,8 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -308,9 +348,8 @@ class CI_DB_postgre_driver extends CI_DB {
* "Smart" Escape String
*
* Escapes data based on type
- * Sets boolean and null types
*
- * @param string
+ * @param string $str
* @return mixed
*/
public function escape($str)
@@ -388,12 +427,12 @@ class CI_DB_postgre_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \'public\'';
+ $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \''.$this->schema."'";
if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
@@ -408,31 +447,56 @@ class CI_DB_postgre_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Show column query
+ * List column query
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
{
- return 'SELECT "column_name" FROM "information_schema"."columns" WHERE "table_name" = '.$this->escape($table);
+ return 'SELECT "column_name"
+ FROM "information_schema"."columns"
+ WHERE LOWER("table_name") = '.$this->escape(strtolower($table));
}
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return 'SELECT * FROM '.$table.' LIMIT 1';
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT "column_name", "data_type", "character_maximum_length", "numeric_precision", "column_default"
+ FROM "information_schema"."columns"
+ WHERE LOWER("table_name") = '.$this->escape(strtolower($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->column_name;
+ $retval[$i]->type = $query[$i]->data_type;
+ $retval[$i]->max_length = ($query[$i]->character_maximum_length > 0) ? $query[$i]->character_maximum_length : $query[$i]->numeric_precision;
+ $retval[$i]->default = $query[$i]->column_default;
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
@@ -453,17 +517,36 @@ class CI_DB_postgre_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
+ * ORDER BY
*
- * @param array
- * @return string
+ * @param string $orderby
+ * @param string $direction ASC or DESC
+ * @param bool $escape
+ * @return object
*/
- protected function _from_tables($tables)
+ public function order_by($orderby, $direction = '', $escape = NULL)
{
- return is_array($tables) ? implode(', ', $tables) : $tables;
+ $direction = strtoupper(trim($direction));
+ if ($direction === 'RANDOM')
+ {
+ if ( ! is_float($orderby) && ctype_digit((string) $orderby))
+ {
+ $orderby = ($orderby > 1)
+ ? (float) '0.'.$orderby
+ : (float) $orderby;
+ }
+
+ if (is_float($orderby))
+ {
+ $this->simple_query('SET SEED '.$orderby);
+ }
+
+ $orderby = $this->_random_keyword[0];
+ $direction = '';
+ $escape = FALSE;
+ }
+
+ return parent::order_by($orderby, $direction, $escape);
}
// --------------------------------------------------------------------
@@ -473,29 +556,15 @@ class CI_DB_postgre_driver extends CI_DB {
*
* Generates a platform-specific update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @param array the orderby clause (ignored)
- * @param array the limit clause (ignored)
- * @param array the like clause
+ * @param string $table
+ * @param array $values
* @return string
*/
- protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array())
+ protected function _update($table, $values)
{
- foreach ($values as $key => $val)
- {
- $valstr[] = $key.' = '.$val;
- }
-
- $where = empty($where) ? '' : ' WHERE '.implode(' ', $where);
-
- if ( ! empty($like))
- {
- $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like);
- }
-
- return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -505,12 +574,12 @@ class CI_DB_postgre_driver extends CI_DB {
*
* Generates a platform-specific batch update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
* @return string
*/
- protected function _update_batch($table, $values, $index, $where = NULL)
+ protected function _update_batch($table, $values, $index)
{
$ids = array();
foreach ($values as $key => $val)
@@ -521,7 +590,7 @@ class CI_DB_postgre_driver extends CI_DB {
{
if ($field !== $index)
{
- $final[$field][] = 'WHEN '.$val[$index].' THEN '.$val[$field];
+ $final[$field][] = 'WHEN '.$val[$index].' THEN '.$val[$field];
}
}
}
@@ -529,14 +598,14 @@ class CI_DB_postgre_driver extends CI_DB {
$cases = '';
foreach ($final as $k => $v)
{
- $cases .= $k.' = (CASE '.$k."\n"
+ $cases .= $k.' = (CASE '.$index."\n"
.implode("\n", $v)."\n"
.'ELSE '.$k.' END), ';
}
- return 'UPDATE '.$table.' SET '.substr($cases, 0, -2)
- .' WHERE '.(($where !== '' && count($where) > 0) ? implode(' ', $where).' AND ' : '')
- .$index.' IN('.implode(',', $ids).')';
+ $this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);
+
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
@@ -546,108 +615,28 @@ class CI_DB_postgre_driver extends CI_DB {
*
* Generates a platform-specific delete string from the supplied data
*
- * @param string the table name
- * @param array the where clause
- * @param array the like clause
- * @param string the limit clause (ignored)
+ * @param string $table
* @return string
*/
- protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- return 'DELETE FROM '.$table.(count($conditions) > 0 ? ' WHERE '.implode(' AND ', $conditions) : '');
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * LIMIT
*
* Generates a platform-specific LIMIT clause
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
+ * @param string $sql SQL Query
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _limit($sql)
{
- return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : '');
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Where
- *
- * Called by where() or or_where()
- *
- * @param mixed
- * @param mixed
- * @param string
- * @param mixed
- * @return object
- */
- protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
- {
- if ( ! is_array($key))
- {
- $key = array($key => $value);
- }
-
- // If the escape value was not set will will base it on the global setting
- is_bool($escape) OR $escape = $this->_protect_identifiers;
-
- foreach ($key as $k => $v)
- {
- $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
- ? $this->_group_get_type('')
- : $this->_group_get_type($type);
-
- if ($escape === TRUE)
- {
- $k = (($op = $this->_get_operator($k)) !== FALSE)
- ? $this->escape_identifiers(trim(substr($k, 0, strpos($k, $op)))).' '.strstr($k, $op)
- : $this->escape_identifiers(trim($k));
- }
-
- if (is_null($v) && ! $this->_has_operator($k))
- {
- // value appears not to have been set, assign the test to IS NULL
- $k .= ' IS NULL';
- }
-
- if ( ! is_null($v))
- {
- if ($escape === TRUE)
- {
- $v = ' '.$this->escape($v);
- }
- elseif (is_bool($v))
- {
- $v = ($v ? ' TRUE' : ' FALSE');
- }
-
- if ( ! $this->_has_operator($k))
- {
- $k .= ' = ';
- }
- }
-
- $this->qb_where[] = $prefix.$k.$v;
- if ($this->qb_caching === TRUE)
- {
- $this->qb_cache_where[] = $prefix.$k.$v;
- $this->qb_cache_exists[] = 'where';
- }
-
- }
-
- return $this;
+ return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/postgre/postgre_forge.php b/system/database/drivers/postgre/postgre_forge.php
index c434e9510..5e378385c 100644
--- a/system/database/drivers/postgre/postgre_forge.php
+++ b/system/database/drivers/postgre/postgre_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Postgre Forge Class
@@ -34,184 +35,152 @@
*/
class CI_DB_postgre_forge extends CI_DB_forge {
- protected $_drop_table = 'DROP TABLE IF EXISTS %s CASCADE';
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'INT2' => 'INTEGER',
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INT4' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'INT8' => 'NUMERIC',
+ 'BIGINT' => 'NUMERIC',
+ 'REAL' => 'DOUBLE PRECISION',
+ 'FLOAT' => 'DOUBLE PRECISION'
+ );
/**
- * Process Fields
+ * NULL value representation in CREATE/ALTER TABLE statements
*
- * @param mixed the fields
- * @return string
+ * @var string
*/
- protected function _process_fields($fields, $primary_keys = array())
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
{
- $sql = '';
- $current_field_count = 0;
+ parent::__construct($db);
- foreach ($fields as $field => $attributes)
+ if (version_compare($this->db->version(), '9.0', '>'))
{
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
+ $this->create_table_if = 'CREATE TABLE IF NOT EXISTS';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ return FALSE;
+ }
+
+ if (version_compare($this->db->version(), '8', '>=') && isset($field[$i]['type']))
{
- $sql .= "\n\t".$attributes;
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TYPE '.$field[$i]['type'].$field[$i]['length'];
}
- else
+
+ if ( ! empty($field[$i]['default']))
+ {
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' SET DEFAULT '.$field[$i]['default'];
+ }
+
+ if (isset($field[$i]['null']))
{
- $sql .= "\n\t".$this->db->escape_identifiers($field);
-
- $attributes = array_change_key_case($attributes, CASE_UPPER);
- $is_unsigned = ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE);
-
- // Convert datatypes to be PostgreSQL-compatible
- switch (strtoupper($attributes['TYPE']))
- {
- case 'TINYINT':
- $attributes['TYPE'] = 'SMALLINT';
- break;
- case 'SMALLINT':
- $attributes['TYPE'] = ($is_unsigned) ? 'INTEGER' : 'SMALLINT';
- break;
- case 'MEDIUMINT':
- $attributes['TYPE'] = 'INTEGER';
- break;
- case 'INT':
- $attributes['TYPE'] = ($is_unsigned) ? 'BIGINT' : 'INTEGER';
- break;
- case 'BIGINT':
- $attributes['TYPE'] = ($is_unsigned) ? 'NUMERIC' : 'BIGINT';
- break;
- case 'DOUBLE':
- $attributes['TYPE'] = 'DOUBLE PRECISION';
- break;
- case 'DATETIME':
- $attributes['TYPE'] = 'TIMESTAMP';
- break;
- case 'LONGTEXT':
- $attributes['TYPE'] = 'TEXT';
- break;
- case 'BLOB':
- $attributes['TYPE'] = 'BYTEA';
- break;
- default:
- break;
- }
-
- // If this is an auto-incrementing primary key, use the serial data type instead
- $sql .= (in_array($field, $primary_keys) && ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- ? ' SERIAL' : ' '.$attributes['TYPE'];
-
- // Modified to prevent constraints with integer data types
- if ( ! empty($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') === FALSE)
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
-
- // Added new attribute to create unique fields. Also works with MySQL
- if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
- {
- $sql .= ' UNIQUE';
- }
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .($field[$i]['null'] === TRUE ? ' DROP NOT NULL' : ' SET NOT NULL');
}
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
+ if ( ! empty($field[$i]['new_name']))
{
- $sql .= ',';
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
}
}
- return $sql;
- }
+ return $sqls;
+ }
// --------------------------------------------------------------------
/**
- * Create Table
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @param array &$attributes
+ * @return void
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _attr_type(&$attributes)
{
- $sql = 'CREATE TABLE ';
-
- // PostgreSQL doesn't support IF NOT EXISTS syntax so we check if table exists manually
- if ($if_not_exists === TRUE && $this->db->table_exists($table))
+ // Reset field lenghts for data types that don't support it
+ if (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE)
{
- return TRUE;
+ $attributes['CONSTRAINT'] = NULL;
}
- $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields, $primary_keys);
-
- if (count($primary_keys) > 0)
+ switch (strtoupper($attributes['TYPE']))
{
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')';
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
}
-
- $sql .= "\n);";
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- foreach ($key as $field)
- {
- $sql .= "\nCREATE INDEX ".$this->db->escape_identifiers($table.'_'.str_replace(array('"', "'"), '', $field).'_index')
- .' ON '.$this->db->escape_identifiers($table).' ('.$this->db->escape_identifiers($field).');';
- }
- }
- }
-
- return $sql;
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute AUTO_INCREMENT
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
- *
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $fields, $after_field = '')
- {
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' ';
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
- {
- return $sql.$this->db->escape_identifiers($fields);
- }
-
- return $sql.$this->_process_fields($fields)
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
- }
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
+ {
+ $field['type'] = ($field['type'] === 'NUMERIC')
+ ? 'BIGSERIAL'
+ : 'SERIAL';
+ }
+ }
}
diff --git a/system/database/drivers/postgre/postgre_result.php b/system/database/drivers/postgre/postgre_result.php
index eb9d647e7..fdaeaef70 100644
--- a/system/database/drivers/postgre/postgre_result.php
+++ b/system/database/drivers/postgre/postgre_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Postgres Result Class
@@ -99,8 +100,6 @@ class CI_DB_postgre_result extends CI_DB_result {
$retval[$i]->name = pg_field_name($this->result_id, $i);
$retval[$i]->type = pg_field_type($this->result_id, $i);
$retval[$i]->max_length = pg_field_size($this->result_id, $i);
- $retval[$i]->primary_key = 0;
- $retval[$i]->default = '';
}
return $retval;
@@ -129,11 +128,12 @@ class CI_DB_postgre_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n
* @return bool
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return pg_result_seek($this->result_id, $n);
}
@@ -159,7 +159,7 @@ class CI_DB_postgre_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @param string
+ * @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
diff --git a/system/database/drivers/postgre/postgre_utility.php b/system/database/drivers/postgre/postgre_utility.php
index c95e6df0c..d3b2b9cdc 100644
--- a/system/database/drivers/postgre/postgre_utility.php
+++ b/system/database/drivers/postgre/postgre_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Postgre Utility Class
@@ -34,19 +35,32 @@
*/
class CI_DB_postgre_utility extends CI_DB_utility {
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
protected $_list_databases = 'SELECT datname FROM pg_database';
+
+ /**
+ * OPTIMIZE TABLE statement
+ *
+ * @var string
+ */
protected $_optimize_table = 'REINDEX TABLE %s';
+ // --------------------------------------------------------------------
+
/**
- * Postgre Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index 19824dbbf..8c706c242 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite Database Adapter Class
@@ -40,16 +41,23 @@
*/
class CI_DB_sqlite_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'sqlite';
- // The character used to escape with - not needed for SQLite
- protected $_escape_char = '"';
+ // --------------------------------------------------------------------
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RANDOM()', 'RANDOM()');
- protected $_random_keyword = ' Random()'; // database specific random keyword
+ // --------------------------------------------------------------------
/**
* Non-persistent database connection
@@ -116,7 +124,7 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
@@ -131,6 +139,7 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -193,8 +202,8 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -253,7 +262,7 @@ class CI_DB_sqlite_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
@@ -275,7 +284,7 @@ class CI_DB_sqlite_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return bool
*/
protected function _list_columns($table = '')
@@ -287,16 +296,41 @@ class CI_DB_sqlite_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return 'SELECT * FROM '.$this->escape_identifiers($table).' LIMIT 1';
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ if (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
+ {
+ return FALSE;
+ }
+
+ $query = $query->result_array();
+ if (empty($query))
+ {
+ return FALSE;
+ }
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]['name'];
+ $retval[$i]->type = $query[$i]['type'];
+ $retval[$i]->max_length = NULL;
+ $retval[$i]->default = $query[$i]['dflt_value'];
+ $retval[$i]->primary_key = isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0;
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
@@ -323,9 +357,9 @@ class CI_DB_sqlite_driver extends CI_DB {
*
* Generates a platform-specific replace string from the supplied data
*
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
* @return string
*/
protected function _replace($table, $keys, $values)
@@ -340,10 +374,10 @@ class CI_DB_sqlite_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this function maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
diff --git a/system/database/drivers/sqlite/sqlite_forge.php b/system/database/drivers/sqlite/sqlite_forge.php
index e02e327f3..6ad583560 100644
--- a/system/database/drivers/sqlite/sqlite_forge.php
+++ b/system/database/drivers/sqlite/sqlite_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite Forge Class
@@ -35,9 +36,32 @@
class CI_DB_sqlite_forge extends CI_DB_forge {
/**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
* Create database
*
- * @param string the database name
+ * @param string $db_name (ignored)
* @return bool
*/
public function create_database($db_name = '')
@@ -52,7 +76,7 @@ class CI_DB_sqlite_forge extends CI_DB_forge {
/**
* Drop database
*
- * @param string the database name (ignored)
+ * @param string $db_name (ignored)
* @return bool
*/
public function drop_database($db_name = '')
@@ -76,126 +100,95 @@ class CI_DB_sqlite_forge extends CI_DB_forge {
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @todo implement drop_column(), modify_column()
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = 'CREATE TABLE ';
-
- // IF NOT EXISTS added to SQLite in 3.3.0
- if ($if_not_exists === TRUE && version_compare($this->db->version(), '3.3.0', '>=') === TRUE)
+ if ($alter_type === 'DROP' OR $alter_type === 'CHANGE')
{
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- empty($attributes['CONSTRAINT']) OR $sql .= '('.$attributes['CONSTRAINT'].')';
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
+ // drop_column():
+ // BEGIN TRANSACTION;
+ // CREATE TEMPORARY TABLE t1_backup(a,b);
+ // INSERT INTO t1_backup SELECT a,b FROM t1;
+ // DROP TABLE t1;
+ // CREATE TABLE t1(a,b);
+ // INSERT INTO t1 SELECT a,b FROM t1_backup;
+ // DROP TABLE t1_backup;
+ // COMMIT;
+ return FALSE;
+ }
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
+ return parent::_alter_table($alter_type, $table, $field);
+ }
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ // --------------------------------------------------------------------
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type']
+ .$field['auto_increment']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
+ }
- if (count($primary_keys) > 0)
- {
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')';
- }
+ // --------------------------------------------------------------------
- if (is_array($keys) && count($keys) > 0)
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
{
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- $sql .= ",\n\tUNIQUE (".implode(', ', $key).')';
- }
+ case 'ENUM':
+ case 'SET':
+ $attributes['TYPE'] = 'TEXT';
+ return;
+ default: return;
}
-
- return $sql."\n)";
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute AUTO_INCREMENT
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
- *
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- /* SQLite only supports adding new columns and it does
- * NOT support the AFTER statement. Each new column will
- * be added as the last one in the table.
- */
- if ($alter_type !== 'ADD COLUMN')
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
{
- // Not supported
- return FALSE;
- }
+ $field['type'] = 'INTEGER PRIMARY KEY';
+ $field['default'] = '';
+ $field['null'] = '';
+ $field['unique'] = '';
+ $field['auto_increment'] = ' AUTOINCREMENT';
- return 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name)
- .' '.$column_definition
- .($default_value != '' ? " DEFAULT '".$default_value."'" : '')
- // If NOT NULL is specified, the field must have a DEFAULT value other than NULL
- .(($null !== NULL && $default_value !== 'NULL') ? ' NOT NULL' : ' NULL');
+ $this->primary_keys = array();
+ }
}
}
diff --git a/system/database/drivers/sqlite/sqlite_result.php b/system/database/drivers/sqlite/sqlite_result.php
index eef9787a1..889757dea 100644
--- a/system/database/drivers/sqlite/sqlite_result.php
+++ b/system/database/drivers/sqlite/sqlite_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite Result Class
@@ -97,10 +98,8 @@ class CI_DB_sqlite_result extends CI_DB_result {
{
$retval[$i] = new stdClass();
$retval[$i]->name = sqlite_field_name($this->result_id, $i);
- $retval[$i]->type = 'varchar';
- $retval[$i]->max_length = 0;
- $retval[$i]->primary_key = 0;
- $retval[$i]->default = '';
+ $retval[$i]->type = NULL;
+ $retval[$i]->max_length = NULL;
}
return $retval;
@@ -113,11 +112,12 @@ class CI_DB_sqlite_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n
* @return bool
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return sqlite_seek($this->result_id, $n);
}
@@ -143,7 +143,7 @@ class CI_DB_sqlite_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @param string
+ * @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
diff --git a/system/database/drivers/sqlite/sqlite_utility.php b/system/database/drivers/sqlite/sqlite_utility.php
index 1bcb42d9f..222d02712 100644
--- a/system/database/drivers/sqlite/sqlite_utility.php
+++ b/system/database/drivers/sqlite/sqlite_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite Utility Class
@@ -34,18 +35,16 @@
*/
class CI_DB_sqlite_utility extends CI_DB_utility {
- protected $_list_databases = FALSE;
-
/**
- * SQLite Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php
index cc35d319f..e37268aca 100644
--- a/system/database/drivers/sqlite3/sqlite3_driver.php
+++ b/system/database/drivers/sqlite3/sqlite3_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite3 Database Adapter Class
@@ -41,16 +42,23 @@
*/
class CI_DB_sqlite3_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'sqlite3';
- // The character used for escaping
- protected $_escape_char = '"';
+ // --------------------------------------------------------------------
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = ' ESCAPE \'%s\' ';
- protected $_like_escape_chr = '!';
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RANDOM()', 'RANDOM()');
- protected $_random_keyword = ' RANDOM()';
+ // --------------------------------------------------------------------
/**
* Non-persistent database connection
@@ -107,13 +115,12 @@ class CI_DB_sqlite3_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @todo Implement use of SQLite3::querySingle(), if needed
+ * @param string $sql
* @return mixed SQLite3Result object or bool
*/
protected function _execute($sql)
{
- // TODO: Implement use of SQLite3::querySingle(), if needed
-
return $this->is_write_type($sql)
? $this->conn_id->exec($sql)
: $this->conn_id->query($sql);
@@ -124,6 +131,7 @@ class CI_DB_sqlite3_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -183,8 +191,8 @@ class CI_DB_sqlite3_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -243,7 +251,7 @@ class CI_DB_sqlite3_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @param bool
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
@@ -261,7 +269,7 @@ class CI_DB_sqlite3_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
@@ -273,40 +281,56 @@ class CI_DB_sqlite3_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Returns an object with field data
*
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return 'SELECT * FROM '.$table.' LIMIT 0,1';
- }
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
- // --------------------------------------------------------------------
+ if (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
+ {
+ return FALSE;
+ }
- /**
- * The error message string
- *
- * @return string
- */
- protected function _error_message()
- {
- return $this->conn_id->lastErrorMsg();
+ $query = $query->result_array();
+ if (empty($query))
+ {
+ return FALSE;
+ }
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]['name'];
+ $retval[$i]->type = $query[$i]['type'];
+ $retval[$i]->max_length = NULL;
+ $retval[$i]->default = $query[$i]['dflt_value'];
+ $retval[$i]->primary_key = isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0;
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
/**
- * The error message number
+ * Error
*
- * @return int
+ * Returns an array containing code and message of the last
+ * database error that has occured.
+ *
+ * @return array
*/
- protected function _error_number()
+ public function error()
{
- return $this->conn_id->lastErrorCode();
+ return array('code' => $this->conn_id->lastErrorCode(), 'message' => $this->conn_id->lastErrorMsg());
}
// --------------------------------------------------------------------
@@ -316,9 +340,9 @@ class CI_DB_sqlite3_driver extends CI_DB {
*
* Generates a platform-specific replace string from the supplied data
*
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
* @return string
*/
protected function _replace($table, $keys, $values)
@@ -333,10 +357,10 @@ class CI_DB_sqlite3_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command, then,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
diff --git a/system/database/drivers/sqlite3/sqlite3_forge.php b/system/database/drivers/sqlite3/sqlite3_forge.php
index 6a76ba929..e9b91e972 100644
--- a/system/database/drivers/sqlite3/sqlite3_forge.php
+++ b/system/database/drivers/sqlite3/sqlite3_forge.php
@@ -1,8 +1,8 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
- * An open source application development framework for PHP 5.1.6 or newer
+ * An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite3 Forge Class
@@ -35,9 +36,43 @@
class CI_DB_sqlite3_forge extends CI_DB_forge {
/**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param object &$db Database object
+ * @return void
+ */
+ public function __construct(&$db)
+ {
+ parent::__construct($db);
+
+ if (version_compare($this->db->version(), '3.3', '<'))
+ {
+ $this->create_table_if = FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Create database
*
- * @param string the database name
+ * @param string $db_name
* @return bool
*/
public function create_database($db_name = '')
@@ -52,7 +87,7 @@ class CI_DB_sqlite3_forge extends CI_DB_forge {
/**
* Drop database
*
- * @param string the database name (ignored)
+ * @param string $db_name (ignored)
* @return bool
*/
public function drop_database($db_name = '')
@@ -84,125 +119,95 @@ class CI_DB_sqlite3_forge extends CI_DB_forge {
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @todo implement drop_column(), modify_column()
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = 'CREATE TABLE ';
-
- // IF NOT EXISTS added to SQLite in 3.3.0
- if ($if_not_exists === TRUE && version_compare($this->db->version(), '3.3.0', '>=') === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
+ if ($alter_type === 'DROP' OR $alter_type === 'CHANGE')
{
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- empty($attributes['CONSTRAINT']) OR $sql .= '('.$attributes['CONSTRAINT'].')';
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
+ // drop_column():
+ // BEGIN TRANSACTION;
+ // CREATE TEMPORARY TABLE t1_backup(a,b);
+ // INSERT INTO t1_backup SELECT a,b FROM t1;
+ // DROP TABLE t1;
+ // CREATE TABLE t1(a,b);
+ // INSERT INTO t1 SELECT a,b FROM t1_backup;
+ // DROP TABLE t1_backup;
+ // COMMIT;
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
+ return FALSE;
+ }
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
+ return parent::_alter_table($alter_type, $table, $field);
+ }
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ // --------------------------------------------------------------------
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type']
+ .$field['auto_increment']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
+ }
- if (count($primary_keys) > 0)
- {
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')';
- }
+ // --------------------------------------------------------------------
- if (is_array($keys) && count($keys) > 0)
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
{
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- $sql .= ",\n\tUNIQUE (".implode(', ', $key).')';
- }
+ case 'ENUM':
+ case 'SET':
+ $attributes['TYPE'] = 'TEXT';
+ return;
+ default: return;
}
-
- return $sql."\n)";
}
// --------------------------------------------------------------------
/**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Field attribute AUTO_INCREMENT
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- /* SQLite only supports adding new columns and it does
- * NOT support the AFTER statement. Each new column will
- * be added as the last one in the table.
- */
- if ($alter_type !== 'ADD COLUMN')
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
{
- // Not supported
- return FALSE;
- }
+ $field['type'] = 'INTEGER PRIMARY KEY';
+ $field['default'] = '';
+ $field['null'] = '';
+ $field['unique'] = '';
+ $field['auto_increment'] = ' AUTOINCREMENT';
- return 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name)
- .' '.$column_definition
- .($default_value !== '' ? ' DEFAULT '.$default_value : '')
- // If NOT NULL is specified, the field must have a DEFAULT value other than NULL
- .(($null !== NULL && $default_value !== 'NULL') ? ' NOT NULL' : ' NULL');
+ $this->primary_keys = array();
+ }
}
}
diff --git a/system/database/drivers/sqlite3/sqlite3_result.php b/system/database/drivers/sqlite3/sqlite3_result.php
index 8e9b9c15f..69c42002c 100644
--- a/system/database/drivers/sqlite3/sqlite3_result.php
+++ b/system/database/drivers/sqlite3/sqlite3_result.php
@@ -1,8 +1,8 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
- * An open source application development framework for PHP 5.1.6 or newer
+ * An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite3 Result Class
@@ -37,9 +38,6 @@
*/
class CI_DB_sqlite3_result extends CI_DB_result {
- // num_fields() might be called multiple times, so we'll use this one to cache it's result
- protected $_num_fields;
-
/**
* Number of fields in the result set
*
@@ -47,9 +45,7 @@ class CI_DB_sqlite3_result extends CI_DB_result {
*/
public function num_fields()
{
- return ( ! is_int($this->_num_fields))
- ? $this->_num_fields = $this->result_id->numColumns()
- : $this->_num_fields;
+ return $this->result_id->numColumns();
}
// --------------------------------------------------------------------
@@ -83,15 +79,24 @@ class CI_DB_sqlite3_result extends CI_DB_result {
*/
public function field_data()
{
+ static $data_types = array(
+ SQLITE3_INTEGER => 'integer',
+ SQLITE3_FLOAT => 'float',
+ SQLITE3_TEXT => 'text',
+ SQLITE3_BLOB => 'blob',
+ SQLITE3_NULL => 'null'
+ );
+
$retval = array();
for ($i = 0, $c = $this->num_fields(); $i < $this->num_fields(); $i++)
{
$retval[$i] = new stdClass();
$retval[$i]->name = $this->result_id->columnName($i);
- $retval[$i]->type = 'varchar';
- $retval[$i]->max_length = 0;
- $retval[$i]->primary_key = 0;
- $retval[$i]->default = '';
+
+ $type = $this->result_id->columnType($i);
+ $retval[$i]->type = isset($data_types[$type]) ? $data_types[$type] : $type;
+
+ $retval[$i]->max_length = NULL;
}
return $retval;
@@ -134,7 +139,7 @@ class CI_DB_sqlite3_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @param string
+ * @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
@@ -165,14 +170,15 @@ class CI_DB_sqlite3_result extends CI_DB_result {
*
* Moves the internal pointer to the desired offset. We call
* this internally before fetching results to make sure the
- * result set starts at zero
+ * result set starts at zero.
*
+ * @param int $n (ignored)
* @return array
*/
- protected function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
// Only resetting to the start of the result set is supported
- return $this->result_id->reset();
+ return ($n > 0) ? FALSE : $this->result_id->reset();
}
}
diff --git a/system/database/drivers/sqlite3/sqlite3_utility.php b/system/database/drivers/sqlite3/sqlite3_utility.php
index 965c838e5..c7736cc6d 100644
--- a/system/database/drivers/sqlite3/sqlite3_utility.php
+++ b/system/database/drivers/sqlite3/sqlite3_utility.php
@@ -1,8 +1,8 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
- * An open source application development framework for PHP 5.1.6 or newer
+ * An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite3 Utility Class
@@ -34,18 +35,16 @@
*/
class CI_DB_sqlite3_utility extends CI_DB_utility {
- protected $_list_databases = FALSE;
-
/**
- * SQLite Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
protected function _backup($params = array())
{
// Not supported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php
index 8bd18bd76..ee9823ed1 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 2.0.3
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLSRV Database Adapter Class
@@ -40,36 +41,52 @@
*/
class CI_DB_sqlsrv_driver extends CI_DB {
+ /**
+ * Database driver
+ *
+ * @var string
+ */
public $dbdriver = 'sqlsrv';
- // The character used for escaping
- protected $_escape_char = '"';
-
- // clause and character used for LIKE escape sequences
- protected $_like_escape_str = " ESCAPE '%s' ";
- protected $_like_escape_chr = '!';
+ // --------------------------------------------------------------------
- protected $_random_keyword = ' NEWID()';
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('NEWID()', 'RAND(%d)');
- // SQLSRV-specific properties
+ /**
+ * Quoted identifier flag
+ *
+ * Whether to use SQL-92 standard quoted identifier
+ * (double quotes) or brackets for identifier escaping.
+ *
+ * @var bool
+ */
protected $_quoted_identifier = TRUE;
+ // --------------------------------------------------------------------
+
/**
- * Non-persistent database connection
+ * Database connection
*
+ * @param bool $pooling
* @return resource
*/
public function db_connect($pooling = FALSE)
{
- // Check for a UTF-8 charset being passed as CI's default 'utf8'.
- $character_set = (0 === strcasecmp('utf8', $this->char_set)) ? 'UTF-8' : $this->char_set;
+ $charset = in_array(strtolower($this->char_set), array('utf-8', 'utf8'), TRUE)
+ ? 'UTF-8' : SQLSRV_ENC_CHAR;
$connection = array(
'UID' => empty($this->username) ? '' : $this->username,
'PWD' => empty($this->password) ? '' : $this->password,
'Database' => $this->database,
- 'ConnectionPooling' => $pooling ? 1 : 0,
- 'CharacterSet' => $character_set,
+ 'ConnectionPooling' => ($pooling === TRUE) ? 1 : 0,
+ 'CharacterSet' => $charset,
+ 'Encrypt' => ($this->encrypt === TRUE) ? 1 : 0,
'ReturnDatesAsStrings' => 1
);
@@ -108,7 +125,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
/**
* Select the database
*
- * @param string database name
+ * @param string $database
* @return bool
*/
public function db_select($database = '')
@@ -118,7 +135,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
$database = $this->database;
}
- if ($this->_execute('USE '.$database))
+ if ($this->_execute('USE '.$this->escape_identifiers($database)))
{
$this->database = $database;
return TRUE;
@@ -132,7 +149,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
/**
* Execute the query
*
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
protected function _execute($sql)
@@ -147,6 +164,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
/**
* Begin Transaction
*
+ * @param bool $test_mode
* @return bool
*/
public function trans_begin($test_mode = FALSE)
@@ -206,8 +224,8 @@ class CI_DB_sqlsrv_driver extends CI_DB {
/**
* Escape String
*
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
+ * @param string $str
+ * @param bool $like Whether or not the string will be used in a LIKE condition
* @return string
*/
public function escape_str($str, $like = FALSE)
@@ -225,7 +243,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*/
public function affected_rows()
{
- return sqlrv_rows_affected($this->result_id);
+ return sqlsrv_rows_affected($this->result_id);
}
// --------------------------------------------------------------------
@@ -257,8 +275,12 @@ class CI_DB_sqlsrv_driver extends CI_DB {
{
return $this->data_cache['version'];
}
+ elseif ( ! $this->conn_id)
+ {
+ $this->initialize();
+ }
- if (($info = sqlsrv_server_info($this->conn_id)) === FALSE)
+ if ( ! $this->conn_id OR ($info = sqlsrv_server_info($this->conn_id)) === FALSE)
{
return FALSE;
}
@@ -274,7 +296,7 @@ class CI_DB_sqlsrv_driver extends CI_DB {
* Generates a platform-specific query string so that the table names can be fetched
*
* @param bool
- * @return string
+ * @return string $prefix_limit
*/
protected function _list_tables($prefix_limit = FALSE)
{
@@ -298,27 +320,52 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _list_columns($table = '')
{
- return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$table."'";
+ return 'SELECT COLUMN_NAME
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
}
// --------------------------------------------------------------------
/**
- * Field data query
+ * Returns an object with field data
*
- * Generates a platform-specific query so that the column data can be retrieved
- *
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return array
*/
- protected function _field_data($table)
+ public function field_data($table = '')
{
- return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table);
+ if ($table === '')
+ {
+ return ($this->db_debug) ? $this->display_error('db_field_param_missing') : FALSE;
+ }
+
+ $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
+
+ if (($query = $this->query($sql)) === FALSE)
+ {
+ return FALSE;
+ }
+ $query = $query->result_object();
+
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
+ $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;
+ $retval[$i]->default = $query[$i]->COLUMN_DEFAULT;
+ }
+
+ return $retval;
}
// --------------------------------------------------------------------
@@ -362,49 +409,19 @@ class CI_DB_sqlsrv_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @param array
- * @return string
- */
- protected function _from_tables($tables)
- {
- return is_array($tables) ? implode(', ', $tables) : $tables;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Update statement
*
* Generates a platform-specific update string from the supplied data
*
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @param array the orderby clause (ignored)
- * @param array the limit clause (ignored)
- * @param array the like clause
+ * @param string $table
+ * @param array $values
* @return string
*/
- protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE, $like = array())
+ protected function _update($table, $values)
{
- foreach ($values as $key => $val)
- {
- $valstr[] = $key.' = '.$val;
- }
-
- $where = empty($where) ? '' : ' WHERE '.implode(' ', $where);
-
- if ( ! empty($like))
- {
- $where .= ($where === '' ? ' WHERE ' : ' AND ').implode(' ', $like);
- }
-
- return 'UPDATE '.$table.' SET '.implode(', ', $valstr).$where;
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
@@ -414,10 +431,10 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*
* Generates a platform-specific truncate string from the supplied data
*
- * If the database does not support the truncate() command,
+ * If the database does not support the TRUNCATE statement,
* then this method maps to 'DELETE FROM table'
*
- * @param string the table name
+ * @param string $table
* @return string
*/
protected function _truncate($table)
@@ -432,60 +449,70 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*
* Generates a platform-specific delete string from the supplied data
*
- * @param string the table name
- * @param array the where clause
- * @param array the like clause
- * @param string the limit clause
+ * @param string $table
* @return string
*/
- protected function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _delete($table)
{
- $conditions = array();
-
- empty($where) OR $conditions[] = implode(' ', $where);
- empty($like) OR $conditions[] = implode(' ', $like);
-
- $conditions = (count($conditions) > 0) ? ' WHERE '.implode(' AND ', $conditions) : '';
+ if ($this->qb_limit)
+ {
+ return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';
+ }
- return ($limit)
- ? 'WITH ci_delete AS (SELECT TOP '.$limit.' * FROM '.$table.$conditions.') DELETE FROM ci_delete'
- : 'DELETE FROM '.$table.$conditions;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * LIMIT
*
* Generates a platform-specific LIMIT clause
*
- * @param string the sql query string
- * @param int the number of rows to limit the query to
- * @param int the offset value
+ * @param string $sql SQL Query
* @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _limit($sql)
{
// As of SQL Server 2012 (11.0.*) OFFSET is supported
if (version_compare($this->version(), '11', '>='))
{
- return $sql.' OFFSET '.(int) $offset.' ROWS FETCH NEXT '.(int) $limit.' ROWS ONLY';
+ return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';
}
- $limit = $offset + $limit;
+ $limit = $this->qb_offset + $this->qb_limit;
// An ORDER BY clause is required for ROW_NUMBER() to work
- if ($offset && ! empty($this->qb_orderby))
+ if ($this->qb_offset && ! empty($this->qb_orderby))
{
- $orderby = 'ORDER BY '.implode(', ', $this->qb_orderby);
+ $orderby = $this->_compile_order_by();
// We have to strip the ORDER BY clause
- $sql = trim(substr($sql, 0, strrpos($sql, 'ORDER BY '.$orderby)));
-
- return 'SELECT '.(count($this->qb_select) === 0 ? '*' : implode(', ', $this->qb_select))." FROM (\n"
- .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.$orderby.') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)
- ."\n) ".$this->escape_identifiers('CI_subquery')
- ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.((int) $offset + 1).' AND '.$limit;
+ $sql = trim(substr($sql, 0, strrpos($sql, $orderby)));
+
+ // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results
+ if (count($this->qb_select) === 0)
+ {
+ $select = '*'; // Inevitable
+ }
+ else
+ {
+ // Use only field names and their aliases, everything else is out of our scope.
+ $select = array();
+ $field_regexp = ($this->_quoted_identifier)
+ ? '("[^\"]+")' : '(\[[^\]]+\])';
+ for ($i = 0, $c = count($this->qb_select); $i < $c; $i++)
+ {
+ $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)
+ ? $m[1] : $this->qb_select[$i];
+ }
+ $select = implode(', ', $select);
+ }
+
+ return 'SELECT '.$select." FROM (\n\n"
+ .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)
+ ."\n\n) ".$this->escape_identifiers('CI_subquery')
+ ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;
}
return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
@@ -494,6 +521,29 @@ class CI_DB_sqlsrv_driver extends CI_DB {
// --------------------------------------------------------------------
/**
+ * Insert batch statement
+ *
+ * Generates a platform-specific insert string from the supplied data.
+ *
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string|bool
+ */
+ protected function _insert_batch($table, $keys, $values)
+ {
+ // Multiple-value inserts are only supported as of SQL Server 2008
+ if (version_compare($this->version(), '10', '>='))
+ {
+ return parent::_insert_batch($table, $keys, $values);
+ }
+
+ return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Close DB Connection
*
* @return void
diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php
index ccdb36929..da8f68c56 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_forge.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 2.0.3
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLSRV Forge Class
@@ -34,124 +35,99 @@
*/
class CI_DB_sqlsrv_forge extends CI_DB_forge {
- protected $_drop_table = 'DROP TABLE %s';
-
/**
- * Create Table
+ * CREATE TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return string
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = ($if_not_exists === TRUE)
- ? "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'".$table."') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\n"
- : '';
-
- $sql .= 'CREATE TABLE '.$this->db->escape_identifiers($table).' (';
-
- $current_field_count = 0;
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- if (stripos($attributes['TYPE'], 'INT') === FALSE && ! empty($attributes['CONSTRAINT']))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
+ protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attribues['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ // --------------------------------------------------------------------
- if (count($primary_keys) > 0)
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
{
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')';
+ return parent::_alter_table($alter_type, $table, $field);
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->escape_identifiers($key));
-
- $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')';
- }
+ $sqls[] = $sql.$this->_process_column($field[$i]);
}
- return $sql."\n)";
+ return $sqls;
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute TYPE
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Performs a data type mapping between different databases.
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_type(&$attributes)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
+ switch (strtoupper($attributes['TYPE']))
{
- return $sql;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
}
+ }
- return $sql.' '.$column_definition
- .($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field != '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' IDENTITY(1,1)';
+ }
}
}
diff --git a/system/database/drivers/sqlsrv/sqlsrv_result.php b/system/database/drivers/sqlsrv/sqlsrv_result.php
index fb7a68647..b084b84cd 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_result.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_result.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 1.0
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLSRV Result Class
@@ -93,16 +94,12 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
public function field_data()
{
$retval = array();
- foreach (sqlsrv_field_metadata($this->result_id) as $offset => $field)
+ foreach (sqlsrv_field_metadata($this->result_id) as $i => $field)
{
- $F = new stdClass();
- $F->name = $field['Name'];
- $F->type = $field['Type'];
- $F->max_length = $field['Size'];
- $F->primary_key = 0;
- $F->default = '';
-
- $retval[] = $F;
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $field['Name'];
+ $retval[$i]->type = $field['Type'];
+ $retval[$i]->max_length = $field['Size'];
}
return $retval;
@@ -145,7 +142,7 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @param string
+ * @param string $class_name
* @return object
*/
protected function _fetch_object($class_name = 'stdClass')
diff --git a/system/database/drivers/sqlsrv/sqlsrv_utility.php b/system/database/drivers/sqlsrv/sqlsrv_utility.php
index d518cc15a..2bc7f9e03 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_utility.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_utility.php
@@ -1,4 +1,4 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+<?php
/**
* CodeIgniter
*
@@ -24,6 +24,7 @@
* @since Version 2.0.3
* @filesource
*/
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLSRV Utility Class
@@ -34,19 +35,32 @@
*/
class CI_DB_sqlsrv_utility extends CI_DB_utility {
+ /**
+ * List databases statement
+ *
+ * @var string
+ */
protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases
+
+ /**
+ * OPTIMIZE TABLE statement
+ *
+ * @var string
+ */
protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE';
+ // --------------------------------------------------------------------
+
/**
- * SQLSRV Export
+ * Export
*
- * @param array Preferences
+ * @param array $params Preferences
* @return bool
*/
protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}