Index: database/database.pgsql
===================================================================
RCS file: /cvs/drupal/drupal/database/database.pgsql,v
retrieving revision 1.140
diff -u -p -r1.140 database.pgsql
--- database/database.pgsql	18 Oct 2005 14:41:26 -0000	1.140
+++ database/database.pgsql	3 Nov 2005 15:33:21 -0000
@@ -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
Index: database/updates.inc
===================================================================
RCS file: /cvs/drupal/drupal/database/updates.inc,v
retrieving revision 1.140
diff -u -p -r1.140 updates.inc
--- database/updates.inc	22 Oct 2005 15:14:46 -0000	1.140
+++ database/updates.inc	3 Nov 2005 15:33:21 -0000
@@ -23,8 +23,41 @@
  *   return $ret;
  * }
  *
+ *
+ * A quick guide to mysql2postgres conversion. Usually (but not allways!) you will use following sql statements:
+ *
+ * - Adding a key (an index):
+ * mysql: ALTER TABLE {$table} ADD KEY $column ($column)
+ * pgsql: CREATE INDEX {$table}_$column_idx ON {$table}($column)  // Please note the _idx "extension"
+ * 
+ * - Adding a primary key:
+ * mysql: ALTER TABLE {$table} ADD PRIMARY KEY $column ($column)
+ * pgsql: ALTER TABLE {$table} ADD PRIMARY KEY ($column)
+ *
+ * - Dropping a primary key:
+ * mysql: ALTER TABLE {$table} DROP PRIMARY KEY
+ * pgsql: ALTER TABLE {$table} DROP CONSTRAINT {$table}_pkey
+ *
+ * - Dropping a column:
+ * mysql: ALTER TABLE {$table} DROP $column
+ * pgsql: ALTER TABLE {$table} RENAME $column TO $column_old  // For compatibility reasons we don't drop columns but rename them
+ * 
+ * - Dropping an index:
+ * mysql: ALTER TABLE {$table} DROP INDEX $index
+ * pgsql: DROP INDEX {$table}_$column_idx                            // When index was defined by CREATE INDEX
+ * pgsql: ALTER TABLE {$table} DROP CONSTRAINT {$table}_$column_key  // In case of UNIQUE($column)
+ *
+ * - Adding a column: (an example)
+ * mysql: $ret = update_sql("ALTER TABLE {vocabulary} ADD tags tinyint(3) unsigned default '0' NOT NULL");
+ * pgsql: db_add_column($ret, 'vocabulary', 'tags', 'smallint', array('default' => 0, 'not null' => TRUE));
+ *
+ * - Changing a column: (an example):
+ * mysql: $ret[] = update_sql("ALTER TABLE {locales_source} CHANGE location location varchar(255) NOT NULL default ''");
+ * pgsql: db_change_column($ret, 'locales_source', 'location', 'location', 'varchar(255)', array('not null' => TRUE, 'default' => ''));
+ *
  */
 
+
 // 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 +100,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 +553,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('default' => 0, 'not null' => TRUE));
   }
 
   return $ret;
@@ -528,10 +562,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'"); 
   }
   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 +575,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 +608,33 @@ 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');
+    $ret[] = update_sql("ALTER TABLE {blocks} RENAME types TO types_old"); 
   }
   return $ret;
 }
@@ -615,7 +650,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");
+      $ret[] = update_sql("CREATE INDEX {users}_access_idx on {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 +675,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 +689,16 @@ function update_138() {
 
 function update_139() {
   $ret = array();
-  $ret[] = update_sql("ALTER TABLE {accesslog} ADD timer int(10) unsigned NOT NULL default '0'");
+  switch ($GLOBALS['db_type']) {
+    case 'pgsql':
+      db_add_column($ret, 'accesslog', 'timer', 'int', array('not null' => TRUE, 'default' => 0));
+      break;
+    case 'mysql':
+    case 'mysqli':
+      $ret[] = update_sql("ALTER TABLE {accesslog} ADD timer int(10) unsigned NOT NULL default '0'");
+      break;
+  }
+ 
   return $ret;
 }
 
@@ -658,7 +709,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)");
+    $ret[] = update_sql("CREATE INDEX {url_alias}_src_idx ON {url_alias}(src)");
   }
   return $ret;
 }
@@ -673,7 +724,15 @@ function update_141() {
 
 function update_142() {
   $ret = array();
-  $ret[] = update_sql("ALTER TABLE {watchdog} ADD COLUMN referer varchar(128) NOT NULL");
+  switch ($GLOBALS['db_type']) {
+    case 'pgsql':
+      db_add_column($ret, 'watchdog', 'referer', 'varchar(128)', array('not null' => TRUE, 'default' => ''));
+      break;
+    case 'mysql':
+    case 'mysqli':
+      $ret[] = update_sql("ALTER TABLE {watchdog} ADD COLUMN referer varchar(128) NOT NULL");
+      break;
+  }
   return $ret;
 }
 
@@ -682,11 +741,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 +761,13 @@ 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" column
+    $ret[] = update_sql("DROP INDEX {node}_title_idx");
+    db_change_column($ret, 'node', 'type', 'type', 'varchar(32)', array('not null' => TRUE, 'default' => ''));
+    // Let's recreate the indexes
+    $ret[] = update_sql("CREATE INDEX {node}_type_idx ON {node}(type)"); 
+    $ret[] = update_sql("CREATE INDEX {node}_title_type_idx ON {node}(title,type)"); 
+    $ret[] = update_sql("CREATE INDEX {node}_status_type_nid_idx ON {node}(status,type,nid)");
   }
   return $ret;
 }
