I don't see an email address in the osm2pgsql source, so I'm just sending
this here; if there's a better destination, please let me know.

I think it would be really useful to have a table that tracks relation
membership so you can do JOINs to get the components of relations, so I
added one to osm2pgsql.  If this is accepted into the trunk, I plan to use
it to submit some rendering patches to render highway shields from route
relations.

I'm attaching three patches; I've tried to keep my changes orthogonal,
plus I think the first two are improvements on the codebase even if no one
likes the planet_osm_member table:

 * exportlist-indexing.patch changes exportList in output-pgsql.c so that
   it's explicitly indexed by OsmType.  Most of the code that uses it does
   so with OsmType indexing, but a few spots treat it as if it's indexed
   by table_id, which it isn't (at least, not any more).

 * common-set-prefix.patch merely moves the set_prefix() function from
   middle-pgsql.c into pgsql.h and uses it in output-pgsql.c.

 * planet-osm-member.patch adds a new table, <prefix>_member, which
   cross-references relations and their members.  It's intended to allow
   JOINs on the line, polygon, and node tables, so it has a field for the
   member type, and all IDs referring to relations are negative.
   The patch creates a distinction in output-pgsql.c between geometric
   tables (ones with a way field) and non-geometric tables; the
   distinction is made by the presence or absence of the type member of
   the s_table struct.

-- 
...computer contrarian of the first order... / http://aperiodic.net/phil/
PGP: 026A27F2  print: D200 5BDB FC4B B24A 9248  9F7A 4322 2D22 026A 27F2
--- --
Hire an expert marksman to stand by the entrance to your fortress.  His
job will be to shoot anyone who rides up to challenge you.
                       -- Evil Overlord's Handbook, entry 196
---- --- --
=== modified file 'osmtypes.h'
--- osmtypes.h	2010-11-07 18:54:12 +0000
+++ osmtypes.h	2011-01-13 13:49:52 +0000
@@ -6,6 +6,7 @@
 #include "keyvals.h"
 
 enum OsmType { OSMTYPE_WAY, OSMTYPE_NODE, OSMTYPE_RELATION };
+#define OSM_TYPE_COUNT 3
 
 struct osmNode {
     double lon;

=== modified file 'output-pgsql.c'
--- output-pgsql.c	2010-12-05 23:32:10 +0000
+++ output-pgsql.c	2011-01-13 13:49:52 +0000
@@ -86,8 +86,8 @@
     int count;
 };
 
-static struct taginfo *exportList[4]; /* Indexed by enum table_id */
-static int exportListCount[4];
+static struct taginfo *exportList[OSM_TYPE_COUNT]; /* Indexed by enum table_id */
+static int exportListCount[OSM_TYPE_COUNT];
 
 /* Data to generate z-order column and road table
  * The name of the roads table is misleading, this table
@@ -227,7 +227,7 @@
     // Currently this scales with n^2 number of styles
     int i,j;
 
-    for (i=0; i<NUM_TABLES; i++) {
+    for (i=0; i<OSM_TYPE_COUNT; i++) {
         for(j=0; j<exportListCount[i]; j++) {
             if (exportList[i][j].name == name)
                 exportList[i][j].name = NULL;
@@ -240,14 +240,14 @@
 static void free_style(void)
 {
     int i, j;
-    for (i=0; i<NUM_TABLES; i++) {
+    for (i=0; i<OSM_TYPE_COUNT; i++) {
         for(j=0; j<exportListCount[i]; j++) {
             free(exportList[i][j].name);
             free(exportList[i][j].type);
             free_style_refs(exportList[i][j].name, exportList[i][j].type);
         }
     }
-    for (i=0; i<NUM_TABLES; i++)
+    for (i=0; i<OSM_TYPE_COUNT; i++)
         free(exportList[i]);
 }
 

=== modified file 'middle-pgsql.c'
--- middle-pgsql.c	2010-12-05 23:32:10 +0000
+++ middle-pgsql.c	2011-01-13 21:54:05 +0000
@@ -1085,26 +1085,6 @@
     }
 }
 
-/* Replace %s with prefix */
-static inline void set_prefix( const char *prefix, const char **string )
-{
-  char buffer[1024];
-  if( *string == NULL )
-      return;
-  sprintf( buffer, *string, prefix, prefix, prefix, prefix, prefix, prefix );
-  *string = strdup( buffer );
-}
-
-/* Replace %s with prefix and tablespace*/
-static inline void set_prefixtbls( const char *prefix, const char *tbls, const char **string )
-{
-  char buffer[1024];
-  if( *string == NULL )
-      return;
-  sprintf( buffer, *string, prefix, prefix, tbls );
-  *string = strdup( buffer );
-}
-
 static int build_indexes;
 
 static int pgsql_start(const struct output_options *options)

