summaryrefslogtreecommitdiffstats
path: root/system/database/drivers
diff options
context:
space:
mode:
authorAndrey Andreev <narf@bofh.bg>2012-11-05 22:19:59 +0100
committerAndrey Andreev <narf@bofh.bg>2012-11-05 22:19:59 +0100
commita287a34c215903d3452023d74149eb5880125715 (patch)
tree92af334c0797e8c3112ce5d05cb6be741dda658c /system/database/drivers
parent2b73037e450859e85fb468ad7499a26882a67292 (diff)
Refactored DB Forge
- PDO subdrivers are isolated from each other now. - Added compatibility for pretty much all of the features, for every DB platform. - Unified the way that stuff works in general. - Fixes issue #1005.
Diffstat (limited to 'system/database/drivers')
-rw-r--r--system/database/drivers/cubrid/cubrid_forge.php214
-rw-r--r--system/database/drivers/ibase/ibase_forge.php204
-rw-r--r--system/database/drivers/mssql/mssql_forge.php160
-rw-r--r--system/database/drivers/mysql/mysql_forge.php207
-rw-r--r--system/database/drivers/mysqli/mysqli_forge.php207
-rw-r--r--system/database/drivers/oci8/oci8_forge.php131
-rw-r--r--system/database/drivers/odbc/odbc_forge.php126
-rw-r--r--system/database/drivers/pdo/pdo_forge.php131
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_4d_forge.php209
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php173
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php136
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php228
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php146
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_informix_forge.php155
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php198
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_oci_forge.php133
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php62
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php193
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php228
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php136
-rw-r--r--system/database/drivers/postgre/postgre_forge.php245
-rw-r--r--system/database/drivers/sqlite/sqlite_forge.php192
-rw-r--r--system/database/drivers/sqlite3/sqlite3_forge.php201
-rw-r--r--system/database/drivers/sqlsrv/sqlsrv_forge.php160
24 files changed, 2869 insertions, 1306 deletions
diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php
index 33d502137..e3f8bc334 100644
--- a/system/database/drivers/cubrid/cubrid_forge.php
+++ b/system/database/drivers/cubrid/cubrid_forge.php
@@ -42,8 +42,6 @@ class CI_DB_cubrid_forge extends CI_DB_forge {
*/
protected $_create_database = FALSE;
- // --------------------------------------------------------------------
-
/**
* DROP DATABASE statement
*
@@ -52,177 +50,121 @@ class CI_DB_cubrid_forge extends CI_DB_forge {
protected $_drop_database = FALSE;
/**
- * Process Fields
+ * CREATE TABLE IF statement
*
- * @param mixed $fields
- * @return string
+ * @var string
+ */
+ protected $_create_table_if = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
*/
- protected function _process_fields($fields)
+ 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)
{
- $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->escape_identifiers($field);
-
- empty($attributes['NAME']) OR $sql .= ' '.$this->db->escape_identifiers($attributes['NAME']).' ';
-
- if ( ! empty($attributes['TYPE']))
- {
- $sql .= ' '.$attributes['TYPE'];
-
- if ( ! empty($attributes['CONSTRAINT']))
- {
- switch (strtolower($attributes['TYPE']))
- {
- case 'decimal':
- case 'float':
- case 'numeric':
- $sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
- break;
- case 'enum':
- // Will be supported in the future as part a part of
- // MySQL compatibility features.
- break;
- case 'set':
- $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
- break;
- default:
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
- }
-
- /* As of version 8.4.1 CUBRID does not support UNSIGNED INTEGER data type.
- * Will be supported in the next release as a part of MySQL Compatibility.
- *
- if (isset($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
- */
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
-
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
-
- if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ $sqls[] = $sql.' CHANGE '.$this->_process_column($field[$i]);
+ if ( ! empty($field[$i]['new_name']))
{
- $sql .= ' UNIQUE';
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' AS '.$this->db->escape_identifiers($field[$i]['name']);
}
}
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
}
- return $sql;
+ return $sqls;
}
// --------------------------------------------------------------------
/**
- * Create Table
+ * Field attribute TYPE
*
- * @param string the table name
- * @param mixed the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _attr_type(&$attributes)
{
- $sql = 'CREATE TABLE ';
-
- /* As of version 8.4.1 CUBRID does not support this SQL syntax.
- if ($if_not_exists === TRUE)
+ switch (strtoupper($attributes['TYPE']))
{
- $sql .= 'IF NOT EXISTS ';
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
}
- */
-
- $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields);
-
- // If there is a PK defined
- if (count($primary_keys) > 0)
- {
- $key_name = $this->db->escape_identifiers('pk_'.$table.'_'.implode('_', $primary_keys));
- $sql .= ",\n\tCONSTRAINT ".$key_name.' PRIMARY KEY('.implode(', ', $this->db->escape_identifiers($primary_keys)).')';
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- if (is_array($key))
- {
- $key_name = $this->db->escape_identifiers('idx_'.$table.implode('_', $key));
- $key = $this->db->escape_identifiers($key);
- }
- else
- {
- $key_name = $this->db->escape_identifiers('idx_'.$table.$key);
- $key = array($key_name);
- }
-
- $sql .= ",\n\tKEY ".$key_name.' ('.implode(', ', $key).')';
- }
- }
-
- return $sql."\n);";
}
// --------------------------------------------------------------------
/**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Process indexes
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param array fields
- * @param string the field after which we should add the new field
+ * @param string $table (ignored)
* @return string
*/
- protected function _alter_table($alter_type, $table, $fields, $after_field = '')
+ protected function _process_indexes($table = NULL)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' ';
+ $sql = '';
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- return $sql.$this->db->escape_identifiers($fields);
+ if ( ! isset($this->fields[$this->keys[$i]]))
+ {
+ unset($this->keys[$i]);
+ continue;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
- return $sql.$this->_process_fields($fields)
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ $this->keys = array();
+
+ return $sql;
}
}
diff --git a/system/database/drivers/ibase/ibase_forge.php b/system/database/drivers/ibase/ibase_forge.php
index 7c4d00a23..a0c4e6563 100644
--- a/system/database/drivers/ibase/ibase_forge.php
+++ b/system/database/drivers/ibase/ibase_forge.php
@@ -36,11 +36,43 @@ defined('BASEPATH') OR exit('No direct script access allowed');
class CI_DB_ibase_forge extends CI_DB_forge {
/**
- * DROP TABLE statement
+ * CREATE TABLE IF statement
*
* @var string
*/
- protected $_drop_table = 'DROP TABLE %s';
+ 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';
// --------------------------------------------------------------------
@@ -65,8 +97,7 @@ class CI_DB_ibase_forge extends CI_DB_forge {
/**
* Drop database
*
- * @param string the database name
- * - not used in this driver, the current db is dropped
+ * @param string $db_name (ignored)
* @return bool
*/
public function drop_database($db_name = '')
@@ -90,110 +121,119 @@ class CI_DB_ibase_forge extends CI_DB_forge {
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return string
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
-
- $sql .= $this->db->escape_identifiers($table).'(';
- $current_field_count = 0;
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
- foreach ($fields as $field => $attributes)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field), $sql .= $alter_type.' '; $i < $c; $i++)
{
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
+ if ($field[$i]['_literal'] !== FALSE)
{
- $sql .= "\n\t".$attributes;
+ return FALSE;
}
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- empty($attributes['CONSTRAINT']) OR $sql .= '('.$attributes['CONSTRAINT'].')';
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
-
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
+ if (isset($field[$i]['type']))
+ {
+ $sqls[] = $sql.' 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 '.$this->db->escape_identifiers($field[$i]['name'])
+ .' SET '.$field[$i]['default'];
}
- }
- if (count($primary_keys) > 0)
- {
- $primary_keys = $this->db->escape_identifiers($primary_keys);
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $primary_keys).')';
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
+ if (isset($field[$i]['null']))
{
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
+ $sqls[] = 'UPDATE "RDB$RELATION_FIELDS" SET "RDB$NULL_FLAG" = '
+ .($field[$i]['null'] === TRUE ? 'NULL' : '1')
+ .' WHERE "RDB$FIELD_NAME" = '.$this->db->escape($field[$i]['name'])
+ .' AND "RDB$RELATION_NAME" = '.$this->db->escape($table);
+ }
- $sql .= ",\n\tUNIQUE (".implode(', ', $key).')';
+ if ( ! empty($field[$i]['new_name']))
+ {
+ $sqls[] = $sql.' ALTER '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
}
}
- return $sql."\n)";
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type'].$field['length']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute TYPE
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Performs a data type mapping between different databases.
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INT':
+ $attributes['TYPE'] = 'INTEGER';
+ return;
+ case 'BIGINT':
+ $attributes['TYPE'] = 'INT64';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- return 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name)
- .' '.$column_definition
- .($default_value !== '' ? ' DEFAULT "'.$default_value.'"' : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ // Not supported
}
}
diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php
index 1eef648b0..5eebedbf7 100644
--- a/system/database/drivers/mssql/mssql_forge.php
+++ b/system/database/drivers/mssql/mssql_forge.php
@@ -36,130 +36,98 @@ defined('BASEPATH') OR exit('No direct script access allowed');
class CI_DB_mssql_forge extends CI_DB_forge {
/**
- * DROP TABLE statement
+ * CREATE TABLE IF statement
*
* @var string
*/
- protected $_drop_table = 'DROP TABLE %s';
-
- // --------------------------------------------------------------------
+ protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
/**
- * Create Table
+ * DROP TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return string
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = ($if_not_exists === TRUE)
- ? "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'".$table."') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\n"
- : '';
-
- $sql .= 'CREATE TABLE '.$this->db->escape_identifiers($table).' (';
-
- $current_field_count = 0;
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
- if (stripos($attributes['TYPE'], 'INT') === FALSE && ! empty($attributes['CONSTRAINT']))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
-
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ // --------------------------------------------------------------------
- if (count($primary_keys) > 0)
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
{
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')';
+ return parent::_alter_table($alter_type, $table, $field);
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')';
- }
+ $sqls[] = $sql.$this->_process_column($field[$i]);
}
- return $sql."\n)";
+ return $sqls;
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute TYPE
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Performs a data type mapping between different databases.
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_type(&$attributes)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
+ switch (strtoupper($attributes['TYPE']))
{
- return $sql;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
}
+ }
- return $sql.' '.$column_definition
- .($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field != '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' IDENTITY(1,1)';
+ }
}
}
diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php
index 7ce4e8b00..ea3207760 100644
--- a/system/database/drivers/mysql/mysql_forge.php
+++ b/system/database/drivers/mysql/mysql_forge.php
@@ -42,165 +42,140 @@ class CI_DB_mysql_forge extends CI_DB_forge {
*/
protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';
- // --------------------------------------------------------------------
-
/**
- * Process Fields
+ * UNSIGNED support
*
- * @param mixed $fields
- * @return string
+ * @var array
*/
- protected function _process_fields($fields)
- {
- $current_field_count = 0;
- $sql = '';
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field);
-
- empty($attributes['NAME']) OR $sql .= ' '.$this->db->escape_identifiers($attributes['NAME']).' ';
-
- if ( ! empty($attributes['TYPE']))
- {
- $sql .= ' '.$attributes['TYPE'];
-
- if ( ! empty($attributes['CONSTRAINT']))
- {
- switch (strtolower($attributes['TYPE']))
- {
- case 'decimal':
- case 'float':
- case 'numeric':
- $sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
- break;
- case 'enum':
- case 'set':
- $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
- break;
- default:
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
- }
+ protected $_unsigned = array(
+ 'TINYINT',
+ 'SMALLINT',
+ 'MEDIUMINT',
+ 'INT',
+ 'INTEGER',
+ 'BIGINT',
+ 'REAL',
+ 'DOUBLE',
+ 'DOUBLE PRECISION',
+ 'FLOAT',
+ 'DECIMAL',
+ 'NUMERIC'
+ );
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ // --------------------------------------------------------------------
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
- return $sql;
+ $this->_create_table .= ' DEFAULT CHARSET '.$this->db->char_set.' COLLATE '.$this->db->dbcollat;
}
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param mixed the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields);
-
- if (count($primary_keys) > 0)
+ if ($alter_type === 'DROP')
{
- $key_name = $this->db->escape_identifiers(implode('_', $primary_keys));
- $sql .= ",\n\tPRIMARY KEY ".$key_name.' ('.implode(', ', $this->db->escape_identifiers($primary_keys)).')';
+ return parent::_alter_table($alter_type, $table, $field);
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
+ if ($field[$i]['_literal'] !== FALSE)
{
- if (is_array($key))
+ $field[$i] = ($alter_type === 'ADD')
+ ? "\n\tADD ".$field[$i]['_literal']
+ : "\n\tMODIFY ".$field[$i]['_literal'];
+ }
+ else
+ {
+ if ($alter_type === 'ADD')
{
- $key_name = $this->db->escape_identifiers(implode('_', $key));
- $key = $this->db->escape_identifiers($key);
+ $field[$i]['_literal'] = "\n\tADD ";
}
else
{
- $key_name = $this->db->escape_identifiers($key);
- $key = array($key_name);
+ $field[$i]['_literal'] = empty($field['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE ";
}
- $sql .= ",\n\tKEY ".$key_name.' ('.implode(', ', $key).')';
+ $field[$i] = $field['_literal'].$this->_process_column($field[$i]);
}
}
- return $sql."\n) DEFAULT CHARACTER SET ".$this->db->char_set.' COLLATE '.$this->db->dbcollat.';';
+ return array($sql.implode(',', $field));
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Process column
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column() and column_alter()
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ 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'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param array fields
- * @param string the field after which we should add the new field
+ * @param string $table (ignored)
* @return string
*/
- protected function _alter_table($alter_type, $table, $fields, $after_field = '')
+ protected function _process_indexes($table = NULL)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' ';
+ $sql = '';
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- return $sql.$this->db->escape_identifiers($fields);
+ if ( ! isset($this->fields[$this->keys[$i]]))
+ {
+ unset($this->keys[$i]);
+ continue;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
- return $sql.$this->_process_fields($fields)
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ $this->keys = array();
+
+ return $sql;
}
}
diff --git a/system/database/drivers/mysqli/mysqli_forge.php b/system/database/drivers/mysqli/mysqli_forge.php
index 0732dfea5..914d6a268 100644
--- a/system/database/drivers/mysqli/mysqli_forge.php
+++ b/system/database/drivers/mysqli/mysqli_forge.php
@@ -42,165 +42,140 @@ class CI_DB_mysqli_forge extends CI_DB_forge {
*/
protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';
- // --------------------------------------------------------------------
-
/**
- * Process Fields
+ * UNSIGNED support
*
- * @param mixed $fields
- * @return string
+ * @var array
*/
- protected function _process_fields($fields)
- {
- $current_field_count = 0;
- $sql = '';
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field);
-
- empty($attributes['NAME']) OR $sql .= ' '.$this->db->escape_identifiers($attributes['NAME']).' ';
-
- if ( ! empty($attributes['TYPE']))
- {
- $sql .= ' '.$attributes['TYPE'];
-
- if ( ! empty($attributes['CONSTRAINT']))
- {
- switch (strtolower($attributes['TYPE']))
- {
- case 'decimal':
- case 'float':
- case 'numeric':
- $sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
- break;
- case 'enum':
- case 'set':
- $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
- break;
- default:
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
- }
+ protected $_unsigned = array(
+ 'TINYINT',
+ 'SMALLINT',
+ 'MEDIUMINT',
+ 'INT',
+ 'INTEGER',
+ 'BIGINT',
+ 'REAL',
+ 'DOUBLE',
+ 'DOUBLE PRECISION',
+ 'FLOAT',
+ 'DECIMAL',
+ 'NUMERIC'
+ );
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ // --------------------------------------------------------------------
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
- return $sql;
+ $this->_create_table .= ' DEFAULT CHARSET '.$this->db->char_set.' COLLATE '.$this->db->dbcollat;
}
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param mixed the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields);
-
- if (count($primary_keys) > 0)
+ if ($alter_type === 'DROP')
{
- $key_name = $this->db->escape_identifiers(implode('_', $primary_keys));
- $sql .= ",\n\tPRIMARY KEY ".$key_name.' ('.implode(', ', $this->db->escape_identifiers($primary_keys)).')';
+ return parent::_alter_table($alter_type, $table, $field);
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
+ if ($field[$i]['_literal'] !== FALSE)
{
- if (is_array($key))
+ $field[$i] = ($alter_type === 'ADD')
+ ? "\n\tADD ".$field[$i]['_literal']
+ : "\n\tMODIFY ".$field[$i]['_literal'];
+ }
+ else
+ {
+ if ($alter_type === 'ADD')
{
- $key_name = $this->db->escape_identifiers(implode('_', $key));
- $key = $this->db->escape_identifiers($key);
+ $field[$i]['_literal'] = "\n\tADD ";
}
else
{
- $key_name = $this->db->escape_identifiers($key);
- $key = array($key_name);
+ $field[$i]['_literal'] = empty($field['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE ";
}
- $sql .= ",\n\tKEY ".$key_name.' ('.implode(', ', $key).')';
+ $field[$i] = $field['_literal'].$this->_process_column($field[$i]);
}
}
- return $sql."\n) DEFAULT CHARACTER SET ".$this->db->char_set.' COLLATE '.$this->db->dbcollat.';';
+ return array($sql.implode(',', $field));
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Process column
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ 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'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param array fields
- * @param string the field after which we should add the new field
+ * @param string $table (ignored)
* @return string
*/
- protected function _alter_table($alter_type, $table, $fields, $after_field = '')
+ protected function _process_indexes($table = NULL)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' ';
+ $sql = '';
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
{
- return $sql.$this->db->escape_identifiers($fields);
+ if ( ! isset($this->fields[$this->keys[$i]]))
+ {
+ unset($this->keys[$i]);
+ continue;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
}
- return $sql.$this->_process_fields($fields)
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ $this->keys = array();
+
+ return $sql;
}
}
diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php
index ad578f830..bd9d2df3c 100644
--- a/system/database/drivers/oci8/oci8_forge.php
+++ b/system/database/drivers/oci8/oci8_forge.php
@@ -50,126 +50,81 @@ class CI_DB_oci8_forge extends CI_DB_forge {
protected $_drop_database = FALSE;
/**
- * DROP TABLE statement
+ * DROP TABLE IF statement
*
* @var string
*/
- protected $_drop_table = 'DROP TABLE %s';
+ protected $_drop_table_if = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return string
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ 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->escape_identifiers($field).' '.$attributes['TYPE'];
-
- if (isset($attributes['UNSINGED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
+ $field[$i]['_literal'] = "\n\t".$this->_process_column($field[$i]);
+ if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name']))
{
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' '.$this->db->escape_identifiers($field[$i]['new_name']);
}
-
- $sql .= (isset($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? '' : ' NOT NULL';
-
- empty($attributes['CONSTRAINT']) OR ' CONSTRAINT '.$attributes['CONSTRAINT'];
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
}
}
- if (count($primary_keys) > 0)
- {
- $sql .= ",\n\tCONSTRAINT ".$table.' PRIMARY KEY ('.implode(', ', $this->db->escape_identifiers($primary_keys)).')';
- }
+ $sql .= ' '.$alter_type.' ';
+ $sql .= (count($field) === 1)
+ ? $fields[0]
+ : '('.implode(',', $field).')';
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- $sql .= ",\n\tUNIQUE COLUMNS (".implode(', ', $key).')';
- }
- }
-
- return $sql."\n)";
+ // RENAME COLUMN must be executed after MODIFY
+ array_unshift($sqls, $sql);
+ return $sql;
}
// --------------------------------------------------------------------
/**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Field attribute AUTO_INCREMENT
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
- {
- return $sql;
- }
-
- return $sql.' '.$column_definition
- .($default_value !== '' ? ' DEFAULT "'.$default_value.'"' : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
-
+ // Not supported - sequences and triggers must be used instead
}
}
diff --git a/system/database/drivers/odbc/odbc_forge.php b/system/database/drivers/odbc/odbc_forge.php
index 699ce996c..fb16ca5cf 100644
--- a/system/database/drivers/odbc/odbc_forge.php
+++ b/system/database/drivers/odbc/odbc_forge.php
@@ -36,130 +36,38 @@ defined('BASEPATH') OR exit('No direct script access allowed');
class CI_DB_odbc_forge extends CI_DB_forge {
/**
- * DROP TABLE statement
+ * CREATE TABLE IF statement
*
* @var string
*/
- protected $_drop_table = 'DROP TABLE %s';
-
- // --------------------------------------------------------------------
+ protected $_create_table_if = FALSE;
/**
- * Create Table
+ * DROP TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- empty($attributes['CONSTRAINT']) OR $sql .= '('.$attributes['CONSTRAINT'].')';
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
+ protected $_drop_table_if = FALSE;
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
-
- if (count($primary_keys) > 0)
- {
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->escape_identifiers($primary_keys)).')';
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')';
- }
- }
-
- return $sql."\n)";
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute AUTO_INCREMENT
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
- *
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
- {
- return $sql;
- }
-
- return $sql.' '.$column_definition
- .($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field != '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ // Not supported (in most databases at least)
}
}
diff --git a/system/database/drivers/pdo/pdo_forge.php b/system/database/drivers/pdo/pdo_forge.php
index e77970cf2..130d3667e 100644
--- a/system/database/drivers/pdo/pdo_forge.php
+++ b/system/database/drivers/pdo/pdo_forge.php
@@ -36,139 +36,18 @@ defined('BASEPATH') OR exit('No direct script access allowed');
class CI_DB_pdo_forge extends CI_DB_forge {
/**
- * DROP TABLE statement
+ * CREATE TABLE IF statement
*
* @var string
*/
- protected $_drop_table = 'DROP TABLE %s';
-
- // --------------------------------------------------------------------
-
- /**
- * Create Table
- *
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
- */
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = 'CREATE TABLE ';
-
- if ($if_not_exists === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
- $numeric = array('SERIAL', 'INTEGER');
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- if ( ! empty($attributes['CONSTRAINT']))
- {
- // Exception for Postgre numeric which not too happy with constraint within those type
- if ( ! ($this->db->subdriver === 'pgsql' && in_array($attributes['TYPE'], $numeric)))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
- }
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
-
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
-
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
-
- if (count($primary_keys) > 0)
- {
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')';
- }
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')';
- }
- }
-
- return $sql."\n)";
- }
-
- // --------------------------------------------------------------------
+ protected $_create_table_if = FALSE;
/**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * DROP TABLE IF statement
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @var string
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
- {
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
- {
- return $sql;
- }
-
- return $sql .' '.$column_definition
- .($default_value !== '' ? " DEFAULT '".$default_value."'" : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
- }
+ protected $_drop_table_if = FALSE;
}
diff --git a/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php b/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php
new file mode 100644
index 000000000..231ad53a4
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php
@@ -0,0 +1,209 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO 4D Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_4d_forge extends CI_DB_4d_forge {
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
+ protected $_create_database = 'CREATE SCHEMA %s';
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
+ protected $_drop_database = 'DROP SCHEMA %s';
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * RENAME TABLE statement
+ *
+ * @var string
+ */
+ protected $_rename_table = FALSE;
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'INT16' => 'INT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'INT64',
+ 'INT32' => 'INT64'
+ );
+
+ /**
+ * DEFAULT value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_default = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
+ {
+ return parent::_alter_table($alter_table, $table, $field);
+ }
+
+ // No method of modifying columns is supported
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type'].$field['length']
+ .$field['null']
+ .$field['unique']
+ .$field['auto_increment'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ case 'BIGINT':
+ $attribites['TYPE'] = 'INT64';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute UNIQUE
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_unique(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ {
+ $field['unique'] = ' UNIQUE';
+
+ // UNIQUE must be used with NOT NULL
+ $field['null'] = ' NOT NULL';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
+ {
+ if (stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' AUTO_INCREMENT';
+ }
+ elseif (strcasecmp($field['type'], 'UUID') === 0)
+ {
+ $field['auto_increment'] = ' AUTO_GENERATE';
+ }
+ }
+ }
+
+}
+
+/* End of file pdo_4d_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_4d_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php
new file mode 100644
index 000000000..c01a0fb81
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php
@@ -0,0 +1,173 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO CUBRID Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_cubrid_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
+ protected $_create_database = FALSE;
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
+ protected $_drop_database = FALSE;
+
+ /**
+ * 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
+ {
+ $sqls[] = $sql.' CHANGE '.$this->_process_column($field[$i]);
+ if ( ! empty($field[$i]['new_name']))
+ {
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' AS '.$this->db->escape_identifiers($field[$i]['name']);
+ }
+ }
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
+ *
+ * @param string $table (ignored)
+ * @return string
+ */
+ protected function _process_indexes($table = NULL)
+ {
+ $sql = '';
+
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i]]))
+ {
+ unset($this->keys[$i]);
+ continue;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
+ }
+
+ $this->keys = array();
+
+ return $sql;
+ }
+
+}
+
+/* End of file pdo_cubrid_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php
new file mode 100644
index 000000000..fb33127fd
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php
@@ -0,0 +1,136 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO DBLIB Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_dblib_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ $sqls[] = $sql.$this->_process_column($field[$i]);
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' IDENTITY(1,1)';
+ }
+ }
+
+}
+
+/* End of file pdo_dblib_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php
new file mode 100644
index 000000000..88c53510a
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php
@@ -0,0 +1,228 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Firebird Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_firebird_forge extends CI_DB_pdo_forge {
+
+ /**
+ * RENAME TABLE statement
+ *
+ * @var string
+ */
+ protected $_rename_table = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SMALLINT' => 'INTEGER',
+ 'INTEGER' => 'INT64',
+ 'FLOAT' => 'DOUBLE PRECISION'
+ );
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create database
+ *
+ * @param string $db_name
+ * @return string
+ */
+ public function create_database($db_name)
+ {
+ // Firebird databases are flat files, so a path is required
+
+ // Hostname is needed for remote access
+ empty($this->db->hostname) OR $db_name = $this->hostname.':'.$db_name;
+
+ return parent::create_database('"'.$db_name.'"');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Drop database
+ *
+ * @param string $db_name (ignored)
+ * @return bool
+ */
+ public function drop_database($db_name = '')
+ {
+ if ( ! ibase_drop_db($this->conn_id))
+ {
+ return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;
+ }
+ elseif ( ! empty($this->db->data_cache['db_names']))
+ {
+ $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
+ if ($key !== FALSE)
+ {
+ unset($this->db->data_cache['db_names'][$key]);
+ }
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field), $sql .= $alter_type.' '; $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ return FALSE;
+ }
+
+ if (isset($field[$i]['type']))
+ {
+ $sqls[] = $sql.' TYPE '.$field[$i]['type'].$field[$i]['length'];
+ }
+
+ if ( ! empty($field[$i]['default']))
+ {
+ $sqls[] = $sql.' ALTER '.$this->db->escape_identifiers($field[$i]['name'])
+ .' SET '.$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 '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
+ }
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type'].$field['length']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INT':
+ $attributes['TYPE'] = 'INTEGER';
+ return;
+ case 'BIGINT':
+ $attributes['TYPE'] = 'INT64';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported
+ }
+
+}
+
+/* End of file pdo_firebird_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php b/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php
new file mode 100644
index 000000000..6a2c9b87e
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php
@@ -0,0 +1,146 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO IBM DB2 Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_ibm_forge extends CI_DB_pdo_forge {
+
+ /**
+ * RENAME TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_rename_table = 'RENAME TABLE %s TO %s';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INTEGER' => 'BIGINT'
+ );
+
+ /**
+ * DEFAULT value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_default = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'CHANGE')
+ {
+ $alter_type = 'MODIFY';
+ }
+
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute UNIQUE
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_unique(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ {
+ $field['unique'] = ' UNIQUE';
+
+ // UNIQUE must be used with NOT NULL
+ $field['null'] = ' NOT NULL';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported
+ }
+
+}
+
+/* End of file pdo_ibm_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php b/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php
new file mode 100644
index 000000000..715a7cbba
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php
@@ -0,0 +1,155 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Informix Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_informix_forge extends CI_DB_pdo_forge {
+
+ /**
+ * RENAME TABLE statement
+ *
+ * @var string
+ */
+ protected $_rename_table = 'RENAME TABLE %s TO %s';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'REAL' => 'DOUBLE PRECISION',
+ 'SMALLFLOAT' => 'DOUBLE PRECISION'
+ );
+
+ /**
+ * DEFAULT value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_default = ', ';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'CHANGE')
+ {
+ $alter_type = 'MODIFY';
+ }
+
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'BYTE':
+ case 'TEXT':
+ case 'BLOB':
+ case 'CLOB':
+ $attributes['UNIQUE'] = FALSE;
+ if (isset($attributes['DEFAULT']))
+ {
+ unset($attributes['DEFAULT']);
+ }
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute UNIQUE
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_unique(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
+ {
+ $field['unique'] = ' UNIQUE CONSTRAINT '.$this->db->escape_identifiers($field['name']);
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported
+ }
+
+}
+
+/* End of file pdo_informix_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_informix_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php
new file mode 100644
index 000000000..dc856ed2c
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php
@@ -0,0 +1,198 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO MySQL Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_mysql_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
+ protected $_create_database = 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT',
+ 'SMALLINT',
+ 'MEDIUMINT',
+ 'INT',
+ 'INTEGER',
+ 'BIGINT',
+ 'REAL',
+ 'DOUBLE',
+ 'DOUBLE PRECISION',
+ 'FLOAT',
+ 'DECIMAL',
+ 'NUMERIC'
+ );
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ $this->_create_table .= ' DEFAULT CHARSET '.$this->db->char_set.' COLLATE '.$this->db->dbcollat;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'DROP')
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ $field[$i] = ($alter_type === 'ADD')
+ ? "\n\tADD ".$field[$i]['_literal']
+ : "\n\tMODIFY ".$field[$i]['_literal'];
+ }
+ else
+ {
+ if ($alter_type === 'ADD')
+ {
+ $field[$i]['_literal'] = "\n\tADD ";
+ }
+ else
+ {
+ $field[$i]['_literal'] = empty($field['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE ";
+ }
+
+ $field[$i] = $field['_literal'].$this->_process_column($field[$i]);
+ }
+ }
+
+ return array($sql.implode(',', $field));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ 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'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process indexes
+ *
+ * @param string $table (ignored)
+ * @return string
+ */
+ protected function _process_indexes($table = NULL)
+ {
+ $sql = '';
+
+ for ($i = 0, $c = count($this->keys); $i < $c; $i++)
+ {
+ if ( ! isset($this->fields[$this->keys[$i]]))
+ {
+ unset($this->keys[$i]);
+ continue;
+ }
+
+ is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
+
+ $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';
+ }
+
+ $this->keys = array();
+
+ return $sql;
+ }
+
+}
+
+/* End of file pdo_mysql_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php
new file mode 100644
index 000000000..dbcb64d31
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php
@@ -0,0 +1,133 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO Oracle Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_oci_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE DATABASE statement
+ *
+ * @var string
+ */
+ protected $_create_database = FALSE;
+
+ /**
+ * DROP DATABASE statement
+ *
+ * @var string
+ */
+ protected $_drop_database = FALSE;
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'DROP')
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+ elseif ($alter_type === 'CHANGE')
+ {
+ $alter_type = 'MODIFY';
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ $field[$i] = "\n\t".$field[$i]['_literal'];
+ }
+ else
+ {
+ $field[$i]['_literal'] = "\n\t".$this->_process_column($field[$i]);
+ if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name']))
+ {
+ $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])
+ .' '.$this->db->escape_identifiers($field[$i]['new_name']);
+ }
+ }
+ }
+
+ $sql .= ' '.$alter_type.' ';
+ $sql .= (count($field) === 1)
+ ? $fields[0]
+ : '('.implode(',', $field).')';
+
+ // RENAME COLUMN must be executed after MODIFY
+ array_unshift($sqls, $sql);
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported - sequences and triggers must be used instead
+ }
+
+}
+
+/* End of file pdo_oci_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_oci_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php
new file mode 100644
index 000000000..cd6b19c68
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php
@@ -0,0 +1,62 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO ODBC Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/database/
+ */
+class CI_DB_pdo_odbc_forge extends CI_DB_pdo_forge {
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ // Not supported (in most databases at least)
+ }
+
+}
+
+/* End of file pdo_odbc_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php
new file mode 100644
index 000000000..b5235d24b
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php
@@ -0,0 +1,193 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO PostgreSQL Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_pgsql_forge extends CI_DB_pdo_forge {
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'INT2' => 'INTEGER',
+ 'SMALLINT' => 'INTEGER',
+ 'INT' => 'BIGINT',
+ 'INT4' => 'BIGINT',
+ 'INTEGER' => 'BIGINT',
+ 'INT8' => 'NUMERIC',
+ 'BIGINT' => 'NUMERIC',
+ 'REAL' => 'DOUBLE PRECISION',
+ 'FLOAT' => 'DOUBLE PRECISION'
+ );
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ 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), $sql .= $alter_type.' '; $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
+ {
+ return FALSE;
+ }
+
+ if (version_compare($this->db->version(), '8', '>=') && isset($field[$i]['type']))
+ {
+ $sqls[] = $sql.' TYPE '.$field[$i]['type'].$field[$i]['length'];
+ }
+
+ if ( ! empty($field[$i]['default']))
+ {
+ $sqls[] = $sql.' ALTER '.$this->db->escape_identifiers($field[$i]['name'])
+ .' SET '.$field[$i]['default'];
+ }
+
+ if (isset($field[$i]['null']))
+ {
+ $sqls[] = $sql.' ALTER '.$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 '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
+ }
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ // Reset field lenghts for data types that don't support it
+ if (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE)
+ {
+ $attributes['CONSTRAINT'] = NULL;
+ }
+
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
+ {
+ $field['type'] = ($field['type'] === 'NUMERIC')
+ ? 'BIGSERIAL'
+ : 'SERIAL';
+ }
+ }
+
+}
+
+/* End of file pdo_pgsql_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php b/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php
new file mode 100644
index 000000000..414826212
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php
@@ -0,0 +1,228 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO SQLite Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_sqlite_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = 'CREATE TABLE IF NOT EXISTS';
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = 'DROP TABLE IF EXISTS';
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Class constructor
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ if (version_compare($this->db->version(), '3.3', '<'))
+ {
+ $this->_create_table_if = FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create database
+ *
+ * @param string $db_name (ignored)
+ * @return bool
+ */
+ public function create_database($db_name = '')
+ {
+ // In SQLite, a database is created when you connect to the database.
+ // We'll return TRUE so that an error isn't generated
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Drop database
+ *
+ * @param string $db_name (ignored)
+ * @return bool
+ */
+ public function drop_database($db_name = '')
+ {
+ // In SQLite, a database is dropped when we delete a file
+ if (@file_exists($this->db->database))
+ {
+ // We need to close the pseudo-connection first
+ $this->db->close();
+ if ( ! @unlink($this->db->database))
+ {
+ return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;
+ }
+ elseif ( ! empty($this->db->data_cache['db_names']))
+ {
+ $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);
+ if ($key !== FALSE)
+ {
+ unset($this->db->data_cache['db_names'][$key]);
+ }
+ }
+
+ return TRUE;
+ }
+
+ return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if ($alter_type === 'DROP' OR $alter_type === 'CHANGE')
+ {
+ // drop_column():
+ // BEGIN TRANSACTION;
+ // CREATE TEMPORARY TABLE t1_backup(a,b);
+ // INSERT INTO t1_backup SELECT a,b FROM t1;
+ // DROP TABLE t1;
+ // CREATE TABLE t1(a,b);
+ // INSERT INTO t1 SELECT a,b FROM t1_backup;
+ // DROP TABLE t1_backup;
+ // COMMIT;
+
+ return FALSE;
+ }
+
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type']
+ .$field['auto_increment']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'ENUM':
+ case 'SET':
+ $attributes['TYPE'] = 'TEXT';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['type'] = 'INTEGER PRIMARY KEY';
+ $field['default'] = '';
+ $field['null'] = '';
+ $field['unique'] = '';
+ $field['auto_increment'] = ' AUTOINCREMENT';
+
+ $this->primary_keys = array();
+ }
+ }
+
+}
+
+/* End of file pdo_sqlite_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php
new file mode 100644
index 000000000..c62720d48
--- /dev/null
+++ b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php
@@ -0,0 +1,136 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Open Software License version 3.0
+ *
+ * This source file is subject to the Open Software License (OSL 3.0) that is
+ * bundled with this package in the files license.txt / license.rst. It is
+ * also available through the world wide web at this URL:
+ * http://opensource.org/licenses/OSL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/)
+ * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
+ * @link http://codeigniter.com
+ * @since Version 2.1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+/**
+ * PDO SQLSRV Forge Class
+ *
+ * @category Database
+ * @author EllisLab Dev Team
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_pdo_sqlsrv_forge extends CI_DB_pdo_forge {
+
+ /**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
+
+ /**
+ * DROP TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
+
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
+ {
+ $sqls[] = $sql.$this->_process_column($field[$i]);
+ }
+
+ return $sqls;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
+ {
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' IDENTITY(1,1)';
+ }
+ }
+
+}
+
+/* End of file pdo_sqlsrv_forge.php */
+/* Location: ./system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php */ \ No newline at end of file
diff --git a/system/database/drivers/postgre/postgre_forge.php b/system/database/drivers/postgre/postgre_forge.php
index b08fa5177..ad26763a4 100644
--- a/system/database/drivers/postgre/postgre_forge.php
+++ b/system/database/drivers/postgre/postgre_forge.php
@@ -36,188 +36,149 @@ defined('BASEPATH') OR exit('No direct script access allowed');
class CI_DB_postgre_forge extends CI_DB_forge {
/**
- * DROP TABLE statement
+ * 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 $_drop_table = 'DROP TABLE IF EXISTS %s CASCADE';
+ protected $_null = 'NULL';
// --------------------------------------------------------------------
/**
- * Process Fields
+ * Class constructor
*
- * @param mixed $fields
- * @param array $primary_keys
- * @return string
+ * @return void
*/
- protected function _process_fields($fields, $primary_keys = array())
+ public function __construct()
{
- $sql = '';
- $current_field_count = 0;
+ parent::__construct();
- foreach ($fields as $field => $attributes)
+ if (version_compare($this->db->version(), '9.0', '>'))
{
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
+ $this->create_table_if = 'CREATE TABLE IF NOT EXISTS';
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('DROP', 'ADD'), TRUE))
+ {
+ return parent::_alter_table($alter_type, $table, $field);
+ }
+
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);
+ $sqls = array();
+ for ($i = 0, $c = count($field), $sql .= $alter_type.' '; $i < $c; $i++)
+ {
+ if ($field[$i]['_literal'] !== FALSE)
{
- $sql .= "\n\t".$attributes;
+ return FALSE;
}
- else
+
+ if (version_compare($this->db->version(), '8', '>=') && isset($field[$i]['type']))
{
- $sql .= "\n\t".$this->db->escape_identifiers($field);
-
- $attributes = array_change_key_case($attributes, CASE_UPPER);
- $is_unsigned = ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE);
-
- // Convert datatypes to be PostgreSQL-compatible
- switch (strtoupper($attributes['TYPE']))
- {
- case 'TINYINT':
- $attributes['TYPE'] = 'SMALLINT';
- break;
- case 'SMALLINT':
- $attributes['TYPE'] = ($is_unsigned) ? 'INTEGER' : 'SMALLINT';
- break;
- case 'MEDIUMINT':
- $attributes['TYPE'] = 'INTEGER';
- break;
- case 'INT':
- $attributes['TYPE'] = ($is_unsigned) ? 'BIGINT' : 'INTEGER';
- break;
- case 'BIGINT':
- $attributes['TYPE'] = ($is_unsigned) ? 'NUMERIC' : 'BIGINT';
- break;
- case 'DOUBLE':
- $attributes['TYPE'] = 'DOUBLE PRECISION';
- break;
- case 'DATETIME':
- $attributes['TYPE'] = 'TIMESTAMP';
- break;
- case 'LONGTEXT':
- $attributes['TYPE'] = 'TEXT';
- break;
- case 'BLOB':
- $attributes['TYPE'] = 'BYTEA';
- break;
- default:
- break;
- }
-
- // If this is an auto-incrementing primary key, use the serial data type instead
- $sql .= (in_array($field, $primary_keys) && ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- ? ' SERIAL' : ' '.$attributes['TYPE'];
-
- // Modified to prevent constraints with integer data types
- if ( ! empty($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') === FALSE)
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
-
- // Added new attribute to create unique fields. Also works with MySQL
- if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)
- {
- $sql .= ' UNIQUE';
- }
+ $sqls[] = $sql.' 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 '.$this->db->escape_identifiers($field[$i]['name'])
+ .' SET '.$field[$i]['default'];
+ }
+
+ if (isset($field[$i]['null']))
+ {
+ $sqls[] = $sql.' ALTER '.$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 '.$this->db->escape_identifiers($field[$i]['name'])
+ .' TO '.$this->db->escape_identifiers($field[$i]['new_name']);
}
}
- return $sql;
- }
+ return $sqls;
+ }
// --------------------------------------------------------------------
/**
- * Create Table
+ * Field attribute TYPE
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _attr_type(&$attributes)
{
- $sql = 'CREATE TABLE ';
-
- // PostgreSQL doesn't support IF NOT EXISTS syntax so we check if table exists manually
- if ($if_not_exists === TRUE && $this->db->table_exists($table))
+ // Reset field lenghts for data types that don't support it
+ if (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE)
{
- return TRUE;
+ $attributes['CONSTRAINT'] = NULL;
}
- $sql .= $this->db->escape_identifiers($table).' ('.$this->_process_fields($fields, $primary_keys);
-
- if (count($primary_keys) > 0)
+ switch (strtoupper($attributes['TYPE']))
{
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')';
- }
-
- $sql .= "\n);";
-
- if (is_array($keys) && count($keys) > 0)
- {
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- foreach ($key as $field)
- {
- $sql .= "\nCREATE INDEX ".$this->db->escape_identifiers($table.'_'.str_replace(array('"', "'"), '', $field).'_index')
- .' ON '.$this->db->escape_identifiers($table).' ('.$this->db->escape_identifiers($field).');';
- }
- }
+ case 'TINYINT':
+ $attributes['TYPE'] = 'SMALLINT';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ default: return;
}
-
- return $sql;
}
// --------------------------------------------------------------------
/**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Field attribute AUTO_INCREMENT
*
- * @param string $alter_type the ALTER type (ADD, DROP, CHANGE)
- * @param string $table the table name
- * @param string $fields the column definition
- * @param string $after_field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $fields, $after_field = '')
- {
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' ';
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
- {
- return $sql.$this->db->escape_identifiers($fields);
- }
-
- return $sql.$this->_process_fields($fields)
- .($after_field !== '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
- }
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
+ {
+ $field['type'] = ($field['type'] === 'NUMERIC')
+ ? 'BIGSERIAL'
+ : 'SERIAL';
+ }
+ }
}
diff --git a/system/database/drivers/sqlite/sqlite_forge.php b/system/database/drivers/sqlite/sqlite_forge.php
index 5650af7be..6ad583560 100644
--- a/system/database/drivers/sqlite/sqlite_forge.php
+++ b/system/database/drivers/sqlite/sqlite_forge.php
@@ -36,9 +36,32 @@ defined('BASEPATH') OR exit('No direct script access allowed');
class CI_DB_sqlite_forge extends CI_DB_forge {
/**
+ * CREATE TABLE IF statement
+ *
+ * @var string
+ */
+ protected $_create_table_if = FALSE;
+
+ /**
+ * UNSIGNED support
+ *
+ * @var bool|array
+ */
+ protected $_unsigned = FALSE;
+
+ /**
+ * NULL value representation in CREATE/ALTER TABLE statements
+ *
+ * @var string
+ */
+ protected $_null = 'NULL';
+
+ // --------------------------------------------------------------------
+
+ /**
* Create database
*
- * @param string the database name
+ * @param string $db_name (ignored)
* @return bool
*/
public function create_database($db_name = '')
@@ -53,7 +76,7 @@ class CI_DB_sqlite_forge extends CI_DB_forge {
/**
* Drop database
*
- * @param string the database name (ignored)
+ * @param string $db_name (ignored)
* @return bool
*/
public function drop_database($db_name = '')
@@ -77,126 +100,95 @@ class CI_DB_sqlite_forge extends CI_DB_forge {
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @todo implement drop_column(), modify_column()
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = 'CREATE TABLE ';
-
- // IF NOT EXISTS added to SQLite in 3.3.0
- if ($if_not_exists === TRUE && version_compare($this->db->version(), '3.3.0', '>=') === TRUE)
+ if ($alter_type === 'DROP' OR $alter_type === 'CHANGE')
{
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- empty($attributes['CONSTRAINT']) OR $sql .= '('.$attributes['CONSTRAINT'].')';
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
+ // drop_column():
+ // BEGIN TRANSACTION;
+ // CREATE TEMPORARY TABLE t1_backup(a,b);
+ // INSERT INTO t1_backup SELECT a,b FROM t1;
+ // DROP TABLE t1;
+ // CREATE TABLE t1(a,b);
+ // INSERT INTO t1 SELECT a,b FROM t1_backup;
+ // DROP TABLE t1_backup;
+ // COMMIT;
+ return FALSE;
+ }
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
+ return parent::_alter_table($alter_type, $table, $field);
+ }
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ // --------------------------------------------------------------------
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type']
+ .$field['auto_increment']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
+ }
- if (count($primary_keys) > 0)
- {
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')';
- }
+ // --------------------------------------------------------------------
- if (is_array($keys) && count($keys) > 0)
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
{
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- $sql .= ",\n\tUNIQUE (".implode(', ', $key).')';
- }
+ case 'ENUM':
+ case 'SET':
+ $attributes['TYPE'] = 'TEXT';
+ return;
+ default: return;
}
-
- return $sql."\n)";
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute AUTO_INCREMENT
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
- *
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- /* SQLite only supports adding new columns and it does
- * NOT support the AFTER statement. Each new column will
- * be added as the last one in the table.
- */
- if ($alter_type !== 'ADD COLUMN')
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
{
- // Not supported
- return FALSE;
- }
+ $field['type'] = 'INTEGER PRIMARY KEY';
+ $field['default'] = '';
+ $field['null'] = '';
+ $field['unique'] = '';
+ $field['auto_increment'] = ' AUTOINCREMENT';
- return 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name)
- .' '.$column_definition
- .($default_value != '' ? " DEFAULT '".$default_value."'" : '')
- // If NOT NULL is specified, the field must have a DEFAULT value other than NULL
- .(($null !== NULL && $default_value !== 'NULL') ? ' NOT NULL' : ' NULL');
+ $this->primary_keys = array();
+ }
}
}
diff --git a/system/database/drivers/sqlite3/sqlite3_forge.php b/system/database/drivers/sqlite3/sqlite3_forge.php
index e1dd3fa91..7ba0f7bab 100644
--- a/system/database/drivers/sqlite3/sqlite3_forge.php
+++ b/system/database/drivers/sqlite3/sqlite3_forge.php
@@ -36,9 +36,42 @@ defined('BASEPATH') OR exit('No direct script access allowed');
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
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ if (version_compare($this->db->version(), '3.3', '<'))
+ {
+ $this->create_table_if = FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Create database
*
- * @param string the database name
+ * @param string $db_name
* @return bool
*/
public function create_database($db_name = '')
@@ -53,7 +86,7 @@ class CI_DB_sqlite3_forge extends CI_DB_forge {
/**
* Drop database
*
- * @param string the database name (ignored)
+ * @param string $db_name (ignored)
* @return bool
*/
public function drop_database($db_name = '')
@@ -85,125 +118,95 @@ class CI_DB_sqlite3_forge extends CI_DB_forge {
// --------------------------------------------------------------------
/**
- * Create Table
+ * ALTER TABLE
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return bool
+ * @todo implement drop_column(), modify_column()
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ protected function _alter_table($alter_type, $table, $field)
{
- $sql = 'CREATE TABLE ';
-
- // IF NOT EXISTS added to SQLite in 3.3.0
- if ($if_not_exists === TRUE && version_compare($this->db->version(), '3.3.0', '>=') === TRUE)
- {
- $sql .= 'IF NOT EXISTS ';
- }
-
- $sql .= $this->db->escape_identifiers($table).' (';
- $current_field_count = 0;
-
- foreach ($fields as $field => $attributes)
+ if ($alter_type === 'DROP' OR $alter_type === 'CHANGE')
{
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
-
- empty($attributes['CONSTRAINT']) OR $sql .= '('.$attributes['CONSTRAINT'].')';
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
+ // drop_column():
+ // BEGIN TRANSACTION;
+ // CREATE TEMPORARY TABLE t1_backup(a,b);
+ // INSERT INTO t1_backup SELECT a,b FROM t1;
+ // DROP TABLE t1;
+ // CREATE TABLE t1(a,b);
+ // INSERT INTO t1 SELECT a,b FROM t1_backup;
+ // DROP TABLE t1_backup;
+ // COMMIT;
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
+ return FALSE;
+ }
- $sql .= ( ! empty($attributes['NULL']) && $attributes['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
+ return parent::_alter_table($alter_type, $table, $field);
+ }
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ // --------------------------------------------------------------------
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ /**
+ * Process column
+ *
+ * @param array $field
+ * @return string
+ */
+ protected function _process_column($field)
+ {
+ return $this->db->escape_identifiers($field['name'])
+ .' '.$field['type']
+ .$field['auto_increment']
+ .$field['null']
+ .$field['unique']
+ .$field['default'];
+ }
- if (count($primary_keys) > 0)
- {
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')';
- }
+ // --------------------------------------------------------------------
- if (is_array($keys) && count($keys) > 0)
+ /**
+ * Field attribute TYPE
+ *
+ * Performs a data type mapping between different databases.
+ *
+ * @param array &$attributes
+ * @return void
+ */
+ protected function _attr_type(&$attributes)
+ {
+ switch (strtoupper($attributes['TYPE']))
{
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->db->escape_identifiers($key));
-
- $sql .= ",\n\tUNIQUE (".implode(', ', $key).')';
- }
+ case 'ENUM':
+ case 'SET':
+ $attributes['TYPE'] = 'TEXT';
+ return;
+ default: return;
}
-
- return $sql."\n)";
}
// --------------------------------------------------------------------
/**
- * Alter table query
- *
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Field attribute AUTO_INCREMENT
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_auto_increment(&$attributes, &$field)
{
- /* SQLite only supports adding new columns and it does
- * NOT support the AFTER statement. Each new column will
- * be added as the last one in the table.
- */
- if ($alter_type !== 'ADD COLUMN')
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
{
- // Not supported
- return FALSE;
- }
+ $field['type'] = 'INTEGER PRIMARY KEY';
+ $field['default'] = '';
+ $field['null'] = '';
+ $field['unique'] = '';
+ $field['auto_increment'] = ' AUTOINCREMENT';
- return 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name)
- .' '.$column_definition
- .($default_value !== '' ? ' DEFAULT '.$default_value : '')
- // If NOT NULL is specified, the field must have a DEFAULT value other than NULL
- .(($null !== NULL && $default_value !== 'NULL') ? ' NOT NULL' : ' NULL');
+ $this->primary_keys = array();
+ }
}
}
diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php
index 8155565c0..da8f68c56 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_forge.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_forge.php
@@ -36,130 +36,98 @@ defined('BASEPATH') OR exit('No direct script access allowed');
class CI_DB_sqlsrv_forge extends CI_DB_forge {
/**
- * DROP TABLE statement
+ * CREATE TABLE IF statement
*
* @var string
*/
- protected $_drop_table = 'DROP TABLE %s';
-
- // --------------------------------------------------------------------
+ protected $_create_table_if = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nCREATE TABLE";
/**
- * Create Table
+ * DROP TABLE IF statement
*
- * @param string the table name
- * @param array the fields
- * @param mixed primary key(s)
- * @param mixed key(s)
- * @param bool should 'IF NOT EXISTS' be added to the SQL
- * @return string
+ * @var string
*/
- protected function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
- {
- $sql = ($if_not_exists === TRUE)
- ? "IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'".$table."') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\n"
- : '';
-
- $sql .= 'CREATE TABLE '.$this->db->escape_identifiers($table).' (';
-
- $current_field_count = 0;
- foreach ($fields as $field => $attributes)
- {
- // Numeric field names aren't allowed in databases, so if the key is
- // numeric, we know it was assigned by PHP and the developer manually
- // entered the field information, so we'll simply add it to the list
- if (is_numeric($field))
- {
- $sql .= "\n\t".$attributes;
- }
- else
- {
- $attributes = array_change_key_case($attributes, CASE_UPPER);
-
- $sql .= "\n\t".$this->db->escape_identifiers($field).' '.$attributes['TYPE'];
+ protected $_drop_table_if = "IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\nDROP TABLE";
- if (stripos($attributes['TYPE'], 'INT') === FALSE && ! empty($attributes['CONSTRAINT']))
- {
- $sql .= '('.$attributes['CONSTRAINT'].')';
- }
-
- if ( ! empty($attributes['UNSIGNED']) && $attributes['UNSIGNED'] === TRUE)
- {
- $sql .= ' UNSIGNED';
- }
-
- if (isset($attributes['DEFAULT']))
- {
- $sql .= " DEFAULT '".$attributes['DEFAULT']."'";
- }
-
- $sql .= ( ! empty($attributes['NULL']) && $attribues['NULL'] === TRUE)
- ? ' NULL' : ' NOT NULL';
-
- if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)
- {
- $sql .= ' AUTO_INCREMENT';
- }
- }
+ /**
+ * UNSIGNED support
+ *
+ * @var array
+ */
+ protected $_unsigned = array(
+ 'TINYINT' => 'SMALLINT',
+ 'SMALLINT' => 'INT',
+ 'INT' => 'BIGINT',
+ 'REAL' => 'FLOAT'
+ );
- // don't add a comma on the end of the last field
- if (++$current_field_count < count($fields))
- {
- $sql .= ',';
- }
- }
+ // --------------------------------------------------------------------
- if (count($primary_keys) > 0)
+ /**
+ * ALTER TABLE
+ *
+ * @param string $alter_type ALTER type
+ * @param string $table Table name
+ * @param mixed $field Column definition
+ * @return string|string[]
+ */
+ protected function _alter_table($alter_type, $table, $field)
+ {
+ if (in_array($alter_type, array('ADD', 'DROP'), TRUE))
{
- $sql .= ",\n\tPRIMARY KEY (".implode(', ', $this->db->escape_identifiers($primary_keys)).')';
+ return parent::_alter_table($alter_type, $table, $field);
}
- if (is_array($keys) && count($keys) > 0)
+ $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';
+ $sqls = array();
+ for ($i = 0, $c = count($field); $i < $c; $i++)
{
- foreach ($keys as $key)
- {
- $key = is_array($key)
- ? $this->db->escape_identifiers($key)
- : array($this->escape_identifiers($key));
-
- $sql .= ",\n\tFOREIGN KEY (".implode(', ', $key).')';
- }
+ $sqls[] = $sql.$this->_process_column($field[$i]);
}
- return $sql."\n)";
+ return $sqls;
}
// --------------------------------------------------------------------
/**
- * Alter table query
+ * Field attribute TYPE
*
- * Generates a platform-specific query so that a table can be altered
- * Called by add_column(), drop_column(), and column_alter(),
+ * Performs a data type mapping between different databases.
*
- * @param string the ALTER type (ADD, DROP, CHANGE)
- * @param string the column name
- * @param string the table name
- * @param string the column definition
- * @param string the default value
- * @param bool should 'NOT NULL' be added
- * @param string the field after which we should add the new field
- * @return string
+ * @param array &$attributes
+ * @return void
*/
- protected function _alter_table($alter_type, $table, $column_name, $column_definition = '', $default_value = '', $null = '', $after_field = '')
+ protected function _attr_type(&$attributes)
{
- $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '.$alter_type.' '.$this->db->escape_identifiers($column_name);
-
- // DROP has everything it needs now.
- if ($alter_type === 'DROP')
+ switch (strtoupper($attributes['TYPE']))
{
- return $sql;
+ case 'MEDIUMINT':
+ $attributes['TYPE'] = 'INTEGER';
+ $attributes['UNSIGNED'] = FALSE;
+ return;
+ case 'INTEGER':
+ $attributes['TYPE'] = 'INT';
+ return;
+ default: return;
}
+ }
- return $sql.' '.$column_definition
- .($default_value != '' ? ' DEFAULT "'.$default_value.'"' : '')
- .($null === NULL ? ' NULL' : ' NOT NULL')
- .($after_field != '' ? ' AFTER '.$this->db->escape_identifiers($after_field) : '');
+ // --------------------------------------------------------------------
+
+ /**
+ * Field attribute AUTO_INCREMENT
+ *
+ * @param array &$attributes
+ * @param array &$field
+ * @return void
+ */
+ protected function _attr_auto_increment(&$attributes, &$field)
+ {
+ if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)
+ {
+ $field['auto_increment'] = ' IDENTITY(1,1)';
+ }
}
}