From 4d498d47cb5ea3df5ffad4f5723439a962883fd5 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 10 Feb 2005 15:15:29 +0000 Subject: [PATCH] updates to work around postgres error while upgrading a phpGW 0.9.14 install --- .../adodb/datadict/datadict-postgres.inc.php | 7 +- phpgwapi/inc/class.schema_proc.inc.php | 55 ++++++++++++--- phpgwapi/setup/tables_update_0_9_14.inc.php | 67 ++++++++++++++----- 3 files changed, 100 insertions(+), 29 deletions(-) diff --git a/phpgwapi/inc/adodb/datadict/datadict-postgres.inc.php b/phpgwapi/inc/adodb/datadict/datadict-postgres.inc.php index a2034f5645..8c1bd3544a 100644 --- a/phpgwapi/inc/adodb/datadict/datadict-postgres.inc.php +++ b/phpgwapi/inc/adodb/datadict/datadict-postgres.inc.php @@ -134,10 +134,11 @@ class ADODB2_postgres extends ADODB_DataDict { if (($not_null = preg_match('/NOT NULL/i',$v))) { $v = preg_replace('/NOT NULL/i','',$v); } - if (preg_match('/^([^ ]+) .*(DEFAULT [^ ]+)/',$v,$matches)) { + if (preg_match('/^([^ ]+) .*DEFAULT ([^ ]+)/',$v,$matches)) { list(,$colname,$default) = $matches; - $sql[] = $alter . str_replace($default,'',$v); - $sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET ' . $default; + $sql[] = $alter . str_replace('DEFAULT '.$default,'',$v); + $sql[] = 'UPDATE '.$tabname.' SET '.$colname.'='.$default; + $sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET DEFAULT ' . $default; } else { $sql[] = $alter . $v; } diff --git a/phpgwapi/inc/class.schema_proc.inc.php b/phpgwapi/inc/class.schema_proc.inc.php index 57007450d1..83291c26cf 100644 --- a/phpgwapi/inc/class.schema_proc.inc.php +++ b/phpgwapi/inc/class.schema_proc.inc.php @@ -223,29 +223,62 @@ */ function RenameTable($sOldTableName, $sNewTableName) { - if ($this->sType == 'pgsql') $this->_PostgresTestDropOldSequence($sTableName); + // if we have an old postgres sequence or index (the ones not linked to the table), + // we create a new table, copy the content and drop the old one + if ($this->sType == 'pgsql') + { + $table_def = $this->GetTableDefinition($sOldTableName); + if ($this->_PostgresHasOldSequence($sOldTableName) || count($table_def['pk']) || + count($table_def['ix']) || count($table_def['uc'])) + { + if ($this->adodb->BeginTrans() && + $this->CreateTable($sNewTableName,$table_def) && + $this->m_odb->query("INSERT INTO $sNewTableName SELECT * FROM $sOldTableName",__LINE__,__FILE__) && + $this->DropTable($sOldTableName)) + { + $this->adodb->CommitTrans(); + return 2; + } + $this->adodb->RollbackTrans(); + return 0; + } + } $aSql = $this->dict->RenameTableSQL($sOldTableName, $sNewTableName); return $this->ExecuteSQLArray($aSql,2,'RenameTableSQL(%1,%2) sql=%3',False,$sOldTableName,$sNewTableName,$aSql); } /** - * Check if we have an old, not automaticaly droped sequence and drop it + * Check if we have an old, not automaticaly droped sequence * - * - * @param $sTableName + * @param string $sTableName + * @param boolean/string sequence-name or false */ - function _PostgresTestDropOldSequence($sTableName) + function _PostgresHasOldSequence($sTableName) { - if ($this->sType != 'pgsql') return; + if ($this->sType != 'pgsql') return false; $seq = $this->adodb->GetOne("SELECT d.adsrc FROM pg_attribute a, pg_class c, pg_attrdef d WHERE c.relname='$sTableName' AND c.oid=d.adrelid AND d.adsrc LIKE '%seq_$sTableName%' AND a.attrelid=c.oid AND d.adnum=a.attnum"); if ($seq && preg_match('/^nextval\(\'(.*)\'/',$seq,$matches)) { - $this->query('DROP SEQUENCE '.$matches[1],__LINE__,__FILE__); + return $matches[1]; + } + return false; + } + + /** + * Check if we have an old, not automaticaly droped sequence and drop it + * + * @param $sTableName + */ + function _PostgresTestDropOldSequence($sTableName) + { + if ($this->sType == 'pgsql' && ($seq = $this->_PostgresHasOldSequence($sTableName))) + { + $this->query('DROP SEQUENCE '.$seq,__LINE__,__FILE__); } } @@ -355,7 +388,7 @@ } else { - foreach($this->dict->MetaIndexes($sTableName) as $idx => $idx_data) + foreach($indexes as $idx => $idx_data) { if (strtolower(implode(':',$idx_data['columns'])) == implode(':',$aColumnNames)) { @@ -1014,6 +1047,12 @@ else { $definition['fd'][$name]['type'] = 'int'; + // detect postgres type-spec and remove it + if ($this->sType == 'pgsql' && $column->has_default && preg_match('/\(([^)])\)::/',$column->default_value,$matches)) + { + $definition['fd'][$name]['default'] = $matches[1]; + $column->has_default = False; + } } break; } diff --git a/phpgwapi/setup/tables_update_0_9_14.inc.php b/phpgwapi/setup/tables_update_0_9_14.inc.php index 48127963f6..d915aeb7e5 100644 --- a/phpgwapi/setup/tables_update_0_9_14.inc.php +++ b/phpgwapi/setup/tables_update_0_9_14.inc.php @@ -572,8 +572,17 @@ $test[] = '0.9.14.502'; function phpgwapi_upgrade0_9_14_502() { - $GLOBALS['phpgw_setup']->oProc->RenameTable('phpgw_preferences','old_preferences'); - + // because of all the trouble with sequences and indexes in the global namespace, + // we use an additional temp. table for postgres and not rename the existing one, but drop it. + if ($GLOBALS['phpgw_setup']->oProc->sType == 'pgsql') + { + $GLOBALS['phpgw_setup']->oProc->query("SELEcT * INTO TEMPORARY TABLE old_preferences FROM phpgw_preferences",__LINE__,__FILE__); + $GLOBALS['phpgw_setup']->oProc->DropTable('phpgw_preferences'); + } + else + { + $GLOBALS['phpgw_setup']->oProc->RenameTable('phpgw_preferences','old_preferences'); + } $GLOBALS['phpgw_setup']->oProc->CreateTable('phpgw_preferences',array( 'fd' => array( 'preference_owner' => array('type' => 'int','precision' => '4','nullable' => False), @@ -616,12 +625,24 @@ $test[] = '0.9.14.503'; function phpgwapi_upgrade0_9_14_503() { - $GLOBALS['phpgw_setup']->oProc->AddColumn('phpgw_addressbook','last_mod',array( - 'type' => 'int', - 'precision' => '4', - 'nullable' => False - )); - + // we create the column for postgres nullable, set all its values to 0 and set it NOT NULL + if ($GLOBALS['phpgw_setup']->oProc->sType == 'pgsql') + { + $GLOBALS['phpgw_setup']->oProc->AddColumn('phpgw_addressbook','last_mod',array( + 'type' => 'int', + 'precision' => '4', + )); + $GLOBALS['phpgw_setup']->oProc->query("UPDATE phpgw_addressbook SET last_mod=0",__LINE__,__FILE__); + $GLOBALS['phpgw_setup']->oProc->query("ALTER TABLE phpgw_addressbook ALTER COLUMN last_mod SET NOT NULL",__LINE__,__FILE__); + } + else + { + $GLOBALS['phpgw_setup']->oProc->AddColumn('phpgw_addressbook','last_mod',array( + 'type' => 'int', + 'precision' => '4', + 'nullable' => false, + )); + } $GLOBALS['setup_info']['phpgwapi']['currentver'] = '0.9.14.504'; return $GLOBALS['setup_info']['phpgwapi']['currentver']; } @@ -629,12 +650,24 @@ $test[] = '0.9.14.504'; function phpgwapi_upgrade0_9_14_504() { - $GLOBALS['phpgw_setup']->oProc->AddColumn('phpgw_categories','last_mod',array( - 'type' => 'int', - 'precision' => '4', - 'nullable' => False - )); - + // we create the column for postgres nullable, set all its values to 0 and set it NOT NULL + if ($GLOBALS['phpgw_setup']->oProc->sType == 'pgsql') + { + $GLOBALS['phpgw_setup']->oProc->AddColumn('phpgw_categories','last_mod',array( + 'type' => 'int', + 'precision' => '4', + )); + $GLOBALS['phpgw_setup']->oProc->query("UPDATE phpgw_categories SET last_mod=0",__LINE__,__FILE__); + $GLOBALS['phpgw_setup']->oProc->query("ALTER TABLE phpgw_categories ALTER COLUMN last_mod SET NOT NULL",__LINE__,__FILE__); + } + else + { + $GLOBALS['phpgw_setup']->oProc->AddColumn('phpgw_categories','last_mod',array( + 'type' => 'int', + 'precision' => '4', + 'nullable' => false, + )); + } $GLOBALS['setup_info']['phpgwapi']['currentver'] = '0.9.14.505'; return $GLOBALS['setup_info']['phpgwapi']['currentver']; } @@ -642,6 +675,8 @@ $test[] = '0.9.14.505'; function phpgwapi_upgrade0_9_14_505() { + // postgres cant convert a column containing empty strings to int, updating them to '0' first + $GLOBALS['phpgw_setup']->oProc->query("UPDATE phpgw_access_log SET lo='0' WHERE lo=''",__LINE__,__FILE__); $GLOBALS['phpgw_setup']->oProc->AlterColumn('phpgw_access_log','lo',array( 'type' => 'int', 'precision' => '4', @@ -1323,10 +1358,6 @@ $test[] = '0.9.99.020'; function phpgwapi_upgrade0_9_99_020() { - // at least for postgres we need to change the colum-type, else we get an error in RefreshTable - $GLOBALS['phpgw_setup']->oProc->AlterColumn('phpgw_app_sessions','loginid',array( - 'type' => 'int','precision' => '4','nullable' => False - )); $GLOBALS['phpgw_setup']->oProc->RefreshTable('phpgw_app_sessions',array( 'fd' => array( 'sessionid' => array('type' => 'varchar','precision' => '128','nullable' => False),