=== modified file 'output-pgsql.c'
--- output-pgsql.c	2011-01-13 13:49:52 +0000
+++ output-pgsql.c	2011-01-13 21:54:05 +0000
@@ -1141,12 +1141,8 @@
     for (i=0; i<NUM_TABLES; i++) {
         PGconn *sql_conn;
 
-        /* Substitute prefix into name of table */
-        {
-            char *temp = malloc( strlen(options->prefix) + strlen(tables[i].name) + 1 );
-            sprintf( temp, tables[i].name, options->prefix );
-            tables[i].name = temp;
-        }
+        set_prefix( options->prefix, &(tables[i].name) );
+	
         fprintf(stderr, "Setting up table: %s\n", tables[i].name);
         sql_conn = PQconnectdb(options->conninfo);
 

=== modified file 'pgsql.h'
--- pgsql.h	2008-06-05 20:09:23 +0000
+++ pgsql.h	2011-01-13 21:54:05 +0000
@@ -9,3 +9,23 @@
 int pgsql_CopyData(const char *context, PGconn *sql_conn, const char *sql);
 int pgsql_exec(PGconn *sql_conn, ExecStatusType expect, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
 void escape(char *out, int len, const char *in);
+
+/* Replace %s with prefix */
+static inline void set_prefix( const char *prefix, const char **string )
+{
+  char buffer[1024];
+  if( *string == NULL )
+      return;
+  sprintf( buffer, *string, prefix, prefix, prefix, prefix, prefix, prefix );
+  *string = strdup( buffer );
+}
+
+/* Replace %s with prefix and tablespace*/
+static inline void set_prefixtbls( const char *prefix, const char *tbls, const char **string )
+{
+  char buffer[1024];
+  if( *string == NULL )
+      return;
+  sprintf( buffer, *string, prefix, prefix, tbls );
+  *string = strdup( buffer );
+}

=== modified file 'output-pgsql.c'
--- output-pgsql.c	2011-01-13 21:54:05 +0000
+++ output-pgsql.c	2011-01-18 15:56:10 +0000
@@ -38,7 +38,7 @@
 #define MAX_STYLES 1000
 
 enum table_id {
-    t_point, t_line, t_poly, t_roads
+    t_point, t_line, t_poly, t_roads, t_member
 };
 
 static const struct output_options *Options;
@@ -46,18 +46,27 @@
 /* Tables to output */
 static struct s_table {
     //enum table_id table;
-    char *name;
-    const char *type;
+    const char *name;
+    const char *type;  // Geometry type in the table.  NULL for non-geometry tables.
     PGconn *sql_conn;
     char buffer[1024];
     unsigned int buflen;
     int copyMode;
     char *columns;
+    const char *create;  // Command to create non-geometry tables.
+    const char *index;  // Command to create table indices.
+    const char *copy;  // Command to start COPY mode on non-geometry tables.
 } tables [] = {
     { .name = "%s_point",   .type = "POINT"     },
     { .name = "%s_line",    .type = "LINESTRING"},
     { .name = "%s_polygon", .type = "GEOMETRY"  }, // Actually POLGYON & MULTIPOLYGON but no way to limit to just these two
-    { .name = "%s_roads",   .type = "LINESTRING"}
+    { .name = "%s_roads",   .type = "LINESTRING"},
+    { .name = "%s_member",  .type = NULL,
+      .columns = "rel_id, member_id, mem_type, role",
+      .create = "CREATE TABLE %s_member (rel_id int4, member_id int4, mem_type int4, role text);\n",
+      .index = "CREATE INDEX %s_member_rel ON %s_member (rel_id);\n"
+               "CREATE INDEX %s_member_mem ON %s_member (member_id);\n",
+      .copy = "COPY %s_member (rel_id, member_id, mem_type, role) FROM STDIN" }
 };
 #define NUM_TABLES ((signed)(sizeof(tables) / sizeof(tables[0])))
 
@@ -267,7 +276,13 @@
     /* Return to copy mode if we dropped out */
     if( !tables[table].copyMode )
     {
-        pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way) FROM STDIN", tables[table].name, tables[table].columns);
+	if (tables[table].type)
+	{
+	    pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way) FROM STDIN", tables[table].name, tables[table].columns);
+	} else
+	{
+	    pgsql_exec(sql_conn, PGRES_COPY_IN, "%s", tables[table].copy);
+	}	    
         tables[table].copyMode = 1;
     }
     /* If the combination of old and new data is too big, flush old data */
