]> git.openstreetmap.org Git - nominatim.git/blob - nominatim/import.c
345b2cd4423b2fb307114efc2121c43bf7503570
[nominatim.git] / nominatim / import.c
1 /*
2 */
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include <libpq-fe.h>
7
8 #include <libxml/xmlstring.h>
9 #include <libxml/xmlreader.h>
10 #include <libxml/hash.h>
11
12 #include "nominatim.h"
13 #include "import.h"
14 #include "input.h"
15
16 typedef enum { FILETYPE_NONE, FILETYPE_STRUCTUREDV0P1 } filetypes_t;
17 typedef enum { FILEMODE_NONE, FILEMODE_ADD, FILEMODE_UPDATE, FILEMODE_DELETE } filemodes_t;
18
19 #define MAX_FEATUREADDRESS 500
20 #define MAX_FEATURENAMES 1000
21 #define MAX_FEATUREEXTRATAGS 100
22 #define MAX_FEATURENAMESTRING 100000
23 #define MAX_FEATUREEXTRATAGSTRING 50000
24
25 struct feature_address {
26         int                     place_id;
27         int                     rankAddress;
28         char                    isAddress[2];
29         xmlChar *       type;
30         xmlChar *       id;
31         xmlChar *       key;
32         xmlChar *       value;
33         xmlChar *       distance;
34 };
35
36 struct feature_tag {
37         xmlChar *       type;
38         xmlChar *       value;
39 };
40
41 struct feature {
42         int                     placeID;
43         xmlChar *       type;
44         xmlChar *       id;
45         xmlChar *       key;
46         xmlChar *       value;
47         xmlChar *       rankAddress;
48         xmlChar *       rankSearch;
49         xmlChar *       countryCode;
50         xmlChar *       adminLevel;
51         xmlChar *       houseNumber;
52         xmlChar *       geometry;
53 } feature;
54
55 int                                     fileType = FILETYPE_NONE;
56 int                                     fileMode = FILEMODE_ADD;
57 PGconn *                                conn;
58 struct feature_address  featureAddress[MAX_FEATUREADDRESS];
59 struct feature_tag              featureName[MAX_FEATURENAMES];
60 struct feature_tag              featureExtraTag[MAX_FEATUREEXTRATAGS];
61 struct feature                  feature;
62 int                                     featureAddressLines = 0;
63 int                                     featureNameLines = 0;
64 int                                     featureExtraTagLines = 0;
65 int                                     featureCount = 0;
66 xmlHashTablePtr                 partionTableTagsHash;
67 char                                    featureNameString[MAX_FEATURENAMESTRING];
68 char                                    featureExtraTagString[MAX_FEATUREEXTRATAGSTRING];
69
70 void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
71 {
72     char * value;
73     float version;
74     int isAddressLine;
75
76     if (fileType == FILETYPE_NONE)
77     {
78         // Potential to handle other file types in the future / versions
79         if (xmlStrEqual(name, BAD_CAST "osmStructured"))
80         {
81                 value = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "version");
82                 version = strtof(value, NULL);
83                 xmlFree(value);
84
85                 if (version == (float)0.1)
86                 {
87                         fileType = FILETYPE_STRUCTUREDV0P1;
88                         fileMode = FILEMODE_ADD;
89                 }
90                 else
91                 {
92                 fprintf( stderr, "Unknown osmStructured version %f\n", version );
93                 exit_nicely();
94                 }
95         }
96         else
97         {
98             fprintf( stderr, "Unknown XML document type: %s\n", name );
99             exit_nicely();
100         }
101         return;
102     }
103
104     if (xmlStrEqual(name, BAD_CAST "add"))
105     {
106         fileMode = FILEMODE_ADD;
107         return;
108     }
109     if (xmlStrEqual(name, BAD_CAST "update"))
110     {
111         fileMode = FILEMODE_UPDATE;
112         return;
113     }
114     if (xmlStrEqual(name, BAD_CAST "delete"))
115     {
116         fileMode = FILEMODE_DELETE;
117         return;
118     }
119     if (fileMode == FILEMODE_NONE)
120     {
121         fprintf( stderr, "Unknown import mode in: %s\n", name );
122         exit_nicely();
123     }
124
125     if (xmlStrEqual(name, BAD_CAST "feature"))
126     {
127         feature.type = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
128         feature.id = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
129         feature.key = xmlTextReaderGetAttribute(reader, BAD_CAST "key");
130         feature.value = xmlTextReaderGetAttribute(reader, BAD_CAST "value");
131         feature.rankAddress = xmlTextReaderGetAttribute(reader, BAD_CAST "rank");
132         feature.rankSearch = xmlTextReaderGetAttribute(reader, BAD_CAST "importance");
133
134                 feature.countryCode = NULL;
135                 feature.adminLevel = NULL;
136                 feature.houseNumber = NULL;
137                 feature.geometry = NULL;
138                 featureAddressLines = 0;
139                 featureNameLines = 0;
140
141         return;
142     }
143     if (xmlStrEqual(name, BAD_CAST "names")) return;
144     if (xmlStrEqual(name, BAD_CAST "name"))
145     {
146         featureName[featureNameLines].type = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
147         featureName[featureNameLines].value = xmlTextReaderReadString(reader);
148         featureNameLines++;
149         if (featureNameLines >= MAX_FEATURENAMES)
150         {
151             fprintf( stderr, "Too many name elements\n");
152             exit_nicely();
153         }
154         return;
155     }
156     if (xmlStrEqual(name, BAD_CAST "tags")) return;
157     if (xmlStrEqual(name, BAD_CAST "tag"))
158     {
159         featureExtraTag[featureExtraTagLines].type = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
160         featureExtraTag[featureExtraTagLines].value = xmlTextReaderReadString(reader);
161         featureExtraTagLines++;
162         if (featureExtraTagLines >= MAX_FEATUREEXTRATAGS)
163         {
164             fprintf( stderr, "Too many extra tag elements\n");
165             exit_nicely();
166         }
167         return;
168     }
169     if (xmlStrEqual(name, BAD_CAST "osmGeometry"))
170     {
171         feature.geometry = xmlTextReaderReadString(reader);
172         return;
173     }
174     if (xmlStrEqual(name, BAD_CAST "adminLevel"))
175     {
176         feature.adminLevel = xmlTextReaderReadString(reader);
177         return;
178     }
179     if (xmlStrEqual(name, BAD_CAST "countryCode"))
180     {
181         feature.countryCode = xmlTextReaderReadString(reader);
182         return;
183     }
184     if (xmlStrEqual(name, BAD_CAST "houseNumber"))
185     {
186         feature.houseNumber = xmlTextReaderReadString(reader);
187         return;
188     }
189     if (xmlStrEqual(name, BAD_CAST "address"))
190     {
191         featureAddressLines = 0;
192         return;
193     }
194     isAddressLine = 0;
195     if (xmlStrEqual(name, BAD_CAST "continent"))
196     {
197         isAddressLine = 1;
198     }
199     else if (xmlStrEqual(name, BAD_CAST "sea"))
200     {
201         isAddressLine = 1;
202     }
203     else if (xmlStrEqual(name, BAD_CAST "country"))
204     {
205         isAddressLine = 1;
206     }
207     else if (xmlStrEqual(name, BAD_CAST "state"))
208     {
209         isAddressLine = 1;
210     }
211     else if (xmlStrEqual(name, BAD_CAST "county"))
212     {
213         isAddressLine = 1;
214     }
215     else if (xmlStrEqual(name, BAD_CAST "city"))
216     {
217         isAddressLine = 1;
218     }
219     else if (xmlStrEqual(name, BAD_CAST "town"))
220     {
221         isAddressLine = 1;
222     }
223     else if (xmlStrEqual(name, BAD_CAST "village"))
224     {
225         isAddressLine = 1;
226     }
227     else if (xmlStrEqual(name, BAD_CAST "unknown"))
228     {
229         isAddressLine = 1;
230     }
231     else if (xmlStrEqual(name, BAD_CAST "suburb"))
232     {
233         isAddressLine = 1;
234     }
235     else if (xmlStrEqual(name, BAD_CAST "postcode"))
236     {
237         isAddressLine = 1;
238     }
239     else if (xmlStrEqual(name, BAD_CAST "neighborhood"))
240     {
241         isAddressLine = 1;
242     }
243     else if (xmlStrEqual(name, BAD_CAST "street"))
244     {
245         isAddressLine = 1;
246     }
247     else if (xmlStrEqual(name, BAD_CAST "access"))
248     {
249         isAddressLine = 1;
250     }
251     else if (xmlStrEqual(name, BAD_CAST "building"))
252     {
253         isAddressLine = 1;
254     }
255     else if (xmlStrEqual(name, BAD_CAST "other"))
256     {
257         isAddressLine = 1;
258     }
259     if (isAddressLine)
260     {
261         value = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "rank");
262         if (!value)
263         {
264             fprintf( stderr, "Address element missing rank\n");
265             exit_nicely();
266         }
267         featureAddress[featureAddressLines].rankAddress =  atoi(value);
268         xmlFree(value);
269
270         value = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "isaddress");
271         if (!value)
272         {
273             fprintf( stderr, "Address element missing rank\n");
274             exit_nicely();
275         }
276         if (*value == 't') strcpy(featureAddress[featureAddressLines].isAddress, "t");
277         else strcpy(featureAddress[featureAddressLines].isAddress, "f");
278         xmlFree(value);
279
280         featureAddress[featureAddressLines].type = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
281         featureAddress[featureAddressLines].id = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
282         featureAddress[featureAddressLines].key = xmlTextReaderGetAttribute(reader, BAD_CAST "key");
283         featureAddress[featureAddressLines].value = xmlTextReaderGetAttribute(reader, BAD_CAST "value");
284         featureAddress[featureAddressLines].distance = xmlTextReaderGetAttribute(reader, BAD_CAST "distance");
285
286         featureAddressLines++;
287         if (featureAddressLines >= MAX_FEATUREADDRESS)
288         {
289             fprintf( stderr, "Too many address elements\n");
290             exit_nicely();
291         }
292
293         return;
294     }
295     fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
296 }
297
298 void EndElement(xmlTextReaderPtr reader, const xmlChar *name)
299 {
300         PGresult *              res;
301         PGresult *              resPlaceID;
302     const char *        paramValues[11];
303     char *                      place_id;
304     char *                      partionQueryName;
305         int i, namePos, lineTypeLen, lineValueLen;
306
307     if (xmlStrEqual(name, BAD_CAST "feature"))
308         {
309         featureCount++;
310         if (featureCount % 1000 == 0) printf("feature %i(k)\n", featureCount/1000);
311
312         if (fileMode == FILEMODE_ADD)
313         {
314                 resPlaceID = PQexecPrepared(conn, "get_new_place_id", 0, NULL, NULL, NULL, 0);
315                 if (PQresultStatus(resPlaceID) != PGRES_TUPLES_OK)
316                         {
317                                 fprintf(stderr, "get_place_id: INSERT failed: %s", PQerrorMessage(conn));
318                                 PQclear(resPlaceID);
319                                 exit(EXIT_FAILURE);
320                         }
321         }
322         else
323         {
324             paramValues[0] = (const char *)feature.type;
325             paramValues[1] = (const char *)feature.id;
326             paramValues[2] = (const char *)feature.key;
327             paramValues[3] = (const char *)feature.value;
328             resPlaceID = PQexecPrepared(conn, "get_new_place_id", 4, paramValues, NULL, NULL, 0);
329             if (PQresultStatus(resPlaceID) != PGRES_TUPLES_OK)
330             {
331                 fprintf(stderr, "index_placex: INSERT failed: %s", PQerrorMessage(conn));
332                 PQclear(resPlaceID);
333                 exit(EXIT_FAILURE);
334             }
335         }
336                 place_id = PQgetvalue(resPlaceID, 0, 0);
337
338         if (fileMode == FILEMODE_UPDATE || fileMode == FILEMODE_DELETE)
339         {
340             paramValues[0] = (const char *)place_id;
341             res = PQexecPrepared(conn, "placex_delete", 1, paramValues, NULL, NULL, 0);
342             if (PQresultStatus(res) != PGRES_COMMAND_OK)
343             {
344                 fprintf(stderr, "placex_delete: DELETE failed: %s", PQerrorMessage(conn));
345                 PQclear(res);
346                 exit(EXIT_FAILURE);
347             }
348             PQclear(res);
349
350             res = PQexecPrepared(conn, "search_name_delete", 1, paramValues, NULL, NULL, 0);
351             if (PQresultStatus(res) != PGRES_COMMAND_OK)
352             {
353                 fprintf(stderr, "search_name_delete: DELETE failed: %s", PQerrorMessage(conn));
354                 PQclear(res);
355                 exit(EXIT_FAILURE);
356             }
357             PQclear(res);
358
359             res = PQexecPrepared(conn, "place_addressline_delete", 1, paramValues, NULL, NULL, 0);
360             if (PQresultStatus(res) != PGRES_COMMAND_OK)
361             {
362                 fprintf(stderr, "place_addressline_delete: DELETE failed: %s", PQerrorMessage(conn));
363                 PQclear(res);
364                 exit(EXIT_FAILURE);
365             }
366             PQclear(res);
367         }
368
369         if (fileMode == FILEMODE_UPDATE || fileMode == FILEMODE_ADD)
370         {
371                         // Insert into placex
372                         paramValues[0] = (const char *)place_id;
373                         paramValues[1] = (const char *)feature.type;
374                         paramValues[2] = (const char *)feature.id;
375                         paramValues[3] = (const char *)feature.key;
376                         paramValues[4] = (const char *)feature.value;
377
378                         featureNameString[0] = 0;
379                         if (featureNameLines)
380                         {
381                                 namePos = 0;
382                                 lineTypeLen = 0;
383                                 lineValueLen = 0;
384                                 for(i = 0; i < featureNameLines; i++)
385                                 {
386                                         lineTypeLen = strlen(BAD_CAST featureName[i].type);
387                                         lineValueLen = strlen(BAD_CAST featureName[i].value);
388                                         if (namePos+lineTypeLen+lineValueLen+7 > MAX_FEATURENAMESTRING)
389                             {
390                                 fprintf(stderr, "feature name too long: %s", (const char *)featureName[i].value);
391                                                 break;
392                             }
393                                         if (namePos) strcpy(featureNameString+(namePos++), ",");
394                                         strcpy(featureNameString+(namePos++), "\"");
395                                         strcpy(featureNameString+namePos, BAD_CAST featureName[i].type);
396                                         namePos += lineTypeLen;
397                                         strcpy(featureNameString+namePos, "\"=>\"");
398                                         namePos += 4;
399                                         strcpy(featureNameString+namePos, BAD_CAST featureName[i].value);
400                                         namePos += lineValueLen;
401                                         strcpy(featureNameString+(namePos++), "\"");
402                                 }
403                         }
404                         paramValues[5] = (const char *)featureNameString;
405
406                         featureExtraTagString[0] = 0;
407                         if (featureExtraTagLines)
408                         {
409                                 namePos = 0;
410                                 lineTypeLen = 0;
411                                 lineValueLen = 0;
412                                 for(i = 0; i < featureExtraTagLines; i++)
413                                 {
414                                         lineTypeLen = strlen(BAD_CAST featureExtraTag[i].type);
415                                         lineValueLen = strlen(BAD_CAST featureExtraTag[i].value);
416                                         if (namePos+lineTypeLen+lineValueLen+7 > MAX_FEATUREEXTRATAGSTRING)
417                             {
418                                 fprintf(stderr, "feature extra tag too long: %s", (const char *)featureExtraTag[i].value);
419                                                 break;
420                             }
421                                         if (namePos) strcpy(featureExtraTagString+(namePos++),",");
422                                         strcpy(featureExtraTagString+(namePos++), "\"");
423                                         strcpy(featureExtraTagString+namePos, BAD_CAST featureExtraTag[i].type);
424                                         namePos += lineTypeLen;
425                                         strcpy(featureExtraTagString+namePos, "\"=>\"");
426                                         namePos += 4;
427                                         strcpy(featureExtraTagString+namePos, BAD_CAST featureExtraTag[i].value);
428                                         namePos += lineValueLen;
429                                         strcpy(featureExtraTagString+(namePos++), "\"");
430                                 }
431                         }
432                         paramValues[6] = (const char *)featureExtraTagString;
433
434                         paramValues[7] = (const char *)feature.adminLevel;
435                         paramValues[8] = (const char *)feature.houseNumber;
436                         paramValues[9] = (const char *)feature.rankAddress;
437                         paramValues[10] = (const char *)feature.rankSearch;
438                         paramValues[11] = (const char *)feature.geometry;
439                         res = PQexecPrepared(conn, "placex_insert", 12, paramValues, NULL, NULL, 0);
440                         if (PQresultStatus(res) != PGRES_COMMAND_OK)
441                         {
442                                 fprintf(stderr, "index_placex: INSERT failed: %s", PQerrorMessage(conn));
443                                 PQclear(res);
444                                 exit(EXIT_FAILURE);
445                         }
446                         PQclear(res);
447
448                         for(i = 0; i < featureAddressLines; i++)
449                         {
450                                 // insert into place_address
451                                 paramValues[0] = (const char *)place_id;
452                                 paramValues[1] = (const char *)featureAddress[i].distance;
453                                 paramValues[2] = (const char *)featureAddress[i].type;
454                                 paramValues[3] = (const char *)featureAddress[i].id;
455                                 paramValues[4] = (const char *)featureAddress[i].key;
456                                 paramValues[5] = (const char *)featureAddress[i].value;
457                                 paramValues[6] = (const char *)featureAddress[i].isAddress;
458                                 res = PQexecPrepared(conn, "place_addressline_insert", 7, paramValues, NULL, NULL, 0);
459                                 if (PQresultStatus(res) != PGRES_COMMAND_OK)
460                                 {
461                                         fprintf(stderr, "place_addressline_insert: INSERT failed: %s", PQerrorMessage(conn));
462                                         PQclear(res);
463                                         exit(EXIT_FAILURE);
464                                 }
465                                 PQclear(res);
466
467                                 xmlFree(featureAddress[i].type);
468                                 xmlFree(featureAddress[i].id);
469                                 xmlFree(featureAddress[i].key);
470                                 xmlFree(featureAddress[i].value);
471                                 xmlFree(featureAddress[i].distance);
472                         }
473
474                         if (featureNameLines)
475                         {
476                                 paramValues[0] = (const char *)place_id;
477                                 res = PQexecPrepared(conn, "search_name_insert", 1, paramValues, NULL, NULL, 0);
478                                 if (PQresultStatus(res) != PGRES_COMMAND_OK)
479                                 {
480                                         fprintf(stderr, "search_name_insert: INSERT failed: %s", PQerrorMessage(conn));
481                                         PQclear(res);
482                                         exit(EXIT_FAILURE);
483                                 }
484                                 PQclear(res);
485                         }
486
487                         partionQueryName = xmlHashLookup2(partionTableTagsHash, feature.key, feature.value);
488                         if (partionQueryName)
489                         {
490                                 // insert into partition table
491                                 paramValues[0] = (const char *)place_id;
492                                 paramValues[1] = (const char *)feature.geometry;
493                                 res = PQexecPrepared(conn, partionQueryName, 2, paramValues, NULL, NULL, 0);
494                                 if (PQresultStatus(res) != PGRES_COMMAND_OK)
495                                 {
496                                         fprintf(stderr, "%s: INSERT failed: %s", partionQueryName, PQerrorMessage(conn));
497                                         PQclear(res);
498                                         exit(EXIT_FAILURE);
499                                 }
500                                 PQclear(res);
501
502                         }
503
504         }
505         else
506         {
507                         for(i = 0; i < featureAddressLines; i++)
508                         {
509                                 xmlFree(featureAddress[i].type);
510                                 xmlFree(featureAddress[i].id);
511                                 xmlFree(featureAddress[i].key);
512                                 xmlFree(featureAddress[i].value);
513                                 xmlFree(featureAddress[i].distance);
514                         }
515         }
516
517                 xmlFree(feature.type);
518                 xmlFree(feature.id);
519                 xmlFree(feature.key);
520                 xmlFree(feature.value);
521                 xmlFree(feature.rankAddress);
522                 xmlFree(feature.rankSearch);
523 //              if (feature.name) xmlFree(feature.name);
524                 if (feature.countryCode) xmlFree(feature.countryCode);
525                 if (feature.adminLevel) xmlFree(feature.adminLevel);
526                 if (feature.houseNumber) xmlFree(feature.houseNumber);
527                 if (feature.geometry) xmlFree(feature.geometry);
528
529                 PQclear(resPlaceID);
530         }
531 }
532
533 static void processNode(xmlTextReaderPtr reader)
534 {
535         xmlChar *name;
536     name = xmlTextReaderName(reader);
537     if (name == NULL)
538     {
539         name = xmlStrdup(BAD_CAST "--");
540     }
541
542     switch(xmlTextReaderNodeType(reader))
543     {
544         case XML_READER_TYPE_ELEMENT:
545             StartElement(reader, name);
546             if (xmlTextReaderIsEmptyElement(reader))
547                 EndElement(reader, name); /* No end_element for self closing tags! */
548             break;
549         case XML_READER_TYPE_END_ELEMENT:
550             EndElement(reader, name);
551             break;
552         case XML_READER_TYPE_TEXT:
553         case XML_READER_TYPE_CDATA:
554         case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
555             /* Ignore */
556             break;
557         default:
558             fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));
559             break;
560     }
561
562     xmlFree(name);
563 }
564
565 int nominatim_import(const char *conninfo, const char *partionTagsFilename, const char *filename)
566 {
567     xmlTextReaderPtr    reader;
568     int                                 ret = 0;
569         PGresult *                      res;
570         FILE *                          partionTagsFile;
571         char *                          partionQueryName;
572     char                                partionQuerySQL[1024];
573
574         conn = PQconnectdb(conninfo);
575     if (PQstatus(conn) != CONNECTION_OK)
576     {
577         fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn));
578         exit(EXIT_FAILURE);
579     }
580
581         partionTableTagsHash = xmlHashCreate(200);
582
583         partionTagsFile = fopen(partionTagsFilename, "rt");
584         if (!partionTagsFile)
585     {
586         fprintf(stderr, "Unable to read partition tags file: %s\n", partionTagsFilename);
587         exit(EXIT_FAILURE);
588     }
589
590         char buffer[1024], osmkey[256], osmvalue[256];
591         int fields;
592         while(fgets(buffer, sizeof(buffer), partionTagsFile) != NULL)
593         {
594                 fields = sscanf( buffer, "%23s %63s", osmkey, osmvalue );
595
596                 if( fields <= 0 ) continue;
597
598             if( fields != 2  )
599             {
600               fprintf( stderr, "Error partition file\n");
601               exit_nicely();
602             }
603             partionQueryName = malloc(strlen("partition_insert_")+strlen(osmkey)+strlen(osmvalue)+2);
604                 strcpy(partionQueryName, "partition_insert_");
605                 strcat(partionQueryName, osmkey);
606                 strcat(partionQueryName, "_");
607                 strcat(partionQueryName, osmvalue);
608
609                 strcpy(partionQuerySQL, "insert into place_classtype_");
610                 strcat(partionQuerySQL, osmkey);
611                 strcat(partionQuerySQL, "_");
612                 strcat(partionQuerySQL, osmvalue);
613                 strcat(partionQuerySQL, " (place_id, centroid) values ($1, ST_Centroid(st_setsrid($2, 4326)))");
614
615             res = PQprepare(conn, partionQueryName, partionQuerySQL, 2, NULL);
616             if (PQresultStatus(res) != PGRES_COMMAND_OK)
617                 {
618                 fprintf(stderr, "Failed to prepare %s: %s\n", partionQueryName, PQerrorMessage(conn));
619                 exit(EXIT_FAILURE);
620                 }
621
622                 xmlHashAddEntry2(partionTableTagsHash, BAD_CAST osmkey, BAD_CAST osmvalue, BAD_CAST partionQueryName);
623         }
624
625     res = PQprepare(conn, "get_new_place_id",
626                 "select nextval('seq_place')",
627         0, NULL);
628     if (PQresultStatus(res) != PGRES_COMMAND_OK)
629         {
630         fprintf(stderr, "Failed to prepare get_new_place_id: %s\n", PQerrorMessage(conn));
631         exit(EXIT_FAILURE);
632         }
633
634     res = PQprepare(conn, "get_place_id",
635                 "select place_id from placex where osm_type = $1 and osm_id = $2 and class = $3 and type = $4",
636         4, NULL);
637     if (PQresultStatus(res) != PGRES_COMMAND_OK)
638         {
639         fprintf(stderr, "Failed to prepare get_place_id: %s\n", PQerrorMessage(conn));
640         exit(EXIT_FAILURE);
641         }
642
643     res = PQprepare(conn, "placex_insert",
644                 "insert into placex (place_id,osm_type,osm_id,class,type,name,extratags,admin_level,housenumber,rank_address,rank_search,geometry) "
645                 "values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, st_setsrid($12, 4326))",
646         12, NULL);
647     if (PQresultStatus(res) != PGRES_COMMAND_OK)
648         {
649         fprintf(stderr, "Failed to prepare placex_insert: %s\n", PQerrorMessage(conn));
650         exit(EXIT_FAILURE);
651         }
652
653     res = PQprepare(conn, "search_name_insert",
654                 "insert into search_name (place_id, search_rank, address_rank, country_code, name_vector, nameaddress_vector, centroid) "
655                 "select place_id, rank_address, rank_search, country_code, make_keywords(name), "
656                 "(select uniq(sort(array_agg(name_vector))) from place_addressline join search_name on "
657                 "(address_place_id = search_name.place_id) where place_addressline.place_id = $1 ), st_centroid(geometry) from placex "
658                 "where place_id = $1",
659         1, NULL);
660     if (PQresultStatus(res) != PGRES_COMMAND_OK)
661         {
662         fprintf(stderr, "Failed to prepare search_name_insert: %s\n", PQerrorMessage(conn));
663         exit(EXIT_FAILURE);
664         }
665
666     res = PQprepare(conn, "place_addressline_insert",
667                 "insert into place_addressline (place_id, address_place_id, fromarea, isaddress, distance, cached_rank_address) "
668                 "select $1, place_id, false, $7, $2, rank_address from placex where osm_type = $3 and osm_id = $4 and class = $5 and type = $6",
669         7, NULL);
670     if (PQresultStatus(res) != PGRES_COMMAND_OK)
671         {
672         fprintf(stderr, "Failed to prepare place_addressline_insert: %s\n", PQerrorMessage(conn));
673         exit(EXIT_FAILURE);
674         }
675
676     res = PQprepare(conn, "placex_delete",
677                 "delete from placex where place_id = $1",
678         1, NULL);
679     if (PQresultStatus(res) != PGRES_COMMAND_OK)
680         {
681         fprintf(stderr, "Failed to prepare placex_delete: %s\n", PQerrorMessage(conn));
682         exit(EXIT_FAILURE);
683         }
684
685     res = PQprepare(conn, "search_name_delete",
686                 "delete from search_name where place_id = $1",
687         1, NULL);
688     if (PQresultStatus(res) != PGRES_COMMAND_OK)
689         {
690         fprintf(stderr, "Failed to prepare search_name_delete: %s\n", PQerrorMessage(conn));
691         exit(EXIT_FAILURE);
692         }
693
694     res = PQprepare(conn, "place_addressline_delete",
695                 "delete from place_addressline where place_id = $1",
696         1, NULL);
697     if (PQresultStatus(res) != PGRES_COMMAND_OK)
698         {
699         fprintf(stderr, "Failed to prepare place_addressline_delete: %s\n", PQerrorMessage(conn));
700         exit(EXIT_FAILURE);
701         }
702
703     featureCount = 0;
704
705     reader = inputUTF8(filename);
706
707     if (reader == NULL)
708     {
709         fprintf(stderr, "Unable to open %s\n", filename);
710         return 1;
711     }
712
713     ret = xmlTextReaderRead(reader);
714     while (ret == 1)
715     {
716         processNode(reader);
717         ret = xmlTextReaderRead(reader);
718     }
719         if (ret != 0) {
720                 fprintf(stderr, "%s : failed to parse\n", filename);
721                 return ret;
722         }
723
724         xmlFreeTextReader(reader);
725         xmlHashFree(partionTableTagsHash, NULL);
726
727     return 0;
728 }