diff --git a/etemplate/inc/class.db_tools.inc.php b/etemplate/inc/class.db_tools.inc.php index 38d13dacbf..76c935e07e 100644 --- a/etemplate/inc/class.db_tools.inc.php +++ b/etemplate/inc/class.db_tools.inc.php @@ -188,7 +188,8 @@ } else // import { - $oProc = CreateObject('phpgwapi.schema_proc',$GLOBALS['phpgw_info']['server']['db_type']); + $schema_app = $this->editor->stable ? 'etemplate' : 'phpgwapi'; // this is for 0.9.14 + $oProc = CreateObject($schema_app.'.schema_proc',$GLOBALS['phpgw_info']['server']['db_type']); $oProc->m_odb = $GLOBALS['phpgw']->db; $oProc->m_oTranslator->_GetColumns($oProc,$content['new_table_name'],$nul); diff --git a/etemplate/inc/class.schema_proc.inc.php b/etemplate/inc/class.schema_proc.inc.php new file mode 100644 index 0000000000..eccec6f869 --- /dev/null +++ b/etemplate/inc/class.schema_proc.inc.php @@ -0,0 +1,455 @@ + * + * and Miles Lott * + * -------------------------------------------- * + * This program is free software; you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; either version 2 of the License, or (at your * + * option) any later version. * + \**************************************************************************/ + + /* $Id$ */ + + class schema_proc + { + var $m_oTranslator; + var $m_oDeltaProc; + var $m_odb; + var $m_aTables; + var $m_bDeltaOnly; + + function schema_proc($dbms) + { + $this->m_oTranslator = CreateObject('etemplate.schema_proc_' . $dbms); + $this->m_oDeltaProc = CreateObject('etemplate.schema_proc_array'); + $this->m_aTables = array(); + $this->m_bDeltaOnly = False; // Default to false here in case it's just a CreateTable script + } + + function GenerateScripts($aTables, $bOutputHTML=False) + { + if (!is_array($aTables)) + { + return False; + } + + $this->m_aTables = $aTables; + + reset($this->m_aTables); + $sAllTableSQL = ''; + while (list($sTableName, $aTableDef) = each($this->m_aTables)) + { + $sSequenceSQL = ''; + if($this->_GetTableSQL($sTableName, $aTableDef, $sTableSQL, $sSequenceSQL)) + { + $sTableSQL = "CREATE TABLE $sTableName (\n$sTableSQL\n)" + . $this->m_oTranslator->m_sStatementTerminator; + if($sSequenceSQL != '') + { + $sAllTableSQL .= $sSequenceSQL . "\n"; + } + $sAllTableSQL .= $sTableSQL . "\n\n"; + } + else + { + if($bOutputHTML) + { + print('
Failed generating script for ' . $sTableName . '
'); + } + + return false; + } + } + + if($bOutputHTML) + { + print('
' . $sAllTableSQL . '


