source: subversion/applications/utils/export/osm2pgsql/middle-pgsql.c @ 3210

Last change on this file since 3210 was 2827, checked in by jonb, 13 years ago

osm2pgsql - make experimental version current, move previous implementation to legacy

File size: 21.8 KB
Line 
1/* Implements the mid-layer processing for osm2pgsql
2 * using several PostgreSQL tables
3 *
4 * This layer stores data read in from the planet.osm file
5 * and is then read by the backend processing code to
6 * emit the final geometry-enabled output formats
7*/
8 
9#include <stdio.h>
10#include <unistd.h>
11#include <stdlib.h>
12#include <string.h>
13#include <assert.h>
14
15#include <libpq-fe.h>
16
17#include "osmtypes.h"
18#include "middle.h"
19#include "middle-pgsql.h"
20
21#include "output-pgsql.h"
22
23/* Postgres database parameters */
24static const char *conninfo = "dbname = gis";
25
26enum table_id {
27    t_node, t_segment, t_node_tag, t_way_tag, t_way_seg
28} ;
29
30struct table_desc {
31    //enum table_id table;
32    const char *name;
33    const char *start;
34    const char *create;
35    const char *prepare;
36    const char *copy;
37    const char *analyze;
38    const char *stop;
39};
40
41static struct table_desc tables [] = {
42    { 
43        //table: t_node,
44         name: "nodes",
45        start: "BEGIN;\n",
46       create: "CREATE  TABLE nodes (\"id\" int4 PRIMARY KEY, \"lat\" double precision, \"lon\" double precision);\n",
47      prepare: "PREPARE insert_node (int4, double precision, double precision) AS INSERT INTO nodes VALUES ($1,$2,$3);\n"
48               "PREPARE get_node (int4) AS SELECT \"lat\",\"lon\" FROM nodes WHERE \"id\" = $1 LIMIT 1;\n",
49         copy: "COPY nodes FROM STDIN;\n",
50      analyze: "ANALYZE nodes;\n",
51         stop: "COMMIT;\n"
52    },
53    {
54        //table: t_segment,
55         name: "segments",
56        start: "BEGIN;\n",
57       create: "CREATE  TABLE segments (\"id\" int4 PRIMARY KEY,\"from\" int4,\"to\" int4);\n",
58      prepare: "PREPARE insert_segment (int4, int4, int4) AS INSERT INTO segments VALUES ($1,$2,$3);\n"
59               "PREPARE get_segment (int4) AS SELECT \"from\",\"to\" FROM segments WHERE \"id\" = $1 LIMIT 1;\n",
60         copy: "COPY segments FROM STDIN;\n",
61      analyze: "ANALYZE segments;\n",
62         stop: "COMMIT;\n"
63    },
64    { 
65        //table: t_node_tag,
66         name: "node_tag",
67        start: "BEGIN;\n",
68       create: "CREATE  TABLE node_tag (\"id\" int4 NOT NULL, \"key\" text, \"value\" text);\n"
69               "CREATE INDEX node_tag_idx ON node_tag (\"id\");\n",
70      prepare: "PREPARE insert_node_tag (int4, text, text) AS INSERT INTO node_tag VALUES ($1,$2,$3);\n"
71               "PREPARE get_node_tag_key (int4, text) AS SELECT \"value\" FROM node_tag WHERE \"id\" = $1 AND \"key\" = $2 LIMIT 1;\n"
72               "PREPARE get_node_tag (int4) AS SELECT \"key\",\"value\" FROM node_tag WHERE \"id\" = $1;\n",
73         copy: "COPY node_tag FROM STDIN;\n",
74      analyze: "ANALYZE node_tag;\n",
75         stop: "COMMIT;\n"
76    },
77    { 
78        //table: t_way_tag,
79         name: "way_tag",
80        start: "BEGIN;\n",
81       create: "CREATE  TABLE way_tag (\"id\" int4 NOT NULL, \"key\" text, \"value\" text);\n"
82               "CREATE INDEX way_tag_idx ON way_tag (\"id\");\n",
83      prepare: "PREPARE insert_way_tag (int4, text, text) AS INSERT INTO way_tag VALUES ($1,$2,$3);\n"
84               "PREPARE get_way_tag_key (int4, text) AS SELECT \"value\" FROM way_tag WHERE \"id\" = $1 AND \"key\" = $2 LIMIT 1;\n"
85               "PREPARE get_way_tag (int4) AS SELECT \"key\",\"value\" FROM way_tag WHERE \"id\" = $1;\n",
86         copy: "COPY way_tag FROM STDIN;\n",
87      analyze: "ANALYZE way_tag;\n",
88         stop:  "COMMIT;\n"
89    },
90    { 
91        //table: t_way_seg,
92         name: "way_seg",
93        start: "BEGIN;\n",
94       create: "CREATE  TABLE way_seg (\"id\" int4 NOT NULL, \"seg_id\" int4);\n"
95               "CREATE INDEX way_seg_idx ON way_seg (\"id\");\n",
96      prepare: "PREPARE insert_way_seg (int4, int4) AS INSERT INTO way_seg VALUES ($1,$2);\n"
97               "PREPARE get_way_seg (int4) AS SELECT \"seg_id\" FROM way_seg WHERE \"id\" = $1;\n",
98         copy: "COPY way_seg FROM STDIN;\n",
99      analyze: "ANALYZE way_seg;\n",
100         stop: "COMMIT;\n"
101    }
102};
103
104static int num_tables = sizeof(tables)/sizeof(*tables);
105static PGconn **sql_conns;
106
107static void pgsql_cleanup(void)
108{
109    int i;
110
111    if (!sql_conns)
112           return;
113
114    for (i=0; i<num_tables; i++) {
115        if (sql_conns[i]) {
116            PQfinish(sql_conns[i]);
117            sql_conns[i] = NULL;
118        }
119    }
120}
121
122void escape(char *out, int len, const char *in)
123{ 
124    /* Apply escaping of TEXT COPY data
125    Escape: backslash itself, newline, carriage return, and the current delimiter character (tab)
126    file:///usr/share/doc/postgresql-8.1.8/html/sql-copy.html
127    */
128    int count = 0; 
129    const char *old_in = in, *old_out = out;
130
131    if (!len)
132        return;
133
134    while(*in && count < len-3) { 
135        switch(*in) {
136            case '\\': *out++ = '\\'; *out++ = '\\'; count+= 2; break;
137      //    case    8: *out++ = '\\'; *out++ = '\b'; count+= 2; break;
138      //    case   12: *out++ = '\\'; *out++ = '\f'; count+= 2; break;
139            case '\n': *out++ = '\\'; *out++ = '\n'; count+= 2; break;
140            case '\r': *out++ = '\\'; *out++ = '\r'; count+= 2; break;
141            case '\t': *out++ = '\\'; *out++ = '\t'; count+= 2; break;
142      //    case   11: *out++ = '\\'; *out++ = '\v'; count+= 2; break;
143            default:   *out++ = *in; count++; break;
144        }
145        in++;
146    }
147    *out = '\0';
148
149    if (*in)
150        fprintf(stderr, "%s truncated at %d chars: %s\n%s\n", __FUNCTION__, count, old_in, old_out);
151}
152
153static void psql_add_tag_generic(PGconn *sql_conn, int id, const char *key, const char *value)
154{
155    char sql[256];
156    int r;
157    /* TODO:
158    * Also watch for buffer overflow on long tag / value!
159    */
160    //sprintf(sql, "%d\t%s\t%s\n", node_id, key, value);
161    sprintf(sql, "%d\t", id);
162    r = PQputCopyData(sql_conn, sql, strlen(sql));
163    if (r != 1) {
164        fprintf(stderr, "%s - bad result %d, line %s\n", __FUNCTION__, r, sql);
165        exit_nicely();
166    }
167    escape(sql, sizeof(sql), key);
168    r = PQputCopyData(sql_conn, sql, strlen(sql));
169    if (r != 1) {
170        fprintf(stderr, "%s - bad result %d, line %s\n", __FUNCTION__, r, sql);
171        exit_nicely();
172    }
173    r = PQputCopyData(sql_conn, "\t", 1);
174    if (r != 1) {
175        fprintf(stderr, "%s - bad result %d, tab\n", __FUNCTION__, r);
176        exit_nicely();
177    }
178
179    escape(sql, sizeof(sql), value);
180    r = PQputCopyData(sql_conn, sql, strlen(sql));
181    if (r != 1) {
182        fprintf(stderr, "%s - bad result %d, line %s\n", __FUNCTION__, r, sql);
183        exit_nicely();
184    }
185
186    r = PQputCopyData(sql_conn, "\n", 1);
187    if (r != 1) {
188        fprintf(stderr, "%s - bad result %d, newline\n", __FUNCTION__, r);
189        exit_nicely();
190    }
191}
192
193#if 0
194static void psql_add_node_tag(int id, const char *key, const char *value)
195{
196    PGconn *sql_conn = sql_conns[t_node_tag];
197    psql_add_tag_generic(sql_conn, id, key, value);
198}
199#endif
200static void psql_add_way_tag(int id, const char *key, const char *value)
201{
202    PGconn *sql_conn = sql_conns[t_way_tag];
203    psql_add_tag_generic(sql_conn, id, key, value);
204}
205
206static int pgsql_nodes_set_pos(int id, double lat, double lon)
207{
208    PGconn *sql_conn = sql_conns[t_node];
209    char sql[128];
210    int r;
211
212    sprintf(sql, "%d\t%.15g\t%.15g\n", id, lat, lon);
213    r = PQputCopyData(sql_conn, sql, strlen(sql));
214    if (r != 1) {
215        fprintf(stderr, "%s - bad result %d, line %s\n", __FUNCTION__, r, sql);
216        exit_nicely();
217    }
218
219    return 0;
220}
221
222static int pgsql_nodes_set(int id, double lat, double lon, struct keyval *tags)
223{
224//    struct keyval *p;
225    int r = pgsql_nodes_set_pos(id, lat,  lon);
226
227    if (r) return r;
228
229#if 1
230    /* FIXME: This is a performance hack which interferes with a clean middle / output separation */
231    out_pgsql.node(id, tags, lat, lon);
232    resetList(tags);
233#else
234    while((p = popItem(tags)) != NULL) {
235        psql_add_node_tag(id, p->key, p->value);
236        freeItem(p);
237    }
238#endif
239    return 0;
240}
241
242
243static int pgsql_nodes_get(struct osmNode *out, int id)
244{
245    PGresult   *res;
246    char tmp[16];
247    char const *paramValues[1];
248    PGconn *sql_conn = sql_conns[t_node];
249
250    snprintf(tmp, sizeof(tmp), "%d", id);
251    paramValues[0] = tmp;
252 
253    res = PQexecPrepared(sql_conn, "get_node", 1, paramValues, NULL, NULL, 0);
254    if (PQresultStatus(res) != PGRES_TUPLES_OK) {
255        fprintf(stderr, "get_node failed: %s(%d)\n", PQerrorMessage(sql_conn), PQresultStatus(res));
256        PQclear(res);
257        exit_nicely();
258    }
259
260    if (PQntuples(res) != 1) {
261        PQclear(res);
262        return 1;
263    } 
264
265    out->lat = strtod(PQgetvalue(res, 0, 0), NULL);
266    out->lon = strtod(PQgetvalue(res, 0, 1), NULL);
267    PQclear(res);
268    return 0;
269}
270
271static int pgsql_segments_set(int id, int from, int to, struct keyval *tags)
272{
273    PGconn *sql_conn = sql_conns[t_segment];
274    char sql[128];
275    int r;
276
277    sprintf(sql, "%d\t%d\t%d\n", id, from, to);
278    r = PQputCopyData(sql_conn, sql, strlen(sql));
279    if (r != 1) {
280        fprintf(stderr, "%s - bad result %d, line %s\n", __FUNCTION__, r, sql);
281        exit_nicely();
282    }
283    resetList(tags);
284
285    return 0;
286}
287
288static int pgsql_segments_get(struct osmSegment *out, int id)
289{
290    PGresult   *res;
291    char tmp[16];
292    char const *paramValues[1];
293    PGconn *sql_conn = sql_conns[t_segment];
294
295    snprintf(tmp, sizeof(tmp), "%d", id);
296    paramValues[0] = tmp;
297
298    res = PQexecPrepared(sql_conn, "get_segment", 1, paramValues, NULL, NULL, 0);
299    if (PQresultStatus(res) != PGRES_TUPLES_OK) {
300        fprintf(stderr, "get_segment failed: %s(%d)\n", PQerrorMessage(sql_conn), PQresultStatus(res));
301        PQclear(res);
302        exit_nicely();
303    }
304
305    if (PQntuples(res) != 1) {
306        PQclear(res);
307        return 1;
308    }
309
310    out->from = strtol(PQgetvalue(res, 0, 0), NULL, 10);
311    out->to   = strtol(PQgetvalue(res, 0, 1), NULL, 10);
312    PQclear(res);
313    return 0;
314}
315
316
317static void psql_add_way_seg(int way_id, int seg_id)
318{
319    PGconn *sql_conn = sql_conns[t_way_seg];
320    char sql[128];
321    int r;
322
323    sprintf(sql, "%d\t%d\n", way_id, seg_id);
324    r = PQputCopyData(sql_conn, sql, strlen(sql));
325    if (r != 1) {
326        fprintf(stderr, "%s - bad result %d, line %s\n", __FUNCTION__, r, sql);
327        exit_nicely();
328    }
329}
330
331
332static int pgsql_ways_set(int way_id, struct keyval *segs, struct keyval *tags)
333{
334#if 1
335    struct keyval *p;
336
337    while((p = popItem(segs)) != NULL) {
338        int seg_id = strtol(p->value, NULL, 10);
339        psql_add_way_seg(way_id, seg_id);
340        freeItem(p);
341    }
342
343    while((p = popItem(tags)) != NULL) {
344        psql_add_way_tag(way_id, p->key, p->value);
345        freeItem(p);
346    }
347#else
348    // FIXME: Performance hack - output ways directly. Doesn't work in COPY model
349   out_pgsql.way(&mid_pgsql, way_id, tags, segs);
350   resetList(tags);
351   resetList(segs);
352#endif
353    return 0;
354}
355
356static int *pgsql_ways_get(int id)
357{
358    fprintf(stderr, "TODO: %s %d\n", __FUNCTION__, id);
359    return NULL;
360}
361
362
363static void pgsql_iterate_nodes(int (*callback)(int id, struct keyval *tags, double node_lat, double node_lon))
364{
365    PGresult   *res_nodes, *res_tags;
366    PGconn *sql_conn_nodes = sql_conns[t_node];
367    PGconn *sql_conn_tags = sql_conns[t_node_tag];
368    int i, j;
369    struct keyval tags;
370
371    initList(&tags);
372
373    res_nodes = PQexec(sql_conn_nodes, "SELECT * FROM nodes");
374    if (PQresultStatus(res_nodes) != PGRES_TUPLES_OK) {
375        fprintf(stderr, "%s failed: %s", __FUNCTION__, PQerrorMessage(sql_conn_nodes));
376        PQclear(res_nodes);
377        exit_nicely();
378    }
379
380    for (i = 0; i < PQntuples(res_nodes); i++) {
381        const char *paramValues[1];
382        const char *xid = PQgetvalue(res_nodes, i, 0);
383        int          id = strtol(xid, NULL, 10);
384        double node_lat = strtod(PQgetvalue(res_nodes, i, 1), NULL);
385        double node_lon = strtod(PQgetvalue(res_nodes, i, 2), NULL);
386
387        if (i %10000 == 0)
388            fprintf(stderr, "\rprocessing node (%dk)", i/1000);
389
390        paramValues[0] = xid;
391
392        res_tags = PQexecPrepared(sql_conn_tags, "get_node_tag", 1, paramValues, NULL, NULL, 0);
393        if (PQresultStatus(res_tags) != PGRES_TUPLES_OK) {
394            fprintf(stderr, "get_node_tag failed: %s(%d)\n", PQerrorMessage(sql_conn_tags), PQresultStatus(res_tags));
395            PQclear(res_tags);
396            exit_nicely();
397        }
398
399        for (j=0; j<PQntuples(res_tags); j++) {
400            const char *key   = PQgetvalue(res_tags, j, 0);
401            const char *value = PQgetvalue(res_tags, j, 1);
402            addItem(&tags, key, value, 0);
403        }
404
405        callback(id, &tags, node_lat, node_lon);
406
407        PQclear(res_tags);
408        resetList(&tags);
409    }
410
411    PQclear(res_nodes);
412    fprintf(stderr, "\n");
413}
414
415#if 0
416static struct osmSegLL *getSegLL(struct keyval *segs, int *segCount)
417{
418    struct keyval *p;
419    struct osmSegment segment;
420    struct osmNode node;
421    int id;
422    int count = 0;
423    struct osmSegLL *segll = malloc(countList(segs) * sizeof(struct osmSegLL));
424
425    if (!segll) {
426        resetList(segs);
427        *segCount = 0;
428        return NULL;
429    }
430
431    while ((p = popItem(segs)) != NULL)
432    {
433        id = strtol(p->value, NULL, 10);
434        freeItem(p);
435
436        if (pgsql_segments_get(&segment, id))
437            continue;
438
439        if (pgsql_nodes_get(&node, segment.from))
440            continue;
441
442        segll[count].lon0 = node.lon;
443        segll[count].lat0 = node.lat;
444
445        if (pgsql_nodes_get(&node, segment.to))
446            continue;
447
448        segll[count].lon1 = node.lon;
449        segll[count].lat1 = node.lat;
450
451        count++;
452    }
453    *segCount = count;
454    return segll;
455}
456#endif
457
458void getTags(int id, struct keyval *tags)
459{
460    PGconn *sql_conn_tags = sql_conns[t_way_tag];
461    PGresult   *res_tags;
462    char tmp[16];
463    const char *paramValues[1];
464    int j;
465
466    snprintf(tmp, sizeof(tmp), "%d", id);
467    paramValues[0] = tmp;
468
469    res_tags = PQexecPrepared(sql_conn_tags, "get_way_tag", 1, paramValues, NULL, NULL, 0);
470    if (PQresultStatus(res_tags) != PGRES_TUPLES_OK) {
471        fprintf(stderr, "get_way_tag failed: %s(%d)\n", PQerrorMessage(sql_conn_tags), PQresultStatus(res_tags));
472        PQclear(res_tags);
473        exit_nicely();
474    }
475
476    for (j=0; j<PQntuples(res_tags); j++) {
477        const char *key   = PQgetvalue(res_tags, j, 0);
478        const char *value = PQgetvalue(res_tags, j, 1);
479        addItem(tags, key, value, 0);
480    }
481    PQclear(res_tags);
482}
483
484
485static void pgsql_iterate_ways(int (*callback)(int id, struct keyval *tags, struct osmSegLL *segll, int count))
486{
487    char sql[2048];
488    PGresult   *res_ways, *res_nodes;
489    int i, j, count = 0;
490    struct keyval tags;
491    struct osmSegLL *segll;
492    PGconn *sql_conn_segs = sql_conns[t_way_seg];
493
494    initList(&tags);
495
496    fprintf(stderr, "\nRetrieving way list\n");
497
498/*
499gis=> select w.id,s.id,nf.lat,nf.lon,nt.lat,nt.lon from way_seg as w,nodes as nf, nodes as nt, segments as s where w.seg_id=s.id and nf.id=s.from and nt.id=s.to limit 10;
500   id    |    id    |    lat    |    lon    |    lat    |    lon
501---------+----------+-----------+-----------+-----------+-----------
502 3186577 | 10872312 | 51.720753 | -0.362055 | 51.720567 | -0.364115
503 3186577 | 10872311 | 51.720979 | -0.360532 | 51.720753 | -0.362055
504 3186577 | 10872310 | 51.721258 | -0.359137 | 51.720979 | -0.360532
505*/
506
507    res_ways = PQexec(sql_conn_segs, "SELECT id from way_seg GROUP BY id");
508    if (PQresultStatus(res_ways) != PGRES_TUPLES_OK) {
509        fprintf(stderr, "%s(%d) failed: %s", __FUNCTION__, __LINE__, PQerrorMessage(sql_conn_segs));
510        PQclear(res_ways);
511        exit_nicely();
512    }
513
514    fprintf(stderr, "\nIterating ways\n");
515    for (i = 0; i < PQntuples(res_ways); i++) {
516        int id = strtol(PQgetvalue(res_ways, i, 0), NULL, 10);
517        int segCount;
518
519        if (count++ %1000 == 0)
520                fprintf(stderr, "\rprocessing way (%dk)", count/1000);
521
522        getTags(id, &tags);
523
524        sprintf(sql,"SELECT nf.lat,nf.lon,nt.lat,nt.lon "
525                    "FROM way_seg AS w,nodes AS nf, nodes AS nt, segments AS s "
526                    "WHERE w.seg_id=s.id AND nf.id=s.from AND nt.id=s.to AND w.id=%d", id);
527
528        res_nodes = PQexec(sql_conn_segs, sql);
529        if (PQresultStatus(res_nodes) != PGRES_TUPLES_OK) {
530            fprintf(stderr, "%s(%d) failed: %s", __FUNCTION__, __LINE__, PQerrorMessage(sql_conn_segs));
531            PQclear(res_nodes);
532            exit_nicely();
533        }
534
535        segCount = PQntuples(res_nodes);
536        segll = malloc(segCount * sizeof(struct osmSegLL));
537
538        if (segll) {
539            for (j=0; j<segCount; j++) {
540                segll[j].lat0 = strtod(PQgetvalue(res_nodes, j, 0), NULL);
541                segll[j].lon0 = strtod(PQgetvalue(res_nodes, j, 1), NULL);
542                segll[j].lat1 = strtod(PQgetvalue(res_nodes, j, 2), NULL);
543                segll[j].lon1 = strtod(PQgetvalue(res_nodes, j, 3), NULL);
544            }
545            callback(id, &tags, segll, segCount);
546            free(segll);
547        }
548        PQclear(res_nodes);
549        resetList(&tags);
550    }
551
552    PQclear(res_ways);
553    fprintf(stderr, "\n");
554}
555
556
557static void pgsql_analyze(void)
558{
559    PGresult   *res;
560    int i;
561
562    for (i=0; i<num_tables; i++) {
563        PGconn *sql_conn = sql_conns[i];
564 
565        if (tables[i].analyze) {
566            res = PQexec(sql_conn, tables[i].analyze);
567            if (PQresultStatus(res) != PGRES_COMMAND_OK) {
568                fprintf(stderr, "%s failed: %s", tables[i].analyze, PQerrorMessage(sql_conn));
569                PQclear(res);
570                exit_nicely();
571            }
572            PQclear(res);
573        }
574    }
575}
576
577static void pgsql_end(void)
578{
579    PGresult   *res;
580    int i;
581
582    for (i=0; i<num_tables; i++) {
583        PGconn *sql_conn = sql_conns[i];
584 
585        /* Terminate any pending COPY */
586         if (tables[i].copy) {
587            int stop = PQputCopyEnd(sql_conn, NULL);
588            if (stop != 1) {
589                fprintf(stderr, "COPY_END for %s failed: %s", tables[i].copy, PQerrorMessage(sql_conn));
590                exit_nicely();
591            }
592
593            res = PQgetResult(sql_conn);
594            if (PQresultStatus(res) != PGRES_COMMAND_OK) {
595                fprintf(stderr, "COPY_END for %s failed: %s", tables[i].copy, PQerrorMessage(sql_conn));
596                PQclear(res);
597                exit_nicely();
598            }
599            PQclear(res);
600        }
601
602        // Commit transaction
603        if (tables[i].stop) {
604            res = PQexec(sql_conn, tables[i].stop);
605            if (PQresultStatus(res) != PGRES_COMMAND_OK) {
606                fprintf(stderr, "%s failed: %s", tables[i].stop, PQerrorMessage(sql_conn));
607                PQclear(res);
608                exit_nicely();
609            }
610            PQclear(res);
611        }
612
613    }
614}
615
616static int pgsql_start(int dropcreate)
617{
618    char sql[2048];
619    PGresult   *res;
620    int i;
621
622    /* We use a connection per table to enable the use of COPY */
623    sql_conns = calloc(num_tables, sizeof(PGconn *));
624    assert(sql_conns);
625
626    for (i=0; i<num_tables; i++) {
627        PGconn *sql_conn;
628
629        fprintf(stderr, "Setting up table: %s\n", tables[i].name);
630        sql_conn = PQconnectdb(conninfo);
631
632        /* Check to see that the backend connection was successfully made */
633        if (PQstatus(sql_conn) != CONNECTION_OK) {
634            fprintf(stderr, "Connection to database failed: %s", PQerrorMessage(sql_conn));
635            exit_nicely();
636        }
637        sql_conns[i] = sql_conn;
638
639        if (dropcreate) {
640            sql[0] = '\0';
641            strcat(sql, "DROP TABLE ");
642            strcat(sql, tables[i].name);
643            res = PQexec(sql_conn, sql);
644            PQclear(res); /* Will be an error if table does not exist */
645        }
646
647        if (tables[i].start) {
648            res = PQexec(sql_conn, tables[i].start);
649            if (PQresultStatus(res) != PGRES_COMMAND_OK) {
650                fprintf(stderr, "%s failed: %s", tables[i].start, PQerrorMessage(sql_conn));
651                PQclear(res);
652                exit_nicely();
653            }
654            PQclear(res);
655        }
656
657        if (dropcreate && tables[i].create) {
658            res = PQexec(sql_conn, tables[i].create);
659            if (PQresultStatus(res) != PGRES_COMMAND_OK) {
660                fprintf(stderr, "%s failed: %s", tables[i].create, PQerrorMessage(sql_conn));
661                PQclear(res);
662                exit_nicely();
663            }
664            PQclear(res);
665        }
666
667        if (tables[i].prepare) {
668            res = PQexec(sql_conn, tables[i].prepare);
669            if (PQresultStatus(res) != PGRES_COMMAND_OK) {
670                fprintf(stderr, "%s failed: %s", tables[i].prepare, PQerrorMessage(sql_conn));
671                PQclear(res);
672                exit_nicely();
673            }
674            PQclear(res);
675        }
676
677        if (tables[i].copy) {
678            res = PQexec(sql_conn, tables[i].copy);
679            if (PQresultStatus(res) != PGRES_COPY_IN) {
680                fprintf(stderr, "%s failed: %s", tables[i].copy, PQerrorMessage(sql_conn));
681                PQclear(res);
682                exit_nicely();
683            }
684            PQclear(res);
685        }
686    }
687
688    return 0;
689}
690
691static void pgsql_stop(void)
692{
693    //PGresult   *res;
694    PGconn *sql_conn;
695    int i;
696
697   for (i=0; i<num_tables; i++) {
698        //fprintf(stderr, "Stopping table: %s\n", tables[i].name);
699        sql_conn = sql_conns[i];
700#if 0
701        if (tables[i].stop) {
702            res = PQexec(sql_conn, tables[i].stop);
703            if (PQresultStatus(res) != PGRES_COMMAND_OK) {
704                fprintf(stderr, "%s failed: %s", tables[i].stop, PQerrorMessage(sql_conn));
705                PQclear(res);
706                exit_nicely();
707            }
708            PQclear(res);
709        }
710#endif
711        PQfinish(sql_conn);
712        sql_conns[i] = NULL;
713    }
714    free(sql_conns);
715    sql_conns = NULL;
716}
717 
718struct middle_t mid_pgsql = {
719        start:          pgsql_start,
720        stop:           pgsql_stop,
721        cleanup:        pgsql_cleanup,
722        analyze:        pgsql_analyze,
723        end:            pgsql_end,
724        segments_set:   pgsql_segments_set,
725        segments_get:   pgsql_segments_get,
726        nodes_set:      pgsql_nodes_set,
727        nodes_get:      pgsql_nodes_get,
728        ways_set:       pgsql_ways_set,
729        ways_get:       pgsql_ways_get,
730        iterate_nodes:  pgsql_iterate_nodes,
731        iterate_ways:   pgsql_iterate_ways
732};
Note: See TracBrowser for help on using the repository browser.