8 #include <libxml/xmlstring.h>
 
   9 #include <libxml/xmlreader.h>
 
  10 #include <libxml/hash.h>
 
  12 #include "nominatim.h"
 
  16 typedef enum { FILETYPE_NONE, FILETYPE_STRUCTUREDV0P1 } filetypes_t;
 
  17 typedef enum { FILEMODE_NONE, FILEMODE_ADD, FILEMODE_UPDATE, FILEMODE_DELETE } filemodes_t;
 
  19 #define MAX_FEATUREADDRESS 5000
 
  20 #define MAX_FEATURENAMES 10000
 
  21 #define MAX_FEATUREEXTRATAGS 10000
 
  22 #define MAX_FEATURENAMESTRING 1000000
 
  23 #define MAX_FEATUREEXTRATAGSTRING 500000
 
  25 struct feature_address
 
  50     xmlChar *   rankAddress;
 
  52     xmlChar *   countryCode;
 
  53     xmlChar *   parentPlaceID;
 
  57     xmlChar *   houseNumber;
 
  61 int                                     fileType = FILETYPE_NONE;
 
  62 int                                     fileMode = FILEMODE_ADD;
 
  64 struct feature_address  featureAddress[MAX_FEATUREADDRESS];
 
  65 struct feature_tag              featureName[MAX_FEATURENAMES];
 
  66 struct feature_tag              featureExtraTag[MAX_FEATUREEXTRATAGS];
 
  67 struct feature                  feature;
 
  68 int                                     featureAddressLines = 0;
 
  69 int                                     featureNameLines = 0;
 
  70 int                                     featureExtraTagLines = 0;
 
  72 xmlHashTablePtr                 partionTableTagsHash;
 
  73 xmlHashTablePtr                 partionTableTagsHashDelete;
 
  74 char                                    featureNameString[MAX_FEATURENAMESTRING];
 
  75 char                                    featureExtraTagString[MAX_FEATUREEXTRATAGSTRING];
 
  79 void StartElement(xmlTextReaderPtr reader, const xmlChar *name)
 
  85     if (fileType == FILETYPE_NONE)
 
  87         // Potential to handle other file types in the future / versions
 
  88         if (xmlStrEqual(name, BAD_CAST "osmStructured"))
 
  90             value = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "version");
 
  91             version = strtof(value, NULL);
 
  94             if (version == (float)0.1)
 
  96                 fileType = FILETYPE_STRUCTUREDV0P1;
 
  97                 fileMode = FILEMODE_ADD;
 
 101                 fprintf( stderr, "Unknown osmStructured version %f (%s)\n", version, value );
 
 107             fprintf( stderr, "Unknown XML document type: %s\n", name );
 
 113     if (xmlStrEqual(name, BAD_CAST "add"))
 
 115         fileMode = FILEMODE_ADD;
 
 118     if (xmlStrEqual(name, BAD_CAST "update"))
 
 120         fileMode = FILEMODE_UPDATE;
 
 123     if (xmlStrEqual(name, BAD_CAST "delete"))
 
 125         fileMode = FILEMODE_DELETE;
 
 128     if (fileMode == FILEMODE_NONE)
 
 130         fprintf( stderr, "Unknown import mode in: %s\n", name );
 
 134     if (xmlStrEqual(name, BAD_CAST "feature"))
 
 136         feature.placeID = xmlTextReaderGetAttribute(reader, BAD_CAST "place_id");
 
 137         feature.type = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
 
 138         feature.id = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
 
 139         feature.key = xmlTextReaderGetAttribute(reader, BAD_CAST "key");
 
 140         feature.value = xmlTextReaderGetAttribute(reader, BAD_CAST "value");
 
 141         feature.rankAddress = xmlTextReaderGetAttribute(reader, BAD_CAST "rank");
 
 142         feature.rankSearch = xmlTextReaderGetAttribute(reader, BAD_CAST "importance");
 
 144         feature.parentPlaceID = xmlTextReaderGetAttribute(reader, BAD_CAST "parent_place_id");
 
 146         if (strlen(feature.parentPlaceID) == 0)
 
 148                 xmlFree(feature.parentPlaceID);
 
 149                 feature.parentPlaceID = NULL;
 
 152         feature.parentType = xmlTextReaderGetAttribute(reader, BAD_CAST "parent_type");
 
 153         feature.parentID = xmlTextReaderGetAttribute(reader, BAD_CAST "parent_id");
 
 155         feature.countryCode = NULL;
 
 156         feature.adminLevel = NULL;
 
 157         feature.houseNumber = NULL;
 
 158         feature.geometry = NULL;
 
 159         featureAddressLines = 0;
 
 160         featureNameLines = 0;
 
 161         featureExtraTagLines = 0;
 
 165     if (xmlStrEqual(name, BAD_CAST "names")) return;
 
 166     if (xmlStrEqual(name, BAD_CAST "name"))
 
 168         if (featureNameLines < MAX_FEATURENAMES)
 
 170                 featureName[featureNameLines].type = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
 
 171             featureName[featureNameLines].value = xmlTextReaderReadString(reader);
 
 176             fprintf( stderr, "Too many name elements (%s%s)\n", feature.type, feature.id);
 
 181     if (xmlStrEqual(name, BAD_CAST "tags")) return;
 
 182     if (xmlStrEqual(name, BAD_CAST "tag"))
 
 184         if (featureExtraTagLines < MAX_FEATUREEXTRATAGS)
 
 186                 featureExtraTag[featureExtraTagLines].type = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
 
 187             featureExtraTag[featureExtraTagLines].value = xmlTextReaderReadString(reader);
 
 188                 featureExtraTagLines++;
 
 192             fprintf( stderr, "Too many extra tag elements (%s%s)\n", feature.type, feature.id);
 
 197     if (xmlStrEqual(name, BAD_CAST "osmGeometry"))
 
 199         feature.geometry = xmlTextReaderReadString(reader);
 
 202     if (xmlStrEqual(name, BAD_CAST "adminLevel"))
 
 204         feature.adminLevel = xmlTextReaderReadString(reader);
 
 207     if (xmlStrEqual(name, BAD_CAST "countryCode"))
 
 209         feature.countryCode = xmlTextReaderReadString(reader);
 
 212     if (xmlStrEqual(name, BAD_CAST "houseNumber"))
 
 214         feature.houseNumber = xmlTextReaderReadString(reader);
 
 217     if (xmlStrEqual(name, BAD_CAST "address"))
 
 219         featureAddressLines = 0;
 
 223     if (xmlStrEqual(name, BAD_CAST "continent"))
 
 227     else if (xmlStrEqual(name, BAD_CAST "sea"))
 
 231     else if (xmlStrEqual(name, BAD_CAST "country"))
 
 235     else if (xmlStrEqual(name, BAD_CAST "state"))
 
 239     else if (xmlStrEqual(name, BAD_CAST "county"))
 
 243     else if (xmlStrEqual(name, BAD_CAST "city"))
 
 247     else if (xmlStrEqual(name, BAD_CAST "town"))
 
 251     else if (xmlStrEqual(name, BAD_CAST "village"))
 
 255     else if (xmlStrEqual(name, BAD_CAST "unknown"))
 
 259     else if (xmlStrEqual(name, BAD_CAST "suburb"))
 
 263     else if (xmlStrEqual(name, BAD_CAST "postcode"))
 
 267     else if (xmlStrEqual(name, BAD_CAST "neighborhood"))
 
 271     else if (xmlStrEqual(name, BAD_CAST "street"))
 
 275     else if (xmlStrEqual(name, BAD_CAST "access"))
 
 279     else if (xmlStrEqual(name, BAD_CAST "building"))
 
 283     else if (xmlStrEqual(name, BAD_CAST "other"))
 
 289         if (featureAddressLines < MAX_FEATUREADDRESS)
 
 291                 value = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "rank");
 
 294                 fprintf( stderr, "Address element missing rank\n");
 
 297             featureAddress[featureAddressLines].rankAddress =  atoi(value);
 
 300                 value = (char*)xmlTextReaderGetAttribute(reader, BAD_CAST "isaddress");
 
 303                     fprintf( stderr, "Address element missing rank\n");
 
 306                 if (*value == 't') strcpy(featureAddress[featureAddressLines].isAddress, "t");
 
 307             else strcpy(featureAddress[featureAddressLines].isAddress, "f");
 
 310                 featureAddress[featureAddressLines].type = xmlTextReaderGetAttribute(reader, BAD_CAST "type");
 
 311             featureAddress[featureAddressLines].id = xmlTextReaderGetAttribute(reader, BAD_CAST "id");
 
 312                 featureAddress[featureAddressLines].key = xmlTextReaderGetAttribute(reader, BAD_CAST "key");
 
 313                 featureAddress[featureAddressLines].value = xmlTextReaderGetAttribute(reader, BAD_CAST "value");
 
 314             featureAddress[featureAddressLines].distance = xmlTextReaderGetAttribute(reader, BAD_CAST "distance");
 
 316             featureAddressLines++;
 
 320             fprintf( stderr, "Too many address elements (%s%s)\n", feature.type, feature.id);
 
 326     fprintf(stderr, "%s: Unknown element name: %s\n", __FUNCTION__, name);
 
 329 void EndElement(xmlTextReaderPtr reader, const xmlChar *name)
 
 332     const char *        paramValues[14];
 
 334     char *                      partionQueryName;
 
 335     int i, namePos, lineTypeLen, lineValueLen;
 
 337     if (xmlStrEqual(name, BAD_CAST "feature"))
 
 340         if (featureCount % 1000 == 0) printf("feature %i(k)\n", featureCount/1000);
 
 342         if (fileMode == FILEMODE_ADD)
 
 344             resPlaceID = PQexecPrepared(conn, "get_new_place_id", 0, NULL, NULL, NULL, 0);
 
 345             if (PQresultStatus(resPlaceID) != PGRES_TUPLES_OK)
 
 347                 fprintf(stderr, "get_place_id: INSERT failed: %s", PQerrorMessage(conn));
 
 354             paramValues[0] = (const char *)feature.type;
 
 355             paramValues[1] = (const char *)feature.id;
 
 356             paramValues[2] = (const char *)feature.key;
 
 357             paramValues[3] = (const char *)feature.value;
 
 358             resPlaceID = PQexecPrepared(conn, "get_new_place_id", 4, paramValues, NULL, NULL, 0);
 
 359             if (PQresultStatus(resPlaceID) != PGRES_TUPLES_OK)
 
 361                 fprintf(stderr, "index_placex: INSERT failed: %s", PQerrorMessage(conn));
 
 367         place_id = (char *)feature.placeID;
 
 369         if (fileMode == FILEMODE_UPDATE || fileMode == FILEMODE_DELETE || fileMode == FILEMODE_ADD)
 
 371             paramValues[0] = (const char *)place_id;
 
 372             if (verbose) fprintf(stderr, "placex_delete: %s\n", paramValues[0]);
 
 373             res = PQexecPrepared(conn, "placex_delete", 1, paramValues, NULL, NULL, 0);
 
 374             if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 376                 fprintf(stderr, "placex_delete: DELETE failed: %s", PQerrorMessage(conn));
 
 382             if (verbose) fprintf(stderr, "search_name_delete: %s\n", paramValues[0]);
 
 383             res = PQexecPrepared(conn, "search_name_delete", 1, paramValues, NULL, NULL, 0);
 
 384             if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 386                 fprintf(stderr, "search_name_delete: DELETE failed: %s", PQerrorMessage(conn));
 
 392             if (verbose) fprintf(stderr, "place_addressline_delete: %s\n", paramValues[0]);
 
 393             res = PQexecPrepared(conn, "place_addressline_delete", 1, paramValues, NULL, NULL, 0);
 
 394             if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 396                 fprintf(stderr, "place_addressline_delete: DELETE failed: %s", PQerrorMessage(conn));
 
 402             partionQueryName = xmlHashLookup2(partionTableTagsHashDelete, feature.key, feature.value);
 
 403             if (partionQueryName)
 
 405                 res = PQexecPrepared(conn, partionQueryName, 1, paramValues, NULL, NULL, 0);
 
 406                 if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 408                     fprintf(stderr, "%s: DELETE failed: %s", partionQueryName, PQerrorMessage(conn));
 
 416         if (fileMode == FILEMODE_UPDATE || fileMode == FILEMODE_ADD)
 
 418             // Insert into placex
 
 419             paramValues[0] = (const char *)place_id;
 
 420             paramValues[1] = (const char *)feature.type;
 
 421             paramValues[2] = (const char *)feature.id;
 
 422             paramValues[3] = (const char *)feature.key;
 
 423             paramValues[4] = (const char *)feature.value;
 
 425             featureNameString[0] = 0;
 
 426             if (featureNameLines)
 
 431                 for (i = 0; i < featureNameLines; i++)
 
 433                     lineTypeLen = (int)strlen((char *) featureName[i].type);
 
 434                     lineValueLen = (int)strlen((char *) featureName[i].value);
 
 435                     if (namePos+lineTypeLen+lineValueLen+7 > MAX_FEATURENAMESTRING)
 
 437                         fprintf(stderr, "feature name too long: %s", (const char *)featureName[i].value);
 
 440                     if (namePos) strcpy(featureNameString+(namePos++), ",");
 
 441                     strcpy(featureNameString+(namePos++), "\"");
 
 442                     strcpy(featureNameString+namePos, (char*) featureName[i].type);
 
 443                     namePos += lineTypeLen;
 
 444                     strcpy(featureNameString+namePos, "\"=>\"");
 
 446                     strcpy(featureNameString+namePos, (char *) featureName[i].value);
 
 447                     namePos += lineValueLen;
 
 448                     strcpy(featureNameString+(namePos++), "\"");
 
 450                     xmlFree(featureName[i].type);
 
 451                     xmlFree(featureName[i].value);
 
 454             paramValues[5] = (const char *)featureNameString;
 
 456             paramValues[6] = (const char *)feature.countryCode;
 
 458             featureExtraTagString[0] = 0;
 
 459             if (featureExtraTagLines)
 
 464                 for (i = 0; i < featureExtraTagLines; i++)
 
 466                     lineTypeLen = strlen((char *) featureExtraTag[i].type);
 
 467                     lineValueLen = strlen((char *) featureExtraTag[i].value);
 
 468                     if (namePos+lineTypeLen+lineValueLen+7 > MAX_FEATUREEXTRATAGSTRING)
 
 470                         fprintf(stderr, "feature extra tag too long: %s", (const char *)featureExtraTag[i].value);
 
 473                     if (namePos) strcpy(featureExtraTagString+(namePos++),",");
 
 474                     strcpy(featureExtraTagString+(namePos++), "\"");
 
 475                     strcpy(featureExtraTagString+namePos, (char *) featureExtraTag[i].type);
 
 476                     namePos += lineTypeLen;
 
 477                     strcpy(featureExtraTagString+namePos, "\"=>\"");
 
 479                     strcpy(featureExtraTagString+namePos, (char *) featureExtraTag[i].value);
 
 480                     namePos += lineValueLen;
 
 481                     strcpy(featureExtraTagString+(namePos++), "\"");
 
 483                     xmlFree(featureExtraTag[i].type);
 
 484                     xmlFree(featureExtraTag[i].value);
 
 487             paramValues[7] = (const char *)featureExtraTagString;
 
 489             if (xmlStrlen(feature.parentPlaceID) == 0)
 
 490                 paramValues[8] = "0";
 
 492                 paramValues[8] = (const char *)feature.parentPlaceID;
 
 494             paramValues[9] = (const char *)feature.adminLevel;
 
 495             paramValues[10] = (const char *)feature.houseNumber;
 
 496             paramValues[11] = (const char *)feature.rankAddress;
 
 497             paramValues[12] = (const char *)feature.rankSearch;
 
 498             paramValues[13] = (const char *)feature.geometry;
 
 499             if (strlen(paramValues[3]) && strlen(paramValues[13]))
 
 501                 if (verbose) fprintf(stderr, "placex_insert: %s\n", paramValues[0]);
 
 502                 res = PQexecPrepared(conn, "placex_insert", 14, paramValues, NULL, NULL, 0);
 
 503                 if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 505                     fprintf(stderr, "index_placex: INSERT failed: %s", PQerrorMessage(conn));
 
 506                     fprintf(stderr, "index_placex: INSERT failed: %s %s %s", paramValues[0], paramValues[1], paramValues[2]);
 
 513             for (i = 0; i < featureAddressLines; i++)
 
 515                 // insert into place_address
 
 516                 paramValues[0] = (const char *)place_id;
 
 517                 paramValues[1] = (const char *)featureAddress[i].distance;
 
 518                 if (paramValues[1] == NULL || strlen(paramValues[1]) == 0) paramValues[1] = "0";
 
 519                 paramValues[2] = (const char *)featureAddress[i].type;
 
 520                 paramValues[3] = (const char *)featureAddress[i].id;
 
 521                 paramValues[4] = (const char *)featureAddress[i].key;
 
 522                 paramValues[5] = (const char *)featureAddress[i].value;
 
 523                 paramValues[6] = (const char *)featureAddress[i].isAddress;
 
 524                 if (verbose) fprintf(stderr, "placex_insert: %s %s\n", paramValues[2], paramValues[3]);
 
 525                 res = PQexecPrepared(conn, "place_addressline_insert", 7, paramValues, NULL, NULL, 0);
 
 526                 if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 528                     fprintf(stderr, "place_addressline_insert: INSERT failed: %s", PQerrorMessage(conn));
 
 529                     fprintf(stderr, "(%s,%s,%s,%s,%s,%s,%s)",paramValues[0],paramValues[1],paramValues[2],paramValues[3],paramValues[4],paramValues[5],paramValues[6]);
 
 535                 xmlFree(featureAddress[i].type);
 
 536                 xmlFree(featureAddress[i].id);
 
 537                 xmlFree(featureAddress[i].key);
 
 538                 xmlFree(featureAddress[i].value);
 
 539                 xmlFree(featureAddress[i].distance);
 
 542             if (featureNameLines)
 
 544                 if (xmlStrlen(feature.parentPlaceID) > 0 && featureAddressLines == 0)
 
 546                     paramValues[0] = (const char *)place_id;
 
 547                     paramValues[1] = (const char *)feature.parentPlaceID;
 
 548                     if (verbose) fprintf(stderr, "search_name_from_parent_insert: INSERT %s %s\n", paramValues[0], paramValues[1]);
 
 549                     res = PQexecPrepared(conn, "search_name_from_parent_insert", 2, paramValues, NULL, NULL, 0);
 
 550                     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 552                         fprintf(stderr, "search_name_from_parent_insert: INSERT failed: %s", PQerrorMessage(conn));
 
 560                     paramValues[0] = (const char *)place_id;
 
 561                     if (verbose) fprintf(stderr, "search_name_insert: INSERT %s\n", paramValues[0]);
 
 562                     res = PQexecPrepared(conn, "search_name_insert", 1, paramValues, NULL, NULL, 0);
 
 563                     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 565                         fprintf(stderr, "search_name_insert: INSERT failed: %s", PQerrorMessage(conn));
 
 573             partionQueryName = xmlHashLookup2(partionTableTagsHash, feature.key, feature.value);
 
 574             if (partionQueryName)
 
 576                 // insert into partition table
 
 577                 paramValues[0] = (const char *)place_id;
 
 578                 paramValues[1] = (const char *)feature.geometry;
 
 579                 res = PQexecPrepared(conn, partionQueryName, 2, paramValues, NULL, NULL, 0);
 
 580                 if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 582                     fprintf(stderr, "%s: INSERT failed: %s", partionQueryName, PQerrorMessage(conn));
 
 592             for (i = 0; i < featureAddressLines; i++)
 
 594                 xmlFree(featureAddress[i].type);
 
 595                 xmlFree(featureAddress[i].id);
 
 596                 xmlFree(featureAddress[i].key);
 
 597                 xmlFree(featureAddress[i].value);
 
 598                 xmlFree(featureAddress[i].distance);
 
 602         xmlFree(feature.placeID);
 
 603         xmlFree(feature.type);
 
 605         xmlFree(feature.key);
 
 606         xmlFree(feature.value);
 
 607         xmlFree(feature.rankAddress);
 
 608         xmlFree(feature.rankSearch);
 
 609         if (feature.countryCode) xmlFree(feature.countryCode);
 
 610         if (feature.parentPlaceID) xmlFree(feature.parentPlaceID);
 
 611         if (feature.parentType) xmlFree(feature.parentType);
 
 612         if (feature.parentID) xmlFree(feature.parentID);
 
 613 //              if (feature.name) xmlFree(feature.name);
 
 614         if (feature.adminLevel) xmlFree(feature.adminLevel);
 
 615         if (feature.houseNumber) xmlFree(feature.houseNumber);
 
 616         if (feature.geometry) xmlFree(feature.geometry);
 
 618 //        PQclear(resPlaceID);
 
 622 static void processNode(xmlTextReaderPtr reader)
 
 625     name = xmlTextReaderName(reader);
 
 628         name = xmlStrdup(BAD_CAST "--");
 
 631     switch (xmlTextReaderNodeType(reader))
 
 633     case XML_READER_TYPE_ELEMENT:
 
 634         StartElement(reader, name);
 
 635         if (xmlTextReaderIsEmptyElement(reader))
 
 636             EndElement(reader, name); /* No end_element for self closing tags! */
 
 638     case XML_READER_TYPE_END_ELEMENT:
 
 639         EndElement(reader, name);
 
 641     case XML_READER_TYPE_TEXT:
 
 642     case XML_READER_TYPE_CDATA:
 
 643     case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
 
 647         fprintf(stderr, "Unknown node type %d\n", xmlTextReaderNodeType(reader));
 
 654 int nominatim_import(const char *conninfo, const char *partionTagsFilename, const char *filename)
 
 656     xmlTextReaderPtr    reader;
 
 659     FILE *                              partionTagsFile;
 
 660     char *                              partionQueryName;
 
 661     char                                partionQuerySQL[1024];
 
 663     conn = PQconnectdb(conninfo);
 
 664     if (PQstatus(conn) != CONNECTION_OK)
 
 666         fprintf(stderr, "Connection to database failed: %s\n", PQerrorMessage(conn));
 
 670     partionTableTagsHash = xmlHashCreate(200);
 
 671     partionTableTagsHashDelete = xmlHashCreate(200);
 
 673     partionTagsFile = fopen(partionTagsFilename, "rt");
 
 674     if (!partionTagsFile)
 
 676         fprintf(stderr, "Unable to read partition tags file: %s\n", partionTagsFilename);
 
 680     char buffer[1024], osmkey[256], osmvalue[256];
 
 682     while (fgets(buffer, sizeof(buffer), partionTagsFile) != NULL)
 
 684         fields = sscanf( buffer, "%23s %63s", osmkey, osmvalue );
 
 686         if ( fields <= 0 ) continue;
 
 690             fprintf( stderr, "Error partition file\n");
 
 693         partionQueryName = malloc(strlen("partition_insert_")+strlen(osmkey)+strlen(osmvalue)+2);
 
 694         strcpy(partionQueryName, "partition_insert_");
 
 695         strcat(partionQueryName, osmkey);
 
 696         strcat(partionQueryName, "_");
 
 697         strcat(partionQueryName, osmvalue);
 
 699         strcpy(partionQuerySQL, "insert into place_classtype_");
 
 700         strcat(partionQuerySQL, osmkey);
 
 701         strcat(partionQuerySQL, "_");
 
 702         strcat(partionQuerySQL, osmvalue);
 
 703         strcat(partionQuerySQL, " (place_id, centroid) values ($1, ST_Centroid(st_setsrid($2, 4326)))");
 
 705         res = PQprepare(conn, partionQueryName, partionQuerySQL, 2, NULL);
 
 706         if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 708             fprintf(stderr, "Failed to prepare %s: %s\n", partionQueryName, PQerrorMessage(conn));
 
 712         xmlHashAddEntry2(partionTableTagsHash, BAD_CAST osmkey, BAD_CAST osmvalue, BAD_CAST partionQueryName);
 
 714         partionQueryName = malloc(strlen("partition_delete_")+strlen(osmkey)+strlen(osmvalue)+2);
 
 715         strcpy(partionQueryName, "partition_delete_");
 
 716         strcat(partionQueryName, osmkey);
 
 717         strcat(partionQueryName, "_");
 
 718         strcat(partionQueryName, osmvalue);
 
 720         strcpy(partionQuerySQL, "delete from place_classtype_");
 
 721         strcat(partionQuerySQL, osmkey);
 
 722         strcat(partionQuerySQL, "_");
 
 723         strcat(partionQuerySQL, osmvalue);
 
 724         strcat(partionQuerySQL, " where place_id = $1::integer");
 
 726         res = PQprepare(conn, partionQueryName, partionQuerySQL, 1, NULL);
 
 727         if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 729             fprintf(stderr, "Failed to prepare %s: %s\n", partionQueryName, PQerrorMessage(conn));
 
 733         xmlHashAddEntry2(partionTableTagsHashDelete, BAD_CAST osmkey, BAD_CAST osmvalue, BAD_CAST partionQueryName);
 
 736     res = PQprepare(conn, "get_new_place_id",
 
 737                     "select nextval('seq_place')",
 
 739     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 741         fprintf(stderr, "Failed to prepare get_new_place_id: %s\n", PQerrorMessage(conn));
 
 745     res = PQprepare(conn, "get_place_id",
 
 746                     "select place_id from placex where osm_type = $1 and osm_id = $2 and class = $3 and type = $4",
 
 748     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 750         fprintf(stderr, "Failed to prepare get_place_id: %s\n", PQerrorMessage(conn));
 
 754     res = PQprepare(conn, "placex_insert",
 
 755                     "insert into placex (place_id,osm_type,osm_id,class,type,name,country_code,extratags,parent_place_id,admin_level,housenumber,rank_address,rank_search,geometry) "
 
 756                     "values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, st_setsrid($14, 4326))",
 
 758     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 760         fprintf(stderr, "Failed to prepare placex_insert: %s\n", PQerrorMessage(conn));
 
 764     res = PQprepare(conn, "search_name_insert",
 
 765                     "insert into search_name (place_id, search_rank, address_rank, country_code, name_vector, nameaddress_vector, centroid) "
 
 766                     "select place_id, rank_search, rank_address, country_code, make_keywords(name), "
 
 767                     "(select uniq(sort(array_agg(parent_search_name.name_vector))) from search_name as parent_search_name where place_id in "
 
 768                      "(select distinct address_place_id from place_addressline where place_addressline.place_id = $1 limit 1000)"
 
 769                     "), st_centroid(geometry) from placex "
 
 770                     "where place_id = $1",
 
 773     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 775         fprintf(stderr, "Failed to prepare search_name_insert: %s\n", PQerrorMessage(conn));
 
 779     res = PQprepare(conn, "search_name_from_parent_insert",
 
 780                     "insert into search_name (place_id, search_rank, address_rank, country_code, name_vector, nameaddress_vector, centroid) "
 
 781                     "select place_id, rank_search, rank_address, country_code, make_keywords(name), "
 
 782                     "(select uniq(sort(name_vector+nameaddress_vector)) from search_name as parent_search_name "
 
 783                     "where parent_search_name.place_id = $2 ), st_centroid(geometry) from placex "
 
 784                     "where place_id = $1",
 
 786     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 788         fprintf(stderr, "Failed to prepare search_name_insert: %s\n", PQerrorMessage(conn));
 
 792     res = PQprepare(conn, "place_addressline_insert",
 
 793                     "insert into place_addressline (place_id, address_place_id, fromarea, isaddress, distance, cached_rank_address) "
 
 794                     "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",
 
 796     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 798         fprintf(stderr, "Failed to prepare place_addressline_insert: %s\n", PQerrorMessage(conn));
 
 802     res = PQprepare(conn, "placex_delete",
 
 803                     "delete from placex where place_id = $1",
 
 805     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 807         fprintf(stderr, "Failed to prepare placex_delete: %s\n", PQerrorMessage(conn));
 
 811     res = PQprepare(conn, "search_name_delete",
 
 812                     "delete from search_name where place_id = $1",
 
 814     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 816         fprintf(stderr, "Failed to prepare search_name_delete: %s\n", PQerrorMessage(conn));
 
 820     res = PQprepare(conn, "place_addressline_delete",
 
 821                     "delete from place_addressline where place_id = $1",
 
 823     if (PQresultStatus(res) != PGRES_COMMAND_OK)
 
 825         fprintf(stderr, "Failed to prepare place_addressline_delete: %s\n", PQerrorMessage(conn));
 
 831     reader = inputUTF8(filename);
 
 835         fprintf(stderr, "Unable to open %s\n", filename);
 
 839     ret = xmlTextReaderRead(reader);
 
 843         ret = xmlTextReaderRead(reader);
 
 847         fprintf(stderr, "%s : failed to parse\n", filename);
 
 851     xmlFreeTextReader(reader);
 
 852     xmlHashFree(partionTableTagsHash, NULL);
 
 853     xmlHashFree(partionTableTagsHashDelete, NULL);