@@ -1123,6 +1138,46 @@
     return 0;
 }
 
+static void pgsql_out_member(int id, struct member *members, int member_count)
+{
+    static char *sql;
+    static size_t sqllen=0;
+    int slen;
+    int i;
+
+    if (sqllen==0) {
+	sqllen=2048;
+	sql=malloc(sqllen);
+    }
+
+    for (i=0; i < member_count; i++) {
+	slen = strlen(members[i].role) + 1;
+        if (slen > sqllen) {
+            sqllen = slen;
+            sql = realloc(sql, sqllen);
+        }
+	sprintf(sql, "%d\t", -id);
+	copy_to_table(t_member, sql);
+
+	if (members[i].type == OSMTYPE_RELATION)
+	{
+	    sprintf(sql, "%d\t", -members[i].id);
+	} else
+	{
+	    sprintf(sql, "%d\t", members[i].id);
+	}
+	copy_to_table(t_member, sql);
+
+	sprintf(sql, "%d\t", members[i].type);
+	copy_to_table(t_member, sql);
+
+	escape_type(sql, sqllen, members[i].role, "text");
+	copy_to_table(t_member, sql);
+
+	copy_to_table(t_member, "\n");
+    }
+}
+
 static int pgsql_out_start(const struct output_options *options)
 {
     char *sql, tmp[256];
@@ -1142,7 +1197,14 @@
         PGconn *sql_conn;
 
         set_prefix( options->prefix, &(tables[i].name) );
-	
+	if (!tables[i].type)
+	{
+	    set_prefix( options->prefix, &(tables[i].create) );
+	    if (tables[i].index)
+		set_prefix( options->prefix, &(tables[i].index) );
+	    set_prefix( options->prefix, &(tables[i].copy) );
+	}
+
         fprintf(stderr, "Setting up table: %s\n", tables[i].name);
         sql_conn = PQconnectdb(options->conninfo);
 
@@ -1156,7 +1218,7 @@
         if (!options->append) {
             pgsql_exec(sql_conn, PGRES_COMMAND_OK, "DROP TABLE IF EXISTS %s", tables[i].name);
         }
-        else
+        else if (tables[i].type)
         {
             sprintf(sql, "SELECT srid FROM geometry_columns WHERE f_table_name='%s';", tables[i].name);
             res = PQexec(sql_conn, sql);
@@ -1179,111 +1241,128 @@
 
         pgsql_exec(sql_conn, PGRES_COMMAND_OK, "BEGIN");
 
-        enum OsmType type = (i == t_point)?OSMTYPE_NODE:OSMTYPE_WAY;
-        int numTags = exportListCount[type];
-        struct taginfo *exportTags = exportList[type];
-        if (!options->append) {
-            sprintf(sql, "CREATE TABLE %s ( osm_id int4", tables[i].name );
-            for (j=0; j < numTags; j++) {
-                if( exportTags[j].flags & FLAG_DELETE )
-                    continue;
+	if (tables[i].type)
+	{
+	    enum OsmType type = (i == t_point)?OSMTYPE_NODE:OSMTYPE_WAY;
+	    int numTags = exportListCount[type];
+	    struct taginfo *exportTags = exportList[type];
+	    if (!options->append) {
+		sprintf(sql, "CREATE TABLE %s ( osm_id int4", tables[i].name );
+		for (j=0; j < numTags; j++) {
+		    if( exportTags[j].flags & FLAG_DELETE )
+			continue;
+		    if( (exportTags[j].flags & FLAG_PHSTORE ) == FLAG_PHSTORE)
+			continue;
+		    sprintf(tmp, ",\"%s\" %s", exportTags[j].name, exportTags[j].type);
+		    if (strlen(sql) + strlen(tmp) + 1 > sql_len) {
+			sql_len *= 2;
+			sql = realloc(sql, sql_len);
+			assert(sql);
+		    }
+		    strcat(sql, tmp);
+		}
+		int i_hstore_column;
+		for(i_hstore_column = 0; i_hstore_column < Options->n_hstore_columns; i_hstore_column++)
+		{
+		    strcat(sql, ",\"");
+		    strcat(sql, Options->hstore_columns[i_hstore_column]);
+		    strcat(sql, "\" hstore ");
+		}
+		if (Options->enable_hstore) {
+		    strcat(sql, ",tags hstore );\n");
+		} else {
+		    strcat(sql, " );\n");
+		}
+		
+		pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", sql);
+		pgsql_exec(sql_conn, PGRES_TUPLES_OK, "SELECT AddGeometryColumn('%s', 'way', %d, '%s', 2 );\n",
+			   tables[i].name, SRID, tables[i].type );
+		pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ALTER TABLE %s ALTER COLUMN way SET NOT NULL;\n", tables[i].name);
+		/* slim mode needs this to be able to apply diffs */
+		if( Options->slim )
+		    pgsql_exec(sql_conn, PGRES_COMMAND_OK, "CREATE INDEX %s_pkey ON %s USING BTREE (osm_id) TABLESPACE %s;\n", tables[i].name, tables[i].name, Options->tblsindex);
+	    } else {
+		/* Add any new columns referenced in the default.style */
+		PGresult *res;
+		sprintf(sql, "SELECT * FROM %s LIMIT 0;\n", tables[i].name);
+		res = PQexec(sql_conn, sql);
+		if (PQresultStatus(res) != PGRES_TUPLES_OK) {
+		    fprintf(stderr, "Error, failed to query table %s\n%s\n", tables[i].name, sql);
+		    exit_nicely();
+		}
+		for (j=0; j < numTags; j++) {
+		    if( exportTags[j].flags & FLAG_DELETE )
+			continue;
+		    if( (exportTags[j].flags & FLAG_PHSTORE) == FLAG_PHSTORE)
+			continue;
+		    sprintf(tmp, "\"%s\"", exportTags[j].name);
+		    if (PQfnumber(res, tmp) < 0) {
+#if 0
+			fprintf(stderr, "Append failed. Column \"%s\" is missing from \"%s\"\n", exportTags[j].name, tables[i].name);
+			exit_nicely();
+#else
+			fprintf(stderr, "Adding new column \"%s\" to \"%s\"\n", exportTags[j].name, tables[i].name);
+			pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ALTER TABLE %s ADD COLUMN \"%s\" %s;\n", tables[i].name, exportTags[j].name, exportTags[j].type);
+#endif
+		    }
+		    /* Note: we do not verify the type or delete unused columns */
+		}
+		
+		PQclear(res);
+		
+		/* change the type of the geometry column if needed - this can only change to a more permisive type */
+		pgsql_exec(sql_conn, PGRES_COMMAND_OK, "UPDATE geometry_columns SET type = '%s' where type != '%s' and f_table_name = '%s' and f_geometry_column = 'way'",
+			   tables[i].type, tables[i].type, tables[i].name);
+	    }
+	    pgsql_exec(sql_conn, PGRES_COMMAND_OK, "PREPARE get_way (int4) AS SELECT AsText(way) FROM %s WHERE osm_id = $1;\n", tables[i].name);
+	    
+	    /* Generate column list for COPY */
+	    strcpy(sql, "osm_id");
+	    for (j=0; j < numTags; j++) {
+		if( exportTags[j].flags & FLAG_DELETE )
+		    continue;
 		if( (exportTags[j].flags & FLAG_PHSTORE ) == FLAG_PHSTORE)
 		    continue;
-                sprintf(tmp, ",\"%s\" %s", exportTags[j].name, exportTags[j].type);
-                if (strlen(sql) + strlen(tmp) + 1 > sql_len) {
-                    sql_len *= 2;
-                    sql = realloc(sql, sql_len);
-                    assert(sql);
-                }
-                strcat(sql, tmp);
-            }
-            int i_hstore_column;
-            for(i_hstore_column = 0; i_hstore_column < Options->n_hstore_columns; i_hstore_column++)
-            {
-                strcat(sql, ",\"");
-                strcat(sql, Options->hstore_columns[i_hstore_column]);
-                strcat(sql, "\" hstore ");
-            }
-            if (Options->enable_hstore) {
-                strcat(sql, ",tags hstore );\n");
-	    } else {
-	      strcat(sql, " );\n");
-	    }
-
-            pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", sql);
-            pgsql_exec(sql_conn, PGRES_TUPLES_OK, "SELECT AddGeometryColumn('%s', 'way', %d, '%s', 2 );\n",
-                        tables[i].name, SRID, tables[i].type );
-            pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ALTER TABLE %s ALTER COLUMN way SET NOT NULL;\n", tables[i].name);
-            /* slim mode needs this to be able to apply diffs */
-            if( Options->slim )
-	      pgsql_exec(sql_conn, PGRES_COMMAND_OK, "CREATE INDEX %s_pkey ON %s USING BTREE (osm_id) TABLESPACE %s;\n", tables[i].name, tables[i].name, Options->tblsindex);
-        } else {
-            /* Add any new columns referenced in the default.style */
-            PGresult *res;
-            sprintf(sql, "SELECT * FROM %s LIMIT 0;\n", tables[i].name);
-            res = PQexec(sql_conn, sql);
-            if (PQresultStatus(res) != PGRES_TUPLES_OK) {
-                fprintf(stderr, "Error, failed to query table %s\n%s\n", tables[i].name, sql);
-                exit_nicely();
-            }
-            for (j=0; j < numTags; j++) {
-                if( exportTags[j].flags & FLAG_DELETE )
-                    continue;
-		if( (exportTags[j].flags & FLAG_PHSTORE) == FLAG_PHSTORE)
-		    continue;
-                sprintf(tmp, "\"%s\"", exportTags[j].name);
-                if (PQfnumber(res, tmp) < 0) {
-#if 0
-                    fprintf(stderr, "Append failed. Column \"%s\" is missing from \"%s\"\n", exportTags[j].name, tables[i].name);
-                    exit_nicely();
-#else
-                    fprintf(stderr, "Adding new column \"%s\" to \"%s\"\n", exportTags[j].name, tables[i].name);
-                    pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ALTER TABLE %s ADD COLUMN \"%s\" %s;\n", tables[i].name, exportTags[j].name, exportTags[j].type);
-#endif
-                }
-                /* Note: we do not verify the type or delete unused columns */
-            }
-
-            PQclear(res);
-
-            /* change the type of the geometry column if needed - this can only change to a more permisive type */
-            pgsql_exec(sql_conn, PGRES_COMMAND_OK, "UPDATE geometry_columns SET type = '%s' where type != '%s' and f_table_name = '%s' and f_geometry_column = 'way'",
-                        tables[i].type, tables[i].type, tables[i].name);
-        }
-        pgsql_exec(sql_conn, PGRES_COMMAND_OK, "PREPARE get_way (int4) AS SELECT AsText(way) FROM %s WHERE osm_id = $1;\n", tables[i].name);
-        
-        /* Generate column list for COPY */
-        strcpy(sql, "osm_id");
-        for (j=0; j < numTags; j++) {
-            if( exportTags[j].flags & FLAG_DELETE )
-                continue;
-	    if( (exportTags[j].flags & FLAG_PHSTORE ) == FLAG_PHSTORE)
-		    continue;
-            sprintf(tmp, ",\"%s\"", exportTags[j].name);
-
-            if (strlen(sql) + strlen(tmp) + 1 > sql_len) {
-                sql_len *= 2;
-                sql = realloc(sql, sql_len);
-                assert(sql);
-            }
-            strcat(sql, tmp);
-        }
-
-        int i_hstore_column;
-        for(i_hstore_column = 0; i_hstore_column < Options->n_hstore_columns; i_hstore_column++)
-        {
-            strcat(sql, ",\"");
-            strcat(sql, Options->hstore_columns[i_hstore_column]);
-            strcat(sql, "\" ");
-        }
-    
-	if (Options->enable_hstore) strcat(sql,",tags");
-
-	tables[i].columns = strdup(sql);
-        pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way) FROM STDIN", tables[i].name, tables[i].columns);
-
-        tables[i].copyMode = 1;
+		sprintf(tmp, ",\"%s\"", exportTags[j].name);
+		
+		if (strlen(sql) + strlen(tmp) + 1 > sql_len) {
+		    sql_len *= 2;
+		    sql = realloc(sql, sql_len);
+		    assert(sql);
+		}
+		strcat(sql, tmp);
+	    }
+	    
+	    int i_hstore_column;
+	    for(i_hstore_column = 0; i_hstore_column < Options->n_hstore_columns; i_hstore_column++)
+	    {
+		strcat(sql, ",\"");
+		strcat(sql, Options->hstore_columns[i_hstore_column]);
+		strcat(sql, "\" ");
+	    }
+	    
+	    if (Options->enable_hstore) strcat(sql,",tags");
+	    
+	    tables[i].columns = strdup(sql);
+	    pgsql_exec(sql_conn, PGRES_COPY_IN, "COPY %s (%s,way) FROM STDIN", tables[i].name, tables[i].columns);
+	    
+	    tables[i].copyMode = 1;
+	} else  // non-geometry table
+	{
+	    if (!options->append) {
+		pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", tables[i].create);
+		if (tables[i].index)
+		    pgsql_exec(sql_conn, PGRES_COMMAND_OK, "%s", tables[i].index);
+	    }
+
+	    // Duplication is so there's something to free later.
+	    tables[i].columns = strdup(tables[i].columns);
+
+	    pgsql_exec(sql_conn, PGRES_COPY_IN, "%s", tables[i].copy);
+	    tables[i].copyMode = 1;
+	}
     }
