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