--- spam.install.orig	2007-11-26 23:48:26.000000000 +0100
+++ spam.install	2007-12-14 09:49:12.773936892 +0100
@@ -8,8 +8,6 @@
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
-    // TODO: PostgreSQL support -- patches welcome!
-    default:
       /**
        * Provides global and granular per-content-type configurations for all
        * enabled spam filters.  The status allows a filter to be enabled or
@@ -95,6 +93,88 @@
         KEY timestamp (timestamp)
       ) TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;");
 
+    case 'pgsql':
+      /**
+       * tinyint (above) has usually been implemented as integer,
+       * because of the following comment in pgsql docs:
+       * "The type integer is the usual choice, as it offers the best 
+       * balance between range, storage size, and performance.
+       * The smallint type is generally only used if disk space is at a premium.
+       */
+      db_query("CREATE TABLE {spam_filters} (
+	fid serial PRIMARY KEY,
+	gid integer NOT NULL default 0,
+	name varchar(128) NOT NULL default '',
+	module varchar(128) NOT NULL default '',
+	status integer NOT NULL default 0,
+	weight integer NOT NULL default 0,
+	gain integer NOT NULL default 0
+      );");
+      db_query("CREATE INDEX {spam_filters}_gid_key ON {spam_filters} (gid);");
+      db_query("CREATE INDEX {spam_filters}_name_key ON {spam_filters} (name);");
+      db_query("CREATE INDEX {spam_filters}_module_key ON {spam_filters} (module);");
+      db_query("CREATE INDEX {spam_filters}_status_key ON {spam_filters} (status);");
+      db_query("CREATE INDEX {spam_filters}_weight_key ON {spam_filters} (weight);");
+      db_query("CREATE TABLE {spam_filters_groups} (
+        gid serial PRIMARY KEY,
+	name varchar(255) NOT NULL default '',
+	weight integer NOT NULL default 0
+      );");
+      db_query("CREATE INDEX {spam_filters_groups}_weight_key ON {spam_filters_groups} (weight);");
+      db_query("CREATE TABLE {spam_filters_groups_data} (
+	gid serial,
+	content_type varchar(64) NOT NULL default '',
+	CONSTRAINT spam_filters_groups_data_pk PRIMARY KEY(gid,content_type)
+      );");
+      db_query("CREATE INDEX {spam_filters_groups_data}_content_type_key ON {spam_filters_groups_data} (content_type);");
+      /**
+       * Tracks all filtered site content, included both spam and non-spam.
+       */
+      db_query("CREATE TABLE {spam_tracker} (
+	sid serial PRIMARY KEY,
+	content_type varchar(128) NOT NULL default '',
+	content_id integer NOT NULL default 0,
+	score integer NOT NULL default 0,
+	hostname varchar(15) NOT NULL default '',
+	timestamp integer NOT NULL default 0,
+	CONSTRAINT spam_tracker_u UNIQUE(content_id,content_type)
+      );");
+      db_query("CREATE INDEX {spam_tracker}_u_key ON {spam_tracker} (content_id,content_type);");
+      db_query("CREATE INDEX {spam_tracker}_content_type_key ON {spam_tracker} (content_type);");
+      db_query("CREATE INDEX {spam_tracker}_score_key ON {spam_tracker} (score);");
+      db_query("CREATE INDEX {spam_tracker}_hostname_key ON {spam_tracker} (hostname);");
+      db_query("CREATE INDEX {spam_tracker}_timestamp_key ON {spam_tracker} (timestamp);");
+      /**
+       *
+       */
+      db_query("CREATE TABLE {spam_filters_errors} (
+	bid serial PRIMARY KEY,
+	content_type varchar(128) NOT NULL default '',
+	content_id integer NOT NULL default 0,
+	content_hash char(32) NOT NULL default '',
+	hostname varchar(15) NOT NULL default '',
+	timestamp integer NOT NULL default 0,
+	CONSTRAINT spam_filters_errors_u1 UNIQUE(content_id,content_type),
+	CONSTRAINT spam_filters_errors_u2 UNIQUE(content_hash)
+      );");
+      db_query("CREATE INDEX {spam_filters_errors}_content_type_key ON {spam_filters_errors} (content_type);");
+      db_query("CREATE INDEX {spam_filters_errors}_content_hash_key ON {spam_filters_errors} (content_hash);");
+      db_query("CREATE INDEX {spam_filters_errors}_hostname_key ON {spam_filters_errors} (hostname);");
+      db_query("CREATE INDEX {spam_filters_errors}_timestamp_key ON {spam_filters_errors} (timestamp);");
+      /**
+       * Logging mechanism similar to watchdog, but provides additional 
+       * information specific to spam tracking.
+       */
+      db_query("CREATE TABLE {spam_log} (
+	lid serial PRIMARY KEY,
+	sid integer NOT NULL default 0,
+	uid integer NOT NULL default 0,
+	log varchar(255) NOT NULL default '',
+	timestamp integer NOT NULL default 0
+      );");
+      db_query("CREATE INDEX {spam_log}_sid_key ON {spam_log} (sid);");
+      db_query("CREATE INDEX {spam_log}_timestamp_key ON {spam_log} (timestamp);");
+
   }
   drupal_set_message(t('All required spam tables have been created.'));
 }
@@ -103,7 +183,7 @@
  * Completely uninstall the spam module.
  */
 function spam_uninstall() {
-  $tables = array('spam_filters', 'spam_tracker', 'spam_log', 'spam_filters_groups', 'spam_filters_groups_data');
+  $tables = array('spam_filters', 'spam_tracker', 'spam_log', 'spam_filters_groups', 'spam_filters_groups_data','spam_filters_errors');
   foreach ($tables as $table) {
     db_query('DROP TABLE {'. $table .'}');
   }
--- filters/duplicate/duplicate.install.orig	2007-12-02 23:30:12.000000000 +0100
+++ filters/duplicate/duplicate.install	2007-12-14 09:44:30.619680660 +0100
@@ -5,8 +5,6 @@
   switch ($GLOBALS['db_type']) {
     case 'mysql':
     case 'mysqli':
-    // TODO: PostgreSQL support -- patches welcome!
-    default:
       /**
        * Tracks a 32-bit hash and the IP for each piece of content.
        */
@@ -27,6 +25,24 @@
         KEY  (spam),
         KEY  (timestamp)
       ) TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;");
+    case 'pgsql':
+      db_query("CREATE TABLE {spam_duplicate} (
+	iid serial PRIMARY KEY,
+	sid integer NOT NULL default 0,
+	content_hash char(32) NOT NULL default '',
+	hostname varchar(15) NOT NULL default '',
+	duplicate_hash integer NOT NULL default 0,
+	duplicate_ip integer NOT NULL default 0,
+	spam integer NOT NULL default 0,
+	expired integer NOT NULL default 0,
+	timestamp integer NOT NULL default 0
+      );");
+      db_query("CREATE INDEX {spam_duplicate}_sid_key ON {spam_duplicate} (sid);");
+      db_query("CREATE INDEX {spam_duplicate}_content_hash_key ON {spam_duplicate} (content_hash);");
+      db_query("CREATE INDEX {spam_duplicate}_hostname_key ON {spam_duplicate} (hostname);");
+      db_query("CREATE INDEX {spam_duplicate}_spam_key ON {spam_duplicate} (spam);");
+      db_query("CREATE INDEX {spam_duplicate}_timestamp_key ON {spam_duplicate} (timestamp);");
+
   }
 }
 