+
     free(sql);
 
     expire_tiles_init(options);
@@ -1333,22 +1412,24 @@
     pgsql_exec(sql_conn, PGRES_COMMAND_OK, "COMMIT");
     if( !Options->append )
     {
-      fprintf(stderr, "Sorting data and creating indexes for %s\n", table->name);
-      pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ANALYZE %s;\n", table->name);
-      pgsql_exec(sql_conn, PGRES_COMMAND_OK, "CREATE TABLE %s_tmp AS SELECT * FROM %s ORDER BY way;\n", table->name, table->name);
-      pgsql_exec(sql_conn, PGRES_COMMAND_OK, "DROP TABLE %s;\n", table->name);
-      pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ALTER TABLE %s_tmp RENAME TO %s;\n", table->name, table->name);
-      pgsql_exec(sql_conn, PGRES_COMMAND_OK, "CREATE INDEX %s_index ON %s USING GIST (way GIST_GEOMETRY_OPS) TABLESPACE %s;\n", table->name, table->name, Options->tblsindex);
-      /* slim mode needs this to be able to apply diffs */
-      if( Options->slim )
-	pgsql_exec(sql_conn, PGRES_COMMAND_OK, "CREATE INDEX %s_pkey ON %s USING BTREE (osm_id) TABLESPACE %s;\n", table->name, table->name, Options->tblsindex);
-      pgsql_exec(sql_conn, PGRES_COMMAND_OK, "GRANT SELECT ON %s TO PUBLIC;\n", table->name);
-      pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ANALYZE %s;\n", table->name);
+	fprintf(stderr, "Sorting data and creating indexes for %s\n", table->name);
+	if (table->type)
+	{
+	    pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ANALYZE %s;\n", table->name);
+	    pgsql_exec(sql_conn, PGRES_COMMAND_OK, "CREATE TABLE %s_tmp AS SELECT * FROM %s ORDER BY way;\n", table->name, table->name);
+	    pgsql_exec(sql_conn, PGRES_COMMAND_OK, "DROP TABLE %s;\n", table->name);
+	    pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ALTER TABLE %s_tmp RENAME TO %s;\n", table->name, table->name);
+	    pgsql_exec(sql_conn, PGRES_COMMAND_OK, "CREATE INDEX %s_index ON %s USING GIST (way GIST_GEOMETRY_OPS) TABLESPACE %s;\n", table->name, table->name, Options->tblsindex);
+	    /* slim mode needs this to be able to apply diffs */
+	    if( Options->slim )
+		pgsql_exec(sql_conn, PGRES_COMMAND_OK, "CREATE INDEX %s_pkey ON %s USING BTREE (osm_id) TABLESPACE %s;\n", table->name, table->name, Options->tblsindex);
+	}
+	pgsql_exec(sql_conn, PGRES_COMMAND_OK, "GRANT SELECT ON %s TO PUBLIC;\n", table->name);
+	pgsql_exec(sql_conn, PGRES_COMMAND_OK, "ANALYZE %s;\n", table->name);
     }
     PQfinish(sql_conn);
     table->sql_conn = NULL;
     fprintf(stderr, "Completed %s\n", table->name);
