home *** CD-ROM | disk | FTP | other *** search
- <?php
-
- /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
-
- /**
- * Creates, checks or alters tables from DB_Table definitions.
- *
- * DB_Table_Manager provides database automated table creation
- * facilities.
- *
- * PHP versions 4 and 5
- *
- * LICENSE:
- *
- * Copyright (c) 1997-2007, Paul M. Jones <pmjones@php.net>
- * David C. Morse <morse@php.net>
- * Mark Wiesemann <wiesemann@php.net>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * The names of the authors may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
- * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Database
- * @package DB_Table
- * @author Paul M. Jones <pmjones@php.net>
- * @author David C. Morse <morse@php.net>
- * @author Mark Wiesemann <wiesemann@php.net>
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Manager.php,v 1.39 2008/06/08 17:49:28 wiesemann Exp $
- * @link http://pear.php.net/package/DB_Table
- */
-
- require_once 'DB/Table.php';
-
-
- /**
- * Valid types for the different data types in the different DBMS.
- */
- $GLOBALS['_DB_TABLE']['valid_type'] = array(
- 'fbsql' => array( // currently not supported
- 'boolean' => '',
- 'char' => '',
- 'varchar' => '',
- 'smallint' => '',
- 'integer' => '',
- 'bigint' => '',
- 'decimal' => '',
- 'single' => '',
- 'double' => '',
- 'clob' => '',
- 'date' => '',
- 'time' => '',
- 'timestamp' => ''
- ),
- 'ibase' => array(
- 'boolean' => array('char', 'integer', 'real', 'smallint'),
- 'char' => array('char', 'varchar'),
- 'varchar' => 'varchar',
- 'smallint' => array('integer', 'smallint'),
- 'integer' => 'integer',
- 'bigint' => array('bigint', 'integer'),
- 'decimal' => 'numeric',
- 'single' => array('double precision', 'float'),
- 'double' => 'double precision',
- 'clob' => 'blob',
- 'date' => 'date',
- 'time' => 'time',
- 'timestamp' => 'timestamp'
- ),
- 'mssql' => array( // currently not supported
- 'boolean' => '',
- 'char' => '',
- 'varchar' => '',
- 'smallint' => '',
- 'integer' => '',
- 'bigint' => '',
- 'decimal' => '',
- 'single' => '',
- 'double' => '',
- 'clob' => '',
- 'date' => '',
- 'time' => '',
- 'timestamp' => ''
- ),
- 'mysql' => array(
- 'boolean' => array('char', 'decimal', 'int', 'real', 'tinyint'),
- 'char' => array('char', 'string', 'varchar'),
- 'varchar' => array('char', 'string', 'varchar'),
- 'smallint' => array('smallint', 'int'),
- 'integer' => 'int',
- 'bigint' => array('int', 'bigint'),
- 'decimal' => array('decimal', 'real'),
- 'single' => array('double', 'real'),
- 'double' => array('double', 'real'),
- 'clob' => array('blob', 'longtext', 'tinytext', 'text', 'mediumtext'),
- 'date' => array('char', 'date', 'string'),
- 'time' => array('char', 'string', 'time'),
- 'timestamp' => array('char', 'datetime', 'string')
- ),
- 'mysqli' => array(
- 'boolean' => array('char', 'decimal', 'tinyint'),
- 'char' => array('char', 'varchar'),
- 'varchar' => array('char', 'varchar'),
- 'smallint' => array('smallint', 'int'),
- 'integer' => 'int',
- 'bigint' => array('int', 'bigint'),
- 'decimal' => 'decimal',
- 'single' => array('double', 'float'),
- 'double' => 'double',
- 'clob' => array('blob', 'longtext', 'tinytext', 'text', 'mediumtext'),
- 'date' => array('char', 'date', 'varchar'),
- 'time' => array('char', 'time', 'varchar'),
- 'timestamp' => array('char', 'datetime', 'varchar')
- ),
- 'oci8' => array(
- 'boolean' => 'number',
- 'char' => array('char', 'varchar2'),
- 'varchar' => 'varchar2',
- 'smallint' => 'number',
- 'integer' => 'number',
- 'bigint' => 'number',
- 'decimal' => 'number',
- 'single' => array('float', 'number'),
- 'double' => array('float', 'number'),
- 'clob' => 'clob',
- 'date' => array('char', 'date'),
- 'time' => array('char', 'date'),
- 'timestamp' => array('char', 'date')
- ),
- 'pgsql' => array(
- 'boolean' => array('bool', 'numeric'),
- 'char' => array('bpchar', 'varchar'),
- 'varchar' => 'varchar',
- 'smallint' => array('int2', 'int4'),
- 'integer' => 'int4',
- 'bigint' => array('int4', 'int8'),
- 'decimal' => 'numeric',
- 'single' => array('float4', 'float8'),
- 'double' => 'float8',
- 'clob' => array('oid', 'text'),
- 'date' => array('bpchar', 'date'),
- 'time' => array('bpchar', 'time'),
- 'timestamp' => array('bpchar', 'timestamp')
- ),
- 'sqlite' => array(
- 'boolean' => 'boolean',
- 'char' => 'char',
- 'varchar' => array('char', 'varchar'),
- 'smallint' => array('int', 'smallint'),
- 'integer' => array('int', 'integer'),
- 'bigint' => array('int', 'bigint'),
- 'decimal' => array('decimal', 'numeric'),
- 'single' => array('double', 'float'),
- 'double' => 'double',
- 'clob' => array('clob', 'longtext'),
- 'date' => 'date',
- 'time' => 'time',
- 'timestamp' => array('datetime', 'timestamp')
- ),
- );
-
- /**
- * Mapping between DB_Table and MDB2 data types.
- */
- $GLOBALS['_DB_TABLE']['mdb2_type'] = array(
- 'boolean' => 'boolean',
- 'char' => 'text',
- 'varchar' => 'text',
- 'smallint' => 'integer',
- 'integer' => 'integer',
- 'bigint' => 'integer',
- 'decimal' => 'decimal',
- 'single' => 'float',
- 'double' => 'float',
- 'clob' => 'clob',
- 'date' => 'date',
- 'time' => 'time',
- 'timestamp' => 'timestamp'
- );
-
- /**
- * Creates, checks or alters tables from DB_Table definitions.
- *
- * DB_Table_Manager provides database automated table creation
- * facilities.
- *
- * @category Database
- * @package DB_Table
- * @author Paul M. Jones <pmjones@php.net>
- * @author David C. Morse <morse@php.net>
- * @author Mark Wiesemann <wiesemann@php.net>
- * @version Release: 1.5.5
- * @link http://pear.php.net/package/DB_Table
- */
- class DB_Table_Manager {
-
-
- /**
- *
- * Create the table based on DB_Table column and index arrays.
- *
- * @static
- *
- * @access public
- *
- * @param object &$db A PEAR DB/MDB2 object.
- *
- * @param string $table The table name to connect to in the database.
- *
- * @param mixed $column_set A DB_Table $this->col array.
- *
- * @param mixed $index_set A DB_Table $this->idx array.
- *
- * @return mixed Boolean false if there was no attempt to create the
- * table, boolean true if the attempt succeeded, and a PEAR_Error if
- * the attempt failed.
- *
- */
-
- function create(&$db, $table, $column_set, $index_set)
- {
- if (is_subclass_of($db, 'db_common')) {
- $backend = 'db';
- } elseif (is_subclass_of($db, 'mdb2_driver_common')) {
- $backend = 'mdb2';
- $db->loadModule('Manager');
- }
- $phptype = $db->phptype;
-
- // columns to be created
- $column = array();
-
- // max. value for scope (only used with MDB2 as backend)
- $max_scope = 0;
-
- // indexes to be created
- $indexes = array();
-
- // check the table name
- $name_check = DB_Table_Manager::_validateTableName($table);
- if (PEAR::isError($name_check)) {
- return $name_check;
- }
-
-
- // -------------------------------------------------------------
- //
- // validate each column mapping and build the individual
- // definitions, and note column indexes as we go.
- //
-
- if (is_null($column_set)) {
- $column_set = array();
- }
-
- foreach ($column_set as $colname => $val) {
-
- $colname = trim($colname);
-
- // check the column name
- $name_check = DB_Table_Manager::_validateColumnName($colname);
- if (PEAR::isError($name_check)) {
- return $name_check;
- }
-
-
- // prepare variables
- $type = (isset($val['type'])) ? $val['type'] : null;
- $size = (isset($val['size'])) ? $val['size'] : null;
- $scope = (isset($val['scope'])) ? $val['scope'] : null;
- $require = (isset($val['require'])) ? $val['require'] : null;
- $default = (isset($val['default'])) ? $val['default'] : null;
-
- if ($backend == 'mdb2') {
-
- // get the declaration string
- $result = DB_Table_Manager::getDeclareMDB2($type,
- $size, $scope, $require, $default, $max_scope);
-
- // did it work?
- if (PEAR::isError($result)) {
- $result->userinfo .= " ('$colname')";
- return $result;
- }
-
- // add the declaration to the array of all columns
- $column[$colname] = $result;
-
- } else {
-
- // get the declaration string
- $result = DB_Table_Manager::getDeclare($phptype, $type,
- $size, $scope, $require, $default);
-
- // did it work?
- if (PEAR::isError($result)) {
- $result->userinfo .= " ('$colname')";
- return $result;
- }
-
- // add the declaration to the array of all columns
- $column[] = "$colname $result";
-
- }
-
- }
-
-
- // -------------------------------------------------------------
- //
- // validate the indexes.
- //
-
- if (is_null($index_set)) {
- $index_set = array();
- }
-
- $count_primary_keys = 0;
-
- foreach ($index_set as $idxname => $val) {
-
- list($type, $cols) = DB_Table_Manager::_getIndexTypeAndColumns($val, $idxname);
-
- $newIdxName = '';
-
- // check the index definition
- $index_check = DB_Table_Manager::_validateIndexName($idxname,
- $table, $phptype, $type, $cols, $column_set, $newIdxName);
- if (PEAR::isError($index_check)) {
- return $index_check;
- }
-
- // check number of primary keys (only one is allowed)
- if ($type == 'primary') {
- // SQLite does not support primary keys
- if ($phptype == 'sqlite') {
- return DB_Table::throwError(DB_TABLE_ERR_DECLARE_PRIM_SQLITE);
- }
- $count_primary_keys++;
- }
- if ($count_primary_keys > 1) {
- return DB_Table::throwError(DB_TABLE_ERR_DECLARE_PRIMARY);
- }
-
- // create index entry
- if ($backend == 'mdb2') {
-
- // array with column names as keys
- $idx_cols = array();
- foreach ($cols as $col) {
- $idx_cols[$col] = array();
- }
-
- switch ($type) {
- case 'primary':
- $indexes['primary'][$newIdxName] =
- array('fields' => $idx_cols,
- 'primary' => true);
- break;
- case 'unique':
- $indexes['unique'][$newIdxName] =
- array('fields' => $idx_cols,
- 'unique' => true);
- break;
- case 'normal':
- $indexes['normal'][$newIdxName] =
- array('fields' => $idx_cols);
- break;
- }
-
- } else {
-
- $indexes[] = DB_Table_Manager::getDeclareForIndex($phptype,
- $type, $newIdxName, $table, $cols);
-
- }
-
- }
-
-
- // -------------------------------------------------------------
- //
- // now for the real action: create the table and indexes!
- //
- if ($backend == 'mdb2') {
-
- // save user defined 'decimal_places' option
- $decimal_places = $db->getOption('decimal_places');
- $db->setOption('decimal_places', $max_scope);
-
- // attempt to create the table
- $result = $db->manager->createTable($table, $column);
- // restore user defined 'decimal_places' option
- $db->setOption('decimal_places', $decimal_places);
- if (PEAR::isError($result)) {
- return $result;
- }
-
- } else {
-
- // build the CREATE TABLE command
- $cmd = "CREATE TABLE $table (\n\t";
- $cmd .= implode(",\n\t", $column);
- $cmd .= "\n)";
-
- // attempt to create the table
- $result = $db->query($cmd);
- if (PEAR::isError($result)) {
- return $result;
- }
-
- }
-
- $result = DB_Table_Manager::_createIndexesAndContraints($db, $backend,
- $table, $indexes);
- if (PEAR::isError($result)) {
- return $result;
- }
-
- // we're done!
- return true;
- }
-
-
- /**
- *
- * Verify whether the table and columns exist, whether the columns
- * have the right type and whether the indexes exist.
- *
- * @static
- *
- * @access public
- *
- * @param object &$db A PEAR DB/MDB2 object.
- *
- * @param string $table The table name to connect to in the database.
- *
- * @param mixed $column_set A DB_Table $this->col array.
- *
- * @param mixed $index_set A DB_Table $this->idx array.
- *
- * @return mixed Boolean true if the verification was successful, and a
- * PEAR_Error if verification failed.
- *
- */
-
- function verify(&$db, $table, $column_set, $index_set)
- {
- if (is_subclass_of($db, 'db_common')) {
- $backend = 'db';
- $reverse =& $db;
- $table_info_mode = DB_TABLEINFO_FULL;
- $table_info_error = DB_ERROR_NEED_MORE_DATA;
- } elseif (is_subclass_of($db, 'mdb2_driver_common')) {
- $backend = 'mdb2';
- $reverse =& $this->db->loadModule('Reverse');
- $table_info_mode = MDB2_TABLEINFO_FULL;
- $table_info_error = MDB2_ERROR_NEED_MORE_DATA;
- }
- $phptype = $db->phptype;
-
- // check #1: does the table exist?
-
- // check the table name
- $name_check = DB_Table_Manager::_validateTableName($table);
- if (PEAR::isError($name_check)) {
- return $name_check;
- }
-
- // get table info
- $tableInfo = $reverse->tableInfo($table, $table_info_mode);
- if (PEAR::isError($tableInfo)) {
- if ($tableInfo->getCode() == $table_info_error) {
- return DB_Table::throwError(
- DB_TABLE_ERR_VER_TABLE_MISSING,
- "(table='$table')"
- );
- }
- return $tableInfo;
- }
- $tableInfoOrder = array_change_key_case($tableInfo['order'], CASE_LOWER);
-
- if (is_null($column_set)) {
- $column_set = array();
- }
-
- foreach ($column_set as $colname => $val) {
- $colname = strtolower(trim($colname));
-
- // check the column name
- $name_check = DB_Table_Manager::_validateColumnName($colname);
- if (PEAR::isError($name_check)) {
- return $name_check;
- }
-
- // check #2: do all columns exist?
- $column_exists = DB_Table_Manager::_columnExists($colname,
- $tableInfoOrder, 'verify');
- if (PEAR::isError($column_exists)) {
- return $column_exists;
- }
-
- // check #3: do all columns have the right type?
-
- // check whether the column type is a known type
- $type_check = DB_Table_Manager::_validateColumnType($phptype, $val['type']);
- if (PEAR::isError($type_check)) {
- return $type_check;
- }
-
- // check whether the column has the right type
- $type_check = DB_Table_Manager::_checkColumnType($phptype,
- $colname, $val['type'], $tableInfoOrder, $tableInfo, 'verify');
- if (PEAR::isError($type_check)) {
- return $type_check;
- }
-
- }
-
- // check #4: do all indexes exist?
- $table_indexes = DB_Table_Manager::getIndexes($db, $table);
- if (PEAR::isError($table_indexes)) {
- return $table_indexes;
- }
-
- if (is_null($index_set)) {
- $index_set = array();
- }
-
- foreach ($index_set as $idxname => $val) {
-
- list($type, $cols) = DB_Table_Manager::_getIndexTypeAndColumns($val, $idxname);
-
- $newIdxName = '';
-
- // check the index definition
- $index_check = DB_Table_Manager::_validateIndexName($idxname,
- $table, $phptype, $type, $cols, $column_set, $newIdxName);
- if (PEAR::isError($index_check)) {
- return $index_check;
- }
-
- // check whether the index has the right type and has all
- // specified columns
- $index_check = DB_Table_Manager::_checkIndex($idxname, $newIdxName,
- $type, $cols, $table_indexes, 'verify');
- if (PEAR::isError($index_check)) {
- return $index_check;
- }
-
- }
-
- return true;
- }
-
-
- /**
- *
- * Alter columns and indexes of a table based on DB_Table column and index
- * arrays.
- *
- * @static
- *
- * @access public
- *
- * @param object &$db A PEAR DB/MDB2 object.
- *
- * @param string $table The table name to connect to in the database.
- *
- * @param mixed $column_set A DB_Table $this->col array.
- *
- * @param mixed $index_set A DB_Table $this->idx array.
- *
- * @return bool|object True if altering was successful or a PEAR_Error on
- * failure.
- *
- */
-
- function alter(&$db, $table, $column_set, $index_set)
- {
- $phptype = $db->phptype;
-
- if (is_subclass_of($db, 'db_common')) {
- $backend = 'db';
- $reverse =& $db;
- // workaround for missing index and constraint information methods
- // in PEAR::DB ==> use adopted code from MDB2's driver classes
- require_once 'DB/Table/Manager/' . $phptype . '.php';
- $classname = 'DB_Table_Manager_' . $phptype;
- $dbtm =& new $classname();
- $dbtm->_db =& $db; // pass database instance to the 'workaround' class
- $manager =& $dbtm;
- $table_info_mode = DB_TABLEINFO_FULL;
- $ok_const = DB_OK;
- } elseif (is_subclass_of($db, 'mdb2_driver_common')) {
- $backend = 'mdb2';
- $db->loadModule('Reverse');
- $manager =& $db->manager;
- $reverse =& $db->reverse;
- $table_info_mode = MDB2_TABLEINFO_FULL;
- $ok_const = MDB2_OK;
- }
-
- // get table info
- $tableInfo = $reverse->tableInfo($table, $table_info_mode);
- if (PEAR::isError($tableInfo)) {
- return $tableInfo;
- }
- $tableInfoOrder = array_change_key_case($tableInfo['order'], CASE_LOWER);
-
- // emulate MDB2 Reverse extension for PEAR::DB as backend
- if (is_subclass_of($db, 'db_common')) {
- $reverse =& $dbtm;
- }
-
- // check (and alter) columns
- if (is_null($column_set)) {
- $column_set = array();
- }
-
- foreach ($column_set as $colname => $val) {
- $colname = strtolower(trim($colname));
-
- // check the column name
- $name_check = DB_Table_Manager::_validateColumnName($colname);
- if (PEAR::isError($name_check)) {
- return $name_check;
- }
-
- // check the column's existence
- $column_exists = DB_Table_Manager::_columnExists($colname,
- $tableInfoOrder, 'alter');
- if (PEAR::isError($column_exists)) {
- return $column_exists;
- }
- if ($column_exists === false) { // add the column
- $definition = DB_Table_Manager::_getColumnDefinition($backend,
- $phptype, $val);
- if (PEAR::isError($definition)) {
- return $definition;
- }
- $changes = array('add' => array($colname => $definition));
- if (array_key_exists('debug', $GLOBALS['_DB_TABLE'])) {
- echo "(alter) New table field will be added ($colname):\n";
- var_dump($changes);
- echo "\n";
- }
- $result = $manager->alterTable($table, $changes, false);
- if (PEAR::isError($result)) {
- return $result;
- }
- continue;
- }
-
- // check whether the column type is a known type
- $type_check = DB_Table_Manager::_validateColumnType($phptype, $val['type']);
- if (PEAR::isError($type_check)) {
- return $type_check;
- }
-
- // check whether the column has the right type
- $type_check = DB_Table_Manager::_checkColumnType($phptype,
- $colname, $val['type'], $tableInfoOrder, $tableInfo, 'alter');
- if (PEAR::isError($type_check)) {
- return $type_check;
- }
- if ($type_check === false) { // change the column type
- $definition = DB_Table_Manager::_getColumnDefinition($backend,
- $phptype, $val);
- if (PEAR::isError($definition)) {
- return $definition;
- }
- $changes = array('change' =>
- array($colname => array('type' => null,
- 'definition' => $definition)));
- if (array_key_exists('debug', $GLOBALS['_DB_TABLE'])) {
- echo "(alter) Table field's type will be changed ($colname):\n";
- var_dump($changes);
- echo "\n";
- }
- $result = $manager->alterTable($table, $changes, false);
- if (PEAR::isError($result)) {
- return $result;
- }
- continue;
- }
-
- }
-
- // get information about indexes / constraints
- $table_indexes = DB_Table_Manager::getIndexes($db, $table);
- if (PEAR::isError($table_indexes)) {
- return $table_indexes;
- }
-
- // check (and alter) indexes / constraints
- if (is_null($index_set)) {
- $index_set = array();
- }
-
- foreach ($index_set as $idxname => $val) {
-
- list($type, $cols) = DB_Table_Manager::_getIndexTypeAndColumns($val, $idxname);
-
- $newIdxName = '';
-
- // check the index definition
- $index_check = DB_Table_Manager::_validateIndexName($idxname,
- $table, $phptype, $type, $cols, $column_set, $newIdxName);
- if (PEAR::isError($index_check)) {
- return $index_check;
- }
-
- // check whether the index has the right type and has all
- // specified columns
- $index_check = DB_Table_Manager::_checkIndex($idxname, $newIdxName,
- $type, $cols, $table_indexes, 'alter');
- if (PEAR::isError($index_check)) {
- return $index_check;
- }
- if ($index_check === false) { // (1) drop wrong index/constraint
- // (2) add right index/constraint
- if ($backend == 'mdb2') {
- // save user defined 'idxname_format' option
- $idxname_format = $db->getOption('idxname_format');
- $db->setOption('idxname_format', '%s');
- }
- // drop index/constraint only if it exists
- foreach (array('normal', 'unique', 'primary') as $idx_type) {
- if (array_key_exists(strtolower($newIdxName),
- $table_indexes[$idx_type])) {
- if (array_key_exists('debug', $GLOBALS['_DB_TABLE'])) {
- echo "(alter) Index/constraint will be deleted (name: '$newIdxName', type: '$idx_type').\n";
- }
- if ($idx_type == 'normal') {
- $result = $manager->dropIndex($table, $newIdxName);
- } else {
- $result = $manager->dropConstraint($table, $newIdxName);
- }
- if (PEAR::isError($result)) {
- if ($backend == 'mdb2') {
- // restore user defined 'idxname_format' option
- $db->setOption('idxname_format', $idxname_format);
- }
- return $result;
- }
- break;
- }
- }
-
- // prepare index/constraint definition
- $indexes = array();
- if ($backend == 'mdb2') {
-
- // array with column names as keys
- $idx_cols = array();
- foreach ($cols as $col) {
- $idx_cols[$col] = array();
- }
-
- switch ($type) {
- case 'primary':
- $indexes['primary'][$newIdxName] =
- array('fields' => $idx_cols,
- 'primary' => true);
- break;
- case 'unique':
- $indexes['unique'][$newIdxName] =
- array('fields' => $idx_cols,
- 'unique' => true);
- break;
- case 'normal':
- $indexes['normal'][$newIdxName] =
- array('fields' => $idx_cols);
- break;
- }
-
- } else {
-
- $indexes[] = DB_Table_Manager::getDeclareForIndex($phptype,
- $type, $newIdxName, $table, $cols);
-
- }
-
- // create index/constraint
- if (array_key_exists('debug', $GLOBALS['_DB_TABLE'])) {
- echo "(alter) New index/constraint will be created (name: '$newIdxName', type: '$type'):\n";
- var_dump($indexes);
- echo "\n";
- }
- $result = DB_Table_Manager::_createIndexesAndContraints(
- $db, $backend, $table, $indexes);
- if ($backend == 'mdb2') {
- // restore user defined 'idxname_format' option
- $db->setOption('idxname_format', $idxname_format);
- }
- if (PEAR::isError($result)) {
- return $result;
- }
-
- continue;
- }
-
- }
-
- return true;
- }
-
-
- /**
- *
- * Check whether a table exists.
- *
- * @static
- *
- * @access public
- *
- * @param object &$db A PEAR DB/MDB2 object.
- *
- * @param string $table The table name that should be checked.
- *
- * @return bool|object True if the table exists, false if not, or a
- * PEAR_Error on failure.
- *
- */
-
- function tableExists(&$db, $table)
- {
- if (is_subclass_of($db, 'db_common')) {
- $list = $db->getListOf('tables');
- } elseif (is_subclass_of($db, 'mdb2_driver_common')) {
- $db->loadModule('Manager');
- $list = $db->manager->listTables();
- }
- if (PEAR::isError($list)) {
- return $list;
- }
- array_walk($list, create_function('&$value,$key',
- '$value = trim(strtolower($value));'));
- return in_array(strtolower($table), $list);
- }
-
-
- /**
- *
- * Get the column declaration string for a DB_Table column.
- *
- * @static
- *
- * @access public
- *
- * @param string $phptype The DB/MDB2 phptype key.
- *
- * @param string $coltype The DB_Table column type.
- *
- * @param int $size The size for the column (needed for string and
- * decimal).
- *
- * @param int $scope The scope for the column (needed for decimal).
- *
- * @param bool $require True if the column should be NOT NULL, false
- * allowed to be NULL.
- *
- * @param string $default The SQL calculation for a default value.
- *
- * @return string|object A declaration string on success, or a
- * PEAR_Error on failure.
- *
- */
-
- function getDeclare($phptype, $coltype, $size = null, $scope = null,
- $require = null, $default = null)
- {
- // validate char/varchar/decimal type declaration
- $validation = DB_Table_Manager::_validateTypeDeclaration($coltype, $size,
- $scope);
- if (PEAR::isError($validation)) {
- return $validation;
- }
-
- // map of column types and declarations for this RDBMS
- $map = $GLOBALS['_DB_TABLE']['type'][$phptype];
-
- // is it a recognized column type?
- $types = array_keys($map);
- if (! in_array($coltype, $types)) {
- return DB_Table::throwError(
- DB_TABLE_ERR_DECLARE_TYPE,
- "('$coltype')"
- );
- }
-
- // basic declaration
- switch ($coltype) {
-
- case 'char':
- case 'varchar':
- $declare = $map[$coltype] . "($size)";
- break;
-
- case 'decimal':
- $declare = $map[$coltype] . "($size,$scope)";
- break;
-
- default:
- $declare = $map[$coltype];
- break;
-
- }
-
- // set the "NULL"/"NOT NULL" portion
- $null = ' NULL';
- if ($phptype == 'ibase') { // Firebird does not like 'NULL'
- $null = ''; // in CREATE TABLE
- }
- if ($phptype == 'pgsql') { // PostgreSQL does not like 'NULL'
- $null = ''; // in ALTER TABLE
- }
- $declare .= ($require) ? ' NOT NULL' : $null;
-
- // set the "DEFAULT" portion
- if ($default) {
- switch ($coltype) {
- case 'char':
- case 'varchar':
- case 'clob':
- $declare .= " DEFAULT '$default'";
- break;
-
- default:
- $declare .= " DEFAULT $default";
- break;
- }
- }
-
- // done
- return $declare;
- }
-
-
- /**
- *
- * Get the column declaration string for a DB_Table column.
- *
- * @static
- *
- * @access public
- *
- * @param string $coltype The DB_Table column type.
- *
- * @param int $size The size for the column (needed for string and
- * decimal).
- *
- * @param int $scope The scope for the column (needed for decimal).
- *
- * @param bool $require True if the column should be NOT NULL, false
- * allowed to be NULL.
- *
- * @param string $default The SQL calculation for a default value.
- *
- * @param int $max_scope The maximal scope for all table column
- * (pass-by-reference).
- *
- * @return string|object A MDB2 column definition array on success, or a
- * PEAR_Error on failure.
- *
- */
-
- function getDeclareMDB2($coltype, $size = null, $scope = null,
- $require = null, $default = null, &$max_scope)
- {
- // validate char/varchar/decimal type declaration
- $validation = DB_Table_Manager::_validateTypeDeclaration($coltype, $size,
- $scope);
- if (PEAR::isError($validation)) {
- return $validation;
- }
-
- // map of MDB2 column types
- $map = $GLOBALS['_DB_TABLE']['mdb2_type'];
-
- // is it a recognized column type?
- $types = array_keys($map);
- if (! in_array($coltype, $types)) {
- return DB_Table::throwError(
- DB_TABLE_ERR_DECLARE_TYPE,
- "('$coltype')"
- );
- }
-
- // build declaration array
- $new_column = array(
- 'type' => $map[$coltype],
- 'notnull' => $require
- );
-
- if ($size) {
- $new_column['length'] = $size;
- }
-
- // determine integer length to be used in MDB2
- if (in_array($coltype, array('smallint', 'integer', 'bigint'))) {
- switch ($coltype) {
- case 'smallint':
- $new_column['length'] = 2;
- break;
- case 'integer':
- $new_column['length'] = 4;
- break;
- case 'bigint':
- $new_column['length'] = 5;
- break;
- }
- }
-
- if ($scope) {
- $max_scope = max($max_scope, $scope);
- }
-
- if ($default) {
- $new_column['default'] = $default;
- }
-
- return $new_column;
- }
-
-
- /**
- *
- * Get the index declaration string for a DB_Table index.
- *
- * @static
- *
- * @access public
- *
- * @param string $phptype The DB phptype key.
- *
- * @param string $type The index type.
- *
- * @param string $idxname The index name.
- *
- * @param string $table The table name.
- *
- * @param mixed $cols Array with the column names for the index.
- *
- * @return string A declaration string.
- *
- */
-
- function getDeclareForIndex($phptype, $type, $idxname, $table, $cols)
- {
- // string of column names
- $colstring = implode(', ', $cols);
-
- switch ($type) {
-
- case 'primary':
- switch ($phptype) {
- case 'ibase':
- case 'oci8':
- case 'pgsql':
- $declare = "ALTER TABLE $table ADD";
- $declare .= " CONSTRAINT $idxname";
- $declare .= " PRIMARY KEY ($colstring)";
- break;
- case 'mysql':
- case 'mysqli':
- $declare = "ALTER TABLE $table ADD PRIMARY KEY";
- $declare .= " ($colstring)";
- break;
- case 'sqlite':
- // currently not possible
- break;
- }
- break;
-
- case 'unique':
- $declare = "CREATE UNIQUE INDEX $idxname ON $table ($colstring)";
- break;
-
- case 'normal':
- $declare = "CREATE INDEX $idxname ON $table ($colstring)";
- break;
-
- }
-
- return $declare;
- }
-
-
- /**
- *
- * Return the definition array for a column.
- *
- * @access private
- *
- * @param string $backend The name of the backend ('db' or 'mdb2').
- *
- * @param string $phptype The DB/MDB2 phptype key.
- *
- * @param mixed $column A single DB_Table column definition array.
- *
- * @return mixed|object Declaration string (DB), declaration array (MDB2) or a
- * PEAR_Error with a description about the invalidity, otherwise.
- *
- */
-
- function _getColumnDefinition($backend, $phptype, $column)
- {
- static $max_scope;
-
- // prepare variables
- $type = (isset($column['type'])) ? $column['type'] : null;
- $size = (isset($column['size'])) ? $column['size'] : null;
- $scope = (isset($column['scope'])) ? $column['scope'] : null;
- $require = (isset($column['require'])) ? $column['require'] : null;
- $default = (isset($column['default'])) ? $column['default'] : null;
-
- if ($backend == 'db') {
- return DB_Table_Manager::getDeclare($phptype, $type,
- $size, $scope, $require, $default);
- } else {
- return DB_Table_Manager::getDeclareMDB2($type,
- $size, $scope, $require, $default, $max_scope);
- }
- }
-
-
- /**
- *
- * Check char/varchar/decimal type declarations for validity.
- *
- * @access private
- *
- * @param string $coltype The DB_Table column type.
- *
- * @param int $size The size for the column (needed for string and
- * decimal).
- *
- * @param int $scope The scope for the column (needed for decimal).
- *
- * @return bool|object Boolean true if the type declaration is valid or a
- * PEAR_Error with a description about the invalidity, otherwise.
- *
- */
-
- function _validateTypeDeclaration($coltype, $size, $scope)
- {
- // validate char and varchar: does it have a size?
- if (($coltype == 'char' || $coltype == 'varchar') &&
- ($size < 1 || $size > 255) ) {
- return DB_Table::throwError(
- DB_TABLE_ERR_DECLARE_STRING,
- "(size='$size')"
- );
- }
-
- // validate decimal: does it have a size and scope?
- if ($coltype == 'decimal' &&
- ($size < 1 || $size > 255 || $scope < 0 || $scope > $size)) {
- return DB_Table::throwError(
- DB_TABLE_ERR_DECLARE_DECIMAL,
- "(size='$size' scope='$scope')"
- );
- }
-
- return true;
- }
-
-
- /**
- *
- * Check a table name for validity.
- *
- * @access private
- *
- * @param string $tablename The table name.
- *
- * @return bool|object Boolean true if the table name is valid or a
- * PEAR_Error with a description about the invalidity, otherwise.
- *
- */
-
- function _validateTableName($tablename)
- {
- // is the table name too long?
- if (strlen($tablename) > 30) {
- return DB_Table::throwError(
- DB_TABLE_ERR_TABLE_STRLEN,
- " ('$tablename')"
- );
- }
-
- return true;
- }
-
-
- /**
- *
- * Check a column name for validity.
- *
- * @access private
- *
- * @param string $colname The column name.
- *
- * @return bool|object Boolean true if the column name is valid or a
- * PEAR_Error with a description about the invalidity, otherwise.
- *
- */
-
- function _validateColumnName($colname)
- {
- // column name cannot be a reserved keyword
- $reserved = in_array(
- strtoupper($colname),
- $GLOBALS['_DB_TABLE']['reserved']
- );
-
- if ($reserved) {
- return DB_Table::throwError(
- DB_TABLE_ERR_DECLARE_COLNAME,
- " ('$colname')"
- );
- }
-
- // column name must be no longer than 30 chars
- if (strlen($colname) > 30) {
- return DB_Table::throwError(
- DB_TABLE_ERR_DECLARE_STRLEN,
- "('$colname')"
- );
- }
-
- return true;
- }
-
-
- /**
- *
- * Check whether a column exists.
- *
- * @access private
- *
- * @param string $colname The column name.
- *
- * @param mixed $tableInfoOrder Array with columns in the table (result
- * from tableInfo(), shortened to key 'order').
- *
- * @param string $mode The name of the calling function, this can be either
- * 'verify' or 'alter'.
- *
- * @return bool|object Boolean true if the column exists.
- * Otherwise, either boolean false (case 'alter') or a PEAR_Error
- * (case 'verify').
- *
- */
-
- function _columnExists($colname, $tableInfoOrder, $mode)
- {
- if (array_key_exists($colname, $tableInfoOrder)) {
- return true;
- }
-
- switch ($mode) {
-
- case 'alter':
- return false;
-
- case 'verify':
- return DB_Table::throwError(
- DB_TABLE_ERR_VER_COLUMN_MISSING,
- "(column='$colname')"
- );
-
- }
- }
-
-
- /**
- *
- * Check whether a column type is a known type.
- *
- * @access private
- *
- * @param string $phptype The DB/MDB2 phptype key.
- *
- * @param string $type The column type.
- *
- * @return bool|object Boolean true if the column type is a known type
- * or a PEAR_Error, otherwise.
- *
- */
-
- function _validateColumnType($phptype, $type)
- {
- // map of valid types for the current RDBMS
- $map = $GLOBALS['_DB_TABLE']['valid_type'][$phptype];
-
- // is it a recognized column type?
- $types = array_keys($map);
- if (!in_array($type, $types)) {
- return DB_Table::throwError(
- DB_TABLE_ERR_DECLARE_TYPE,
- "('" . $type . "')"
- );
- }
-
- return true;
- }
-
-
- /**
- *
- * Check whether a column has the right type.
- *
- * @access private
- *
- * @param string $phptype The DB/MDB2 phptype key.
- *
- * @param string $colname The column name.
- *
- * @param string $coltype The column type.
- *
- * @param mixed $tableInfoOrder Array with columns in the table (result
- * from tableInfo(), shortened to key 'order').
- *
- * @param mixed $tableInfo Array with information about the table (result
- * from tableInfo()).
- *
- * @param string $mode The name of the calling function, this can be either
- * 'verify' or 'alter'.
- *
- * @return bool|object Boolean true if the column has the right type.
- * Otherwise, either boolean false (case 'alter') or a PEAR_Error
- * (case 'verify').
- *
- */
-
- function _checkColumnType($phptype, $colname, $coltype, $tableInfoOrder,
- $tableInfo, $mode)
- {
- // map of valid types for the current RDBMS
- $map = $GLOBALS['_DB_TABLE']['valid_type'][$phptype];
-
- // get the column type from tableInfo()
- $colindex = $tableInfoOrder[$colname];
- $type = strtolower($tableInfo[$colindex]['type']);
-
- // workaround for possibly wrong detected column type (taken from MDB2)
- if ($type == 'unknown' && ($phptype == 'mysql' || $phptype == 'mysqli')) {
- $type = 'decimal';
- }
-
- // strip size information (e.g. NUMERIC(9,2) => NUMERIC) if given
- if (($pos = strpos($type, '(')) !== false) {
- $type = substr($type, 0, $pos);
- }
-
- // is the type valid for the given DB_Table column type?
- if (in_array($type, (array)$map[$coltype])) {
- return true;
- }
-
- switch ($mode) {
-
- case 'alter':
- return false;
-
- case 'verify':
- return DB_Table::throwError(
- DB_TABLE_ERR_VER_COLUMN_TYPE,
- "(column='$colname', type='$type')"
- );
-
- }
- }
-
-
- /**
- *
- * Return the index type and the columns belonging to this index.
- *
- * @access private
- *
- * @param mixed $idx_def The index definition.
- *
- * @return mixed Array with the index type and the columns belonging to
- * this index.
- *
- */
-
- function _getIndexTypeAndColumns($idx_def, $idxname)
- {
- $type = '';
- $cols = '';
- if (is_string($idx_def)) {
- // shorthand for index names: colname => index_type
- $type = trim($idx_def);
- $cols = trim($idxname);
- } elseif (is_array($idx_def)) {
- // normal: index_name => array('type' => ..., 'cols' => ...)
- $type = (isset($idx_def['type'])) ? $idx_def['type'] : 'normal';
- $cols = (isset($idx_def['cols'])) ? $idx_def['cols'] : null;
- }
-
- return array($type, $cols);
- }
-
-
- /**
- *
- * Check an index name for validity.
- *
- * @access private
- *
- * @param string $idxname The index name.
- *
- * @param string $table The table name.
- *
- * @param string $phptype The DB/MDB2 phptype key.
- *
- * @param string $type The index type.
- *
- * @param mixed $cols The column names for the index. Will become an array
- * if it is not an array.
- *
- * @param mixed $column_set A DB_Table $this->col array.
- *
- * @param string $newIdxName The new index name (prefixed with the table
- * name, suffixed with '_idx').
- *
- * @return bool|object Boolean true if the index name is valid or a
- * PEAR_Error with a description about the invalidity, otherwise.
- *
- */
-
- function _validateIndexName($idxname, $table, $phptype, $type, &$cols,
- $column_set, &$newIdxName)
- {
- // index name cannot be a reserved keyword
- $reserved = in_array(
- strtoupper($idxname),
- $GLOBALS['_DB_TABLE']['reserved']
- );
-
- if ($reserved && !($type == 'primary' && $idxname == 'PRIMARY')) {
- return DB_Table::throwError(
- DB_TABLE_ERR_DECLARE_IDXNAME,
- "('$idxname')"
- );
- }
-
- // are there any columns for the index?
- if (! $cols) {
- return DB_Table::throwError(
- DB_TABLE_ERR_IDX_NO_COLS,
- "('$idxname')"
- );
- }
-
- // are there any CLOB columns, or any columns that are not
- // in the schema?
- settype($cols, 'array');
- $valid_cols = array_keys($column_set);
- foreach ($cols as $colname) {
-
- if (! in_array($colname, $valid_cols)) {
- return DB_Table::throwError(
- DB_TABLE_ERR_IDX_COL_UNDEF,
- "'$idxname' ('$colname')"
- );
- }
-
- if ($column_set[$colname]['type'] == 'clob') {
- return DB_Table::throwError(
- DB_TABLE_ERR_IDX_COL_CLOB,
- "'$idxname' ('$colname')"
- );
- }
-
- }
-
- // we prefix all index names with the table name,
- // and suffix all index names with '_idx'. this
- // is to soothe PostgreSQL, which demands that index
- // names not collide, even when they indexes are on
- // different tables.
- $newIdxName = $table . '_' . $idxname . '_idx';
-
- // MySQL requires the primary key to be named 'primary', therefore let's
- // ignore the user defined name
- if (($phptype == 'mysql' || $phptype == 'mysqli') && $type == 'primary') {
- $newIdxName = 'primary';
- }
-
- // now check the length; must be under 30 chars to
- // soothe Oracle.
- if (strlen($newIdxName) > 30) {
- return DB_Table::throwError(
- DB_TABLE_ERR_IDX_STRLEN,
- "'$idxname' ('$newIdxName')"
- );
- }
-
- // check index type
- if ($type != 'primary' && $type != 'unique' && $type != 'normal') {
- return DB_Table::throwError(
- DB_TABLE_ERR_IDX_TYPE,
- "'$idxname' ('$type')"
- );
- }
-
- return true;
- }
-
-
- /**
- *
- * Return all indexes for a table.
- *
- * @access public
- *
- * @param object &$db A PEAR DB/MDB2 object.
- *
- * @param string $table The table name.
- *
- * @return mixed Array with all indexes or a PEAR_Error when an error
- * occured.
- *
- */
-
- function getIndexes(&$db, $table)
- {
- if (is_subclass_of($db, 'db_common')) {
- $backend = 'db';
- // workaround for missing index and constraint information methods
- // in PEAR::DB ==> use adopted code from MDB2's driver classes
- require_once 'DB/Table/Manager/' . $db->phptype . '.php';
- $classname = 'DB_Table_Manager_' . $db->phptype;
- $dbtm =& new $classname();
- $dbtm->_db =& $db; // pass database instance to the 'workaround' class
- $manager =& $dbtm;
- $reverse =& $dbtm;
- } elseif (is_subclass_of($db, 'mdb2_driver_common')) {
- $backend = 'mdb2';
- $manager =& $db->manager;
- $reverse =& $db->reverse;
- }
-
- $indexes = array('normal' => array(),
- 'primary' => array(),
- 'unique' => array()
- );
-
- // save user defined 'idxname_format' option (MDB2 only)
- if ($backend == 'mdb2') {
- $idxname_format = $db->getOption('idxname_format');
- $db->setOption('idxname_format', '%s');
- }
-
- // get table constraints
- $table_indexes_tmp = $manager->listTableConstraints($table);
- if (PEAR::isError($table_indexes_tmp)) {
- // restore user defined 'idxname_format' option (MDB2 only)
- if ($backend == 'mdb2') {
- $db->setOption('idxname_format', $idxname_format);
- }
- return $table_indexes_tmp;
- }
-
- // get fields of table constraints
- foreach ($table_indexes_tmp as $table_idx_tmp) {
- $index_fields = $reverse->getTableConstraintDefinition($table,
- $table_idx_tmp);
- if (PEAR::isError($index_fields)) {
- // restore user defined 'idxname_format' option (MDB2 only)
- if ($backend == 'mdb2') {
- $db->setOption('idxname_format', $idxname_format);
- }
- return $index_fields;
- }
- // get the first key of $index_fields that has boolean true value
- foreach ($index_fields as $index_type => $value) {
- if ($value === true) {
- break;
- }
- }
- $indexes[$index_type][$table_idx_tmp] = array_keys($index_fields['fields']);
- }
-
- // get table indexes
- $table_indexes_tmp = $manager->listTableIndexes($table);
- if (PEAR::isError($table_indexes_tmp)) {
- // restore user defined 'idxname_format' option (MDB2 only)
- if ($backend == 'mdb2') {
- $db->setOption('idxname_format', $idxname_format);
- }
- return $table_indexes_tmp;
- }
-
- // get fields of table indexes
- foreach ($table_indexes_tmp as $table_idx_tmp) {
- $index_fields = $reverse->getTableIndexDefinition($table,
- $table_idx_tmp);
- if (PEAR::isError($index_fields)) {
- // restore user defined 'idxname_format' option (MDB2 only)
- if ($backend == 'mdb2') {
- $db->setOption('idxname_format', $idxname_format);
- }
- return $index_fields;
- }
- $indexes['normal'][$table_idx_tmp] = array_keys($index_fields['fields']);
- }
-
- // restore user defined 'idxname_format' option (MDB2 only)
- if ($backend == 'mdb2') {
- $db->setOption('idxname_format', $idxname_format);
- }
-
- return $indexes;
- }
-
-
- /**
- *
- * Check whether an index has the right type and has all specified columns.
- *
- * @access private
- *
- * @param string $idxname The index name.
- *
- * @param string $newIdxName The prefixed and suffixed index name.
- *
- * @param string $type The index type.
- *
- * @param mixed $cols The column names for the index.
- *
- * @param mixed $table_indexes Array with all indexes of the table.
- *
- * @param string $mode The name of the calling function, this can be either
- * 'verify' or 'alter'.
- *
- * @return bool|object Boolean true if the index has the right type and all
- * specified columns. Otherwise, either boolean false (case 'alter') or a
- * PEAR_Error (case 'verify').
- *
- */
-
- function _checkIndex($idxname, $newIdxName, $type, $cols, &$table_indexes, $mode)
- {
- $index_found = false;
-
- foreach ($table_indexes[$type] as $index_name => $index_fields) {
- if (strtolower($index_name) == strtolower($newIdxName)) {
- $index_found = true;
- array_walk($cols, create_function('&$value,$key',
- '$value = trim(strtolower($value));'));
- array_walk($index_fields, create_function('&$value,$key',
- '$value = trim(strtolower($value));'));
- foreach ($index_fields as $index_field) {
- if (($key = array_search($index_field, $cols)) !== false) {
- unset($cols[$key]);
- }
- }
- break;
- }
- }
-
- if (!$index_found) {
- return ($mode == 'alter') ? false : DB_Table::throwError(
- DB_TABLE_ERR_VER_IDX_MISSING,
- "'$idxname' ('$newIdxName')"
- );
- }
-
- if (count($cols) > 0) {
- // string of column names
- $colstring = implode(', ', $cols);
- return ($mode == 'alter') ? false : DB_Table::throwError(
- DB_TABLE_ERR_VER_IDX_COL_MISSING,
- "'$idxname' ($colstring)"
- );
- }
-
- return true;
- }
-
-
- /**
- *
- * Create indexes and contraints.
- *
- * @access private
- *
- * @param object &$db A PEAR DB/MDB2 object.
- *
- * @param string $backend The name of the backend ('db' or 'mdb2').
- *
- * @param string $table The table name.
- *
- * @param mixed $indexes An array with index and constraint definitions.
- *
- * @return bool|object Boolean true on success or a PEAR_Error with a
- * description about the invalidity, otherwise.
- *
- */
-
- function _createIndexesAndContraints($db, $backend, $table, $indexes)
- {
- if ($backend == 'mdb2') {
-
- // save user defined 'idxname_format' option
- $idxname_format = $db->getOption('idxname_format');
- $db->setOption('idxname_format', '%s');
-
- // attempt to create the primary key
- if (!array_key_exists('primary', $indexes)) {
- $indexes['primary'] = array();
- }
- foreach ($indexes['primary'] as $name => $definition) {
- $result = $db->manager->createConstraint($table, $name, $definition);
- if (PEAR::isError($result)) {
- // restore user defined 'idxname_format' option
- $db->setOption('idxname_format', $idxname_format);
- return $result;
- }
- }
-
- // attempt to create the unique indexes / constraints
- if (!array_key_exists('unique', $indexes)) {
- $indexes['unique'] = array();
- }
- foreach ($indexes['unique'] as $name => $definition) {
- $result = $db->manager->createConstraint($table, $name, $definition);
- if (PEAR::isError($result)) {
- // restore user defined 'idxname_format' option
- $db->setOption('idxname_format', $idxname_format);
- return $result;
- }
- }
-
- // attempt to create the normal indexes
- if (!array_key_exists('normal', $indexes)) {
- $indexes['normal'] = array();
- }
- foreach ($indexes['normal'] as $name => $definition) {
- $result = $db->manager->createIndex($table, $name, $definition);
- if (PEAR::isError($result)) {
- // restore user defined 'idxname_format' option
- $db->setOption('idxname_format', $idxname_format);
- return $result;
- }
- }
-
- // restore user defined 'idxname_format' option
- $db->setOption('idxname_format', $idxname_format);
-
- } else {
-
- // attempt to create the indexes
- foreach ($indexes as $cmd) {
- $result = $db->query($cmd);
- if (PEAR::isError($result)) {
- return $result;
- }
- }
-
- }
-
- return true;
-
- }
-
- }
-
-
- /**
- * List of all reserved words for all supported databases. Yes, this is a
- * monster of a list.
- */
- if (! isset($GLOBALS['_DB_TABLE']['reserved'])) {
- $GLOBALS['_DB_TABLE']['reserved'] = array(
- '_ROWID_',
- 'ABSOLUTE',
- 'ACCESS',
- 'ACTION',
- 'ADD',
- 'ADMIN',
- 'AFTER',
- 'AGGREGATE',
- 'ALIAS',
- 'ALL',
- 'ALLOCATE',
- 'ALTER',
- 'ANALYSE',
- 'ANALYZE',
- 'AND',
- 'ANY',
- 'ARE',
- 'ARRAY',
- 'AS',
- 'ASC',
- 'ASENSITIVE',
- 'ASSERTION',
- 'AT',
- 'AUDIT',
- 'AUTHORIZATION',
- 'AUTO_INCREMENT',
- 'AVG',
- 'BACKUP',
- 'BDB',
- 'BEFORE',
- 'BEGIN',
- 'BERKELEYDB',
- 'BETWEEN',
- 'BIGINT',
- 'BINARY',
- 'BIT',
- 'BIT_LENGTH',
- 'BLOB',
- 'BOOLEAN',
- 'BOTH',
- 'BREADTH',
- 'BREAK',
- 'BROWSE',
- 'BULK',
- 'BY',
- 'CALL',
- 'CASCADE',
- 'CASCADED',
- 'CASE',
- 'CAST',
- 'CATALOG',
- 'CHANGE',
- 'CHAR',
- 'CHAR_LENGTH',
- 'CHARACTER',
- 'CHARACTER_LENGTH',
- 'CHECK',
- 'CHECKPOINT',
- 'CLASS',
- 'CLOB',
- 'CLOSE',
- 'CLUSTER',
- 'CLUSTERED',
- 'COALESCE',
- 'COLLATE',
- 'COLLATION',
- 'COLUMN',
- 'COLUMNS',
- 'COMMENT',
- 'COMMIT',
- 'COMPLETION',
- 'COMPRESS',
- 'COMPUTE',
- 'CONDITION',
- 'CONNECT',
- 'CONNECTION',
- 'CONSTRAINT',
- 'CONSTRAINTS',
- 'CONSTRUCTOR',
- 'CONTAINS',
- 'CONTAINSTABLE',
- 'CONTINUE',
- 'CONVERT',
- 'CORRESPONDING',
- 'COUNT',
- 'CREATE',
- 'CROSS',
- 'CUBE',
- 'CURRENT',
- 'CURRENT_DATE',
- 'CURRENT_PATH',
- 'CURRENT_ROLE',
- 'CURRENT_TIME',
- 'CURRENT_TIMESTAMP',
- 'CURRENT_USER',
- 'CURSOR',
- 'CYCLE',
- 'DATA',
- 'DATABASE',
- 'DATABASES',
- 'DATE',
- 'DAY',
- 'DAY_HOUR',
- 'DAY_MICROSECOND',
- 'DAY_MINUTE',
- 'DAY_SECOND',
- 'DBCC',
- 'DEALLOCATE',
- 'DEC',
- 'DECIMAL',
- 'DECLARE',
- 'DEFAULT',
- 'DEFERRABLE',
- 'DEFERRED',
- 'DELAYED',
- 'DELETE',
- 'DENY',
- 'DEPTH',
- 'DEREF',
- 'DESC',
- 'DESCRIBE',
- 'DESCRIPTOR',
- 'DESTROY',
- 'DESTRUCTOR',
- 'DETERMINISTIC',
- 'DIAGNOSTICS',
- 'DICTIONARY',
- 'DISCONNECT',
- 'DISK',
- 'DISTINCT',
- 'DISTINCTROW',
- 'DISTRIBUTED',
- 'DIV',
- 'DO',
- 'DOMAIN',
- 'DOUBLE',
- 'DROP',
- 'DUMMY',
- 'DUMP',
- 'DYNAMIC',
- 'EACH',
- 'ELSE',
- 'ELSEIF',
- 'ENCLOSED',
- 'END',
- 'END-EXEC',
- 'EQUALS',
- 'ERRLVL',
- 'ESCAPE',
- 'ESCAPED',
- 'EVERY',
- 'EXCEPT',
- 'EXCEPTION',
- 'EXCLUSIVE',
- 'EXEC',
- 'EXECUTE',
- 'EXISTS',
- 'EXIT',
- 'EXPLAIN',
- 'EXTERNAL',
- 'EXTRACT',
- 'FALSE',
- 'FETCH',
- 'FIELDS',
- 'FILE',
- 'FILLFACTOR',
- 'FIRST',
- 'FLOAT',
- 'FOR',
- 'FORCE',
- 'FOREIGN',
- 'FOUND',
- 'FRAC_SECOND',
- 'FREE',
- 'FREETEXT',
- 'FREETEXTTABLE',
- 'FREEZE',
- 'FROM',
- 'FULL',
- 'FULLTEXT',
- 'FUNCTION',
- 'GENERAL',
- 'GET',
- 'GLOB',
- 'GLOBAL',
- 'GO',
- 'GOTO',
- 'GRANT',
- 'GROUP',
- 'GROUPING',
- 'HAVING',
- 'HIGH_PRIORITY',
- 'HOLDLOCK',
- 'HOST',
- 'HOUR',
- 'HOUR_MICROSECOND',
- 'HOUR_MINUTE',
- 'HOUR_SECOND',
- 'IDENTIFIED',
- 'IDENTITY',
- 'IDENTITY_INSERT',
- 'IDENTITYCOL',
- 'IF',
- 'IGNORE',
- 'ILIKE',
- 'IMMEDIATE',
- 'IN',
- 'INCREMENT',
- 'INDEX',
- 'INDICATOR',
- 'INFILE',
- 'INITIAL',
- 'INITIALIZE',
- 'INITIALLY',
- 'INNER',
- 'INNODB',
- 'INOUT',
- 'INPUT',
- 'INSENSITIVE',
- 'INSERT',
- 'INT',
- 'INTEGER',
- 'INTERSECT',
- 'INTERVAL',
- 'INTO',
- 'IO_THREAD',
- 'IS',
- 'ISNULL',
- 'ISOLATION',
- 'ITERATE',
- 'JOIN',
- 'KEY',
- 'KEYS',
- 'KILL',
- 'LANGUAGE',
- 'LARGE',
- 'LAST',
- 'LATERAL',
- 'LEADING',
- 'LEAVE',
- 'LEFT',
- 'LESS',
- 'LEVEL',
- 'LIKE',
- 'LIMIT',
- 'LINENO',
- 'LINES',
- 'LOAD',
- 'LOCAL',
- 'LOCALTIME',
- 'LOCALTIMESTAMP',
- 'LOCATOR',
- 'LOCK',
- 'LONG',
- 'LONGBLOB',
- 'LONGTEXT',
- 'LOOP',
- 'LOW_PRIORITY',
- 'LOWER',
- 'MAIN',
- 'MAP',
- 'MASTER_SERVER_ID',
- 'MATCH',
- 'MAX',
- 'MAXEXTENTS',
- 'MEDIUMBLOB',
- 'MEDIUMINT',
- 'MEDIUMTEXT',
- 'MIDDLEINT',
- 'MIN',
- 'MINUS',
- 'MINUTE',
- 'MINUTE_MICROSECOND',
- 'MINUTE_SECOND',
- 'MLSLABEL',
- 'MOD',
- 'MODE',
- 'MODIFIES',
- 'MODIFY',
- 'MODULE',
- 'MONTH',
- 'NAMES',
- 'NATIONAL',
- 'NATURAL',
- 'NCHAR',
- 'NCLOB',
- 'NEW',
- 'NEXT',
- 'NO',
- 'NO_WRITE_TO_BINLOG',
- 'NOAUDIT',
- 'NOCHECK',
- 'NOCOMPRESS',
- 'NONCLUSTERED',
- 'NONE',
- 'NOT',
- 'NOTNULL',
- 'NOWAIT',
- 'NULL',
- 'NULLIF',
- 'NUMBER',
- 'NUMERIC',
- 'OBJECT',
- 'OCTET_LENGTH',
- 'OF',
- 'OFF',
- 'OFFLINE',
- 'OFFSET',
- 'OFFSETS',
- 'OID',
- 'OLD',
- 'ON',
- 'ONLINE',
- 'ONLY',
- 'OPEN',
- 'OPENDATASOURCE',
- 'OPENQUERY',
- 'OPENROWSET',
- 'OPENXML',
- 'OPERATION',
- 'OPTIMIZE',
- 'OPTION',
- 'OPTIONALLY',
- 'OR',
- 'ORDER',
- 'ORDINALITY',
- 'OUT',
- 'OUTER',
- 'OUTFILE',
- 'OUTPUT',
- 'OVER',
- 'OVERLAPS',
- 'PAD',
- 'PARAMETER',
- 'PARAMETERS',
- 'PARTIAL',
- 'PATH',
- 'PCTFREE',
- 'PERCENT',
- 'PLACING',
- 'PLAN',
- 'POSITION',
- 'POSTFIX',
- 'PRECISION',
- 'PREFIX',
- 'PREORDER',
- 'PREPARE',
- 'PRESERVE',
- 'PRIMARY',
- 'PRINT',
- 'PRIOR',
- 'PRIVILEGES',
- 'PROC',
- 'PROCEDURE',
- 'PUBLIC',
- 'PURGE',
- 'RAISERROR',
- 'RAW',
- 'READ',
- 'READS',
- 'READTEXT',
- 'REAL',
- 'RECONFIGURE',
- 'RECURSIVE',
- 'REF',
- 'REFERENCES',
- 'REFERENCING',
- 'REGEXP',
- 'RELATIVE',
- 'RENAME',
- 'REPEAT',
- 'REPLACE',
- 'REPLICATION',
- 'REQUIRE',
- 'RESOURCE',
- 'RESTORE',
- 'RESTRICT',
- 'RESULT',
- 'RETURN',
- 'RETURNS',
- 'REVOKE',
- 'RIGHT',
- 'RLIKE',
- 'ROLE',
- 'ROLLBACK',
- 'ROLLUP',
- 'ROUTINE',
- 'ROW',
- 'ROWCOUNT',
- 'ROWGUIDCOL',
- 'ROWID',
- 'ROWNUM',
- 'ROWS',
- 'RULE',
- 'SAVE',
- 'SAVEPOINT',
- 'SCHEMA',
- 'SCOPE',
- 'SCROLL',
- 'SEARCH',
- 'SECOND',
- 'SECOND_MICROSECOND',
- 'SECTION',
- 'SELECT',
- 'SENSITIVE',
- 'SEPARATOR',
- 'SEQUENCE',
- 'SESSION',
- 'SESSION_USER',
- 'SET',
- 'SETS',
- 'SETUSER',
- 'SHARE',
- 'SHOW',
- 'SHUTDOWN',
- 'SIMILAR',
- 'SIZE',
- 'SMALLINT',
- 'SOME',
- 'SONAME',
- 'SPACE',
- 'SPATIAL',
- 'SPECIFIC',
- 'SPECIFICTYPE',
- 'SQL',
- 'SQL_BIG_RESULT',
- 'SQL_CALC_FOUND_ROWS',
- 'SQL_SMALL_RESULT',
- 'SQL_TSI_DAY',
- 'SQL_TSI_FRAC_SECOND',
- 'SQL_TSI_HOUR',
- 'SQL_TSI_MINUTE',
- 'SQL_TSI_MONTH',
- 'SQL_TSI_QUARTER',
- 'SQL_TSI_SECOND',
- 'SQL_TSI_WEEK',
- 'SQL_TSI_YEAR',
- 'SQLCODE',
- 'SQLERROR',
- 'SQLEXCEPTION',
- 'SQLITE_MASTER',
- 'SQLITE_TEMP_MASTER',
- 'SQLSTATE',
- 'SQLWARNING',
- 'SSL',
- 'START',
- 'STARTING',
- 'STATE',
- 'STATEMENT',
- 'STATIC',
- 'STATISTICS',
- 'STRAIGHT_JOIN',
- 'STRIPED',
- 'STRUCTURE',
- 'SUBSTRING',
- 'SUCCESSFUL',
- 'SUM',
- 'SYNONYM',
- 'SYSDATE',
- 'SYSTEM_USER',
- 'TABLE',
- 'TABLES',
- 'TEMPORARY',
- 'TERMINATE',
- 'TERMINATED',
- 'TEXTSIZE',
- 'THAN',
- 'THEN',
- 'TIME',
- 'TIMESTAMP',
- 'TIMESTAMPADD',
- 'TIMESTAMPDIFF',
- 'TIMEZONE_HOUR',
- 'TIMEZONE_MINUTE',
- 'TINYBLOB',
- 'TINYINT',
- 'TINYTEXT',
- 'TO',
- 'TOP',
- 'TRAILING',
- 'TRAN',
- 'TRANSACTION',
- 'TRANSLATE',
- 'TRANSLATION',
- 'TREAT',
- 'TRIGGER',
- 'TRIM',
- 'TRUE',
- 'TRUNCATE',
- 'TSEQUAL',
- 'UID',
- 'UNDER',
- 'UNDO',
- 'UNION',
- 'UNIQUE',
- 'UNKNOWN',
- 'UNLOCK',
- 'UNNEST',
- 'UNSIGNED',
- 'UPDATE',
- 'UPDATETEXT',
- 'UPPER',
- 'USAGE',
- 'USE',
- 'USER',
- 'USER_RESOURCES',
- 'USING',
- 'UTC_DATE',
- 'UTC_TIME',
- 'UTC_TIMESTAMP',
- 'VALIDATE',
- 'VALUE',
- 'VALUES',
- 'VARBINARY',
- 'VARCHAR',
- 'VARCHAR2',
- 'VARCHARACTER',
- 'VARIABLE',
- 'VARYING',
- 'VERBOSE',
- 'VIEW',
- 'WAITFOR',
- 'WHEN',
- 'WHENEVER',
- 'WHERE',
- 'WHILE',
- 'WITH',
- 'WITHOUT',
- 'WORK',
- 'WRITE',
- 'WRITETEXT',
- 'XOR',
- 'YEAR',
- 'YEAR_MONTH',
- 'ZEROFILL',
- 'ZONE',
- );
- }
-
- ?>
-