diff -Naurp drupal-head/database/database.pgsql drupal-head-db_add_column-29082/database/database.pgsql --- drupal-head/database/database.pgsql 2005-10-25 11:47:20.000000000 +0200 +++ drupal-head-db_add_column-29082/database/database.pgsql 2005-10-31 16:38:15.000000000 +0100 @@ -138,7 +138,6 @@ CREATE TABLE book ( weight smallint NOT NULL default '0', PRIMARY KEY (vid) ); -CREATE INDEX book_vid_idx ON book(vid); CREATE INDEX book_nid_idx ON book(nid); CREATE INDEX book_parent ON book(parent); @@ -295,7 +294,6 @@ CREATE TABLE forum ( nid integer NOT NULL default '0', vid integer NOT NULL default '0', tid integer NOT NULL default '0', - shadow integer NOT NULL default '0', PRIMARY KEY (nid) ); CREATE INDEX forum_tid_idx ON forum(tid); @@ -424,7 +422,7 @@ CREATE TABLE node ( PRIMARY KEY (nid) ); CREATE INDEX node_type_idx ON node(type); -CREATE INDEX node_title_idx ON node(title,type); +CREATE INDEX node_title_type_idx ON node(title,type); CREATE INDEX node_status_idx ON node(status); CREATE INDEX node_uid_idx ON node(uid); CREATE INDEX node_moderate_idx ON node (moderate); @@ -432,6 +430,7 @@ CREATE INDEX node_promote_status_idx ON CREATE INDEX node_created ON node(created); CREATE INDEX node_changed ON node(changed); CREATE INDEX node_vid_idx ON node(vid); +CREATE INDEX node_status_type_nid_idx ON node(status,type,nid); -- -- Table structure for table `node_access` @@ -522,7 +521,7 @@ CREATE TABLE url_alias ( PRIMARY KEY (pid) ); CREATE INDEX url_alias_dst_idx ON url_alias(dst); -CREATE INDEX url_alias_src ON url_alias(src); +CREATE INDEX url_alias_src_idx ON url_alias(src); -- -- Table structure for permission -- @@ -577,9 +576,9 @@ CREATE TABLE role ( CREATE TABLE search_dataset ( sid integer NOT NULL default '0', type varchar(16) default NULL, - data text NOT NULL default '', - KEY sid_type (sid, type) + data text NOT NULL default '' ); +CREATE INDEX search_dataset_sid_type_idx on search_dataset(sid, type); -- -- Table structure for search_index @@ -594,7 +593,7 @@ CREATE TABLE search_index ( score float default NULL ); CREATE INDEX search_index_sid_type_idx ON search_index(sid, type); -CREATE INDEX search_index_from_sid_type_idx ON search_index(fromsid, fromtype); +CREATE INDEX search_index_fromsid_fromtype_idx ON search_index(fromsid, fromtype); CREATE INDEX search_index_word_idx ON search_index(word); -- @@ -603,9 +602,9 @@ CREATE INDEX search_index_word_idx ON se CREATE TABLE search_total ( word varchar(50) NOT NULL default '', - count float default NULL + count float default NULL, + PRIMARY KEY(word) ); -CREATE INDEX search_total_word_idx ON search_total(word); -- -- Table structure for sessions diff -Naurp drupal-head/database/updates.inc drupal-head-db_add_column-29082/database/updates.inc --- drupal-head/database/updates.inc 2005-10-25 11:47:20.000000000 +0200 +++ drupal-head-db_add_column-29082/database/updates.inc 2005-10-31 16:38:15.000000000 +0100 @@ -25,6 +25,17 @@ * */ +switch ($GLOBALS['db_type']) { + case 'pgsql': + include_once 'database/updates.pgsql.inc'; + break; + case 'mysql': + case 'mysqli': + include_once 'database/updates.mysql.inc'; + break; +} + + // Define the various updates in an array("date : comment" => "function"); $sql_updates = array( "2004-10-31: first update since Drupal 4.5.0 release" => "update_110", @@ -67,7 +78,8 @@ $sql_updates = array( "2005-09-07" => "update_147", "2005-09-18" => "update_148", "2005-09-27" => "update_149", - "2005-10-15" => "update_150" + "2005-10-15" => "update_150", + "2005-10-28" => "update_151" ); function update_110() { @@ -519,7 +531,7 @@ function update_129() { $ret[] = update_sql("ALTER TABLE {vocabulary} ADD tags tinyint(3) unsigned default '0' NOT NULL"); } elseif ($GLOBALS['db_type'] == 'pgsql') { - $ret[] = update_sql("ALTER TABLE {vocabulary} ADD tags smallint default '0' NOT NULL"); + db_add_column($ret, 'vocabulary', 'tags', 'smallint', array('unsigned' => TRUE, 'default' => 0, 'not null' => TRUE)); } return $ret; @@ -528,10 +540,10 @@ function update_129() { function update_130() { $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { - $ret[] = update_sql("ALTER TABLE {sessions} ADD cache int(11) NOT NULL default '0' AFTER timestamp"); + $ret[] = update_sql("ALTER TABLE {sessions} ADD cache int(11) NOT NULL default '0'"); // It is said that we should not depend on column orders thus removing "AFTER column" } elseif ($GLOBALS['db_type'] == 'pgsql') { - $ret[] = update_sql("ALTER TABLE {sessions} ADD cache int(11) NOT NULL default '0' AFTER timestamp"); + db_add_column($ret, 'sessions', 'cache', 'int', array('default' => 0, 'not null' => TRUE)); } return $ret; } @@ -541,11 +553,10 @@ function update_131() { if ($GLOBALS['db_type'] == 'mysql') { $ret[] = update_sql("ALTER TABLE {boxes} DROP INDEX title"); - $ret[] = update_sql("ALTER TABLE {boxes} ADD INDEX title (title)"); + // Removed recreation of the index, which is not present in the db schema } elseif ($GLOBALS['db_type'] == 'pgsql') { - $ret[] = update_sql("DROP INDEX boxes_title_idx");; - $ret[] = update_sql("CREATE INDEX title ON {boxes} (title)"); + $ret[] = update_sql("ALTER TABLE {boxes} DROP CONSTRAINT {boxes}_title_key;"); } return $ret; @@ -575,31 +586,34 @@ function update_132() { } function update_133() { - $ret[] = update_sql("CREATE TABLE {contact} ( - subject varchar(255) NOT NULL default '', - recipients longtext NOT NULL default '', - reply longtext NOT NULL default '' - )"); - + $ret = array(); + if ($GLOBALS['db_type'] == 'mysql') { + $ret[] = update_sql("CREATE TABLE {contact} ( + subject varchar(255) NOT NULL default '', + recipients longtext NOT NULL default '', + reply longtext NOT NULL default '' + )"); $ret[] = update_sql("ALTER TABLE {users} ADD login int(11) NOT NULL default '0'"); } elseif ($GLOBALS['db_type'] == 'pgsql') { - $ret[] = update_sql("ALTER TABLE {users} ADD login integer"); - $ret[] = update_sql("ALTER TABLE {users} ALTER COLUMN login SET NOT NULL"); - $ret[] = update_sql("ALTER TABLE {users} ALTER COLUMN login SET DEFAULT '0'"); + // Table {contact} is changed in update_143() so I have moved it's creation there. + // It was never created here for postgres because of errors. + + db_add_column($ret, 'users', 'login', 'int', array('default' => 0, 'not null' => TRUE)); } return $ret; } function update_134() { + $ret = array(); if ($GLOBALS['db_type'] == 'mysql') { $ret[] = update_sql('ALTER TABLE {blocks} DROP types'); } else { - // Postgres can only drop columns since 7.4 - #$ret[] = update_sql('ALTER TABLE {blocks} DROP types'); + // We rename the column to note it's not longer used + db_drop_column($ret, 'blocks', 'types'); } return $ret; } @@ -615,7 +629,19 @@ function update_135() { function update_136() { $ret = array(); - $ret[] = update_sql("ALTER TABLE {users} CHANGE COLUMN changed access int(11) NOT NULL default '0'"); + + switch ($GLOBALS['db_type']) { + case 'pgsql': + $ret[] = update_sql("DROP INDEX {users}_changed_idx"); // We drop the index first because it won't be renamed + $ret[] = update_sql("ALTER TABLE {users} RENAME changed TO access"); + db_add_key($ret, 'users', 'access'); // Re-add the index + break; + case 'mysql': + case 'mysqli': + $ret[] = update_sql("ALTER TABLE {users} CHANGE COLUMN changed access int(11) NOT NULL default '0'"); + break; + } + $ret[] = update_sql('UPDATE {users} SET access = login WHERE login > created'); $ret[] = update_sql('UPDATE {users} SET access = created WHERE access = 0'); return $ret; @@ -628,12 +654,7 @@ function update_137() { $ret[] = update_sql("ALTER TABLE {locales_source} CHANGE location location varchar(255) NOT NULL default ''"); } elseif ($GLOBALS['db_type'] == 'pgsql') { - $ret[] = update_sql("ALTER TABLE {locales_source} RENAME location TO location_old"); - $ret[] = update_sql("ALTER TABLE {locales_source} ADD location varchar(255)"); - $ret[] = update_sql("UPDATE {locales_source} SET location = location_old"); - $ret[] = update_sql("ALTER TABLE {locales_source} ALTER location SET NOT NULL"); - $ret[] = update_sql("ALTER TABLE {locales_source} ALTER location SET DEFAULT ''"); - $ret[] = update_sql("ALTER TABLE {locales_source} DROP location_old"); + db_change_column($ret, 'locales_source', 'location', 'location', 'varchar(255)', array('not null' => TRUE, 'default' => '')); } return $ret; } @@ -647,7 +668,7 @@ function update_138() { function update_139() { $ret = array(); - $ret[] = update_sql("ALTER TABLE {accesslog} ADD timer int(10) unsigned NOT NULL default '0'"); + db_add_column($ret, 'accesslog', 'timer', 'int', array('unsigned' => TRUE, 'not null' => TRUE, 'default' => 0)); return $ret; } @@ -658,7 +679,7 @@ function update_140() { $ret[] = update_sql("ALTER TABLE {url_alias} ADD INDEX (src)"); } elseif ($GLOBALS['db_type'] == 'pgsql') { - $ret[] = update_sql("CREATE INDEX url_alias_src ON {url_alias}(src)"); + db_add_key($ret, 'url_alias', 'src'); } return $ret; } @@ -673,7 +694,7 @@ function update_141() { function update_142() { $ret = array(); - $ret[] = update_sql("ALTER TABLE {watchdog} ADD COLUMN referer varchar(128) NOT NULL"); + db_add_column($ret, 'watchdog', 'referer', 'varchar(128)', array('not null' => TRUE, 'default' => '')); return $ret; } @@ -682,11 +703,16 @@ function update_143() { if ($GLOBALS['db_type'] == 'mysql') { $ret[] = update_sql("ALTER TABLE {contact} CHANGE subject category VARCHAR(255) NOT NULL "); + $ret[] = update_sql("ALTER TABLE {contact} ADD PRIMARY KEY (category)"); } elseif ($GLOBALS['db_type'] == 'pgsql') { - $ret[] = update_sql("ALTER TABLE {contact} RENAME COLUMN subject TO category"); + // Why the table is created here? See update_133(). + $ret[] = update_sql("CREATE TABLE {contact} ( + category varchar(255) NOT NULL default '', + recipients text NOT NULL default '', + reply text NOT NULL default '', + PRIMARY KEY (category))"); } - $ret[] = update_sql("ALTER TABLE {contact} ADD PRIMARY KEY (category)"); return $ret; } @@ -697,12 +723,12 @@ function update_144() { $ret[] = update_sql("ALTER TABLE {node} CHANGE type type VARCHAR(32) NOT NULL"); } elseif ($GLOBALS['db_type'] == 'pgsql') { - $ret[] = update_sql("ALTER TABLE {node} RENAME type TO type_old"); - $ret[] = update_sql("ALTER TABLE {node} ADD type varchar(32)"); - $ret[] = update_sql("ALTER TABLE {node} ALTER type SET NOT NULL"); - $ret[] = update_sql("ALTER TABLE {node} ALTER type SET DEFAULT ''"); - $ret[] = update_sql("UPDATE {node} SET type = type_old"); - $ret[] = update_sql("ALTER TABLE {node} DROP type_old"); + $ret[] = update_sql("DROP INDEX {node}_type_idx"); // Drop indexes using "type" + $ret[] = update_sql("DROP INDEX {node}_title_idx"); + db_change_column($ret, 'node', 'type', 'type', 'varchar(32)', array('not null' => TRUE, 'default' => '')); + db_add_key($ret, 'node', 'type'); // Let's recreate the indexes + $ret[] = update_sql("CREATE INDEX {node}_title_type_idx ON {node}(title,type)"); // TODO multi-keys indexes function? + $ret[] = update_sql("CREATE INDEX {node}_status_type_nid_idx ON {node}(status,type,nid)"); } return $ret; } @@ -710,8 +736,18 @@ function update_144() { function update_145() { $default_theme = variable_get('theme_default', 'bluemarine'); $ret = array(); - $ret[] = update_sql("ALTER TABLE {blocks} CHANGE region region varchar(64) default 'left' NOT NULL"); - $ret[] = update_sql("ALTER TABLE {blocks} ADD theme varchar(255) NOT NULL default ''"); + + switch ($GLOBALS['db_type']) { + case 'pgsql': + db_change_column($ret, 'blocks', 'region', 'region', 'varchar(64)', array('default' => 'left', 'not null' => TRUE)); + db_add_column($ret, 'blocks', 'theme', 'varchar(255)', array('not null' => TRUE, 'default' => '')); + break; + case 'mysql': + case 'mysqli': + $ret[] = update_sql("ALTER TABLE {blocks} CHANGE region region varchar(64) default 'left' NOT NULL"); + $ret[] = update_sql("ALTER TABLE {blocks} ADD theme varchar(255) NOT NULL default ''"); + break; + } // Intialize block data for default theme $ret[] = update_sql("UPDATE {blocks} SET region = 'left' WHERE region = '0'"); @@ -770,16 +806,47 @@ function update_146() { $ret[] = update_sql("INSERT INTO {sequences} (name, id) VALUES ('{node_revisions}_vid', $vid)"); } else { // pgsql - $ret[] = update_sql("CREATE TABLE {node_revisions} AS - SELECT nid, nid AS vid, uid, type, title, body, teaser, changed AS timestamp, format - FROM {node}"); + $ret[] = update_sql("CREATE TABLE {node_revisions} ( + nid integer NOT NULL default '0', + vid integer NOT NULL default '0', + uid integer NOT NULL default '0', + title varchar(128) NOT NULL default '', + body text NOT NULL default '', + teaser text NOT NULL default '', + log text NOT NULL default '', + timestamp integer NOT NULL default '0', + format int NOT NULL default '0', + PRIMARY KEY (nid,vid))"); + $ret[] = update_sql("INSERT INTO {node_revisions} + SELECT nid, nid AS vid, uid, title, body, teaser, changed AS timestamp, format + FROM {node}"); + db_add_key($ret, 'node_revisions', 'uid'); + $vid = db_next_id('{node}_nid'); + $ret[] = update_sql("CREATE SEQUENCE {node_revisions}_vid_seq INCREMENT 1 START $vid"); + db_add_column($ret, 'node', 'vid', 'int', array('not null' => TRUE, 'default' => 0)); + db_add_column($ret, 'files', 'vid', 'int', array('not null' => TRUE, 'default' => 0)); + db_add_column($ret, 'book', 'vid', 'int', array('not null' => TRUE, 'default' => 0)); + db_add_column($ret, 'forum', 'vid', 'int', array('not null' => TRUE, 'default' => 0)); + + db_drop_primary_key($ret, 'book'); + db_drop_primary_key($ret, 'forum'); + db_drop_primary_key($ret, 'files'); + $ret[] = update_sql("UPDATE {node} SET vid = nid"); $ret[] = update_sql("UPDATE {forum} SET vid = nid"); $ret[] = update_sql("UPDATE {book} SET vid = nid"); $ret[] = update_sql("UPDATE {files} SET vid = nid"); - + + db_add_primary_key($ret, 'book', 'vid'); + db_add_primary_key($ret, 'forum', 'nid'); // We, The Postgres, will do it database.* way, not update() way. + $ret[] = update_sql("CREATE TABLE {old_revisions} AS SELECT nid, type, revisions FROM {node} WHERE revisions != ''"); + + db_add_key($ret, 'node', 'vid'); + db_add_key($ret, 'forum', 'vid'); + db_add_key($ret, 'files', 'fid'); + db_add_key($ret, 'files', 'vid'); } // Move logs too. @@ -796,6 +863,11 @@ function update_146() { $ret[] = update_sql("ALTER TABLE {node} DROP revisions"); } else { // pgsql + db_drop_column($ret, 'book', 'log'); + db_drop_column($ret, 'node', 'teaser'); + db_drop_column($ret, 'node', 'body'); + db_drop_column($ret, 'node', 'format'); + db_drop_column($ret, 'node', 'revisions'); } return $ret; @@ -818,9 +890,7 @@ function update_148() { // Add support for tracking users' session ids (useful for tracking anon users) switch ($GLOBALS['db_type']) { case 'pgsql': - $ret[] = update_sql("ALTER TABLE {accesslog} ADD sid varchar(32)"); - $ret[] = update_sql("ALTER TABLE {accesslog} ALTER sid SET NOT NULL"); - $ret[] = update_sql("ALTER TABLE {accesslog} ALTER sid SET DEFAULT ''"); + db_add_column($ret, 'accesslog', 'sid', 'varchar(32)', array('not null' => TRUE, 'default' => '')); break; case 'mysql': case 'mysqli': @@ -836,6 +906,8 @@ function update_149() { switch ($GLOBALS['db_type']) { case 'pgsql': + db_add_column($ret, 'files', 'description', 'varchar(255)', array('not null' => TRUE, 'default' => '')); + break; case 'mysql': case 'mysqli': $ret[] = update_sql("ALTER TABLE {files} ADD COLUMN description VARCHAR(255) NOT NULL DEFAULT ''"); @@ -888,30 +960,27 @@ function update_150() { )"); break; case 'pgsql': - $ret[] = update_sql("CREATE TABLE {search_dataset} ( - sid integer NOT NULL default '0', - type varchar(16) default NULL, - data text NOT NULL default '', - KEY sid_type (sid, type) - )"); - - $ret[] = update_sql("CREATE TABLE {search_index} ( - word varchar(50) NOT NULL default '', - sid integer NOT NULL default '0', - type varchar(16) default NULL, - fromsid integer NOT NULL default '0', - fromtype varchar(16) default NULL, - score float default NULL - )"); - $ret[] = update_sql("CREATE INDEX search_index_sid_type_idx ON {search_index}(sid, type)"); - $ret[] = update_sql("CREATE INDEX search_index_from_sid_type_idx ON {search_index}(fromsid, fromtype)"); - $ret[] = update_sql("CREATE INDEX search_index_word_idx ON {search_index}(word)"); - - $ret[] = update_sql("CREATE TABLE {search_total} ( - word varchar(50) NOT NULL default '', - count float default NULL - )"); - $ret[] = update_sql("CREATE INDEX search_total_word_idx ON {search_total}(word)"); + $ret[] = update_sql("CREATE TABLE search_dataset ( + sid integer NOT NULL default '0', + type varchar(16) default NULL, + data text NOT NULL default '')"); + $ret[] = update_sql("CREATE INDEX search_dataset_sid_type_idx on search_dataset(sid, type)"); + + $ret[] = update_sql("CREATE TABLE search_index ( + word varchar(50) NOT NULL default '', + sid integer NOT NULL default '0', + type varchar(16) default NULL, + fromsid integer NOT NULL default '0', + fromtype varchar(16) default NULL, + score float default NULL)"); + $ret[] = update_sql("CREATE INDEX search_index_sid_type_idx ON search_index(sid, type)"); + $ret[] = update_sql("CREATE INDEX search_index_fromsid_fromtype_idx ON search_index(fromsid, fromtype)"); + $ret[] = update_sql("CREATE INDEX search_index_word_idx ON search_index(word)"); + + $ret[] = update_sql("CREATE TABLE search_total ( + word varchar(50) NOT NULL default '', + count float default NULL, + PRIMARY KEY(word))"); break; default: break; @@ -919,6 +988,23 @@ function update_150() { return $ret; } +function update_151() { + $ret = array(); + + // Postgresql only update + switch ($GLOBALS['db_type']) { + case 'pgsql': + db_drop_column($ret, 'forum', 'shadow'); + break; + case 'mysql': + case 'mysqli': + break; + } + + return $ret; +} + + function update_sql($sql) { $edit = $_POST["edit"]; $result = db_query($sql); diff -Naurp drupal-head/database/updates.mysql.inc drupal-head-db_add_column-29082/database/updates.mysql.inc --- drupal-head/database/updates.mysql.inc 1970-01-01 01:00:00.000000000 +0100 +++ drupal-head-db_add_column-29082/database/updates.mysql.inc 2005-10-31 16:38:15.000000000 +0100 @@ -0,0 +1,136 @@ + TRUE/FALSE + * - not null => TRUE/FALSE + * - default => NULL/FALSE/value (without '') + * @return + * nothing, but modifies $ret parametr. + */ +function db_add_column(&$ret, $table, $column, $type, $attributes = array()) { + if (array_key_exists('unsigned', $attributes) and $attributes['unsigned']) { + $unsigned = 'unsigned'; + } + if (array_key_exists('not null', $attributes) and $attributes['not null']) { + $not_null = 'NOT NULL'; + } + if (array_key_exists('default', $attributes)) { + if (is_null($attributes['default'])) { + $default = 'default NULL'; + } + elseif ($attributes['defaul'] === FALSE) { + $default = ''; + } + else { + $default = "default '$attributes[default]'"; + } + } + + $ret[] = update_sql("ALTER TABLE {". $table ."} ADD $column $type $unsigned $not_null $default"); +} + +/** + * Changes a column definition. Uses syntax appropriate for used db (MySQL/PostgreSQL). + * Saves result of SQL commands in $ret array. + * + * Differences between MySQL and PostgreSQL: + * - PostgreSQL do not support _unsigned_, it's ignored. + * - all _tinyint_, _smallint_ etc integer-types (any type with 'int' in the name) are converted + * to INTEGER for PostgreSQL. + * - all *text* types (longtext, mediumtext etc) are converted to TEXT for PostgreSQL + * - FIXME: when changing a column in mysql the PRIMARY KEY attribute is retained. In Postgres, due to the + * nature of changing process (i.e. dropping a column) this attribute is dropped. How to workaround it? + * Need to check other attributes too (e.g. NOT NULL, index etc). + * + * TODO: add more attributes? Like primary key, key (mysql: synonym for unique), unique, index, + * auto increment ? (mysql: must be indexed and must have a default) + * + * TODO: when setting NOT NOLL, and DEFAULT is set, update the table to default WHERE column IS NULL ? + * + * @param $ret + * Array to which results will be added. + * @param $table + * Name of the table, without {} + * @param $column + * Name of the column to change + * @param $column_new + * New name for the column (set to the same as $column if you don't want to change the name) + * @param $type + * Type of column + * @param $attributes + * Additional optional attributes. Recognized atributes: + * - unsigned => TRUE/FALSE + * - not null => TRUE/FALSE + * - default => NULL/FALSE/value (without '') + * @return + * nothing, but modifies $ret parametr. + */ +function db_change_column(&$ret, $table, $column, $column_new, $type, $attributes = array()) { + if (array_key_exists('unsigned', $attributes) and $attributes['unsigned']) { + $unsigned = 'unsigned'; + } + if (array_key_exists('not null', $attributes) and $attributes['not null']) { + $not_null = 'NOT NULL'; + } + if (array_key_exists('default', $attributes)) { + if (is_null($attributes['default'])) { + $default = 'default NULL'; + } + elseif ($attributes['default'] === FALSE) { + $default = ''; + } + else { + $default = "default '$attributes[default]'"; + } + } + + $ret[] = update_sql("ALTER TABLE {". $table ."} CHANGE $column $column_new $type $unsigned $not_null $default"); +} + + diff -Naurp drupal-head/database/updates.pgsql.inc drupal-head-db_add_column-29082/database/updates.pgsql.inc --- drupal-head/database/updates.pgsql.inc 1970-01-01 01:00:00.000000000 +0100 +++ drupal-head-db_add_column-29082/database/updates.pgsql.inc 2005-10-31 16:38:15.000000000 +0100 @@ -0,0 +1,156 @@ + TRUE/FALSE + * - not null => TRUE/FALSE + * - default => NULL/FALSE/value (without '') + * @return + * nothing, but modifies $ret parametr. + */ +function db_add_column(&$ret, $table, $column, $type, $attributes = array()) { + $pg_type = (preg_match('/int/i', $type)) ? 'int' : $type; + $pg_type = (preg_match('/text/i', $type)) ? 'text' : $type; + if (array_key_exists('not null', $attributes) and $attributes['not null']) { + $not_null = 'NOT NULL'; + } + if (array_key_exists('default', $attributes)) { + if (is_null($attributes['default'])) { + $default_val = 'NULL'; + $default = 'default NULL'; + } + elseif ($attributes['defaul'] === FALSE) { + $default = ''; + } + else { + $default_val = "'$attributes[default]'"; + $default = "default '$attributes[default]'"; + } + } + + $ret[] = update_sql("ALTER TABLE {". $table ."} ADD $column $pg_type"); + if ($default) { + $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $column SET $default"); + } + if ($not_null) { + if ($default) { + $ret[] = update_sql("UPDATE {". $table ."} SET $column = $default_val"); + } + $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $column SET NOT NULL"); + } +} + +/** + * Changes a column definition. Uses syntax appropriate for used db (MySQL/PostgreSQL). + * Saves result of SQL commands in $ret array. + * + * Differences between MySQL and PostgreSQL: + * - PostgreSQL do not support _unsigned_, it's ignored. + * - all _tinyint_, _smallint_ etc integer-types (any type with 'int' in the name) are converted + * to INTEGER for PostgreSQL. + * - all *text* types (longtext, mediumtext etc) are converted to TEXT for PostgreSQL + * - FIXME: when changing a column in mysql the PRIMARY KEY attribute is retained. In Postgres, due to the + * nature of changing process (i.e. dropping a column) this attribute is dropped. How to workaround it? + * Need to check other attributes too (e.g. NOT NULL, index etc). + * + * TODO: add more attributes? Like primary key, key (mysql: synonym for unique), unique, index, + * auto increment ? (mysql: must be indexed and must have a default) + * + * TODO: when setting NOT NOLL, and DEFAULT is set, update the table to default WHERE column IS NULL ? + * + * @param $ret + * Array to which results will be added. + * @param $table + * Name of the table, without {} + * @param $column + * Name of the column to change + * @param $column_new + * New name for the column (set to the same as $column if you don't want to change the name) + * @param $type + * Type of column + * @param $attributes + * Additional optional attributes. Recognized atributes: + * - unsigned => TRUE/FALSE + * - not null => TRUE/FALSE + * - default => NULL/FALSE/value (without '') + * @return + * nothing, but modifies $ret parametr. + */ +function db_change_column(&$ret, $table, $column, $column_new, $type, $attributes = array()) { + $pg_type = (preg_match('/int/i', $type)) ? 'int' : $type; + $pg_type = (preg_match('/text/i', $type)) ? 'text' : $type; + if (array_key_exists('not null', $attributes) and $attributes['not null']) { + $not_null = 'NOT NULL'; + } + if (array_key_exists('default', $attributes)) { + if (is_null($attributes['default'])) { + $default = 'default NULL'; + } + elseif ($attributes['default'] === FALSE) { + $default = ''; + } + else { + $default = "default '$attributes[default]'"; + } + } + + $ret[] = update_sql("ALTER TABLE {". $table ."} RENAME $column TO ". $column ."_old"); + $ret[] = update_sql("ALTER TABLE {". $table ."} ADD $column_new $pg_type"); + $ret[] = update_sql("UPDATE {". $table ."} SET $column_new = ". $column ."_old"); + if ($default) { + $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $column_new SET $default"); + } + if ($not_null) { + $ret[] = update_sql("ALTER TABLE {". $table ."} ALTER $column_new SET NOT NULL"); + } + // We don't drop columns for now + // $ret[] = update_sql("ALTER TABLE {". $table ."} DROP ". $column ."_old"); +} + +