- res = PQexecPrepared(conn, "placex_details", 1, paramValues, paramLengths, paramFormats, 0);
- if (PQresultStatus(res) != PGRES_TUPLES_OK)
- {
- fprintf(stderr, "placex_details: SELECT failed: %s", PQerrorMessage(conn));
- PQclear(res);
- exit(EXIT_FAILURE);
- }
-
- resNames = PQexecPrepared(conn, "placex_names", 1, paramValues, paramLengths, paramFormats, 0);
- if (PQresultStatus(resNames) != PGRES_TUPLES_OK)
- {
- fprintf(stderr, "placex_names: SELECT failed: %s", PQerrorMessage(conn));
- PQclear(resNames);
- exit(EXIT_FAILURE);
- }
-
- resAddress = PQexecPrepared(conn, "placex_address", 1, paramValues, paramLengths, paramFormats, 0);
- if (PQresultStatus(resAddress) != PGRES_TUPLES_OK)
- {
- fprintf(stderr, "placex_address: SELECT failed: %s", PQerrorMessage(conn));
- PQclear(resAddress);
- exit(EXIT_FAILURE);
- }
-
- if (writer_mutex) pthread_mutex_lock( writer_mutex );
-
- xmlTextWriterStartElement(writer, BAD_CAST "feature");
- xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "place_id", "%li", place_id);
- xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(res, 0, 0));
- xmlTextWriterWriteAttribute(writer, BAD_CAST "id", BAD_CAST PQgetvalue(res, 0, 1));
- xmlTextWriterWriteAttribute(writer, BAD_CAST "key", BAD_CAST PQgetvalue(res, 0, 2));
- xmlTextWriterWriteAttribute(writer, BAD_CAST "value", BAD_CAST PQgetvalue(res, 0, 3));
- xmlTextWriterWriteAttribute(writer, BAD_CAST "rank", BAD_CAST PQgetvalue(res, 0, 9));
- xmlTextWriterWriteAttribute(writer, BAD_CAST "importance", BAD_CAST PQgetvalue(res, 0, 10));
-
- if (PQgetvalue(res, 0, 4) && strlen(PQgetvalue(res, 0, 4)))
- {
- xmlTextWriterStartElement(writer, BAD_CAST "names");
-
- for(i = 0; i < PQntuples(resNames); i++)
- {
- xmlTextWriterStartElement(writer, BAD_CAST "name");
- xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(resNames, i, 0));
- xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(resNames, i, 1));
- xmlTextWriterEndElement(writer);
- }
-
- xmlTextWriterEndElement(writer);
- }
-
- if (PQgetvalue(res, 0, 5) && strlen(PQgetvalue(res, 0, 5)))
- {
- xmlTextWriterStartElement(writer, BAD_CAST "houseNumber");
- xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(res, 0, 5));
- xmlTextWriterEndElement(writer);
- }
-
- if (PQgetvalue(res, 0, 8) && strlen(PQgetvalue(res, 0, 8)))
- {
- xmlTextWriterStartElement(writer, BAD_CAST "adminLevel");
- xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(res, 0, 8));
- xmlTextWriterEndElement(writer);
- }
-
- if (PQgetvalue(res, 0, 6) && strlen(PQgetvalue(res, 0, 6)))
- {
- xmlTextWriterStartElement(writer, BAD_CAST "countryCode");
- xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(res, 0, 6));
- xmlTextWriterEndElement(writer);
- }
-
- if (PQntuples(resAddress) > 0)
- {
- xmlTextWriterStartElement(writer, BAD_CAST "address");
- for(i = 0; i < PQntuples(resAddress); i++)
- {
- xmlTextWriterStartElement(writer, BAD_CAST getRankLabel(atoi(PQgetvalue(resAddress, i, 5))));
- xmlTextWriterWriteAttribute(writer, BAD_CAST "rank", BAD_CAST PQgetvalue(resAddress, i, 5));
- xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(resAddress, i, 0));
- xmlTextWriterWriteAttribute(writer, BAD_CAST "id", BAD_CAST PQgetvalue(resAddress, i, 1));
- xmlTextWriterWriteAttribute(writer, BAD_CAST "key", BAD_CAST PQgetvalue(resAddress, i, 2));
- xmlTextWriterWriteAttribute(writer, BAD_CAST "value", BAD_CAST PQgetvalue(resAddress, i, 3));
- xmlTextWriterWriteAttribute(writer, BAD_CAST "distance", BAD_CAST PQgetvalue(resAddress, i, 4));
- xmlTextWriterEndElement(writer);
- }
- xmlTextWriterEndElement(writer);
- }
-
- xmlTextWriterStartElement(writer, BAD_CAST "osmGeometry");
- xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(res, 0, 7));
- xmlTextWriterEndElement(writer);
-
- xmlTextWriterEndElement(writer); // </feature>
-
- if (writer_mutex) pthread_mutex_unlock( writer_mutex );
-
- PQclear(res);
- PQclear(resNames);
- PQclear(resAddress);
+ querySet->res = PQexecPrepared(conn, "placex_details", 1, paramValues, paramLengths, paramFormats, 0);
+ if (PQresultStatus(querySet->res) != PGRES_TUPLES_OK)
+ {
+ fprintf(stderr, "placex_details: SELECT failed: %s", PQerrorMessage(conn));
+ PQclear(querySet->res);
+ exit(EXIT_FAILURE);
+ }
+
+ querySet->resNames = PQexecPrepared(conn, "placex_names", 1, paramValues, paramLengths, paramFormats, 0);
+ if (PQresultStatus(querySet->resNames) != PGRES_TUPLES_OK)
+ {
+ fprintf(stderr, "placex_names: SELECT failed: %s", PQerrorMessage(conn));
+ PQclear(querySet->resNames);
+ exit(EXIT_FAILURE);
+ }
+
+ querySet->resAddress = PQexecPrepared(conn, "placex_address", 1, paramValues, paramLengths, paramFormats, 0);
+ if (PQresultStatus(querySet->resAddress) != PGRES_TUPLES_OK)
+ {
+ fprintf(stderr, "placex_address: SELECT failed: %s", PQerrorMessage(conn));
+ PQclear(querySet->resAddress);
+ exit(EXIT_FAILURE);
+ }
+
+ querySet->resExtraTags = PQexecPrepared(conn, "placex_extratags", 1, paramValues, paramLengths, paramFormats, 0);
+ if (PQresultStatus(querySet->resExtraTags) != PGRES_TUPLES_OK)
+ {
+ fprintf(stderr, "placex_extratags: SELECT failed: %s", PQerrorMessage(conn));
+ PQclear(querySet->resExtraTags);
+ exit(EXIT_FAILURE);
+ }
+}
+
+void nominatim_exportFreeQueries(struct export_data * querySet)
+{
+ PQclear(querySet->res);
+ PQclear(querySet->resNames);
+ PQclear(querySet->resAddress);
+ PQclear(querySet->resExtraTags);
+}
+
+/*
+ * Requirements: the prepared queries must exist
+ */
+void nominatim_exportPlace(uint64_t place_id, PGconn * conn,
+ xmlTextWriterPtr writer, pthread_mutex_t * writer_mutex, struct export_data * prevQuerySet)
+{
+ struct export_data querySet;
+
+ int i;
+
+ nominatim_exportPlaceQueries(place_id, conn, &querySet);
+
+ // Add, modify or delete?
+ if (prevQuerySet)
+ {
+ if ((PQgetvalue(prevQuerySet->res, 0, 14) && strcmp(PQgetvalue(prevQuerySet->res, 0, 14), "100") == 0) || PQntuples(querySet.res) == 0)
+ {
+ // Delete
+ if (writer_mutex) pthread_mutex_lock( writer_mutex );
+ nominatim_exportStartMode(writer, 3);
+ xmlTextWriterStartElement(writer, BAD_CAST "feature");
+ xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "place_id", "%li", place_id);
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(prevQuerySet->res, 0, 0));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "id", BAD_CAST PQgetvalue(prevQuerySet->res, 0, 1));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "key", BAD_CAST PQgetvalue(prevQuerySet->res, 0, 2));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "value", BAD_CAST PQgetvalue(prevQuerySet->res, 0, 3));
+ xmlTextWriterEndElement(writer);
+ if (writer_mutex) pthread_mutex_unlock( writer_mutex );
+ nominatim_exportFreeQueries(&querySet);
+ return;
+ }
+ if (PQgetvalue(prevQuerySet->res, 0, 14) && strcmp(PQgetvalue(prevQuerySet->res, 0, 14), "1") == 0)
+ {
+ // Add
+ if (writer_mutex) pthread_mutex_lock( writer_mutex );
+ nominatim_exportStartMode(writer, 1);
+ }
+ else
+ {
+ // Update, but only if something has changed
+
+ // TODO: detect changes
+
+ if (writer_mutex) pthread_mutex_lock( writer_mutex );
+ nominatim_exportStartMode(writer, 2);
+ }
+ }
+ else
+ {
+ // Add
+ if (writer_mutex) pthread_mutex_lock( writer_mutex );
+ nominatim_exportStartMode(writer, 1);
+ }
+
+ xmlTextWriterStartElement(writer, BAD_CAST "feature");
+ xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "place_id", "%li", place_id);
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(querySet.res, 0, 0));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "id", BAD_CAST PQgetvalue(querySet.res, 0, 1));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "key", BAD_CAST PQgetvalue(querySet.res, 0, 2));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "value", BAD_CAST PQgetvalue(querySet.res, 0, 3));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "rank", BAD_CAST PQgetvalue(querySet.res, 0, 9));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "importance", BAD_CAST PQgetvalue(querySet.res, 0, 10));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "parent_place_id", BAD_CAST PQgetvalue(querySet.res, 0, 11));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "parent_type", BAD_CAST PQgetvalue(querySet.res, 0, 12));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "parent_id", BAD_CAST PQgetvalue(querySet.res, 0, 13));
+
+ if (PQntuples(querySet.resNames))
+ {
+ xmlTextWriterStartElement(writer, BAD_CAST "names");
+
+ for (i = 0; i < PQntuples(querySet.resNames); i++)
+ {
+ xmlTextWriterStartElement(writer, BAD_CAST "name");
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(querySet.resNames, i, 0));
+ xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(querySet.resNames, i, 1));
+ xmlTextWriterEndElement(writer);
+ }
+
+ xmlTextWriterEndElement(writer);
+ }
+
+ if (PQgetvalue(querySet.res, 0, 5) && strlen(PQgetvalue(querySet.res, 0, 5)))
+ {
+ xmlTextWriterStartElement(writer, BAD_CAST "houseNumber");
+ xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(querySet.res, 0, 5));
+ xmlTextWriterEndElement(writer);
+ }
+
+ if (PQgetvalue(querySet.res, 0, 8) && strlen(PQgetvalue(querySet.res, 0, 8)))
+ {
+ xmlTextWriterStartElement(writer, BAD_CAST "adminLevel");
+ xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(querySet.res, 0, 8));
+ xmlTextWriterEndElement(writer);
+ }
+
+ if (PQgetvalue(querySet.res, 0, 6) && strlen(PQgetvalue(querySet.res, 0, 6)))
+ {
+ xmlTextWriterStartElement(writer, BAD_CAST "countryCode");
+ xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(querySet.res, 0, 6));
+ xmlTextWriterEndElement(writer);
+ }
+
+ if (PQntuples(querySet.resAddress) > 0)
+ {
+ xmlTextWriterStartElement(writer, BAD_CAST "address");
+ for (i = 0; i < PQntuples(querySet.resAddress); i++)
+ {
+ xmlTextWriterStartElement(writer, BAD_CAST getRankLabel(atoi(PQgetvalue(querySet.resAddress, i, 5))));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "rank", BAD_CAST PQgetvalue(querySet.resAddress, i, 5));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(querySet.resAddress, i, 0));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "id", BAD_CAST PQgetvalue(querySet.resAddress, i, 1));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "key", BAD_CAST PQgetvalue(querySet.resAddress, i, 2));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "value", BAD_CAST PQgetvalue(querySet.resAddress, i, 3));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "distance", BAD_CAST PQgetvalue(querySet.resAddress, i, 4));
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "isaddress", BAD_CAST PQgetvalue(querySet.resAddress, i, 6));
+ xmlTextWriterEndElement(writer);
+ }
+ xmlTextWriterEndElement(writer);
+ }
+
+ if (PQntuples(querySet.resExtraTags))
+ {
+ xmlTextWriterStartElement(writer, BAD_CAST "tags");
+
+ for (i = 0; i < PQntuples(querySet.resExtraTags); i++)
+ {
+ xmlTextWriterStartElement(writer, BAD_CAST "tag");
+ xmlTextWriterWriteAttribute(writer, BAD_CAST "type", BAD_CAST PQgetvalue(querySet.resExtraTags, i, 0));
+ xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(querySet.resExtraTags, i, 1));
+ xmlTextWriterEndElement(writer);
+ }
+
+ xmlTextWriterEndElement(writer);
+ }
+
+
+ xmlTextWriterStartElement(writer, BAD_CAST "osmGeometry");
+ xmlTextWriterWriteString(writer, BAD_CAST PQgetvalue(querySet.res, 0, 7));
+ xmlTextWriterEndElement(writer);
+
+ xmlTextWriterEndElement(writer); // </feature>
+
+ if (writer_mutex) pthread_mutex_unlock( writer_mutex );
+
+ nominatim_exportFreeQueries(&querySet);