diff src/nabble/model/DbSiteUpdater.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/nabble/model/DbSiteUpdater.java	Thu Mar 21 19:15:52 2019 -0600
@@ -0,0 +1,837 @@
+
+package nabble.model;
+
+import fschmidt.db.DbDatabase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+
+final class DbSiteUpdater {
+	private static final Logger logger = LoggerFactory.getLogger(DbSiteUpdater.class);
+
+	// don't forget to update site.schema
+	static final int version = 167;
+
+	private static class Result {
+		private static final long wait = 2000L;  // 2 seconds
+		private final long waitUntil = System.currentTimeMillis() + wait;
+		private DbSiteUpdater updater;
+		private SQLException sqlException = null;
+		private RuntimeException runtimeException = null;
+		private Error error = null;
+		private final String user;
+
+		private Result(DbDatabase db,String user) {
+			updater = new DbSiteUpdater(db,this,user);
+			this.user = user;
+			updater.start();
+		}
+
+		private synchronized void check() throws SQLException {
+			if( !isDone() ) {
+				long now = System.currentTimeMillis();
+				if( now < waitUntil ) {
+					try {
+						wait( waitUntil - now );
+					} catch(InterruptedException e) {
+						throw new RuntimeException(e);
+					}
+				}
+				if( !isDone() )
+					throw new UpdatingException(user);
+			}
+			if( sqlException != null )
+				throw sqlException;
+			if( runtimeException != null )
+				throw runtimeException;
+			if( error != null )
+				throw error;
+		}
+
+		synchronized boolean isDone() {
+			return updater==null;
+		}
+
+		synchronized void done(Throwable e) {
+			updater = null;
+			if( e != null ) {
+				if( e instanceof SQLException ) {
+					sqlException = (SQLException)e;
+				} else if( e instanceof RuntimeException ) {
+					runtimeException = (RuntimeException)e;
+				} else if( e instanceof Error ) {
+					error = (Error)e;
+				} else {
+					runtimeException = new RuntimeException("invalid exception type",e);
+				}
+			}
+			notifyAll();
+		}
+	}
+
+	private static final Map<String,Result> userResults = new HashMap<String,Result>();
+	private static final Object lock = new Object();
+
+	static void update(String user,DbDatabase db) throws SQLException {
+		if( user.equals("global") )
+			return;  // done from command line
+		getResult(user,db).check();
+	}
+
+	private static Result getResult(String user,DbDatabase db) throws SQLException {
+		synchronized(lock) {
+			Result result = userResults.get(user);
+			if( result == null ) {
+				result = new Result(db,user);
+				userResults.put(user,result);
+			}
+			return result;
+		}
+	}
+
+	// for shell
+	public static void clearResult(long siteId) {
+		String user = SiteKey.getInstance(siteId).schema();
+		synchronized(lock) {
+			userResults.remove(user);
+		}
+	}
+
+
+
+
+	private final Result result;
+	private final DbUpdater up;
+
+	private DbSiteUpdater(DbDatabase db,Result result,String schema) {
+		this.up = new DbUpdater(db,schema);
+		this.result = result;
+	}
+
+	private void start() {
+		try {  // needed for site creation because version is only up to date in current transaction
+			if( up.dbVersion() == version ) {
+				result.done(null);
+				return;
+			}
+		} catch(RuntimeException e) {
+			result.done(e);
+			return;
+		} catch(Error e) {
+			result.done(e);
+			return;
+		}
+		Executors.executeNow(new Runnable(){public void run(){
+			try {
+				go();
+				result.done(null);
+			} catch(SQLException e) {
+				result.done(e);
+			} catch(RuntimeException e) {
+				result.done(e);
+			} catch(Error e) {
+				result.done(e);
+			} finally {
+				if( !result.isDone() )
+					logger.error("result isn't done");
+			}
+		}});
+	}
+
+	void go() throws SQLException {
+		try {
+			update();
+			if( up.databaseVersion() != version )
+				throw new RuntimeException();
+		} finally {
+			up.close();
+		}
+	}
+
+	@Override public String toString() {
+		return "DbSiteUpdater-" + up.schema;
+	}
+
+	private void execCatching(String sql,String exStr) throws SQLException {
+		up.begin();
+		try {
+			up.exec(sql);
+		} catch(SQLException e) {
+			if( !e.getMessage().contains(exStr) )
+				throw e;
+			logger.info(e.toString());
+			up.exec("rollback");
+		}
+		up.commit();
+	}
+
+	void update() throws SQLException {
+		switch( up.dbVersion() ) {
+		case 0:
+			up.execStep( 
+		"\r\n				create index embed_key_site_idx on embed_key(site_id)\r\n			"
+ );
+		case 1:
+			up.execStep( 
+		"\r\n				create index file_avatar_site_idx on file_avatar(site_id)\r\n			"
+ );
+		case 2:
+			up.execStep( 
+		"\r\n				create index file_node_site_idx on file_node(site_id)\r\n			"
+ );
+		case 3:
+			up.execStep( 
+		"\r\n				create index file_temp_site_idx on file_temp(site_id)\r\n			"
+ );
+		case 4:
+			up.execStep( 
+		"\r\n				create index mailing_list_site_idx on mailing_list(site_id)\r\n			"
+ );
+		case 5:
+			up.execStep( 
+		"\r\n				create index node_msg_site_idx on node_msg(site_id)\r\n			"
+ );
+		case 6:
+			up.execStep( 
+		"\r\n				create index node_property_site_idx on node_property(site_id)\r\n			"
+ );
+		case 7:
+			up.execStep( 
+		"\r\n				create index paid_site_idx on paid(site_id)\r\n			"
+ );
+		case 8:
+			up.execStep( 
+		"\r\n				create index registration_site_idx on registration(site_id)\r\n			"
+ );
+		case 9:
+			up.execStep( 
+		"\r\n				create index subscription_site_idx on subscription(site_id)\r\n			"
+ );
+		case 10:
+			up.execStep( 
+		"\r\n				create index user_property_site_idx on user_property(site_id)\r\n			"
+ );
+		case 11:
+			up.execStep( 
+		"\r\n				create index view_count_site_idx on view_count(site_id)\r\n			"
+ );
+		case 12:
+			up.execStep( 
+		"\r\n				create index visited_site_idx on visited(site_id)\r\n			"
+ );
+
+		case 13:
+			up.execStep( 
+		"\r\n				create index tag_node_idx on tag(node_id)\r\n			"
+ );
+		case 14:
+			up.execStep( 
+		"\r\n				create index tag_user_idx on tag(user_id)\r\n			"
+ );
+		case 15:
+			up.execStep( 
+		"\r\n				create index embed_key_node_idx on embed_key(node_id)\r\n			"
+ );
+		case 16:
+			up.execStep( 
+		"\r\n				create index visited_node_idx on visited(node_id)\r\n			"
+ );
+		case 17:
+			up.execStep( 
+		"\r\n				create index visited_last_node_idx on visited(last_node_id)\r\n			"
+ );
+		case 18:
+			up.execStep( 
+		"\r\n				alter table node add column poll_option_count integer default null\r\n			"
+ );
+		case 19:
+			up.execStep( 
+		"\r\n				alter table configuration drop column site_id\r\n			"
+ );
+		case 20:
+			up.execStep( 
+		"\r\n				alter table configuration ADD PRIMARY KEY (name)\r\n			"
+ );
+		case 21:
+			up.execStep( 
+		"\r\n				alter table embed_key drop column site_id\r\n			"
+ );
+		case 22:
+			up.execStep( 
+		"\r\n				alter table file_avatar drop column site_id\r\n			"
+ );
+		case 23:
+			up.execStep( 
+		"\r\n				alter table file_node drop column site_id\r\n			"
+ );
+		case 24:
+			up.execStep( 
+		"\r\n				alter table file_temp drop column site_id\r\n			"
+ );
+		case 25:
+			up.execStep( 
+		"\r\n				alter table mailing_list drop column site_id\r\n			"
+ );
+		case 26:
+			up.execStep( 
+		"\r\n				alter table node_msg drop column site_id\r\n			"
+ );
+		case 27:
+			up.execStep( 
+		"\r\n				alter table node_property drop column site_id\r\n			"
+ );
+		case 28:
+			up.execStep( 
+		"\r\n				alter table paid drop column site_id\r\n			"
+ );
+		case 29:
+			up.execStep( 
+		"\r\n				alter table registration drop column site_id\r\n			"
+ );
+		case 30:
+			up.execStep( 
+		"\r\n				alter table subscription drop column site_id\r\n			"
+ );
+		case 31:
+			up.execStep( 
+		"\r\n				alter table user_property drop column site_id\r\n			"
+ );
+		case 32:
+			up.execStep( 
+		"\r\n				alter table view_count drop column site_id\r\n			"
+ );
+		case 33:
+			up.execStep( 
+		"\r\n				alter table visited drop column site_id\r\n			"
+ );
+		case 34:
+			up.execStep( 
+		"\r\n				alter table file_site drop column site_id\r\n			"
+ );
+		case 35:
+			up.execStep( 
+		"\r\n				alter table file_site ADD PRIMARY KEY (name)\r\n			"
+ );
+		case 36:
+			up.execStep( 
+		"\r\n				alter table module drop column site_id\r\n			"
+ );
+		case 37:
+			up.execStep( 
+		"\r\n				alter table module ADD PRIMARY KEY (module_name)\r\n			"
+ );
+		case 38:
+			up.execStep( 
+		"\r\n				alter table site_property drop column site_id\r\n			"
+ );
+		case 39:
+			up.execStep( 
+		"\r\n				alter table site_property ADD PRIMARY KEY (key)\r\n			"
+ );
+		case 40:
+			up.execStep( 
+		"\r\n				alter table tweak drop column site_id\r\n			"
+ );
+		case 41:
+			up.execStep( 
+		"\r\n				alter table tweak ADD PRIMARY KEY (tweak_name)\r\n			"
+ );
+		case 42:
+			up.execStep( 
+		"\r\n				alter table tag drop column site_id\r\n			"
+ );
+		case 43:
+			up.execStep( 
+		"\r\n				CREATE UNIQUE INDEX tag_idx\r\n					ON tag (node_id, user_id, label);\r\n			"
+ );
+		case 44:
+			up.execStep( 
+		"\r\n				drop index tag_node_idx\r\n			"
+ );
+		case 45:
+			up.execStep( 
+		"\r\n				alter table user_ drop column site_id\r\n			"
+ );
+		case 46:
+			up.execStep( 
+		"\r\n				CREATE UNIQUE INDEX user_email_idx\r\n					ON user_ (lower(email));\r\n			"
+ );
+		case 47:
+			up.execStep( 
+		"\r\n				CREATE UNIQUE INDEX user_name_idx\r\n					ON user_ (lower(name));\r\n			"
+ );
+		case 48:
+			up.execStep( 
+		"\r\n				alter table node drop column site_id\r\n			"
+ );
+		case 49:
+			up.execStep( 
+		"\r\n				CREATE INDEX node_cookie_idx\r\n					ON node (cookie)\r\n					WHERE cookie IS NOT NULL;\r\n			"
+ );
+		case 50:
+			up.execStep( 
+		"\r\n				CREATE INDEX node_message_id_idx\r\n					ON node (lower(message_id))\r\n					WHERE message_id IS NOT NULL;\r\n			"
+ );
+		case 51:
+			up.execStep( 
+		"\r\n				drop table embed_key\r\n			"
+ );
+		case 52:
+			up.execStep( 
+		"\r\n				delete from site_property where key = '__embedding_warning'\r\n			"
+ );
+		case 53:
+			up.execStep( 
+		"\r\n				alter table site drop column site_id\r\n			"
+ );
+		case 54:
+			up.execStep( 
+		"\r\n				alter table site add column one integer default 1 not null\r\n			"
+ );
+		case 55:
+			up.execStep( 
+		"\r\n				alter table site ADD PRIMARY KEY (one)\r\n			"
+ );
+		case 56:
+			up.execStep( 
+		"\r\n				alter table site add column content_type character varying;\r\n			"
+ );
+		case 57:
+			up.execStep( 
+		"\r\n				update configuration set naml=E'<override_macro name=\"site_style\">\\n\\t<n.overridden/>\\n\\t#search-box { text-align:left; }\\n</override_macro>' where name='searchBoxAlignment';\r\n			"
+ );
+		case 58:
+			up.execStep( 
+		"\r\n				update site set ad_type=null where ad_type='ADBRITE' or ad_type='ADSENSE'\r\n			"
+ );
+
+		case 59:
+			up.execStep( 
+		"\r\n				alter table node\r\n					add column unsafe character varying default 'new',\r\n					add column safe_version integer\r\n			"
+ );
+		case 60:
+			up.execStep( 
+		"\r\n				alter table user_\r\n					add column unsafe character varying default 'new',\r\n					add column safe_version integer\r\n			"
+ );
+
+		case 61:
+			up.execStep( 
+		"\r\n				update site set ad_type='HOPELESS' where ad_type='COPYRIGHTED'\r\n			"
+ );
+		case 62:
+			up.execStep( 
+		"\r\n				update site set ad_type='HOPELESS' where ad_type='OURS'\r\n			"
+ );
+		case 63:
+			up.execStep( 
+		"\r\n				update site set ad_type=null, ad_free="
+		+(Integer.MAX_VALUE)
+		+" where ad_type='NONE'\r\n			"
+ );
+
+		case 64:
+			up.execStep( 
+		"\r\n				alter table node\r\n					add column is_safe boolean\r\n			"
+ );
+		case 65:
+			up.execStep( 
+		"\r\n				alter table user_\r\n					add column is_safe boolean\r\n			"
+ );
+		case 66:
+			up.execStep( null );
+		case 67:
+			up.execStep( null );
+		case 68:
+			up.execStep( 
+		"\r\n				delete from tag where label='hide_ads'\r\n			"
+ );
+		case 69:
+			up.execStep( 
+		"\r\n				update site set ad_type=null where ad_type='SOME_ADSENSE'\r\n			"
+ );
+		case 70:
+			up.execStep( 
+		"\r\n				update site set ad_type='ADULT' where ad_type='HACK'\r\n			"
+ );
+		case 71:
+			up.execStep( 
+		"\r\n				update site set content_type=null where content_type='FAMILY'\r\n			"
+ );
+		case 72:
+			up.execStep( 
+		"\r\n				drop index if exists node_is_safe_idx\r\n			"
+ );
+		case 73:
+			up.execStep( 
+		"\r\n				drop index if exists user_is_safe_idx\r\n			"
+ );
+		case 74:
+			up.execStep( 
+		"\r\n				create index node_unsafe_idx on node(unsafe) where unsafe is not null and unsafe!='new'\r\n			"
+ );
+		case 75:
+			up.execStep( 
+		"\r\n				create index user_unsafe_idx on user_(unsafe) where unsafe is not null and unsafe!='new'\r\n			"
+ );
+		case 76:
+			up.execStep( 
+		"\r\n				update site set content_type=ad_type where content_type is null and ad_type is not null and ad_type!='HOPELESS'\r\n			"
+ );
+		case 77:
+			up.execStep( 
+		"\r\n				update site set ad_type=content_type where content_type is not null and ad_type is null\r\n			"
+ );
+		case 78:
+			up.execStep( 
+		"\r\n				update site set ad_type='ADULT' where content_type='ADULT' and ad_type='PORN'\r\n			"
+ );
+
+		case 79:
+			up.execStep( 
+		"\r\n				alter table user_\r\n					drop column unsafe,\r\n					drop column safe_version,\r\n					drop column is_safe\r\n			"
+ );
+		case 80:
+			up.execStep( null );
+		case 81:
+			up.execStep( null );
+		case 82:
+			up.begin();
+			up.exec( 
+		"\r\n				alter table node\r\n					drop column unsafe,\r\n					drop column safe_version,\r\n					drop column is_safe\r\n			"
+ );
+			up.exec( 
+		"\r\n				alter table node\r\n					add column unsafe character varying,\r\n					add column safe_version integer,\r\n					add column is_safe boolean\r\n			"
+ );
+			up.commit();
+		case 83:
+			up.execStep( 
+		"\r\n				create index node_unsafe_idx on node(unsafe) where safe_version is not null\r\n			"
+ );
+		case 84:
+			up.execStep( 
+		"\r\n				delete from module where module_name = 'topic_ads';\r\n			"
+ );
+		case 85:
+			up.execStep( 
+		"\r\n				alter table node\r\n					drop column unsafe,\r\n					drop column safe_version,\r\n					drop column is_safe\r\n			"
+ );
+		case 86:
+			up.execStep( 
+		"\r\n				alter table site\r\n					add column when_created timestamp with time zone NOT NULL DEFAULT now()\r\n			"
+ );
+		case 87:
+			up.execStep( 
+		"\r\n				update site\r\n					set when_created = node.when_created\r\n					from node\r\n					where node.node_id = site.root_node_id\r\n			"
+ );
+
+		case 88:
+			up.execStep( 
+		"\r\n				alter table site\r\n					add column is_safe boolean NOT NULL DEFAULT true\r\n			"
+ );
+		case 89:
+			up.execStep( 
+		"\r\n				update site set is_safe = false where ad_type is not null\r\n			"
+ );
+		case 90:
+			up.execStep( 
+		"\r\n				update site set when_created = now() where not is_safe\r\n			"
+ );
+		case 91:
+			up.execStep( 
+		"\r\n				alter table site rename column ad_type to old_ad_type\r\n			"
+ );
+		case 92:
+			up.execStep( 
+		"\r\n				alter table site rename column content_type to old_content_type\r\n			"
+ );
+		case 93:
+			up.execStep( 
+		"\r\n				alter table site\r\n					add column ad_credits_for_users boolean NOT NULL DEFAULT false\r\n			"
+ );
+		case 94:
+			up.execStep( 
+		"\r\n				alter table site\r\n					add column monthly_views integer NOT NULL DEFAULT 0\r\n			"
+ );
+		case 95:
+			up.execStep( 
+		"\r\n				delete from tag where label='group:Administrators' and node_id is null and user_id = (select user_id from user_ where email = 'pedro@nabble.com')\r\n			"
+ );
+
+		case 96:
+			execCatching( 
+		"\r\n				alter table tweak ADD PRIMARY KEY (tweak_name)\r\n			"
+, "multiple primary keys for table" );
+		case 97:
+			execCatching( 
+		"\r\n				alter table mailing_list ADD PRIMARY KEY (node_id)\r\n			"
+, "multiple primary keys for table" );
+		case 98:
+/*
+			execCatching( 
+		"\r\n				alter table mailing_list ADD CONSTRAINT mailing_list_node_id_fkey FOREIGN KEY (node_id) REFERENCES node (node_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+*/
+			up.execStep( null );
+		case 99:
+			execCatching( 
+		"\r\n				CREATE INDEX forum_ml_idx ON mailing_list (lower(list_address))\r\n			"
+, "already exists" );
+		case 100:
+			execCatching( 
+		"\r\n				alter table node ADD PRIMARY KEY (node_id)\r\n			"
+, "multiple primary keys for table" );
+		case 101:
+			execCatching( 
+		"\r\n				alter table configuration ADD PRIMARY KEY (name)\r\n			"
+, "multiple primary keys for table" );
+		case 102:
+			execCatching( 
+		"\r\n				alter table file_avatar ADD PRIMARY KEY (user_id, name)\r\n			"
+, "multiple primary keys for table" );
+		case 103:
+			execCatching( 
+		"\r\n				alter table file_node ADD PRIMARY KEY (node_id, name)\r\n			"
+, "multiple primary keys for table" );
+		case 104:
+			execCatching( 
+		"\r\n				alter table file_site ADD PRIMARY KEY (name)\r\n			"
+, "multiple primary keys for table" );
+		case 105:
+			execCatching( 
+		"\r\n				alter table file_temp ADD PRIMARY KEY (user_id, name)\r\n			"
+, "multiple primary keys for table" );
+		case 106:
+			execCatching( 
+		"\r\n				CREATE INDEX file_temp_date_idx ON file_temp (date_)\r\n			"
+, "already exists" );
+		case 107:
+			execCatching( 
+		"\r\n				alter table module ADD PRIMARY KEY (module_name)\r\n			"
+, "multiple primary keys for table" );
+		case 108:
+			execCatching( 
+		"\r\n				CREATE INDEX node_cookie_idx ON node (cookie) WHERE cookie IS NOT NULL\r\n			"
+, "already exists" );
+		case 109:
+			execCatching( 
+		"\r\n				CREATE INDEX node_export ON node (export_permalink) WHERE export_permalink IS NOT NULL\r\n			"
+, "already exists" );
+		case 110:
+			execCatching( 
+		"\r\n				CREATE INDEX node_message_id_idx ON node (lower(message_id)) WHERE message_id IS NOT NULL\r\n			"
+, "already exists" );
+		case 111:
+			execCatching( 
+		"\r\n				CREATE INDEX node_ml2_idx ON node (lower(parent_message_id)) WHERE lower(parent_message_id) IS NOT NULL\r\n			"
+, "already exists" );
+		case 112:
+			execCatching( 
+		"\r\n				CREATE INDEX node_owner_idx ON node (owner_id, when_created)\r\n			"
+, "already exists" );
+		case 113:
+			execCatching( 
+		"\r\n				CREATE UNIQUE INDEX node_parent2_idx ON node (parent_id, when_created, node_id)\r\n			"
+, "already exists" );
+		case 114:
+			execCatching( 
+		"\r\n				CREATE UNIQUE INDEX node_parent_idx ON node (parent_id, last_node_date, node_id)\r\n			"
+, "already exists" );
+		case 115:
+			execCatching( 
+		"\r\n				CREATE INDEX node_sent_idx ON node (when_sent) WHERE when_sent IS NOT NULL\r\n			"
+, "already exists" );
+		case 116:
+			execCatching( 
+		"\r\n				CREATE UNIQUE INDEX pinned_node_idx ON node (parent_id, pin) WHERE pin IS NOT NULL\r\n			"
+, "already exists" );
+		case 117:
+			execCatching( 
+		"\r\n				CREATE INDEX post_date ON node (when_created)\r\n			"
+, "already exists" );
+		case 118:
+			execCatching( 
+		"\r\n				alter table node_msg ADD PRIMARY KEY (node_id)\r\n			"
+, "multiple primary keys for table" );
+		case 119:
+			execCatching( 
+		"\r\n				alter table node_property ADD PRIMARY KEY (node_id, key)\r\n			"
+, "multiple primary keys for table" );
+		case 120:
+			execCatching( 
+		"\r\n				alter table paid ADD PRIMARY KEY (user_id)\r\n			"
+, "multiple primary keys for table" );
+		case 121:
+			execCatching( 
+		"\r\n				alter table registration ADD PRIMARY KEY (key_)\r\n			"
+, "multiple primary keys for table" );
+		case 122:
+			execCatching( 
+		"\r\n				CREATE INDEX registration_date_idx ON registration (date_)\r\n			"
+, "already exists" );
+		case 123:
+			execCatching( 
+		"\r\n				alter table site ADD PRIMARY KEY (one)\r\n			"
+, "multiple primary keys for table" );
+		case 124:
+			execCatching( 
+		"\r\n				alter table site_property ADD PRIMARY KEY (key)\r\n			"
+, "multiple primary keys for table" );
+		case 125:
+			execCatching( 
+		"\r\n				alter table subscription ADD PRIMARY KEY (user_id, node_id)\r\n			"
+, "multiple primary keys for table" );
+		case 126:
+			execCatching( 
+		"\r\n				CREATE INDEX subscription_node_idx ON subscription (node_id)\r\n			"
+, "already exists" );
+		case 127:
+			execCatching( 
+		"\r\n				CREATE UNIQUE INDEX tag_idx ON tag (node_id, user_id, label)\r\n			"
+, "already exists" );
+		case 128:
+			execCatching( 
+		"\r\n				CREATE INDEX tag_user_idx ON tag (user_id)\r\n			"
+, "already exists" );
+		case 129:
+			execCatching( 
+		"\r\n				alter table user_ ADD PRIMARY KEY (user_id)\r\n			"
+, "multiple primary keys for table" );
+		case 130:
+			execCatching( 
+		"\r\n				CREATE UNIQUE INDEX user_email_idx ON user_ (lower(email))\r\n			"
+, "already exists" );
+		case 131:
+			execCatching( 
+		"\r\n				CREATE UNIQUE INDEX user_name_idx ON user_ (lower(name))\r\n			"
+, "already exists" );
+		case 132:
+			execCatching( 
+		"\r\n				alter table user_property ADD PRIMARY KEY (user_id, key)\r\n			"
+, "multiple primary keys for table" );
+		case 133:
+			execCatching( 
+		"\r\n				alter table view_count ADD PRIMARY KEY (node_id)\r\n			"
+, "multiple primary keys for table" );
+		case 134:
+			execCatching( 
+		"\r\n				alter table visited ADD PRIMARY KEY (user_id, node_id)\r\n			"
+, "multiple primary keys for table" );
+		case 135:
+			execCatching( 
+		"\r\n				CREATE INDEX visited_last_node_idx ON visited (last_node_id)\r\n			"
+, "already exists" );
+		case 136:
+			execCatching( 
+		"\r\n				CREATE INDEX visited_node_idx ON visited (node_id)\r\n			"
+, "already exists" );
+
+		case 137:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY file_avatar \r\n					ADD CONSTRAINT file_avatar_user_id_fkey FOREIGN KEY (user_id) REFERENCES user_(user_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 138:
+			up.execStep( null );
+		case 139:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY file_temp \r\n					ADD CONSTRAINT file_temp_user_id_fkey FOREIGN KEY (user_id) REFERENCES user_(user_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 140:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY mailing_list \r\n					ADD CONSTRAINT mailing_list_node_id_fkey FOREIGN KEY (node_id) REFERENCES node(node_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 141:
+			up.execStep( null );
+		case 142:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY node \r\n					ADD CONSTRAINT node_new_owner_id_fkey FOREIGN KEY (owner_id) REFERENCES user_(user_id)\r\n			"
+, "already exists" );
+		case 143:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY node \r\n					ADD CONSTRAINT node_node_id_fkey FOREIGN KEY (node_id) REFERENCES node_msg(node_id) DEFERRABLE INITIALLY DEFERRED\r\n			"
+, "already exists" );
+		case 144:
+			up.execStep( null );
+		case 145:
+			up.execStep( null );
+		case 146:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY paid \r\n					ADD CONSTRAINT paid_user_id_fkey FOREIGN KEY (user_id) REFERENCES user_(user_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 147:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY site \r\n					ADD CONSTRAINT site_root_node_id_fkey FOREIGN KEY (root_node_id) REFERENCES node(node_id) DEFERRABLE INITIALLY DEFERRED\r\n			"
+, "already exists" );
+		case 148:
+			up.execStep( null );
+		case 149:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY subscription \r\n					ADD CONSTRAINT subscription_user_id_fkey FOREIGN KEY (user_id) REFERENCES user_(user_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 150:
+			up.execStep( null );
+		case 151:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY tag \r\n					ADD CONSTRAINT tag_user_id_fkey FOREIGN KEY (user_id) REFERENCES user_(user_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 152:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY user_property \r\n					ADD CONSTRAINT user_property_user_id_fkey FOREIGN KEY (user_id) REFERENCES user_(user_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 153:
+			up.execStep( null );
+		case 154:
+			up.execStep( null );
+		case 155:
+			up.execStep( null );
+		case 156:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY visited \r\n					ADD CONSTRAINT visited_user_id_fkey FOREIGN KEY (user_id) REFERENCES user_(user_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 157:
+			up.execStep( null );
+
+		// problematic constraints
+		case 158:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY file_node \r\n					ADD CONSTRAINT file_node_node_id_fkey FOREIGN KEY (node_id) REFERENCES node(node_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 159:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY node_msg \r\n					ADD CONSTRAINT node_msg_node_id_fkey FOREIGN KEY (node_id) REFERENCES node(node_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 160:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY node \r\n					ADD CONSTRAINT node_parent_id_fkey FOREIGN KEY (parent_id) REFERENCES node(node_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 161:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY node_property \r\n					ADD CONSTRAINT node_property_node_id_fkey FOREIGN KEY (node_id) REFERENCES node(node_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 162:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY subscription \r\n					ADD CONSTRAINT subscription_node_id_fkey FOREIGN KEY (node_id) REFERENCES node(node_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 163:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY tag \r\n					ADD CONSTRAINT tag_node_id_fkey FOREIGN KEY (node_id) REFERENCES node(node_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 164:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY view_count \r\n					ADD CONSTRAINT view_count_node_id_fkey FOREIGN KEY (node_id) REFERENCES node(node_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 165:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY visited \r\n					ADD CONSTRAINT visited_last_node_id_fkey FOREIGN KEY (last_node_id) REFERENCES node(node_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		case 166:
+			execCatching( 
+		"\r\n				ALTER TABLE ONLY visited \r\n					ADD CONSTRAINT visited_node_id_fkey FOREIGN KEY (node_id) REFERENCES node(node_id) ON DELETE CASCADE\r\n			"
+, "already exists" );
+		}
+	}
+}
+