-    free(table->name);
     free(table->columns);
     return NULL;
 }
@@ -1491,6 +1572,7 @@
   if(Options->mid->relations_set)
     Options->mid->relations_set(id, members, member_count, tags);
   // (int id, struct keyval *rel_tags, struct osmNode **xnodes, struct keyval **xtags, int *xcount)
+  pgsql_out_member(id, members, member_count);
 
   return pgsql_process_relation(id, members, member_count, tags, 0);
 }
@@ -1555,6 +1637,10 @@
     pgsql_exec(tables[t_roads].sql_conn, PGRES_COMMAND_OK, "DELETE FROM %s WHERE osm_id = %d", tables[t_roads].name, -osm_id );
     pgsql_exec(tables[t_line].sql_conn, PGRES_COMMAND_OK, "DELETE FROM %s WHERE osm_id = %d", tables[t_line].name, -osm_id );
     pgsql_exec(tables[t_poly].sql_conn, PGRES_COMMAND_OK, "DELETE FROM %s WHERE osm_id = %d", tables[t_poly].name, -osm_id );
+
+    pgsql_pause_copy(&tables[t_member]);
+    pgsql_exec(tables[t_member].sql_conn, PGRES_COMMAND_OK, "DELETE FROM %s WHERE rel_id = %d", tables[t_member].name, -osm_id );
+
     return 0;
 }
 

=== modified file 'pgsql.h'
--- pgsql.h	2011-01-13 21:54:05 +0000
+++ pgsql.h	2011-01-18 15:56:10 +0000
@@ -3,7 +3,7 @@
 /* Current middle and output-pgsql do a lot of things similarly, this should
  * be used to abstract to commonalities */
 
-//#define DEBUG_PGSQL
+#define DEBUG_PGSQL
 
 PGresult *pgsql_execPrepared( PGconn *sql_conn, const char *stmtName, int nParams, const char *const * paramValues, ExecStatusType expect);
 int pgsql_CopyData(const char *context, PGconn *sql_conn, const char *sql);

_______________________________________________
dev mailing list
dev@openstreetmap.org
http://lists.openstreetmap.org/listinfo/dev

Reply via email to