@@ -710,8 +775,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 +845,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}");
+    $ret[] = update_sql('CREATE INDEX {node_revisions}_uid_idx ON {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));
+    
+    $ret[] = update_sql("ALTER TABLE {book} DROP CONSTRAINT {book}_pkey"); 
+    $ret[] = update_sql("ALTER TABLE {forum} DROP CONSTRAINT {forum}_pkey"); 
+    $ret[] = update_sql("ALTER TABLE {files} DROP CONSTRAINT {files}_pkey"); 
+    
     $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");
-
+    
+    $ret[] = update_sql("ALTER TABLE {book} ADD PRIMARY KEY (vid)");
+    $ret[] = update_sql("ALTER TABLE {forum} ADD PRIMARY KEY (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 != ''");
+    
+    $ret[] = update_sql('CREATE INDEX {node}_vid_idx ON {node}(vid)');
+    $ret[] = update_sql('CREATE INDEX {forum}_vid_idx ON {forum}(vid)');
+    $ret[] = update_sql('CREATE INDEX {files}_fid_idx ON {files}(fid)');
+    $ret[] = update_sql('CREATE INDEX {files}_vid_idx ON {files}(vid)');
   }
 
   // Move logs too.
@@ -796,6 +902,11 @@ function update_146() {
     $ret[] = update_sql("ALTER TABLE {node} DROP revisions");
   }
   else { // pgsql
+    $ret[] = update_sql("ALTER TABLE {book} RENAME log TO log_old"); 
+    $ret[] = update_sql("ALTER TABLE {node} RENAME teaser TO teaser_old"); 
+    $ret[] = update_sql("ALTER TABLE {node} RENAME body TO body_old"); 
+    $ret[] = update_sql("ALTER TABLE {node} RENAME format TO format_old"); 
+    $ret[] = update_sql("ALTER TABLE {node} RENAME revisions TO revisions_old"); 
   }
 
   return $ret;
@@ -818,9 +929,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 +945,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 ''");
@@ -889,29 +1000,26 @@ 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)
-                           )");
-
+        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_from_sid_type_idx ON {search_index}(fromsid, fromtype)");
-      $ret[] = update_sql("CREATE INDEX search_index_word_idx ON {search_index}(word)");
+        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
-                           )");
-      $ret[] = update_sql("CREATE INDEX search_total_word_idx ON {search_total}(word)");
+        word varchar(50) NOT NULL default '',
+        count float default NULL,
+        PRIMARY KEY(word))");
       break;
     default:
       break;
@@ -919,6 +1027,122 @@ function update_150() {
   return $ret;
 }
 
+function update_151() {
+  $ret = array();
+  
+  // Postgresql only update
+  switch ($GLOBALS['db_type']) {
+    case 'pgsql':    
+      $ret[] = update_sql("ALTER TABLE {forum} RENAME shadow TO shadow_old");
+      break;
+    case 'mysql':
+    case 'mysqli':
+      break;
+  }
+ 
+  return $ret;
+}
+
+
+
+/**
+ * Adds a column to a database. Uses syntax appropriate for PostgreSQL.
+ * Saves result of SQL commands in $ret array.
+ *
+ * Note: when you add a column with NOT NULL and you are not sure if there are rows in table already,
+ *  you MUST also add DEFAULT. Otherwise PostgreSQL won't work if the table is not empty. If NOT NULL and 
+ *  DEFAULT is set the Postgresql version will set values of the added column in old rows to the DEFAULT value.
+ *
+ * @param $ret 
+ *  Array to which results will be added.
+ * @param $table 
+ *  Name of the table, without {}
+ * @param $column 
+ *  Name of the column
+ * @param $type
+ *  Type of column
+ * @param $attributes
+ *  Additional optional attributes. Recognized atributes:
+ *    - 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('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['default'] === FALSE) {
+      $default = '';
+    } 
+    else {
+      $default_val = "'$attributes[default]'"; 
+      $default = "default '$attributes[default]'";
+    }
+  }
+  
+  $ret[] = update_sql("ALTER TABLE {". $table ."} ADD $column $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 PostgreSQL.
+ * Saves result of SQL commands in $ret array.
+ *
+ * @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:
+ *    - 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('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['default'] === FALSE) {
+      $default = '';
+    } 
+    else {
+      $default_val = "'$attributes[default]'"; 
+      $default = "default '$attributes[default]'";
+    }
+  }
+  
+  $ret[] = update_sql("ALTER TABLE {". $table ."} RENAME $column TO ". $column ."_old");
+  $ret[] = update_sql("ALTER TABLE {". $table ."} ADD $column_new $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");
+}
+
+
 function update_sql($sql) {
   $edit = $_POST["edit"];
   $result = db_query($sql);
