diff --git a/calendar/setup/tables_update.inc.php b/calendar/setup/tables_update.inc.php index 8b5cc35499..0cd6b52879 100644 --- a/calendar/setup/tables_update.inc.php +++ b/calendar/setup/tables_update.inc.php @@ -1166,7 +1166,7 @@ function calendar_upgrade1_0_0_005() { // change prefix of all calendar tables to egw_ - foreach(array('cal','cal_user','cal_repeats','cal_extra','cal_holidays') as $name) + foreach(array('cal_user','cal_repeats','cal_extra','cal_holidays','cal') as $name) { $GLOBALS['egw_setup']->oProc->RenameTable('phpgw_'.$name,'egw_'.$name); } diff --git a/infolog/setup/tables_update.inc.php b/infolog/setup/tables_update.inc.php index 8eb1368850..98bf4dc1be 100644 --- a/infolog/setup/tables_update.inc.php +++ b/infolog/setup/tables_update.inc.php @@ -402,7 +402,7 @@ 'precision' => '2', 'default' => '1' )); - $GLOBALS['phpgw_setup']->oProc->query("UPDATE phpgw_infolog SET info_priority=(CASE WHEN info_pri='urgent' THEN 3 WHEN info_pre='high' THEN 2 WHEN info_pri='low' THEN 0 ELSE 1 END)",__LINE__,__FILE__); + $GLOBALS['phpgw_setup']->oProc->query("UPDATE phpgw_infolog SET info_priority=(CASE WHEN info_pri='urgent' THEN 3 WHEN info_pri='high' THEN 2 WHEN info_pri='low' THEN 0 ELSE 1 END)",__LINE__,__FILE__); $GLOBALS['phpgw_setup']->oProc->DropColumn('phpgw_infolog',array( 'fd' => array( diff --git a/phpgwapi/inc/class.egw_db.inc.php b/phpgwapi/inc/class.egw_db.inc.php index 34ae1d8801..697e20d5af 100644 --- a/phpgwapi/inc/class.egw_db.inc.php +++ b/phpgwapi/inc/class.egw_db.inc.php @@ -894,7 +894,8 @@ */ function table_names() { - if (!$this->Link_ID && !$this->connect()) + if (!$this->Link_ID) $this->connect(); + if (!$this->Link_ID) { return False; } @@ -1284,13 +1285,15 @@ * @param int $line line-number to pass to query * @param string $file file-name to pass to query * @param string/boolean $app string with name of app or False to use the current-app + * @param bool $use_prepared_statement use a prepared statement + * @param array/bool $table_def use this table definition. If False, the table definition will be read from tables_baseline * @return ADORecordSet or false, if the query fails */ - function insert($table,$data,$where,$line,$file,$app=False,$use_prepared_statement=false) + function insert($table,$data,$where,$line,$file,$app=False,$use_prepared_statement=false,$table_def=False) { if ($this->Debug) echo "

db::insert('$table',".print_r($data,True).",".print_r($where,True).",$line,$file,'$app')

\n"; - $table_def = $this->get_table_definitions($app,$table); + if (!$table_def) $table_def = $this->get_table_definitions($app,$table); $sql_append = ''; $cmd = 'INSERT'; @@ -1368,12 +1371,14 @@ * @param int $line line-number to pass to query * @param string $file file-name to pass to query * @param string/boolean $app string with name of app or False to use the current-app + * @param bool $use_prepared_statement use a prepared statement + * @param array/bool $table_def use this table definition. If False, the table definition will be read from tables_baseline * @return ADORecordSet or false, if the query fails */ - function update($table,$data,$where,$line,$file,$app=False,$use_prepared_statement=false) + function update($table,$data,$where,$line,$file,$app=False,$use_prepared_statement=false,$table_def=False) { if ($this->Debug) echo "

db::update('$table',".print_r($data,true).','.print_r($where,true).",$line,$file,'$app')

\n"; - $table_def = $this->get_table_definitions($app,$table); + if (!$table_def) $table_def = $this->get_table_definitions($app,$table); $blobs2update = array(); // SapDB/MaxDB cant update LONG columns / blob's: if a blob-column is included in the update we remember it in $blobs2update @@ -1451,11 +1456,12 @@ * @param int $line line-number to pass to query * @param string $file file-name to pass to query * @param string/boolean $app string with name of app or False to use the current-app + * @param array/bool $table_def use this table definition. If False, the table definition will be read from tables_baseline * @return ADORecordSet or false, if the query fails */ - function delete($table,$where,$line,$file,$app=False) + function delete($table,$where,$line,$file,$app=False,$table_def=False) { - $table_def = $this->get_table_definitions($app,$table); + if (!$table_def) $table_def = $this->get_table_definitions($app,$table); $sql = "DELETE FROM $table WHERE ". $this->column_data_implode(' AND ',$where,True,False,$table_def['fd']); @@ -1474,11 +1480,12 @@ * array: column-name / value pairs: the value gets quoted according to the type of the column and prefixed * with column-name=, multiple pairs are AND'ed together, see db::column_data_implode * bool: If False or is_null($arg): the next 2 (!) arguments gets ignored + * @param array/bool $table_def use this table definition. If False, the table definition will be read from tables_baseline * @return string the expression generated from the arguments */ - function expression($table,$args) + function expression($table,$args,$table_def=False) { - $table_def = $this->get_table_definitions('',$table); + if (!$table_def) $table_def = $this->get_table_definitions('',$table); $sql = ''; $ignore_next = 0; foreach(func_get_args() as $n => $arg) @@ -1525,13 +1532,14 @@ * @param int $num_rows number of rows to return if offset set, default 0 = use default in user prefs * @param string $join=null sql to do a join, added as is after the table-name, eg. ", table2 WHERE x=y" or * "LEFT JOIN table2 ON (x=y)", Note: there's no quoting done on $join! + * @param array/bool $table_def use this table definition. If False, the table definition will be read from tables_baseline * @return ADORecordSet or false, if the query fails */ - function select($table,$cols,$where,$line,$file,$offset=False,$append='',$app=False,$num_rows=0,$join='') + function select($table,$cols,$where,$line,$file,$offset=False,$append='',$app=False,$num_rows=0,$join='',$table_def=False) { if ($this->Debug) echo "

db::select('$table',".print_r($cols,True).",".print_r($where,True).",$line,$file,$offset,'$app')

\n"; - $table_def = $this->get_table_definitions($app,$table); + if (!$table_def) $table_def = $this->get_table_definitions($app,$table); if (is_array($cols)) { $cols = implode(',',$cols); diff --git a/phpgwapi/inc/class.schema_proc.inc.php b/phpgwapi/inc/class.schema_proc.inc.php index 55e3f1c429..ab07711856 100644 --- a/phpgwapi/inc/class.schema_proc.inc.php +++ b/phpgwapi/inc/class.schema_proc.inc.php @@ -70,6 +70,10 @@ * @var array $capabilities reference to the array of the db-class */ var $capabilities; + /** + * @var int $pgsql_old_seq preserve value of old sequences in PostgreSQL + */ + var $pgsql_old_seq; /** * Constructor of schema-processor @@ -115,9 +119,10 @@ * * @param string $sTableName * @param array $aTableDef + * @param bool $preserveSequence * @return int 2: no error, 1: errors, but continued, 0: errors aborted */ - function CreateTable($sTableName, $aTableDef) + function CreateTable($sTableName, $aTableDef, $preserveSequence=False) { if ($this->debug) { @@ -192,6 +197,16 @@ return $retVal; } } + // preserve last value of an old sequence + if ($this->sType == 'pgsql' && $preserveSequence && $this->pgsql_old_seq) + { + if ($seq = $this->_PostgresHasOldSequence($sTableName)) + { + $this->pgsql_old_seq = $this->pgsql_old_seq + 1; + $this->m_odb->query("ALTER SEQUENCE $seq RESTART WITH " . $this->pgsql_old_seq,__LINE__,__FILE__); + } + $this->pgsql_old_seq = 0; + } return $retVal; } @@ -278,11 +293,11 @@ { $table_def = $this->GetTableDefinition($sOldTableName); - if ($this->_PostgresHasOldSequence($sOldTableName) || count($table_def['pk']) || + if ($this->_PostgresHasOldSequence($sOldTableName,True) || count($table_def['pk']) || count($table_def['ix']) || count($table_def['uc'])) { if ($this->adodb->BeginTrans() && - $this->CreateTable($sNewTableName,$table_def) && + $this->CreateTable($sNewTableName,$table_def,True) && $this->m_odb->query("INSERT INTO $sNewTableName SELECT * FROM $sOldTableName",__LINE__,__FILE__) && $this->DropTable($sOldTableName)) { @@ -302,17 +317,24 @@ * Check if we have an old, not automaticaly droped sequence * * @param string $sTableName - * @param boolean/string sequence-name or false + * @param bool $preserveValue + * @return boolean/string sequence-name or false */ - function _PostgresHasOldSequence($sTableName) + function _PostgresHasOldSequence($sTableName,$preserveValue=False) { 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"); + $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\'::text)' AND a.attrelid=c.oid AND d.adnum=a.attnum"); + $seq2 = $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 '%$sTableName%_seq\'::text)' AND a.attrelid=c.oid AND d.adnum=a.attnum"); if ($seq && preg_match('/^nextval\(\'(.*)\'/',$seq,$matches)) { - + if ($preserveValue) $this->pgsql_old_seq = $this->adodb->GetOne("SELECT last_value FROM " . $matches[1]); + return $matches[1]; + } + if ($seq2 && preg_match('/^nextval\(\'public\.(.*)\'/',$seq2,$matches)) + { + if ($preserveValue) $this->pgsql_old_seq = $this->adodb->GetOne("SELECT last_value FROM " . $matches[1]); return $matches[1]; } return false; @@ -322,14 +344,20 @@ * Check if we have an old, not automaticaly droped sequence and drop it * * @param $sTableName + * @param bool $preserveValue */ - function _PostgresTestDropOldSequence($sTableName) + function _PostgresTestDropOldSequence($sTableName,$preserveValue=False) { + $this->pgsql_old_seq = 0; if ($this->sType == 'pgsql' && ($seq = $this->_PostgresHasOldSequence($sTableName))) { + // only drop sequence, if there is no dependency on it + if (!$this->adodb->GetOne("SELECT relname FROM pg_class JOIN pg_depend ON pg_class.relfilenode=pg_depend.objid WHERE relname='$seq' AND relkind='S' AND deptype='i'")) + { $this->query('DROP SEQUENCE '.$seq,__LINE__,__FILE__); } } + } /** * Changes one (exiting) column in a table @@ -365,6 +393,7 @@ function RenameColumn($sTableName, $sOldColumnName, $sNewColumnName, $bCopyData=True) { $table_def = $this->GetTableDefinition($sTableName); + $old_def = array(); if (isset($table_def['fd'][$sOldColumnName])) { @@ -374,7 +403,7 @@ { foreach($table_def['fd'] as $col => $def) { - if (strtolower($col) == strtolower($OldColumnName)) + if (strtolower($col) == strtolower($sOldColumnName)) { $old_def = $def; break; @@ -1034,6 +1063,7 @@ 'F' => 'float', 'N' => 'decimal', 'R' => 'auto', + 'L' => 'bool', ); $definition['fd'][$name]['type'] = $ado_type2egw[$type]; diff --git a/phpgwapi/setup/tables_update.inc.php b/phpgwapi/setup/tables_update.inc.php index 4b7296c2f8..cf929924b5 100644 --- a/phpgwapi/setup/tables_update.inc.php +++ b/phpgwapi/setup/tables_update.inc.php @@ -93,6 +93,10 @@ { // removing the ACL entries of deleted accounts $GLOBALS['egw_setup']->setup_account_object(); + if ($GLOBALS['phpgw']->accounts->table) + { + $GLOBALS['phpgw']->accounts->table = $GLOBALS['egw_setup']->accounts_table; + } if (($all_accounts = $GLOBALS['phpgw']->accounts->search(array('type'=>'both')))) { $all_accounts = array_keys($all_accounts); @@ -390,7 +394,7 @@ $GLOBALS['egw_setup']->oProc->AddColumn('phpgw_vfs2_files', 'modified', array('type' => 'timestamp', 'nullable' => true)); //Updating existing values - $sql = "SELECT max(modified) as mod, file_id, modifiedby_id from phpgw_vfs2_versioning group by file_id"; + $sql = "SELECT max(modified) as mod, file_id, min(modifiedby_id) from phpgw_vfs2_versioning group by file_id"; $GLOBALS['egw_setup']->oProc->m_odb->query($sql,__LINE__,__FILE__); @@ -492,10 +496,10 @@ 'app_version' => $home_version, ),array( 'app_name' => 'home', - ),__LINE__,__FILE__); + ),__LINE__,__FILE__,False,False,$GLOBALS['egw_setup']->oProc->GetTableDefinition($GLOBALS['egw_setup']->applications_table)); // give all users and groups with preferences rights, rights for the home app. - $GLOBALS['egw_setup']->db->select('phpgw_acl','acl_account',array( + $GLOBALS['egw_setup']->db->select($GLOBALS['egw_setup']->acl_table,'acl_account',array( 'acl_appname' => 'preferences', 'acl_location' => 'run', 'acl_rights' => 1, @@ -507,13 +511,13 @@ } foreach($accounts_with_preference_rights as $account) { - $GLOBALS['egw_setup']->db->insert('phpgw_acl',array( + $GLOBALS['egw_setup']->db->insert($GLOBALS['egw_setup']->acl_table,array( 'acl_rights' => 1, ),array( 'acl_appname' => 'home', 'acl_location' => 'run', 'acl_account' => $account, - ),__LINE__,__FILE__); + ),__LINE__,__FILE__,False,False,$GLOBALS['egw_setup']->oProc->GetTableDefinition($GLOBALS['egw_setup']->acl_table)); } } $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.0.1.010'; @@ -584,9 +588,13 @@ function phpgwapi_upgrade1_0_1_012() { $GLOBALS['egw_setup']->oProc->RenameTable('phpgw_accounts','egw_accounts'); - $GLOBALS['egw_setup']->accounts_table = 'egw_accounts'; + $GLOBALS['egw_setup']->set_table_names(True); + if ($GLOBALS['phpgw']->accounts->table) + { + $GLOBALS['phpgw']->accounts->table = $GLOBALS['egw_setup']->accounts_table; + } $GLOBALS['egw_setup']->oProc->RenameTable('phpgw_acl','egw_acl'); - $GLOBALS['egw_setup']->acl_table = 'egw_acl'; + $GLOBALS['egw_setup']->set_table_names(True); $GLOBALS['egw_setup']->oProc->RenameTable('phpgw_log','egw_log'); $GLOBALS['egw_setup']->oProc->RenameTable('phpgw_log_msg','egw_log_msg'); @@ -598,9 +606,9 @@ function phpgwapi_upgrade1_0_1_013() { $GLOBALS['egw_setup']->oProc->RenameTable('phpgw_config','egw_config'); - $GLOBALS['egw_setup']->config_table = 'egw_config'; + $GLOBALS['egw_setup']->set_table_names(True); $GLOBALS['egw_setup']->oProc->RenameTable('phpgw_applications','egw_applications'); - $GLOBALS['egw_setup']->applications_table = 'egw_applications'; + $GLOBALS['egw_setup']->set_table_names(True); $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.0.1.014'; return $GLOBALS['setup_info']['phpgwapi']['currentver']; @@ -611,7 +619,9 @@ { // index was to big for mysql with charset utf8 (max 1000byte = 333 utf8 chars) // before we can shorten the message_id, we have to make sure there are no identical message_id > 128 chars + // and we have to truncate the message_id explicitly, postgresql f.e. will not do it for us, but bail out instead $to_delete = array(); + $to_truncate = array(); $GLOBALS['egw_setup']->db->select('phpgw_lang','app_name,lang,message_id','LENGTH(message_id) > 128',__LINE__,__FILE__, false,'ORDER BY app_name,lang,message_id'); while(($row = $GLOBALS['egw_setup']->db->row(true))) @@ -621,12 +631,22 @@ { $to_delete[] = $row; } + else + { + $to_truncate[] = $row; + } $last_row = $row; } foreach ($to_delete as $row) { $GLOBALS['egw_setup']->db->delete('phpgw_lang',$row,__LINE__,__FILE__); } + foreach ($to_truncate as $row) + { + $where = $row; + $row['message_id'] = substr($row['message_id'],0,128); + $GLOBALS['egw_setup']->db->update('phpgw_lang',$row,$where,__LINE__,__FILE__,'phpgwapi'); + } $GLOBALS['egw_setup']->oProc->AlterColumn('phpgw_lang','app_name',array( 'type' => 'varchar', 'precision' => '32', @@ -640,9 +660,9 @@ 'default' => '' )); $GLOBALS['egw_setup']->oProc->RenameTable('phpgw_lang','egw_lang'); - $GLOBALS['egw_setup']->lang_table = 'egw_lang'; + $GLOBALS['egw_setup']->set_table_names(True); $GLOBALS['egw_setup']->oProc->RenameTable('phpgw_languages','egw_languages'); - $GLOBALS['egw_setup']->languages_table = 'egw_languages'; + $GLOBALS['egw_setup']->set_table_names(True); $GLOBALS['setup_info']['phpgwapi']['currentver'] = '1.0.1.015'; return $GLOBALS['setup_info']['phpgwapi']['currentver']; @@ -757,26 +777,28 @@ // (shortening them twice, does no harm) !!! if ($GLOBALS['egw_setup']->table_exist(array('phpgw_felamimail_cache'))) { - $GLOBALS['egw_setup']->oProc->AlterColumn('phpgw_felamimail_cache','fmail_accountname',array( + $table_def_cache = $GLOBALS['egw_setup']->oProc->GetTableDefinition('phpgw_felamimail_cache'); + $table_def_folderstatus = $GLOBALS['egw_setup']->oProc->GetTableDefinition('phpgw_felamimail_folderstatus'); + + foreach (array('fmail_accountname','accountname','fmail_foldername','foldername') as $column_name) + { + if (isset($table_def_cache['fd'][$column_name])) + { + $GLOBALS['egw_setup']->oProc->AlterColumn('phpgw_felamimail_cache',$column_name,array( 'type' => 'varchar', 'precision' => '128', 'nullable' => False )); - $GLOBALS['egw_setup']->oProc->AlterColumn('phpgw_felamimail_cache','fmail_foldername',array( - 'type' => 'varchar', - 'precision' => '128', - 'nullable' => False - )); - $GLOBALS['egw_setup']->oProc->AlterColumn('phpgw_felamimail_folderstatus','fmail_accountname',array( - 'type' => 'varchar', - 'precision' => '128', - 'nullable' => False - )); - $GLOBALS['egw_setup']->oProc->AlterColumn('phpgw_felamimail_folderstatus','fmail_foldername',array( + } + if (isset($table_def_folderstatus['fd'][$column_name])) + { + $GLOBALS['egw_setup']->oProc->AlterColumn('phpgw_felamimail_folderstatus',$column_name,array( 'type' => 'varchar', 'precision' => '128', 'nullable' => False )); + } + } } if (substr($GLOBALS['egw_setup']->db->Type,0,5) == 'mysql' && $GLOBALS['egw_setup']->system_charset && $GLOBALS['egw_setup']->db_charset_was && $GLOBALS['egw_setup']->system_charset != $GLOBALS['egw_setup']->db_charset_was) diff --git a/setup/inc/class.setup.inc.php b/setup/inc/class.setup.inc.php index 878ede3da8..b0dc6a7ab5 100644 --- a/setup/inc/class.setup.inc.php +++ b/setup/inc/class.setup.inc.php @@ -1004,11 +1004,11 @@ * @param array $tables array with possible table-names * @return string/boolean tablename or false */ - function table_exist($tables) + function table_exist($tables,$force_refresh=False) { - static $table_names; + static $table_names = False; - if (!$table_names) $table_names = $this->db->table_names(); + if (!$table_names || $force_refresh) $table_names = $this->db->table_names(); if (!$table_names) return false; @@ -1027,16 +1027,18 @@ * * Other tables can always use the most up to date name */ - function set_table_names() + function set_table_names($force_refresh=False) { foreach(array( 'config_table' => array('egw_config','phpgw_config','config'), 'applications_table' => array('egw_applications','phpgw_applications','applications'), + 'accounts_table' => array('egw_accounts','phpgw_accounts'), + 'acl_table' => array('egw_acl','phpgw_acl'), 'lang_table' => array('egw_lang','phpgw_lang','lang'), 'languages_table' => array('egw_languages','phpgw_languages','languages'), ) as $name => $tables) { - $table = $this->table_exist($tables); + $table = $this->table_exist($tables,$force_refresh); if ($table && $table != $this->$name) // only overwrite the default name, if we realy got one (important for new installs) {