示例#1
0
 /**
  * 
  * 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;
 }