2010-10-24 03:12:37 +04:00
/*
*/
# include <stdlib.h>
# include <string.h>
# include <libpq-fe.h>
# include <libxml/xmlstring.h>
# include <libxml/xmlreader.h>
# include <libxml/hash.h>
# include "nominatim.h"
# include "import.h"
# include "input.h"
typedef enum { FILETYPE_NONE , FILETYPE_STRUCTUREDV0P1 } filetypes_t ;
typedef enum { FILEMODE_NONE , FILEMODE_ADD , FILEMODE_UPDATE , FILEMODE_DELETE } filemodes_t ;
2011-01-21 13:40:44 +03:00
# define MAX_FEATUREADDRESS 5000
# define MAX_FEATURENAMES 10000
# define MAX_FEATUREEXTRATAGS 10000
# define MAX_FEATURENAMESTRING 1000000
# define MAX_FEATUREEXTRATAGSTRING 500000
2010-10-24 03:12:37 +04:00
2010-12-10 19:13:07 +03:00
struct feature_address
{
int place_id ;
int rankAddress ;
char isAddress [ 2 ] ;
xmlChar * type ;
xmlChar * id ;
xmlChar * key ;
xmlChar * value ;
xmlChar * distance ;
2010-10-24 03:12:37 +04:00
} ;
2010-12-10 19:13:07 +03:00
struct feature_tag
{
xmlChar * type ;
xmlChar * value ;
2010-10-24 03:12:37 +04:00
} ;
2010-12-10 19:13:07 +03:00
struct feature
{
2011-01-21 13:40:44 +03:00
xmlChar * placeID ;
2010-12-10 19:13:07 +03:00
xmlChar * type ;
xmlChar * id ;
xmlChar * key ;
xmlChar * value ;
xmlChar * rankAddress ;
xmlChar * rankSearch ;
xmlChar * countryCode ;
2011-02-07 14:13:18 +03:00
xmlChar * parentPlaceID ;
xmlChar * parentType ;
xmlChar * parentID ;
2010-12-10 19:13:07 +03:00
xmlChar * adminLevel ;
xmlChar * houseNumber ;
xmlChar * geometry ;
2010-10-24 03:12:37 +04:00
} feature ;
int fileType = FILETYPE_NONE ;
int fileMode = FILEMODE_ADD ;
PGconn * conn ;
struct feature_address featureAddress [ MAX_FEATUREADDRESS ] ;
2010-12-07 16:41:02 +03:00
struct feature_tag featureName [ MAX_FEATURENAMES ] ;
struct feature_tag featureExtraTag [ MAX_FEATUREEXTRATAGS ] ;
2010-10-24 03:12:37 +04:00
struct feature feature ;
int featureAddressLines = 0 ;
int featureNameLines = 0 ;
2010-12-07 16:41:02 +03:00
int featureExtraTagLines = 0 ;
2010-10-24 03:12:37 +04:00
int featureCount = 0 ;
xmlHashTablePtr partionTableTagsHash ;
2011-02-07 14:13:18 +03:00
xmlHashTablePtr partionTableTagsHashDelete ;
2010-12-07 16:41:02 +03:00
char featureNameString [ MAX_FEATURENAMESTRING ] ;
char featureExtraTagString [ MAX_FEATUREEXTRATAGSTRING ] ;
2010-10-24 03:12:37 +04:00
void StartElement ( xmlTextReaderPtr reader , const xmlChar * name )
{
char * value ;
float version ;
int isAddressLine ;
if ( fileType = = FILETYPE_NONE )
{
2010-12-10 19:13:07 +03:00
// Potential to handle other file types in the future / versions
2010-10-24 03:12:37 +04:00
if ( xmlStrEqual ( name , BAD_CAST " osmStructured " ) )
{
2010-12-10 19:13:07 +03:00
value = ( char * ) xmlTextReaderGetAttribute ( reader , BAD_CAST " version " ) ;
version = strtof ( value , NULL ) ;
xmlFree ( value ) ;
if ( version = = ( float ) 0.1 )
{
fileType = FILETYPE_STRUCTUREDV0P1 ;
fileMode = FILEMODE_ADD ;
}
else
{
2011-01-21 13:40:44 +03:00
fprintf ( stderr , " Unknown osmStructured version %f (%s) \n " , version , value ) ;
2010-10-24 03:12:37 +04:00
exit_nicely ( ) ;
2010-12-10 19:13:07 +03:00
}
2010-10-24 03:12:37 +04:00
}
else
{
fprintf ( stderr , " Unknown XML document type: %s \n " , name ) ;
exit_nicely ( ) ;
}
return ;
}
if ( xmlStrEqual ( name , BAD_CAST " add " ) )
{
2010-12-10 19:13:07 +03:00
fileMode = FILEMODE_ADD ;
return ;
2010-10-24 03:12:37 +04:00
}
if ( xmlStrEqual ( name , BAD_CAST " update " ) )
{
2010-12-10 19:13:07 +03:00
fileMode = FILEMODE_UPDATE ;
return ;
2010-10-24 03:12:37 +04:00
}
if ( xmlStrEqual ( name , BAD_CAST " delete " ) )
{
2010-12-10 19:13:07 +03:00
fileMode = FILEMODE_DELETE ;
return ;
2010-10-24 03:12:37 +04:00
}
if ( fileMode = = FILEMODE_NONE )
{
fprintf ( stderr , " Unknown import mode in: %s \n " , name ) ;
exit_nicely ( ) ;
}
if ( xmlStrEqual ( name , BAD_CAST " feature " ) )
{
2011-01-21 13:40:44 +03:00
feature . placeID = xmlTextReaderGetAttribute ( reader , BAD_CAST " place_id " ) ;
2010-12-10 19:13:07 +03:00
feature . type = xmlTextReaderGetAttribute ( reader , BAD_CAST " type " ) ;
feature . id = xmlTextReaderGetAttribute ( reader , BAD_CAST " id " ) ;
feature . key = xmlTextReaderGetAttribute ( reader , BAD_CAST " key " ) ;
feature . value = xmlTextReaderGetAttribute ( reader , BAD_CAST " value " ) ;
feature . rankAddress = xmlTextReaderGetAttribute ( reader , BAD_CAST " rank " ) ;
feature . rankSearch = xmlTextReaderGetAttribute ( reader , BAD_CAST " importance " ) ;
2010-10-24 03:12:37 +04:00
2011-02-07 14:13:18 +03:00
feature . parentPlaceID = xmlTextReaderGetAttribute ( reader , BAD_CAST " parent_place_id " ) ;
2011-03-18 12:52:16 +03:00
/*
if ( strlen ( feature . parentPlaceID ) = = 0 )
{
xmlFree ( feature . parentPlaceID ) ;
feature . parentPlaceID = NULL ;
}
*/
2011-02-07 14:13:18 +03:00
feature . parentType = xmlTextReaderGetAttribute ( reader , BAD_CAST " parent_type " ) ;
feature . parentID = xmlTextReaderGetAttribute ( reader , BAD_CAST " parent_id " ) ;
2010-12-10 19:13:07 +03:00
feature . countryCode = NULL ;
feature . adminLevel = NULL ;
feature . houseNumber = NULL ;
feature . geometry = NULL ;
featureAddressLines = 0 ;
featureNameLines = 0 ;
2011-02-07 14:13:18 +03:00
featureExtraTagLines = 0 ;
2010-10-24 03:12:37 +04:00
2010-12-10 19:13:07 +03:00
return ;
2010-10-24 03:12:37 +04:00
}
if ( xmlStrEqual ( name , BAD_CAST " names " ) ) return ;
if ( xmlStrEqual ( name , BAD_CAST " name " ) )
{
2011-01-21 13:40:44 +03:00
if ( featureNameLines < MAX_FEATURENAMES )
2010-12-10 19:13:07 +03:00
{
2011-01-21 13:40:44 +03:00
featureName [ featureNameLines ] . type = xmlTextReaderGetAttribute ( reader , BAD_CAST " type " ) ;
featureName [ featureNameLines ] . value = xmlTextReaderReadString ( reader ) ;
featureNameLines + + ;
}
else
{
fprintf ( stderr , " Too many name elements (%s%s) \n " , feature . type , feature . id ) ;
// exit_nicely();
2010-12-10 19:13:07 +03:00
}
return ;
2010-10-24 03:12:37 +04:00
}
2010-12-07 16:41:02 +03:00
if ( xmlStrEqual ( name , BAD_CAST " tags " ) ) return ;
if ( xmlStrEqual ( name , BAD_CAST " tag " ) )
{
2011-01-21 13:40:44 +03:00
if ( featureExtraTagLines < MAX_FEATUREEXTRATAGS )
{
featureExtraTag [ featureExtraTagLines ] . type = xmlTextReaderGetAttribute ( reader , BAD_CAST " type " ) ;
featureExtraTag [ featureExtraTagLines ] . value = xmlTextReaderReadString ( reader ) ;
featureExtraTagLines + + ;
}
else
2010-12-10 19:13:07 +03:00
{
2011-01-21 13:40:44 +03:00
fprintf ( stderr , " Too many extra tag elements (%s%s) \n " , feature . type , feature . id ) ;
// exit_nicely();
2010-12-10 19:13:07 +03:00
}
return ;
2010-12-07 16:41:02 +03:00
}
2010-10-24 03:12:37 +04:00
if ( xmlStrEqual ( name , BAD_CAST " osmGeometry " ) )
{
2010-12-10 19:13:07 +03:00
feature . geometry = xmlTextReaderReadString ( reader ) ;
return ;
2010-10-24 03:12:37 +04:00
}
if ( xmlStrEqual ( name , BAD_CAST " adminLevel " ) )
{
2010-12-10 19:13:07 +03:00
feature . adminLevel = xmlTextReaderReadString ( reader ) ;
return ;
2010-10-24 03:12:37 +04:00
}
if ( xmlStrEqual ( name , BAD_CAST " countryCode " ) )
{
2010-12-10 19:13:07 +03:00
feature . countryCode = xmlTextReaderReadString ( reader ) ;
return ;
2010-10-24 03:12:37 +04:00
}
if ( xmlStrEqual ( name , BAD_CAST " houseNumber " ) )
{
2010-12-10 19:13:07 +03:00
feature . houseNumber = xmlTextReaderReadString ( reader ) ;
return ;
2010-10-24 03:12:37 +04:00
}
if ( xmlStrEqual ( name , BAD_CAST " address " ) )
{
2010-12-10 19:13:07 +03:00
featureAddressLines = 0 ;
return ;
2010-10-24 03:12:37 +04:00
}
isAddressLine = 0 ;
if ( xmlStrEqual ( name , BAD_CAST " continent " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " sea " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " country " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " state " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " county " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " city " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " town " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " village " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " unknown " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " suburb " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " postcode " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " neighborhood " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " street " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " access " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " building " ) )
{
isAddressLine = 1 ;
}
else if ( xmlStrEqual ( name , BAD_CAST " other " ) )
{
isAddressLine = 1 ;
}
if ( isAddressLine )
{
2011-01-21 13:40:44 +03:00
if ( featureAddressLines < MAX_FEATUREADDRESS )
{
value = ( char * ) xmlTextReaderGetAttribute ( reader , BAD_CAST " rank " ) ;
if ( ! value )
{
fprintf ( stderr , " Address element missing rank \n " ) ;
exit_nicely ( ) ;
}
featureAddress [ featureAddressLines ] . rankAddress = atoi ( value ) ;
xmlFree ( value ) ;
value = ( char * ) xmlTextReaderGetAttribute ( reader , BAD_CAST " isaddress " ) ;
if ( ! value )
{
fprintf ( stderr , " Address element missing rank \n " ) ;
exit_nicely ( ) ;
}
if ( * value = = ' t ' ) strcpy ( featureAddress [ featureAddressLines ] . isAddress , " t " ) ;
else strcpy ( featureAddress [ featureAddressLines ] . isAddress , " f " ) ;
xmlFree ( value ) ;
featureAddress [ featureAddressLines ] . type = xmlTextReaderGetAttribute ( reader , BAD_CAST " type " ) ;
featureAddress [ featureAddressLines ] . id = xmlTextReaderGetAttribute ( reader , BAD_CAST " id " ) ;
featureAddress [ featureAddressLines ] . key = xmlTextReaderGetAttribute ( reader , BAD_CAST " key " ) ;
featureAddress [ featureAddressLines ] . value = xmlTextReaderGetAttribute ( reader , BAD_CAST " value " ) ;
featureAddress [ featureAddressLines ] . distance = xmlTextReaderGetAttribute ( reader , BAD_CAST " distance " ) ;
featureAddressLines + + ;
}
else
2010-12-10 19:13:07 +03:00
{
2011-01-21 13:40:44 +03:00
fprintf ( stderr , " Too many address elements (%s%s) \n " , feature . type , feature . id ) ;
// exit_nicely();
2010-12-10 19:13:07 +03:00
}
2010-10-24 03:12:37 +04:00
2010-12-10 19:13:07 +03:00
return ;
2010-10-24 03:12:37 +04:00
}
fprintf ( stderr , " %s: Unknown element name: %s \n " , __FUNCTION__ , name ) ;
}
void EndElement ( xmlTextReaderPtr reader , const xmlChar * name )
{
2010-12-10 19:13:07 +03:00
PGresult * res ;
2011-03-18 12:52:16 +03:00
const char * paramValues [ 14 ] ;
2010-10-24 03:12:37 +04:00
char * place_id ;
char * partionQueryName ;
2010-12-10 19:13:07 +03:00
int i , namePos , lineTypeLen , lineValueLen ;
2010-10-24 03:12:37 +04:00
if ( xmlStrEqual ( name , BAD_CAST " feature " ) )
2010-12-10 19:13:07 +03:00
{
featureCount + + ;
if ( featureCount % 1000 = = 0 ) printf ( " feature %i(k) \n " , featureCount / 1000 ) ;
2011-01-21 13:40:44 +03:00
/*
2010-10-24 03:12:37 +04:00
if ( fileMode = = FILEMODE_ADD )
{
2010-12-10 19:13:07 +03:00
resPlaceID = PQexecPrepared ( conn , " get_new_place_id " , 0 , NULL , NULL , NULL , 0 ) ;
if ( PQresultStatus ( resPlaceID ) ! = PGRES_TUPLES_OK )
{
fprintf ( stderr , " get_place_id: INSERT failed: %s " , PQerrorMessage ( conn ) ) ;
PQclear ( resPlaceID ) ;
exit ( EXIT_FAILURE ) ;
}
2010-10-24 03:12:37 +04:00
}
else
{
paramValues [ 0 ] = ( const char * ) feature . type ;
paramValues [ 1 ] = ( const char * ) feature . id ;
paramValues [ 2 ] = ( const char * ) feature . key ;
paramValues [ 3 ] = ( const char * ) feature . value ;
resPlaceID = PQexecPrepared ( conn , " get_new_place_id " , 4 , paramValues , NULL , NULL , 0 ) ;
if ( PQresultStatus ( resPlaceID ) ! = PGRES_TUPLES_OK )
{
fprintf ( stderr , " index_placex: INSERT failed: %s " , PQerrorMessage ( conn ) ) ;
PQclear ( resPlaceID ) ;
exit ( EXIT_FAILURE ) ;
}
}
2011-01-21 13:40:44 +03:00
*/
2011-02-07 14:13:18 +03:00
place_id = ( char * ) feature . placeID ;
2010-10-24 03:12:37 +04:00
2011-02-07 14:13:18 +03:00
if ( fileMode = = FILEMODE_UPDATE | | fileMode = = FILEMODE_DELETE | | fileMode = = FILEMODE_ADD )
2010-10-24 03:12:37 +04:00
{
paramValues [ 0 ] = ( const char * ) place_id ;
res = PQexecPrepared ( conn , " placex_delete " , 1 , paramValues , NULL , NULL , 0 ) ;
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
fprintf ( stderr , " placex_delete: DELETE failed: %s " , PQerrorMessage ( conn ) ) ;
PQclear ( res ) ;
exit ( EXIT_FAILURE ) ;
}
PQclear ( res ) ;
res = PQexecPrepared ( conn , " search_name_delete " , 1 , paramValues , NULL , NULL , 0 ) ;
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
fprintf ( stderr , " search_name_delete: DELETE failed: %s " , PQerrorMessage ( conn ) ) ;
PQclear ( res ) ;
exit ( EXIT_FAILURE ) ;
}
PQclear ( res ) ;
res = PQexecPrepared ( conn , " place_addressline_delete " , 1 , paramValues , NULL , NULL , 0 ) ;
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
fprintf ( stderr , " place_addressline_delete: DELETE failed: %s " , PQerrorMessage ( conn ) ) ;
PQclear ( res ) ;
exit ( EXIT_FAILURE ) ;
}
PQclear ( res ) ;
2011-02-07 14:13:18 +03:00
partionQueryName = xmlHashLookup2 ( partionTableTagsHashDelete , feature . key , feature . value ) ;
if ( partionQueryName )
{
res = PQexecPrepared ( conn , partionQueryName , 1 , paramValues , NULL , NULL , 0 ) ;
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
fprintf ( stderr , " %s: DELETE failed: %s " , partionQueryName , PQerrorMessage ( conn ) ) ;
PQclear ( res ) ;
exit ( EXIT_FAILURE ) ;
}
PQclear ( res ) ;
}
2010-10-24 03:12:37 +04:00
}
if ( fileMode = = FILEMODE_UPDATE | | fileMode = = FILEMODE_ADD )
{
2010-12-10 19:13:07 +03:00
// Insert into placex
paramValues [ 0 ] = ( const char * ) place_id ;
paramValues [ 1 ] = ( const char * ) feature . type ;
paramValues [ 2 ] = ( const char * ) feature . id ;
paramValues [ 3 ] = ( const char * ) feature . key ;
paramValues [ 4 ] = ( const char * ) feature . value ;
featureNameString [ 0 ] = 0 ;
if ( featureNameLines )
{
namePos = 0 ;
lineTypeLen = 0 ;
lineValueLen = 0 ;
for ( i = 0 ; i < featureNameLines ; i + + )
{
2011-02-07 14:13:18 +03:00
lineTypeLen = ( int ) strlen ( ( char * ) featureName [ i ] . type ) ;
lineValueLen = ( int ) strlen ( ( char * ) featureName [ i ] . value ) ;
2010-12-10 19:13:07 +03:00
if ( namePos + lineTypeLen + lineValueLen + 7 > MAX_FEATURENAMESTRING )
{
fprintf ( stderr , " feature name too long: %s " , ( const char * ) featureName [ i ] . value ) ;
break ;
}
if ( namePos ) strcpy ( featureNameString + ( namePos + + ) , " , " ) ;
strcpy ( featureNameString + ( namePos + + ) , " \" " ) ;
2011-02-07 14:13:18 +03:00
strcpy ( featureNameString + namePos , ( char * ) featureName [ i ] . type ) ;
2010-12-10 19:13:07 +03:00
namePos + = lineTypeLen ;
strcpy ( featureNameString + namePos , " \" => \" " ) ;
namePos + = 4 ;
2011-02-07 14:13:18 +03:00
strcpy ( featureNameString + namePos , ( char * ) featureName [ i ] . value ) ;
2010-12-10 19:13:07 +03:00
namePos + = lineValueLen ;
strcpy ( featureNameString + ( namePos + + ) , " \" " ) ;
}
}
paramValues [ 5 ] = ( const char * ) featureNameString ;
2011-03-18 12:52:16 +03:00
paramValues [ 6 ] = ( const char * ) feature . countryCode ;
2010-12-10 19:13:07 +03:00
featureExtraTagString [ 0 ] = 0 ;
if ( featureExtraTagLines )
{
namePos = 0 ;
lineTypeLen = 0 ;
lineValueLen = 0 ;
for ( i = 0 ; i < featureExtraTagLines ; i + + )
{
2011-02-07 14:13:18 +03:00
lineTypeLen = strlen ( ( char * ) featureExtraTag [ i ] . type ) ;
lineValueLen = strlen ( ( char * ) featureExtraTag [ i ] . value ) ;
2010-12-10 19:13:07 +03:00
if ( namePos + lineTypeLen + lineValueLen + 7 > MAX_FEATUREEXTRATAGSTRING )
{
fprintf ( stderr , " feature extra tag too long: %s " , ( const char * ) featureExtraTag [ i ] . value ) ;
break ;
}
if ( namePos ) strcpy ( featureExtraTagString + ( namePos + + ) , " , " ) ;
strcpy ( featureExtraTagString + ( namePos + + ) , " \" " ) ;
2011-02-07 14:13:18 +03:00
strcpy ( featureExtraTagString + namePos , ( char * ) featureExtraTag [ i ] . type ) ;
2010-12-10 19:13:07 +03:00
namePos + = lineTypeLen ;
strcpy ( featureExtraTagString + namePos , " \" => \" " ) ;
namePos + = 4 ;
2011-02-07 14:13:18 +03:00
strcpy ( featureExtraTagString + namePos , ( char * ) featureExtraTag [ i ] . value ) ;
2010-12-10 19:13:07 +03:00
namePos + = lineValueLen ;
strcpy ( featureExtraTagString + ( namePos + + ) , " \" " ) ;
}
}
2011-03-18 12:52:16 +03:00
paramValues [ 7 ] = ( const char * ) featureExtraTagString ;
2010-12-10 19:13:07 +03:00
2011-03-18 12:52:16 +03:00
if ( strlen ( feature . parentPlaceID ) = = 0 )
paramValues [ 8 ] = " 0 " ;
else
paramValues [ 8 ] = ( const char * ) feature . parentPlaceID ;
2011-02-07 14:13:18 +03:00
2011-03-18 12:52:16 +03:00
paramValues [ 9 ] = ( const char * ) feature . adminLevel ;
paramValues [ 10 ] = ( const char * ) feature . houseNumber ;
paramValues [ 11 ] = ( const char * ) feature . rankAddress ;
paramValues [ 12 ] = ( const char * ) feature . rankSearch ;
paramValues [ 13 ] = ( const char * ) feature . geometry ;
2011-02-07 14:13:18 +03:00
if ( strlen ( paramValues [ 3 ] ) )
2010-12-10 19:13:07 +03:00
{
2011-03-18 12:52:16 +03:00
res = PQexecPrepared ( conn , " placex_insert " , 14 , paramValues , NULL , NULL , 0 ) ;
2011-02-07 14:13:18 +03:00
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
fprintf ( stderr , " index_placex: INSERT failed: %s " , PQerrorMessage ( conn ) ) ;
fprintf ( stderr , " index_placex: INSERT failed: %s %s %s " , paramValues [ 0 ] , paramValues [ 1 ] , paramValues [ 2 ] ) ;
PQclear ( res ) ;
exit ( EXIT_FAILURE ) ;
}
PQclear ( res ) ;
2010-12-10 19:13:07 +03:00
}
for ( i = 0 ; i < featureAddressLines ; i + + )
{
// insert into place_address
paramValues [ 0 ] = ( const char * ) place_id ;
paramValues [ 1 ] = ( const char * ) featureAddress [ i ] . distance ;
paramValues [ 2 ] = ( const char * ) featureAddress [ i ] . type ;
paramValues [ 3 ] = ( const char * ) featureAddress [ i ] . id ;
paramValues [ 4 ] = ( const char * ) featureAddress [ i ] . key ;
paramValues [ 5 ] = ( const char * ) featureAddress [ i ] . value ;
paramValues [ 6 ] = ( const char * ) featureAddress [ i ] . isAddress ;
res = PQexecPrepared ( conn , " place_addressline_insert " , 7 , paramValues , NULL , NULL , 0 ) ;
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
fprintf ( stderr , " place_addressline_insert: INSERT failed: %s " , PQerrorMessage ( conn ) ) ;
PQclear ( res ) ;
exit ( EXIT_FAILURE ) ;
}
PQclear ( res ) ;
xmlFree ( featureAddress [ i ] . type ) ;
xmlFree ( featureAddress [ i ] . id ) ;
xmlFree ( featureAddress [ i ] . key ) ;
xmlFree ( featureAddress [ i ] . value ) ;
xmlFree ( featureAddress [ i ] . distance ) ;
}
if ( featureNameLines )
{
paramValues [ 0 ] = ( const char * ) place_id ;
res = PQexecPrepared ( conn , " search_name_insert " , 1 , paramValues , NULL , NULL , 0 ) ;
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
fprintf ( stderr , " search_name_insert: INSERT failed: %s " , PQerrorMessage ( conn ) ) ;
PQclear ( res ) ;
exit ( EXIT_FAILURE ) ;
}
PQclear ( res ) ;
}
partionQueryName = xmlHashLookup2 ( partionTableTagsHash , feature . key , feature . value ) ;
if ( partionQueryName )
{
// insert into partition table
paramValues [ 0 ] = ( const char * ) place_id ;
paramValues [ 1 ] = ( const char * ) feature . geometry ;
res = PQexecPrepared ( conn , partionQueryName , 2 , paramValues , NULL , NULL , 0 ) ;
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
fprintf ( stderr , " %s: INSERT failed: %s " , partionQueryName , PQerrorMessage ( conn ) ) ;
PQclear ( res ) ;
exit ( EXIT_FAILURE ) ;
}
PQclear ( res ) ;
}
2010-10-24 03:12:37 +04:00
}
else
{
2010-12-10 19:13:07 +03:00
for ( i = 0 ; i < featureAddressLines ; i + + )
{
xmlFree ( featureAddress [ i ] . type ) ;
xmlFree ( featureAddress [ i ] . id ) ;
xmlFree ( featureAddress [ i ] . key ) ;
xmlFree ( featureAddress [ i ] . value ) ;
xmlFree ( featureAddress [ i ] . distance ) ;
}
2010-10-24 03:12:37 +04:00
}
2011-01-21 13:40:44 +03:00
xmlFree ( feature . placeID ) ;
2010-12-10 19:13:07 +03:00
xmlFree ( feature . type ) ;
xmlFree ( feature . id ) ;
xmlFree ( feature . key ) ;
xmlFree ( feature . value ) ;
xmlFree ( feature . rankAddress ) ;
xmlFree ( feature . rankSearch ) ;
2011-03-18 12:52:16 +03:00
if ( feature . parentPlaceID ) xmlFree ( feature . parentPlaceID ) ;
if ( feature . parentType ) xmlFree ( feature . parentType ) ;
if ( feature . parentID ) xmlFree ( feature . parentID ) ;
2010-10-24 03:12:37 +04:00
// if (feature.name) xmlFree(feature.name);
2010-12-10 19:13:07 +03:00
if ( feature . countryCode ) xmlFree ( feature . countryCode ) ;
if ( feature . adminLevel ) xmlFree ( feature . adminLevel ) ;
if ( feature . houseNumber ) xmlFree ( feature . houseNumber ) ;
if ( feature . geometry ) xmlFree ( feature . geometry ) ;
2010-10-24 03:12:37 +04:00
2011-01-21 13:40:44 +03:00
// PQclear(resPlaceID);
2010-12-10 19:13:07 +03:00
}
2010-10-24 03:12:37 +04:00
}
static void processNode ( xmlTextReaderPtr reader )
{
2010-12-10 19:13:07 +03:00
xmlChar * name ;
2010-10-24 03:12:37 +04:00
name = xmlTextReaderName ( reader ) ;
if ( name = = NULL )
{
name = xmlStrdup ( BAD_CAST " -- " ) ;
}
2010-12-10 19:13:07 +03:00
switch ( xmlTextReaderNodeType ( reader ) )
2010-10-24 03:12:37 +04:00
{
2010-12-10 19:13:07 +03:00
case XML_READER_TYPE_ELEMENT :
StartElement ( reader , name ) ;
if ( xmlTextReaderIsEmptyElement ( reader ) )
EndElement ( reader , name ) ; /* No end_element for self closing tags! */
break ;
case XML_READER_TYPE_END_ELEMENT :
EndElement ( reader , name ) ;
break ;
case XML_READER_TYPE_TEXT :
case XML_READER_TYPE_CDATA :
case XML_READER_TYPE_SIGNIFICANT_WHITESPACE :
/* Ignore */
break ;
default :
fprintf ( stderr , " Unknown node type %d \n " , xmlTextReaderNodeType ( reader ) ) ;
break ;
2010-10-24 03:12:37 +04:00
}
xmlFree ( name ) ;
}
int nominatim_import ( const char * conninfo , const char * partionTagsFilename , const char * filename )
{
xmlTextReaderPtr reader ;
int ret = 0 ;
2010-12-10 19:13:07 +03:00
PGresult * res ;
FILE * partionTagsFile ;
char * partionQueryName ;
2010-10-24 03:12:37 +04:00
char partionQuerySQL [ 1024 ] ;
2010-12-10 19:13:07 +03:00
conn = PQconnectdb ( conninfo ) ;
2010-10-24 03:12:37 +04:00
if ( PQstatus ( conn ) ! = CONNECTION_OK )
{
fprintf ( stderr , " Connection to database failed: %s \n " , PQerrorMessage ( conn ) ) ;
exit ( EXIT_FAILURE ) ;
}
2010-12-10 19:13:07 +03:00
partionTableTagsHash = xmlHashCreate ( 200 ) ;
2011-02-07 14:13:18 +03:00
partionTableTagsHashDelete = xmlHashCreate ( 200 ) ;
2010-10-24 03:12:37 +04:00
2010-12-10 19:13:07 +03:00
partionTagsFile = fopen ( partionTagsFilename , " rt " ) ;
if ( ! partionTagsFile )
2010-10-24 03:12:37 +04:00
{
fprintf ( stderr , " Unable to read partition tags file: %s \n " , partionTagsFilename ) ;
exit ( EXIT_FAILURE ) ;
}
2010-12-10 19:13:07 +03:00
char buffer [ 1024 ] , osmkey [ 256 ] , osmvalue [ 256 ] ;
int fields ;
while ( fgets ( buffer , sizeof ( buffer ) , partionTagsFile ) ! = NULL )
{
fields = sscanf ( buffer , " %23s %63s " , osmkey , osmvalue ) ;
if ( fields < = 0 ) continue ;
if ( fields ! = 2 )
{
fprintf ( stderr , " Error partition file \n " ) ;
exit_nicely ( ) ;
}
partionQueryName = malloc ( strlen ( " partition_insert_ " ) + strlen ( osmkey ) + strlen ( osmvalue ) + 2 ) ;
strcpy ( partionQueryName , " partition_insert_ " ) ;
strcat ( partionQueryName , osmkey ) ;
strcat ( partionQueryName , " _ " ) ;
strcat ( partionQueryName , osmvalue ) ;
strcpy ( partionQuerySQL , " insert into place_classtype_ " ) ;
strcat ( partionQuerySQL , osmkey ) ;
strcat ( partionQuerySQL , " _ " ) ;
strcat ( partionQuerySQL , osmvalue ) ;
strcat ( partionQuerySQL , " (place_id, centroid) values ($1, ST_Centroid(st_setsrid($2, 4326))) " ) ;
res = PQprepare ( conn , partionQueryName , partionQuerySQL , 2 , NULL ) ;
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
fprintf ( stderr , " Failed to prepare %s: %s \n " , partionQueryName , PQerrorMessage ( conn ) ) ;
exit ( EXIT_FAILURE ) ;
}
xmlHashAddEntry2 ( partionTableTagsHash , BAD_CAST osmkey , BAD_CAST osmvalue , BAD_CAST partionQueryName ) ;
2011-02-07 14:13:18 +03:00
partionQueryName = malloc ( strlen ( " partition_delete_ " ) + strlen ( osmkey ) + strlen ( osmvalue ) + 2 ) ;
strcpy ( partionQueryName , " partition_delete_ " ) ;
strcat ( partionQueryName , osmkey ) ;
strcat ( partionQueryName , " _ " ) ;
strcat ( partionQueryName , osmvalue ) ;
strcpy ( partionQuerySQL , " delete from place_classtype_ " ) ;
strcat ( partionQuerySQL , osmkey ) ;
strcat ( partionQuerySQL , " _ " ) ;
strcat ( partionQuerySQL , osmvalue ) ;
strcat ( partionQuerySQL , " where place_id = $1::integer " ) ;
res = PQprepare ( conn , partionQueryName , partionQuerySQL , 1 , NULL ) ;
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
{
fprintf ( stderr , " Failed to prepare %s: %s \n " , partionQueryName , PQerrorMessage ( conn ) ) ;
exit ( EXIT_FAILURE ) ;
}
xmlHashAddEntry2 ( partionTableTagsHashDelete , BAD_CAST osmkey , BAD_CAST osmvalue , BAD_CAST partionQueryName ) ;
2010-12-10 19:13:07 +03:00
}
2010-10-24 03:12:37 +04:00
res = PQprepare ( conn , " get_new_place_id " ,
2010-12-10 19:13:07 +03:00
" select nextval('seq_place') " ,
0 , NULL ) ;
2010-10-24 03:12:37 +04:00
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
2010-12-10 19:13:07 +03:00
{
2010-10-24 03:12:37 +04:00
fprintf ( stderr , " Failed to prepare get_new_place_id: %s \n " , PQerrorMessage ( conn ) ) ;
2010-12-10 19:13:07 +03:00
exit ( EXIT_FAILURE ) ;
}
2010-10-24 03:12:37 +04:00
res = PQprepare ( conn , " get_place_id " ,
2010-12-10 19:13:07 +03:00
" select place_id from placex where osm_type = $1 and osm_id = $2 and class = $3 and type = $4 " ,
4 , NULL ) ;
2010-10-24 03:12:37 +04:00
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
2010-12-10 19:13:07 +03:00
{
2010-10-24 03:12:37 +04:00
fprintf ( stderr , " Failed to prepare get_place_id: %s \n " , PQerrorMessage ( conn ) ) ;
2010-12-10 19:13:07 +03:00
exit ( EXIT_FAILURE ) ;
}
2010-10-24 03:12:37 +04:00
res = PQprepare ( conn , " placex_insert " ,
2011-03-18 12:52:16 +03:00
" 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) "
" values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, st_setsrid($14, 4326)) " ,
2010-12-10 19:13:07 +03:00
12 , NULL ) ;
2010-10-24 03:12:37 +04:00
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
2010-12-10 19:13:07 +03:00
{
2010-10-24 03:12:37 +04:00
fprintf ( stderr , " Failed to prepare placex_insert: %s \n " , PQerrorMessage ( conn ) ) ;
2010-12-10 19:13:07 +03:00
exit ( EXIT_FAILURE ) ;
}
2010-10-24 03:12:37 +04:00
res = PQprepare ( conn , " search_name_insert " ,
2010-12-10 19:13:07 +03:00
" insert into search_name (place_id, search_rank, address_rank, country_code, name_vector, nameaddress_vector, centroid) "
2011-03-21 13:15:29 +03:00
" select place_id, rank_search, rank_address, country_code, make_keywords(name), "
2010-12-10 19:13:07 +03:00
" (select uniq(sort(array_agg(name_vector))) from place_addressline join search_name on "
" (address_place_id = search_name.place_id) where place_addressline.place_id = $1 ), st_centroid(geometry) from placex "
" where place_id = $1 " ,
1 , NULL ) ;
2010-10-24 03:12:37 +04:00
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
2010-12-10 19:13:07 +03:00
{
2010-12-07 16:41:02 +03:00
fprintf ( stderr , " Failed to prepare search_name_insert: %s \n " , PQerrorMessage ( conn ) ) ;
2010-12-10 19:13:07 +03:00
exit ( EXIT_FAILURE ) ;
}
2010-10-24 03:12:37 +04:00
res = PQprepare ( conn , " place_addressline_insert " ,
2010-12-10 19:13:07 +03:00
" insert into place_addressline (place_id, address_place_id, fromarea, isaddress, distance, cached_rank_address) "
" 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 " ,
7 , NULL ) ;
2010-10-24 03:12:37 +04:00
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
2010-12-10 19:13:07 +03:00
{
2010-10-24 03:12:37 +04:00
fprintf ( stderr , " Failed to prepare place_addressline_insert: %s \n " , PQerrorMessage ( conn ) ) ;
2010-12-10 19:13:07 +03:00
exit ( EXIT_FAILURE ) ;
}
2010-10-24 03:12:37 +04:00
res = PQprepare ( conn , " placex_delete " ,
2010-12-10 19:13:07 +03:00
" delete from placex where place_id = $1 " ,
1 , NULL ) ;
2010-10-24 03:12:37 +04:00
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
2010-12-10 19:13:07 +03:00
{
2010-10-24 03:12:37 +04:00
fprintf ( stderr , " Failed to prepare placex_delete: %s \n " , PQerrorMessage ( conn ) ) ;
2010-12-10 19:13:07 +03:00
exit ( EXIT_FAILURE ) ;
}
2010-10-24 03:12:37 +04:00
res = PQprepare ( conn , " search_name_delete " ,
2010-12-10 19:13:07 +03:00
" delete from search_name where place_id = $1 " ,
1 , NULL ) ;
2010-10-24 03:12:37 +04:00
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
2010-12-10 19:13:07 +03:00
{
2010-10-24 03:12:37 +04:00
fprintf ( stderr , " Failed to prepare search_name_delete: %s \n " , PQerrorMessage ( conn ) ) ;
2010-12-10 19:13:07 +03:00
exit ( EXIT_FAILURE ) ;
}
2010-10-24 03:12:37 +04:00
res = PQprepare ( conn , " place_addressline_delete " ,
2010-12-10 19:13:07 +03:00
" delete from place_addressline where place_id = $1 " ,
1 , NULL ) ;
2010-10-24 03:12:37 +04:00
if ( PQresultStatus ( res ) ! = PGRES_COMMAND_OK )
2010-12-10 19:13:07 +03:00
{
2010-10-24 03:12:37 +04:00
fprintf ( stderr , " Failed to prepare place_addressline_delete: %s \n " , PQerrorMessage ( conn ) ) ;
2010-12-10 19:13:07 +03:00
exit ( EXIT_FAILURE ) ;
}
2010-10-24 03:12:37 +04:00
featureCount = 0 ;
reader = inputUTF8 ( filename ) ;
if ( reader = = NULL )
{
fprintf ( stderr , " Unable to open %s \n " , filename ) ;
return 1 ;
}
ret = xmlTextReaderRead ( reader ) ;
while ( ret = = 1 )
{
2010-12-10 19:13:07 +03:00
processNode ( reader ) ;
ret = xmlTextReaderRead ( reader ) ;
}
if ( ret ! = 0 )
{
fprintf ( stderr , " %s : failed to parse \n " , filename ) ;
return ret ;
2010-10-24 03:12:37 +04:00
}
2010-12-10 19:13:07 +03:00
xmlFreeTextReader ( reader ) ;
xmlHashFree ( partionTableTagsHash , NULL ) ;
2011-02-07 14:13:18 +03:00
xmlHashFree ( partionTableTagsHashDelete , NULL ) ;
2010-10-24 03:12:37 +04:00
return 0 ;
}