summaryrefslogtreecommitdiffstats
path: root/system/database/drivers
diff options
context:
space:
mode:
authorFlorian Pritz <bluewind@xinu.at>2017-09-09 16:05:22 +0200
committerFlorian Pritz <bluewind@xinu.at>2017-09-09 16:05:22 +0200
commit27639d64d06b62f237bbde253c46cd28fdce8884 (patch)
tree7a2f00cfd44cfcdfe6cb1abc1cfc0675632948c4 /system/database/drivers
parent9c5bfbee5b42ea50a5611c537b8dbf01d7a64f79 (diff)
parent6c7a4266410070d30f8f6bcdf9c9e67f3d6478e3 (diff)
Merge tag '3.1.5' into dev-ci3
Signed-off-by: Florian Pritz <bluewind@xinu.at>
Diffstat (limited to 'system/database/drivers')
-rw-r--r--system/database/drivers/cubrid/cubrid_driver.php713
-rw-r--r--system/database/drivers/cubrid/cubrid_forge.php362
-rw-r--r--system/database/drivers/cubrid/cubrid_result.php147
-rw-r--r--system/database/drivers/cubrid/cubrid_utility.php107
-rw-r--r--system/database/drivers/cubrid/index.html3
-rw-r--r--system/database/drivers/ibase/ibase_driver.php413
-rw-r--r--system/database/drivers/ibase/ibase_forge.php251
-rw-r--r--system/database/drivers/ibase/ibase_result.php161
-rw-r--r--system/database/drivers/ibase/ibase_utility.php69
-rw-r--r--system/database/drivers/ibase/index.html11
-rw-r--r--system/database/drivers/index.html3
-rw-r--r--system/database/drivers/mssql/index.html3
-rw-r--r--system/database/drivers/mssql/mssql_driver.php677
-rw-r--r--system/database/drivers/mssql/mssql_forge.php273
-rw-r--r--system/database/drivers/mssql/mssql_result.php129
-rw-r--r--system/database/drivers/mssql/mssql_utility.php105
-rw-r--r--system/database/drivers/mysql/index.html3
-rw-r--r--system/database/drivers/mysql/mysql_driver.php743
-rw-r--r--system/database/drivers/mysql/mysql_forge.php336
-rw-r--r--system/database/drivers/mysql/mysql_result.php135
-rw-r--r--system/database/drivers/mysql/mysql_utility.php157
-rw-r--r--system/database/drivers/mysqli/index.html3
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php798
-rw-r--r--system/database/drivers/mysqli/mysqli_forge.php322
-rw-r--r--system/database/drivers/mysqli/mysqli_result.php130
-rw-r--r--system/database/drivers/mysqli/mysqli_utility.php230
-rw-r--r--system/database/drivers/oci8/index.html3
-rw-r--r--system/database/drivers/oci8/oci8_driver.php824
-rw-r--r--system/database/drivers/oci8/oci8_forge.php297
-rw-r--r--system/database/drivers/oci8/oci8_result.php192
-rw-r--r--system/database/drivers/oci8/oci8_utility.php103
-rw-r--r--system/database/drivers/odbc/index.html3
-rw-r--r--system/database/drivers/odbc/odbc_driver.php616
-rw-r--r--system/database/drivers/odbc/odbc_forge.php282
-rw-r--r--system/database/drivers/odbc/odbc_result.php242
-rw-r--r--system/database/drivers/odbc/odbc_utility.php120
-rw-r--r--system/database/drivers/pdo/index.html3
-rw-r--r--system/database/drivers/pdo/pdo_driver.php774
-rw-r--r--system/database/drivers/pdo/pdo_forge.php283
-rw-r--r--system/database/drivers/pdo/pdo_result.php145
-rw-r--r--system/database/drivers/pdo/pdo_utility.php118
-rw-r--r--system/database/drivers/pdo/subdrivers/index.html11
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_4d_driver.php200
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_4d_forge.php217
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php209
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php230
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php337
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php149
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php279
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php237
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php244
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php154
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_informix_driver.php309
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_informix_forge.php163
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php374
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php256
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_oci_driver.php326
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_oci_forge.php176
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php229
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php70
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php384
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php210
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php219
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php238
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php369
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php149
-rw-r--r--system/database/drivers/postgre/index.html3
-rw-r--r--system/database/drivers/postgre/postgre_driver.php736
-rw-r--r--system/database/drivers/postgre/postgre_forge.php354
-rw-r--r--system/database/drivers/postgre/postgre_result.php113
-rw-r--r--system/database/drivers/postgre/postgre_utility.php102
-rw-r--r--system/database/drivers/sqlite/index.html3
-rw-r--r--system/database/drivers/sqlite/sqlite_driver.php574
-rw-r--r--system/database/drivers/sqlite/sqlite_forge.php314
-rw-r--r--system/database/drivers/sqlite/sqlite_result.php133
-rw-r--r--system/database/drivers/sqlite/sqlite_utility.php113
-rw-r--r--system/database/drivers/sqlite3/index.html11
-rw-r--r--system/database/drivers/sqlite3/sqlite3_driver.php350
-rw-r--r--system/database/drivers/sqlite3/sqlite3_forge.php225
-rw-r--r--system/database/drivers/sqlite3/sqlite3_result.php194
-rw-r--r--system/database/drivers/sqlite3/sqlite3_utility.php61
-rw-r--r--system/database/drivers/sqlsrv/index.html3
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_driver.php668
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_forge.php268
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_result.php150
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_utility.php101
86 files changed, 12418 insertions, 8086 deletions
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
index 13bafa3ed..6e8aff7c6 100644
--- a/system/database/drivers/cubrid/cubrid_driver.php
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -1,108 +1,135 @@
-<?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
*
- * @package CodeIgniter
- * @author Esen Sagynov
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 2.0.2
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 2.1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CUBRID Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
* @subpackage Drivers
* @category Database
* @author Esen Sagynov
- * @link http://codeigniter.com/user_guide/database/
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_cubrid_driver extends CI_DB {
- // Default CUBRID Broker port. Will be used unless user
- // explicitly specifies another one.
- const DEFAULT_PORT = 33000;
+ /**
+ * Database driver
+ *
+ * @var string
+ */
+ public $dbdriver = 'cubrid';
- var $dbdriver = 'cubrid';
+ /**
+ * Auto-commit flag
+ *
+ * @var bool
+ */
+ public $auto_commit = TRUE;
- // The character used for escaping - no need in CUBRID
- var $_escape_char = '';
+ // --------------------------------------------------------------------
- // clause and character used for LIKE escape sequences - not used in CUBRID
- var $_like_escape_str = '';
- var $_like_escape_chr = '';
+ /**
+ * Identifier escape character
+ *
+ * @var string
+ */
+ protected $_escape_char = '`';
/**
- * 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.
+ * ORDER BY random keyword
+ *
+ * @var array
*/
- var $_count_string = 'SELECT COUNT(*) AS ';
- var $_random_keyword = ' RAND()'; // database specific random keyword
+ protected $_random_keyword = array('RANDOM()', 'RANDOM(%d)');
+
+ // --------------------------------------------------------------------
/**
- * Non-persistent database connection
+ * Class constructor
*
- * @access private called by the base class
- * @return resource
+ * @param array $params
+ * @return void
*/
- function db_connect()
+ public function __construct($params)
{
- // If no port is defined by the user, use the default value
- if ($this->port == '')
- {
- $this->port = self::DEFAULT_PORT;
- }
+ parent::__construct($params);
- $conn = cubrid_connect($this->hostname, $this->port, $this->database, $this->username, $this->password);
-
- if ($conn)
+ if (preg_match('/^CUBRID:[^:]+(:[0-9][1-9]{0,4})?:[^:]+:[^:]*:[^:]*:(\?.+)?$/', $this->dsn, $matches))
{
- // Check if a user wants to run queries in dry, i.e. run the
- // queries but not commit them.
- if (isset($this->auto_commit) && ! $this->auto_commit)
- {
- cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_FALSE);
- }
- else
+ if (stripos($matches[2], 'autocommit=off') !== FALSE)
{
- cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_TRUE);
- $this->auto_commit = TRUE;
+ $this->auto_commit = FALSE;
}
}
-
- return $conn;
+ else
+ {
+ // If no port is defined by the user, use the default value
+ empty($this->port) OR $this->port = 33000;
+ }
}
// --------------------------------------------------------------------
/**
- * Persistent database connection
- * In CUBRID persistent DB connection is supported natively in CUBRID
- * engine which can be configured in the CUBRID Broker configuration
- * file by setting the CCI_PCONNECT parameter to ON. In that case, all
- * connections established between the client application and the
- * server will become persistent. This is calling the same
- * @cubrid_connect function will establish persisten connection
- * considering that the CCI_PCONNECT is ON.
+ * Non-persistent database connection
*
- * @access private called by the base class
+ * @param bool $persistent
* @return resource
*/
- function db_pconnect()
+ public function db_connect($persistent = FALSE)
{
- return $this->db_connect();
+ if (preg_match('/^CUBRID:[^:]+(:[0-9][1-9]{0,4})?:[^:]+:([^:]*):([^:]*):(\?.+)?$/', $this->dsn, $matches))
+ {
+ $func = ($persistent !== TRUE) ? 'cubrid_connect_with_url' : 'cubrid_pconnect_with_url';
+ return ($matches[2] === '' && $matches[3] === '' && $this->username !== '' && $this->password !== '')
+ ? $func($this->dsn, $this->username, $this->password)
+ : $func($this->dsn);
+ }
+
+ $func = ($persistent !== TRUE) ? 'cubrid_connect' : 'cubrid_pconnect';
+ return ($this->username !== '')
+ ? $func($this->hostname, $this->port, $this->database, $this->username, $this->password)
+ : $func($this->hostname, $this->port, $this->database);
}
// --------------------------------------------------------------------
@@ -113,10 +140,9 @@ class CI_DB_cubrid_driver extends CI_DB {
* Keep / reestablish the db connection if no queries have been
* sent for a length of time exceeding the server's idle timeout
*
- * @access public
* @return void
*/
- function reconnect()
+ public function reconnect()
{
if (cubrid_ping($this->conn_id) === FALSE)
{
@@ -127,54 +153,20 @@ class CI_DB_cubrid_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Select the database
- *
- * @access private called by the base class
- * @return resource
- */
- function db_select()
- {
- // In CUBRID there is no need to select a database as the database
- // is chosen at the connection time.
- // So, to determine if the database is "selected", all we have to
- // do is ping the server and return that value.
- return cubrid_ping($this->conn_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Set client character set
- *
- * @access public
- * @param string
- * @param string
- * @return resource
- */
- function db_set_charset($charset, $collation)
- {
- // In CUBRID, there is no need to set charset or collation.
- // This is why returning true will allow the application continue
- // its normal process.
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Version number query string
+ * Database version number
*
- * @access public
* @return string
*/
- function _version()
+ public function version()
{
- // To obtain the CUBRID Server version, no need to run the SQL query.
- // CUBRID PHP API provides a function to determin this value.
- // This is why we also need to add 'cubrid' value to the list of
- // $driver_version_exceptions array in DB_driver class in
- // version() function.
- return cubrid_get_server_info($this->conn_id);
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+
+ return ( ! $this->conn_id OR ($version = cubrid_get_server_info($this->conn_id)) === FALSE)
+ ? FALSE
+ : $this->data_cache['version'] = $version;
}
// --------------------------------------------------------------------
@@ -182,31 +174,12 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Execute the query
*
- * @access private called by the base class
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
- function _execute($sql)
+ protected function _execute($sql)
{
- $sql = $this->_prep_query($sql);
- return @cubrid_query($sql, $this->conn_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Prep the query
- *
- * If needed, each database adapter can prep the query string
- *
- * @access private called by execute()
- * @param string an SQL query
- * @return string
- */
- function _prep_query($sql)
- {
- // No need to prepare
- return $sql;
+ return cubrid_query($sql, $this->conn_id);
}
// --------------------------------------------------------------------
@@ -214,30 +187,17 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Begin Transaction
*
- * @access public
* @return bool
*/
- function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- if ( ! $this->trans_enabled)
+ if (($autocommit = cubrid_get_autocommit($this->conn_id)) === NULL)
{
- return TRUE;
+ return FALSE;
}
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
-
- if (cubrid_get_autocommit($this->conn_id))
+ elseif ($autocommit === TRUE)
{
- cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_FALSE);
+ return cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_FALSE);
}
return TRUE;
@@ -248,27 +208,18 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Commit Transaction
*
- * @access public
* @return bool
*/
- function trans_commit()
+ protected function _trans_commit()
{
- if ( ! $this->trans_enabled)
+ if ( ! cubrid_commit($this->conn_id))
{
- return TRUE;
+ return FALSE;
}
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- cubrid_commit($this->conn_id);
-
if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))
{
- cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
+ return cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
}
return TRUE;
@@ -279,24 +230,15 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Rollback Transaction
*
- * @access public
* @return bool
*/
- function trans_rollback()
+ protected function _trans_rollback()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ( ! cubrid_rollback($this->conn_id))
{
- return TRUE;
+ return FALSE;
}
- cubrid_rollback($this->conn_id);
-
if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))
{
cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
@@ -308,41 +250,14 @@ class CI_DB_cubrid_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Escape String
+ * Platform-dependent string escape
*
- * @access public
* @param string
- * @param bool whether or not the string will be used in a LIKE condition
* @return string
*/
- function escape_str($str, $like = FALSE)
+ protected function _escape_str($str)
{
- if (is_array($str))
- {
- foreach ($str as $key => $val)
- {
- $str[$key] = $this->escape_str($val, $like);
- }
-
- return $str;
- }
-
- if (function_exists('cubrid_real_escape_string') AND is_resource($this->conn_id))
- {
- $str = cubrid_real_escape_string($str, $this->conn_id);
- }
- else
- {
- $str = addslashes($str);
- }
-
- // escape LIKE condition wildcards
- if ($like === TRUE)
- {
- $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str);
- }
-
- return $str;
+ return cubrid_real_escape_string($str, $this->conn_id);
}
// --------------------------------------------------------------------
@@ -350,12 +265,11 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Affected Rows
*
- * @access public
- * @return integer
+ * @return int
*/
- function affected_rows()
+ public function affected_rows()
{
- return @cubrid_affected_rows($this->conn_id);
+ return cubrid_affected_rows();
}
// --------------------------------------------------------------------
@@ -363,43 +277,11 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Insert ID
*
- * @access public
- * @return integer
+ * @return int
*/
- function insert_id()
+ public function insert_id()
{
- return @cubrid_insert_id($this->conn_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified table
- *
- * @access public
- * @param string
- * @return string
- */
- function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
-
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
+ return cubrid_insert_id($this->conn_id);
}
// --------------------------------------------------------------------
@@ -409,17 +291,16 @@ class CI_DB_cubrid_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @access private
- * @param boolean
+ * @param bool $prefix_limit
* @return string
*/
- function _list_tables($prefix_limit = FALSE)
+ protected function _list_tables($prefix_limit = FALSE)
{
- $sql = "SHOW TABLES";
+ $sql = 'SHOW TABLES';
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- $sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%'";
+ return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
}
return $sql;
@@ -432,343 +313,81 @@ class CI_DB_cubrid_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @access public
- * @param string the table name
- * @return string
- */
- function _list_columns($table = '')
- {
- return "SHOW COLUMNS FROM ".$this->_protect_identifiers($table, TRUE, NULL, FALSE);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
- *
- * @access public
- * @param string the table name
- * @return object
- */
- function _field_data($table)
- {
- return "SELECT * FROM ".$table." LIMIT 1";
- }
-
- // --------------------------------------------------------------------
-
- /**
- * The error message string
- *
- * @access private
+ * @param string $table
* @return string
*/
- function _error_message()
+ protected function _list_columns($table = '')
{
- return cubrid_error($this->conn_id);
+ return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
}
// --------------------------------------------------------------------
/**
- * The error message number
+ * Returns an object with field data
*
- * @access private
- * @return integer
+ * @param string $table
+ * @return array
*/
- function _error_number()
+ public function field_data($table)
{
- return cubrid_errno($this->conn_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Escape the SQL Identifiers
- *
- * This function escapes column and table names
- *
- * @access private
- * @param string
- * @return string
- */
- function _escape_identifiers($item)
- {
- if ($this->_escape_char == '')
- {
- return $item;
- }
-
- foreach ($this->_reserved_identifiers as $id)
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
{
- if (strpos($item, '.'.$id) !== FALSE)
- {
- $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
- }
+ return FALSE;
}
+ $query = $query->result_object();
- if (strpos($item, '.') !== FALSE)
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
{
- $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
- }
- else
- {
- $str = $this->_escape_char.$item.$this->_escape_char;
- }
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->Field;
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
- }
-
- // --------------------------------------------------------------------
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
- /**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @access public
- * @param type
- * @return type
- */
- function _from_tables($tables)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
+ $retval[$i]->default = $query[$i]->Default;
+ $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
}
- return '('.implode(', ', $tables).')';
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Insert statement
- *
- * Generates a platform-specific insert string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
- */
- function _insert($table, $keys, $values)
- {
- return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")";
- }
-
- // --------------------------------------------------------------------
-
-
- /**
- * Replace statement
- *
- * Generates a platform-specific replace string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
- */
- function _replace($table, $keys, $values)
- {
- return "REPLACE INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")";
+ return $retval;
}
// --------------------------------------------------------------------
/**
- * Insert_batch statement
+ * Error
*
- * Generates a platform-specific insert string from the supplied data
+ * Returns an array containing code and message of the last
+ * database error that has occurred.
*
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
+ * @return array
*/
- function _insert_batch($table, $keys, $values)
+ public function error()
{
- return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES ".implode(', ', $values);
+ return array('code' => cubrid_errno($this->conn_id), 'message' => cubrid_error($this->conn_id));
}
// --------------------------------------------------------------------
-
/**
- * Update statement
+ * FROM tables
*
- * Generates a platform-specific update string from the supplied data
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
*
- * @access public
- * @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
* @return string
*/
- function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
+ protected function _from_tables()
{
- foreach ($values as $key => $val)
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
{
- $valstr[] = sprintf('"%s" = %s', $key, $val);
+ return '('.implode(', ', $this->qb_from).')';
}
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
- $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
- $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
- $sql .= $orderby.$limit;
-
- return $sql;
- }
-
- // --------------------------------------------------------------------
-
-
- /**
- * Update_Batch statement
- *
- * Generates a platform-specific batch update string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @return string
- */
- function _update_batch($table, $values, $index, $where = NULL)
- {
- $ids = array();
- $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : '';
-
- 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];
- }
- }
- }
-
- $sql = "UPDATE ".$table." SET ";
- $cases = '';
-
- foreach ($final as $k => $v)
- {
- $cases .= $k.' = CASE '."\n";
- foreach ($v as $row)
- {
- $cases .= $row."\n";
- }
-
- $cases .= 'ELSE '.$k.' END, ';
- }
-
- $sql .= substr($cases, 0, -2);
-
- $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
-
- return $sql;
- }
-
- // --------------------------------------------------------------------
-
-
- /**
- * Truncate statement
- *
- * Generates a platform-specific truncate string from the supplied data
- * If the database does not support the truncate() command
- * This function maps to "DELETE FROM table"
- *
- * @access public
- * @param string the table name
- * @return string
- */
- function _truncate($table)
- {
- return "TRUNCATE ".$table;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Delete statement
- *
- * Generates a platform-specific delete string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the where clause
- * @param string the limit clause
- * @return string
- */
- function _delete($table, $where = array(), $like = array(), $limit = FALSE)
- {
- $conditions = '';
-
- if (count($where) > 0 OR count($like) > 0)
- {
- $conditions = "\nWHERE ";
- $conditions .= implode("\n", $this->ar_where);
-
- if (count($where) > 0 && count($like) > 0)
- {
- $conditions .= " AND ";
- }
- $conditions .= implode("\n", $like);
- }
-
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- return "DELETE FROM ".$table.$conditions.$limit;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Limit string
- *
- * Generates a platform-specific LIMIT clause
- *
- * @access public
- * @param string the sql query string
- * @param integer the number of rows to limit the query to
- * @param integer the offset value
- * @return string
- */
- function _limit($sql, $limit, $offset)
- {
- if ($offset == 0)
- {
- $offset = '';
- }
- else
- {
- $offset .= ", ";
- }
-
- return $sql."LIMIT ".$offset.$limit;
+ return implode(', ', $this->qb_from);
}
// --------------------------------------------------------------------
@@ -776,17 +395,11 @@ class CI_DB_cubrid_driver extends CI_DB {
/**
* Close DB Connection
*
- * @access public
- * @param resource
* @return void
*/
- function _close($conn_id)
+ protected function _close()
{
- @cubrid_close($conn_id);
+ cubrid_close($this->conn_id);
}
}
-
-
-/* End of file cubrid_driver.php */
-/* Location: ./system/database/drivers/cubrid/cubrid_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php
index 0c0b08a62..27bfc1466 100644
--- a/system/database/drivers/cubrid/cubrid_forge.php
+++ b/system/database/drivers/cubrid/cubrid_forge.php
@@ -1,288 +1,230 @@
-<?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
*
- * @package CodeIgniter
- * @author Esen Sagynov
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 2.1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CUBRID Forge Class
*
* @category Database
* @author Esen Sagynov
- * @link http://codeigniter.com/user_guide/database/
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_cubrid_forge extends CI_DB_forge {
/**
- * Create database
+ * CREATE DATABASE statement
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var string
*/
- function _create_database($name)
- {
- // CUBRID does not allow to create a database in SQL. The GUI tools
- // have to be used for this purpose.
- return FALSE;
- }
+ protected $_create_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 database
+ * DROP DATABASE statement
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var string
*/
- function _drop_database($name)
- {
- // CUBRID does not allow to drop a database in SQL. The GUI tools
- // have to be used for this purpose.
- return FALSE;
- }
+ protected $_drop_database = FALSE;
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SHORT' => 'INTEGER',
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'BIGINT' => 'NUMERIC',
+ 'FLOAT' => 'DOUBLE',
+ 'REAL' => 'DOUBLE'
+ );
// --------------------------------------------------------------------
/**
- * Process Fields
+ * ALTER TABLE
*
- * @access private
- * @param mixed the fields
- * @return string
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- function _process_fields($fields)
+ protected function _alter_table($alter_type, $table, $field)
{
- $current_field_count = 0;
- $sql = '';
+ 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";
+ $sqls[] = $sql.' CHANGE '.$field[$i]['_literal'];
}
else
{
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t\"" . $this->db->_protect_identifiers($field) . "\"";
-
- if (array_key_exists('NAME', $attributes))
- {
- $sql .= ' '.$this->db->_protect_identifiers($attributes['NAME']).' ';
- }
-
- if (array_key_exists('TYPE', $attributes))
- {
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- switch ($attributes['TYPE'])
- {
- case 'decimal':
- case 'float':
- case 'numeric':
- $sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
- break;
- case 'enum': // As of version 8.4.0 CUBRID does not support
- // enum data type.
- break;
- case 'set':
- $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
- break;
- default:
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
- }
-
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- //$sql .= ' UNSIGNED';
- // As of version 8.4.0 CUBRID does not support UNSIGNED INTEGER data type.
- // Will be supported in the next release as a part of MySQL Compatibility.
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
-
- if (array_key_exists('UNIQUE', $attributes) && $attributes['UNIQUE'] === TRUE)
- {
- $sql .= ' UNIQUE';
- }
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $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
*
- * @access private
- * @param string the table name
- * @param mixed the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param boolean should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @param array $field
+ * @return string
*/
- function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _process_column($field)
{
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- //$sql .= 'IF NOT EXISTS ';
- // As of version 8.4.0 CUBRID does not support this SQL syntax.
- }
-
- $sql .= $this->db->_escape_identifiers($table)." (";
-
- $sql .= $this->_process_fields($fields);
+ $extra_clause = isset($field['after'])
+ ? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';
- // If there is a PK defined
- if (count($primary_keys) > 0)
+ if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)
{
- $key_name = "pk_" . $table . "_" .
- $this->db->_protect_identifiers(implode('_', $primary_keys));
-
- $primary_keys = $this->db->_protect_identifiers($primary_keys);
- $sql .= ",\n\tCONSTRAINT " . $key_name . " PRIMARY KEY(" . implode(', ', $primary_keys) . ")";
+ $extra_clause = ' FIRST';
}
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key_name = $this->db->_protect_identifiers(implode('_', $key));
- $key = $this->db->_protect_identifiers($key);
- }
- else
- {
- $key_name = $this->db->_protect_identifiers($key);
- $key = array($key_name);
- }
-
- $sql .= ",\n\tKEY \"{$key_name}\" (" . implode(', ', $key) . ")";
- }
- }
-
- $sql .= "\n);";
-
- return $sql;
+ 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;
}
// --------------------------------------------------------------------
/**
- * Drop Table
+ * Field attribute TYPE
*
- * @access private
- * @return string
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
*/
- function _drop_table($table)
+ protected function _attr_type(&$attributes)
{
- return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table);
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'LONGTEXT':
+ $attributes['TYPE'] = 'STRING';
+ return;
+ default: return;
+ }
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Process indexes
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
- *
- * @access private
- * @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
- * @return object
+ * @param string $table (ignored)
+ * @return string
*/
- function _alter_table($alter_type, $table, $fields, $after_field = '')
+ protected function _process_indexes($table)
{
- $sql = 'ALTER TABLE '.$this->db->_protect_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->_protect_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;
+ }
- $sql .= $this->_process_fields($fields);
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
- if ($after_field != '')
- {
- $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
- return $sql;
- }
+ $this->keys = array();
- // --------------------------------------------------------------------
-
- /**
- * Rename a table
- *
- * Generates a platform-specific query so that a table can be renamed
- *
- * @access private
- * @param string the old table name
- * @param string the new table name
- * @return string
- */
- function _rename_table($table_name, $new_table_name)
- {
- $sql = 'RENAME TABLE '.$this->db->_protect_identifiers($table_name)." AS ".$this->db->_protect_identifiers($new_table_name);
return $sql;
}
}
-
-/* End of file cubrid_forge.php */
-/* Location: ./system/database/drivers/cubrid/cubrid_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/cubrid/cubrid_result.php b/system/database/drivers/cubrid/cubrid_result.php
index 3f4dca935..251b70a63 100644
--- a/system/database/drivers/cubrid/cubrid_result.php
+++ b/system/database/drivers/cubrid/cubrid_result.php
@@ -1,19 +1,41 @@
-<?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
*
- * @package CodeIgniter
- * @author Esen Sagynov
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 2.0.2
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 2.1.0
* @filesource
*/
-
-// --------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CUBRID Result Class
@@ -22,19 +44,20 @@
*
* @category Database
* @author Esen Sagynov
- * @link http://codeigniter.com/user_guide/database/
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_cubrid_result extends CI_DB_result {
/**
* Number of rows in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_rows()
+ public function num_rows()
{
- return @cubrid_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = cubrid_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -42,12 +65,11 @@ class CI_DB_cubrid_result extends CI_DB_result {
/**
* Number of fields in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_fields()
+ public function num_fields()
{
- return @cubrid_num_fields($this->result_id);
+ return cubrid_num_fields($this->result_id);
}
// --------------------------------------------------------------------
@@ -57,10 +79,9 @@ class CI_DB_cubrid_result extends CI_DB_result {
*
* Generates an array of column names
*
- * @access public
* @return array
*/
- function list_fields()
+ public function list_fields()
{
return cubrid_column_names($this->result_id);
}
@@ -72,59 +93,19 @@ class CI_DB_cubrid_result extends CI_DB_result {
*
* Generates an array of objects containing field meta-data
*
- * @access public
* @return array
*/
- function field_data()
+ public function field_data()
{
$retval = array();
- $tablePrimaryKeys = array();
-
- while ($field = cubrid_fetch_field($this->result_id))
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
- $F = new stdClass();
- $F->name = $field->name;
- $F->type = $field->type;
- $F->default = $field->def;
- $F->max_length = $field->max_length;
-
- // At this moment primary_key property is not returned when
- // cubrid_fetch_field is called. The following code will
- // provide a patch for it. primary_key property will be added
- // in the next release.
-
- // TODO: later version of CUBRID will provide primary_key
- // property.
- // When PK is defined in CUBRID, an index is automatically
- // created in the db_index system table in the form of
- // pk_tblname_fieldname. So the following will count how many
- // columns are there which satisfy this format.
- // The query will search for exact single columns, thus
- // compound PK is not supported.
- $res = cubrid_query($this->conn_id,
- "SELECT COUNT(*) FROM db_index WHERE class_name = '" . $field->table .
- "' AND is_primary_key = 'YES' AND index_name = 'pk_" .
- $field->table . "_" . $field->name . "'"
- );
-
- if ($res)
- {
- $row = cubrid_fetch_array($res, CUBRID_NUM);
- $F->primary_key = ($row[0] > 0 ? 1 : null);
- }
- else
- {
- $F->primary_key = null;
- }
-
- if (is_resource($res))
- {
- cubrid_close_request($res);
- $this->result_id = FALSE;
- }
-
- $retval[] = $F;
+ $retval[$i] = new stdClass();
+ $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 = (int) (strpos(cubrid_field_flags($this->result_id, $i), 'primary_key') !== FALSE);
}
return $retval;
@@ -135,13 +116,12 @@ class CI_DB_cubrid_result extends CI_DB_result {
/**
* Free the result
*
- * @return null
+ * @return void
*/
- function free_result()
+ public function free_result()
{
- if(is_resource($this->result_id) ||
- get_resource_type($this->result_id) == "Unknown" &&
- preg_match('/Resource id #/', strval($this->result_id)))
+ if (is_resource($this->result_id) OR
+ (get_resource_type($this->result_id) === 'Unknown' && preg_match('/Resource id #/', strval($this->result_id))))
{
cubrid_close_request($this->result_id);
$this->result_id = FALSE;
@@ -155,12 +135,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.
*
- * @access private
- * @return array
+ * @param int $n
+ * @return bool
*/
- function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return cubrid_data_seek($this->result_id, $n);
}
@@ -172,10 +152,9 @@ class CI_DB_cubrid_result extends CI_DB_result {
*
* Returns the result set as an array
*
- * @access private
* @return array
*/
- function _fetch_assoc()
+ protected function _fetch_assoc()
{
return cubrid_fetch_assoc($this->result_id);
}
@@ -187,16 +166,12 @@ class CI_DB_cubrid_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @access private
+ * @param string $class_name
* @return object
*/
- function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return cubrid_fetch_object($this->result_id);
+ return cubrid_fetch_object($this->result_id, $class_name);
}
}
-
-
-/* End of file cubrid_result.php */
-/* Location: ./system/database/drivers/cubrid/cubrid_result.php */ \ No newline at end of file
diff --git a/system/database/drivers/cubrid/cubrid_utility.php b/system/database/drivers/cubrid/cubrid_utility.php
index 3336a4914..555ae7a91 100644
--- a/system/database/drivers/cubrid/cubrid_utility.php
+++ b/system/database/drivers/cubrid/cubrid_utility.php
@@ -1,108 +1,79 @@
-<?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
*
- * @package CodeIgniter
- * @author Esen Sagynov
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 2.1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CUBRID Utility Class
*
* @category Database
* @author Esen Sagynov
- * @link http://codeigniter.com/user_guide/database/
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_cubrid_utility extends CI_DB_utility {
/**
* List databases
*
- * @access private
* @return array
*/
- function _list_databases()
+ public function list_databases()
{
- // CUBRID does not allow to see the list of all databases on the
- // server. It is the way its architecture is designed. Every
- // database is independent and isolated.
- // For this reason we can return only the name of the currect
- // connected database.
- if ($this->conn_id)
+ if (isset($this->db->data_cache['db_names']))
{
- return "SELECT '" . $this->database . "'";
+ return $this->db->data_cache['db_names'];
}
- else
- {
- return FALSE;
- }
- }
- // --------------------------------------------------------------------
-
- /**
- * Optimize table query
- *
- * Generates a platform-specific query so that a table can be optimized
- *
- * @access private
- * @param string the table name
- * @return object
- * @link http://www.cubrid.org/manual/840/en/Optimize%20Database
- */
- function _optimize_table($table)
- {
- // No SQL based support in CUBRID as of version 8.4.0. Database or
- // table optimization can be performed using CUBRID Manager
- // database administration tool. See the link above for more info.
- return FALSE;
+ return $this->db->data_cache['db_names'] = cubrid_list_dbs($this->db->conn_id);
}
// --------------------------------------------------------------------
/**
- * Repair table query
- *
- * Generates a platform-specific query so that a table can be repaired
- *
- * @access private
- * @param string the table name
- * @return object
- * @link http://www.cubrid.org/manual/840/en/Checking%20Database%20Consistency
- */
- function _repair_table($table)
- {
- // Not supported in CUBRID as of version 8.4.0. Database or
- // table consistency can be checked using CUBRID Manager
- // database administration tool. See the link above for more info.
- return FALSE;
- }
-
- // --------------------------------------------------------------------
- /**
* CUBRID Export
*
- * @access private
* @param array Preferences
* @return mixed
*/
- function _backup($params = array())
+ protected function _backup($params = array())
{
// 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');
}
}
-
-/* End of file cubrid_utility.php */
-/* Location: ./system/database/drivers/cubrid/cubrid_utility.php */ \ No newline at end of file
diff --git a/system/database/drivers/cubrid/index.html b/system/database/drivers/cubrid/index.html
index c942a79ce..b702fbc39 100644
--- a/system/database/drivers/cubrid/index.html
+++ b/system/database/drivers/cubrid/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/system/database/drivers/ibase/ibase_driver.php b/system/database/drivers/ibase/ibase_driver.php
new file mode 100644
index 000000000..3069d6699
--- /dev/null
+++ b/system/database/drivers/ibase/ibase_driver.php
@@ -0,0 +1,413 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * Firebird/Interbase 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 https://codeigniter.com/user_guide/database/
+ */
+class CI_DB_ibase_driver extends CI_DB {
+
+ /**
+ * Database driver
+ *
+ * @var string
+ */
+ public $dbdriver = 'ibase';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RAND()', 'RAND()');
+
+ /**
+ * IBase Transaction status flag
+ *
+ * @var resource
+ */
+ protected $_ibase_trans;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Non-persistent database connection
+ *
+ * @param bool $persistent
+ * @return resource
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ return ($persistent === TRUE)
+ ? ibase_pconnect($this->hostname.':'.$this->database, $this->username, $this->password, $this->char_set)
+ : ibase_connect($this->hostname.':'.$this->database, $this->username, $this->password, $this->char_set);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database version number
+ *
+ * @return string
+ */
+ public function version()
+ {
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+
+ if (($service = ibase_service_attach($this->hostname, $this->username, $this->password)))
+ {
+ $this->data_cache['version'] = ibase_server_info($service, IBASE_SVC_SERVER_VERSION);
+
+ // Don't keep the service open
+ ibase_service_detach($service);
+ return $this->data_cache['version'];
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Execute the query
+ *
+ * @param string $sql an SQL query
+ * @return resource
+ */
+ protected function _execute($sql)
+ {
+ return ibase_query(isset($this->_ibase_trans) ? $this->_ibase_trans : $this->conn_id, $sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Begin Transaction
+ *
+ * @return bool
+ */
+ protected function _trans_begin()
+ {
+ if (($trans_handle = ibase_trans($this->conn_id)) === FALSE)
+ {
+ return FALSE;
+ }
+
+ $this->_ibase_trans = $trans_handle;
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Commit Transaction
+ *
+ * @return bool
+ */
+ protected function _trans_commit()
+ {
+ if (ibase_commit($this->_ibase_trans))
+ {
+ $this->_ibase_trans = NULL;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Rollback Transaction
+ *
+ * @return bool
+ */
+ protected function _trans_rollback()
+ {
+ if (ibase_rollback($this->_ibase_trans))
+ {
+ $this->_ibase_trans = NULL;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Affected Rows
+ *
+ * @return int
+ */
+ public function affected_rows()
+ {
+ return ibase_affected_rows($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @param string $generator_name
+ * @param int $inc_by
+ * @return int
+ */
+ public function insert_id($generator_name, $inc_by = 0)
+ {
+ //If a generator hasn't been used before it will return 0
+ return ibase_gen_id('"'.$generator_name.'"', $inc_by);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * List 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 TRIM("RDB$RELATION_NAME") AS TABLE_NAME FROM "RDB$RELATIONS" WHERE "RDB$RELATION_NAME" NOT LIKE \'RDB$%\' AND "RDB$RELATION_NAME" NOT LIKE \'MON$%\'';
+
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
+ {
+ return $sql.' AND TRIM("RDB$RELATION_NAME") AS 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 TRIM("RDB$FIELD_NAME") AS COLUMN_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)
+ {
+ $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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Error
+ *
+ * Returns an array containing code and message of the last
+ * database error that has occurred.
+ *
+ * @return array
+ */
+ public function error()
+ {
+ return array('code' => ibase_errcode(), 'message' => ibase_errmsg());
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 ? ' SKIP '.$this->qb_offset : '');
+ }
+ else
+ {
+ $select = 'ROWS '
+ .($this->qb_offset ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit);
+ }
+
+ return preg_replace('`SELECT`i', 'SELECT '.$select, $sql, 1);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Close DB Connection
+ *
+ * @return void
+ */
+ protected function _close()
+ {
+ ibase_close($this->conn_id);
+ }
+
+}
diff --git a/system/database/drivers/ibase/ibase_forge.php b/system/database/drivers/ibase/ibase_forge.php
new file mode 100644
index 000000000..31352f128
--- /dev/null
+++ b/system/database/drivers/ibase/ibase_forge.php
@@ -0,0 +1,251 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * Interbase/Firebird Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
+ */
+class CI_DB_ibase_forge extends CI_DB_forge {
+
+ /**
+ * 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 $db_name
+ * @return bool
+ */
+ 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_identififers($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
+ }
+
+}
diff --git a/system/database/drivers/ibase/ibase_result.php b/system/database/drivers/ibase/ibase_result.php
new file mode 100644
index 000000000..7d7dd79ac
--- /dev/null
+++ b/system/database/drivers/ibase/ibase_result.php
@@ -0,0 +1,161 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * Interbase/Firebird Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
+ */
+class CI_DB_ibase_result extends CI_DB_result {
+
+ /**
+ * Number of fields in the result set
+ *
+ * @return int
+ */
+ public function num_fields()
+ {
+ return ibase_num_fields($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch Field Names
+ *
+ * Generates an array of column names
+ *
+ * @return array
+ */
+ public function list_fields()
+ {
+ $field_names = array();
+ for ($i = 0, $num_fields = $this->num_fields(); $i < $num_fields; $i++)
+ {
+ $info = ibase_field_info($this->result_id, $i);
+ $field_names[] = $info['name'];
+ }
+
+ return $field_names;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data
+ *
+ * Generates an array of objects containing field meta-data
+ *
+ * @return array
+ */
+ public function field_data()
+ {
+ $retval = array();
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
+ {
+ $info = ibase_field_info($this->result_id, $i);
+
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $info['name'];
+ $retval[$i]->type = $info['type'];
+ $retval[$i]->max_length = $info['length'];
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Free the result
+ *
+ * @return void
+ */
+ public function free_result()
+ {
+ ibase_free_result($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - associative array
+ *
+ * Returns the result set as an array
+ *
+ * @return array
+ */
+ protected function _fetch_assoc()
+ {
+ return ibase_fetch_assoc($this->result_id, IBASE_FETCH_BLOBS);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - object
+ *
+ * Returns the result set as an object
+ *
+ * @param string $class_name
+ * @return object
+ */
+ protected function _fetch_object($class_name = 'stdClass')
+ {
+ $row = ibase_fetch_object($this->result_id, IBASE_FETCH_BLOBS);
+
+ if ($class_name === 'stdClass' OR ! $row)
+ {
+ return $row;
+ }
+
+ $class_name = new $class_name();
+ foreach ($row as $key => $value)
+ {
+ $class_name->$key = $value;
+ }
+
+ return $class_name;
+ }
+
+}
diff --git a/system/database/drivers/ibase/ibase_utility.php b/system/database/drivers/ibase/ibase_utility.php
new file mode 100644
index 000000000..3c152101a
--- /dev/null
+++ b/system/database/drivers/ibase/ibase_utility.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * Interbase/Firebird Utility Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
+ */
+class CI_DB_ibase_utility extends CI_DB_utility {
+
+ /**
+ * Export
+ *
+ * @param string $filename
+ * @return mixed
+ */
+ protected function _backup($filename)
+ {
+ if ($service = ibase_service_attach($this->db->hostname, $this->db->username, $this->db->password))
+ {
+ $res = ibase_backup($service, $this->db->database, $filename.'.fbk');
+
+ // Close the service connection
+ ibase_service_detach($service);
+ return $res;
+ }
+
+ return FALSE;
+ }
+
+}
diff --git a/system/database/drivers/ibase/index.html b/system/database/drivers/ibase/index.html
new file mode 100644
index 000000000..b702fbc39
--- /dev/null
+++ b/system/database/drivers/ibase/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>403 Forbidden</title>
+</head>
+<body>
+
+<p>Directory access is forbidden.</p>
+
+</body>
+</html>
diff --git a/system/database/drivers/index.html b/system/database/drivers/index.html
index c942a79ce..b702fbc39 100644
--- a/system/database/drivers/index.html
+++ b/system/database/drivers/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/system/database/drivers/mssql/index.html b/system/database/drivers/mssql/index.html
index c942a79ce..b702fbc39 100644
--- a/system/database/drivers/mssql/index.html
+++ b/system/database/drivers/mssql/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index 1823edce8..a2ccd1c80 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -1,648 +1,506 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MS SQL Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
* @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_mssql_driver extends CI_DB {
- var $dbdriver = 'mssql';
-
- // The character used for escaping
- var $_escape_char = '';
-
- // clause and character used for LIKE escape sequences
- var $_like_escape_str = " ESCAPE '%s' ";
- var $_like_escape_chr = '!';
-
- /**
- * 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.
- */
- var $_count_string = "SELECT COUNT(*) AS ";
- var $_random_keyword = ' ASC'; // not currently supported
-
/**
- * Non-persistent database connection
+ * Database driver
*
- * @access private called by the base class
- * @return resource
+ * @var string
*/
- function db_connect()
- {
- if ($this->port != '')
- {
- $this->hostname .= ','.$this->port;
- }
-
- return @mssql_connect($this->hostname, $this->username, $this->password);
- }
+ public $dbdriver = 'mssql';
// --------------------------------------------------------------------
/**
- * Persistent database connection
+ * ORDER BY random keyword
*
- * @access private called by the base class
- * @return resource
+ * @var array
*/
- function db_pconnect()
- {
- if ($this->port != '')
- {
- $this->hostname .= ','.$this->port;
- }
-
- return @mssql_pconnect($this->hostname, $this->username, $this->password);
- }
-
- // --------------------------------------------------------------------
+ protected $_random_keyword = array('NEWID()', 'RAND(%d)');
/**
- * Reconnect
+ * Quoted identifier flag
*
- * Keep / reestablish the db connection if no queries have been
- * sent for a length of time exceeding the server's idle timeout
+ * Whether to use SQL-92 standard quoted identifier
+ * (double quotes) or brackets for identifier escaping.
*
- * @access public
- * @return void
+ * @var bool
*/
- function reconnect()
- {
- // not implemented in MSSQL
- }
+ protected $_quoted_identifier = TRUE;
// --------------------------------------------------------------------
/**
- * Select the database
+ * Class constructor
*
- * @access private called by the base class
- * @return resource
- */
- function db_select()
- {
- // Note: The brackets are required in the event that the DB name
- // contains reserved characters
- return @mssql_select_db('['.$this->database.']', $this->conn_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Set client character set
+ * Appends the port number to the hostname, if needed.
*
- * @access public
- * @param string
- * @param string
- * @return resource
+ * @param array $params
+ * @return void
*/
- function db_set_charset($charset, $collation)
+ public function __construct($params)
{
- // @todo - add support if needed
- return TRUE;
- }
+ parent::__construct($params);
- // --------------------------------------------------------------------
-
- /**
- * Execute the query
- *
- * @access private called by the base class
- * @param string an SQL query
- * @return resource
- */
- function _execute($sql)
- {
- $sql = $this->_prep_query($sql);
- return @mssql_query($sql, $this->conn_id);
+ if ( ! empty($this->port))
+ {
+ $this->hostname .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port;
+ }
}
// --------------------------------------------------------------------
/**
- * Prep the query
- *
- * If needed, each database adapter can prep the query string
+ * Non-persistent database connection
*
- * @access private called by execute()
- * @param string an SQL query
- * @return string
+ * @param bool $persistent
+ * @return resource
*/
- function _prep_query($sql)
+ public function db_connect($persistent = FALSE)
{
- return $sql;
- }
-
- // --------------------------------------------------------------------
+ $this->conn_id = ($persistent)
+ ? mssql_pconnect($this->hostname, $this->username, $this->password)
+ : mssql_connect($this->hostname, $this->username, $this->password);
- /**
- * Begin Transaction
- *
- * @access public
- * @return bool
- */
- function trans_begin($test_mode = FALSE)
- {
- if ( ! $this->trans_enabled)
+ if ( ! $this->conn_id)
{
- return TRUE;
+ return FALSE;
}
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ // ----------------------------------------------------------------
+
+ // Select the DB... assuming a database name is specified in the config file
+ if ($this->database !== '' && ! $this->db_select())
{
- return TRUE;
+ log_message('error', 'Unable to select database: '.$this->database);
+
+ return ($this->db_debug === TRUE)
+ ? $this->display_error('db_unable_to_select', $this->database)
+ : FALSE;
}
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
+ // 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('[', ']');
- $this->simple_query('BEGIN TRAN');
- return TRUE;
+ return $this->conn_id;
}
// --------------------------------------------------------------------
/**
- * Commit Transaction
+ * Select the database
*
- * @access public
+ * @param string $database
* @return bool
*/
- function trans_commit()
+ public function db_select($database = '')
{
- if ( ! $this->trans_enabled)
+ if ($database === '')
{
- return TRUE;
+ $database = $this->database;
}
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ // Note: Escaping is required in the event that the DB name
+ // contains reserved characters.
+ if (mssql_select_db('['.$database.']', $this->conn_id))
{
+ $this->database = $database;
+ $this->data_cache = array();
return TRUE;
}
- $this->simple_query('COMMIT TRAN');
- return TRUE;
+ return FALSE;
}
// --------------------------------------------------------------------
/**
- * Rollback Transaction
+ * Execute the query
*
- * @access public
- * @return bool
+ * @param string $sql an SQL query
+ * @return mixed resource if rows are returned, bool otherwise
*/
- function trans_rollback()
+ protected function _execute($sql)
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- $this->simple_query('ROLLBACK TRAN');
- return TRUE;
+ return mssql_query($sql, $this->conn_id);
}
// --------------------------------------------------------------------
/**
- * Escape String
+ * Begin Transaction
*
- * @access public
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
- * @return string
+ * @return bool
*/
- function escape_str($str, $like = FALSE)
+ protected function _trans_begin()
{
- if (is_array($str))
- {
- foreach ($str as $key => $val)
- {
- $str[$key] = $this->escape_str($val, $like);
- }
-
- return $str;
- }
-
- // Escape single quotes
- $str = str_replace("'", "''", remove_invisible_characters($str));
-
- // escape LIKE condition wildcards
- if ($like === TRUE)
- {
- $str = str_replace(
- array($this->_like_escape_chr, '%', '_'),
- array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'),
- $str
- );
- }
-
- return $str;
+ return $this->simple_query('BEGIN TRAN');
}
// --------------------------------------------------------------------
/**
- * Affected Rows
+ * Commit Transaction
*
- * @access public
- * @return integer
+ * @return bool
*/
- function affected_rows()
+ protected function _trans_commit()
{
- return @mssql_rows_affected($this->conn_id);
+ return $this->simple_query('COMMIT TRAN');
}
// --------------------------------------------------------------------
/**
- * Insert ID
- *
- * Returns the last id created in the Identity column.
- *
- * @access public
- * @return integer
- */
- function insert_id()
- {
- $ver = self::_parse_major_version($this->version());
- $sql = ($ver >= 8 ? "SELECT SCOPE_IDENTITY() AS last_id" : "SELECT @@IDENTITY AS last_id");
- $query = $this->query($sql);
- $row = $query->row();
- return $row->last_id;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Parse major version
- *
- * Grabs the major version number from the
- * database server version string passed in.
- *
- * @access private
- * @param string $version
- * @return int16 major version number
- */
- function _parse_major_version($version)
+ * Rollback Transaction
+ *
+ * @return bool
+ */
+ protected function _trans_rollback()
{
- preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $version, $ver_info);
- return $ver_info[1]; // return the major version b/c that's all we're interested in.
+ return $this->simple_query('ROLLBACK TRAN');
}
// --------------------------------------------------------------------
/**
- * Version number query string
- *
- * @access public
- * @return string
- */
- function _version()
+ * Affected Rows
+ *
+ * @return int
+ */
+ public function affected_rows()
{
- return "SELECT @@VERSION AS ver";
+ return mssql_rows_affected($this->conn_id);
}
// --------------------------------------------------------------------
/**
- * "Count All" query
+ * Insert ID
*
- * Generates a platform-specific query string that counts all records in
- * the specified database
+ * Returns the last id created in the Identity column.
*
- * @access public
- * @param string
* @return string
*/
- function count_all($table = '')
+ public function insert_id()
{
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
-
- if ($query->num_rows() == 0)
- {
- return 0;
- }
+ $query = version_compare($this->version(), '8', '>=')
+ ? 'SELECT SCOPE_IDENTITY() AS last_id'
+ : 'SELECT @@IDENTITY AS last_id';
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
+ $query = $this->query($query);
+ $query = $query->row();
+ return $query->last_id;
}
// --------------------------------------------------------------------
/**
- * List table query
- *
- * Generates a platform-specific query string so that the table names can be fetched
+ * Set client character set
*
- * @access private
- * @param boolean
- * @return string
+ * @param string $charset
+ * @return bool
*/
- function _list_tables($prefix_limit = FALSE)
+ protected function _db_set_charset($charset)
{
- $sql = "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name";
-
- // for future compatibility
- if ($prefix_limit !== FALSE AND $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;
+ return (ini_set('mssql.charset', $charset) !== FALSE);
}
// --------------------------------------------------------------------
/**
- * List column query
- *
- * Generates a platform-specific query string so that the column names can be fetched
+ * Version number query string
*
- * @access private
- * @param string the table name
* @return string
*/
- function _list_columns($table = '')
+ protected function _version()
{
- return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$table."'";
+ return "SELECT SERVERPROPERTY('ProductVersion') AS ver";
}
// --------------------------------------------------------------------
/**
- * Field data query
+ * List table query
*
- * Generates a platform-specific query so that the column data can be retrieved
+ * Generates a platform-specific query string so that the table names can be fetched
*
- * @access public
- * @param string the table name
- * @return object
+ * @param bool $prefix_limit
+ * @return string
*/
- function _field_data($table)
+ protected function _list_tables($prefix_limit = FALSE)
{
- return "SELECT TOP 1 * FROM ".$table;
- }
+ $sql = 'SELECT '.$this->escape_identifiers('name')
+ .' FROM '.$this->escape_identifiers('sysobjects')
+ .' WHERE '.$this->escape_identifiers('type')." = 'U'";
- // --------------------------------------------------------------------
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
+ {
+ $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ }
- /**
- * The error message string
- *
- * @access private
- * @return string
- */
- function _error_message()
- {
- return mssql_get_last_message();
+ return $sql.' ORDER BY '.$this->escape_identifiers('name');
}
// --------------------------------------------------------------------
/**
- * The error message number
+ * List column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
*
- * @access private
- * @return integer
+ * @param string $table
+ * @return string
*/
- function _error_number()
+ protected function _list_columns($table = '')
{
- // Are error numbers supported?
- return '';
+ return 'SELECT COLUMN_NAME
+ FROM INFORMATION_SCHEMA.Columns
+ WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
}
// --------------------------------------------------------------------
/**
- * Escape the SQL Identifiers
- *
- * This function escapes column and table names
+ * Returns an object with field data
*
- * @access private
- * @param string
- * @return string
+ * @param string $table
+ * @return array
*/
- function _escape_identifiers($item)
+ public function field_data($table)
{
- if ($this->_escape_char == '')
- {
- return $item;
- }
+ $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));
- foreach ($this->_reserved_identifiers as $id)
+ if (($query = $this->query($sql)) === FALSE)
{
- if (strpos($item, '.'.$id) !== FALSE)
- {
- $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
- }
+ return FALSE;
}
+ $query = $query->result_object();
- if (strpos($item, '.') !== FALSE)
- {
- $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
- }
- else
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
{
- $str = $this->_escape_char.$item.$this->_escape_char;
+ $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;
}
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
+ return $retval;
}
// --------------------------------------------------------------------
/**
- * From Tables
+ * Error
*
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
+ * Returns an array containing code and message of the last
+ * database error that has occurred.
*
- * @access public
- * @param type
- * @return type
+ * @return array
*/
- function _from_tables($tables)
+ public function error()
{
- if ( ! is_array($tables))
+ // We need this because the error info is discarded by the
+ // server the first time you request it, and query() already
+ // calls error() once for logging purposes when a query fails.
+ static $error = array('code' => 0, 'message' => NULL);
+
+ $message = mssql_get_last_message();
+ if ( ! empty($message))
{
- $tables = array($tables);
+ $error['code'] = $this->query('SELECT @@ERROR AS code')->row()->code;
+ $error['message'] = $message;
}
- return implode(', ', $tables);
+ return $error;
}
// --------------------------------------------------------------------
/**
- * Insert statement
+ * Update statement
*
- * Generates a platform-specific insert string from the supplied data
+ * Generates a platform-specific update string from the supplied data
*
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
+ * @param string $table
+ * @param array $values
* @return string
*/
- function _insert($table, $keys, $values)
+ protected function _update($table, $values)
{
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
/**
- * Update statement
+ * Truncate statement
*
- * Generates a platform-specific update string from the supplied data
+ * 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'
*
- * @access public
- * @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
+ * @param string $table
* @return string
*/
- function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
+ protected function _truncate($table)
{
- foreach ($values as $key => $val)
- {
- $valstr[] = $key." = ".$val;
- }
-
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
- $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
- $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
- $sql .= $orderby.$limit;
-
- return $sql;
+ return 'TRUNCATE TABLE '.$table;
}
-
// --------------------------------------------------------------------
/**
- * Truncate statement
+ * Delete statement
*
- * Generates a platform-specific truncate string from the supplied data
- * If the database does not support the truncate() command
- * This function maps to "DELETE FROM table"
+ * Generates a platform-specific delete string from the supplied data
*
- * @access public
- * @param string the table name
+ * @param string $table
* @return string
*/
- function _truncate($table)
+ protected function _delete($table)
{
- return "TRUNCATE ".$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);
}
// --------------------------------------------------------------------
/**
- * Delete statement
+ * LIMIT
*
- * Generates a platform-specific delete string from the supplied data
+ * Generates a platform-specific LIMIT clause
*
- * @access public
- * @param string the table name
- * @param array the where clause
- * @param string the limit clause
+ * @param string $sql SQL Query
* @return string
*/
- function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _limit($sql)
{
- $conditions = '';
+ $limit = $this->qb_offset + $this->qb_limit;
- if (count($where) > 0 OR count($like) > 0)
+ // 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))
{
- $conditions = "\nWHERE ";
- $conditions .= implode("\n", $this->ar_where);
+ $orderby = $this->_compile_order_by();
- if (count($where) > 0 && count($like) > 0)
+ // 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)
{
- $conditions .= " AND ";
+ $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);
}
- $conditions .= implode("\n", $like);
- }
- $limit = ( ! $limit) ? '' : ' LIMIT '.$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 "DELETE FROM ".$table.$conditions.$limit;
+ return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * Insert batch statement
*
- * Generates a platform-specific LIMIT clause
+ * Generates a platform-specific insert string from the supplied data.
*
- * @access public
- * @param string the sql query string
- * @param integer the number of rows to limit the query to
- * @param integer the offset value
- * @return string
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string|bool
*/
- function _limit($sql, $limit, $offset)
+ protected function _insert_batch($table, $keys, $values)
{
- $i = $limit + $offset;
+ // 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 preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql);
+ return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE;
}
// --------------------------------------------------------------------
@@ -650,18 +508,11 @@ class CI_DB_mssql_driver extends CI_DB {
/**
* Close DB Connection
*
- * @access public
- * @param resource
* @return void
*/
- function _close($conn_id)
+ protected function _close()
{
- @mssql_close($conn_id);
+ mssql_close($this->conn_id);
}
}
-
-
-
-/* End of file mssql_driver.php */
-/* Location: ./system/database/drivers/mssql/mssql_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php
index acb4dc50b..6b6109868 100644
--- a/system/database/drivers/mssql/mssql_forge.php
+++ b/system/database/drivers/mssql/mssql_forge.php
@@ -1,248 +1,151 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MS SQL Forge Class
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_mssql_forge extends CI_DB_forge {
/**
- * Create database
+ * CREATE TABLE IF statement
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var string
*/
- function _create_database($name)
- {
- return "CREATE DATABASE ".$name;
- }
-
- // --------------------------------------------------------------------
+ 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 database
+ * DROP TABLE IF statement
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var string
*/
- function _drop_database($name)
- {
- return "DROP DATABASE ".$name;
- }
-
- // --------------------------------------------------------------------
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
/**
- * Drop Table
+ * UNSIGNED support
*
- * @access private
- * @return bool
+ * @var array
*/
- function _drop_table($table)
- {
- return "DROP TABLE ".$this->db->_escape_identifiers($table);
- }
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @access private
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param boolean 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[]
*/
- 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)." (";
- $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->_protect_identifiers($field);
-
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $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)
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
{
- $primary_keys = $this->db->_protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $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)
- {
- if (is_array($key))
- {
- $key = $this->db->_protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->_protect_identifiers($key));
- }
-
- $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")";
- }
+ $sqls[] = $sql.$this->_process_column($field[$i]);
}
- $sql .= "\n)";
-
- return $sql;
+ 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.
*
- * @access private
- * @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 boolean should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return object
+ * @param array &$attributes
+ * @return void
*/
- 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->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
- {
- return $sql;
- }
-
- $sql .= " $column_definition";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"$default_value\"";
- }
-
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
+ if (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE)
{
- $sql .= ' NOT NULL';
+ unset($attributes['CONSTRAINT']);
}
- if ($after_field != '')
+ switch (strtoupper($attributes['TYPE']))
{
- $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
}
-
- return $sql;
-
}
// --------------------------------------------------------------------
/**
- * Rename a table
- *
- * Generates a platform-specific query so that a table can be renamed
+ * Field attribute AUTO_INCREMENT
*
- * @access private
- * @param string the old table name
- * @param string the new table name
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- function _rename_table($table_name, $new_table_name)
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- // I think this syntax will work, but can find little documentation on renaming tables in MSSQL
- $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name);
- return $sql;
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' IDENTITY(1,1)';
+ }
}
}
-
-/* End of file mssql_forge.php */
-/* Location: ./system/database/drivers/mssql/mssql_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/mssql/mssql_result.php b/system/database/drivers/mssql/mssql_result.php
index af4b3c541..38a0a0574 100644
--- a/system/database/drivers/mssql/mssql_result.php
+++ b/system/database/drivers/mssql/mssql_result.php
@@ -1,40 +1,65 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * MS SQL Result Class
+ * MSSQL Result Class
*
* This class extends the parent result class: CI_DB_result
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_mssql_result extends CI_DB_result {
/**
* Number of rows in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_rows()
+ public function num_rows()
{
- return @mssql_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = mssql_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -42,12 +67,11 @@ class CI_DB_mssql_result extends CI_DB_result {
/**
* Number of fields in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_fields()
+ public function num_fields()
{
- return @mssql_num_fields($this->result_id);
+ return mssql_num_fields($this->result_id);
}
// --------------------------------------------------------------------
@@ -57,12 +81,12 @@ class CI_DB_mssql_result extends CI_DB_result {
*
* Generates an array of column names
*
- * @access public
* @return array
*/
- function list_fields()
+ public function list_fields()
{
$field_names = array();
+ mssql_field_seek($this->result_id, 0);
while ($field = mssql_fetch_field($this->result_id))
{
$field_names[] = $field->name;
@@ -78,22 +102,19 @@ class CI_DB_mssql_result extends CI_DB_result {
*
* Generates an array of objects containing field meta-data
*
- * @access public
* @return array
*/
- function field_data()
+ public function field_data()
{
$retval = array();
- while ($field = mssql_fetch_field($this->result_id))
+ for ($i = 0, $c = $this->num_fields(); $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;
@@ -104,9 +125,9 @@ class CI_DB_mssql_result extends CI_DB_result {
/**
* Free the result
*
- * @return null
+ * @return void
*/
- function free_result()
+ public function free_result()
{
if (is_resource($this->result_id))
{
@@ -120,14 +141,14 @@ class CI_DB_mssql_result extends CI_DB_result {
/**
* Data Seek
*
- * Moves the internal pointer to the desired offset. We call
+ * 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.
*
- * @access private
- * @return array
+ * @param int $n
+ * @return bool
*/
- function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return mssql_data_seek($this->result_id, $n);
}
@@ -139,10 +160,9 @@ class CI_DB_mssql_result extends CI_DB_result {
*
* Returns the result set as an array
*
- * @access private
* @return array
*/
- function _fetch_assoc()
+ protected function _fetch_assoc()
{
return mssql_fetch_assoc($this->result_id);
}
@@ -154,16 +174,25 @@ class CI_DB_mssql_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @access private
+ * @param string $class_name
* @return object
*/
- function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return mssql_fetch_object($this->result_id);
- }
+ $row = mssql_fetch_object($this->result_id);
-}
+ if ($class_name === 'stdClass' OR ! $row)
+ {
+ return $row;
+ }
+ $class_name = new $class_name();
+ foreach ($row as $key => $value)
+ {
+ $class_name->$key = $value;
+ }
-/* End of file mssql_result.php */
-/* Location: ./system/database/drivers/mssql/mssql_result.php */ \ No newline at end of file
+ return $class_name;
+ }
+
+}
diff --git a/system/database/drivers/mssql/mssql_utility.php b/system/database/drivers/mssql/mssql_utility.php
index 0e4e7be8c..95ce88f13 100644
--- a/system/database/drivers/mssql/mssql_utility.php
+++ b/system/database/drivers/mssql/mssql_utility.php
@@ -1,88 +1,77 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MS SQL Utility Class
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_mssql_utility extends CI_DB_utility {
/**
- * List databases
- *
- * @access private
- * @return bool
- */
- function _list_databases()
- {
- return "EXEC sp_helpdb"; // Can also be: EXEC sp_databases
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Optimize table query
- *
- * Generates a platform-specific query so that a table can be optimized
+ * List databases statement
*
- * @access private
- * @param string the table name
- * @return object
+ * @var string
*/
- function _optimize_table($table)
- {
- return FALSE; // Is this supported in MS SQL?
- }
-
- // --------------------------------------------------------------------
+ protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases
/**
- * Repair table query
+ * OPTIMIZE TABLE statement
*
- * Generates a platform-specific query so that a table can be repaired
- *
- * @access private
- * @param string the table name
- * @return object
+ * @var string
*/
- function _repair_table($table)
- {
- return FALSE; // Is this supported in MS SQL?
- }
-
- // --------------------------------------------------------------------
+ protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE';
/**
- * MSSQL Export
+ * Export
*
- * @access private
- * @param array Preferences
- * @return mixed
+ * @param array $params Preferences
+ * @return bool
*/
- function _backup($params = array())
+ protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
-
-/* End of file mssql_utility.php */
-/* Location: ./system/database/drivers/mssql/mssql_utility.php */ \ No newline at end of file
diff --git a/system/database/drivers/mysql/index.html b/system/database/drivers/mysql/index.html
index c942a79ce..b702fbc39 100644
--- a/system/database/drivers/mysql/index.html
+++ b/system/database/drivers/mysql/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index 832b9d83e..71dad676e 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -1,94 +1,175 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.0.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQL Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
* @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_mysql_driver extends CI_DB {
- var $dbdriver = 'mysql';
-
- // The character used for escaping
- var $_escape_char = '`';
+ /**
+ * Database driver
+ *
+ * @var string
+ */
+ public $dbdriver = 'mysql';
- // clause and character used for LIKE escape sequences - not used in MySQL
- var $_like_escape_str = '';
- var $_like_escape_chr = '';
+ /**
+ * 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
*/
- var $delete_hack = TRUE;
+ public $delete_hack = TRUE;
/**
- * 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.
+ * Strict ON flag
+ *
+ * Whether we're running in strict SQL mode.
+ *
+ * @var bool
*/
- var $_count_string = 'SELECT COUNT(*) AS ';
- var $_random_keyword = ' RAND()'; // database specific random keyword
+ public $stricton;
+
+ // --------------------------------------------------------------------
- // whether SET NAMES must be used to set the character set
- var $use_set_names;
-
/**
- * Non-persistent database connection
+ * Identifier escape character
*
- * @access private called by the base class
- * @return resource
+ * @var string
*/
- function db_connect()
+ protected $_escape_char = '`';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @param array $params
+ * @return void
+ */
+ public function __construct($params)
{
- if ($this->port != '')
+ parent::__construct($params);
+
+ if ( ! empty($this->port))
{
$this->hostname .= ':'.$this->port;
}
-
- return @mysql_connect($this->hostname, $this->username, $this->password, TRUE);
}
// --------------------------------------------------------------------
/**
- * Persistent database connection
+ * Non-persistent database connection
*
- * @access private called by the base class
+ * @param bool $persistent
* @return resource
*/
- function db_pconnect()
+ public function db_connect($persistent = FALSE)
{
- if ($this->port != '')
+ $client_flags = ($this->compress === FALSE) ? 0 : MYSQL_CLIENT_COMPRESS;
+
+ if ($this->encrypt === TRUE)
{
- $this->hostname .= ':'.$this->port;
+ $client_flags = $client_flags | MYSQL_CLIENT_SSL;
}
- return @mysql_pconnect($this->hostname, $this->username, $this->password);
+ // Error suppression is necessary mostly due to PHP 5.5+ issuing E_DEPRECATED messages
+ $this->conn_id = ($persistent === TRUE)
+ ? mysql_pconnect($this->hostname, $this->username, $this->password, $client_flags)
+ : mysql_connect($this->hostname, $this->username, $this->password, TRUE, $client_flags);
+
+ // ----------------------------------------------------------------
+
+ // Select the DB... assuming a database name is specified in the config file
+ if ($this->database !== '' && ! $this->db_select())
+ {
+ log_message('error', 'Unable to select database: '.$this->database);
+
+ return ($this->db_debug === TRUE)
+ ? $this->display_error('db_unable_to_select', $this->database)
+ : FALSE;
+ }
+
+ if (isset($this->stricton) && is_resource($this->conn_id))
+ {
+ if ($this->stricton)
+ {
+ $this->simple_query('SET SESSION sql_mode = CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")');
+ }
+ else
+ {
+ $this->simple_query(
+ 'SET SESSION sql_mode =
+ REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
+ @@sql_mode,
+ "STRICT_ALL_TABLES,", ""),
+ ",STRICT_ALL_TABLES", ""),
+ "STRICT_ALL_TABLES", ""),
+ "STRICT_TRANS_TABLES,", ""),
+ ",STRICT_TRANS_TABLES", ""),
+ "STRICT_TRANS_TABLES", "")'
+ );
+ }
+ }
+
+ return $this->conn_id;
}
// --------------------------------------------------------------------
@@ -99,10 +180,9 @@ class CI_DB_mysql_driver extends CI_DB {
* Keep / reestablish the db connection if no queries have been
* sent for a length of time exceeding the server's idle timeout
*
- * @access public
* @return void
*/
- function reconnect()
+ public function reconnect()
{
if (mysql_ping($this->conn_id) === FALSE)
{
@@ -115,12 +195,24 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Select the database
*
- * @access private called by the base class
- * @return resource
+ * @param string $database
+ * @return bool
*/
- function db_select()
+ public function db_select($database = '')
{
- return @mysql_select_db($this->database, $this->conn_id);
+ if ($database === '')
+ {
+ $database = $this->database;
+ }
+
+ if (mysql_select_db($database, $this->conn_id))
+ {
+ $this->database = $database;
+ $this->data_cache = array();
+ return TRUE;
+ }
+
+ return FALSE;
}
// --------------------------------------------------------------------
@@ -128,40 +220,34 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Set client character set
*
- * @access public
- * @param string
- * @param string
- * @return resource
+ * @param string $charset
+ * @return bool
*/
- function db_set_charset($charset, $collation)
+ protected function _db_set_charset($charset)
{
- if ( ! isset($this->use_set_names))
- {
- // mysql_set_charset() requires PHP >= 5.2.3 and MySQL >= 5.0.7, use SET NAMES as fallback
- $this->use_set_names = (version_compare(PHP_VERSION, '5.2.3', '>=') && version_compare(mysql_get_server_info(), '5.0.7', '>=')) ? FALSE : TRUE;
- }
-
- if ($this->use_set_names === TRUE)
- {
- return @mysql_query("SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'", $this->conn_id);
- }
- else
- {
- return @mysql_set_charset($charset, $this->conn_id);
- }
+ return mysql_set_charset($charset, $this->conn_id);
}
// --------------------------------------------------------------------
/**
- * Version number query string
+ * Database version number
*
- * @access public
* @return string
*/
- function _version()
+ public function version()
{
- return "SELECT version() AS ver";
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+
+ if ( ! $this->conn_id OR ($version = mysql_get_server_info($this->conn_id)) === FALSE)
+ {
+ return FALSE;
+ }
+
+ return $this->data_cache['version'] = $version;
}
// --------------------------------------------------------------------
@@ -169,14 +255,12 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Execute the query
*
- * @access private called by the base class
- * @param string an SQL query
- * @return resource
+ * @param string $sql an SQL query
+ * @return mixed
*/
- function _execute($sql)
+ protected function _execute($sql)
{
- $sql = $this->_prep_query($sql);
- return @mysql_query($sql, $this->conn_id);
+ return mysql_query($this->_prep_query($sql), $this->conn_id);
}
// --------------------------------------------------------------------
@@ -186,20 +270,16 @@ class CI_DB_mysql_driver extends CI_DB {
*
* If needed, each database adapter can prep the query string
*
- * @access private called by execute()
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return string
*/
- function _prep_query($sql)
+ protected function _prep_query($sql)
{
- // "DELETE FROM TABLE" returns 0 affected rows This hack modifies
- // the query so that it returns the number of affected rows
- if ($this->delete_hack === TRUE)
+ // mysql_affected_rows() returns 0 for "DELETE FROM TABLE" queries. This hack
+ // modifies the query so that it a proper number of affected rows is returned.
+ if ($this->delete_hack === TRUE && preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
{
- if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
- {
- $sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql);
- }
+ return trim($sql).' WHERE 1=1';
}
return $sql;
@@ -210,30 +290,12 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Begin Transaction
*
- * @access public
* @return bool
*/
- function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
-
$this->simple_query('SET AUTOCOMMIT=0');
- $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
- return TRUE;
+ return $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
}
// --------------------------------------------------------------------
@@ -241,25 +303,17 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Commit Transaction
*
- * @access public
* @return bool
*/
- function trans_commit()
+ protected function _trans_commit()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ($this->simple_query('COMMIT'))
{
+ $this->simple_query('SET AUTOCOMMIT=1');
return TRUE;
}
- $this->simple_query('COMMIT');
- $this->simple_query('SET AUTOCOMMIT=1');
- return TRUE;
+ return FALSE;
}
// --------------------------------------------------------------------
@@ -267,69 +321,30 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Rollback Transaction
*
- * @access public
* @return bool
*/
- function trans_rollback()
+ protected function _trans_rollback()
{
- if ( ! $this->trans_enabled)
+ if ($this->simple_query('ROLLBACK'))
{
+ $this->simple_query('SET AUTOCOMMIT=1');
return TRUE;
}
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- $this->simple_query('ROLLBACK');
- $this->simple_query('SET AUTOCOMMIT=1');
- return TRUE;
+ return FALSE;
}
// --------------------------------------------------------------------
/**
- * Escape String
+ * Platform-dependent string escape
*
- * @access public
* @param string
- * @param bool whether or not the string will be used in a LIKE condition
* @return string
*/
- function escape_str($str, $like = FALSE)
+ protected function _escape_str($str)
{
- if (is_array($str))
- {
- foreach ($str as $key => $val)
- {
- $str[$key] = $this->escape_str($val, $like);
- }
-
- return $str;
- }
-
- if (function_exists('mysql_real_escape_string') AND is_resource($this->conn_id))
- {
- $str = mysql_real_escape_string($str, $this->conn_id);
- }
- elseif (function_exists('mysql_escape_string'))
- {
- $str = mysql_escape_string($str);
- }
- else
- {
- $str = addslashes($str);
- }
-
- // escape LIKE condition wildcards
- if ($like === TRUE)
- {
- $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str);
- }
-
- return $str;
+ return mysql_real_escape_string($str, $this->conn_id);
}
// --------------------------------------------------------------------
@@ -337,12 +352,11 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Affected Rows
*
- * @access public
- * @return integer
+ * @return int
*/
- function affected_rows()
+ public function affected_rows()
{
- return @mysql_affected_rows($this->conn_id);
+ return mysql_affected_rows($this->conn_id);
}
// --------------------------------------------------------------------
@@ -350,43 +364,11 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Insert ID
*
- * @access public
- * @return integer
+ * @return int
*/
- function insert_id()
+ public function insert_id()
{
- return @mysql_insert_id($this->conn_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @access public
- * @param string
- * @return string
- */
- function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
-
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
+ return mysql_insert_id($this->conn_id);
}
// --------------------------------------------------------------------
@@ -396,17 +378,16 @@ class CI_DB_mysql_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @access private
- * @param boolean
+ * @param bool $prefix_limit
* @return string
*/
- function _list_tables($prefix_limit = FALSE)
+ protected function _list_tables($prefix_limit = FALSE)
{
- $sql = "SHOW TABLES FROM ".$this->_escape_char.$this->database.$this->_escape_char;
+ $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- $sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%'";
+ return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
}
return $sql;
@@ -419,343 +400,81 @@ class CI_DB_mysql_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @access public
- * @param string the table name
- * @return string
- */
- function _list_columns($table = '')
- {
- return "SHOW COLUMNS FROM ".$this->_protect_identifiers($table, TRUE, NULL, FALSE);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
- *
- * @access public
- * @param string the table name
- * @return object
- */
- function _field_data($table)
- {
- return "DESCRIBE ".$table;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * The error message string
- *
- * @access private
+ * @param string $table
* @return string
*/
- function _error_message()
- {
- return mysql_error($this->conn_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * The error message number
- *
- * @access private
- * @return integer
- */
- function _error_number()
+ protected function _list_columns($table = '')
{
- return mysql_errno($this->conn_id);
+ return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
}
// --------------------------------------------------------------------
/**
- * Escape the SQL Identifiers
- *
- * This function escapes column and table names
+ * Returns an object with field data
*
- * @access private
- * @param string
- * @return string
+ * @param string $table
+ * @return array
*/
- function _escape_identifiers($item)
+ public function field_data($table)
{
- if ($this->_escape_char == '')
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
{
- return $item;
+ return FALSE;
}
+ $query = $query->result_object();
- foreach ($this->_reserved_identifiers as $id)
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
{
- if (strpos($item, '.'.$id) !== FALSE)
- {
- $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->Field;
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
- }
- }
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
- if (strpos($item, '.') !== FALSE)
- {
- $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
- }
- else
- {
- $str = $this->_escape_char.$item.$this->_escape_char;
+ $retval[$i]->default = $query[$i]->Default;
+ $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
}
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
+ return $retval;
}
// --------------------------------------------------------------------
/**
- * From Tables
+ * Error
*
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
+ * Returns an array containing code and message of the last
+ * database error that has occurred.
*
- * @access public
- * @param type
- * @return type
+ * @return array
*/
- function _from_tables($tables)
+ public function error()
{
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
+ return array('code' => mysql_errno($this->conn_id), 'message' => mysql_error($this->conn_id));
}
// --------------------------------------------------------------------
/**
- * Insert statement
+ * FROM tables
*
- * Generates a platform-specific insert string from the supplied data
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
*
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
* @return string
*/
- function _insert($table, $keys, $values)
+ protected function _from_tables()
{
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
- }
-
- // --------------------------------------------------------------------
-
-
- /**
- * Replace statement
- *
- * Generates a platform-specific replace string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
- */
- function _replace($table, $keys, $values)
- {
- return "REPLACE INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Insert_batch statement
- *
- * Generates a platform-specific insert string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
- */
- function _insert_batch($table, $keys, $values)
- {
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values);
- }
-
- // --------------------------------------------------------------------
-
-
- /**
- * Update statement
- *
- * Generates a platform-specific update string from the supplied data
- *
- * @access public
- * @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
- * @return string
- */
- function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
- {
- foreach ($values as $key => $val)
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
{
- $valstr[] = $key . ' = ' . $val;
+ return '('.implode(', ', $this->qb_from).')';
}
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
- $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
- $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
- $sql .= $orderby.$limit;
-
- return $sql;
- }
-
- // --------------------------------------------------------------------
-
-
- /**
- * Update_Batch statement
- *
- * Generates a platform-specific batch update string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @return string
- */
- function _update_batch($table, $values, $index, $where = NULL)
- {
- $ids = array();
- $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : '';
-
- 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];
- }
- }
- }
-
- $sql = "UPDATE ".$table." SET ";
- $cases = '';
-
- foreach ($final as $k => $v)
- {
- $cases .= $k.' = CASE '."\n";
- foreach ($v as $row)
- {
- $cases .= $row."\n";
- }
-
- $cases .= 'ELSE '.$k.' END, ';
- }
-
- $sql .= substr($cases, 0, -2);
-
- $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
-
- return $sql;
- }
-
- // --------------------------------------------------------------------
-
-
- /**
- * Truncate statement
- *
- * Generates a platform-specific truncate string from the supplied data
- * If the database does not support the truncate() command
- * This function maps to "DELETE FROM table"
- *
- * @access public
- * @param string the table name
- * @return string
- */
- function _truncate($table)
- {
- return "TRUNCATE ".$table;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Delete statement
- *
- * Generates a platform-specific delete string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the where clause
- * @param string the limit clause
- * @return string
- */
- function _delete($table, $where = array(), $like = array(), $limit = FALSE)
- {
- $conditions = '';
-
- if (count($where) > 0 OR count($like) > 0)
- {
- $conditions = "\nWHERE ";
- $conditions .= implode("\n", $this->ar_where);
-
- if (count($where) > 0 && count($like) > 0)
- {
- $conditions .= " AND ";
- }
- $conditions .= implode("\n", $like);
- }
-
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- return "DELETE FROM ".$table.$conditions.$limit;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Limit string
- *
- * Generates a platform-specific LIMIT clause
- *
- * @access public
- * @param string the sql query string
- * @param integer the number of rows to limit the query to
- * @param integer the offset value
- * @return string
- */
- function _limit($sql, $limit, $offset)
- {
- if ($offset == 0)
- {
- $offset = '';
- }
- else
- {
- $offset .= ", ";
- }
-
- return $sql."LIMIT ".$offset.$limit;
+ return implode(', ', $this->qb_from);
}
// --------------------------------------------------------------------
@@ -763,17 +482,13 @@ class CI_DB_mysql_driver extends CI_DB {
/**
* Close DB Connection
*
- * @access public
- * @param resource
* @return void
*/
- function _close($conn_id)
+ protected function _close()
{
- @mysql_close($conn_id);
+ // Error suppression to avoid annoying E_WARNINGs in cases
+ // where the connection has already been closed for some reason.
+ @mysql_close($this->conn_id);
}
}
-
-
-/* End of file mysql_driver.php */
-/* Location: ./system/database/drivers/mysql/mysql_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php
index bc419d1bd..7ed8f8d38 100644
--- a/system/database/drivers/mysql/mysql_forge.php
+++ b/system/database/drivers/mysql/mysql_forge.php
@@ -1,144 +1,123 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.0.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQL Forge Class
*
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_mysql_forge extends CI_DB_forge {
/**
- * Create database
+ * CREATE DATABASE statement
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var string
*/
- function _create_database($name)
- {
- return "CREATE DATABASE ".$name;
- }
+ protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';
- // --------------------------------------------------------------------
+ /**
+ * CREATE TABLE keys flag
+ *
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
+ */
+ protected $_create_table_keys = TRUE;
/**
- * Drop database
+ * UNSIGNED support
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var array
*/
- function _drop_database($name)
- {
- return "DROP DATABASE ".$name;
- }
+ 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';
// --------------------------------------------------------------------
/**
- * Process Fields
+ * CREATE TABLE attributes
*
- * @access private
- * @param mixed the fields
+ * @param array $attributes Associative array of table attributes
* @return string
*/
- function _process_fields($fields)
+ protected function _create_table_attr($attributes)
{
- $current_field_count = 0;
$sql = '';
- foreach ($fields as $field=>$attributes)
+ foreach (array_keys($attributes) as $key)
{
- // 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 (is_string($key))
{
- $sql .= "\n\t$attributes";
+ $sql .= ' '.strtoupper($key).' = '.$attributes[$key];
}
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->_protect_identifiers($field);
-
- if (array_key_exists('NAME', $attributes))
- {
- $sql .= ' '.$this->db->_protect_identifiers($attributes['NAME']).' ';
- }
-
- if (array_key_exists('TYPE', $attributes))
- {
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- switch ($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'].')';
- }
- }
- }
-
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
+ }
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ if ( ! empty($this->db->char_set) && ! strpos($sql, 'CHARACTER SET') && ! strpos($sql, 'CHARSET'))
+ {
+ $sql .= ' DEFAULT CHARACTER SET = '.$this->db->char_set;
+ }
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
+ if ( ! empty($this->db->dbcollat) && ! strpos($sql, 'COLLATE'))
+ {
+ $sql .= ' COLLATE = '.$this->db->dbcollat;
}
return $sql;
@@ -147,127 +126,118 @@ class CI_DB_mysql_forge extends CI_DB_forge {
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @access private
- * @param string the table name
- * @param mixed the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param boolean 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[]
*/
- 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)." (";
-
- $sql .= $this->_process_fields($fields);
-
- if (count($primary_keys) > 0)
+ if ($alter_type === 'DROP')
{
- $key_name = $this->db->_protect_identifiers(implode('_', $primary_keys));
- $primary_keys = $this->db->_protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY ".$key_name." (" . implode(', ', $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)
+ {
+ $field[$i] = ($alter_type === 'ADD')
+ ? "\n\tADD ".$field[$i]['_literal']
+ : "\n\tMODIFY ".$field[$i]['_literal'];
+ }
+ else
{
- if (is_array($key))
+ if ($alter_type === 'ADD')
{
- $key_name = $this->db->_protect_identifiers(implode('_', $key));
- $key = $this->db->_protect_identifiers($key);
+ $field[$i]['_literal'] = "\n\tADD ";
}
else
{
- $key_name = $this->db->_protect_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]);
}
}
- $sql .= "\n) DEFAULT CHARACTER SET {$this->db->char_set} COLLATE {$this->db->dbcollat};";
-
- return $sql;
+ return array($sql.implode(',', $field));
}
// --------------------------------------------------------------------
/**
- * Drop Table
+ * Process column
*
- * @access private
+ * @param array $field
* @return string
*/
- function _drop_table($table)
+ protected function _process_column($field)
{
- return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table);
+ $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']
+ .(empty($field['comment']) ? '' : ' COMMENT '.$field['comment'])
+ .$extra_clause;
}
// --------------------------------------------------------------------
/**
- * 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
*
- * @access private
- * @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
- * @return object
+ * @param string $table (ignored)
+ * @return string
*/
- function _alter_table($alter_type, $table, $fields, $after_field = '')
+ protected function _process_indexes($table)
{
- $sql = 'ALTER TABLE '.$this->db->_protect_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->_protect_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;
+ }
- $sql .= $this->_process_fields($fields);
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
- if ($after_field != '')
- {
- $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
- return $sql;
- }
-
- // --------------------------------------------------------------------
+ $this->keys = array();
- /**
- * Rename a table
- *
- * Generates a platform-specific query so that a table can be renamed
- *
- * @access private
- * @param string the old table name
- * @param string the new table name
- * @return string
- */
- function _rename_table($table_name, $new_table_name)
- {
- $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name);
return $sql;
}
}
-
-/* End of file mysql_forge.php */
-/* Location: ./system/database/drivers/mysql/mysql_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/mysql/mysql_result.php b/system/database/drivers/mysql/mysql_result.php
index 27a0132d0..7aa265ebb 100644
--- a/system/database/drivers/mysql/mysql_result.php
+++ b/system/database/drivers/mysql/mysql_result.php
@@ -1,19 +1,41 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.0.0
* @filesource
*/
-
-// --------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQL Result Class
@@ -21,20 +43,36 @@
* This class extends the parent result class: CI_DB_result
*
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_mysql_result extends CI_DB_result {
/**
+ * Class constructor
+ *
+ * @param object &$driver_object
+ * @return void
+ */
+ public function __construct(&$driver_object)
+ {
+ parent::__construct($driver_object);
+
+ // Required, due to mysql_data_seek() causing nightmares
+ // with empty result sets
+ $this->num_rows = mysql_num_rows($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Number of rows in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_rows()
+ public function num_rows()
{
- return @mysql_num_rows($this->result_id);
+ return $this->num_rows;
}
// --------------------------------------------------------------------
@@ -42,12 +80,11 @@ class CI_DB_mysql_result extends CI_DB_result {
/**
* Number of fields in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_fields()
+ public function num_fields()
{
- return @mysql_num_fields($this->result_id);
+ return mysql_num_fields($this->result_id);
}
// --------------------------------------------------------------------
@@ -57,12 +94,12 @@ class CI_DB_mysql_result extends CI_DB_result {
*
* Generates an array of column names
*
- * @access public
* @return array
*/
- function list_fields()
+ public function list_fields()
{
$field_names = array();
+ mysql_field_seek($this->result_id, 0);
while ($field = mysql_fetch_field($this->result_id))
{
$field_names[] = $field->name;
@@ -78,27 +115,18 @@ class CI_DB_mysql_result extends CI_DB_result {
*
* Generates an array of objects containing field meta-data
*
- * @access public
* @return array
*/
- function field_data()
+ public function field_data()
{
$retval = array();
- while ($field = mysql_fetch_object($this->result_id))
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
- preg_match('/([a-zA-Z]+)(\(\d+\))?/', $field->Type, $matches);
-
- $type = (array_key_exists(1, $matches)) ? $matches[1] : NULL;
- $length = (array_key_exists(2, $matches)) ? preg_replace('/[^\d]/', '', $matches[2]) : NULL;
-
- $F = new stdClass();
- $F->name = $field->Field;
- $F->type = $type;
- $F->default = $field->Default;
- $F->max_length = $length;
- $F->primary_key = ( $field->Key == 'PRI' ? 1 : 0 );
-
- $retval[] = $F;
+ $retval[$i] = new stdClass();
+ $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 = (int) (strpos(mysql_field_flags($this->result_id, $i), 'primary_key') !== FALSE);
}
return $retval;
@@ -109,9 +137,9 @@ class CI_DB_mysql_result extends CI_DB_result {
/**
* Free the result
*
- * @return null
+ * @return void
*/
- function free_result()
+ public function free_result()
{
if (is_resource($this->result_id))
{
@@ -125,16 +153,18 @@ class CI_DB_mysql_result extends CI_DB_result {
/**
* Data Seek
*
- * Moves the internal pointer to the desired offset. We call
+ * 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.
*
- * @access private
- * @return array
+ * @param int $n
+ * @return bool
*/
- function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
- return mysql_data_seek($this->result_id, $n);
+ return $this->num_rows
+ ? mysql_data_seek($this->result_id, $n)
+ : FALSE;
}
// --------------------------------------------------------------------
@@ -144,10 +174,9 @@ class CI_DB_mysql_result extends CI_DB_result {
*
* Returns the result set as an array
*
- * @access private
* @return array
*/
- function _fetch_assoc()
+ protected function _fetch_assoc()
{
return mysql_fetch_assoc($this->result_id);
}
@@ -159,16 +188,12 @@ class CI_DB_mysql_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @access private
+ * @param string $class_name
* @return object
*/
- function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return mysql_fetch_object($this->result_id);
+ return mysql_fetch_object($this->result_id, $class_name);
}
}
-
-
-/* End of file mysql_result.php */
-/* Location: ./system/database/drivers/mysql/mysql_result.php */ \ No newline at end of file
diff --git a/system/database/drivers/mysql/mysql_utility.php b/system/database/drivers/mysql/mysql_utility.php
index f22c3d043..bc01fc58d 100644
--- a/system/database/drivers/mysql/mysql_utility.php
+++ b/system/database/drivers/mysql/mysql_utility.php
@@ -1,83 +1,83 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.0.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQL Utility Class
*
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_mysql_utility extends CI_DB_utility {
/**
- * List databases
+ * List databases statement
*
- * @access private
- * @return bool
+ * @var string
*/
- function _list_databases()
- {
- return "SHOW DATABASES";
- }
-
- // --------------------------------------------------------------------
+ protected $_list_databases = 'SHOW DATABASES';
/**
- * Optimize table query
+ * OPTIMIZE TABLE statement
*
- * Generates a platform-specific query so that a table can be optimized
- *
- * @access private
- * @param string the table name
- * @return object
+ * @var string
*/
- function _optimize_table($table)
- {
- return "OPTIMIZE TABLE ".$this->db->_escape_identifiers($table);
- }
-
- // --------------------------------------------------------------------
+ protected $_optimize_table = 'OPTIMIZE TABLE %s';
/**
- * Repair table query
+ * REPAIR TABLE statement
*
- * Generates a platform-specific query so that a table can be repaired
- *
- * @access private
- * @param string the table name
- * @return object
+ * @var string
*/
- function _repair_table($table)
- {
- return "REPAIR TABLE ".$this->db->_escape_identifiers($table);
- }
+ protected $_repair_table = 'REPAIR TABLE %s';
// --------------------------------------------------------------------
+
/**
- * MySQL Export
+ * Export
*
- * @access private
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
- function _backup($params = array())
+ protected function _backup($params = array())
{
- if (count($params) == 0)
+ if (count($params) === 0)
{
return FALSE;
}
@@ -87,16 +87,23 @@ class CI_DB_mysql_utility extends CI_DB_utility {
// Build the output
$output = '';
- foreach ((array)$tables as $table)
+
+ // Do we need to include a statement to disable foreign key checks?
+ if ($foreign_key_checks === FALSE)
+ {
+ $output .= 'SET foreign_key_checks = 0;'.$newline;
+ }
+
+ foreach ( (array) $tables as $table)
{
// Is the table in the "ignore" list?
- if (in_array($table, (array)$ignore, TRUE))
+ if (in_array($table, (array) $ignore, TRUE))
{
continue;
}
// Get the table schema
- $query = $this->db->query("SHOW CREATE TABLE `".$this->db->database.'`.`'.$table.'`');
+ $query = $this->db->query('SHOW CREATE TABLE '.$this->db->escape_identifiers($this->db->database.'.'.$table));
// No result means the table name was invalid
if ($query === FALSE)
@@ -107,9 +114,9 @@ class CI_DB_mysql_utility extends CI_DB_utility {
// Write out the table schema
$output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline;
- if ($add_drop == TRUE)
+ if ($add_drop === TRUE)
{
- $output .= 'DROP TABLE IF EXISTS '.$table.';'.$newline.$newline;
+ $output .= 'DROP TABLE IF EXISTS '.$this->db->protect_identifiers($table).';'.$newline.$newline;
}
$i = 0;
@@ -123,21 +130,21 @@ class CI_DB_mysql_utility extends CI_DB_utility {
}
// If inserts are not needed we're done...
- if ($add_insert == FALSE)
+ if ($add_insert === FALSE)
{
continue;
}
// Grab all the data from the current table
- $query = $this->db->query("SELECT * FROM $table");
+ $query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table));
- if ($query->num_rows() == 0)
+ if ($query->num_rows() === 0)
{
continue;
}
// Fetch the field names and determine if the field is an
- // integer type. We use this info to decide whether to
+ // integer type. We use this info to decide whether to
// surround the data with quotes or not
$i = 0;
@@ -146,20 +153,17 @@ class CI_DB_mysql_utility extends CI_DB_utility {
while ($field = mysql_fetch_field($query->result_id))
{
// Most versions of MySQL store timestamp as a string
- $is_int[$i] = (in_array(
- strtolower(mysql_field_type($query->result_id, $i)),
- array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'),
- TRUE)
- ) ? TRUE : FALSE;
+ $is_int[$i] = in_array(strtolower(mysql_field_type($query->result_id, $i)),
+ array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'),
+ TRUE);
// Create a string of field names
- $field_str .= '`'.$field->name.'`, ';
+ $field_str .= $this->db->escape_identifiers($field->name).', ';
$i++;
}
// Trim off the end comma
- $field_str = preg_replace( "/, $/" , "" , $field_str);
-
+ $field_str = preg_replace('/, $/' , '', $field_str);
// Build the insert string
foreach ($query->result_array() as $row)
@@ -177,14 +181,7 @@ class CI_DB_mysql_utility extends CI_DB_utility {
else
{
// Escape the data if it's not an integer
- if ($is_int[$i] == FALSE)
- {
- $val_str .= $this->db->escape($v);
- }
- else
- {
- $val_str .= $v;
- }
+ $val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v;
}
// Append a comma
@@ -193,18 +190,22 @@ class CI_DB_mysql_utility extends CI_DB_utility {
}
// Remove the comma at the end of the string
- $val_str = preg_replace( "/, $/" , "" , $val_str);
+ $val_str = preg_replace('/, $/' , '', $val_str);
// Build the INSERT string
- $output .= 'INSERT INTO '.$table.' ('.$field_str.') VALUES ('.$val_str.');'.$newline;
+ $output .= 'INSERT INTO '.$this->db->protect_identifiers($table).' ('.$field_str.') VALUES ('.$val_str.');'.$newline;
}
$output .= $newline.$newline;
}
+ // Do we need to include a statement to re-enable foreign key checks?
+ if ($foreign_key_checks === FALSE)
+ {
+ $output .= 'SET foreign_key_checks = 1;'.$newline;
+ }
+
return $output;
}
-}
-/* End of file mysql_utility.php */
-/* Location: ./system/database/drivers/mysql/mysql_utility.php */ \ No newline at end of file
+}
diff --git a/system/database/drivers/mysqli/index.html b/system/database/drivers/mysqli/index.html
index c942a79ce..b702fbc39 100644
--- a/system/database/drivers/mysqli/index.html
+++ b/system/database/drivers/mysqli/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index a0896d8aa..b59e89494 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -1,413 +1,327 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * MySQLi Database Adapter Class - MySQLi only works with PHP 5
+ * MySQLi Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
* @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_mysqli_driver extends CI_DB {
- var $dbdriver = 'mysqli';
-
- // The character used for escaping
- var $_escape_char = '`';
-
- // clause and character used for LIKE escape sequences - not used in MySQL
- var $_like_escape_str = '';
- var $_like_escape_chr = '';
+ /**
+ * Database driver
+ *
+ * @var string
+ */
+ public $dbdriver = 'mysqli';
/**
- * 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.
+ * Compression flag
+ *
+ * @var bool
*/
- var $_count_string = "SELECT COUNT(*) AS ";
- var $_random_keyword = ' RAND()'; // database specific random keyword
+ 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 $delete_hack = TRUE;
-
- // whether SET NAMES must be used to set the character set
- var $use_set_names;
-
- // --------------------------------------------------------------------
-
- /**
- * Non-persistent database connection
*
- * @access private called by the base class
- * @return resource
+ * @var bool
*/
- function db_connect()
- {
- if ($this->port != '')
- {
- return @mysqli_connect($this->hostname, $this->username, $this->password, $this->database, $this->port);
- }
- else
- {
- return @mysqli_connect($this->hostname, $this->username, $this->password, $this->database);
- }
-
- }
-
- // --------------------------------------------------------------------
+ public $delete_hack = TRUE;
/**
- * Persistent database connection
+ * Strict ON flag
+ *
+ * Whether we're running in strict SQL mode.
*
- * @access private called by the base class
- * @return resource
+ * @var bool
*/
- function db_pconnect()
- {
- return $this->db_connect();
- }
+ public $stricton;
// --------------------------------------------------------------------
/**
- * Reconnect
- *
- * Keep / reestablish the db connection if no queries have been
- * sent for a length of time exceeding the server's idle timeout
+ * Identifier escape character
*
- * @access public
- * @return void
+ * @var string
*/
- function reconnect()
- {
- if (mysqli_ping($this->conn_id) === FALSE)
- {
- $this->conn_id = FALSE;
- }
- }
+ protected $_escape_char = '`';
// --------------------------------------------------------------------
/**
- * Select the database
+ * MySQLi object
*
- * @access private called by the base class
- * @return resource
+ * Has to be preserved without being assigned to $conn_id.
+ *
+ * @var MySQLi
*/
- function db_select()
- {
- return @mysqli_select_db($this->conn_id, $this->database);
- }
+ protected $_mysqli;
// --------------------------------------------------------------------
/**
- * Set client character set
+ * Database connection
*
- * @access private
- * @param string
- * @param string
- * @return resource
+ * @param bool $persistent
+ * @return object
*/
- function _db_set_charset($charset, $collation)
+ public function db_connect($persistent = FALSE)
{
- if ( ! isset($this->use_set_names))
+ // Do we have a socket path?
+ if ($this->hostname[0] === '/')
{
- // mysqli_set_charset() requires MySQL >= 5.0.7, use SET NAMES as fallback
- $this->use_set_names = (version_compare(mysqli_get_server_info($this->conn_id), '5.0.7', '>=')) ? FALSE : TRUE;
- }
-
- if ($this->use_set_names === TRUE)
- {
- return @mysqli_query($this->conn_id, "SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'");
+ $hostname = NULL;
+ $port = NULL;
+ $socket = $this->hostname;
}
else
{
- return @mysqli_set_charset($this->conn_id, $charset);
+ $hostname = ($persistent === TRUE)
+ ? 'p:'.$this->hostname : $this->hostname;
+ $port = empty($this->port) ? NULL : $this->port;
+ $socket = NULL;
}
- }
- // --------------------------------------------------------------------
+ $client_flags = ($this->compress === TRUE) ? MYSQLI_CLIENT_COMPRESS : 0;
+ $this->_mysqli = mysqli_init();
- /**
- * Version number query string
- *
- * @access public
- * @return string
- */
- function _version()
- {
- return "SELECT version() AS ver";
- }
+ $this->_mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 10);
- // --------------------------------------------------------------------
+ if (isset($this->stricton))
+ {
+ if ($this->stricton)
+ {
+ $this->_mysqli->options(MYSQLI_INIT_COMMAND, 'SET SESSION sql_mode = CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")');
+ }
+ else
+ {
+ $this->_mysqli->options(MYSQLI_INIT_COMMAND,
+ 'SET SESSION sql_mode =
+ REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
+ @@sql_mode,
+ "STRICT_ALL_TABLES,", ""),
+ ",STRICT_ALL_TABLES", ""),
+ "STRICT_ALL_TABLES", ""),
+ "STRICT_TRANS_TABLES,", ""),
+ ",STRICT_TRANS_TABLES", ""),
+ "STRICT_TRANS_TABLES", "")'
+ );
+ }
+ }
- /**
- * Execute the query
- *
- * @access private called by the base class
- * @param string an SQL query
- * @return resource
- */
- function _execute($sql)
- {
- $sql = $this->_prep_query($sql);
- $result = @mysqli_query($this->conn_id, $sql);
- return $result;
- }
+ if (is_array($this->encrypt))
+ {
+ $ssl = array();
+ empty($this->encrypt['ssl_key']) OR $ssl['key'] = $this->encrypt['ssl_key'];
+ empty($this->encrypt['ssl_cert']) OR $ssl['cert'] = $this->encrypt['ssl_cert'];
+ empty($this->encrypt['ssl_ca']) OR $ssl['ca'] = $this->encrypt['ssl_ca'];
+ empty($this->encrypt['ssl_capath']) OR $ssl['capath'] = $this->encrypt['ssl_capath'];
+ empty($this->encrypt['ssl_cipher']) OR $ssl['cipher'] = $this->encrypt['ssl_cipher'];
+
+ if ( ! empty($ssl))
+ {
+ if (isset($this->encrypt['ssl_verify']))
+ {
+ if ($this->encrypt['ssl_verify'])
+ {
+ defined('MYSQLI_OPT_SSL_VERIFY_SERVER_CERT') && $this->_mysqli->options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, TRUE);
+ }
+ // Apparently (when it exists), setting MYSQLI_OPT_SSL_VERIFY_SERVER_CERT
+ // to FALSE didn't do anything, so PHP 5.6.16 introduced yet another
+ // constant ...
+ //
+ // https://secure.php.net/ChangeLog-5.php#5.6.16
+ // https://bugs.php.net/bug.php?id=68344
+ elseif (defined('MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT'))
+ {
+ $client_flags |= MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT;
+ }
+ }
- // --------------------------------------------------------------------
+ $client_flags |= MYSQLI_CLIENT_SSL;
+ $this->_mysqli->ssl_set(
+ isset($ssl['key']) ? $ssl['key'] : NULL,
+ isset($ssl['cert']) ? $ssl['cert'] : NULL,
+ isset($ssl['ca']) ? $ssl['ca'] : NULL,
+ isset($ssl['capath']) ? $ssl['capath'] : NULL,
+ isset($ssl['cipher']) ? $ssl['cipher'] : NULL
+ );
+ }
+ }
- /**
- * Prep the query
- *
- * If needed, each database adapter can prep the query string
- *
- * @access private called by execute()
- * @param string an SQL query
- * @return string
- */
- function _prep_query($sql)
- {
- // "DELETE FROM TABLE" returns 0 affected rows This hack modifies
- // the query so that it returns the number of affected rows
- if ($this->delete_hack === TRUE)
+ if ($this->_mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, $socket, $client_flags))
{
- if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
+ // Prior to version 5.7.3, MySQL silently downgrades to an unencrypted connection if SSL setup fails
+ if (
+ ($client_flags & MYSQLI_CLIENT_SSL)
+ && version_compare($this->_mysqli->client_info, '5.7.3', '<=')
+ && empty($this->_mysqli->query("SHOW STATUS LIKE 'ssl_cipher'")->fetch_object()->Value)
+ )
{
- $sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql);
+ $this->_mysqli->close();
+ $message = 'MySQLi was configured for an SSL connection, but got an unencrypted connection instead!';
+ log_message('error', $message);
+ return ($this->db_debug) ? $this->display_error($message, '', TRUE) : FALSE;
}
+
+ return $this->_mysqli;
}
- return $sql;
+ return FALSE;
}
// --------------------------------------------------------------------
/**
- * Begin Transaction
+ * Reconnect
*
- * @access public
- * @return bool
+ * Keep / reestablish the db connection if no queries have been
+ * sent for a length of time exceeding the server's idle timeout
+ *
+ * @return void
*/
- function trans_begin($test_mode = FALSE)
+ public function reconnect()
{
- if ( ! $this->trans_enabled)
+ if ($this->conn_id !== FALSE && $this->conn_id->ping() === FALSE)
{
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
+ $this->conn_id = FALSE;
}
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
-
- $this->simple_query('SET AUTOCOMMIT=0');
- $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
- return TRUE;
}
// --------------------------------------------------------------------
/**
- * Commit Transaction
+ * Select the database
*
- * @access public
+ * @param string $database
* @return bool
*/
- function trans_commit()
+ public function db_select($database = '')
{
- if ( ! $this->trans_enabled)
+ if ($database === '')
{
- return TRUE;
+ $database = $this->database;
}
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ($this->conn_id->select_db($database))
{
+ $this->database = $database;
+ $this->data_cache = array();
return TRUE;
}
- $this->simple_query('COMMIT');
- $this->simple_query('SET AUTOCOMMIT=1');
- return TRUE;
+ return FALSE;
}
// --------------------------------------------------------------------
/**
- * Rollback Transaction
+ * Set client character set
*
- * @access public
+ * @param string $charset
* @return bool
*/
- function trans_rollback()
+ protected function _db_set_charset($charset)
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- $this->simple_query('ROLLBACK');
- $this->simple_query('SET AUTOCOMMIT=1');
- return TRUE;
+ return $this->conn_id->set_charset($charset);
}
// --------------------------------------------------------------------
/**
- * Escape String
+ * Database version number
*
- * @access public
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
* @return string
*/
- function escape_str($str, $like = FALSE)
+ public function version()
{
- if (is_array($str))
+ if (isset($this->data_cache['version']))
{
- foreach ($str as $key => $val)
- {
- $str[$key] = $this->escape_str($val, $like);
- }
-
- return $str;
+ return $this->data_cache['version'];
}
- if (function_exists('mysqli_real_escape_string') AND is_object($this->conn_id))
- {
- $str = mysqli_real_escape_string($this->conn_id, $str);
- }
- elseif (function_exists('mysql_escape_string'))
- {
- $str = mysql_escape_string($str);
- }
- else
- {
- $str = addslashes($str);
- }
-
- // escape LIKE condition wildcards
- if ($like === TRUE)
- {
- $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str);
- }
-
- return $str;
+ return $this->data_cache['version'] = $this->conn_id->server_info;
}
// --------------------------------------------------------------------
/**
- * Affected Rows
- *
- * @access public
- * @return integer
- */
- function affected_rows()
- {
- return @mysqli_affected_rows($this->conn_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Insert ID
+ * Execute the query
*
- * @access public
- * @return integer
+ * @param string $sql an SQL query
+ * @return mixed
*/
- function insert_id()
+ protected function _execute($sql)
{
- return @mysqli_insert_id($this->conn_id);
+ return $this->conn_id->query($this->_prep_query($sql));
}
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @access public
- * @param string
- * @return string
- */
- function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
-
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * List table query
+ * Prep the query
*
- * Generates a platform-specific query string so that the table names can be fetched
+ * If needed, each database adapter can prep the query string
*
- * @access private
- * @param boolean
+ * @param string $sql an SQL query
* @return string
*/
- function _list_tables($prefix_limit = FALSE)
+ protected function _prep_query($sql)
{
- $sql = "SHOW TABLES FROM ".$this->_escape_char.$this->database.$this->_escape_char;
-
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ // mysqli_affected_rows() returns 0 for "DELETE FROM TABLE" queries. This hack
+ // modifies the query so that it a proper number of affected rows is returned.
+ if ($this->delete_hack === TRUE && preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
{
- $sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%'";
+ return trim($sql).' WHERE 1=1';
}
return $sql;
@@ -416,342 +330,203 @@ class CI_DB_mysqli_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Show column query
- *
- * Generates a platform-specific query string so that the column names can be fetched
+ * Begin Transaction
*
- * @access public
- * @param string the table name
- * @return string
+ * @return bool
*/
- function _list_columns($table = '')
+ protected function _trans_begin()
{
- return "SHOW COLUMNS FROM ".$this->_protect_identifiers($table, TRUE, NULL, FALSE);
+ $this->conn_id->autocommit(FALSE);
+ return is_php('5.5')
+ ? $this->conn_id->begin_transaction()
+ : $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
}
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Commit Transaction
*
- * @access public
- * @param string the table name
- * @return object
+ * @return bool
*/
- function _field_data($table)
+ protected function _trans_commit()
{
- return "DESCRIBE ".$table;
- }
-
- // --------------------------------------------------------------------
+ if ($this->conn_id->commit())
+ {
+ $this->conn_id->autocommit(TRUE);
+ return TRUE;
+ }
- /**
- * The error message string
- *
- * @access private
- * @return string
- */
- function _error_message()
- {
- return mysqli_error($this->conn_id);
+ return FALSE;
}
// --------------------------------------------------------------------
/**
- * The error message number
+ * Rollback Transaction
*
- * @access private
- * @return integer
+ * @return bool
*/
- function _error_number()
+ protected function _trans_rollback()
{
- return mysqli_errno($this->conn_id);
+ if ($this->conn_id->rollback())
+ {
+ $this->conn_id->autocommit(TRUE);
+ return TRUE;
+ }
+
+ return FALSE;
}
// --------------------------------------------------------------------
/**
- * Escape the SQL Identifiers
- *
- * This function escapes column and table names
+ * Platform-dependent string escape
*
- * @access private
* @param string
* @return string
*/
- function _escape_identifiers($item)
+ protected function _escape_str($str)
{
- if ($this->_escape_char == '')
- {
- return $item;
- }
-
- foreach ($this->_reserved_identifiers as $id)
- {
- if (strpos($item, '.'.$id) !== FALSE)
- {
- $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
- }
- }
-
- if (strpos($item, '.') !== FALSE)
- {
- $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
- }
- else
- {
- $str = $this->_escape_char.$item.$this->_escape_char;
- }
-
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
+ return $this->conn_id->real_escape_string($str);
}
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
+ * Affected Rows
*
- * @access public
- * @param type
- * @return type
+ * @return int
*/
- function _from_tables($tables)
+ public function affected_rows()
{
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
+ return $this->conn_id->affected_rows;
}
// --------------------------------------------------------------------
/**
- * Insert statement
- *
- * Generates a platform-specific insert string from the supplied data
+ * Insert ID
*
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
+ * @return int
*/
- function _insert($table, $keys, $values)
+ public function insert_id()
{
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ return $this->conn_id->insert_id;
}
// --------------------------------------------------------------------
/**
- * Insert_batch statement
+ * List table query
*
- * Generates a platform-specific insert string from the supplied data
+ * Generates a platform-specific query string so that the table names can be fetched
*
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
+ * @param bool $prefix_limit
* @return string
*/
- function _insert_batch($table, $keys, $values)
+ protected function _list_tables($prefix_limit = FALSE)
{
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values);
- }
-
- // --------------------------------------------------------------------
+ $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
+ {
+ return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'";
+ }
- /**
- * Replace statement
- *
- * Generates a platform-specific replace string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
- */
- function _replace($table, $keys, $values)
- {
- return "REPLACE INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ return $sql;
}
-
+
// --------------------------------------------------------------------
/**
- * Update statement
+ * Show column query
*
- * Generates a platform-specific update string from the supplied data
+ * Generates a platform-specific query string so that the column names can be fetched
*
- * @access public
- * @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
+ * @param string $table
* @return string
*/
- function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
+ protected function _list_columns($table = '')
{
- foreach ($values as $key => $val)
- {
- $valstr[] = $key." = ".$val;
- }
-
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
- $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
- $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
- $sql .= $orderby.$limit;
-
- return $sql;
+ return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
}
// --------------------------------------------------------------------
/**
- * Update_Batch statement
- *
- * Generates a platform-specific batch update string from the supplied data
+ * Returns an object with field data
*
- * @access public
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @return string
+ * @param string $table
+ * @return array
*/
- function _update_batch($table, $values, $index, $where = NULL)
+ public function field_data($table)
{
- $ids = array();
- $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : '';
-
- foreach ($values as $key => $val)
+ if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)
{
- $ids[] = $val[$index];
-
- foreach (array_keys($val) as $field)
- {
- if ($field != $index)
- {
- $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
- }
- }
+ return FALSE;
}
+ $query = $query->result_object();
- $sql = "UPDATE ".$table." SET ";
- $cases = '';
-
- foreach ($final as $k => $v)
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
{
- $cases .= $k.' = CASE '."\n";
- foreach ($v as $row)
- {
- $cases .= $row."\n";
- }
-
- $cases .= 'ELSE '.$k.' END, ';
- }
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->Field;
- $sql .= substr($cases, 0, -2);
+ sscanf($query[$i]->Type, '%[a-z](%d)',
+ $retval[$i]->type,
+ $retval[$i]->max_length
+ );
- $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
+ $retval[$i]->default = $query[$i]->Default;
+ $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI');
+ }
- return $sql;
+ return $retval;
}
// --------------------------------------------------------------------
/**
- * Truncate statement
+ * Error
*
- * Generates a platform-specific truncate string from the supplied data
- * If the database does not support the truncate() command
- * This function maps to "DELETE FROM table"
+ * Returns an array containing code and message of the last
+ * database error that has occurred.
*
- * @access public
- * @param string the table name
- * @return string
+ * @return array
*/
- function _truncate($table)
+ public function error()
{
- return "TRUNCATE ".$table;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Delete statement
- *
- * Generates a platform-specific delete string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the where clause
- * @param string the limit clause
- * @return string
- */
- function _delete($table, $where = array(), $like = array(), $limit = FALSE)
- {
- $conditions = '';
-
- if (count($where) > 0 OR count($like) > 0)
+ if ( ! empty($this->_mysqli->connect_errno))
{
- $conditions = "\nWHERE ";
- $conditions .= implode("\n", $this->ar_where);
-
- if (count($where) > 0 && count($like) > 0)
- {
- $conditions .= " AND ";
- }
- $conditions .= implode("\n", $like);
+ return array(
+ 'code' => $this->_mysqli->connect_errno,
+ 'message' => $this->_mysqli->connect_error
+ );
}
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- return "DELETE FROM ".$table.$conditions.$limit;
+ return array('code' => $this->conn_id->errno, 'message' => $this->conn_id->error);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * FROM tables
*
- * Generates a platform-specific LIMIT clause
+ * Groups tables in FROM clauses if needed, so there is no confusion
+ * about operator precedence.
*
- * @access public
- * @param string the sql query string
- * @param integer the number of rows to limit the query to
- * @param integer the offset value
* @return string
*/
- function _limit($sql, $limit, $offset)
+ protected function _from_tables()
{
- $sql .= "LIMIT ".$limit;
-
- if ($offset > 0)
+ if ( ! empty($this->qb_join) && count($this->qb_from) > 1)
{
- $sql .= " OFFSET ".$offset;
+ return '('.implode(', ', $this->qb_from).')';
}
- return $sql;
+ return implode(', ', $this->qb_from);
}
// --------------------------------------------------------------------
@@ -759,18 +534,11 @@ class CI_DB_mysqli_driver extends CI_DB {
/**
* Close DB Connection
*
- * @access public
- * @param resource
* @return void
*/
- function _close($conn_id)
+ protected function _close()
{
- @mysqli_close($conn_id);
+ $this->conn_id->close();
}
-
}
-
-
-/* End of file mysqli_driver.php */
-/* Location: ./system/database/drivers/mysqli/mysqli_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/mysqli/mysqli_forge.php b/system/database/drivers/mysqli/mysqli_forge.php
index f11cd7f26..c5b23b6ca 100644
--- a/system/database/drivers/mysqli/mysqli_forge.php
+++ b/system/database/drivers/mysqli/mysqli_forge.php
@@ -1,129 +1,125 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQLi Forge Class
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_mysqli_forge extends CI_DB_forge {
/**
- * Create database
+ * CREATE DATABASE statement
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var string
*/
- function _create_database($name)
- {
- return "CREATE DATABASE ".$name;
- }
+ protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';
- // --------------------------------------------------------------------
+ /**
+ * CREATE TABLE keys flag
+ *
+ * Whether table keys are created from within the
+ * CREATE TABLE statement.
+ *
+ * @var bool
+ */
+ protected $_create_table_keys = TRUE;
/**
- * Drop database
+ * UNSIGNED support
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var array
*/
- function _drop_database($name)
- {
- return "DROP DATABASE ".$name;
- }
+ 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';
// --------------------------------------------------------------------
/**
- * Process Fields
+ * CREATE TABLE attributes
*
- * @access private
- * @param mixed the fields
+ * @param array $attributes Associative array of table attributes
* @return string
*/
- function _process_fields($fields)
+ protected function _create_table_attr($attributes)
{
- $current_field_count = 0;
$sql = '';
- foreach ($fields as $field=>$attributes)
+ foreach (array_keys($attributes) as $key)
{
- // 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 (is_string($key))
{
- $sql .= "\n\t$attributes";
+ $sql .= ' '.strtoupper($key).' = '.$attributes[$key];
}
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->_protect_identifiers($field);
-
- if (array_key_exists('NAME', $attributes))
- {
- $sql .= ' '.$this->db->_protect_identifiers($attributes['NAME']).' ';
- }
-
- if (array_key_exists('TYPE', $attributes))
- {
- $sql .= ' '.$attributes['TYPE'];
- }
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
+ }
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ if ( ! empty($this->db->char_set) && ! strpos($sql, 'CHARACTER SET') && ! strpos($sql, 'CHARSET'))
+ {
+ $sql .= ' DEFAULT CHARACTER SET = '.$this->db->char_set;
+ }
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
+ if ( ! empty($this->db->dbcollat) && ! strpos($sql, 'COLLATE'))
+ {
+ $sql .= ' COLLATE = '.$this->db->dbcollat;
}
return $sql;
@@ -132,127 +128,117 @@ class CI_DB_mysqli_forge extends CI_DB_forge {
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @access private
- * @param string the table name
- * @param mixed the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param boolean 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[]
*/
- 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)
+ if ($alter_type === 'DROP')
{
- $sql .= 'IF NOT EXISTS ';
+ return parent::_alter_table($alter_type, $table, $field);
}
- $sql .= $this->db->_escape_identifiers($table)." (";
-
- $sql .= $this->_process_fields($fields);
-
- if (count($primary_keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- $key_name = $this->db->_protect_identifiers(implode('_', $primary_keys));
- $primary_keys = $this->db->_protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY ".$key_name." (" . implode(', ', $primary_keys) . ")";
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ $field[$i] = ($alter_type === 'ADD')
+ ? "\n\tADD ".$field[$i]['_literal']
+ : "\n\tMODIFY ".$field[$i]['_literal'];
+ }
+ else
{
- if (is_array($key))
+ if ($alter_type === 'ADD')
{
- $key_name = $this->db->_protect_identifiers(implode('_', $key));
- $key = $this->db->_protect_identifiers($key);
+ $field[$i]['_literal'] = "\n\tADD ";
}
else
{
- $key_name = $this->db->_protect_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]);
}
}
- $sql .= "\n) DEFAULT CHARACTER SET {$this->db->char_set} COLLATE {$this->db->dbcollat};";
-
- return $sql;
+ return array($sql.implode(',', $field));
}
// --------------------------------------------------------------------
/**
- * Drop Table
+ * Process column
*
- * @access private
+ * @param array $field
* @return string
*/
- function _drop_table($table)
+ protected function _process_column($field)
{
- return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table);
+ $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']
+ .(empty($field['comment']) ? '' : ' COMMENT '.$field['comment'])
+ .$extra_clause;
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Process indexes
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
- *
- * @access private
- * @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
- * @return object
+ * @param string $table (ignored)
+ * @return string
*/
- function _alter_table($alter_type, $table, $fields, $after_field = '')
+ protected function _process_indexes($table)
{
- $sql = 'ALTER TABLE '.$this->db->_protect_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->_protect_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;
+ }
- $sql .= $this->_process_fields($fields);
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
- if ($after_field != '')
- {
- $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
- return $sql;
- }
-
- // --------------------------------------------------------------------
+ $this->keys = array();
- /**
- * Rename a table
- *
- * Generates a platform-specific query so that a table can be renamed
- *
- * @access private
- * @param string the old table name
- * @param string the new table name
- * @return string
- */
- function _rename_table($table_name, $new_table_name)
- {
- $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name);
return $sql;
}
}
-
-/* End of file mysqli_forge.php */
-/* Location: ./system/database/drivers/mysqli/mysqli_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php
index 4be381a4a..929c2b455 100644
--- a/system/database/drivers/mysqli/mysqli_result.php
+++ b/system/database/drivers/mysqli/mysqli_result.php
@@ -1,40 +1,65 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQLi Result Class
*
* This class extends the parent result class: CI_DB_result
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_mysqli_result extends CI_DB_result {
/**
* Number of rows in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_rows()
+ public function num_rows()
{
- return @mysqli_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = $this->result_id->num_rows;
}
// --------------------------------------------------------------------
@@ -42,12 +67,11 @@ class CI_DB_mysqli_result extends CI_DB_result {
/**
* Number of fields in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_fields()
+ public function num_fields()
{
- return @mysqli_num_fields($this->result_id);
+ return $this->result_id->field_count;
}
// --------------------------------------------------------------------
@@ -57,13 +81,13 @@ class CI_DB_mysqli_result extends CI_DB_result {
*
* Generates an array of column names
*
- * @access public
* @return array
*/
- function list_fields()
+ public function list_fields()
{
$field_names = array();
- while ($field = mysqli_fetch_field($this->result_id))
+ $this->result_id->field_seek(0);
+ while ($field = $this->result_id->fetch_field())
{
$field_names[] = $field->name;
}
@@ -78,44 +102,37 @@ class CI_DB_mysqli_result extends CI_DB_result {
*
* Generates an array of objects containing field meta-data
*
- * @access public
* @return array
*/
- function field_data()
+ public function field_data()
{
$retval = array();
- while ($field = mysqli_fetch_object($this->result_id))
+ $field_data = $this->result_id->fetch_fields();
+ for ($i = 0, $c = count($field_data); $i < $c; $i++)
{
- preg_match('/([a-zA-Z]+)(\(\d+\))?/', $field->Type, $matches);
-
- $type = (array_key_exists(1, $matches)) ? $matches[1] : NULL;
- $length = (array_key_exists(2, $matches)) ? preg_replace('/[^\d]/', '', $matches[2]) : NULL;
-
- $F = new stdClass();
- $F->name = $field->Field;
- $F->type = $type;
- $F->default = $field->Default;
- $F->max_length = $length;
- $F->primary_key = ( $field->Key == 'PRI' ? 1 : 0 );
-
- $retval[] = $F;
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $field_data[$i]->name;
+ $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 = $field_data[$i]->def;
}
return $retval;
}
-
+
// --------------------------------------------------------------------
/**
* Free the result
*
- * @return null
+ * @return void
*/
- function free_result()
+ public function free_result()
{
if (is_object($this->result_id))
{
- mysqli_free_result($this->result_id);
+ $this->result_id->free();
$this->result_id = FALSE;
}
}
@@ -125,16 +142,16 @@ class CI_DB_mysqli_result extends CI_DB_result {
/**
* Data Seek
*
- * Moves the internal pointer to the desired offset. We call
+ * 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.
*
- * @access private
- * @return array
+ * @param int $n
+ * @return bool
*/
- function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
- return mysqli_data_seek($this->result_id, $n);
+ return $this->result_id->data_seek($n);
}
// --------------------------------------------------------------------
@@ -144,12 +161,11 @@ class CI_DB_mysqli_result extends CI_DB_result {
*
* Returns the result set as an array
*
- * @access private
* @return array
*/
- function _fetch_assoc()
+ protected function _fetch_assoc()
{
- return mysqli_fetch_assoc($this->result_id);
+ return $this->result_id->fetch_assoc();
}
// --------------------------------------------------------------------
@@ -159,16 +175,12 @@ class CI_DB_mysqli_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @access private
+ * @param string $class_name
* @return object
*/
- function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return mysqli_fetch_object($this->result_id);
+ return $this->result_id->fetch_object($class_name);
}
}
-
-
-/* End of file mysqli_result.php */
-/* Location: ./system/database/drivers/mysqli/mysqli_result.php */ \ No newline at end of file
diff --git a/system/database/drivers/mysqli/mysqli_utility.php b/system/database/drivers/mysqli/mysqli_utility.php
index bc613a557..4a3dad4d1 100644
--- a/system/database/drivers/mysqli/mysqli_utility.php
+++ b/system/database/drivers/mysqli/mysqli_utility.php
@@ -1,87 +1,213 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* MySQLi Utility Class
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_mysqli_utility extends CI_DB_utility {
/**
- * List databases
+ * List databases statement
*
- * @access private
- * @return bool
+ * @var string
*/
- function _list_databases()
- {
- return "SHOW DATABASES";
- }
-
- // --------------------------------------------------------------------
+ protected $_list_databases = 'SHOW DATABASES';
/**
- * Optimize table query
+ * OPTIMIZE TABLE statement
*
- * Generates a platform-specific query so that a table can be optimized
- *
- * @access private
- * @param string the table name
- * @return object
+ * @var string
*/
- function _optimize_table($table)
- {
- return "OPTIMIZE TABLE ".$this->db->_escape_identifiers($table);
- }
-
- // --------------------------------------------------------------------
+ protected $_optimize_table = 'OPTIMIZE TABLE %s';
/**
- * Repair table query
- *
- * Generates a platform-specific query so that a table can be repaired
+ * REPAIR TABLE statement
*
- * @access private
- * @param string the table name
- * @return object
+ * @var string
*/
- function _repair_table($table)
- {
- return "REPAIR TABLE ".$this->db->_escape_identifiers($table);
- }
+ protected $_repair_table = 'REPAIR TABLE %s';
// --------------------------------------------------------------------
/**
- * MySQLi Export
+ * Export
*
- * @access private
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
- function _backup($params = array())
+ protected function _backup($params = array())
{
- // Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ if (count($params) === 0)
+ {
+ return FALSE;
+ }
+
+ // Extract the prefs for simplicity
+ extract($params);
+
+ // Build the output
+ $output = '';
+
+ // Do we need to include a statement to disable foreign key checks?
+ if ($foreign_key_checks === FALSE)
+ {
+ $output .= 'SET foreign_key_checks = 0;'.$newline;
+ }
+
+ foreach ( (array) $tables as $table)
+ {
+ // Is the table in the "ignore" list?
+ if (in_array($table, (array) $ignore, TRUE))
+ {
+ continue;
+ }
+
+ // Get the table schema
+ $query = $this->db->query('SHOW CREATE TABLE '.$this->db->escape_identifiers($this->db->database.'.'.$table));
+
+ // No result means the table name was invalid
+ if ($query === FALSE)
+ {
+ continue;
+ }
+
+ // Write out the table schema
+ $output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline;
+
+ if ($add_drop === TRUE)
+ {
+ $output .= 'DROP TABLE IF EXISTS '.$this->db->protect_identifiers($table).';'.$newline.$newline;
+ }
+
+ $i = 0;
+ $result = $query->result_array();
+ foreach ($result[0] as $val)
+ {
+ if ($i++ % 2)
+ {
+ $output .= $val.';'.$newline.$newline;
+ }
+ }
+
+ // If inserts are not needed we're done...
+ if ($add_insert === FALSE)
+ {
+ continue;
+ }
+
+ // Grab all the data from the current table
+ $query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table));
+
+ if ($query->num_rows() === 0)
+ {
+ continue;
+ }
+
+ // Fetch the field names and determine if the field is an
+ // integer type. We use this info to decide whether to
+ // surround the data with quotes or not
+
+ $i = 0;
+ $field_str = '';
+ $is_int = array();
+ while ($field = $query->result_id->fetch_field())
+ {
+ // Most versions of MySQL store timestamp as a string
+ $is_int[$i] = in_array(strtolower($field->type),
+ array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'),
+ TRUE);
+
+ // Create a string of field names
+ $field_str .= $this->db->escape_identifiers($field->name).', ';
+ $i++;
+ }
+
+ // Trim off the end comma
+ $field_str = preg_replace('/, $/' , '', $field_str);
+
+ // Build the insert string
+ foreach ($query->result_array() as $row)
+ {
+ $val_str = '';
+
+ $i = 0;
+ foreach ($row as $v)
+ {
+ // Is the value NULL?
+ if ($v === NULL)
+ {
+ $val_str .= 'NULL';
+ }
+ else
+ {
+ // Escape the data if it's not an integer
+ $val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v;
+ }
+
+ // Append a comma
+ $val_str .= ', ';
+ $i++;
+ }
+
+ // Remove the comma at the end of the string
+ $val_str = preg_replace('/, $/' , '', $val_str);
+
+ // Build the INSERT string
+ $output .= 'INSERT INTO '.$this->db->protect_identifiers($table).' ('.$field_str.') VALUES ('.$val_str.');'.$newline;
+ }
+
+ $output .= $newline.$newline;
+ }
+
+ // Do we need to include a statement to re-enable foreign key checks?
+ if ($foreign_key_checks === FALSE)
+ {
+ $output .= 'SET foreign_key_checks = 1;'.$newline;
+ }
+
+ return $output;
}
-}
-/* End of file mysqli_utility.php */
-/* Location: ./system/database/drivers/mysqli/mysqli_utility.php */ \ No newline at end of file
+}
diff --git a/system/database/drivers/oci8/index.html b/system/database/drivers/oci8/index.html
index c942a79ce..b702fbc39 100644
--- a/system/database/drivers/oci8/index.html
+++ b/system/database/drivers/oci8/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index 6255b330a..fb2f6b31b 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -1,32 +1,54 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.4.1
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* oci8 Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
* @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
/**
@@ -36,185 +58,244 @@
* permit access to oracle databases
*
* @author Kelly McArdle
- *
*/
-
class CI_DB_oci8_driver extends CI_DB {
- var $dbdriver = 'oci8';
-
- // The character used for excaping
- var $_escape_char = '"';
-
- // clause and character used for LIKE escape sequences
- var $_like_escape_str = " escape '%s' ";
- var $_like_escape_chr = '!';
-
/**
- * 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.
+ * Database driver
+ *
+ * @var string
*/
- var $_count_string = "SELECT COUNT(1) AS ";
- var $_random_keyword = ' ASC'; // not currently supported
+ public $dbdriver = 'oci8';
- // Set "auto commit" by default
- var $_commit = OCI_COMMIT_ON_SUCCESS;
+ /**
+ * Statement ID
+ *
+ * @var resource
+ */
+ public $stmt_id;
- // need to track statement id and cursor id
- var $stmt_id;
- var $curs_id;
+ /**
+ * Cursor ID
+ *
+ * @var resource
+ */
+ public $curs_id;
- // if we use a limit, we will add a field that will
- // throw off num_fields later
- var $limit_used;
+ /**
+ * Commit mode flag
+ *
+ * @var int
+ */
+ public $commit_mode = OCI_COMMIT_ON_SUCCESS;
/**
- * Non-persistent database connection
+ * Limit used flag
+ *
+ * If we use LIMIT, we'll add a field that will
+ * throw off num_fields later.
*
- * @access private called by the base class
- * @return resource
+ * @var bool
*/
- public function db_connect()
- {
- return @oci_connect($this->username, $this->password, $this->hostname, $this->char_set);
- }
+ public $limit_used;
// --------------------------------------------------------------------
/**
- * Persistent database connection
+ * Reset $stmt_id flag
*
- * @access private called by the base class
- * @return resource
+ * Used by stored_procedure() to prevent _execute() from
+ * re-setting the statement ID.
*/
- public function db_pconnect()
- {
- return @oci_pconnect($this->username, $this->password, $this->hostname, $this->char_set);
- }
-
- // --------------------------------------------------------------------
+ protected $_reset_stmt_id = TRUE;
/**
- * Reconnect
+ * List of reserved identifiers
*
- * Keep / reestablish the db connection if no queries have been
- * sent for a length of time exceeding the server's idle timeout
+ * Identifiers that must NOT be escaped.
*
- * @access public
- * @return void
+ * @var string[]
*/
- public function reconnect()
- {
- // not implemented in oracle
- return;
- }
-
- // --------------------------------------------------------------------
+ protected $_reserved_identifiers = array('*', 'rownum');
/**
- * Select the database
+ * ORDER BY random keyword
*
- * @access private called by the base class
- * @return resource
+ * @var array
*/
- public function db_select()
- {
- // Not in Oracle - schemas are actually usernames
- return TRUE;
- }
-
- // --------------------------------------------------------------------
+ protected $_random_keyword = array('ASC', 'ASC'); // not currently supported
/**
- * Set client character set
+ * COUNT string
*
- * @access public
- * @param string
- * @param string
- * @return resource
+ * @used-by CI_DB_driver::count_all()
+ * @used-by CI_DB_query_builder::count_all_results()
+ *
+ * @var string
*/
- public function db_set_charset($charset, $collation)
- {
- // @todo - add support if needed
- return TRUE;
- }
+ protected $_count_string = 'SELECT COUNT(1) AS ';
// --------------------------------------------------------------------
/**
- * Version number query string
+ * Class constructor
*
- * @access protected
- * @return string
+ * @param array $params
+ * @return void
*/
- protected function _version()
+ public function __construct($params)
{
- return oci_server_version($this->conn_id);
+ parent::__construct($params);
+
+ $valid_dsns = array(
+ 'tns' => '/^\(DESCRIPTION=(\(.+\)){2,}\)$/', // TNS
+ // Easy Connect string (Oracle 10g+)
+ 'ec' => '/^(\/\/)?[a-z0-9.:_-]+(:[1-9][0-9]{0,4})?(\/[a-z0-9$_]+)?(:[^\/])?(\/[a-z0-9$_]+)?$/i',
+ 'in' => '/^[a-z0-9$_]+$/i' // Instance name (defined in tnsnames.ora)
+ );
+
+ /* Space characters don't have any effect when actually
+ * connecting, but can be a hassle while validating the DSN.
+ */
+ $this->dsn = str_replace(array("\n", "\r", "\t", ' '), '', $this->dsn);
+
+ if ($this->dsn !== '')
+ {
+ foreach ($valid_dsns as $regexp)
+ {
+ if (preg_match($regexp, $this->dsn))
+ {
+ return;
+ }
+ }
+ }
+
+ // Legacy support for TNS in the hostname configuration field
+ $this->hostname = str_replace(array("\n", "\r", "\t", ' '), '', $this->hostname);
+ if (preg_match($valid_dsns['tns'], $this->hostname))
+ {
+ $this->dsn = $this->hostname;
+ return;
+ }
+ elseif ($this->hostname !== '' && strpos($this->hostname, '/') === FALSE && strpos($this->hostname, ':') === FALSE
+ && (( ! empty($this->port) && ctype_digit($this->port)) OR $this->database !== ''))
+ {
+ /* If the hostname field isn't empty, doesn't contain
+ * ':' and/or '/' and if port and/or database aren't
+ * empty, then the hostname field is most likely indeed
+ * just a hostname. Therefore we'll try and build an
+ * Easy Connect string from these 3 settings, assuming
+ * that the database field is a service name.
+ */
+ $this->dsn = $this->hostname
+ .(( ! empty($this->port) && ctype_digit($this->port)) ? ':'.$this->port : '')
+ .($this->database !== '' ? '/'.ltrim($this->database, '/') : '');
+
+ if (preg_match($valid_dsns['ec'], $this->dsn))
+ {
+ return;
+ }
+ }
+
+ /* At this point, we can only try and validate the hostname and
+ * database fields separately as DSNs.
+ */
+ if (preg_match($valid_dsns['ec'], $this->hostname) OR preg_match($valid_dsns['in'], $this->hostname))
+ {
+ $this->dsn = $this->hostname;
+ return;
+ }
+
+ $this->database = str_replace(array("\n", "\r", "\t", ' '), '', $this->database);
+ foreach ($valid_dsns as $regexp)
+ {
+ if (preg_match($regexp, $this->database))
+ {
+ return;
+ }
+ }
+
+ /* Well - OK, an empty string should work as well.
+ * PHP will try to use environment variables to
+ * determine which Oracle instance to connect to.
+ */
+ $this->dsn = '';
}
// --------------------------------------------------------------------
/**
- * Execute the query
+ * Non-persistent database connection
*
- * @access protected called by the base class
- * @param string an SQL query
- * @return resource
+ * @param bool $persistent
+ * @return resource
*/
- protected function _execute($sql)
+ public function db_connect($persistent = FALSE)
{
- // oracle must parse the query before it is run. All of the actions with
- // the query are based on the statement id returned by ociparse
- $this->stmt_id = FALSE;
- $this->_set_stmt_id($sql);
- oci_set_prefetch($this->stmt_id, 1000);
- return @oci_execute($this->stmt_id, $this->_commit);
+ $func = ($persistent === TRUE) ? 'oci_pconnect' : 'oci_connect';
+ return empty($this->char_set)
+ ? $func($this->username, $this->password, $this->dsn)
+ : $func($this->username, $this->password, $this->dsn, $this->char_set);
}
+ // --------------------------------------------------------------------
+
/**
- * Generate a statement ID
+ * Database version number
*
- * @access private
- * @param string an SQL query
- * @return none
+ * @return string
*/
- private function _set_stmt_id($sql)
+ public function version()
{
- if ( ! is_resource($this->stmt_id))
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+
+ if ( ! $this->conn_id OR ($version_string = oci_server_version($this->conn_id)) === FALSE)
{
- $this->stmt_id = oci_parse($this->conn_id, $this->_prep_query($sql));
+ return FALSE;
+ }
+ elseif (preg_match('#Release\s(\d+(?:\.\d+)+)#', $version_string, $match))
+ {
+ return $this->data_cache['version'] = $match[1];
}
+
+ return FALSE;
}
// --------------------------------------------------------------------
/**
- * Prep the query
- *
- * If needed, each database adapter can prep the query string
+ * Execute the query
*
- * @access private called by execute()
- * @param string an SQL query
- * @return string
+ * @param string $sql an SQL query
+ * @return resource
*/
- private function _prep_query($sql)
+ protected function _execute($sql)
{
- return $sql;
+ /* Oracle must parse the query before it is run. All of the actions with
+ * the query are based on the statement id returned by oci_parse().
+ */
+ if ($this->_reset_stmt_id === TRUE)
+ {
+ $this->stmt_id = oci_parse($this->conn_id, $sql);
+ }
+
+ oci_set_prefetch($this->stmt_id, 1000);
+ return oci_execute($this->stmt_id, $this->commit_mode);
}
// --------------------------------------------------------------------
/**
- * getCursor. Returns a cursor from the datbase
+ * Get cursor. Returns a cursor from the database
*
- * @access public
- * @return cursor id
+ * @return resource
*/
public function get_cursor()
{
- $this->curs_id = oci_new_cursor($this->conn_id);
- return $this->curs_id;
+ return $this->curs_id = oci_new_cursor($this->conn_id);
}
// --------------------------------------------------------------------
@@ -222,52 +303,49 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Stored Procedure. Executes a stored procedure
*
- * @access public
- * @param package package stored procedure is in
- * @param procedure stored procedure to execute
- * @param params array of parameters
- * @return array
+ * @param string package name in which the stored procedure is in
+ * @param string stored procedure name to execute
+ * @param array parameters
+ * @return mixed
*
* params array keys
*
- * KEY OPTIONAL NOTES
- * name no the name of the parameter should be in :<param_name> format
- * value no the value of the parameter. If this is an OUT or IN OUT parameter,
- * this should be a reference to a variable
- * type yes the type of the parameter
- * length yes the max size of the parameter
+ * KEY OPTIONAL NOTES
+ * name no the name of the parameter should be in :<param_name> format
+ * value no the value of the parameter. If this is an OUT or IN OUT parameter,
+ * this should be a reference to a variable
+ * type yes the type of the parameter
+ * length yes the max size of the parameter
*/
- public function stored_procedure($package, $procedure, $params)
+ public function stored_procedure($package, $procedure, array $params)
{
- if ($package == '' OR $procedure == '' OR ! is_array($params))
+ if ($package === '' OR $procedure === '')
{
- if ($this->db_debug)
- {
- log_message('error', 'Invalid query: '.$package.'.'.$procedure);
- return $this->display_error('db_invalid_query');
- }
- return FALSE;
+ log_message('error', 'Invalid query: '.$package.'.'.$procedure);
+ return ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE;
}
- // build the query string
- $sql = "begin $package.$procedure(";
+ // Build the query string
+ $sql = 'BEGIN '.$package.'.'.$procedure.'(';
$have_cursor = FALSE;
foreach ($params as $param)
{
- $sql .= $param['name'] . ",";
+ $sql .= $param['name'].',';
- if (array_key_exists('type', $param) && ($param['type'] === OCI_B_CURSOR))
+ if (isset($param['type']) && $param['type'] === OCI_B_CURSOR)
{
$have_cursor = TRUE;
}
}
- $sql = trim($sql, ",") . "); end;";
+ $sql = trim($sql, ',').'); END;';
- $this->stmt_id = FALSE;
- $this->_set_stmt_id($sql);
+ $this->_reset_stmt_id = FALSE;
+ $this->stmt_id = oci_parse($this->conn_id, $sql);
$this->_bind_params($params);
- $this->query($sql, FALSE, $have_cursor);
+ $result = $this->query($sql, FALSE, $have_cursor);
+ $this->_reset_stmt_id = TRUE;
+ return $result;
}
// --------------------------------------------------------------------
@@ -275,10 +353,10 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Bind parameters
*
- * @access private
- * @return none
+ * @param array $params
+ * @return void
*/
- private function _bind_params($params)
+ protected function _bind_params($params)
{
if ( ! is_array($params) OR ! is_resource($this->stmt_id))
{
@@ -304,28 +382,11 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Begin Transaction
*
- * @access public
* @return bool
*/
- public function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
-
- $this->_commit = OCI_DEFAULT;
+ $this->commit_mode = OCI_NO_AUTO_COMMIT;
return TRUE;
}
@@ -334,25 +395,13 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Commit Transaction
*
- * @access public
* @return bool
*/
- public function trans_commit()
+ protected function _trans_commit()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
+ $this->commit_mode = OCI_COMMIT_ON_SUCCESS;
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- $ret = oci_commit($this->conn_id);
- $this->_commit = OCI_COMMIT_ON_SUCCESS;
- return $ret;
+ return oci_commit($this->conn_id);
}
// --------------------------------------------------------------------
@@ -360,60 +409,12 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Rollback Transaction
*
- * @access public
* @return bool
*/
- public function trans_rollback()
+ protected function _trans_rollback()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- $ret = oci_rollback($this->conn_id);
- $this->_commit = OCI_COMMIT_ON_SUCCESS;
- return $ret;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Escape String
- *
- * @access public
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
- * @return string
- */
- public function escape_str($str, $like = FALSE)
- {
- if (is_array($str))
- {
- foreach ($str as $key => $val)
- {
- $str[$key] = $this->escape_str($val, $like);
- }
-
- return $str;
- }
-
- $str = remove_invisible_characters($str);
-
- // escape LIKE condition wildcards
- if ($like === TRUE)
- {
- $str = str_replace( array('%', '_', $this->_like_escape_chr),
- array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
- $str);
- }
-
- return $str;
+ $this->commit_mode = OCI_COMMIT_ON_SUCCESS;
+ return oci_rollback($this->conn_id);
}
// --------------------------------------------------------------------
@@ -421,12 +422,11 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Affected Rows
*
- * @access public
- * @return integer
+ * @return int
*/
public function affected_rows()
{
- return @oci_num_rows($this->stmt_id);
+ return oci_num_rows($this->stmt_id);
}
// --------------------------------------------------------------------
@@ -434,8 +434,7 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Insert ID
*
- * @access public
- * @return integer
+ * @return int
*/
public function insert_id()
{
@@ -446,52 +445,21 @@ class CI_DB_oci8_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @access public
- * @param string
- * @return string
- */
- public function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
-
- if ($query == FALSE)
- {
- return 0;
- }
-
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Show table query
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @access protected
- * @param boolean
+ * @param bool $prefix_limit
* @return string
*/
protected function _list_tables($prefix_limit = FALSE)
{
- $sql = "SELECT TABLE_NAME FROM ALL_TABLES";
+ $sql = 'SELECT "TABLE_NAME" FROM "ALL_TABLES"';
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- $sql .= " WHERE TABLE_NAME LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ return $sql.' WHERE "TABLE_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
return $sql;
@@ -504,155 +472,129 @@ class CI_DB_oci8_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @access protected
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return string
*/
protected function _list_columns($table = '')
{
- return "SELECT COLUMN_NAME FROM all_tab_columns WHERE table_name = '$table'";
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
- *
- * @access public
- * @param string the table name
- * @return object
- */
- protected function _field_data($table)
- {
- return "SELECT * FROM ".$table." where rownum = 1";
- }
-
- // --------------------------------------------------------------------
+ if (strpos($table, '.') !== FALSE)
+ {
+ sscanf($table, '%[^.].%s', $owner, $table);
+ }
+ else
+ {
+ $owner = $this->username;
+ }
- /**
- * The error message string
- *
- * @access protected
- * @return string
- */
- protected function _error_message()
- {
- // If the error was during connection, no conn_id should be passed
- $error = is_resource($this->conn_id) ? oci_error($this->conn_id) : oci_error();
- return $error['message'];
+ return 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS
+ WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'
+ AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));
}
// --------------------------------------------------------------------
/**
- * The error message number
+ * Returns an object with field data
*
- * @access protected
- * @return integer
+ * @param string $table
+ * @return array
*/
- protected function _error_number()
+ public function field_data($table)
{
- // Same as _error_message()
- $error = is_resource($this->conn_id) ? oci_error($this->conn_id) : oci_error();
- return $error['code'];
- }
+ if (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));
- /**
- * Escape the SQL Identifiers
- *
- * This function escapes column and table names
- *
- * @access protected
- * @param string
- * @return string
- */
- protected function _escape_identifiers($item)
- {
- if ($this->_escape_char == '')
+ if (($query = $this->query($sql)) === FALSE)
{
- return $item;
+ return FALSE;
}
+ $query = $query->result_object();
- foreach ($this->_reserved_identifiers as $id)
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
{
- if (strpos($item, '.'.$id) !== FALSE)
- {
- $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $query[$i]->COLUMN_NAME;
+ $retval[$i]->type = $query[$i]->DATA_TYPE;
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
+ $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;
- if (strpos($item, '.') !== FALSE)
- {
- $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
- }
- else
- {
- $str = $this->_escape_char.$item.$this->_escape_char;
+ $default = $query[$i]->DATA_DEFAULT;
+ if ($default === NULL && $query[$i]->NULLABLE === 'N')
+ {
+ $default = '';
+ }
+ $retval[$i]->default = $default;
}
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
+ return $retval;
}
// --------------------------------------------------------------------
/**
- * From Tables
+ * Error
*
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
+ * Returns an array containing code and message of the last
+ * database error that has occurred.
*
- * @access protected
- * @param type
- * @return type
+ * @return array
*/
- protected function _from_tables($tables)
+ public function error()
{
- if ( ! is_array($tables))
+ // oci_error() returns an array that already contains
+ // 'code' and 'message' keys, but it can return false
+ // if there was no error ....
+ if (is_resource($this->curs_id))
{
- $tables = array($tables);
+ $error = oci_error($this->curs_id);
+ }
+ elseif (is_resource($this->stmt_id))
+ {
+ $error = oci_error($this->stmt_id);
+ }
+ elseif (is_resource($this->conn_id))
+ {
+ $error = oci_error($this->conn_id);
+ }
+ else
+ {
+ $error = oci_error();
}
- return implode(', ', $tables);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Insert statement
- *
- * Generates a platform-specific insert string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
- */
- protected function _insert($table, $keys, $values)
- {
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ return is_array($error)
+ ? $error
+ : array('code' => '', 'message' => '');
}
// --------------------------------------------------------------------
/**
- * Insert_batch statement
+ * Insert batch statement
*
* Generates a platform-specific insert string from the supplied data
*
- * @access protected
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string
*/
protected function _insert_batch($table, $keys, $values)
{
@@ -661,47 +603,10 @@ class CI_DB_oci8_driver extends CI_DB {
for ($i = 0, $c = count($values); $i < $c; $i++)
{
- $sql .= ' INTO ' . $table . ' (' . $keys . ') VALUES ' . $values[$i] . "\n";
+ $sql .= ' INTO '.$table.' ('.$keys.') VALUES '.$values[$i]."\n";
}
- $sql .= 'SELECT * FROM dual';
-
- return $sql;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Update statement
- *
- * Generates a platform-specific update string from the supplied data
- *
- * @access protected
- * @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
- * @return string
- */
- protected function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
- {
- foreach ($values as $key => $val)
- {
- $valstr[] = $key." = ".$val;
- }
-
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
- $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
- $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
- $sql .= $orderby.$limit;
-
- return $sql;
+ return $sql.'SELECT * FROM dual';
}
// --------------------------------------------------------------------
@@ -710,16 +615,16 @@ class CI_DB_oci8_driver extends CI_DB {
* Truncate statement
*
* Generates a platform-specific truncate string from the supplied data
- * If the database does not support the truncate() command
- * This function maps to "DELETE FROM table"
*
- * @access protected
- * @param string the table name
+ * 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 ".$table;
+ return 'TRUNCATE TABLE '.$table;
}
// --------------------------------------------------------------------
@@ -729,60 +634,43 @@ class CI_DB_oci8_driver extends CI_DB {
*
* Generates a platform-specific delete string from the supplied data
*
- * @access protected
- * @param string the table name
- * @param array the where 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 = '';
-
- if (count($where) > 0 OR count($like) > 0)
+ if ($this->qb_limit)
{
- $conditions = "\nWHERE ";
- $conditions .= implode("\n", $this->ar_where);
-
- if (count($where) > 0 && count($like) > 0)
- {
- $conditions .= " AND ";
- }
- $conditions .= implode("\n", $like);
+ $this->where('rownum <= ',$this->qb_limit, FALSE);
+ $this->qb_limit = FALSE;
}
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- return "DELETE FROM ".$table.$conditions.$limit;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * LIMIT
*
* Generates a platform-specific LIMIT clause
*
- * @access protected
- * @param string the sql query string
- * @param integer the number of rows to limit the query to
- * @param integer the offset value
- * @return string
+ * @param string $sql SQL Query
+ * @return string
*/
- protected function _limit($sql, $limit, $offset)
+ protected function _limit($sql)
{
- $limit = $offset + $limit;
- $newsql = "SELECT * FROM (select inner_query.*, rownum rnum FROM ($sql) inner_query WHERE rownum < $limit)";
-
- if ($offset != 0)
+ if (version_compare($this->version(), '12.1', '>='))
{
- $newsql .= " WHERE rnum >= $offset";
+ // OFFSET-FETCH can be used only with the ORDER BY clause
+ empty($this->qb_orderby) && $sql .= ' ORDER BY 1';
+
+ return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';
}
- // remember that we used limits
$this->limit_used = TRUE;
-
- return $newsql;
+ 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) : '');
}
// --------------------------------------------------------------------
@@ -790,19 +678,11 @@ class CI_DB_oci8_driver extends CI_DB {
/**
* Close DB Connection
*
- * @access protected
- * @param resource
- * @return void
+ * @return void
*/
- protected function _close($conn_id)
+ protected function _close()
{
- @oci_close($conn_id);
+ oci_close($this->conn_id);
}
-
}
-
-
-
-/* End of file oci8_driver.php */
-/* Location: ./system/database/drivers/oci8/oci8_driver.php */
diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php
index ab45220f3..724a76df4 100644
--- a/system/database/drivers/oci8/oci8_forge.php
+++ b/system/database/drivers/oci8/oci8_forge.php
@@ -1,248 +1,187 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.4.1
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Oracle Forge Class
*
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_oci8_forge extends CI_DB_forge {
/**
- * Create database
+ * CREATE DATABASE statement
*
- * @access public
- * @param string the database name
- * @return bool
+ * @var string
*/
- function _create_database($name)
- {
- return FALSE;
- }
+ protected $_create_database = FALSE;
- // --------------------------------------------------------------------
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = FALSE;
/**
- * Drop database
+ * DROP DATABASE statement
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var string
*/
- function _drop_database($name)
- {
- return FALSE;
- }
+ protected $_drop_database = FALSE;
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @access private
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param boolean 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[]
*/
- 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)
+ 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->_protect_identifiers($field);
-
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
+ $field[$i]['_literal'] = "\n\t".$this->_process_column($field[$i]);
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
+ if ( ! empty($field[$i]['comment']))
{
- $sql .= ' UNSIGNED';
+ $sqls[] = 'COMMENT ON COLUMN '
+ .$this->db->escape_identifiers($table).'.'.$this->db->escape_identifiers($field[$i]['name'])
+ .' IS '.$field[$i]['comment'];
}
- if (array_key_exists('DEFAULT', $attributes))
+ if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name']))
{
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
}
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $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 .= ',';
+ $field[$i] = "\n\t".$field[$i]['_literal'];
}
}
- if (count($primary_keys) > 0)
- {
- $primary_keys = $this->db->_protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key = $this->db->_protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->_protect_identifiers($key));
- }
-
- $sql .= ",\n\tUNIQUE COLUMNS (" . implode(', ', $key) . ")";
- }
- }
-
- $sql .= "\n)";
+ $sql .= ' '.$alter_type.' ';
+ $sql .= (count($field) === 1)
+ ? $field[0]
+ : '('.implode(',', $field).')';
- return $sql;
+ // RENAME COLUMN must be executed after MODIFY
+ array_unshift($sqls, $sql);
+ return $sqls;
}
// --------------------------------------------------------------------
/**
- * Drop Table
+ * Field attribute AUTO_INCREMENT
*
- * @access private
- * @return bool
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- function _drop_table($table)
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- return FALSE;
+ // Not supported - sequences and triggers must be used instead
}
// --------------------------------------------------------------------
/**
- * 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.
*
- * @access private
- * @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 boolean should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return object
+ * @param array &$attributes
+ * @return void
*/
- 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->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
- {
- return $sql;
- }
-
- $sql .= " $column_definition";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"$default_value\"";
- }
-
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if ($after_field != '')
+ switch (strtoupper($attributes['TYPE']))
{
- $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
+ case 'TINYINT':
+ $attributes['TYPE'] = 'NUMBER';
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'NUMBER';
+ return;
+ case 'INT':
+ $attributes['TYPE'] = 'NUMBER';
+ return;
+ case 'BIGINT':
+ $attributes['TYPE'] = 'NUMBER';
+ return;
+ default: return;
}
-
- return $sql;
-
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Rename a table
- *
- * Generates a platform-specific query so that a table can be renamed
- *
- * @access private
- * @param string the old table name
- * @param string the new table name
- * @return string
- */
- function _rename_table($table_name, $new_table_name)
- {
- $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name);
- return $sql;
}
-
-
}
-
-/* End of file oci8_forge.php */
-/* Location: ./system/database/drivers/oci8/oci8_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/oci8/oci8_result.php b/system/database/drivers/oci8/oci8_result.php
index cdbee6870..0c3543333 100644
--- a/system/database/drivers/oci8/oci8_result.php
+++ b/system/database/drivers/oci8/oci8_result.php
@@ -1,19 +1,41 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.4.1
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* oci8 Result Class
@@ -21,37 +43,56 @@
* This class extends the parent result class: CI_DB_result
*
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
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;
/**
- * Number of rows in the result set.
+ * Commit mode flag
*
- * Oracle doesn't have a graceful way to retun the number of rows
- * so we have to use what amounts to a hack.
+ * @var int
+ */
+ public $commit_mode;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
*
- * @return integer
+ * @param object &$driver_object
+ * @return void
*/
- public function num_rows()
+ public function __construct(&$driver_object)
{
- if ($this->num_rows === 0 && count($this->result_array()) > 0)
- {
- $this->num_rows = count($this->result_array());
- @oci_execute($this->stmt_id, OCI_DEFAULT);
-
- if ($this->curs_id)
- {
- @oci_execute($this->curs_id, OCI_DEFAULT);
- }
- }
+ parent::__construct($driver_object);
- return $this->num_rows;
+ $this->stmt_id = $driver_object->stmt_id;
+ $this->curs_id = $driver_object->curs_id;
+ $this->limit_used = $driver_object->limit_used;
+ $this->commit_mode =& $driver_object->commit_mode;
+ $driver_object->stmt_id = FALSE;
}
// --------------------------------------------------------------------
@@ -59,20 +100,14 @@ class CI_DB_oci8_result extends CI_DB_result {
/**
* Number of fields in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
public function num_fields()
{
- $count = @oci_num_fields($this->stmt_id);
+ $count = oci_num_fields($this->stmt_id);
// if we used a limit we subtract it
- if ($this->limit_used)
- {
- $count = $count - 1;
- }
-
- return $count;
+ return ($this->limit_used) ? $count - 1 : $count;
}
// --------------------------------------------------------------------
@@ -82,7 +117,6 @@ class CI_DB_oci8_result extends CI_DB_result {
*
* Generates an array of column names
*
- * @access public
* @return array
*/
public function list_fields()
@@ -102,18 +136,17 @@ class CI_DB_oci8_result extends CI_DB_result {
*
* Generates an array of objects containing field meta-data
*
- * @access public
- * @return array
+ * @return array
*/
public function field_data()
{
$retval = array();
for ($c = 1, $fieldCount = $this->num_fields(); $c <= $fieldCount; $c++)
{
- $F = new stdClass();
- $F->name = oci_field_name($this->stmt_id, $c);
- $F->type = oci_field_type($this->stmt_id, $c);
- $F->max_length = oci_field_size($this->stmt_id, $c);
+ $F = new stdClass();
+ $F->name = oci_field_name($this->stmt_id, $c);
+ $F->type = oci_field_type($this->stmt_id, $c);
+ $F->max_length = oci_field_size($this->stmt_id, $c);
$retval[] = $F;
}
@@ -126,7 +159,7 @@ class CI_DB_oci8_result extends CI_DB_result {
/**
* Free the result
*
- * @return null
+ * @return void
*/
public function free_result()
{
@@ -135,6 +168,17 @@ class CI_DB_oci8_result extends CI_DB_result {
oci_free_statement($this->result_id);
$this->result_id = FALSE;
}
+
+ if (is_resource($this->stmt_id))
+ {
+ oci_free_statement($this->stmt_id);
+ }
+
+ if (is_resource($this->curs_id))
+ {
+ oci_cancel($this->curs_id);
+ $this->curs_id = NULL;
+ }
}
// --------------------------------------------------------------------
@@ -144,8 +188,7 @@ class CI_DB_oci8_result extends CI_DB_result {
*
* Returns the result set as an array
*
- * @access protected
- * @return array
+ * @return array
*/
protected function _fetch_assoc()
{
@@ -160,58 +203,27 @@ class CI_DB_oci8_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @access protected
- * @return object
+ * @param string $class_name
+ * @return object
*/
- protected function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- $id = ($this->curs_id) ? $this->curs_id : $this->stmt_id;
- return @oci_fetch_object($id);
- }
+ $row = ($this->curs_id)
+ ? oci_fetch_object($this->curs_id)
+ : oci_fetch_object($this->stmt_id);
- // --------------------------------------------------------------------
-
- /**
- * Query result. "array" version.
- *
- * @access public
- * @return array
- */
- public function result_array()
- {
- if (count($this->result_array) > 0)
+ if ($class_name === 'stdClass' OR ! $row)
{
- return $this->result_array;
+ return $row;
}
- $row = NULL;
- while ($row = $this->_fetch_assoc())
+ $class_name = new $class_name();
+ foreach ($row as $key => $value)
{
- $this->result_array[] = $row;
+ $class_name->$key = $value;
}
- return $this->result_array;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * 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
- *
- * @access protected
- * @return array
- */
- protected function _data_seek($n = 0)
- {
- return FALSE; // Not needed
+ return $class_name;
}
}
-
-
-/* End of file oci8_result.php */
-/* Location: ./system/database/drivers/oci8/oci8_result.php */
diff --git a/system/database/drivers/oci8/oci8_utility.php b/system/database/drivers/oci8/oci8_utility.php
index bdad0255d..ce0dfc5f8 100644
--- a/system/database/drivers/oci8/oci8_utility.php
+++ b/system/database/drivers/oci8/oci8_utility.php
@@ -1,87 +1,68 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.4.1
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Oracle Utility Class
*
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_oci8_utility extends CI_DB_utility {
/**
- * List databases
+ * List databases statement
*
- * @access private
- * @return bool
+ * @var string
*/
- function _list_databases()
- {
- return FALSE;
- }
-
- // --------------------------------------------------------------------
+ protected $_list_databases = 'SELECT username FROM dba_users'; // Schemas are actual usernames
/**
- * Optimize table query
+ * Export
*
- * Generates a platform-specific query so that a table can be optimized
- *
- * @access private
- * @param string the table name
- * @return object
- */
- function _optimize_table($table)
- {
- return FALSE; // Is this supported in Oracle?
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Repair table query
- *
- * Generates a platform-specific query so that a table can be repaired
- *
- * @access private
- * @param string the table name
- * @return object
- */
- function _repair_table($table)
- {
- return FALSE; // Is this supported in Oracle?
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Oracle Export
- *
- * @access private
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
- function _backup($params = array())
+ protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
-}
-/* End of file oci8_utility.php */
-/* Location: ./system/database/drivers/oci8/oci8_utility.php */ \ No newline at end of file
+}
diff --git a/system/database/drivers/odbc/index.html b/system/database/drivers/odbc/index.html
index c942a79ce..b702fbc39 100644
--- a/system/database/drivers/odbc/index.html
+++ b/system/database/drivers/odbc/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index 0e82d57ae..ef982fc63 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -1,617 +1,414 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* ODBC Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
* @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
-class CI_DB_odbc_driver extends CI_DB {
-
- var $dbdriver = 'odbc';
-
- // the character used to excape - not necessary for ODBC
- var $_escape_char = '';
-
- // clause and character used for LIKE escape sequences
- var $_like_escape_str = " {escape '%s'} ";
- var $_like_escape_chr = '!';
+class CI_DB_odbc_driver extends CI_DB_driver {
/**
- * 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.
+ * Database driver
+ *
+ * @var string
*/
- var $_count_string = "SELECT COUNT(*) AS ";
- var $_random_keyword;
-
-
- function __construct($params)
- {
- parent::__construct($params);
-
- $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
- }
+ public $dbdriver = 'odbc';
/**
- * Non-persistent database connection
+ * Database schema
*
- * @access private called by the base class
- * @return resource
+ * @var string
*/
- function db_connect()
- {
- return @odbc_connect($this->hostname, $this->username, $this->password);
- }
+ public $schema = 'public';
// --------------------------------------------------------------------
/**
- * Persistent database connection
+ * Identifier escape character
*
- * @access private called by the base class
- * @return resource
+ * Must be empty for ODBC.
+ *
+ * @var string
*/
- function db_pconnect()
- {
- return @odbc_pconnect($this->hostname, $this->username, $this->password);
- }
-
- // --------------------------------------------------------------------
+ protected $_escape_char = '';
/**
- * Reconnect
- *
- * Keep / reestablish the db connection if no queries have been
- * sent for a length of time exceeding the server's idle timeout
+ * ESCAPE statement string
*
- * @access public
- * @return void
+ * @var string
*/
- function reconnect()
- {
- // not implemented in odbc
- }
-
- // --------------------------------------------------------------------
+ protected $_like_escape_str = " {escape '%s'} ";
/**
- * Select the database
+ * ORDER BY random keyword
*
- * @access private called by the base class
- * @return resource
+ * @var array
*/
- function db_select()
- {
- // Not needed for ODBC
- return TRUE;
- }
+ protected $_random_keyword = array('RND()', 'RND(%d)');
// --------------------------------------------------------------------
/**
- * Set client character set
+ * ODBC result ID resource returned from odbc_prepare()
*
- * @access public
- * @param string
- * @param string
- * @return resource
+ * @var resource
*/
- function db_set_charset($charset, $collation)
- {
- // @todo - add support if needed
- return TRUE;
- }
-
- // --------------------------------------------------------------------
+ private $odbc_result;
/**
- * Version number query string
+ * Values to use with odbc_execute() for prepared statements
*
- * @access public
- * @return string
+ * @var array
*/
- function _version()
- {
- return "SELECT version() AS ver";
- }
+ private $binds = array();
// --------------------------------------------------------------------
/**
- * Execute the query
+ * Class constructor
*
- * @access private called by the base class
- * @param string an SQL query
- * @return resource
+ * @param array $params
+ * @return void
*/
- function _execute($sql)
+ public function __construct($params)
{
- $sql = $this->_prep_query($sql);
- return @odbc_exec($this->conn_id, $sql);
+ parent::__construct($params);
+
+ // Legacy support for DSN in the hostname field
+ if (empty($this->dsn))
+ {
+ $this->dsn = $this->hostname;
+ }
}
// --------------------------------------------------------------------
/**
- * Prep the query
- *
- * If needed, each database adapter can prep the query string
+ * Non-persistent database connection
*
- * @access private called by execute()
- * @param string an SQL query
- * @return string
+ * @param bool $persistent
+ * @return resource
*/
- function _prep_query($sql)
+ public function db_connect($persistent = FALSE)
{
- return $sql;
+ return ($persistent === TRUE)
+ ? odbc_pconnect($this->dsn, $this->username, $this->password)
+ : odbc_connect($this->dsn, $this->username, $this->password);
}
// --------------------------------------------------------------------
/**
- * Begin Transaction
+ * Compile Bindings
*
- * @access public
- * @return bool
+ * @param string $sql SQL statement
+ * @param array $binds An array of values to bind
+ * @return string
*/
- function trans_begin($test_mode = FALSE)
+ public function compile_binds($sql, $binds)
{
- if ( ! $this->trans_enabled)
+ if (empty($binds) OR empty($this->bind_marker) OR strpos($sql, $this->bind_marker) === FALSE)
{
- return TRUE;
+ return $sql;
}
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ elseif ( ! is_array($binds))
{
- return TRUE;
+ $binds = array($binds);
+ $bind_count = 1;
+ }
+ else
+ {
+ // Make sure we're using numeric keys
+ $binds = array_values($binds);
+ $bind_count = count($binds);
}
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
-
- return odbc_autocommit($this->conn_id, FALSE);
- }
-
- // --------------------------------------------------------------------
+ // We'll need the marker length later
+ $ml = strlen($this->bind_marker);
- /**
- * Commit Transaction
- *
- * @access public
- * @return bool
- */
- function trans_commit()
- {
- if ( ! $this->trans_enabled)
+ // Make sure not to replace a chunk inside a string that happens to match the bind marker
+ if ($c = preg_match_all("/'[^']*'|\"[^\"]*\"/i", $sql, $matches))
{
- return TRUE;
+ $c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i',
+ str_replace($matches[0],
+ str_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]),
+ $sql, $c),
+ $matches, PREG_OFFSET_CAPTURE);
+
+ // Bind values' count must match the count of markers in the query
+ if ($bind_count !== $c)
+ {
+ return $sql;
+ }
}
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count)
{
- return TRUE;
+ return $sql;
}
- $ret = odbc_commit($this->conn_id);
- odbc_autocommit($this->conn_id, TRUE);
- return $ret;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Rollback Transaction
- *
- * @access public
- * @return bool
- */
- function trans_rollback()
- {
- if ( ! $this->trans_enabled)
+ if ($this->bind_marker !== '?')
{
- return TRUE;
+ do
+ {
+ $c--;
+ $sql = substr_replace($sql, '?', $matches[0][$c][1], $ml);
+ }
+ while ($c !== 0);
}
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if (FALSE !== ($this->odbc_result = odbc_prepare($this->conn_id, $sql)))
{
- return TRUE;
+ $this->binds = array_values($binds);
}
- $ret = odbc_rollback($this->conn_id);
- odbc_autocommit($this->conn_id, TRUE);
- return $ret;
+ return $sql;
}
// --------------------------------------------------------------------
/**
- * Escape String
+ * Execute the query
*
- * @access public
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
- * @return string
+ * @param string $sql an SQL query
+ * @return resource
*/
- function escape_str($str, $like = FALSE)
+ protected function _execute($sql)
{
- if (is_array($str))
+ if ( ! isset($this->odbc_result))
{
- foreach ($str as $key => $val)
- {
- $str[$key] = $this->escape_str($val, $like);
- }
-
- return $str;
+ return odbc_exec($this->conn_id, $sql);
+ }
+ elseif ($this->odbc_result === FALSE)
+ {
+ return FALSE;
}
- // ODBC doesn't require escaping
- $str = remove_invisible_characters($str);
-
- // escape LIKE condition wildcards
- if ($like === TRUE)
+ if (TRUE === ($success = odbc_execute($this->odbc_result, $this->binds)))
{
- $str = str_replace( array('%', '_', $this->_like_escape_chr),
- array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
- $str);
+ // For queries that return result sets, return the result_id resource on success
+ $this->is_write_type($sql) OR $success = $this->odbc_result;
}
- return $str;
- }
+ $this->odbc_result = NULL;
+ $this->binds = array();
- // --------------------------------------------------------------------
-
- /**
- * Affected Rows
- *
- * @access public
- * @return integer
- */
- function affected_rows()
- {
- return @odbc_num_rows($this->conn_id);
+ return $success;
}
// --------------------------------------------------------------------
/**
- * Insert ID
+ * Begin Transaction
*
- * @access public
- * @return integer
+ * @return bool
*/
- function insert_id()
+ protected function _trans_begin()
{
- return @odbc_insert_id($this->conn_id);
+ return odbc_autocommit($this->conn_id, FALSE);
}
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
+ * Commit Transaction
*
- * @access public
- * @param string
- * @return string
+ * @return bool
*/
- function count_all($table = '')
+ protected function _trans_commit()
{
- if ($table == '')
+ if (odbc_commit($this->conn_id))
{
- return 0;
- }
-
- $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
-
- if ($query->num_rows() == 0)
- {
- return 0;
+ odbc_autocommit($this->conn_id, TRUE);
+ return TRUE;
}
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
+ return FALSE;
}
// --------------------------------------------------------------------
/**
- * Show table query
- *
- * Generates a platform-specific query string so that the table names can be fetched
+ * Rollback Transaction
*
- * @access private
- * @param boolean
- * @return string
+ * @return bool
*/
- function _list_tables($prefix_limit = FALSE)
+ protected function _trans_rollback()
{
- $sql = "SHOW TABLES FROM `".$this->database."`";
-
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ if (odbc_rollback($this->conn_id))
{
- //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
- return FALSE; // not currently supported
+ odbc_autocommit($this->conn_id, TRUE);
+ return TRUE;
}
- return $sql;
+ return FALSE;
}
// --------------------------------------------------------------------
/**
- * Show column query
- *
- * Generates a platform-specific query string so that the column names can be fetched
+ * Determines if a query is a "write" type.
*
- * @access public
- * @param string the table name
- * @return string
- */
- function _list_columns($table = '')
- {
- return "SHOW COLUMNS FROM ".$table;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
- *
- * @access public
- * @param string the table name
- * @return object
+ * @param string An SQL query string
+ * @return bool
*/
- function _field_data($table)
+ public function is_write_type($sql)
{
- return "SELECT TOP 1 FROM ".$table;
- }
-
- // --------------------------------------------------------------------
+ if (preg_match('#^(INSERT|UPDATE).*RETURNING\s.+(\,\s?.+)*$#is', $sql))
+ {
+ return FALSE;
+ }
- /**
- * The error message string
- *
- * @access private
- * @return string
- */
- function _error_message()
- {
- return odbc_errormsg($this->conn_id);
+ return parent::is_write_type($sql);
}
// --------------------------------------------------------------------
/**
- * The error message number
+ * Platform-dependent string escape
*
- * @access private
- * @return integer
- */
- function _error_number()
- {
- return odbc_error($this->conn_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Escape the SQL Identifiers
- *
- * This function escapes column and table names
- *
- * @access private
* @param string
* @return string
*/
- function _escape_identifiers($item)
+ protected function _escape_str($str)
{
- if ($this->_escape_char == '')
- {
- return $item;
- }
-
- foreach ($this->_reserved_identifiers as $id)
- {
- if (strpos($item, '.'.$id) !== FALSE)
- {
- $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
- }
- }
-
- if (strpos($item, '.') !== FALSE)
- {
- $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
- }
- else
- {
- $str = $this->_escape_char.$item.$this->_escape_char;
- }
-
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
+ $this->display_error('db_unsupported_feature');
}
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
+ * Affected Rows
*
- * @access public
- * @param type
- * @return type
+ * @return int
*/
- function _from_tables($tables)
+ public function affected_rows()
{
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return '('.implode(', ', $tables).')';
+ return odbc_num_rows($this->result_id);
}
// --------------------------------------------------------------------
/**
- * Insert statement
- *
- * Generates a platform-specific insert string from the supplied data
+ * Insert ID
*
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
+ * @return bool
*/
- function _insert($table, $keys, $values)
+ public function insert_id()
{
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE;
}
// --------------------------------------------------------------------
/**
- * Update statement
+ * Show table query
*
- * Generates a platform-specific update string from the supplied data
+ * Generates a platform-specific query string so that the table names can be fetched
*
- * @access public
- * @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
+ * @param bool $prefix_limit
* @return string
*/
- function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
+ protected function _list_tables($prefix_limit = FALSE)
{
- foreach ($values as $key => $val)
+ $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = '".$this->schema."'";
+
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- $valstr[] = $key." = ".$val;
+ return $sql." AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
- $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
- $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
- $sql .= $orderby.$limit;
-
return $sql;
}
-
// --------------------------------------------------------------------
/**
- * Truncate statement
+ * Show column query
*
- * Generates a platform-specific truncate string from the supplied data
- * If the database does not support the truncate() command
- * This function maps to "DELETE FROM table"
+ * Generates a platform-specific query string so that the column names can be fetched
*
- * @access public
- * @param string the table name
+ * @param string $table
* @return string
*/
- function _truncate($table)
+ protected function _list_columns($table = '')
{
- return $this->_delete($table);
+ return 'SHOW COLUMNS FROM '.$table;
}
// --------------------------------------------------------------------
/**
- * Delete statement
+ * Field data query
*
- * Generates a platform-specific delete string from the supplied data
+ * Generates a platform-specific query so that the column data can be retrieved
*
- * @access public
- * @param string the table name
- * @param array the where clause
- * @param string the limit clause
+ * @param string $table
* @return string
*/
- function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _field_data($table)
{
- $conditions = '';
-
- if (count($where) > 0 OR count($like) > 0)
- {
- $conditions = "\nWHERE ";
- $conditions .= implode("\n", $this->ar_where);
-
- if (count($where) > 0 && count($like) > 0)
- {
- $conditions .= " AND ";
- }
- $conditions .= implode("\n", $like);
- }
-
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- return "DELETE FROM ".$table.$conditions.$limit;
+ return 'SELECT TOP 1 FROM '.$table;
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * Error
*
- * Generates a platform-specific LIMIT clause
+ * Returns an array containing code and message of the last
+ * database error that has occurred.
*
- * @access public
- * @param string the sql query string
- * @param integer the number of rows to limit the query to
- * @param integer the offset value
- * @return string
+ * @return array
*/
- function _limit($sql, $limit, $offset)
+ public function error()
{
- // Does ODBC doesn't use the LIMIT clause?
- return $sql;
+ return array('code' => odbc_error($this->conn_id), 'message' => odbc_errormsg($this->conn_id));
}
// --------------------------------------------------------------------
@@ -619,19 +416,10 @@ class CI_DB_odbc_driver extends CI_DB {
/**
* Close DB Connection
*
- * @access public
- * @param resource
* @return void
*/
- function _close($conn_id)
+ protected function _close()
{
- @odbc_close($conn_id);
+ odbc_close($this->conn_id);
}
-
-
}
-
-
-
-/* End of file odbc_driver.php */
-/* Location: ./system/database/drivers/odbc/odbc_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/odbc/odbc_forge.php b/system/database/drivers/odbc/odbc_forge.php
index 46ba5c5bc..77b2fdf62 100644
--- a/system/database/drivers/odbc/odbc_forge.php
+++ b/system/database/drivers/odbc/odbc_forge.php
@@ -1,266 +1,86 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* ODBC Forge Class
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/database/
*/
class CI_DB_odbc_forge extends CI_DB_forge {
/**
- * Create database
- *
- * @access private
- * @param string the database name
- * @return bool
- */
- function _create_database()
- {
- // ODBC has no "create database" command since it's
- // designed to connect to an existing database
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Drop database
+ * CREATE TABLE IF statement
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var string
*/
- function _drop_database($name)
- {
- // ODBC has no "drop database" command since it's
- // designed to connect to an existing database
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Create Table
- *
- * @access private
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param boolean should 'IF NOT EXISTS' be added to the SQL
- * @return bool
- */
- 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->_protect_identifiers($field);
-
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $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)
- {
- $primary_keys = $this->db->_protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key = $this->db->_protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->_protect_identifiers($key));
- }
-
- $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")";
- }
- }
-
- $sql .= "\n)";
-
- return $sql;
- }
-
- // --------------------------------------------------------------------
+ protected $_create_table_if = FALSE;
/**
- * Drop Table
+ * DROP TABLE IF statement
*
- * @access private
- * @return bool
+ * @var string
*/
- function _drop_table($table)
- {
- // Not a supported ODBC feature
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
+ protected $_drop_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(),
+ * UNSIGNED support
*
- * @access private
- * @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 boolean should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return object
+ * @var bool|array
*/
- function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
- {
- $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
- {
- return $sql;
- }
-
- $sql .= " $column_definition";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"$default_value\"";
- }
-
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if ($after_field != '')
- {
- $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
- }
-
- return $sql;
-
- }
-
+ protected $_unsigned = FALSE;
// --------------------------------------------------------------------
/**
- * Rename a table
+ * Field attribute AUTO_INCREMENT
*
- * Generates a platform-specific query so that a table can be renamed
- *
- * @access private
- * @param string the old table name
- * @param string the new table name
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- function _rename_table($table_name, $new_table_name)
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name);
- return $sql;
+ // Not supported (in most databases at least)
}
-
}
-
-/* End of file odbc_forge.php */
-/* Location: ./system/database/drivers/odbc/odbc_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/odbc/odbc_result.php b/system/database/drivers/odbc/odbc_result.php
index 0963e9796..845aa9c79 100644
--- a/system/database/drivers/odbc/odbc_result.php
+++ b/system/database/drivers/odbc/odbc_result.php
@@ -1,40 +1,82 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* ODBC Result Class
*
* This class extends the parent result class: CI_DB_result
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_odbc_result extends CI_DB_result {
/**
* Number of rows in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_rows()
+ public function num_rows()
{
- return @odbc_num_rows($this->result_id);
+ if (is_int($this->num_rows))
+ {
+ return $this->num_rows;
+ }
+ elseif (($this->num_rows = odbc_num_rows($this->result_id)) !== -1)
+ {
+ return $this->num_rows;
+ }
+
+ // Work-around for ODBC subdrivers that don't support num_rows()
+ if (count($this->result_array) > 0)
+ {
+ return $this->num_rows = count($this->result_array);
+ }
+ elseif (count($this->result_object) > 0)
+ {
+ return $this->num_rows = count($this->result_object);
+ }
+
+ return $this->num_rows = count($this->result_array());
}
// --------------------------------------------------------------------
@@ -42,12 +84,11 @@ class CI_DB_odbc_result extends CI_DB_result {
/**
* Number of fields in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_fields()
+ public function num_fields()
{
- return @odbc_num_fields($this->result_id);
+ return odbc_num_fields($this->result_id);
}
// --------------------------------------------------------------------
@@ -57,15 +98,19 @@ class CI_DB_odbc_result extends CI_DB_result {
*
* Generates an array of column names
*
- * @access public
* @return array
*/
- function list_fields()
+ public function list_fields()
{
$field_names = array();
- for ($i = 0; $i < $this->num_fields(); $i++)
+ $num_fields = $this->num_fields();
+
+ if ($num_fields > 0)
{
- $field_names[] = odbc_field_name($this->result_id, $i);
+ for ($i = 1; $i <= $num_fields; $i++)
+ {
+ $field_names[] = odbc_field_name($this->result_id, $i);
+ }
}
return $field_names;
@@ -78,22 +123,19 @@ class CI_DB_odbc_result extends CI_DB_result {
*
* Generates an array of objects containing field meta-data
*
- * @access public
* @return array
*/
- function field_data()
+ public function field_data()
{
$retval = array();
- for ($i = 0; $i < $this->num_fields(); $i++)
+ for ($i = 0, $odbc_index = 1, $c = $this->num_fields(); $i < $c; $i++, $odbc_index++)
{
- $F = new stdClass();
- $F->name = odbc_field_name($this->result_id, $i);
- $F->type = odbc_field_type($this->result_id, $i);
- $F->max_length = odbc_field_len($this->result_id, $i);
- $F->primary_key = 0;
- $F->default = '';
-
- $retval[] = $F;
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = odbc_field_name($this->result_id, $odbc_index);
+ $retval[$i]->type = odbc_field_type($this->result_id, $odbc_index);
+ $retval[$i]->max_length = odbc_field_len($this->result_id, $odbc_index);
+ $retval[$i]->primary_key = 0;
+ $retval[$i]->default = '';
}
return $retval;
@@ -104,9 +146,9 @@ class CI_DB_odbc_result extends CI_DB_result {
/**
* Free the result
*
- * @return null
+ * @return void
*/
- function free_result()
+ public function free_result()
{
if (is_resource($this->result_id))
{
@@ -118,111 +160,109 @@ class CI_DB_odbc_result extends CI_DB_result {
// --------------------------------------------------------------------
/**
- * Data Seek
+ * Result - associative array
*
- * Moves the internal pointer to the desired offset. We call
- * this internally before fetching results to make sure the
- * result set starts at zero
+ * Returns the result set as an array
*
- * @access private
* @return array
*/
- function _data_seek($n = 0)
+ protected function _fetch_assoc()
{
- return FALSE;
+ return odbc_fetch_array($this->result_id);
}
// --------------------------------------------------------------------
/**
- * Result - associative array
+ * Result - object
*
- * Returns the result set as an array
+ * Returns the result set as an object
*
- * @access private
- * @return array
+ * @param string $class_name
+ * @return object
*/
- function _fetch_assoc()
+ protected function _fetch_object($class_name = 'stdClass')
{
- if (function_exists('odbc_fetch_object'))
+ $row = odbc_fetch_object($this->result_id);
+
+ if ($class_name === 'stdClass' OR ! $row)
{
- return odbc_fetch_array($this->result_id);
+ return $row;
}
- else
+
+ $class_name = new $class_name();
+ foreach ($row as $key => $value)
{
- return $this->_odbc_fetch_array($this->result_id);
+ $class_name->$key = $value;
}
+
+ return $class_name;
}
- // --------------------------------------------------------------------
+}
+// --------------------------------------------------------------------
+
+if ( ! function_exists('odbc_fetch_array'))
+{
/**
- * Result - object
+ * ODBC Fetch array
*
- * Returns the result set as an object
+ * Emulates the native odbc_fetch_array() function when
+ * it is not available (odbc_fetch_array() requires unixODBC)
*
- * @access private
- * @return object
+ * @param resource &$result
+ * @param int $rownumber
+ * @return array
*/
- function _fetch_object()
+ function odbc_fetch_array(&$result, $rownumber = 1)
{
- if (function_exists('odbc_fetch_object'))
+ $rs = array();
+ if ( ! odbc_fetch_into($result, $rs, $rownumber))
{
- return odbc_fetch_object($this->result_id);
+ return FALSE;
}
- else
+
+ $rs_assoc = array();
+ foreach ($rs as $k => $v)
{
- return $this->_odbc_fetch_object($this->result_id);
+ $field_name = odbc_field_name($result, $k+1);
+ $rs_assoc[$field_name] = $v;
}
+
+ return $rs_assoc;
}
+}
+// --------------------------------------------------------------------
+if ( ! function_exists('odbc_fetch_object'))
+{
/**
- * Result - object
+ * ODBC Fetch object
*
- * subsititutes the odbc_fetch_object function when
- * not available (odbc_fetch_object requires unixODBC)
+ * Emulates the native odbc_fetch_object() function when
+ * it is not available.
*
- * @access private
+ * @param resource &$result
+ * @param int $rownumber
* @return object
*/
- function _odbc_fetch_object(& $odbc_result) {
+ function odbc_fetch_object(&$result, $rownumber = 1)
+ {
$rs = array();
- $rs_obj = FALSE;
- if (odbc_fetch_into($odbc_result, $rs)) {
- foreach ($rs as $k=>$v) {
- $field_name= odbc_field_name($odbc_result, $k+1);
- $rs_obj->$field_name = $v;
- }
+ if ( ! odbc_fetch_into($result, $rs, $rownumber))
+ {
+ return FALSE;
}
- return $rs_obj;
- }
-
- /**
- * Result - array
- *
- * subsititutes the odbc_fetch_array function when
- * not available (odbc_fetch_array requires unixODBC)
- *
- * @access private
- * @return array
- */
- function _odbc_fetch_array(& $odbc_result) {
- $rs = array();
- $rs_assoc = FALSE;
- if (odbc_fetch_into($odbc_result, $rs)) {
- $rs_assoc=array();
- foreach ($rs as $k=>$v) {
- $field_name= odbc_field_name($odbc_result, $k+1);
- $rs_assoc[$field_name] = $v;
- }
+ $rs_object = new stdClass();
+ foreach ($rs as $k => $v)
+ {
+ $field_name = odbc_field_name($result, $k+1);
+ $rs_object->$field_name = $v;
}
- return $rs_assoc;
- }
+ return $rs_object;
+ }
}
-
-
-/* End of file odbc_result.php */
-/* Location: ./system/database/drivers/odbc/odbc_result.php */ \ No newline at end of file
diff --git a/system/database/drivers/odbc/odbc_utility.php b/system/database/drivers/odbc/odbc_utility.php
index 293e21b7d..643f6ec0c 100644
--- a/system/database/drivers/odbc/odbc_utility.php
+++ b/system/database/drivers/odbc/odbc_utility.php
@@ -1,103 +1,63 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* ODBC Utility Class
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/database/
*/
class CI_DB_odbc_utility extends CI_DB_utility {
/**
- * List databases
- *
- * @access private
- * @return bool
- */
- function _list_databases()
- {
- // Not sure if ODBC lets you list all databases...
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Optimize table query
- *
- * Generates a platform-specific query so that a table can be optimized
- *
- * @access private
- * @param string the table name
- * @return object
- */
- function _optimize_table($table)
- {
- // Not a supported ODBC feature
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Repair table query
- *
- * Generates a platform-specific query so that a table can be repaired
- *
- * @access private
- * @param string the table name
- * @return object
- */
- function _repair_table($table)
- {
- // Not a supported ODBC feature
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * ODBC Export
+ * Export
*
- * @access private
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
- function _backup($params = array())
+ protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
-
-/* End of file odbc_utility.php */
-/* Location: ./system/database/drivers/odbc/odbc_utility.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/index.html b/system/database/drivers/pdo/index.html
index c942a79ce..b702fbc39 100644
--- a/system/database/drivers/pdo/index.html
+++ b/system/database/drivers/pdo/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index e0e7dab65..6afc999c2 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -1,811 +1,329 @@
-<?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
*
- * @package CodeIgniter
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @author EllisLab Dev Team
- * @link http://codeigniter.com
- * @since Version 2.1.2
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 2.1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * 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/
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_pdo_driver extends CI_DB {
- var $dbdriver = 'pdo';
-
- // the character used to excape - not necessary for PDO
- var $_escape_char = '';
- var $_like_escape_str;
- var $_like_escape_chr;
-
-
- /**
- * 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.
- */
- var $_count_string = "SELECT COUNT(*) AS ";
- var $_random_keyword;
-
- var $options = array();
-
- function __construct($params)
- {
- parent::__construct($params);
-
- // clause and character used for LIKE escape sequences
- if (strpos($this->hostname, 'mysql') !== FALSE)
- {
- $this->_like_escape_str = '';
- $this->_like_escape_chr = '';
-
- //Prior to this version, the charset can't be set in the dsn
- if(is_php('5.3.6'))
- {
- $this->hostname .= ";charset={$this->char_set}";
- }
-
- //Set the charset with the connection options
- $this->options['PDO::MYSQL_ATTR_INIT_COMMAND'] = "SET NAMES {$this->char_set}";
- }
- elseif (strpos($this->hostname, 'odbc') !== FALSE)
- {
- $this->_like_escape_str = " {escape '%s'} ";
- $this->_like_escape_chr = '!';
- }
- else
- {
- $this->_like_escape_str = " ESCAPE '%s' ";
- $this->_like_escape_chr = '!';
- }
-
- empty($this->database) OR $this->hostname .= ';dbname='.$this->database;
-
- $this->trans_enabled = FALSE;
-
- $this->_random_keyword = ' RND('.time().')'; // database specific random keyword
- }
-
/**
- * Non-persistent database connection
+ * Database driver
*
- * @access private called by the base class
- * @return resource
+ * @var string
*/
- function db_connect()
- {
- $this->options['PDO::ATTR_ERRMODE'] = PDO::ERRMODE_SILENT;
-
- return new PDO($this->hostname, $this->username, $this->password, $this->options);
- }
-
- // --------------------------------------------------------------------
+ public $dbdriver = 'pdo';
/**
- * Persistent database connection
+ * PDO Options
*
- * @access private called by the base class
- * @return resource
+ * @var array
*/
- function db_pconnect()
- {
- $this->options['PDO::ATTR_ERRMODE'] = PDO::ERRMODE_SILENT;
- $this->options['PDO::ATTR_PERSISTENT'] = TRUE;
-
- return new PDO($this->hostname, $this->username, $this->password, $this->options);
- }
+ public $options = array();
// --------------------------------------------------------------------
/**
- * Reconnect
+ * Class constructor
*
- * Keep / reestablish the db connection if no queries have been
- * sent for a length of time exceeding the server's idle timeout
+ * Validates the DSN string and/or detects the subdriver.
*
- * @access public
+ * @param array $params
* @return void
*/
- function reconnect()
- {
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Select the database
- *
- * @access private called by the base class
- * @return resource
- */
- function db_select()
- {
- // Not needed for PDO
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Set client character set
- *
- * @access public
- * @param string
- * @param string
- * @return resource
- */
- function db_set_charset($charset, $collation)
- {
- // @todo - add support if needed
- return TRUE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Version number query string
- *
- * @access public
- * @return string
- */
- function _version()
- {
- return $this->conn_id->getAttribute(PDO::ATTR_CLIENT_VERSION);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Execute the query
- *
- * @access private called by the base class
- * @param string an SQL query
- * @return object
- */
- function _execute($sql)
+ public function __construct($params)
{
- $sql = $this->_prep_query($sql);
- $result_id = $this->conn_id->prepare($sql);
+ parent::__construct($params);
- if (is_object($result_id) && ($result = $result_id->execute()))
+ if (preg_match('/([^:]+):/', $this->dsn, $match) && count($match) === 2)
{
- if (is_numeric(stripos($sql, 'SELECT')))
- {
- $this->affect_rows = count($result_id->fetchAll());
- }
- else
- {
- $this->affect_rows = $result_id->rowCount();
- }
+ // 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->subdriver = $match[1];
+ return;
}
- else
+ // Legacy support for DSN specified in the hostname field
+ elseif (preg_match('/([^:]+):/', $this->hostname, $match) && count($match) === 2)
{
- $this->affect_rows = 0;
- $result = FALSE;
+ $this->dsn = $this->hostname;
+ $this->hostname = NULL;
+ $this->subdriver = $match[1];
+ return;
}
-
- return $result;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Prep the query
- *
- * If needed, each database adapter can prep the query string
- *
- * @access private called by execute()
- * @param string an SQL query
- * @return string
- */
- function _prep_query($sql)
- {
- return $sql;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Begin Transaction
- *
- * @access public
- * @return bool
- */
- function trans_begin($test_mode = FALSE)
- {
- if ( ! $this->trans_enabled)
+ elseif (in_array($this->subdriver, array('mssql', 'sybase'), TRUE))
{
- return TRUE;
+ $this->subdriver = 'dblib';
}
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ elseif ($this->subdriver === '4D')
{
- return TRUE;
+ $this->subdriver = '4d';
}
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = (bool) ($test_mode === TRUE);
-
- return $this->conn_id->beginTransaction();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Commit Transaction
- *
- * @access public
- * @return bool
- */
- function trans_commit()
- {
- if ( ! $this->trans_enabled)
+ elseif ( ! in_array($this->subdriver, array('4d', 'cubrid', 'dblib', 'firebird', 'ibm', 'informix', 'mysql', 'oci', 'odbc', 'pgsql', 'sqlite', 'sqlsrv'), TRUE))
{
- return TRUE;
- }
+ log_message('error', 'PDO: Invalid or non-existent subdriver');
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
+ if ($this->db_debug)
+ {
+ show_error('Invalid or non-existent PDO subdriver');
+ }
}
- $ret = $this->conn->commit();
- return $ret;
+ $this->dsn = NULL;
}
// --------------------------------------------------------------------
/**
- * Rollback Transaction
+ * Database connection
*
- * @access public
- * @return bool
+ * @param bool $persistent
+ * @return object
*/
- function trans_rollback()
+ public function db_connect($persistent = FALSE)
{
- if ( ! $this->trans_enabled)
+ if ($persistent === TRUE)
{
- return TRUE;
+ $this->options[PDO::ATTR_PERSISTENT] = TRUE;
}
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ try
{
- return TRUE;
+ return new PDO($this->dsn, $this->username, $this->password, $this->options);
}
-
- $ret = $this->conn_id->rollBack();
- return $ret;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Escape String
- *
- * @access public
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
- * @return string
- */
- function escape_str($str, $like = FALSE)
- {
- if (is_array($str))
+ catch (PDOException $e)
{
- foreach ($str as $key => $val)
+ if ($this->db_debug && empty($this->failover))
{
- $str[$key] = $this->escape_str($val, $like);
+ $this->display_error($e->getMessage(), '', TRUE);
}
- return $str;
- }
-
- //Escape the string
- $str = $this->conn_id->quote($str);
-
- //If there are duplicated quotes, trim them away
- if (strpos($str, "'") === 0)
- {
- $str = substr($str, 1, -1);
- }
-
- // escape LIKE condition wildcards
- if ($like === TRUE)
- {
- $str = str_replace( array('%', '_', $this->_like_escape_chr),
- array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
- $str);
- }
-
- return $str;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Affected Rows
- *
- * @access public
- * @return integer
- */
- function affected_rows()
- {
- return $this->affect_rows;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Insert ID
- *
- * @access public
- * @return integer
- */
- function insert_id($name=NULL)
- {
- //Convenience method for postgres insertid
- if (strpos($this->hostname, 'pgsql') !== FALSE)
- {
- $v = $this->_version();
-
- $table = func_num_args() > 0 ? func_get_arg(0) : NULL;
-
- if ($table == NULL && $v >= '8.1')
- {
- $sql='SELECT LASTVAL() as ins_id';
- }
- $query = $this->query($sql);
- $row = $query->row();
- return $row->ins_id;
- }
- else
- {
- return $this->conn_id->lastInsertId($name);
+ return FALSE;
}
}
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
+ * Database version number
*
- * @access public
- * @param string
* @return string
*/
- function count_all($table = '')
+ public function version()
{
- if ($table == '')
+ if (isset($this->data_cache['version']))
{
- return 0;
+ return $this->data_cache['version'];
}
- $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
-
- if ($query->num_rows() == 0)
+ // Not all subdrivers support the getAttribute() method
+ try
{
- return 0;
+ return $this->data_cache['version'] = $this->conn_id->getAttribute(PDO::ATTR_SERVER_VERSION);
}
-
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Show table query
- *
- * Generates a platform-specific query string so that the table names can be fetched
- *
- * @access private
- * @param boolean
- * @return string
- */
- function _list_tables($prefix_limit = FALSE)
- {
- $sql = "SHOW TABLES FROM `".$this->database."`";
-
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ catch (PDOException $e)
{
- //$sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
- return FALSE; // not currently supported
+ return parent::version();
}
-
- return $sql;
}
// --------------------------------------------------------------------
/**
- * Show column query
- *
- * Generates a platform-specific query string so that the column names can be fetched
+ * Execute the query
*
- * @access public
- * @param string the table name
- * @return string
+ * @param string $sql SQL query
+ * @return mixed
*/
- function _list_columns($table = '')
+ protected function _execute($sql)
{
- return "SHOW COLUMNS FROM ".$table;
+ return $this->conn_id->query($sql);
}
// --------------------------------------------------------------------
/**
- * Field data query
- *
- * Generates a platform-specific query so that the column data can be retrieved
+ * Begin Transaction
*
- * @access public
- * @param string the table name
- * @return object
+ * @return bool
*/
- function _field_data($table)
+ protected function _trans_begin()
{
- return "SELECT TOP 1 FROM ".$table;
+ return $this->conn_id->beginTransaction();
}
// --------------------------------------------------------------------
/**
- * The error message string
+ * Commit Transaction
*
- * @access private
- * @return string
+ * @return bool
*/
- function _error_message()
+ protected function _trans_commit()
{
- $error_array = $this->conn_id->errorInfo();
- return $error_array[2];
+ return $this->conn_id->commit();
}
// --------------------------------------------------------------------
/**
- * The error message number
+ * Rollback Transaction
*
- * @access private
- * @return integer
+ * @return bool
*/
- function _error_number()
+ protected function _trans_rollback()
{
- return $this->conn_id->errorCode();
+ return $this->conn_id->rollBack();
}
// --------------------------------------------------------------------
/**
- * Escape the SQL Identifiers
- *
- * This function escapes column and table names
+ * Platform-dependent string escape
*
- * @access private
* @param string
* @return string
*/
- function _escape_identifiers($item)
+ protected function _escape_str($str)
{
- if ($this->_escape_char == '')
- {
- return $item;
- }
-
- foreach ($this->_reserved_identifiers as $id)
- {
- if (strpos($item, '.'.$id) !== FALSE)
- {
- $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
- }
- }
-
- if (strpos($item, '.') !== FALSE)
- {
- $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
-
- }
- else
- {
- $str = $this->_escape_char.$item.$this->_escape_char;
- }
+ // Escape the string
+ $str = $this->conn_id->quote($str);
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
+ // If there are duplicated quotes, trim them away
+ return ($str[0] === "'")
+ ? substr($str, 1, -1)
+ : $str;
}
// --------------------------------------------------------------------
/**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
+ * Affected Rows
*
- * @access public
- * @param type
- * @return type
+ * @return int
*/
- function _from_tables($tables)
+ public function affected_rows()
{
- if ( ! is_array($tables))
- {
- $tables = array($tables);
- }
-
- return (count($tables) == 1) ? $tables[0] : '('.implode(', ', $tables).')';
+ return is_object($this->result_id) ? $this->result_id->rowCount() : 0;
}
// --------------------------------------------------------------------
/**
- * Insert statement
- *
- * Generates a platform-specific insert string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
- */
- function _insert($table, $keys, $values)
- {
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Insert_batch statement
- *
- * Generates a platform-specific insert string from the supplied data
+ * Insert ID
*
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
+ * @param string $name
+ * @return int
*/
- function _insert_batch($table, $keys, $values)
+ public function insert_id($name = NULL)
{
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values);
+ return $this->conn_id->lastInsertId($name);
}
// --------------------------------------------------------------------
/**
- * Update statement
+ * Field data query
*
- * Generates a platform-specific update string from the supplied data
+ * Generates a platform-specific query so that the column data can be retrieved
*
- * @access public
- * @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
+ * @param string $table
* @return string
*/
- function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
+ protected function _field_data($table)
{
- foreach ($values as $key => $val)
- {
- $valstr[] = $key." = ".$val;
- }
-
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
- $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
- $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
- $sql .= $orderby.$limit;
-
- return $sql;
+ return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table);
}
-
+
// --------------------------------------------------------------------
/**
- * Update_Batch statement
+ * Error
*
- * Generates a platform-specific batch update string from the supplied data
+ * Returns an array containing code and message of the last
+ * database error that has occurred.
*
- * @access public
- * @param string the table name
- * @param array the update data
- * @param array the where clause
- * @return string
+ * @return array
*/
- function _update_batch($table, $values, $index, $where = NULL)
+ public function error()
{
- $ids = array();
- $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : '';
+ $error = array('code' => '00000', 'message' => '');
+ $pdo_error = $this->conn_id->errorInfo();
- foreach ($values as $key => $val)
+ if (empty($pdo_error[0]))
{
- $ids[] = $val[$index];
-
- foreach (array_keys($val) as $field)
- {
- if ($field != $index)
- {
- $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
- }
- }
+ return $error;
}
- $sql = "UPDATE ".$table." SET ";
- $cases = '';
-
- foreach ($final as $k => $v)
+ $error['code'] = isset($pdo_error[1]) ? $pdo_error[0].'/'.$pdo_error[1] : $pdo_error[0];
+ if (isset($pdo_error[2]))
{
- $cases .= $k.' = CASE '."\n";
- foreach ($v as $row)
- {
- $cases .= $row."\n";
- }
-
- $cases .= 'ELSE '.$k.' END, ';
+ $error['message'] = $pdo_error[2];
}
- $sql .= substr($cases, 0, -2);
-
- $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
-
- return $sql;
+ return $error;
}
-
// --------------------------------------------------------------------
/**
* Truncate statement
*
* Generates a platform-specific truncate string from the supplied data
- * If the database does not support the truncate() command
- * This function maps to "DELETE FROM table"
- *
- * @access public
- * @param string the table name
- * @return string
- */
- function _truncate($table)
- {
- return $this->_delete($table);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Delete statement
- *
- * Generates a platform-specific delete string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the where clause
- * @param string the limit clause
- * @return string
- */
- function _delete($table, $where = array(), $like = array(), $limit = FALSE)
- {
- $conditions = '';
-
- if (count($where) > 0 OR count($like) > 0)
- {
- $conditions = "\nWHERE ";
- $conditions .= implode("\n", $this->ar_where);
-
- if (count($where) > 0 && count($like) > 0)
- {
- $conditions .= " AND ";
- }
- $conditions .= implode("\n", $like);
- }
-
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- return "DELETE FROM ".$table.$conditions.$limit;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Limit string
*
- * Generates a platform-specific LIMIT clause
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
*
- * @access public
- * @param string the sql query string
- * @param integer the number of rows to limit the query to
- * @param integer the offset value
+ * @param string $table
* @return string
*/
- function _limit($sql, $limit, $offset)
- {
- if (strpos($this->hostname, 'cubrid') !== FALSE || strpos($this->hostname, 'sqlite') !== FALSE)
- {
- if ($offset == 0)
- {
- $offset = '';
- }
- else
- {
- $offset .= ", ";
- }
-
- return $sql."LIMIT ".$offset.$limit;
- }
- else
- {
- $sql .= "LIMIT ".$limit;
-
- if ($offset > 0)
- {
- $sql .= " OFFSET ".$offset;
- }
-
- return $sql;
- }
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Close DB Connection
- *
- * @access public
- * @param resource
- * @return void
- */
- function _close($conn_id)
+ protected function _truncate($table)
{
- $this->conn_id = null;
+ return 'TRUNCATE TABLE '.$table;
}
-
}
-
-
-
-/* End of file pdo_driver.php */
-/* Location: ./system/database/drivers/pdo/pdo_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/pdo_forge.php b/system/database/drivers/pdo/pdo_forge.php
index f7beb0a9a..685b6776d 100644
--- a/system/database/drivers/pdo/pdo_forge.php
+++ b/system/database/drivers/pdo/pdo_forge.php
@@ -1,266 +1,65 @@
-<?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
*
- * @package CodeIgniter
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @author EllisLab Dev Team
- * @link http://codeigniter.com
- * @since Version 2.1.2
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 2.1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Forge Class
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
* @author EllisLab Dev Team
- * @link http://codeigniter.com/database/
+ * @link https://codeigniter.com/database/
*/
class CI_DB_pdo_forge extends CI_DB_forge {
/**
- * Create database
- *
- * @access private
- * @param string the database name
- * @return bool
- */
- function _create_database()
- {
- // PDO has no "create database" command since it's
- // designed to connect to an existing database
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Drop database
- *
- * @access private
- * @param string the database name
- * @return bool
- */
- function _drop_database($name)
- {
- // PDO has no "drop database" command since it's
- // designed to connect to an existing database
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Create Table
- *
- * @access private
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param boolean should 'IF NOT EXISTS' be added to the SQL
- * @return bool
- */
- 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->_protect_identifiers($field);
-
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $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)
- {
- $primary_keys = $this->db->_protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key = $this->db->_protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->_protect_identifiers($key));
- }
-
- $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")";
- }
- }
-
- $sql .= "\n)";
-
- return $sql;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Drop Table
+ * CREATE TABLE IF statement
*
- * @access private
- * @return bool
+ * @var string
*/
- function _drop_table($table)
- {
- // Not a supported PDO feature
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
+ protected $_create_table_if = FALSE;
/**
- * Alter table query
+ * DROP TABLE IF statement
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
- *
- * @access private
- * @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 boolean should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return object
+ * @var string
*/
- function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
- {
- $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
- {
- return $sql;
- }
-
- $sql .= " $column_definition";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"$default_value\"";
- }
-
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if ($after_field != '')
- {
- $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
- }
-
- return $sql;
-
- }
-
-
- // --------------------------------------------------------------------
-
- /**
- * Rename a table
- *
- * Generates a platform-specific query so that a table can be renamed
- *
- * @access private
- * @param string the old table name
- * @param string the new table name
- * @return string
- */
- function _rename_table($table_name, $new_table_name)
- {
- $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name);
- return $sql;
- }
-
+ protected $_drop_table_if = FALSE;
}
-
-/* End of file pdo_forge.php */
-/* Location: ./system/database/drivers/pdo/pdo_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/pdo_result.php b/system/database/drivers/pdo/pdo_result.php
index 4843df43b..bbc2cdc5a 100644
--- a/system/database/drivers/pdo/pdo_result.php
+++ b/system/database/drivers/pdo/pdo_result.php
@@ -1,33 +1,55 @@
-<?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
*
- * @package CodeIgniter
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @author EllisLab Dev Team
- * @link http://codeigniter.com
- * @since Version 2.1.2
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 2.1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Result Class
*
* This class extends the parent result class: CI_DB_result
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_pdo_result extends CI_DB_result {
- public $num_rows;
-
/**
* Number of rows in the result set
*
@@ -39,14 +61,20 @@ class CI_DB_pdo_result extends CI_DB_result {
{
return $this->num_rows;
}
- elseif (($this->num_rows = $this->result_id->rowCount()) > 0)
+ elseif (count($this->result_array) > 0)
{
- return $this->num_rows;
+ return $this->num_rows = count($this->result_array);
+ }
+ elseif (count($this->result_object) > 0)
+ {
+ return $this->num_rows = count($this->result_object);
+ }
+ elseif (($num_rows = $this->result_id->rowCount()) > 0)
+ {
+ return $this->num_rows = $num_rows;
}
- $this->num_rows = count($this->result_id->fetchAll());
- $this->result_id->execute();
- return $this->num_rows;
+ return $this->num_rows = count($this->result_array());
}
// --------------------------------------------------------------------
@@ -54,10 +82,9 @@ class CI_DB_pdo_result extends CI_DB_result {
/**
* Number of fields in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_fields()
+ public function num_fields()
{
return $this->result_id->columnCount();
}
@@ -69,16 +96,20 @@ class CI_DB_pdo_result extends CI_DB_result {
*
* Generates an array of column names
*
- * @access public
- * @return array
+ * @return bool
*/
- function list_fields()
+ public function list_fields()
{
- if ($this->db->db_debug)
+ $field_names = array();
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
- return $this->db->display_error('db_unsuported_feature');
+ // Might trigger an E_WARNING due to not all subdrivers
+ // supporting getColumnMeta()
+ $field_names[$i] = @$this->result_id->getColumnMeta($i);
+ $field_names[$i] = $field_names[$i]['name'];
}
- return FALSE;
+
+ return $field_names;
}
// --------------------------------------------------------------------
@@ -88,28 +119,34 @@ class CI_DB_pdo_result extends CI_DB_result {
*
* Generates an array of objects containing field meta-data
*
- * @access public
* @return array
*/
- function field_data()
+ public function field_data()
{
- $data = array();
-
try
{
- for($i = 0; $i < $this->num_fields(); $i++)
+ $retval = array();
+
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
- $data[] = $this->result_id->getColumnMeta($i);
+ $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;
}
}
@@ -119,9 +156,9 @@ class CI_DB_pdo_result extends CI_DB_result {
/**
* Free the result
*
- * @return null
+ * @return void
*/
- function free_result()
+ public function free_result()
{
if (is_object($this->result_id))
{
@@ -132,31 +169,13 @@ class CI_DB_pdo_result extends CI_DB_result {
// --------------------------------------------------------------------
/**
- * 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
- *
- * @access private
- * @return array
- */
- function _data_seek($n = 0)
- {
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Result - associative array
*
* Returns the result set as an array
*
- * @access private
* @return array
*/
- function _fetch_assoc()
+ protected function _fetch_assoc()
{
return $this->result_id->fetch(PDO::FETCH_ASSOC);
}
@@ -168,16 +187,12 @@ class CI_DB_pdo_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @access private
+ * @param string $class_name
* @return object
*/
- function _fetch_object()
- {
- return $this->result_id->fetchObject();
+ protected function _fetch_object($class_name = 'stdClass')
+ {
+ return $this->result_id->fetchObject($class_name);
}
}
-
-
-/* End of file pdo_result.php */
-/* Location: ./system/database/drivers/pdo/pdo_result.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/pdo_utility.php b/system/database/drivers/pdo/pdo_utility.php
index 042ccef8d..5029cac94 100644
--- a/system/database/drivers/pdo/pdo_utility.php
+++ b/system/database/drivers/pdo/pdo_utility.php
@@ -1,103 +1,63 @@
-<?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
*
- * @package CodeIgniter
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @author EllisLab Dev Team
- * @link http://codeigniter.com
- * @since Version 2.1.2
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 2.1.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* PDO Utility Class
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
* @author EllisLab Dev Team
- * @link http://codeigniter.com/database/
+ * @link https://codeigniter.com/database/
*/
class CI_DB_pdo_utility extends CI_DB_utility {
/**
- * List databases
- *
- * @access private
- * @return bool
- */
- function _list_databases()
- {
- // Not sure if PDO lets you list all databases...
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Optimize table query
- *
- * Generates a platform-specific query so that a table can be optimized
+ * Export
*
- * @access private
- * @param string the table name
- * @return object
- */
- function _optimize_table($table)
- {
- // Not a supported PDO feature
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Repair table query
- *
- * Generates a platform-specific query so that a table can be repaired
- *
- * @access private
- * @param string the table name
- * @return object
- */
- function _repair_table($table)
- {
- // Not a supported PDO feature
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * PDO Export
- *
- * @access private
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
- function _backup($params = array())
+ protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
-
-/* End of file pdo_utility.php */
-/* Location: ./system/database/drivers/pdo/pdo_utility.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/index.html b/system/database/drivers/pdo/subdrivers/index.html
new file mode 100644
index 000000000..b702fbc39
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>403 Forbidden</title>
+</head>
+<body>
+
+<p>Directory access is forbidden.</p>
+
+</body>
+</html>
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..7eaeaa1fd
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php
@@ -0,0 +1,200 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://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 https://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 : '');
+ }
+
+}
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..3f636d3bd
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php
@@ -0,0 +1,217 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO 4D Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_4d_forge extends CI_DB_pdo_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_type, $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':
+ $attributes['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';
+ }
+ }
+ }
+
+}
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..fc49e0dd0
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php
@@ -0,0 +1,209 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://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 https://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 (($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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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);
+ }
+
+}
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..276cbb6bc
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php
@@ -0,0 +1,230 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO CUBRID Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://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;
+ case 'LONGTEXT':
+ $attributes['TYPE'] = 'STRING';
+ 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;
+ }
+
+}
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..08243232e
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php
@@ -0,0 +1,337 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://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 https://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)
+ {
+ if ($persistent === TRUE)
+ {
+ log_message('debug', "dblib driver doesn't support persistent connections");
+ }
+
+ $this->conn_id = parent::db_connect(FALSE);
+
+ 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)
+ {
+ $sql = '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)
+ {
+ $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_debug) ? $this->display_error('db_unsupported_feature') : FALSE;
+ }
+
+}
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..d0cca38dd
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO DBLIB Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://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)
+ {
+ if (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE)
+ {
+ unset($attributes['CONSTRAINT']);
+ }
+
+ 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)';
+ }
+ }
+
+}
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..cb93f19b7
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php
@@ -0,0 +1,279 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://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 https://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)
+ {
+ $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);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE;
+ }
+}
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..20c5a6897
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php
@@ -0,0 +1,237 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Firebird Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://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
+ }
+
+}
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..26b556a78
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php
@@ -0,0 +1,244 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://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 https://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;
+ }
+
+}
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..4238ca082
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php
@@ -0,0 +1,154 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO IBM DB2 Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://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
+ }
+
+}
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..050171f64
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php
@@ -0,0 +1,309 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://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 https://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);
+ }
+
+}
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..2ddc2a933
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php
@@ -0,0 +1,163 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Informix Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://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
+ }
+
+}
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..64b13d827
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
@@ -0,0 +1,374 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://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 https://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;
+
+ /**
+ * Strict ON flag
+ *
+ * Whether we're running in strict SQL mode.
+ *
+ * @var bool
+ */
+ public $stricton;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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)
+ {
+ $this->dsn .= ';charset='.$this->char_set;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database connection
+ *
+ * @param bool $persistent
+ * @return object
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ if (isset($this->stricton))
+ {
+ if ($this->stricton)
+ {
+ $sql = 'CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")';
+ }
+ else
+ {
+ $sql = 'REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
+ @@sql_mode,
+ "STRICT_ALL_TABLES,", ""),
+ ",STRICT_ALL_TABLES", ""),
+ "STRICT_ALL_TABLES", ""),
+ "STRICT_TRANS_TABLES,", ""),
+ ",STRICT_TRANS_TABLES", ""),
+ "STRICT_TRANS_TABLES", "")';
+ }
+
+ if ( ! empty($sql))
+ {
+ if (empty($this->options[PDO::MYSQL_ATTR_INIT_COMMAND]))
+ {
+ $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET SESSION sql_mode = '.$sql;
+ }
+ else
+ {
+ $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] .= ', @@session.sql_mode = '.$sql;
+ }
+ }
+ }
+
+ if ($this->compress === TRUE)
+ {
+ $this->options[PDO::MYSQL_ATTR_COMPRESS] = TRUE;
+ }
+
+ if (is_array($this->encrypt))
+ {
+ $ssl = array();
+ empty($this->encrypt['ssl_key']) OR $ssl[PDO::MYSQL_ATTR_SSL_KEY] = $this->encrypt['ssl_key'];
+ empty($this->encrypt['ssl_cert']) OR $ssl[PDO::MYSQL_ATTR_SSL_CERT] = $this->encrypt['ssl_cert'];
+ empty($this->encrypt['ssl_ca']) OR $ssl[PDO::MYSQL_ATTR_SSL_CA] = $this->encrypt['ssl_ca'];
+ empty($this->encrypt['ssl_capath']) OR $ssl[PDO::MYSQL_ATTR_SSL_CAPATH] = $this->encrypt['ssl_capath'];
+ empty($this->encrypt['ssl_cipher']) OR $ssl[PDO::MYSQL_ATTR_SSL_CIPHER] = $this->encrypt['ssl_cipher'];
+
+ // DO NOT use array_merge() here!
+ // It re-indexes numeric keys and the PDO_MYSQL_ATTR_SSL_* constants are integers.
+ empty($ssl) OR $this->options += $ssl;
+ }
+
+ // Prior to version 5.7.3, MySQL silently downgrades to an unencrypted connection if SSL setup fails
+ if (
+ ($pdo = parent::db_connect($persistent)) !== FALSE
+ && ! empty($ssl)
+ && version_compare($pdo->getAttribute(PDO::ATTR_CLIENT_VERSION), '5.7.3', '<=')
+ && empty($pdo->query("SHOW STATUS LIKE 'ssl_cipher'")->fetchObject()->Value)
+ )
+ {
+ $message = 'PDO_MYSQL was configured for an SSL connection, but got an unencrypted connection instead!';
+ log_message('error', $message);
+ return ($this->db_debug) ? $this->display_error($message, '', TRUE) : FALSE;
+ }
+
+ return $pdo;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Select the database
+ *
+ * @param string $database
+ * @return bool
+ */
+ public function db_select($database = '')
+ {
+ if ($database === '')
+ {
+ $database = $this->database;
+ }
+
+ if (FALSE !== $this->simple_query('USE '.$this->escape_identifiers($database)))
+ {
+ $this->database = $database;
+ $this->data_cache = array();
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Begin Transaction
+ *
+ * @return bool
+ */
+ protected function _trans_begin()
+ {
+ $this->conn_id->setAttribute(PDO::ATTR_AUTOCOMMIT, FALSE);
+ return $this->conn_id->beginTransaction();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Commit Transaction
+ *
+ * @return bool
+ */
+ protected function _trans_commit()
+ {
+ if ($this->conn_id->commit())
+ {
+ $this->conn_id->setAttribute(PDO::ATTR_AUTOCOMMIT, TRUE);
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Rollback Transaction
+ *
+ * @return bool
+ */
+ protected function _trans_rollback()
+ {
+ if ($this->conn_id->rollBack())
+ {
+ $this->conn_id->setAttribute(PDO::ATTR_AUTOCOMMIT, TRUE);
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 (($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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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);
+ }
+
+}
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..c7a92b826
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php
@@ -0,0 +1,256 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO MySQL Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://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';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * CREATE TABLE attributes
+ *
+ * @param array $attributes Associative array of table attributes
+ * @return string
+ */
+ protected function _create_table_attr($attributes)
+ {
+ $sql = '';
+
+ foreach (array_keys($attributes) as $key)
+ {
+ if (is_string($key))
+ {
+ $sql .= ' '.strtoupper($key).' = '.$attributes[$key];
+ }
+ }
+
+ if ( ! empty($this->db->char_set) && ! strpos($sql, 'CHARACTER SET') && ! strpos($sql, 'CHARSET'))
+ {
+ $sql .= ' DEFAULT CHARACTER SET = '.$this->db->char_set;
+ }
+
+ if ( ! empty($this->db->dbcollat) && ! strpos($sql, 'COLLATE'))
+ {
+ $sql .= ' COLLATE = '.$this->db->dbcollat;
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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']
+ .(empty($field['comment']) ? '' : ' COMMENT '.$field['comment'])
+ .$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;
+ }
+
+}
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..abf9167d6
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php
@@ -0,0 +1,326 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://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 https://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;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database version number
+ *
+ * @return string
+ */
+ public function version()
+ {
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+
+ $version_string = parent::version();
+ if (preg_match('#Release\s(?<version>\d+(?:\.\d+)+)#', $version_string, $match))
+ {
+ return $this->data_cache['version'] = $match[1];
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 (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)
+ {
+ if (version_compare($this->version(), '12.1', '>='))
+ {
+ // OFFSET-FETCH can be used only with the ORDER BY clause
+ empty($this->qb_orderby) && $sql .= ' ORDER BY 1';
+
+ return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';
+ }
+
+ 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/pdo/subdrivers/pdo_oci_forge.php b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php
new file mode 100644
index 000000000..813207b8e
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php
@@ -0,0 +1,176 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Oracle Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://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;
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = FALSE;
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
+ protected $_drop_database = FALSE;
+
+ /**
+ * 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 ( ! empty($field[$i]['comment']))
+ {
+ $sqls[] = 'COMMENT ON COLUMN '
+ .$this->db->escape_identifiers($table).'.'.$this->db->escape_identifiers($field[$i]['name'])
+ .' IS '.$field[$i]['comment'];
+ }
+
+ if ($alter_type === 'MODIFY' && ! 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']);
+ }
+ }
+ }
+
+ $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
+ }
+
+ /**
+ * 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'] = 'NUMBER';
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'NUMBER';
+ return;
+ case 'INT':
+ $attributes['TYPE'] = 'NUMBER';
+ return;
+ case 'BIGINT':
+ $attributes['TYPE'] = 'NUMBER';
+ return;
+ default: return;
+ }
+ }
+}
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..066dd9614
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php
@@ -0,0 +1,229 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://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 https://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;');
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Platform-dependent string escape
+ *
+ * @param string
+ * @return string
+ */
+ protected function _escape_str($str)
+ {
+ $this->display_error('db_unsupported_feature');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Determines if a query is a "write" type.
+ *
+ * @param string An SQL query string
+ * @return bool
+ */
+ public function is_write_type($sql)
+ {
+ if (preg_match('#^(INSERT|UPDATE).*RETURNING\s.+(\,\s?.+)*$#is', $sql))
+ {
+ return FALSE;
+ }
+
+ return parent::is_write_type($sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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);
+ }
+}
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..a2a3bada3
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO ODBC Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://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)
+ }
+
+}
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..9aed3a2fe
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
@@ -0,0 +1,384 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://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 https://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;
+
+ if ( ! empty($this->username))
+ {
+ $this->dsn .= ';username='.$this->username;
+ empty($this->password) OR $this->dsn .= ';password='.$this->password;
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Determines if a query is a "write" type.
+ *
+ * @param string An SQL query string
+ * @return bool
+ */
+ public function is_write_type($sql)
+ {
+ if (preg_match('#^(INSERT|UPDATE).*RETURNING\s.+(\,\s?.+)*$#is', $sql))
+ {
+ return FALSE;
+ }
+
+ return parent::is_write_type($sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "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, DESC or RANDOM
+ * @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)
+ {
+ $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]['value'];
+
+ foreach (array_keys($val) as $field)
+ {
+ if ($field !== $index)
+ {
+ $final[$val[$field]['field']][] = 'WHEN '.$val[$index]['value'].' THEN '.$val[$field]['value'];
+ }
+ }
+ }
+
+ $cases = '';
+ foreach ($final as $k => $v)
+ {
+ $cases .= $k.' = (CASE '.$val[$index]['field']."\n"
+ .implode("\n", $v)."\n"
+ .'ELSE '.$k.' END), ';
+ }
+
+ $this->where($val[$index]['field'].' 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 : '');
+ }
+
+}
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..b00af4ad0
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php
@@ -0,0 +1,210 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO PostgreSQL Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://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']);
+ }
+
+ if ( ! empty($field[$i]['comment']))
+ {
+ $sqls[] = 'COMMENT ON COLUMN '
+ .$this->db->escape_identifiers($table).'.'.$this->db->escape_identifiers($field[$i]['name'])
+ .' IS '.$field[$i]['comment'];
+ }
+ }
+
+ 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 lengths 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';
+ }
+ }
+
+}
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..9b70f3ea6
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php
@@ -0,0 +1,219 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://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 https://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 = 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 = '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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch Field Names
+ *
+ * @param string $table Table name
+ * @return array
+ */
+ public function list_fields($table)
+ {
+ // Is there a cached result?
+ if (isset($this->data_cache['field_names'][$table]))
+ {
+ return $this->data_cache['field_names'][$table];
+ }
+
+ if (($result = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
+ {
+ return FALSE;
+ }
+
+ $this->data_cache['field_names'][$table] = array();
+ foreach ($result->result_array() as $row)
+ {
+ $this->data_cache['field_names'][$table][] = $row['name'];
+ }
+
+ return $this->data_cache['field_names'][$table];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table)
+ {
+ 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;
+ }
+
+}
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..18c475b17
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php
@@ -0,0 +1,238 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO SQLite Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://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;
+ $this->_drop_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();
+ }
+ }
+
+}
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..07c429eec
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php
@@ -0,0 +1,369 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://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 https://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)
+ {
+ $sql = '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)
+ {
+ $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', '>='))
+ {
+ // SQL Server OFFSET-FETCH can be used only with the ORDER BY clause
+ empty($this->qb_orderby) && $sql .= ' ORDER BY 1';
+
+ 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_debug) ? $this->display_error('db_unsupported_feature') : FALSE;
+ }
+
+}
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..82a0d515d
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO SQLSRV Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link https://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)
+ {
+ if (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE)
+ {
+ unset($attributes['CONSTRAINT']);
+ }
+
+ 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)';
+ }
+ }
+
+}
diff --git a/system/database/drivers/postgre/index.html b/system/database/drivers/postgre/index.html
index c942a79ce..b702fbc39 100644
--- a/system/database/drivers/postgre/index.html
+++ b/system/database/drivers/postgre/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index c9365fdb1..bcdfc060a 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -1,102 +1,172 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Postgre Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
* @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_postgre_driver extends CI_DB {
- var $dbdriver = 'postgre';
+ /**
+ * Database driver
+ *
+ * @var string
+ */
+ public $dbdriver = 'postgre';
- var $_escape_char = '"';
+ /**
+ * Database schema
+ *
+ * @var string
+ */
+ public $schema = 'public';
- // clause and character used for LIKE escape sequences
- var $_like_escape_str = " ESCAPE '%s' ";
- var $_like_escape_chr = '!';
+ // --------------------------------------------------------------------
/**
- * 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.
+ * ORDER BY random keyword
+ *
+ * @var array
*/
- var $_count_string = "SELECT COUNT(*) AS ";
- var $_random_keyword = ' RANDOM()'; // database specific random keyword
+ protected $_random_keyword = array('RANDOM()', 'RANDOM()');
+
+ // --------------------------------------------------------------------
/**
- * Connection String
+ * Class constructor
*
- * @access private
- * @return string
+ * Creates a DSN string to be used for db_connect() and db_pconnect()
+ *
+ * @param array $params
+ * @return void
*/
- function _connect_string()
+ public function __construct($params)
{
- $components = array(
- 'hostname' => 'host',
- 'port' => 'port',
- 'database' => 'dbname',
- 'username' => 'user',
- 'password' => 'password'
- );
-
- $connect_string = "";
- foreach ($components as $key => $val)
+ parent::__construct($params);
+
+ if ( ! empty($this->dsn))
+ {
+ return;
+ }
+
+ $this->dsn === '' OR $this->dsn = '';
+
+ if (strpos($this->hostname, '/') !== FALSE)
+ {
+ // If UNIX sockets are used, we shouldn't set a port
+ $this->port = '';
+ }
+
+ $this->hostname === '' OR $this->dsn = 'host='.$this->hostname.' ';
+
+ if ( ! empty($this->port) && ctype_digit($this->port))
+ {
+ $this->dsn .= 'port='.$this->port.' ';
+ }
+
+ if ($this->username !== '')
+ {
+ $this->dsn .= 'user='.$this->username.' ';
+
+ /* An empty password is valid!
+ *
+ * $db['password'] = NULL must be done in order to ignore it.
+ */
+ $this->password === NULL OR $this->dsn .= "password='".$this->password."' ";
+ }
+
+ $this->database === '' OR $this->dsn .= 'dbname='.$this->database.' ';
+
+ /* We don't have these options as elements in our standard configuration
+ * array, but they might be set by parse_url() if the configuration was
+ * provided via string. Example:
+ *
+ * postgre://username:password@localhost:5432/database?connect_timeout=5&sslmode=1
+ */
+ foreach (array('connect_timeout', 'options', 'sslmode', 'service') as $key)
{
- if (isset($this->$key) && $this->$key != '')
+ if (isset($this->$key) && is_string($this->$key) && $this->$key !== '')
{
- $connect_string .= " $val=".$this->$key;
+ $this->dsn .= $key."='".$this->$key."' ";
}
}
- return trim($connect_string);
+
+ $this->dsn = rtrim($this->dsn);
}
// --------------------------------------------------------------------
/**
- * Non-persistent database connection
+ * Database connection
*
- * @access private called by the base class
+ * @param bool $persistent
* @return resource
*/
- function db_connect()
+ public function db_connect($persistent = FALSE)
{
- return @pg_connect($this->_connect_string());
- }
+ $this->conn_id = ($persistent === TRUE)
+ ? pg_pconnect($this->dsn)
+ : pg_connect($this->dsn);
- // --------------------------------------------------------------------
+ if ($this->conn_id !== FALSE)
+ {
+ if ($persistent === TRUE
+ && pg_connection_status($this->conn_id) === PGSQL_CONNECTION_BAD
+ && pg_ping($this->conn_id) === FALSE
+ )
+ {
+ return FALSE;
+ }
- /**
- * Persistent database connection
- *
- * @access private called by the base class
- * @return resource
- */
- function db_pconnect()
- {
- return @pg_pconnect($this->_connect_string());
+ empty($this->schema) OR $this->simple_query('SET search_path TO '.$this->schema.',public');
+ }
+
+ return $this->conn_id;
}
// --------------------------------------------------------------------
@@ -107,10 +177,9 @@ class CI_DB_postgre_driver extends CI_DB {
* Keep / reestablish the db connection if no queries have been
* sent for a length of time exceeding the server's idle timeout
*
- * @access public
* @return void
*/
- function reconnect()
+ public function reconnect()
{
if (pg_ping($this->conn_id) === FALSE)
{
@@ -121,188 +190,147 @@ class CI_DB_postgre_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Select the database
+ * Set client character set
*
- * @access private called by the base class
- * @return resource
+ * @param string $charset
+ * @return bool
*/
- function db_select()
+ protected function _db_set_charset($charset)
{
- // Not needed for Postgre so we'll return TRUE
- return TRUE;
+ return (pg_set_client_encoding($this->conn_id, $charset) === 0);
}
// --------------------------------------------------------------------
/**
- * Set client character set
+ * Database version number
*
- * @access public
- * @param string
- * @param string
- * @return resource
+ * @return string
*/
- function db_set_charset($charset, $collation)
+ public function version()
{
- // @todo - add support if needed
- return TRUE;
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+
+ if ( ! $this->conn_id OR ($pg_version = pg_version($this->conn_id)) === FALSE)
+ {
+ return FALSE;
+ }
+
+ /* If PHP was compiled with PostgreSQL lib versions earlier
+ * than 7.4, pg_version() won't return the server version
+ * and so we'll have to fall back to running a query in
+ * order to get it.
+ */
+ return isset($pg_version['server'])
+ ? $this->data_cache['version'] = $pg_version['server']
+ : parent::version();
}
// --------------------------------------------------------------------
/**
- * Version number query string
+ * Execute the query
*
- * @access public
- * @return string
+ * @param string $sql an SQL query
+ * @return resource
*/
- function _version()
+ protected function _execute($sql)
{
- $pg_version = pg_version($this->conn_id);
- return $pg_version;
+ return pg_query($this->conn_id, $sql);
}
// --------------------------------------------------------------------
/**
- * Execute the query
+ * Begin Transaction
*
- * @access private called by the base class
- * @param string an SQL query
- * @return resource
+ * @return bool
*/
- function _execute($sql)
+ protected function _trans_begin()
{
- $sql = $this->_prep_query($sql);
- return @pg_query($this->conn_id, $sql);
+ return (bool) pg_query($this->conn_id, 'BEGIN');
}
// --------------------------------------------------------------------
/**
- * Prep the query
- *
- * If needed, each database adapter can prep the query string
+ * Commit Transaction
*
- * @access private called by execute()
- * @param string an SQL query
- * @return string
+ * @return bool
*/
- function _prep_query($sql)
+ protected function _trans_commit()
{
- return $sql;
+ return (bool) pg_query($this->conn_id, 'COMMIT');
}
// --------------------------------------------------------------------
/**
- * Begin Transaction
+ * Rollback Transaction
*
- * @access public
* @return bool
*/
- function trans_begin($test_mode = FALSE)
+ protected function _trans_rollback()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
-
- return @pg_exec($this->conn_id, "begin");
+ return (bool) pg_query($this->conn_id, 'ROLLBACK');
}
// --------------------------------------------------------------------
/**
- * Commit Transaction
+ * Determines if a query is a "write" type.
*
- * @access public
+ * @param string An SQL query string
* @return bool
*/
- function trans_commit()
+ public function is_write_type($sql)
{
- if ( ! $this->trans_enabled)
+ if (preg_match('#^(INSERT|UPDATE).*RETURNING\s.+(\,\s?.+)*$#is', $sql))
{
- return TRUE;
+ return FALSE;
}
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- return @pg_exec($this->conn_id, "commit");
+ return parent::is_write_type($sql);
}
// --------------------------------------------------------------------
/**
- * Rollback Transaction
+ * Platform-dependent string escape
*
- * @access public
- * @return bool
+ * @param string
+ * @return string
*/
- function trans_rollback()
+ protected function _escape_str($str)
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- return @pg_exec($this->conn_id, "rollback");
+ return pg_escape_string($this->conn_id, $str);
}
// --------------------------------------------------------------------
/**
- * Escape String
+ * "Smart" Escape String
*
- * @access public
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
- * @return string
+ * Escapes data based on type
+ *
+ * @param string $str
+ * @return mixed
*/
- function escape_str($str, $like = FALSE)
+ public function escape($str)
{
- if (is_array($str))
+ if (is_php('5.4.4') && (is_string($str) OR (is_object($str) && method_exists($str, '__toString'))))
{
- foreach ($str as $key => $val)
- {
- $str[$key] = $this->escape_str($val, $like);
- }
-
- return $str;
+ return pg_escape_literal($this->conn_id, $str);
}
-
- $str = pg_escape_string($str);
-
- // escape LIKE condition wildcards
- if ($like === TRUE)
+ elseif (is_bool($str))
{
- $str = str_replace( array('%', '_', $this->_like_escape_chr),
- array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
- $str);
+ return ($str) ? 'TRUE' : 'FALSE';
}
- return $str;
+ return parent::escape($str);
}
// --------------------------------------------------------------------
@@ -310,12 +338,11 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Affected Rows
*
- * @access public
- * @return integer
+ * @return int
*/
- function affected_rows()
+ public function affected_rows()
{
- return @pg_affected_rows($this->result_id);
+ return pg_affected_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -323,71 +350,45 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Insert ID
*
- * @access public
- * @return integer
+ * @return string
*/
- function insert_id()
+ public function insert_id()
{
- $v = $this->_version();
- $v = $v['server'];
+ $v = pg_version($this->conn_id);
+ $v = isset($v['server']) ? $v['server'] : 0; // 'server' key is only available since PosgreSQL 7.4
- $table = func_num_args() > 0 ? func_get_arg(0) : NULL;
- $column = func_num_args() > 1 ? func_get_arg(1) : NULL;
+ $table = (func_num_args() > 0) ? func_get_arg(0) : NULL;
+ $column = (func_num_args() > 1) ? func_get_arg(1) : NULL;
- if ($table == NULL && $v >= '8.1')
+ if ($table === NULL && $v >= '8.1')
{
- $sql='SELECT LASTVAL() as ins_id';
+ $sql = 'SELECT LASTVAL() AS ins_id';
}
- elseif ($table != NULL && $column != NULL && $v >= '8.0')
+ elseif ($table !== NULL)
{
- $sql = sprintf("SELECT pg_get_serial_sequence('%s','%s') as seq", $table, $column);
- $query = $this->query($sql);
- $row = $query->row();
- $sql = sprintf("SELECT CURRVAL('%s') as ins_id", $row->seq);
- }
- elseif ($table != NULL)
- {
- // seq_name passed in table parameter
- $sql = sprintf("SELECT CURRVAL('%s') as ins_id", $table);
+ if ($column !== NULL && $v >= '8.0')
+ {
+ $sql = 'SELECT pg_get_serial_sequence(\''.$table."', '".$column."') AS seq";
+ $query = $this->query($sql);
+ $query = $query->row();
+ $seq = $query->seq;
+ }
+ else
+ {
+ // seq_name passed in table parameter
+ $seq = $table;
+ }
+
+ $sql = 'SELECT CURRVAL(\''.$seq."') AS ins_id";
}
else
{
return pg_last_oid($this->result_id);
}
- $query = $this->query($sql);
- $row = $query->row();
- return $row->ins_id;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @access public
- * @param string
- * @return string
- */
- function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
-
- if ($query->num_rows() == 0)
- {
- return 0;
- }
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
+ $query = $this->query($sql);
+ $query = $query->row();
+ return (int) $query->ins_id;
}
// --------------------------------------------------------------------
@@ -397,17 +398,18 @@ class CI_DB_postgre_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @access private
- * @param boolean
+ * @param bool $prefix_limit
* @return string
*/
- function _list_tables($prefix_limit = FALSE)
+ 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 AND $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix !== '')
{
- $sql .= " AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ return $sql.' AND "table_name" LIKE \''
+ .$this->escape_like_str($this->dbprefix)."%' "
+ .sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
return $sql;
@@ -416,212 +418,160 @@ 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
*
- * @access public
- * @param string the table name
+ * @param string $table
* @return string
*/
- function _list_columns($table = '')
+ protected function _list_columns($table = '')
{
- return "SELECT column_name FROM information_schema.columns WHERE table_name ='".$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
*
- * @access public
- * @param string the table name
- * @return object
+ * @param string $table
+ * @return array
*/
- function _field_data($table)
+ public function field_data($table)
{
- return "SELECT * FROM ".$table." LIMIT 1";
- }
+ $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();
- /**
- * The error message string
- *
- * @access private
- * @return string
- */
- function _error_message()
- {
- return pg_last_error($this->conn_id);
+ $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;
}
// --------------------------------------------------------------------
/**
- * The error message number
+ * Error
+ *
+ * Returns an array containing code and message of the last
+ * database error that has occurred.
*
- * @access private
- * @return integer
+ * @return array
*/
- function _error_number()
+ public function error()
{
- return '';
+ return array('code' => '', 'message' => pg_last_error($this->conn_id));
}
// --------------------------------------------------------------------
/**
- * Escape the SQL Identifiers
+ * ORDER BY
*
- * This function escapes column and table names
- *
- * @access private
- * @param string
- * @return string
+ * @param string $orderby
+ * @param string $direction ASC, DESC or RANDOM
+ * @param bool $escape
+ * @return object
*/
- function _escape_identifiers($item)
+ public function order_by($orderby, $direction = '', $escape = NULL)
{
- if ($this->_escape_char == '')
- {
- return $item;
- }
-
- foreach ($this->_reserved_identifiers as $id)
+ $direction = strtoupper(trim($direction));
+ if ($direction === 'RANDOM')
{
- if (strpos($item, '.'.$id) !== FALSE)
+ if ( ! is_float($orderby) && ctype_digit((string) $orderby))
{
- $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
+ $orderby = ($orderby > 1)
+ ? (float) '0.'.$orderby
+ : (float) $orderby;
}
- }
-
- if (strpos($item, '.') !== FALSE)
- {
- $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
- }
- else
- {
- $str = $this->_escape_char.$item.$this->_escape_char;
- }
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
- }
-
- // --------------------------------------------------------------------
+ if (is_float($orderby))
+ {
+ $this->simple_query('SET SEED '.$orderby);
+ }
- /**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @access public
- * @param type
- * @return type
- */
- function _from_tables($tables)
- {
- if ( ! is_array($tables))
- {
- $tables = array($tables);
+ $orderby = $this->_random_keyword[0];
+ $direction = '';
+ $escape = FALSE;
}
- return implode(', ', $tables);
+ return parent::order_by($orderby, $direction, $escape);
}
// --------------------------------------------------------------------
/**
- * Insert statement
+ * Update statement
*
- * Generates a platform-specific insert string from the supplied data
+ * Generates a platform-specific update string from the supplied data
*
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
+ * @param string $table
+ * @param array $values
* @return string
*/
- function _insert($table, $keys, $values)
- {
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Insert_batch statement
- *
- * Generates a platform-specific insert string from the supplied data
- *
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
- */
- function _insert_batch($table, $keys, $values)
+ protected function _update($table, $values)
{
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES ".implode(', ', $values);
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
/**
- * Update statement
+ * Update_Batch statement
*
- * Generates a platform-specific update string from the supplied data
+ * Generates a platform-specific batch update string from the supplied data
*
- * @access public
- * @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
+ * @param string $table Table name
+ * @param array $values Update data
+ * @param string $index WHERE key
* @return string
*/
- function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
+ protected function _update_batch($table, $values, $index)
{
+ $ids = array();
foreach ($values as $key => $val)
{
- $valstr[] = $key." = ".$val;
- }
+ $ids[] = $val[$index]['value'];
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
- $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
- $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
- $sql .= $orderby.$limit;
+ foreach (array_keys($val) as $field)
+ {
+ if ($field !== $index)
+ {
+ $final[$val[$field]['field']][] = 'WHEN '.$val[$index]['value'].' THEN '.$val[$field]['value'];
+ }
+ }
+ }
- return $sql;
- }
+ $cases = '';
+ foreach ($final as $k => $v)
+ {
+ $cases .= $k.' = (CASE '.$val[$index]['field']."\n"
+ .implode("\n", $v)."\n"
+ .'ELSE '.$k.' END), ';
+ }
- // --------------------------------------------------------------------
+ $this->where($val[$index]['field'].' IN('.implode(',', $ids).')', NULL, FALSE);
- /**
- * Truncate statement
- *
- * Generates a platform-specific truncate string from the supplied data
- * If the database does not support the truncate() command
- * This function maps to "DELETE FROM table"
- *
- * @access public
- * @param string the table name
- * @return string
- */
- function _truncate($table)
- {
- return "TRUNCATE ".$table;
+ return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');
}
// --------------------------------------------------------------------
@@ -631,55 +581,28 @@ class CI_DB_postgre_driver extends CI_DB {
*
* Generates a platform-specific delete string from the supplied data
*
- * @access public
- * @param string the table name
- * @param array the where clause
- * @param string the limit clause
+ * @param string $table
* @return string
*/
- function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _delete($table)
{
- $conditions = '';
-
- if (count($where) > 0 OR count($like) > 0)
- {
- $conditions = "\nWHERE ";
- $conditions .= implode("\n", $this->ar_where);
-
- if (count($where) > 0 && count($like) > 0)
- {
- $conditions .= " AND ";
- }
- $conditions .= implode("\n", $like);
- }
-
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- return "DELETE FROM ".$table.$conditions.$limit;
+ $this->qb_limit = FALSE;
+ return parent::_delete($table);
}
// --------------------------------------------------------------------
+
/**
- * Limit string
+ * LIMIT
*
* Generates a platform-specific LIMIT clause
*
- * @access public
- * @param string the sql query string
- * @param integer the number of rows to limit the query to
- * @param integer the offset value
+ * @param string $sql SQL Query
* @return string
*/
- function _limit($sql, $limit, $offset)
+ protected function _limit($sql)
{
- $sql .= "LIMIT ".$limit;
-
- if ($offset > 0)
- {
- $sql .= " OFFSET ".$offset;
- }
-
- return $sql;
+ return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');
}
// --------------------------------------------------------------------
@@ -687,18 +610,11 @@ class CI_DB_postgre_driver extends CI_DB {
/**
* Close DB Connection
*
- * @access public
- * @param resource
* @return void
*/
- function _close($conn_id)
+ protected function _close()
{
- @pg_close($conn_id);
+ pg_close($this->conn_id);
}
-
}
-
-
-/* End of file postgre_driver.php */
-/* Location: ./system/database/drivers/postgre/postgre_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/postgre/postgre_forge.php b/system/database/drivers/postgre/postgre_forge.php
index d9997a433..cdbff4c4b 100644
--- a/system/database/drivers/postgre/postgre_forge.php
+++ b/system/database/drivers/postgre/postgre_forge.php
@@ -1,299 +1,205 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Postgre Forge Class
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_postgre_forge extends CI_DB_forge {
/**
- * Create database
+ * UNSIGNED support
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var array
*/
- function _create_database($name)
- {
- return "CREATE DATABASE ".$name;
- }
+ 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';
// --------------------------------------------------------------------
/**
- * Drop database
+ * Class constructor
*
- * @access private
- * @param string the database name
- * @return bool
+ * @param object &$db Database object
+ * @return void
*/
- function _drop_database($name)
+ public function __construct(&$db)
{
- return "DROP DATABASE ".$name;
+ parent::__construct($db);
+
+ if (version_compare($this->db->version(), '9.0', '>'))
+ {
+ $this->create_table_if = 'CREATE TABLE IF NOT EXISTS';
+ }
}
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @access private
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param boolean 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[]
*/
- function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
{
- if ($this->db->table_exists($table))
- {
- return "SELECT * FROM $table"; // Needs to return innocous but valid SQL statement
- }
+ return parent::_alter_table($alter_type, $table, $field);
}
- $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";
+ return FALSE;
}
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->_protect_identifiers($field);
-
- $is_unsigned = (array_key_exists('UNSIGNED', $attributes) && $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;
- }
-
- // If this is an auto-incrementing primary key, use the serial data type instead
- if (in_array($field, $primary_keys) && array_key_exists('AUTO_INCREMENT', $attributes)
- && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' SERIAL';
- }
- else
- {
- $sql .= ' '.$attributes['TYPE'];
- }
-
- // Modified to prevent constraints with integer data types
- if (array_key_exists('CONSTRAINT', $attributes) && strpos($attributes['TYPE'], 'INT') === false)
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- // Added new attribute to create unqite fields. Also works with MySQL
- if (array_key_exists('UNIQUE', $attributes) && $attributes['UNIQUE'] === TRUE)
- {
- $sql .= ' UNIQUE';
- }
+ 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'];
}
- // 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)
- {
- // Something seems to break when passing an array to _protect_identifiers()
- foreach ($primary_keys as $index => $key)
+ if (isset($field[$i]['null']))
{
- $primary_keys[$index] = $this->db->_protect_identifiers($key);
+ $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .($field[$i]['null'] === TRUE ? ' DROP NOT NULL' : ' SET NOT NULL');
}
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
- }
-
- $sql .= "\n);";
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
+ if ( ! empty($field[$i]['new_name']))
{
- if (is_array($key))
- {
- $key = $this->db->_protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->_protect_identifiers($key));
- }
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
+ }
- foreach ($key as $field)
- {
- $sql .= "CREATE INDEX " . $table . "_" . str_replace(array('"', "'"), '', $field) . "_index ON $table ($field); ";
- }
+ if ( ! empty($field[$i]['comment']))
+ {
+ $sqls[] = 'COMMENT ON COLUMN '
+ .$this->db->escape_identifiers($table).'.'.$this->db->escape_identifiers($field[$i]['name'])
+ .' IS '.$field[$i]['comment'];
}
}
- return $sql;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Drop Table
- *
- * @access private
- * @return bool
- */
- function _drop_table($table)
- {
- return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table)." CASCADE";
- }
+ 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.
*
- * @access private
- * @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 boolean should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return object
+ * @param array &$attributes
+ * @return void
*/
- 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->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
+ // Reset field lengths for data types that don't support it
+ if (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE)
{
- return $sql;
+ $attributes['CONSTRAINT'] = NULL;
}
- $sql .= " $column_definition";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"$default_value\"";
- }
-
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if ($after_field != '')
+ switch (strtoupper($attributes['TYPE']))
{
- $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
}
-
- return $sql;
-
}
// --------------------------------------------------------------------
/**
- * Rename a table
- *
- * Generates a platform-specific query so that a table can be renamed
+ * Field attribute AUTO_INCREMENT
*
- * @access private
- * @param string the old table name
- * @param string the new table name
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- function _rename_table($table_name, $new_table_name)
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name);
- return $sql;
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
+ {
+ $field['type'] = ($field['type'] === 'NUMERIC')
+ ? 'BIGSERIAL'
+ : 'SERIAL';
+ }
}
-
}
-
-/* End of file postgre_forge.php */
-/* Location: ./system/database/drivers/postgre/postgre_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/postgre/postgre_result.php b/system/database/drivers/postgre/postgre_result.php
index 8655f7aee..57864a7f3 100644
--- a/system/database/drivers/postgre/postgre_result.php
+++ b/system/database/drivers/postgre/postgre_result.php
@@ -1,40 +1,65 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Postgres Result Class
*
* This class extends the parent result class: CI_DB_result
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_postgre_result extends CI_DB_result {
/**
* Number of rows in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_rows()
+ public function num_rows()
{
- return @pg_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = pg_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -42,12 +67,11 @@ class CI_DB_postgre_result extends CI_DB_result {
/**
* Number of fields in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_fields()
+ public function num_fields()
{
- return @pg_num_fields($this->result_id);
+ return pg_num_fields($this->result_id);
}
// --------------------------------------------------------------------
@@ -57,13 +81,12 @@ class CI_DB_postgre_result extends CI_DB_result {
*
* Generates an array of column names
*
- * @access public
* @return array
*/
- function list_fields()
+ public function list_fields()
{
$field_names = array();
- for ($i = 0; $i < $this->num_fields(); $i++)
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
$field_names[] = pg_field_name($this->result_id, $i);
}
@@ -78,22 +101,17 @@ class CI_DB_postgre_result extends CI_DB_result {
*
* Generates an array of objects containing field meta-data
*
- * @access public
* @return array
*/
- function field_data()
+ public function field_data()
{
$retval = array();
- for ($i = 0; $i < $this->num_fields(); $i++)
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
- $F = new stdClass();
- $F->name = pg_field_name($this->result_id, $i);
- $F->type = pg_field_type($this->result_id, $i);
- $F->max_length = pg_field_size($this->result_id, $i);
- $F->primary_key = 0;
- $F->default = '';
-
- $retval[] = $F;
+ $retval[$i] = new stdClass();
+ $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);
}
return $retval;
@@ -104,9 +122,9 @@ class CI_DB_postgre_result extends CI_DB_result {
/**
* Free the result
*
- * @return null
+ * @return void
*/
- function free_result()
+ public function free_result()
{
if (is_resource($this->result_id))
{
@@ -120,14 +138,14 @@ class CI_DB_postgre_result extends CI_DB_result {
/**
* Data Seek
*
- * Moves the internal pointer to the desired offset. We call
+ * 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.
*
- * @access private
- * @return array
+ * @param int $n
+ * @return bool
*/
- function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return pg_result_seek($this->result_id, $n);
}
@@ -139,10 +157,9 @@ class CI_DB_postgre_result extends CI_DB_result {
*
* Returns the result set as an array
*
- * @access private
* @return array
*/
- function _fetch_assoc()
+ protected function _fetch_assoc()
{
return pg_fetch_assoc($this->result_id);
}
@@ -154,16 +171,12 @@ class CI_DB_postgre_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @access private
+ * @param string $class_name
* @return object
*/
- function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return pg_fetch_object($this->result_id);
+ return pg_fetch_object($this->result_id, NULL, $class_name);
}
}
-
-
-/* End of file postgre_result.php */
-/* Location: ./system/database/drivers/postgre/postgre_result.php */ \ No newline at end of file
diff --git a/system/database/drivers/postgre/postgre_utility.php b/system/database/drivers/postgre/postgre_utility.php
index d7af1a7ef..5ca358da5 100644
--- a/system/database/drivers/postgre/postgre_utility.php
+++ b/system/database/drivers/postgre/postgre_utility.php
@@ -1,88 +1,78 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Postgre Utility Class
*
+ * @package CodeIgniter
+ * @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_postgre_utility extends CI_DB_utility {
/**
- * List databases
- *
- * @access private
- * @return bool
- */
- function _list_databases()
- {
- return "SELECT datname FROM pg_database";
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Optimize table query
- *
- * Is table optimization supported in Postgre?
+ * List databases statement
*
- * @access private
- * @param string the table name
- * @return object
+ * @var string
*/
- function _optimize_table($table)
- {
- return FALSE;
- }
-
- // --------------------------------------------------------------------
+ protected $_list_databases = 'SELECT datname FROM pg_database';
/**
- * Repair table query
- *
- * Are table repairs supported in Postgre?
+ * OPTIMIZE TABLE statement
*
- * @access private
- * @param string the table name
- * @return object
+ * @var string
*/
- function _repair_table($table)
- {
- return FALSE;
- }
+ protected $_optimize_table = 'REINDEX TABLE %s';
// --------------------------------------------------------------------
/**
- * Postgre Export
+ * Export
*
- * @access private
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
- function _backup($params = array())
+ protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
-
-
-/* End of file postgre_utility.php */
-/* Location: ./system/database/drivers/postgre/postgre_utility.php */ \ No newline at end of file
diff --git a/system/database/drivers/sqlite/index.html b/system/database/drivers/sqlite/index.html
index c942a79ce..b702fbc39 100644
--- a/system/database/drivers/sqlite/index.html
+++ b/system/database/drivers/sqlite/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index 05ea6dd93..03c96e448 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -1,158 +1,105 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
-
-
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
* @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_sqlite_driver extends CI_DB {
- var $dbdriver = 'sqlite';
-
- // The character used to escape with - not needed for SQLite
- var $_escape_char = '';
-
- // clause and character used for LIKE escape sequences
- var $_like_escape_str = " ESCAPE '%s' ";
- var $_like_escape_chr = '!';
-
- /**
- * 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.
- */
- var $_count_string = "SELECT COUNT(*) AS ";
- var $_random_keyword = ' Random()'; // database specific random keyword
-
- /**
- * Non-persistent database connection
- *
- * @access private called by the base class
- * @return resource
- */
- function db_connect()
- {
- if ( ! $conn_id = @sqlite_open($this->database, FILE_WRITE_MODE, $error))
- {
- log_message('error', $error);
-
- if ($this->db_debug)
- {
- $this->display_error($error, '', TRUE);
- }
-
- return FALSE;
- }
-
- return $conn_id;
- }
-
- // --------------------------------------------------------------------
-
/**
- * Persistent database connection
+ * Database driver
*
- * @access private called by the base class
- * @return resource
+ * @var string
*/
- function db_pconnect()
- {
- if ( ! $conn_id = @sqlite_popen($this->database, FILE_WRITE_MODE, $error))
- {
- log_message('error', $error);
-
- if ($this->db_debug)
- {
- $this->display_error($error, '', TRUE);
- }
-
- return FALSE;
- }
-
- return $conn_id;
- }
+ public $dbdriver = 'sqlite';
// --------------------------------------------------------------------
/**
- * Reconnect
- *
- * Keep / reestablish the db connection if no queries have been
- * sent for a length of time exceeding the server's idle timeout
+ * ORDER BY random keyword
*
- * @access public
- * @return void
+ * @var array
*/
- function reconnect()
- {
- // not implemented in SQLite
- }
+ protected $_random_keyword = array('RANDOM()', 'RANDOM()');
// --------------------------------------------------------------------
/**
- * Select the database
+ * Non-persistent database connection
*
- * @access private called by the base class
+ * @param bool $persistent
* @return resource
*/
- function db_select()
+ public function db_connect($persistent = FALSE)
{
- return TRUE;
- }
+ $error = NULL;
+ $conn_id = ($persistent === TRUE)
+ ? sqlite_popen($this->database, 0666, $error)
+ : sqlite_open($this->database, 0666, $error);
- // --------------------------------------------------------------------
+ isset($error) && log_message('error', $error);
- /**
- * Set client character set
- *
- * @access public
- * @param string
- * @param string
- * @return resource
- */
- function db_set_charset($charset, $collation)
- {
- // @todo - add support if needed
- return TRUE;
+ return $conn_id;
}
// --------------------------------------------------------------------
/**
- * Version number query string
+ * Database version number
*
- * @access public
* @return string
*/
- function _version()
+ public function version()
{
- return sqlite_libversion();
+ return isset($this->data_cache['version'])
+ ? $this->data_cache['version']
+ : $this->data_cache['version'] = sqlite_libversion();
}
// --------------------------------------------------------------------
@@ -160,30 +107,14 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Execute the query
*
- * @access private called by the base class
- * @param string an SQL query
+ * @param string $sql an SQL query
* @return resource
*/
- function _execute($sql)
- {
- $sql = $this->_prep_query($sql);
- return @sqlite_query($this->conn_id, $sql);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Prep the query
- *
- * If needed, each database adapter can prep the query string
- *
- * @access private called by execute()
- * @param string an SQL query
- * @return string
- */
- function _prep_query($sql)
+ protected function _execute($sql)
{
- return $sql;
+ return $this->is_write_type($sql)
+ ? sqlite_exec($this->conn_id, $sql)
+ : sqlite_query($this->conn_id, $sql);
}
// --------------------------------------------------------------------
@@ -191,29 +122,11 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Begin Transaction
*
- * @access public
* @return bool
*/
- function trans_begin($test_mode = FALSE)
+ protected function _trans_begin()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
-
- $this->simple_query('BEGIN TRANSACTION');
- return TRUE;
+ return $this->simple_query('BEGIN TRANSACTION');
}
// --------------------------------------------------------------------
@@ -221,24 +134,11 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Commit Transaction
*
- * @access public
* @return bool
*/
- function trans_commit()
+ protected function _trans_commit()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- $this->simple_query('COMMIT');
- return TRUE;
+ return $this->simple_query('COMMIT');
}
// --------------------------------------------------------------------
@@ -246,59 +146,24 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Rollback Transaction
*
- * @access public
* @return bool
*/
- function trans_rollback()
+ protected function _trans_rollback()
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- $this->simple_query('ROLLBACK');
- return TRUE;
+ return $this->simple_query('ROLLBACK');
}
// --------------------------------------------------------------------
/**
- * Escape String
+ * Platform-dependant string escape
*
- * @access public
* @param string
- * @param bool whether or not the string will be used in a LIKE condition
* @return string
*/
- function escape_str($str, $like = FALSE)
+ protected function _escape_str($str)
{
- if (is_array($str))
- {
- foreach ($str as $key => $val)
- {
- $str[$key] = $this->escape_str($val, $like);
- }
-
- return $str;
- }
-
- $str = sqlite_escape_string($str);
-
- // escape LIKE condition wildcards
- if ($like === TRUE)
- {
- $str = str_replace( array('%', '_', $this->_like_escape_chr),
- array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
- $str);
- }
-
- return $str;
+ return sqlite_escape_string($str);
}
// --------------------------------------------------------------------
@@ -306,10 +171,9 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Affected Rows
*
- * @access public
- * @return integer
+ * @return int
*/
- function affected_rows()
+ public function affected_rows()
{
return sqlite_changes($this->conn_id);
}
@@ -319,43 +183,11 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Insert ID
*
- * @access public
- * @return integer
+ * @return int
*/
- function insert_id()
+ public function insert_id()
{
- return @sqlite_last_insert_rowid($this->conn_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
- *
- * @access public
- * @param string
- * @return string
- */
- function count_all($table = '')
- {
- if ($table == '')
- {
- return 0;
- }
-
- $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
-
- if ($query->num_rows() == 0)
- {
- return 0;
- }
-
- $row = $query->row();
- $this->_reset_select();
- return (int) $row->numrows;
+ return sqlite_last_insert_rowid($this->conn_id);
}
// --------------------------------------------------------------------
@@ -365,18 +197,18 @@ class CI_DB_sqlite_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @access private
- * @param boolean
+ * @param bool $prefix_limit
* @return string
*/
- function _list_tables($prefix_limit = FALSE)
+ protected function _list_tables($prefix_limit = FALSE)
{
- $sql = "SELECT name from sqlite_master WHERE type='table'";
+ $sql = "SELECT name FROM sqlite_master WHERE type='table'";
- if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ if ($prefix_limit !== FALSE && $this->dbprefix != '')
{
- $sql .= " AND 'name' LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
+ return $sql." AND 'name' LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
}
+
return $sql;
}
@@ -387,11 +219,10 @@ class CI_DB_sqlite_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @access public
- * @param string the table name
- * @return string
+ * @param string $table
+ * @return bool
*/
- function _list_columns($table = '')
+ protected function _list_columns($table = '')
{
// Not supported
return FALSE;
@@ -400,240 +231,88 @@ class CI_DB_sqlite_driver extends CI_DB {
// --------------------------------------------------------------------
/**
- * Field data query
+ * Returns an object with field data
*
- * Generates a platform-specific query so that the column data can be retrieved
- *
- * @access public
- * @param string the table name
- * @return object
+ * @param string $table
+ * @return array
*/
- function _field_data($table)
+ public function field_data($table)
{
- return "SELECT * FROM ".$table." LIMIT 1";
- }
-
- // --------------------------------------------------------------------
-
- /**
- * The error message string
- *
- * @access private
- * @return string
- */
- function _error_message()
- {
- return sqlite_error_string(sqlite_last_error($this->conn_id));
- }
-
- // --------------------------------------------------------------------
-
- /**
- * The error message number
- *
- * @access private
- * @return integer
- */
- function _error_number()
- {
- return sqlite_last_error($this->conn_id);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Escape the SQL Identifiers
- *
- * This function escapes column and table names
- *
- * @access private
- * @param string
- * @return string
- */
- function _escape_identifiers($item)
- {
- if ($this->_escape_char == '')
- {
- return $item;
- }
-
- foreach ($this->_reserved_identifiers as $id)
+ if (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
{
- if (strpos($item, '.'.$id) !== FALSE)
- {
- $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
-
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
- }
+ return FALSE;
}
- if (strpos($item, '.') !== FALSE)
- {
- $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
- }
- else
+ $query = $query->result_array();
+ if (empty($query))
{
- $str = $this->_escape_char.$item.$this->_escape_char;
+ return FALSE;
}
- // remove duplicates if the user already included the escape
- return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @access public
- * @param type
- * @return type
- */
- function _from_tables($tables)
- {
- if ( ! is_array($tables))
+ $retval = array();
+ for ($i = 0, $c = count($query); $i < $c; $i++)
{
- $tables = array($tables);
+ $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 '('.implode(', ', $tables).')';
+ return $retval;
}
// --------------------------------------------------------------------
/**
- * Insert statement
+ * Error
*
- * Generates a platform-specific insert string from the supplied data
+ * Returns an array containing code and message of the last
+ * database error that has occured.
*
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
- * @return string
+ * @return array
*/
- function _insert($table, $keys, $values)
+ public function error()
{
- return "INSERT INTO ".$table." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ $error = array('code' => sqlite_last_error($this->conn_id));
+ $error['message'] = sqlite_error_string($error['code']);
+ return $error;
}
// --------------------------------------------------------------------
/**
- * Update statement
+ * Replace statement
*
- * Generates a platform-specific update string from the supplied data
+ * Generates a platform-specific replace string from the supplied data
*
- * @access public
- * @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
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
* @return string
*/
- function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
+ protected function _replace($table, $keys, $values)
{
- foreach ($values as $key => $val)
- {
- $valstr[] = $key." = ".$val;
- }
-
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
-
- $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
-
- $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
-
- $sql .= $orderby.$limit;
-
- return $sql;
+ 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() command
- * This function maps to "DELETE FROM table"
*
- * @access public
- * @param string the table name
- * @return string
- */
- function _truncate($table)
- {
- return $this->_delete($table);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Delete statement
- *
- * Generates a platform-specific delete string from the supplied data
+ * If the database does not support the TRUNCATE statement,
+ * then this function maps to 'DELETE FROM table'
*
- * @access public
- * @param string the table name
- * @param array the where clause
- * @param string the limit clause
+ * @param string $table
* @return string
*/
- function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ protected function _truncate($table)
{
- $conditions = '';
-
- if (count($where) > 0 OR count($like) > 0)
- {
- $conditions = "\nWHERE ";
- $conditions .= implode("\n", $this->ar_where);
-
- if (count($where) > 0 && count($like) > 0)
- {
- $conditions .= " AND ";
- }
- $conditions .= implode("\n", $like);
- }
-
- $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
-
- return "DELETE FROM ".$table.$conditions.$limit;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Limit string
- *
- * Generates a platform-specific LIMIT clause
- *
- * @access public
- * @param string the sql query string
- * @param integer the number of rows to limit the query to
- * @param integer the offset value
- * @return string
- */
- function _limit($sql, $limit, $offset)
- {
- if ($offset == 0)
- {
- $offset = '';
- }
- else
- {
- $offset .= ", ";
- }
-
- return $sql."LIMIT ".$offset.$limit;
+ return 'DELETE FROM '.$table;
}
// --------------------------------------------------------------------
@@ -641,18 +320,11 @@ class CI_DB_sqlite_driver extends CI_DB {
/**
* Close DB Connection
*
- * @access public
- * @param resource
* @return void
*/
- function _close($conn_id)
+ protected function _close()
{
- @sqlite_close($conn_id);
+ sqlite_close($this->conn_id);
}
-
}
-
-
-/* End of file sqlite_driver.php */
-/* Location: ./system/database/drivers/sqlite/sqlite_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/sqlite/sqlite_forge.php b/system/database/drivers/sqlite/sqlite_forge.php
index a15e94d3b..a0fc0cdb0 100644
--- a/system/database/drivers/sqlite/sqlite_forge.php
+++ b/system/database/drivers/sqlite/sqlite_forge.php
@@ -1,37 +1,81 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite Forge Class
*
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
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
*
- * @access public
- * @param string the database name
+ * @param string $db_name (ignored)
* @return bool
*/
- function _create_database()
+ 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
@@ -43,223 +87,119 @@ class CI_DB_sqlite_forge extends CI_DB_forge {
/**
* Drop database
*
- * @access private
- * @param string the database name
+ * @param string $db_name (ignored)
* @return bool
*/
- function _drop_database($name)
+ public function drop_database($db_name)
{
- if ( ! @file_exists($this->db->database) OR ! @unlink($this->db->database))
+ if ( ! file_exists($this->db->database) OR ! @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']))
{
- if ($this->db->db_debug)
+ $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
+ if ($key !== FALSE)
{
- return $this->db->display_error('db_unable_to_drop');
+ unset($this->db->data_cache['db_names'][$key]);
}
- return FALSE;
}
+
return TRUE;
}
+
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @access private
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param boolean 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[]
*/
- 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->_protect_identifiers($field);
-
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ // 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;
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
-
- if (count($primary_keys) > 0)
- {
- $primary_keys = $this->db->_protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $primary_keys) . ")";
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key = $this->db->_protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->_protect_identifiers($key));
- }
-
- $sql .= ",\n\tUNIQUE (" . implode(', ', $key) . ")";
- }
+ return FALSE;
}
- $sql .= "\n)";
-
- return $sql;
+ return parent::_alter_table($alter_type, $table, $field);
}
// --------------------------------------------------------------------
/**
- * Drop Table
- *
- * Unsupported feature in SQLite
+ * Process column
*
- * @access private
- * @return bool
+ * @param array $field
+ * @return string
*/
- function _drop_table($table)
+ protected function _process_column($field)
{
- if ($this->db->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return array();
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type']
+ .$field['auto_increment']
+ .$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.
*
- * @access private
- * @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 boolean should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return object
+ * @param array &$attributes
+ * @return void
*/
- 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->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
+ switch (strtoupper($attributes['TYPE']))
{
- // SQLite does not support dropping columns
- // http://www.sqlite.org/omitted.html
- // http://www.sqlite.org/faq.html#q11
- return FALSE;
+ case 'ENUM':
+ case 'SET':
+ $attributes['TYPE'] = 'TEXT';
+ return;
+ default: return;
}
-
- $sql .= " $column_definition";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"$default_value\"";
- }
-
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if ($after_field != '')
- {
- $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
- }
-
- return $sql;
-
}
// --------------------------------------------------------------------
/**
- * Rename a table
+ * Field attribute AUTO_INCREMENT
*
- * Generates a platform-specific query so that a table can be renamed
- *
- * @access private
- * @param string the old table name
- * @param string the new table name
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- function _rename_table($table_name, $new_table_name)
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name);
- return $sql;
+ 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 sqlite_forge.php */
-/* Location: ./system/database/drivers/sqlite/sqlite_forge.php */ \ No newline at end of file
+}
diff --git a/system/database/drivers/sqlite/sqlite_result.php b/system/database/drivers/sqlite/sqlite_result.php
index 9e519dffd..34d3ac3c1 100644
--- a/system/database/drivers/sqlite/sqlite_result.php
+++ b/system/database/drivers/sqlite/sqlite_result.php
@@ -1,19 +1,41 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite Result Class
@@ -21,20 +43,21 @@
* This class extends the parent result class: CI_DB_result
*
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_sqlite_result extends CI_DB_result {
/**
* Number of rows in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_rows()
+ public function num_rows()
{
- return @sqlite_num_rows($this->result_id);
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = @sqlite_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -42,10 +65,9 @@ class CI_DB_sqlite_result extends CI_DB_result {
/**
* Number of fields in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_fields()
+ public function num_fields()
{
return @sqlite_num_fields($this->result_id);
}
@@ -57,15 +79,14 @@ class CI_DB_sqlite_result extends CI_DB_result {
*
* Generates an array of column names
*
- * @access public
* @return array
*/
- function list_fields()
+ public function list_fields()
{
$field_names = array();
- for ($i = 0; $i < $this->num_fields(); $i++)
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
- $field_names[] = sqlite_field_name($this->result_id, $i);
+ $field_names[$i] = sqlite_field_name($this->result_id, $i);
}
return $field_names;
@@ -78,22 +99,17 @@ class CI_DB_sqlite_result extends CI_DB_result {
*
* Generates an array of objects containing field meta-data
*
- * @access public
* @return array
*/
- function field_data()
+ public function field_data()
{
$retval = array();
- for ($i = 0; $i < $this->num_fields(); $i++)
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
{
- $F = new stdClass();
- $F->name = sqlite_field_name($this->result_id, $i);
- $F->type = 'varchar';
- $F->max_length = 0;
- $F->primary_key = 0;
- $F->default = '';
-
- $retval[] = $F;
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = sqlite_field_name($this->result_id, $i);
+ $retval[$i]->type = NULL;
+ $retval[$i]->max_length = NULL;
}
return $retval;
@@ -102,28 +118,16 @@ class CI_DB_sqlite_result extends CI_DB_result {
// --------------------------------------------------------------------
/**
- * Free the result
- *
- * @return null
- */
- function free_result()
- {
- // Not implemented in SQLite
- }
-
- // --------------------------------------------------------------------
-
- /**
* Data Seek
*
- * Moves the internal pointer to the desired offset. We call
+ * 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.
*
- * @access private
- * @return array
+ * @param int $n
+ * @return bool
*/
- function _data_seek($n = 0)
+ public function data_seek($n = 0)
{
return sqlite_seek($this->result_id, $n);
}
@@ -135,10 +139,9 @@ class CI_DB_sqlite_result extends CI_DB_result {
*
* Returns the result set as an array
*
- * @access private
* @return array
*/
- function _fetch_assoc()
+ protected function _fetch_assoc()
{
return sqlite_fetch_array($this->result_id);
}
@@ -150,30 +153,12 @@ class CI_DB_sqlite_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @access private
+ * @param string $class_name
* @return object
*/
- function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- if (function_exists('sqlite_fetch_object'))
- {
- return sqlite_fetch_object($this->result_id);
- }
- else
- {
- $arr = sqlite_fetch_array($this->result_id, SQLITE_ASSOC);
- if (is_array($arr))
- {
- $obj = (object) $arr;
- return $obj;
- } else {
- return NULL;
- }
- }
+ return sqlite_fetch_object($this->result_id, $class_name);
}
}
-
-
-/* End of file sqlite_result.php */
-/* Location: ./system/database/drivers/sqlite/sqlite_result.php */ \ No newline at end of file
diff --git a/system/database/drivers/sqlite/sqlite_utility.php b/system/database/drivers/sqlite/sqlite_utility.php
index 481b735be..90ca4b161 100644
--- a/system/database/drivers/sqlite/sqlite_utility.php
+++ b/system/database/drivers/sqlite/sqlite_utility.php
@@ -1,96 +1,61 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.3.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLite Utility Class
*
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_sqlite_utility extends CI_DB_utility {
/**
- * List databases
- *
- * I don't believe you can do a database listing with SQLite
- * since each database is its own file. I suppose we could
- * try reading a directory looking for SQLite files, but
- * that doesn't seem like a terribly good idea
- *
- * @access private
- * @return bool
- */
- function _list_databases()
- {
- if ($this->db_debug)
- {
- return $this->db->display_error('db_unsuported_feature');
- }
- return array();
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Optimize table query
- *
- * Is optimization even supported in SQLite?
- *
- * @access private
- * @param string the table name
- * @return object
- */
- function _optimize_table($table)
- {
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Repair table query
- *
- * Are table repairs even supported in SQLite?
- *
- * @access private
- * @param string the table name
- * @return object
- */
- function _repair_table($table)
- {
- return FALSE;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * SQLite Export
+ * Export
*
- * @access private
- * @param array Preferences
+ * @param array $params Preferences
* @return mixed
*/
- function _backup($params = array())
+ protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
-}
-/* End of file sqlite_utility.php */
-/* Location: ./system/database/drivers/sqlite/sqlite_utility.php */ \ No newline at end of file
+}
diff --git a/system/database/drivers/sqlite3/index.html b/system/database/drivers/sqlite3/index.html
new file mode 100644
index 000000000..b702fbc39
--- /dev/null
+++ b/system/database/drivers/sqlite3/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>403 Forbidden</title>
+</head>
+<body>
+
+<p>Directory access is forbidden.</p>
+
+</body>
+</html>
diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php
new file mode 100644
index 000000000..d131baad7
--- /dev/null
+++ b/system/database/drivers/sqlite3/sqlite3_driver.php
@@ -0,0 +1,350 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * SQLite3 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 Andrey Andreev
+ * @link https://codeigniter.com/user_guide/database/
+ */
+class CI_DB_sqlite3_driver extends CI_DB {
+
+ /**
+ * Database driver
+ *
+ * @var string
+ */
+ public $dbdriver = 'sqlite3';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ORDER BY random keyword
+ *
+ * @var array
+ */
+ protected $_random_keyword = array('RANDOM()', 'RANDOM()');
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Non-persistent database connection
+ *
+ * @param bool $persistent
+ * @return SQLite3
+ */
+ public function db_connect($persistent = FALSE)
+ {
+ if ($persistent)
+ {
+ log_message('debug', 'SQLite3 doesn\'t support persistent connections');
+ }
+
+ try
+ {
+ return ( ! $this->password)
+ ? new SQLite3($this->database)
+ : new SQLite3($this->database, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE, $this->password);
+ }
+ catch (Exception $e)
+ {
+ return FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Database version number
+ *
+ * @return string
+ */
+ public function version()
+ {
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+
+ $version = SQLite3::version();
+ return $this->data_cache['version'] = $version['versionString'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Execute the query
+ *
+ * @todo Implement use of SQLite3::querySingle(), if needed
+ * @param string $sql
+ * @return mixed SQLite3Result object or bool
+ */
+ protected function _execute($sql)
+ {
+ return $this->is_write_type($sql)
+ ? $this->conn_id->exec($sql)
+ : $this->conn_id->query($sql);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Begin Transaction
+ *
+ * @return bool
+ */
+ protected function _trans_begin()
+ {
+ return $this->conn_id->exec('BEGIN TRANSACTION');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Commit Transaction
+ *
+ * @return bool
+ */
+ protected function _trans_commit()
+ {
+ return $this->conn_id->exec('END TRANSACTION');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Rollback Transaction
+ *
+ * @return bool
+ */
+ protected function _trans_rollback()
+ {
+ return $this->conn_id->exec('ROLLBACK');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Platform-dependent string escape
+ *
+ * @param string
+ * @return string
+ */
+ protected function _escape_str($str)
+ {
+ return $this->conn_id->escapeString($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Affected Rows
+ *
+ * @return int
+ */
+ public function affected_rows()
+ {
+ return $this->conn_id->changes();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @return int
+ */
+ public function insert_id()
+ {
+ return $this->conn_id->lastInsertRowID();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * 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 "NAME" FROM "SQLITE_MASTER" WHERE "TYPE" = \'table\''
+ .(($prefix_limit !== FALSE && $this->dbprefix != '')
+ ? ' AND "NAME" LIKE \''.$this->escape_like_str($this->dbprefix).'%\' '.sprintf($this->_like_escape_str, $this->_like_escape_chr)
+ : '');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch Field Names
+ *
+ * @param string $table Table name
+ * @return array
+ */
+ public function list_fields($table)
+ {
+ // Is there a cached result?
+ if (isset($this->data_cache['field_names'][$table]))
+ {
+ return $this->data_cache['field_names'][$table];
+ }
+
+ if (($result = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)
+ {
+ return FALSE;
+ }
+
+ $this->data_cache['field_names'][$table] = array();
+ foreach ($result->result_array() as $row)
+ {
+ $this->data_cache['field_names'][$table][] = $row['name'];
+ }
+
+ return $this->data_cache['field_names'][$table];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Returns an object with field data
+ *
+ * @param string $table
+ * @return array
+ */
+ public function field_data($table)
+ {
+ 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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Error
+ *
+ * Returns an array containing code and message of the last
+ * database error that has occurred.
+ *
+ * @return array
+ */
+ public function error()
+ {
+ return array('code' => $this->conn_id->lastErrorCode(), 'message' => $this->conn_id->lastErrorMsg());
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Replace statement
+ *
+ * Generates a platform-specific replace string from the supplied data
+ *
+ * @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;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Close DB Connection
+ *
+ * @return void
+ */
+ protected function _close()
+ {
+ $this->conn_id->close();
+ }
+
+}
diff --git a/system/database/drivers/sqlite3/sqlite3_forge.php b/system/database/drivers/sqlite3/sqlite3_forge.php
new file mode 100644
index 000000000..5ee6daae3
--- /dev/null
+++ b/system/database/drivers/sqlite3/sqlite3_forge.php
@@ -0,0 +1,225 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * SQLite3 Forge Class
+ *
+ * @category Database
+ * @author Andrey Andreev
+ * @link https://codeigniter.com/user_guide/database/
+ */
+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;
+ $this->_drop_table_if = FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create database
+ *
+ * @param string $db_name
+ * @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
+ *
+ * @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 _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();
+ }
+ }
+
+}
diff --git a/system/database/drivers/sqlite3/sqlite3_result.php b/system/database/drivers/sqlite3/sqlite3_result.php
new file mode 100644
index 000000000..03751f0dc
--- /dev/null
+++ b/system/database/drivers/sqlite3/sqlite3_result.php
@@ -0,0 +1,194 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * SQLite3 Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category Database
+ * @author Andrey Andreev
+ * @link https://codeigniter.com/user_guide/database/
+ */
+class CI_DB_sqlite3_result extends CI_DB_result {
+
+ /**
+ * Number of fields in the result set
+ *
+ * @return int
+ */
+ public function num_fields()
+ {
+ return $this->result_id->numColumns();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch Field Names
+ *
+ * Generates an array of column names
+ *
+ * @return array
+ */
+ public function list_fields()
+ {
+ $field_names = array();
+ for ($i = 0, $c = $this->num_fields(); $i < $c; $i++)
+ {
+ $field_names[] = $this->result_id->columnName($i);
+ }
+
+ return $field_names;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data
+ *
+ * Generates an array of objects containing field meta-data
+ *
+ * @return array
+ */
+ 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 < $c; $i++)
+ {
+ $retval[$i] = new stdClass();
+ $retval[$i]->name = $this->result_id->columnName($i);
+
+ $type = $this->result_id->columnType($i);
+ $retval[$i]->type = isset($data_types[$type]) ? $data_types[$type] : $type;
+
+ $retval[$i]->max_length = NULL;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Free the result
+ *
+ * @return void
+ */
+ public function free_result()
+ {
+ if (is_object($this->result_id))
+ {
+ $this->result_id->finalize();
+ $this->result_id = NULL;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - associative array
+ *
+ * Returns the result set as an array
+ *
+ * @return array
+ */
+ protected function _fetch_assoc()
+ {
+ return $this->result_id->fetchArray(SQLITE3_ASSOC);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - object
+ *
+ * Returns the result set as an object
+ *
+ * @param string $class_name
+ * @return object
+ */
+ protected function _fetch_object($class_name = 'stdClass')
+ {
+ // No native support for fetching rows as objects
+ if (($row = $this->result_id->fetchArray(SQLITE3_ASSOC)) === FALSE)
+ {
+ return FALSE;
+ }
+ elseif ($class_name === 'stdClass')
+ {
+ return (object) $row;
+ }
+
+ $class_name = new $class_name();
+ foreach (array_keys($row) as $key)
+ {
+ $class_name->$key = $row[$key];
+ }
+
+ 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.
+ *
+ * @param int $n (ignored)
+ * @return array
+ */
+ public function data_seek($n = 0)
+ {
+ // Only resetting to the start of the result set is supported
+ 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
new file mode 100644
index 000000000..20d562f96
--- /dev/null
+++ b/system/database/drivers/sqlite3/sqlite3_utility.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP
+ *
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 3.0.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * SQLite3 Utility Class
+ *
+ * @category Database
+ * @author Andrey Andreev
+ * @link https://codeigniter.com/user_guide/database/
+ */
+class CI_DB_sqlite3_utility extends CI_DB_utility {
+
+ /**
+ * Export
+ *
+ * @param array $params Preferences
+ * @return mixed
+ */
+ protected function _backup($params = array())
+ {
+ // Not supported
+ return $this->db->display_error('db_unsupported_feature');
+ }
+
+}
diff --git a/system/database/drivers/sqlsrv/index.html b/system/database/drivers/sqlsrv/index.html
index c942a79ce..b702fbc39 100644
--- a/system/database/drivers/sqlsrv/index.html
+++ b/system/database/drivers/sqlsrv/index.html
@@ -1,3 +1,4 @@
+<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
@@ -7,4 +8,4 @@
<p>Directory access is forbidden.</p>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php
index 328c8fe7d..a43e2539a 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -1,351 +1,280 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 2.0.3
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLSRV Database Adapter Class
*
* Note: _DB is an extender class that the app controller
- * creates dynamically based on whether the active record
+ * creates dynamically based on whether the query builder
* class is being used or not.
*
* @package CodeIgniter
* @subpackage Drivers
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_sqlsrv_driver extends CI_DB {
- var $dbdriver = 'sqlsrv';
-
- // The character used for escaping
- var $_escape_char = '';
-
- // clause and character used for LIKE escape sequences
- var $_like_escape_str = " ESCAPE '%s' ";
- var $_like_escape_chr = '!';
-
- /**
- * 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.
- */
- var $_count_string = "SELECT COUNT(*) AS ";
- var $_random_keyword = ' ASC'; // not currently supported
-
/**
- * Non-persistent database connection
+ * Database driver
*
- * @access private called by the base class
- * @return resource
+ * @var string
*/
- 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;
-
- $connection = array(
- 'UID' => empty($this->username) ? '' : $this->username,
- 'PWD' => empty($this->password) ? '' : $this->password,
- 'Database' => $this->database,
- 'ConnectionPooling' => $pooling ? 1 : 0,
- 'CharacterSet' => $character_set,
- 'ReturnDatesAsStrings' => 1
- );
-
- // If the username and password are both empty, assume this is a
- // 'Windows Authentication Mode' connection.
- if(empty($connection['UID']) && empty($connection['PWD'])) {
- unset($connection['UID'], $connection['PWD']);
- }
-
- return sqlsrv_connect($this->hostname, $connection);
- }
-
- // --------------------------------------------------------------------
+ public $dbdriver = 'sqlsrv';
/**
- * Persistent database connection
+ * Scrollable flag
*
- * @access private called by the base class
- * @return resource
- */
- function db_pconnect()
- {
- $this->db_connect(TRUE);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Reconnect
+ * Determines what cursor type to use when executing queries.
*
- * Keep / reestablish the db connection if no queries have been
- * sent for a length of time exceeding the server's idle timeout
+ * FALSE or SQLSRV_CURSOR_FORWARD would increase performance,
+ * but would disable num_rows() (and possibly insert_id())
*
- * @access public
- * @return void
+ * @var mixed
*/
- function reconnect()
- {
- // not implemented in MSSQL
- }
+ public $scrollable;
// --------------------------------------------------------------------
/**
- * Select the database
+ * ORDER BY random keyword
*
- * @access private called by the base class
- * @return resource
+ * @var array
*/
- function db_select()
- {
- return $this->_execute('USE ' . $this->database);
- }
-
- // --------------------------------------------------------------------
+ protected $_random_keyword = array('NEWID()', 'RAND(%d)');
/**
- * Set client character set
+ * Quoted identifier flag
*
- * @access public
- * @param string
- * @param string
- * @return resource
+ * Whether to use SQL-92 standard quoted identifier
+ * (double quotes) or brackets for identifier escaping.
+ *
+ * @var bool
*/
- function db_set_charset($charset, $collation)
- {
- // @todo - add support if needed
- return TRUE;
- }
+ protected $_quoted_identifier = TRUE;
// --------------------------------------------------------------------
/**
- * Execute the query
+ * Class constructor
*
- * @access private called by the base class
- * @param string an SQL query
- * @return resource
+ * @param array $params
+ * @return void
*/
- function _execute($sql)
+ public function __construct($params)
{
- $sql = $this->_prep_query($sql);
- return sqlsrv_query($this->conn_id, $sql, null, array(
- 'Scrollable' => SQLSRV_CURSOR_STATIC,
- 'SendStreamParamsAtExec' => true
- ));
+ parent::__construct($params);
+
+ // This is only supported as of SQLSRV 3.0
+ if ($this->scrollable === NULL)
+ {
+ $this->scrollable = defined('SQLSRV_CURSOR_CLIENT_BUFFERED')
+ ? SQLSRV_CURSOR_CLIENT_BUFFERED
+ : FALSE;
+ }
}
// --------------------------------------------------------------------
/**
- * Prep the query
+ * Database connection
*
- * If needed, each database adapter can prep the query string
- *
- * @access private called by execute()
- * @param string an SQL query
- * @return string
+ * @param bool $pooling
+ * @return resource
*/
- function _prep_query($sql)
+ public function db_connect($pooling = FALSE)
{
- return $sql;
- }
+ $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 === TRUE) ? 1 : 0,
+ 'CharacterSet' => $charset,
+ 'Encrypt' => ($this->encrypt === TRUE) ? 1 : 0,
+ 'ReturnDatesAsStrings' => 1
+ );
- /**
- * Begin Transaction
- *
- * @access public
- * @return bool
- */
- function trans_begin($test_mode = FALSE)
- {
- if ( ! $this->trans_enabled)
+ // If the username and password are both empty, assume this is a
+ // 'Windows Authentication Mode' connection.
+ if (empty($connection['UID']) && empty($connection['PWD']))
{
- return TRUE;
+ unset($connection['UID'], $connection['PWD']);
}
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if (FALSE !== ($this->conn_id = sqlsrv_connect($this->hostname, $connection)))
{
- return TRUE;
+ // 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('[', ']');
}
- // Reset the transaction failure flag.
- // If the $test_mode flag is set to TRUE transactions will be rolled back
- // even if the queries produce a successful result.
- $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
-
- return sqlsrv_begin_transaction($this->conn_id);
+ return $this->conn_id;
}
// --------------------------------------------------------------------
/**
- * Commit Transaction
+ * Select the database
*
- * @access public
+ * @param string $database
* @return bool
*/
- function trans_commit()
+ public function db_select($database = '')
{
- if ( ! $this->trans_enabled)
+ if ($database === '')
{
- return TRUE;
+ $database = $this->database;
}
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
+ if ($this->_execute('USE '.$this->escape_identifiers($database)))
{
+ $this->database = $database;
+ $this->data_cache = array();
return TRUE;
}
- return sqlsrv_commit($this->conn_id);
+ return FALSE;
}
// --------------------------------------------------------------------
/**
- * Rollback Transaction
+ * Execute the query
*
- * @access public
- * @return bool
+ * @param string $sql an SQL query
+ * @return resource
*/
- function trans_rollback()
+ protected function _execute($sql)
{
- if ( ! $this->trans_enabled)
- {
- return TRUE;
- }
-
- // When transactions are nested we only begin/commit/rollback the outermost ones
- if ($this->_trans_depth > 0)
- {
- return TRUE;
- }
-
- return sqlsrv_rollback($this->conn_id);
+ return ($this->scrollable === FALSE OR $this->is_write_type($sql))
+ ? sqlsrv_query($this->conn_id, $sql)
+ : sqlsrv_query($this->conn_id, $sql, NULL, array('Scrollable' => $this->scrollable));
}
// --------------------------------------------------------------------
/**
- * Escape String
+ * Begin Transaction
*
- * @access public
- * @param string
- * @param bool whether or not the string will be used in a LIKE condition
- * @return string
+ * @return bool
*/
- function escape_str($str, $like = FALSE)
+ protected function _trans_begin()
{
- // Escape single quotes
- return str_replace("'", "''", $str);
+ return sqlsrv_begin_transaction($this->conn_id);
}
// --------------------------------------------------------------------
/**
- * Affected Rows
+ * Commit Transaction
*
- * @access public
- * @return integer
+ * @return bool
*/
- function affected_rows()
+ protected function _trans_commit()
{
- return @sqlrv_rows_affected($this->conn_id);
+ return sqlsrv_commit($this->conn_id);
}
// --------------------------------------------------------------------
/**
- * Insert ID
- *
- * Returns the last id created in the Identity column.
- *
- * @access public
- * @return integer
- */
- function insert_id()
+ * Rollback Transaction
+ *
+ * @return bool
+ */
+ protected function _trans_rollback()
{
- return $this->query('select @@IDENTITY as insert_id')->row('insert_id');
+ return sqlsrv_rollback($this->conn_id);
}
// --------------------------------------------------------------------
/**
- * Parse major version
- *
- * Grabs the major version number from the
- * database server version string passed in.
- *
- * @access private
- * @param string $version
- * @return int16 major version number
- */
- function _parse_major_version($version)
+ * Affected Rows
+ *
+ * @return int
+ */
+ public function affected_rows()
{
- preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)/', $version, $ver_info);
- return $ver_info[1]; // return the major version b/c that's all we're interested in.
+ return sqlsrv_rows_affected($this->result_id);
}
// --------------------------------------------------------------------
/**
- * Version number query string
- *
- * @access public
- * @return string
- */
- function _version()
+ * Insert ID
+ *
+ * Returns the last id created in the Identity column.
+ *
+ * @return string
+ */
+ public function insert_id()
{
- $info = sqlsrv_server_info($this->conn_id);
- return sprintf("select '%s' as ver", $info['SQLServerVersion']);
+ return $this->query('SELECT SCOPE_IDENTITY() AS insert_id')->row()->insert_id;
}
// --------------------------------------------------------------------
/**
- * "Count All" query
- *
- * Generates a platform-specific query string that counts all records in
- * the specified database
+ * Database version number
*
- * @access public
- * @param string
* @return string
*/
- function count_all($table = '')
+ public function version()
{
- if ($table == '')
- return '0';
-
- $query = $this->query("SELECT COUNT(*) AS numrows FROM " . $this->dbprefix . $table);
-
- if ($query->num_rows() == 0)
- return '0';
-
- $row = $query->row();
- $this->_reset_select();
- return $row->numrows;
+ if (isset($this->data_cache['version']))
+ {
+ return $this->data_cache['version'];
+ }
+
+ if ( ! $this->conn_id OR ($info = sqlsrv_server_info($this->conn_id)) === FALSE)
+ {
+ return FALSE;
+ }
+
+ return $this->data_cache['version'] = $info['SQLServerVersion'];
}
// --------------------------------------------------------------------
@@ -355,13 +284,22 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*
* Generates a platform-specific query string so that the table names can be fetched
*
- * @access private
- * @param boolean
- * @return string
+ * @param bool
+ * @return string $prefix_limit
*/
- function _list_tables($prefix_limit = FALSE)
+ protected function _list_tables($prefix_limit = FALSE)
{
- return "SELECT name FROM sysobjects WHERE type = 'U' ORDER BY name";
+ $sql = '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->_escape_like_str, $this->_escape_like_chr);
+ }
+
+ return $sql.' ORDER BY '.$this->escape_identifiers('name');
}
// --------------------------------------------------------------------
@@ -371,210 +309,223 @@ class CI_DB_sqlsrv_driver extends CI_DB {
*
* Generates a platform-specific query string so that the column names can be fetched
*
- * @access private
- * @param string the table name
+ * @param string $table
* @return string
*/
- function _list_columns($table = '')
+ protected function _list_columns($table = '')
{
- return "SELECT * FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$this->_escape_table($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
*
- * @access public
- * @param string the table name
- * @return object
+ * @param string $table
+ * @return array
*/
- function _field_data($table)
+ public function field_data($table)
{
- return "SELECT TOP 1 * FROM " . $this->_escape_table($table);
- }
-
- // --------------------------------------------------------------------
+ $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));
- /**
- * The error message string
- *
- * @access private
- * @return string
- */
- function _error_message()
- {
- $error = array_shift(sqlsrv_errors());
- return !empty($error['message']) ? $error['message'] : null;
- }
+ 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;
+ }
- /**
- * The error message number
- *
- * @access private
- * @return integer
- */
- function _error_number()
- {
- $error = array_shift(sqlsrv_errors());
- return isset($error['SQLSTATE']) ? $error['SQLSTATE'] : null;
+ return $retval;
}
// --------------------------------------------------------------------
/**
- * Escape Table Name
+ * Error
*
- * This function adds backticks if the table name has a period
- * in it. Some DBs will get cranky unless periods are escaped
+ * Returns an array containing code and message of the last
+ * database error that has occurred.
*
- * @access private
- * @param string the table name
- * @return string
+ * @return array
*/
- function _escape_table($table)
+ public function error()
{
- return $table;
- }
-
+ $error = array('code' => '00000', 'message' => '');
+ $sqlsrv_errors = sqlsrv_errors(SQLSRV_ERR_ERRORS);
- /**
- * Escape the SQL Identifiers
- *
- * This function escapes column and table names
- *
- * @access private
- * @param string
- * @return string
- */
- function _escape_identifiers($item)
- {
- return $item;
- }
+ if ( ! is_array($sqlsrv_errors))
+ {
+ return $error;
+ }
- // --------------------------------------------------------------------
+ $sqlsrv_error = array_shift($sqlsrv_errors);
+ if (isset($sqlsrv_error['SQLSTATE']))
+ {
+ $error['code'] = isset($sqlsrv_error['code']) ? $sqlsrv_error['SQLSTATE'].'/'.$sqlsrv_error['code'] : $sqlsrv_error['SQLSTATE'];
+ }
+ elseif (isset($sqlsrv_error['code']))
+ {
+ $error['code'] = $sqlsrv_error['code'];
+ }
- /**
- * From Tables
- *
- * This function implicitly groups FROM tables so there is no confusion
- * about operator precedence in harmony with SQL standards
- *
- * @access public
- * @param type
- * @return type
- */
- function _from_tables($tables)
- {
- if ( ! is_array($tables))
+ if (isset($sqlsrv_error['message']))
{
- $tables = array($tables);
+ $error['message'] = $sqlsrv_error['message'];
}
- return implode(', ', $tables);
+ return $error;
}
// --------------------------------------------------------------------
/**
- * Insert statement
+ * Update statement
*
- * Generates a platform-specific insert string from the supplied data
+ * Generates a platform-specific update string from the supplied data
*
- * @access public
- * @param string the table name
- * @param array the insert keys
- * @param array the insert values
+ * @param string $table
+ * @param array $values
* @return string
*/
- function _insert($table, $keys, $values)
- {
- return "INSERT INTO ".$this->_escape_table($table)." (".implode(', ', $keys).") VALUES (".implode(', ', $values).")";
+ protected function _update($table, $values)
+ {
+ $this->qb_limit = FALSE;
+ $this->qb_orderby = array();
+ return parent::_update($table, $values);
}
// --------------------------------------------------------------------
/**
- * Update statement
+ * Truncate statement
*
- * Generates a platform-specific update string from the supplied data
+ * Generates a platform-specific truncate string from the supplied data
*
- * @access public
- * @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
+ * If the database does not support the TRUNCATE statement,
+ * then this method maps to 'DELETE FROM table'
+ *
+ * @param string $table
* @return string
*/
- function _update($table, $values, $where)
+ protected function _truncate($table)
{
- foreach($values as $key => $val)
- {
- $valstr[] = $key." = ".$val;
- }
-
- return "UPDATE ".$this->_escape_table($table)." SET ".implode(', ', $valstr)." WHERE ".implode(" ", $where);
+ return 'TRUNCATE TABLE '.$table;
}
-
+
// --------------------------------------------------------------------
/**
- * Truncate statement
+ * Delete statement
*
- * Generates a platform-specific truncate string from the supplied data
- * If the database does not support the truncate() command
- * This function maps to "DELETE FROM table"
+ * Generates a platform-specific delete string from the supplied data
*
- * @access public
- * @param string the table name
+ * @param string $table
* @return string
*/
- function _truncate($table)
+ protected function _delete($table)
{
- return "TRUNCATE TABLE ".$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);
}
// --------------------------------------------------------------------
/**
- * Delete statement
+ * LIMIT
*
- * Generates a platform-specific delete string from the supplied data
+ * Generates a platform-specific LIMIT clause
*
- * @access public
- * @param string the table name
- * @param array the where clause
- * @param string the limit clause
+ * @param string $sql SQL Query
* @return string
*/
- function _delete($table, $where)
+ protected function _limit($sql)
{
- return "DELETE FROM ".$this->_escape_table($table)." WHERE ".implode(" ", $where);
+ // As of SQL Server 2012 (11.0.*) OFFSET is supported
+ if (version_compare($this->version(), '11', '>='))
+ {
+ // SQL Server OFFSET-FETCH can be used only with the ORDER BY clause
+ empty($this->qb_orderby) && $sql .= ' ORDER BY 1';
+
+ 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);
}
// --------------------------------------------------------------------
/**
- * Limit string
+ * Insert batch statement
*
- * Generates a platform-specific LIMIT clause
+ * Generates a platform-specific insert string from the supplied data.
*
- * @access public
- * @param string the sql query string
- * @param integer the number of rows to limit the query to
- * @param integer the offset value
- * @return string
+ * @param string $table Table name
+ * @param array $keys INSERT keys
+ * @param array $values INSERT values
+ * @return string|bool
*/
- function _limit($sql, $limit, $offset)
+ protected function _insert_batch($table, $keys, $values)
{
- $i = $limit + $offset;
-
- return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$i.' ', $sql);
+ // 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_debug) ? $this->display_error('db_unsupported_feature') : FALSE;
}
// --------------------------------------------------------------------
@@ -582,18 +533,11 @@ class CI_DB_sqlsrv_driver extends CI_DB {
/**
* Close DB Connection
*
- * @access public
- * @param resource
* @return void
*/
- function _close($conn_id)
+ protected function _close()
{
- @sqlsrv_close($conn_id);
+ sqlsrv_close($this->conn_id);
}
}
-
-
-
-/* End of file mssql_driver.php */
-/* Location: ./system/database/drivers/mssql/mssql_driver.php */ \ No newline at end of file
diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php
index 8f879d2f6..aa8490ee4 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_forge.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php
@@ -1,245 +1,149 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 2.0.3
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLSRV Forge Class
*
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_sqlsrv_forge extends CI_DB_forge {
/**
- * Create database
+ * CREATE TABLE IF statement
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var string
*/
- function _create_database($name)
- {
- return "CREATE DATABASE ".$name;
- }
-
- // --------------------------------------------------------------------
+ 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 database
+ * DROP TABLE IF statement
*
- * @access private
- * @param string the database name
- * @return bool
+ * @var string
*/
- function _drop_database($name)
- {
- return "DROP DATABASE ".$name;
- }
-
- // --------------------------------------------------------------------
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
/**
- * Drop Table
+ * UNSIGNED support
*
- * @access private
- * @return bool
+ * @var array
*/
- function _drop_table($table)
- {
- return "IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '"
- .$table."')) DROP TABLE [dbo].[".$table."]";
- }
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @access private
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param boolean 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[]
*/
- function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = '';
- if ($if_not_exists === TRUE)
- {
- $sql = "IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = ";
- }
- $sql .= $this->db->_escape_identifiers($table).")) 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->_protect_identifiers($field);
-
- $sql .= ' '.$attributes['TYPE'];
-
- if (array_key_exists('CONSTRAINT', $attributes))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (array_key_exists('DEFAULT', $attributes))
- {
- $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
- }
-
- if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
- {
- $sql .= ' NULL';
- }
- else
- {
- $sql .= ' NOT NULL';
- }
-
- if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' IDENTITY(1,1)';
- }
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
-
- if (count($primary_keys) > 0)
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
{
- $primary_keys = $this->db->_protect_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (" . implode(', ', $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)
- {
- if (is_array($key))
- {
- $key = $this->db->_protect_identifiers($key);
- }
- else
- {
- $key = array($this->db->_protect_identifiers($key));
- }
-
- $sql .= ",\n\tFOREIGN KEY (" . implode(', ', $key) . ")";
- }
+ $sqls[] = $sql.$this->_process_column($field[$i]);
}
- $sql .= "\n)";
-
- return $sql;
+ 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.
*
- * @access private
- * @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 boolean should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return object
+ * @param array &$attributes
+ * @return void
*/
- 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->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type == 'DROP')
- {
- return $sql;
- }
-
- $sql .= " $column_definition";
-
- if ($default_value != '')
- {
- $sql .= " DEFAULT \"$default_value\"";
- }
-
- if ($null === NULL)
- {
- $sql .= ' NULL';
- }
- else
+ if (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE)
{
- $sql .= ' NOT NULL';
+ unset($attributes['CONSTRAINT']);
}
- if ($after_field != '')
+ switch (strtoupper($attributes['TYPE']))
{
- $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
}
-
- return $sql;
-
}
// --------------------------------------------------------------------
/**
- * Rename a table
- *
- * Generates a platform-specific query so that a table can be renamed
+ * Field attribute AUTO_INCREMENT
*
- * @access private
- * @param string the old table name
- * @param string the new table name
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- function _rename_table($table_name, $new_table_name)
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- return 'EXEC sp_rename '.$this->db->_protect_identifiers($table_name).", ".$this->db->_protect_identifiers($new_table_name);
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' IDENTITY(1,1)';
+ }
}
}
-
-/* End of file sqlsrv_forge.php */
-/* Location: ./system/database/drivers/sqlsrv/sqlsrv_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/sqlsrv/sqlsrv_result.php b/system/database/drivers/sqlsrv/sqlsrv_result.php
index a5c972669..f784ebea8 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_result.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_result.php
@@ -1,19 +1,41 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 2.0.3
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLSRV Result Class
@@ -21,20 +43,51 @@
* This class extends the parent result class: CI_DB_result
*
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_sqlsrv_result extends CI_DB_result {
/**
+ * Scrollable flag
+ *
+ * @var mixed
+ */
+ public $scrollable;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Constructor
+ *
+ * @param object $driver_object
+ * @return void
+ */
+ public function __construct(&$driver_object)
+ {
+ parent::__construct($driver_object);
+
+ $this->scrollable = $driver_object->scrollable;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Number of rows in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_rows()
+ public function num_rows()
{
- return @sqlsrv_num_rows($this->result_id);
+ // sqlsrv_num_rows() doesn't work with the FORWARD and DYNAMIC cursors (FALSE is the same as FORWARD)
+ if ( ! in_array($this->scrollable, array(FALSE, SQLSRV_CURSOR_FORWARD, SQLSRV_CURSOR_DYNAMIC), TRUE))
+ {
+ return parent::num_rows();
+ }
+
+ return is_int($this->num_rows)
+ ? $this->num_rows
+ : $this->num_rows = sqlsrv_num_rows($this->result_id);
}
// --------------------------------------------------------------------
@@ -42,10 +95,9 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
/**
* Number of fields in the result set
*
- * @access public
- * @return integer
+ * @return int
*/
- function num_fields()
+ public function num_fields()
{
return @sqlsrv_num_fields($this->result_id);
}
@@ -57,17 +109,16 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
*
* Generates an array of column names
*
- * @access public
* @return array
*/
- function list_fields()
+ public function list_fields()
{
$field_names = array();
- foreach(sqlsrv_field_metadata($this->result_id) as $offset => $field)
+ foreach (sqlsrv_field_metadata($this->result_id) as $offset => $field)
{
$field_names[] = $field['Name'];
}
-
+
return $field_names;
}
@@ -78,24 +129,19 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
*
* Generates an array of objects containing field meta-data
*
- * @access public
* @return array
*/
- function field_data()
+ 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;
}
@@ -104,9 +150,9 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
/**
* Free the result
*
- * @return null
+ * @return void
*/
- function free_result()
+ public function free_result()
{
if (is_resource($this->result_id))
{
@@ -118,31 +164,13 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
// --------------------------------------------------------------------
/**
- * 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
- *
- * @access private
- * @return array
- */
- function _data_seek($n = 0)
- {
- // Not implemented
- }
-
- // --------------------------------------------------------------------
-
- /**
* Result - associative array
*
* Returns the result set as an array
*
- * @access private
* @return array
*/
- function _fetch_assoc()
+ protected function _fetch_assoc()
{
return sqlsrv_fetch_array($this->result_id, SQLSRV_FETCH_ASSOC);
}
@@ -154,16 +182,12 @@ class CI_DB_sqlsrv_result extends CI_DB_result {
*
* Returns the result set as an object
*
- * @access private
+ * @param string $class_name
* @return object
*/
- function _fetch_object()
+ protected function _fetch_object($class_name = 'stdClass')
{
- return sqlsrv_fetch_object($this->result_id);
+ return sqlsrv_fetch_object($this->result_id, $class_name);
}
}
-
-
-/* End of file mssql_result.php */
-/* Location: ./system/database/drivers/mssql/mssql_result.php */ \ No newline at end of file
diff --git a/system/database/drivers/sqlsrv/sqlsrv_utility.php b/system/database/drivers/sqlsrv/sqlsrv_utility.php
index 0004bfdd2..19c93d0c6 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_utility.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_utility.php
@@ -1,88 +1,77 @@
-<?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
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 2.0.3
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* SQLSRV Utility Class
*
* @category Database
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/database/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/database/
*/
class CI_DB_sqlsrv_utility extends CI_DB_utility {
/**
- * List databases
+ * List databases statement
*
- * @access private
- * @return bool
+ * @var string
*/
- function _list_databases()
- {
- return "EXEC sp_helpdb"; // Can also be: EXEC sp_databases
- }
-
- // --------------------------------------------------------------------
+ protected $_list_databases = 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases
/**
- * Optimize table query
- *
- * Generates a platform-specific query so that a table can be optimized
+ * OPTIMIZE TABLE statement
*
- * @access private
- * @param string the table name
- * @return object
+ * @var string
*/
- function _optimize_table($table)
- {
- return FALSE; // Is this supported in MS SQL?
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Repair table query
- *
- * Generates a platform-specific query so that a table can be repaired
- *
- * @access private
- * @param string the table name
- * @return object
- */
- function _repair_table($table)
- {
- return FALSE; // Is this supported in MS SQL?
- }
+ protected $_optimize_table = 'ALTER INDEX all ON %s REORGANIZE';
// --------------------------------------------------------------------
/**
- * MSSQL Export
+ * Export
*
- * @access private
- * @param array Preferences
- * @return mixed
+ * @param array $params Preferences
+ * @return bool
*/
- function _backup($params = array())
+ protected function _backup($params = array())
{
// Currently unsupported
- return $this->db->display_error('db_unsuported_feature');
+ return $this->db->display_error('db_unsupported_feature');
}
}
-
-/* End of file mssql_utility.php */
-/* Location: ./system/database/drivers/mssql/mssql_utility.php */ \ No newline at end of file