'); + } + + return True; + } + + function ExecuteScripts($aTables, $bOutputHTML=False) + { + if(!is_array($aTables) || !IsSet($this->m_odb)) + { + return False; + } + + reset($aTables); + $this->m_aTables = $aTables; + + while(list($sTableName, $aTableDef) = each($aTables)) + { + if($this->CreateTable($sTableName, $aTableDef)) + { + if($bOutputHTML) + { + echo '
Create Table ' . $sTableName . ''; + } + } + else + { + if($bOutputHTML) + { + echo '
Create Table Failed For ' . $sTableName . ''; + } + + return False; + } + } + + return True; + } + + function DropAllTables($aTables, $bOutputHTML=False) + { + if(!is_array($aTables) || !isset($this->m_odb)) + { + return False; + } + + $this->m_aTables = $aTables; + + reset($this->m_aTables); + while(list($sTableName, $aTableDef) = each($this->m_aTables)) + { + if($this->DropTable($sTableName)) + { + if($bOutputHTML) + { + echo '
Drop Table ' . $sTableSQL . ''; + } + } + else + { + return False; + } + } + + return True; + } + + function DropTable($sTableName) + { + $retVal = $this->m_oDeltaProc->DropTable($this, $this->m_aTables, $sTableName); + if($this->m_bDeltaOnly) + { + return $retVal; + } + + return $retVal && $this->m_oTranslator->DropTable($this, $this->m_aTables, $sTableName); + } + + function DropColumn($sTableName, $aTableDef, $sColumnName, $bCopyData = true) + { + $retVal = $this->m_oDeltaProc->DropColumn($this, $this->m_aTables, $sTableName, $aTableDef, $sColumnName, $bCopyData); + if($this->m_bDeltaOnly) + { + return $retVal; + } + + return $retVal && $this->m_oTranslator->DropColumn($this, $this->m_aTables, $sTableName, $aTableDef, $sColumnName, $bCopyData); + } + + function RenameTable($sOldTableName, $sNewTableName) + { + $retVal = $this->m_oDeltaProc->RenameTable($this, $this->m_aTables, $sOldTableName, $sNewTableName); + if($this->m_bDeltaOnly) + { + return $retVal; + } + + return $retVal && $this->m_oTranslator->RenameTable($this, $this->m_aTables, $sOldTableName, $sNewTableName); + } + + function RenameColumn($sTableName, $sOldColumnName, $sNewColumnName, $bCopyData=True) + { + $retVal = $this->m_oDeltaProc->RenameColumn($this, $this->m_aTables, $sTableName, $sOldColumnName, $sNewColumnName, $bCopyData); + if($this->m_bDeltaOnly) + { + return $retVal; + } + + return $retVal && $this->m_oTranslator->RenameColumn($this, $this->m_aTables, $sTableName, $sOldColumnName, $sNewColumnName, $bCopyData); + } + + function AlterColumn($sTableName, $sColumnName, $aColumnDef, $bCopyData=True) + { + $retVal = $this->m_oDeltaProc->AlterColumn($this, $this->m_aTables, $sTableName, $sColumnName, $aColumnDef, $bCopyData); + if($this->m_bDeltaOnly) + { + return $retVal; + } + + return $retVal && $this->m_oTranslator->AlterColumn($this, $this->m_aTables, $sTableName, $sColumnName, $aColumnDef, $bCopyData); + } + + function AddColumn($sTableName, $sColumnName, $aColumnDef) + { + $retVal = $this->m_oDeltaProc->AddColumn($this, $this->m_aTables, $sTableName, $sColumnName, $aColumnDef); + if($this->m_bDeltaOnly) + { + return $retVal; + } + + return $retVal && $this->m_oTranslator->AddColumn($this, $this->m_aTables, $sTableName, $sColumnName, $aColumnDef); + } + + function CreateTable($sTableName, $aTableDef) + { + $retVal = $this->m_oDeltaProc->CreateTable($this, $this->m_aTables, $sTableName, $aTableDef); + if($this->m_bDeltaOnly) + { + return $retVal; + } + + return $retVal && $this->m_oTranslator->CreateTable($this, $this->m_aTables, $sTableName, $aTableDef); + } + + function f($value) + { + if($this->m_bDeltaOnly) + { + // Don't care, since we are processing deltas only + return False; + } + + return $this->m_odb->f($value); + } + + function num_rows() + { + if($this->m_bDeltaOnly) + { + // If not False, we will cause while loops calling us to hang + return False; + } + + return $this->m_odb->num_rows(); + } + + function next_record() + { + if($this->m_bDeltaOnly) + { + // If not False, we will cause while loops calling us to hang + return False; + } + + return $this->m_odb->next_record(); + } + + function query($sQuery, $line='', $file='') + { + if($this->m_bDeltaOnly) + { + // Don't run this query, since we are processing deltas only + return True; + } + + return $this->m_odb->query($sQuery, $line, $file); + } + + function _GetTableSQL($sTableName, $aTableDef, &$sTableSQL, &$sSequenceSQL) + { + global $DEBUG; + + if(!is_array($aTableDef)) + { + return False; + } + + $sTableSQL = ''; + reset($aTableDef['fd']); + while(list($sFieldName, $aFieldAttr) = each($aTableDef['fd'])) + { + $sFieldSQL = ''; + if($this->_GetFieldSQL($aFieldAttr, $sFieldSQL)) + { + if($sTableSQL != '') + { + $sTableSQL .= ",\n"; + } + + $sTableSQL .= "$sFieldName $sFieldSQL"; + + if($aFieldAttr['type'] == 'auto') + { + $this->m_oTranslator->GetSequenceSQL($sTableName, $sSequenceSQL); + if($sSequenceSQL != '') + { + $sTableSQL .= sprintf(" DEFAULT nextval('seq_%s')", $sTableName); + } + } + } + else + { + if($DEBUG) { echo 'GetFieldSQL failed for ' . $sFieldName; } + return False; + } + } + + $sUCSQL = ''; + $sPKSQL = ''; + + if(count($aTableDef['pk']) > 0) + { + if(!$this->_GetPK($aTableDef['pk'], $sPKSQL)) + { + if($bOutputHTML) + { + print('
Failed getting primary key
'); + } + + return False; + } + } + + if(count($aTableDef['uc']) > 0) + { + if(!$this->_GetUC($aTableDef['uc'], $sUCSQL)) + { + if($bOutputHTML) + { + print('
Failed getting unique constraint
'); + } + + return False; + } + } + + if($sPKSQL != '') + { + $sTableSQL .= ",\n" . $sPKSQL; + } + + if($sUCSQL != '') + { + $sTableSQL .= ",\n" . $sUCSQL; + } + + return True; + } + + // Get field DDL + function _GetFieldSQL($aField, &$sFieldSQL) + { + global $DEBUG; + if($DEBUG) { echo'
_GetFieldSQL(): Incoming ARRAY: '; var_dump($aField); } + if(!is_array($aField)) + { + return false; + } + + $sType = ''; + $iPrecision = 0; + $iScale = 0; + $sDefault = ''; + $bNullable = true; + + reset($aField); + while(list($sAttr, $vAttrVal) = each($aField)) + { + switch ($sAttr) + { + case 'type': + $sType = $vAttrVal; + break; + case 'precision': + $iPrecision = (int)$vAttrVal; + break; + case 'scale': + $iScale = (int)$vAttrVal; + break; + case 'default': + $sDefault = $vAttrVal; + if($DEBUG) { echo'
_GetFieldSQL(): Default="' . $sDefault . '"'; } + break; + case 'nullable': + $bNullable = $vAttrVal; + break; + } + } + + // Translate the type for the DBMS + if($sFieldSQL = $this->m_oTranslator->TranslateType($sType, $iPrecision, $iScale)) + { + if($bNullable == False) + { + $sFieldSQL .= ' NOT NULL'; + } + + if($sDefault != '') + { + if($DEBUG) { echo'
_GetFieldSQL(): Calling TranslateDefault for "' . $sDefault . '"'; } + // Get default DDL - useful for differences in date defaults (eg, now() vs. getdate()) + $sTranslatedDefault = $this->m_oTranslator->TranslateDefault($sDefault); + $sFieldSQL .= " DEFAULT '$sTranslatedDefault'"; + } + elseif($sDefault == '0') + { + $sFieldSQL .= " DEFAULT '0'"; + } + if($DEBUG) { echo'
_GetFieldSQL(): Outgoing SQL: ' . $sFieldSQL; } + return true; + } + + if($DEBUG) { echo '
Failed to translate field: type[' . $sType . '] precision[' . $iPrecision . '] scale[' . $iScale . ']
'; } + + return False; + } + + function _GetPK($aFields, &$sPKSQL) + { + $sPKSQL = ''; + if(count($aFields) < 1) + { + return True; + } + + $sFields = ''; + reset($aFields); + while(list($key, $sField) = each($aFields)) + { + if($sFields != '') + { + $sFields .= ','; + } + $sFields .= $sField; + } + + $sPKSQL = $this->m_oTranslator->GetPKSQL($sFields); + + return True; + } + + function _GetUC($aFields, &$sUCSQL) + { + $sUCSQL = ''; + if(count($aFields) < 1) + { + return True; + } + + $sFields = ''; + reset($aFields); + while(list($key,$sField) = each($aFields)) + { + if($sFields != '') + { + $sFields .= ','; + } + $sFields .= $sField; + } + + $sUCSQL = $this->m_oTranslator->GetUCSQL($sFields); + + return True; + } + } +?> diff --git a/etemplate/inc/class.schema_proc_array.inc.php b/etemplate/inc/class.schema_proc_array.inc.php new file mode 100644 index 0000000000..02349c8483 --- /dev/null +++ b/etemplate/inc/class.schema_proc_array.inc.php @@ -0,0 +1,184 @@ + * + * and Miles Lott * + * -------------------------------------------- * + * This program is free software; you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; either version 2 of the License, or (at your * + * option) any later version. * + \**************************************************************************/ + + /* $Id$ */ + + class schema_proc_array + { + var $m_sStatementTerminator; + + function schema_proc_array() + { + $this->m_sStatementTerminator = ';'; + } + + /* Return a type suitable for DDL abstracted array */ + function TranslateType($sType, $iPrecision = 0, $iScale = 0) + { + $sTranslated = $sType; + return $sTranslated; + } + + function TranslateDefault($sDefault) + { + return $sDefault; + } + + function GetPKSQL($sFields) + { + return ''; + } + + function GetUCSQL($sFields) + { + return ''; + } + + function _GetColumns($oProc, &$aTables, $sTableName, &$sColumns, $sDropColumn='') + { + $sColumns = ''; + while(list($sName, $aJunk) = each($aTables[$sTableName]['fd'])) + { + if($sColumns != '') + { + $sColumns .= ','; + } + $sColumns .= $sName; + } + + return True; + } + + function DropTable($oProc, &$aTables, $sTableName) + { + if(isset($aTables[$sTableName])) + { + unset($aTables[$sTableName]); + } + + return True; + } + + function DropColumn($oProc, &$aTables, $sTableName, $aNewTableDef, $sColumnName, $bCopyData=True) + { + if(isset($aTables[$sTableName])) + { + if(isset($aTables[$sTableName]['fd'][$sColumnName])) + { + unset($aTables[$sTableName]['fd'][$sColumnName]); + } + } + + return True; + } + + function RenameTable($oProc, &$aTables, $sOldTableName, $sNewTableName) + { + $aNewTables = array(); + while(list($sTableName, $aTableDef) = each($aTables)) + { + if($sTableName == $sOldTableName) + { + $aNewTables[$sNewTableName] = $aTableDef; + } + else + { + $aNewTables[$sTableName] = $aTableDef; + } + } + + $aTables = $aNewTables; + + return True; + } + + function RenameColumn($oProc, &$aTables, $sTableName, $sOldColumnName, $sNewColumnName, $bCopyData=True) + { + if (isset($aTables[$sTableName])) + { + $aNewTableDef = array(); + reset($aTables[$sTableName]['fd']); + while(list($sColumnName, $aColumnDef) = each($aTables[$sTableName]['fd'])) + { + if($sColumnName == $sOldColumnName) + { + $aNewTableDef[$sNewColumnName] = $aColumnDef; + } + else + { + $aNewTableDef[$sColumnName] = $aColumnDef; + } + } + + $aTables[$sTableName]['fd'] = $aNewTableDef; + + reset($aTables[$sTableName]['pk']); + while(list($key, $sColumnName) = each($aTables[$sTableName]['pk'])) + { + if($sColumnName == $sOldColumnName) + { + $aTables[$sTableName]['pk'][$key] = $sNewColumnName; + } + } + + reset($aTables[$sTableName]['uc']); + while(list($key, $sColumnName) = each($aTables[$sTableName]['uc'])) + { + if($sColumnName == $sOldColumnName) + { + $aTables[$sTableName]['uc'][$key] = $sNewColumnName; + } + } + } + + return True; + } + + function AlterColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef, $bCopyData=True) + { + if(isset($aTables[$sTableName])) + { + if(isset($aTables[$sTableName]['fd'][$sColumnName])) + { + $aTables[$sTableName]['fd'][$sColumnName] = $aColumnDef; + } + } + + return Rrue; + } + + function AddColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef) + { + if(isset($aTables[$sTableName])) + { + if(!isset($aTables[$sTableName]['fd'][$sColumnName])) + { + $aTables[$sTableName]['fd'][$sColumnName] = $aColumnDef; + } + } + + return True; + } + + function CreateTable($oProc, &$aTables, $sTableName, $aTableDef) + { + if(!isset($aTables[$sTableName])) + { + $aTables[$sTableName] = $aTableDef; + } + + return True; + } + } +?> diff --git a/etemplate/inc/class.schema_proc_mssql.inc.php b/etemplate/inc/class.schema_proc_mssql.inc.php new file mode 100644 index 0000000000..d8827175d1 --- /dev/null +++ b/etemplate/inc/class.schema_proc_mssql.inc.php @@ -0,0 +1,341 @@ + * + * and Miles Lott * + * -------------------------------------------- * + * This program is free software; you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; either version 2 of the License, or (at your * + * option) any later version. * + \**************************************************************************/ + + /* $Id$ */ + + class schema_proc_mssql + { + var $m_sStatementTerminator; + /* Following added to convert sql to array */ + var $sCol = array(); + var $pk = array(); + var $fk = array(); + var $ix = array(); + var $uc = array(); + + function schema_proc_mssql() + { + $this->m_sStatementTerminator = ';'; + } + + /* Return a type suitable for DDL */ + function TranslateType($sType, $iPrecision = 0, $iScale = 0) + { + $sTranslated = ''; + switch($sType) + { + case 'auto': + $sTranslated = 'int identity(1,1)'; + break; + case 'blob': + $sTranslated = 'image'; /* wonder how well PHP will support this??? */ + break; + case 'char': + if ($iPrecision > 0 && $iPrecision < 256) + { + $sTranslated = sprintf("char(%d)", $iPrecision); + } + if ($iPrecision > 255) + { + $sTranslated = 'text'; + } + break; + case 'date': + $sTranslated = 'smalldatetime'; + break; + case 'decimal': + $sTranslated = sprintf("decimal(%d,%d)", $iPrecision, $iScale); + break; + case 'float': + switch ($iPrecision) + { + case 4: + $sTranslated = 'float'; + break; + case 8: + $sTranslated = 'real'; + break; + } + break; + case 'int': + switch ($iPrecision) + { + case 2: + $sTranslated = 'smallint'; + break; + case 4: + case 8: + $sTranslated = 'int'; + break; + } + break; + case 'longtext': + case 'text': + $sTranslated = 'text'; + break; + case 'timestamp': + $sTranslated = 'datetime'; + break; + case 'varchar': + if ($iPrecision > 0 && $iPrecision < 256) + { + $sTranslated = sprintf("varchar(%d)", $iPrecision); + } + if ($iPrecision > 255) + { + $sTranslated = 'text'; + } + break; + } + return $sTranslated; + } + + function TranslateDefault($sDefault) + { + switch ($sDefault) + { + case 'current_date': + case 'current_timestamp': + return 'GetDate()'; + } + + return $sDefault; + } + + // Inverse of above, convert sql column types to array info + function rTranslateType($sType, $iPrecision = 0, $iScale = 0) + { + $sTranslated = ''; + if ($sType == 'int' || $sType == 'tinyint' || $sType == 'smallint') + { + if ($iPrecision > 8) + { + $iPrecision = 8; + } + elseif($iPrecision > 4) + { + $iPrecision = 4; + } + else + { + $iPrecision = 2; + } + } + switch($sType) + { + case 'tinyint': + case 'smallint': + $sTranslated = "'type' => 'int', 'precision' => 2"; + break; + case 'int': + $sTranslated = "'type' => 'int', 'precision' => 4"; + break; + case 'char': + if ($iPrecision > 0 && $iPrecision < 256) + { + $sTranslated = "'type' => 'char', 'precision' => $iPrecision"; + } + if ($iPrecision > 255) + { + $sTranslated = "'type' => 'text'"; + } + break; + case 'decimal': + $sTranslated = "'type' => 'decimal', 'precision' => $iPrecision, 'scale' => $iScale"; + break; + case 'float': + case 'double': + $sTranslated = "'type' => 'float', 'precision' => $iPrecision"; + break; + case 'smalldatetime': + $sTranslated = "'type' => 'date'"; + break; + case 'datetime': + $sTranslated = "'type' => 'timestamp'"; + break; + case 'varchar': + if ($iPrecision > 0 && $iPrecision < 256) + { + $sTranslated = "'type' => 'varchar', 'precision' => $iPrecision"; + } + if ($iPrecision > 255) + { + $sTranslated = "'type' => 'text'"; + } + break; + case 'image': + $sTranslated = "'type' => 'blob'"; + break; + case 'text': + $sTranslated = "'type' => '$sType'"; + break; + } + return $sTranslated; + } + + function GetPKSQL($sFields) + { + return "PRIMARY KEY($sFields)"; + } + + function GetUCSQL($sFields) + { + return "UNIQUE($sFields)"; + } + + function _GetColumns($oProc, $sTableName, &$sColumns, $sDropColumn = '') + { + $sColumns = ''; + $this->pk = array(); + $this->fk = array(); + $this->ix = array(); + $this->uc = array(); + + // Field, Type, Null, Key, Default, Extra + $oProc->m_odb->query("exec sp_columns '$sTableName'"); + while ($oProc->m_odb->next_record()) + { + $type = $default = $null = $nullcomma = $prec = $scale = $ret = $colinfo = $scales = ''; + if ($sColumns != '') + { + $sColumns .= ','; + } + $sColumns .= $oProc->m_odb->f(0); + + // The rest of this is used only for SQL->array + $colinfo = explode('(',$oProc->m_odb->f(1)); + $prec = ereg_replace(')','',$colinfo[1]); + $scales = explode(',',$prec); + if ($scales[1]) + { + $prec = $scales[0]; + $scale = $scales[1]; + } + $type = $this->rTranslateType($colinfo[0], $prec, $scale); + + if ($oProc->m_odb->f(2) == 'YES') + { + $null = "'nullable' => True"; + } + else + { + $null = "'nullable' => False"; + } + if ($oProc->m_odb->f(4)) + { + $default = "'default' => '".$oProc->m_odb->f(4)."'"; + $nullcomma = ','; + } + else + { + $default = ''; + $nullcomma = ''; + } + if ($oProc->m_odb->f(5)) + { + $type = "'type' => 'auto'"; + } + $this->sCol[] = "\t\t\t\t'" . $oProc->m_odb->f(0)."' => array(" . $type . ',' . $null . $nullcomma . $default . '),' . "\n"; + if ($oProc->m_odb->f(3) == 'PRI') + { + $this->pk[] = $oProc->m_odb->f(0); + } + if ($oProc->m_odb->f(3) == 'UNI') + { + $this->uc[] = $oProc->m_odb->f(0); + } + /* Hmmm, MUL could also mean unique, or not... */ + if ($oProc->m_odb->f(3) == 'MUL') + { + $this->ix[] = $oProc->m_odb->f(0); + } + } + /* ugly as heck, but is here to chop the trailing comma on the last element (for php3) */ + $this->sCol[count($this->sCol) - 1] = substr($this->sCol[count($this->sCol) - 1],0,-2) . "\n"; + + return false; + } + + function DropTable($oProc, &$aTables, $sTableName) + { + return !!($oProc->m_odb->query("DROP TABLE " . $sTableName)); + } + + function DropColumn($oProc, &$aTables, $sTableName, $aNewTableDef, $sColumnName, $bCopyData = true) + { + return !!($oProc->m_odb->query("ALTER TABLE $sTableName DROP COLUMN $sColumnName")); + } + + function RenameTable($oProc, &$aTables, $sOldTableName, $sNewTableName) + { + return !!($oProc->m_odb->query("EXEC sp_rename '$sOldTableName', '$sNewTableName'")); + } + + function RenameColumn($oProc, &$aTables, $sTableName, $sOldColumnName, $sNewColumnName, $bCopyData = true) + { + // This really needs testing - it can affect primary keys, and other table-related objects + // like sequences and such + global $DEBUG; + if ($DEBUG) { echo '
RenameColumn: calling _GetFieldSQL for ' . $sNewColumnName; } + if ($oProc->_GetFieldSQL($aTables[$sTableName]["fd"][$sNewColumnName], $sNewColumnSQL)) + { + return !!($oProc->m_odb->query("EXEC sp_rename '$sTableName.$sOldColumnName', '$sNewColumnName'")); + } + return false; + } + + function AlterColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef, $bCopyData = true) + { + global $DEBUG; + if ($DEBUG) { echo '
AlterColumn: calling _GetFieldSQL for ' . $sNewColumnName; } + if ($oProc->_GetFieldSQL($aTables[$sTableName]["fd"][$sColumnName], $sNewColumnSQL)) + { + return !!($oProc->m_odb->query("ALTER TABLE $sTableName ALTER COLUMN $sColumnName " . $sNewColumnSQL)); + } + + return false; + } + + function AddColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef) + { + $oProc->_GetFieldSQL($aColumnDef, $sFieldSQL); + $query = "ALTER TABLE $sTableName ADD $sColumnName $sFieldSQL"; + + return !!($oProc->m_odb->query($query)); + } + + function GetSequenceSQL($sTableName, &$sSequenceSQL) + { + $sSequenceSQL = ''; + return true; + } + + function CreateTable($oProc, &$aTables, $sTableName, $aTableDef) + { + if ($oProc->_GetTableSQL($sTableName, $aTableDef, $sTableSQL, $sSequenceSQL)) + { + // create sequence first since it will be needed for default + if ($sSequenceSQL != '') + { + $oProc->m_odb->query($sSequenceSQL); + } + + $query = "CREATE TABLE $sTableName ($sTableSQL)"; + return !!($oProc->m_odb->query($query)); + } + + return false; + } + } +?> diff --git a/etemplate/inc/class.schema_proc_mysql.inc.php b/etemplate/inc/class.schema_proc_mysql.inc.php new file mode 100644 index 0000000000..67247f64c0 --- /dev/null +++ b/etemplate/inc/class.schema_proc_mysql.inc.php @@ -0,0 +1,364 @@ + * + * and Miles Lott * + * -------------------------------------------- * + * This program is free software; you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; either version 2 of the License, or (at your * + * option) any later version. * + \**************************************************************************/ + + /* $Id$ */ + + class schema_proc_mysql + { + var $m_sStatementTerminator; + /* Following added to convert sql to array */ + var $sCol = array(); + var $pk = array(); + var $fk = array(); + var $ix = array(); + var $uc = array(); + + function schema_proc_mysql() + { + $this->m_sStatementTerminator = ';'; + } + + /* Return a type suitable for DDL */ + function TranslateType($sType, $iPrecision = 0, $iScale = 0) + { + $sTranslated = ''; + switch($sType) + { + case 'auto': + $sTranslated = 'int(11) auto_increment'; + break; + case 'blob': + $sTranslated = 'blob'; + break; + case 'char': + if ($iPrecision > 0 && $iPrecision < 256) + { + $sTranslated = sprintf("char(%d)", $iPrecision); + } + if ($iPrecision > 255) + { + $sTranslated = 'text'; + } + break; + case 'date': + $sTranslated = 'date'; + break; + case 'decimal': + $sTranslated = sprintf("decimal(%d,%d)", $iPrecision, $iScale); + break; + case 'float': + switch ($iPrecision) + { + case 4: + $sTranslated = 'float'; + break; + case 8: + $sTranslated = 'double'; + break; + } + break; + case 'int': + switch ($iPrecision) + { + case 2: + $sTranslated = 'smallint'; + break; + case 4: + $sTranslated = 'int'; + break; + case 8: + $sTranslated = 'bigint'; + break; + } + break; + case 'longtext': + $sTranslated = 'longtext'; + break; + case 'text': + $sTranslated = 'text'; + break; + case 'timestamp': + $sTranslated = 'datetime'; + break; + case 'varchar': + if ($iPrecision > 0 && $iPrecision < 256) + { + $sTranslated = sprintf("varchar(%d)", $iPrecision); + } + if ($iPrecision > 255) + { + $sTranslated = 'text'; + } + break; + } + return $sTranslated; + } + + function TranslateDefault($sDefault) + { + switch ($sDefault) + { + case 'current_date': + case 'current_timestamp': + return 'now'; + } + return $sDefault; + } + + /* Inverse of above, convert sql column types to array info */ + function rTranslateType($sType, $iPrecision = 0, $iScale = 0) + { + $sTranslated = ''; + if ($sType == 'int' || $sType == 'tinyint' || $sType == 'smallint' || $sType == 'bigint') + { + if ($iPrecision > 8) + { + $iPrecision = 8; + } + elseif($iPrecision > 4) + { + $iPrecision = 4; + } + else + { + $iPrecision = 2; + } + } + switch($sType) + { + case 'tinyint': + case 'smallint': + $sTranslated = "'type' => 'int', 'precision' => 2"; + break; + case 'int': + $sTranslated = "'type' => 'int', 'precision' => 4"; + break; + case 'bigint': + $sTranslated = "'type' => 'int', 'precision' => 8"; + case 'char': + if ($iPrecision > 0 && $iPrecision < 256) + { + $sTranslated = "'type' => 'char', 'precision' => $iPrecision"; + } + if ($iPrecision > 255) + { + $sTranslated = "'type' => 'text'"; + } + break; + case 'decimal': + $sTranslated = "'type' => 'decimal', 'precision' => $iPrecision, 'scale' => $iScale"; + break; + case 'float': + case 'double': + $sTranslated = "'type' => 'float', 'precision' => $iPrecision"; + break; + case 'datetime': + $sTranslated = "'type' => 'timestamp'"; + break; + case 'enum': + /* Here comes a nasty assumption */ + /* $sTranslated = "'type' => 'varchar', 'precision' => 255"; */ + $sTranslated = "'type' => 'varchar', 'precision' => $iPrecision"; + break; + case 'varchar': + if ($iPrecision > 0 && $iPrecision < 256) + { + $sTranslated = "'type' => 'varchar', 'precision' => $iPrecision"; + } + if ($iPrecision > 255) + { + $sTranslated = "'type' => 'text'"; + } + break; + case 'longtext': + case 'text': + case 'blob': + case 'date': + $sTranslated = "'type' => '$sType'"; + break; + } + return $sTranslated; + } + + function GetPKSQL($sFields) + { + return "PRIMARY KEY($sFields)"; + } + + function GetUCSQL($sFields) + { + return "UNIQUE($sFields)"; + } + + function _GetColumns($oProc, $sTableName, &$sColumns, $sDropColumn = '') + { + $sColumns = ''; + $this->pk = array(); + $this->fk = array(); + $this->ix = array(); + $this->uc = array(); + + /* Field, Type, Null, Key, Default, Extra */ + $oProc->m_odb->query("describe $sTableName"); + while ($oProc->m_odb->next_record()) + { + $type = $default = $null = $nullcomma = $prec = $scale = $ret = $colinfo = $scales = ''; + if ($sColumns != '') + { + $sColumns .= ','; + } + $sColumns .= $oProc->m_odb->f(0); + + /* The rest of this is used only for SQL->array */ + $colinfo = explode('(',$oProc->m_odb->f(1)); + $prec = ereg_replace(')','',$colinfo[1]); + $scales = explode(',',$prec); + + if($colinfo[0] == 'enum') + { + /* set prec to length of longest enum-value */ + for($prec=0; list($nul,$name) = @each($scales);) + { + if($prec < (strlen($name) - 2)) + { + /* -2 as name is like "'name'" */ + $prec = (strlen($name) - 2); + } + } + } + elseif ($scales[1]) + { + $prec = $scales[0]; + $scale = $scales[1]; + } + $type = $this->rTranslateType($colinfo[0], $prec, $scale); + + if ($oProc->m_odb->f(2) == 'YES') + { + $null = "'nullable' => True"; + } + else + { + $null = "'nullable' => False"; + } + if ($oProc->m_odb->f(4) != '') + { + $default = "'default' => '".$oProc->m_odb->f(4)."'"; + $nullcomma = ','; + } + else + { + $default = ''; + $nullcomma = ''; + } + if ($oProc->m_odb->f(5)) + { + $type = "'type' => 'auto'"; + } + $this->sCol[] = "\t\t\t\t'" . $oProc->m_odb->f(0)."' => array(" . $type . ',' . $null . $nullcomma . $default . '),' . "\n"; + if ($oProc->m_odb->f(3) == 'PRI') + { + $this->pk[] = $oProc->m_odb->f(0); + } + if ($oProc->m_odb->f(3) == 'UNI') + { + $this->uc[] = $oProc->m_odb->f(0); + } + /* Hmmm, MUL could also mean unique, or not... */ + if ($oProc->m_odb->f(3) == 'MUL') + { + $this->ix[] = $oProc->m_odb->f(0); + } + } + /* ugly as heck, but is here to chop the trailing comma on the last element (for php3) */ + $this->sCol[count($this->sCol) - 1] = substr($this->sCol[count($this->sCol) - 1],0,-2) . "\n"; + + return false; + } + + function DropTable($oProc, &$aTables, $sTableName) + { + return !!($oProc->m_odb->query("DROP TABLE " . $sTableName)); + } + + function DropColumn($oProc, &$aTables, $sTableName, $aNewTableDef, $sColumnName, $bCopyData = true) + { + return !!($oProc->m_odb->query("ALTER TABLE $sTableName DROP COLUMN $sColumnName")); + } + + function RenameTable($oProc, &$aTables, $sOldTableName, $sNewTableName) + { + return !!($oProc->m_odb->query("ALTER TABLE $sOldTableName RENAME $sNewTableName")); + } + + function RenameColumn($oProc, &$aTables, $sTableName, $sOldColumnName, $sNewColumnName, $bCopyData = true) + { + /* + TODO: This really needs testing - it can affect primary keys, and other table-related objects + like sequences and such + */ + global $DEBUG; + if ($DEBUG) { echo '
RenameColumn: calling _GetFieldSQL for ' . $sNewColumnName; } + if ($oProc->_GetFieldSQL($aTables[$sTableName]["fd"][$sNewColumnName], $sNewColumnSQL)) + { + return !!($oProc->m_odb->query("ALTER TABLE $sTableName CHANGE $sOldColumnName $sNewColumnName " . $sNewColumnSQL)); + } + return false; + } + + function AlterColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef, $bCopyData = true) + { + global $DEBUG; + if ($DEBUG) { echo '
AlterColumn: calling _GetFieldSQL for ' . $sNewColumnName; } + if ($oProc->_GetFieldSQL($aTables[$sTableName]["fd"][$sColumnName], $sNewColumnSQL)) + { + return !!($oProc->m_odb->query("ALTER TABLE $sTableName MODIFY $sColumnName " . $sNewColumnSQL)); + /* return !!($oProc->m_odb->query("ALTER TABLE $sTableName CHANGE $sColumnName $sColumnName " . $sNewColumnSQL)); */ + } + + return false; + } + + function AddColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef) + { + $oProc->_GetFieldSQL($aColumnDef, $sFieldSQL); + $query = "ALTER TABLE $sTableName ADD COLUMN $sColumnName $sFieldSQL"; + + return !!($oProc->m_odb->query($query)); + } + + function GetSequenceSQL($sTableName, &$sSequenceSQL) + { + $sSequenceSQL = ''; + return true; + } + + function CreateTable($oProc, &$aTables, $sTableName, $aTableDef) + { + if ($oProc->_GetTableSQL($sTableName, $aTableDef, $sTableSQL, $sSequenceSQL)) + { + /* create sequence first since it will be needed for default */ + if ($sSequenceSQL != '') + { + $oProc->m_odb->query($sSequenceSQL); + } + + $query = "CREATE TABLE $sTableName ($sTableSQL)"; + return !!($oProc->m_odb->query($query)); + } + + return false; + } + } +?> diff --git a/etemplate/inc/class.schema_proc_pgsql.inc.php b/etemplate/inc/class.schema_proc_pgsql.inc.php new file mode 100644 index 0000000000..5e45bef690 --- /dev/null +++ b/etemplate/inc/class.schema_proc_pgsql.inc.php @@ -0,0 +1,616 @@ + * + * Copyright (C) 1998-1999 Tobias Ratschiller * + * -------------------------------------------- * + * This file written by Michael Dean * + * and Miles Lott * + * -------------------------------------------- * + * This program is free software; you can redistribute it and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; either version 2 of the License, or (at your * + * option) any later version. * + \**************************************************************************/ + + /* $Id$ */ + + class schema_proc_pgsql + { + var $m_sStatementTerminator; + /* Following added to convert sql to array */ + var $sCol = array(); + var $pk = array(); + var $fk = array(); + var $ix = array(); + var $uc = array(); + + function schema_proc_pgsql() + { + $this->m_sStatementTerminator = ';'; + } + + /* Return a type suitable for DDL */ + function TranslateType($sType, $iPrecision = 0, $iScale = 0) + { + switch($sType) + { + case 'auto': + $sTranslated = 'int4'; + break; + case 'blob': + $sTranslated = 'text'; + break; + case 'char': + if ($iPrecision > 0 && $iPrecision < 256) + { + $sTranslated = sprintf("char(%d)", $iPrecision); + } + if ($iPrecision > 255) + { + $sTranslated = 'text'; + } + break; + case 'date': + $sTranslated = 'date'; + break; + case 'decimal': + $sTranslated = sprintf("decimal(%d,%d)", $iPrecision, $iScale); + break; + case 'float': + if ($iPrecision == 4 || $iPrecision == 8) + { + $sTranslated = sprintf("float%d", $iPrecision); + } + break; + case 'int': + if ($iPrecision == 2 || $iPrecision == 4 || $iPrecision == 8) + { + $sTranslated = sprintf("int%d", $iPrecision); + } + break; + case 'longtext': + $sTranslated = 'text'; + break; + case 'text': + $sTranslated = 'text'; + break; + case 'timestamp': + $sTranslated = 'timestamp'; + break; + case 'varchar': + if ($iPrecision > 0 && $iPrecision < 256) + { + $sTranslated = sprintf("varchar(%d)", $iPrecision); + } + if ($iPrecision > 255) + { + $sTranslated = 'text'; + } + break; + } + return $sTranslated; + } + + function TranslateDefault($sDefault) + { + switch ($sDefault) + { + case 'current_date': + case 'current_timestamp': + return 'now'; + } + return $sDefault; + } + + /* Inverse of above, convert sql column types to array info */ + function rTranslateType($sType, $iPrecision = 0, $iScale = 0) + { + $sTranslated = ''; + switch($sType) + { + case 'serial': + $sTranslated = "'type' => 'auto'"; + break; + case 'int2': + $sTranslated = "'type' => 'int', 'precision' => 2"; + break; + case 'int4': + $sTranslated = "'type' => 'int', 'precision' => 4"; + break; + case 'int8': + $sTranslated = "'type' => 'int', 'precision' => 8"; + break; + case 'bpchar': + case 'char': + if ($iPrecision > 0 && $iPrecision < 256) + { + $sTranslated = "'type' => 'char', 'precision' => $iPrecision"; + } + if ($iPrecision > 255) + { + $sTranslated = "'type' => 'text'"; + } + break; + case 'numeric': + /* Borrowed from phpPgAdmin */ + $iPrecision = ($iScale >> 16) & 0xffff; + $iScale = ($iScale - 4) & 0xffff; + $sTranslated = "'type' => 'decimal', 'precision' => $iPrecision, 'scale' => $iScale"; + break; + case 'float': + case 'float4': + case 'float8': + case 'double': + $sTranslated = "'type' => 'float', 'precision' => $iPrecision"; + break; + case 'datetime': + case 'timestamp': + $sTranslated = "'type' => 'timestamp'"; + break; + case 'varchar': + if ($iPrecision > 0 && $iPrecision < 256) + { + $sTranslated = "'type' => 'varchar', 'precision' => $iPrecision"; + } + if ($iPrecision > 255) + { + $sTranslated = "'type' => 'text'"; + } + break; + case 'text': + case 'blob': + case 'date': + $sTranslated = "'type' => '$sType'"; + break; + } + return $sTranslated; + } + + function GetPKSQL($sFields) + { + return "PRIMARY KEY($sFields)"; + } + + function GetUCSQL($sFields) + { + return "UNIQUE($sFields)"; + } + + function _GetColumns($oProc, $sTableName, &$sColumns, $sDropColumn = '', $sAlteredColumn = '', $sAlteredColumnType = '') + { + $sdb = $oProc->m_odb; + $sdc = $oProc->m_odb; + + $sColumns = ''; + $this->pk = array(); + $this->fk = array(); + $this->ix = array(); + $this->uc = array(); + + $query = "SELECT a.attname,a.attnum FROM pg_attribute a,pg_class b WHERE "; + $query .= "b.oid=a.attrelid AND a.attnum>0 and b.relname='$sTableName'"; + if ($sDropColumn != '') + { + $query .= " AND a.attname != '$sDropColumn'"; + } + $query .= ' ORDER BY a.attnum'; + + $oProc->m_odb->query($query); + while ($oProc->m_odb->next_record()) + { + if ($sColumns != '') + { + $sColumns .= ','; + } + + $sFieldName = $oProc->m_odb->f(0); + $sColumns .= $sFieldName; + if ($sAlteredColumn == $sFieldName && $sAlteredColumnType != '') + { + $sColumns .= '::' . $sAlteredColumnType; + } + } + //$qdefault = "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c " + // . "WHERE c.relname = $sTableName AND c.oid = d.adrelid AND d.adnum =" . $oProc->m_odb->f(1); + $sql_get_fields = " + SELECT + a.attnum, + a.attname AS field, + t.typname AS type, + a.attlen AS length, + a.atttypmod AS lengthvar, + a.attnotnull AS notnull + FROM + pg_class c, + pg_attribute a, + pg_type t + WHERE + c.relname = '$sTableName' + and a.attnum > 0 + and a.attrelid = c.oid + and a.atttypid = t.oid + ORDER BY a.attnum"; + /* attnum field type length lengthvar notnull(Yes/No) */ + $sdb->query($sql_get_fields); + while ($sdb->next_record()) + { + $colnum = $sdb->f(0); + $colname = $sdb->f(1); + + if ($sdb->f(5) == 'Yes') + { + $null = "'nullable' => True"; + } + else + { + $null = "'nullable' => False"; + } + + if ($sdb->f(2) == 'numeric') + { + $prec = $sdb->f(3); + $scale = $sdb->f(4); + } + elseif ($sdb->f(3) > 0) + { + $prec = $sdb->f(3); + $scale = 0; + } + elseif ($sdb->f(4) > 0) + { + $prec = $sdb->f(4) - 4; + $scale = 0; + } + else + { + $prec = 0; + $scale = 0; + } + + $type = $this->rTranslateType($sdb->f(2), $prec, $scale); + + $sql_get_default = " + SELECT d.adsrc AS rowdefault + FROM pg_attrdef d, pg_class c + WHERE + c.relname = '$sTableName' AND + c.oid = d.adrelid AND + d.adnum = $colnum + "; + $sdc->query($sql_get_default); + $sdc->next_record(); + if ($sdc->f(0)) + { + if (ereg('nextval',$sdc->f(0))) + { + $default = ''; + $nullcomma = ''; + } + else + { + $default = "'default' => '".$sdc->f(0)."'"; + $nullcomma = ','; + } + } + else + { + $default = ''; + $nullcomma = ''; + } + $default = ereg_replace("''","'",$default); + + $this->sCol[] = "\t\t\t\t'" . $colname . "' => array(" . $type . ',' . $null . $nullcomma . $default . '),' . "\n"; + } + $sql_pri_keys = " + SELECT + ic.relname AS index_name, + bc.relname AS tab_name, + ta.attname AS column_name, + i.indisunique AS unique_key, + i.indisprimary AS primary_key + FROM + pg_class bc, + pg_class ic, + pg_index i, + pg_attribute ta, + pg_attribute ia + WHERE + bc.oid = i.indrelid + AND ic.oid = i.indexrelid + AND ia.attrelid = i.indexrelid + AND ta.attrelid = bc.oid + AND bc.relname = '$sTableName' + AND ta.attrelid = i.indrelid + AND ta.attnum = i.indkey[ia.attnum-1] + ORDER BY + index_name, tab_name, column_name"; + $sdc->query($sql_pri_keys); + while ($sdc->next_record()) + { + //echo '
checking: ' . $sdc->f(4); + if ($sdc->f(4) == 't') + { + $this->pk[] = $sdc->f(2); + } + if ($sdc->f(3) == 't') + { + $this->uc[] = $sdc->f(2); + } + } + /* ugly as heck, but is here to chop the trailing comma on the last element (for php3) */ + $this->sCol[count($this->sCol) - 1] = substr($this->sCol[count($this->sCol) - 1],0,-2) . "\n"; + + return false; + } + + function _CopyAlteredTable($oProc, &$aTables, $sSource, $sDest) + { + $oDB = $oProc->m_odb; + $oProc->m_odb->query("select * from $sSource"); + while ($oProc->m_odb->next_record()) + { + $sSQL = "INSERT INTO $sDest ("; + $i=0; + @reset($aTables[$sDest]['fd']); + while (list($name,$arraydef) = each($aTables[$sDest]['fd'])) + { + if ($i > 0) + { + $sSQL .= ','; + } + + $sSQL .= $name; + $i++; + } + + $sSQL .= ') VALUES ('; + @reset($aTables[$sDest]['fd']); + $i=0; + while (list($name,$arraydef) = each($aTables[$sDest]['fd'])) + { + if ($i > 0) + { + $sSQL .= ','; + } + + if ($oProc->m_odb->f($i) != null) + { + switch ($arraydef['type']) + { + case 'blob': + case 'char': + case 'date': + case 'text': + case 'timestamp': + case 'varchar': + $sSQL .= "'" . $oProc->m_odb->db_addslashes($oProc->m_odb->f($i)) . "'"; + break; + default: + $sSQL .= intval($oProc->m_odb->f($i)); + } + } + else + { + $sSQL .= 'null'; + } + $i++; + } + $sSQL .= ')'; + + $oDB->query($sSQL); + } + + return true; + } + + function GetSequenceForTable($oProc,$table,&$sSequenceName) + { + global $DEBUG; + if($DEBUG) { echo '
GetSequenceForTable: ' . $table; } + + $oProc->m_odb->query("SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*' AND relname LIKE 'seq_$table' AND relkind='S' ORDER BY relname",__LINE__,__FILE__); + $oProc->m_odb->next_record(); + if ($oProc->m_odb->f('relname')) + { + $sSequenceName = $oProc->m_odb->f('relname'); + } + return True; + } + + function GetSequenceFieldForTable($oProc,$table,&$sField) + { + global $DEBUG; + if($DEBUG) { echo '
GetSequenceFieldForTable: You rang?'; } + $oProc->m_odb->query("SELECT a.attname FROM pg_attribute a, pg_class c, pg_attrdef d WHERE c.relname='$table' AND c.oid=d.adrelid AND d.adsrc LIKE '%seq_$table%' AND a.attrelid=c.oid AND d.adnum=a.attnum"); + $oProc->m_odb->next_record(); + if ($oProc->m_odb->f('attname')) + { + $sField = $oProc->m_odb->f('attname'); + } + return True; + } + + function DropSequenceForTable($oProc,$table) + { + global $DEBUG; + if($DEBUG) { echo '
DropSequenceForTable: ' . $table; } + + $this->GetSequenceForTable($oProc,$table,$sSequenceName); + if ($sSequenceName) + { + $oProc->m_odb->query("DROP SEQUENCE " . $sSequenceName,__LINE__,__FILE__); + } + return True; + } + + function DropTable($oProc, &$aTables, $sTableName) + { + $this->DropSequenceForTable($oProc,$sTableName); + + return !!($oProc->m_odb->query("DROP TABLE " . $sTableName)); + } + + function DropColumn($oProc, &$aTables, $sTableName, $aNewTableDef, $sColumnName, $bCopyData = true) + { + if ($bCopyData) + { + $oProc->m_odb->query("SELECT * INTO $sTableName" . "_tmp FROM $sTableName"); + } + + $this->DropTable($oProc, $aTables, $sTableName); + + $oProc->_GetTableSQL($sTableName, $aNewTableDef, $sTableSQL, $sSequenceSQL); + if($sSequenceSQL) + { + $oProc->m_odb->query($sSequenceSQL); + } + $query = "CREATE TABLE $sTableName ($sTableSQL)"; + if (!$bCopyData) + { + return !!($oProc->m_odb->query($query)); + } + + $oProc->m_odb->query($query); + $this->_GetColumns($oProc, $sTableName . '_tmp', $sColumns, $sColumnName); + $query = "INSERT INTO $sTableName SELECT $sColumns FROM $sTableName" . '_tmp'; + $bRet = !!($oProc->m_odb->query($query)); + return ($bRet && $this->DropTable($oProc, $aTables, $sTableName . '_tmp')); + } + + function RenameTable($oProc, &$aTables, $sOldTableName, $sNewTableName) + { + global $DEBUG; + if ($DEBUG) { echo '
RenameTable(): Fetching old sequence for: ' . $sOldTableName; } + $this->GetSequenceForTable($oProc,$sOldTableName,$sSequenceName); + if ($DEBUG) { echo ' - ' . $sSequenceName; } + if ($DEBUG) { echo '
RenameTable(): Fetching sequence field for: ' . $sOldTableName; } + $this->GetSequenceFieldForTable($oProc,$sOldTableName,$sField); + if ($DEBUG) { echo ' - ' . $sField; } + + if ($sSequenceName) + { + $oProc->m_odb->query("SELECT last_value FROM seq_$sOldTableName",__LINE__,__FILE__); + $oProc->m_odb->next_record(); + $lastval = $oProc->m_odb->f(0); + + if ($DEBUG) { echo '
RenameTable(): dropping old sequence: ' . $sSequenceName . ' used on field: ' . $sField; } + $this->DropSequenceForTable($oProc,$sOldTableName); + + if ($lastval) + { + $lastval = ' start ' . $lastval; + } + $this->GetSequenceSQL($sNewTableName,$sSequenceSQL); + if ($DEBUG) { echo '
RenameTable(): Making new sequence using: ' . $sSequenceSQL . $lastval; } + $oProc->m_odb->query($sSequenceSQL . $lastval,__LINE__,__FILE__); + if ($DEBUG) { echo '
RenameTable(): Altering column default for: ' . $sField; } + $oProc->m_odb->query("ALTER TABLE $sOldTableName ALTER $sField SET DEFAULT nextval('seq_" . $sNewTableName . "')",__LINE__,__FILE__); + } + + $indexnames = $oProc->m_odb->index_names(); + while(list($key,$val) = @each($indexnames)) + { + $indexes[] = $val['index_name']; + } + if(!in_array($sOldTableName . '_pkey',$indexes)) + { + $oProc->m_odb->query("DROP INDEX " . $sOldTableName . "_pkey",__LINE__,__FILE__); + } + + return !!($oProc->m_odb->query("ALTER TABLE $sOldTableName RENAME TO $sNewTableName")); + } + + function RenameColumn($oProc, &$aTables, $sTableName, $sOldColumnName, $sNewColumnName, $bCopyData = true) + { + /* + This really needs testing - it can affect primary keys, and other table-related objects + like sequences and such + */ + if ($bCopyData) + { + $oProc->m_odb->query("SELECT * INTO $sTableName" . "_tmp FROM $sTableName"); + } + + $this->DropTable($oProc, $aTables, $sTableName); + + if (!$bCopyData) + { + return $this->CreateTable($oProc, $aTables, $sTableName, $oProc->m_aTables[$sTableName], false); + } + + $this->CreateTable($oProc, $aTables, $sTableName, $aTables[$sTableName], True); + $this->_GetColumns($oProc, $sTableName . "_tmp", $sColumns); + $query = "INSERT INTO $sTableName SELECT $sColumns FROM $sTableName" . "_tmp"; + + $bRet = !!($oProc->m_odb->query($query)); + return ($bRet && $this->DropTable($oProc, $aTables, $sTableName . "_tmp")); + } + + function AlterColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef, $bCopyData = true) + { + if ($bCopyData) + { + $oProc->m_odb->query("SELECT * INTO $sTableName" . "_tmp FROM $sTableName"); + } + + $this->DropTable($oProc, $aTables, $sTableName); + + if (!$bCopyData) + { + return $this->CreateTable($oProc, $aTables, $sTableName, $aTables[$sTableName], True); + } + + $this->CreateTable($oProc, $aTables, $sTableName, $aTables[$sTableName], True); + $this->_GetColumns($oProc, $sTableName . "_tmp", $sColumns, '', $sColumnName, $aColumnDef['type'] == 'auto' ? 'int4' : $aColumnDef['type']); + + /* + TODO: analyze the type of change and determine if this is used or _CopyAlteredTable + this is a performance consideration only, _CopyAlteredTable should be safe + $query = "INSERT INTO $sTableName SELECT $sColumns FROM $sTableName" . "_tmp"; + $bRet = !!($oProc->m_odb->query($query)); + */ + + $bRet = $this->_CopyAlteredTable($oProc, $aTables, $sTableName . '_tmp', $sTableName); + + return ($bRet && $this->DropTable($oProc, $aTables, $sTableName . "_tmp")); + } + + function AddColumn($oProc, &$aTables, $sTableName, $sColumnName, &$aColumnDef) + { + $oProc->_GetFieldSQL($aColumnDef, $sFieldSQL); + $query = "ALTER TABLE $sTableName ADD COLUMN $sColumnName $sFieldSQL"; + + return !!($oProc->m_odb->query($query)); + } + + function GetSequenceSQL($sTableName, &$sSequenceSQL) + { + $sSequenceSQL = sprintf("CREATE SEQUENCE seq_%s", $sTableName); + return true; + } + + function CreateTable($oProc, $aTables, $sTableName, $aTableDef, $bCreateSequence = true) + { + global $DEBUG; + if ($oProc->_GetTableSQL($sTableName, $aTableDef, $sTableSQL, $sSequenceSQL)) + { + /* create sequence first since it will be needed for default */ + if ($bCreateSequence && $sSequenceSQL != '') + { + if ($DEBUG) { echo '
Making sequence using: ' . $sSequenceSQL; } + $oProc->m_odb->query($sSequenceSQL); + } + + $query = "CREATE TABLE $sTableName ($sTableSQL)"; + + return !!($oProc->m_odb->query($query)); + } + + return false; + } + } +?>