]> git.openstreetmap.org Git - nominatim.git/commitdiff
index on geometry of interpolation lines, and more improvements.
authorMarkus Gail <markus.gail.94@gmail.com>
Wed, 27 Apr 2016 15:42:59 +0000 (17:42 +0200)
committerMarkus Gail <markus.gail.94@gmail.com>
Wed, 27 Apr 2016 15:42:59 +0000 (17:42 +0200)
lib/Geocode.php
lib/PlaceLookup.php
lib/ReverseGeocode.php
nominatim/index.c
sql/functions.sql
sql/tables.sql
tests/features/api/reverse.feature
tests/features/db/update/interpolation.feature

index 0fb333aa49b5f1eb7a6f8e469545fbd357314e55..61ac834ba832feb0e88780d8f1ad75bae32f7f12 100644 (file)
                                        $sSQL .= " group by place_id, housenumber_for_place"; //is this group by really needed?, place_id + housenumber (in combination) are unique
                                        if (!$this->bDeDupe) $sSQL .= ", place_id ";
                                }
-                               // osmline, osm_type is 'I' for Interpolation Line
+                               // osmline
                                // interpolation line search only if a housenumber was searched and if it was found (i.e. aPlaceIDs[placeID] = housenumber != -1) (realized through a join)
                                $sSQL .= " union ";
-                               $sSQL .= "select 'I' as osm_type, place_id as osm_id, 'place' as class, 'house' as type, null as admin_level, 30 as rank_search, 30 as rank_address, min(place_id) as place_id, min(parent_place_id) as parent_place_id, calculated_country_code as country_code, ";
+                               $sSQL .= "select 'W' as osm_type, place_id as osm_id, 'place' as class, 'house' as type, null as admin_level, 30 as rank_search, 30 as rank_address, min(place_id) as place_id, min(parent_place_id) as parent_place_id, calculated_country_code as country_code, ";
                                $sSQL .= "get_address_by_language(place_id, housenumber_for_place, $sLanguagePrefArraySQL) as langaddress, ";
                                $sSQL .= "null as placename, ";
                                $sSQL .= "null as ref, ";
                                if ($this->bIncludeNameDetails) $sSQL .= "null as names, ";
                                $sSQL .= " avg(st_x(centroid)) as lon, avg(st_y(centroid)) as lat,";
                                $sSQL .= $sImportanceSQL."-0.1 as importance, ";  // slightly smaller than the importance for normal houses with rank 30, which is 0
-                               $sSQL .= " (select max(p.importance*(p.rank_address+2)) from place_addressline s, placex p where s.place_id = min(blub.parent_place_id) and p.place_id = s.address_place_id and s.isaddress and p.importance is not null) as addressimportance, ";
+                               $sSQL .= " (select max(p.importance*(p.rank_address+2)) from place_addressline s, placex p";
+                               $sSQL .= " where s.place_id = min(blub.parent_place_id) and p.place_id = s.address_place_id and s.isaddress and p.importance is not null) as addressimportance,";
                                $sSQL .= " null as extra_place ";
                                $sSQL .= " from (select place_id, calculated_country_code ";
                                //interpolate the housenumbers here
                                                                $aRoadPlaceIDs = $aPlaceIDs;
                                                                $sPlaceIDs = join(',',$aPlaceIDs);
 
-                                                               // Now they are indexed look for a house attached to a street we found
+                                                               // Now they are indexed, look for a house attached to a street we found
                                                                $sHouseNumberRegex = '\\\\m'.$aSearch['sHouseNumber'].'\\\\M';
                                                                $sSQL = "select place_id from placex where parent_place_id in (".$sPlaceIDs.") and transliteration(housenumber) ~* E'".$sHouseNumberRegex."'";
                                                                if (sizeof($this->aExcludePlaceIDs))
index 79c905d3ebace539c82a2791aeae89ceb59c217a..be60ff0782ba02221ae60ed369455b895a4c6bc8 100644 (file)
                        }
                        else if ($this->sType == 'interpolation')
                        {
-                               $sSQL = "select place_id, partition, 'I' as osm_type, osm_id, 'place' as class, 'house' as type, null admin_level, housenumber, null as street, null as isin, postcode,";
+                               $sSQL = "select place_id, partition, 'W' as osm_type, osm_id, 'place' as class, 'house' as type, null admin_level, housenumber, null as street, null as isin, postcode,";
                                $sSQL .= " calculated_country_code as country_code, parent_place_id, null as linked_place_id, 30 as rank_address, 30 as rank_search,";
-                               $sSQL .= " coalesce(null,0.75-(30::float/40)) as importance, null as indexed_status, null as indexed_date, null as wikipedia, calculated_country_code, ";
+                               $sSQL .= " (0.75-(30::float/40)) as importance, null as indexed_status, null as indexed_date, null as wikipedia, calculated_country_code, ";
                                $sSQL .= " get_address_by_language(place_id, housenumber, $sLanguagePrefArraySQL) as langaddress,";
                                $sSQL .= " null as placename,";
                                $sSQL .= " null as ref,";
 
                        if ($this->bAddressDetails)
                        {
-                               if(CONST_Use_US_Tiger_Data && $this->sType == 'tiger') // to get addressdetails for tiger data, the housenumber is needed
+                               if(CONST_Use_US_Tiger_Data && $this->sType == 'tiger' || $this->sType == 'interpolation') // to get addressdetails for tiger data, the housenumber is needed
                                        $aAddress = $this->getAddressNames($aPlace['housenumber']);
                                else
                                        $aAddress = $this->getAddressNames();
index 30e74234088f2f4c22e76e11a7a6de8b36975ea5..05093af388cfaf36ddd192290f3d96409d8af7d3 100644 (file)
                                $bIsInUnitedStates = ($aPlace['calculated_country_code'] == 'us');
                        }
                        // if a street or house was found, look in interpolation lines table
-                       if ($iMaxRank_orig >= 28 && $iPlaceID && ($aPlace['rank_search'] == 26 || $aPlace['rank_search'] == 27 || $aPlace['rank_search'] == 30))
+                       if ($iMaxRank_orig >= 28 && $aPlace && $aPlace['rank_search'] >= 26)
                        {
-                               $fSearchDiam = 0.001;
-                               if ($aPlace['rank_search'] == 30)
-                               {
-                                       // if a house was found, the closest road needs to be searched, to use its place id as parent_place_id for the interpolation line search
-                                       // because a road can be closer to the point than the house from above
-                                       $iRoadID = null;
-                                       while(!$iRoadID && $fSearchDiam < $fMaxAreaDistance)
-                                       {
-                                               $fSearchDiam = $fSearchDiam * 2;
-                                               $sSQL = 'select place_id ';
-                                               $sSQL .= ' FROM placex';
-                                               $sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', geometry, '.$fSearchDiam.')';
-                                               $sSQL .= ' and (rank_search = 26 or rank_search = 27)';
-                                               $sSQL .= ' and class not in (\'waterway\',\'railway\',\'tunnel\',\'bridge\',\'man_made\')';
-                                               $sSQL .= ' and indexed_status = 0 ';
-                                               $sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', geometry) ASC limit 1';
-                                               $aPlaceRoad = $this->oDB->getRow($sSQL);
-                                               if (PEAR::IsError($aPlace))
-                                               {
-                                                       failInternalError("Could not determine closest place.", $sSQL, $aPlace);
-                                               }
-                                               $iRoadID = $aPlaceRoad['place_id'];
-                                               $iTempPlaceID = $iRoadID;
-                                       }
-                               }
-                               else
-                               {
-                                       // if a street was found, we can take its place_id as parent_place_id
-                                       $iTempPlaceID = $iPlaceID;
-                               }
+                               // if a house was found, search the interpolation line that is at least as close as the house
                                $sSQL = 'SELECT place_id, parent_place_id, 30 as rank_search, ST_line_locate_point(linegeo,'.$sPointSQL.') as fraction';
-                               //if (CONST_Debug) { $sSQL .= ', housenumber, ST_distance('.$sPointSQL.', centroid) as distance, st_y(centroid) as lat, st_x(centroid) as lon'; }
-                               $sSQL .= ' FROM location_property_osmline WHERE parent_place_id = '.$iTempPlaceID;
-                               $sSQL .= ' AND ST_DWithin('.$sPointSQL.', linegeo, '.$fSearchDiam.') AND indexed_status = 0';
+                               $sSQL .= ' FROM location_property_osmline';
+                               $sSQL .= ' WHERE ST_DWithin('.$sPointSQL.', linegeo, '.$fSearchDiam.')';
+                               $sSQL .= ' and indexed_status = 0 ';
                                $sSQL .= ' ORDER BY ST_distance('.$sPointSQL.', linegeo) ASC limit 1';
+                               
                                if (CONST_Debug)
                                {
                                        $sSQL = preg_replace('/limit 1/', 'limit 100', $sSQL);
                                {
                                        failInternalError("Could not determine closest housenumber on an osm interpolation line.", $sSQL, $aPlaceLine);
                                }
-                               $iInterpolationLinePlaceID = $aPlaceLine['place_id'];
                                if ($aPlaceLine)
                                {
                                        if (CONST_Debug) var_dump('found housenumber in interpolation lines table', $aPlaceLine);
                                                $fDistancePlacex = $aDistancePlacex['distance'];
                                                // distance between point and interpolated house (fraction on interpolation line)
                                                $sSQL = 'SELECT ST_distance('.$sPointSQL.', ST_LineInterpolatePoint(linegeo, '.$aPlaceLine['fraction'].')) as distance';
-                                               $sSQL .= ' FROM location_property_osmline WHERE place_id = '.$iInterpolationLinePlaceID;
+                                               $sSQL .= ' FROM location_property_osmline WHERE place_id = '.$aPlaceLine['place_id'];
                                                $aDistanceInterpolation = $this->oDB->getRow($sSQL);
                                                if (PEAR::IsError($aDistanceInterpolation))
                                                {
                                                        // interpolation is closer to point than placex house
                                                        $bPlaceIsLine = true;
                                                        $aPlace = $aPlaceLine;
-                                                       $iPlaceID = $iInterpolationLinePlaceID;
+                                                       $iPlaceID = $aPlaceLine['place_id'];
                                                        $iParentPlaceID = $aPlaceLine['parent_place_id']; // the street
                                                        $fFraction = $aPlaceLine['fraction'];
                                                }
index 253b4f20667c8ff22852f4c271f779c381548196..2a5fa78b47ec10e5664a126d9fcbf2151c382c85 100644 (file)
 
 extern int verbose;
 
-void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile)
+void run_indexing(int rank, int interpolation, PGconn *conn, int num_threads, 
+struct index_thread_data * thread_data, const char *structuredoutputfile)
 {
-    struct index_thread_data * thread_data;
-    pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
     int tuples, count, sleepcount;
-
+    pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
+    
     time_t rankStartTime;
     int rankTotalTuples;
     int rankCountTuples;
     float rankPerSecond;
-
-    PGconn *conn;
-    PGresult * res;
+    
     PGresult * resSectors;
     PGresult * resPlaces;
     PGresult * resNULL;
-
-    int rank;
+    
     int i;
     int iSector;
     int iResult;
-
+    
     const char *paramValues[2];
     int         paramLengths[2];
     int         paramFormats[2];
     uint32_t    paramRank;
     uint32_t    paramSector;
     uint32_t    sector;
+    
+    xmlTextWriterPtr writer;
+    pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER;
+    
+    // Create the output file
+    writer = NULL;
+    if (structuredoutputfile)
+    {
+        writer = nominatim_exportXMLStart(structuredoutputfile);
+    }
+    
+    if (interpolation)
+    {
+        fprintf(stderr, "Starting interpolation lines (location_property_osmline)\n");
+    }
+    else
+    {
+        fprintf(stderr, "Starting rank %d\n", rank);
+    }
+    
+    rankCountTuples = 0;
+    rankPerSecond = 0;
+
+    paramRank = PGint32(rank);
+    paramValues[0] = (char *)&paramRank;
+    paramLengths[0] = sizeof(paramRank);
+    paramFormats[0] = 1;
+    
+    if (interpolation)
+    {
+        resSectors = PQexecPrepared(conn, "index_sectors_osmline", 0, NULL, 0, NULL, 1);
+    }
+    else
+    {
+        resSectors = PQexecPrepared(conn, "index_sectors", 1, paramValues, paramLengths, paramFormats, 1);
+    }
+    if (PQresultStatus(resSectors) != PGRES_TUPLES_OK)
+    {
+        fprintf(stderr, "index_sectors: SELECT failed: %s", PQerrorMessage(conn));
+        PQclear(resSectors);
+        exit(EXIT_FAILURE);
+    }
+    if (PQftype(resSectors, 0) != PG_OID_INT4)
+    {
+        fprintf(stderr, "Sector value has unexpected type\n");
+        PQclear(resSectors);
+        exit(EXIT_FAILURE);
+    }
+    if (PQftype(resSectors, 1) != PG_OID_INT8)
+    {
+        fprintf(stderr, "Sector value has unexpected type\n");
+        PQclear(resSectors);
+        exit(EXIT_FAILURE);
+    }
+    
+    rankTotalTuples = 0;
+    for (iSector = 0; iSector < PQntuples(resSectors); iSector++)
+    {
+        rankTotalTuples += PGint64(*((uint64_t *)PQgetvalue(resSectors, iSector, 1)));
+    }
+
+    rankStartTime = time(0);
+    for (iSector = 0; iSector <= PQntuples(resSectors); iSector++)
+    {
+        if (iSector > 0)
+        {
+            resPlaces = PQgetResult(conn);
+            if (PQresultStatus(resPlaces) != PGRES_TUPLES_OK)
+            {
+                fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn));
+                PQclear(resPlaces);
+                exit(EXIT_FAILURE);
+            }
+            if (PQftype(resPlaces, 0) != PG_OID_INT8)
+            {
+                fprintf(stderr, "Place_id value has unexpected type\n");
+                PQclear(resPlaces);
+                exit(EXIT_FAILURE);
+            }
+            resNULL = PQgetResult(conn);
+            if (resNULL != NULL)
+            {
+                fprintf(stderr, "Unexpected non-null response\n");
+                exit(EXIT_FAILURE);
+            }
+        }
+
+        if (iSector < PQntuples(resSectors))
+        {
+            sector = PGint32(*((uint32_t *)PQgetvalue(resSectors, iSector, 0)));
+//                fprintf(stderr, "\n Starting sector %d size %ld\n", sector, PGint64(*((uint64_t *)PQgetvalue(resSectors, iSector, 1))));
+
+            // Get all the place_id's for this sector
+            paramRank = PGint32(rank);
+            paramValues[0] = (char *)&paramRank;
+            paramLengths[0] = sizeof(paramRank);
+            paramFormats[0] = 1;
+            paramSector = PGint32(sector);
+            paramValues[1] = (char *)&paramSector;
+            paramLengths[1] = sizeof(paramSector);
+            paramFormats[1] = 1;
+            if (rankTotalTuples-rankCountTuples < num_threads*1000)
+            {
+                // no sectors
+                if (interpolation)
+                {
+                    iResult = PQsendQueryPrepared(conn, "index_nosector_places_osmline", 0, NULL, 0, NULL, 1);
+                }
+                else
+                {
+                    iResult = PQsendQueryPrepared(conn, "index_nosector_places", 1, paramValues, paramLengths, paramFormats, 1);
+                }
+            }
+            else
+            {
+                if (interpolation)
+                {
+                    iResult = PQsendQueryPrepared(conn, "index_sector_places", 2, paramValues, paramLengths, paramFormats, 1);
+                }
+                else
+                {
+                    iResult = PQsendQueryPrepared(conn, "index_sector_places_osmline", 1, paramValues, paramLengths, paramFormats, 1);
+                }
+            }
+            if (!iResult)
+            {
+                fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn));
+                PQclear(resPlaces);
+                exit(EXIT_FAILURE);
+            }
+        }
+        if (iSector > 0)
+        {
+            count = 0;
+            rankPerSecond = 0;
+            tuples = PQntuples(resPlaces);
+
+            if (tuples > 0)
+            {
+                // Spawn threads
+                for (i = 0; i < num_threads; i++)
+                {
+                    thread_data[i].res = resPlaces;
+                    thread_data[i].tuples = tuples;
+                    thread_data[i].count = &count;
+                    thread_data[i].count_mutex = &count_mutex;
+                    thread_data[i].writer = writer;
+                    thread_data[i].writer_mutex = &writer_mutex;
+                    if (interpolation)
+                    {
+                        thread_data[i].table = 0;  // use interpolations table
+                    }
+                    else
+                    {
+                        thread_data[i].table = 1;  // use placex table
+                    }
+                    pthread_create(&thread_data[i].thread, NULL, &nominatim_indexThread, (void *)&thread_data[i]);
+                }
+
+                // Monitor threads to give user feedback
+                sleepcount = 0;
+                while (count < tuples)
+                {
+                    usleep(1000);
+
+                    // Aim for one update per second
+                    if (sleepcount++ > 500)
+                    {
+                        rankPerSecond = ((float)rankCountTuples + (float)count) / MAX(difftime(time(0), rankStartTime),1);
+                        fprintf(stderr, "  Done %i in %i @ %f per second - Rank %i ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, rank, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond);
+                        sleepcount = 0;
+                    }
+                }
+
+                // Wait for everything to finish
+                for (i = 0; i < num_threads; i++)
+                {
+                    pthread_join(thread_data[i].thread, NULL);
+                }
+
+                rankCountTuples += tuples;
+            }
+
+            // Finished sector
+            rankPerSecond = (float)rankCountTuples / MAX(difftime(time(0), rankStartTime),1);
+            fprintf(stderr, "  Done %i in %i @ %f per second - ETA (seconds): %f\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond, ((float)(rankTotalTuples - rankCountTuples))/rankPerSecond);
+
+            PQclear(resPlaces);
+        }
+        if (rankTotalTuples-rankCountTuples < num_threads*20 && iSector < PQntuples(resSectors))
+        {
+            iSector = PQntuples(resSectors) - 1;
+        }
+    }
+    // Finished rank
+    fprintf(stderr, "\r  Done %i in %i @ %f per second - FINISHED\n\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond);
+
+    PQclear(resSectors);
+    
+    
+}
+
+void nominatim_index(int rank_min, int rank_max, int num_threads, const char *conninfo, const char *structuredoutputfile)
+{
+    struct index_thread_data * thread_data;
+
+    PGconn *conn;
+    PGresult * res;
+
+    int rank;
+    
+    int i;
 
     xmlTextWriterPtr writer;
     pthread_mutex_t writer_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -182,324 +391,22 @@ void nominatim_index(int rank_min, int rank_max, int num_threads, const char *co
         nominatim_exportCreatePreparedQueries(thread_data[i].conn);
     }
 
-    // Create the output file
-    writer = NULL;
-    if (structuredoutputfile)
-    {
-        writer = nominatim_exportXMLStart(structuredoutputfile);
-    }
 
     fprintf(stderr, "Starting indexing rank (%i to %i) using %i threads\n", rank_min, rank_max, num_threads);
 
-    // first for the placex table
     for (rank = rank_min; rank <= rank_max; rank++)
     {
         // OSMLINE: do reindexing (=> reparenting) for interpolation lines at rank 30, but before all other objects of rank 30
         // reason: houses (rank 30) depend on the updated interpolation line, when reparenting (see placex_update in functions.sql)
         if (rank == 30)
         {
-            fprintf(stderr, "Starting indexing interpolation lines (location_property_osmline)\n");
-            rankCountTuples = 0;
-            rankTotalTuples = 0;
-            resSectors = PQexecPrepared(conn, "index_sectors_osmline", 0, NULL, 0, NULL, 1);
-            if (PQresultStatus(resSectors) != PGRES_TUPLES_OK)
-            {
-                fprintf(stderr, "index_sectors_osmline: SELECT failed: %s", PQerrorMessage(conn));
-                PQclear(resSectors);
-                exit(EXIT_FAILURE);
-            }
-            if (PQftype(resSectors, 0) != PG_OID_INT4)
-            {
-                fprintf(stderr, "Sector value has unexpected type\n");
-                PQclear(resSectors);
-                exit(EXIT_FAILURE);
-            }
-            if (PQftype(resSectors, 1) != PG_OID_INT8)
-            {
-                fprintf(stderr, "Sector value has unexpected type\n");
-                PQclear(resSectors);
-                exit(EXIT_FAILURE);
-            }
-            rankStartTime = time(0);
-            for (iSector = 0; iSector < PQntuples(resSectors); iSector++)
-            {
-                rankTotalTuples += PGint64(*((uint64_t *)PQgetvalue(resSectors, iSector, 1)));
-            }
-            // do it only if tuples with indexed_status > 0 were found in osmline
-            int nTuples = PQntuples(resSectors);
-            if (nTuples > 0)
-            {
-                for (iSector = 0; iSector <= nTuples; iSector++)
-                {
-                    if (iSector > 0)
-                    {
-                        resPlaces = PQgetResult(conn);
-                        if (PQresultStatus(resPlaces) != PGRES_TUPLES_OK)
-                        {
-                            fprintf(stderr, "index_sector_places: SELECT failed: %s\n", PQerrorMessage(conn));
-                            PQclear(resPlaces);
-                            exit(EXIT_FAILURE);
-                        }
-                        if (PQftype(resPlaces, 0) != PG_OID_INT8)
-                        {
-                            fprintf(stderr, "Place_id value has unexpected type\n");
-                            PQclear(resPlaces);
-                            exit(EXIT_FAILURE);
-                        }
-                        resNULL = PQgetResult(conn);
-                        if (resNULL != NULL)
-                        {
-                            fprintf(stderr, "Unexpected non-null response\n");
-                            exit(EXIT_FAILURE);
-                        }
-                    }
-
-                    if (iSector < nTuples)
-                    {
-                        sector = PGint32(*((uint32_t *)PQgetvalue(resSectors, iSector, 0)));
-            //                fprintf(stderr, "\n Starting sector %d size %ld\n", sector, PGint64(*((uint64_t *)PQgetvalue(resSectors, iSector, 1))));
-
-                        // Get all the place_id's for this sector
-                        paramSector = PGint32(sector);
-                        paramValues[0] = (char *)&paramSector;
-                        paramLengths[0] = sizeof(paramSector);
-                        paramFormats[0] = 1;
-                        if (rankTotalTuples-rankCountTuples < num_threads*1000)
-                        {
-                            // no sectors
-                            iResult = PQsendQueryPrepared(conn, "index_nosector_places_osmline", 0, NULL, 0, NULL, 1);
-                        }
-                        else
-                        {
-                            iResult = PQsendQueryPrepared(conn, "index_sector_places_osmline", 1, paramValues, paramLengths, paramFormats, 1);
-                        }
-                        if (!iResult)
-                        {
-                            fprintf(stderr, "index_sector_places_osmline: SELECT failed: %s", PQerrorMessage(conn));
-                            PQclear(resPlaces);
-                            exit(EXIT_FAILURE);
-                        }
-                    }
-                    if (iSector > 0)
-                    {
-                        count = 0;
-                        rankPerSecond = 0;
-                        tuples = PQntuples(resPlaces);
-
-                        if (tuples > 0)
-                        {
-                            // Spawn threads
-                            for (i = 0; i < num_threads; i++)
-                            {
-                                thread_data[i].res = resPlaces;
-                                thread_data[i].tuples = tuples;
-                                thread_data[i].count = &count;
-                                thread_data[i].count_mutex = &count_mutex;
-                                thread_data[i].writer = writer;
-                                thread_data[i].writer_mutex = &writer_mutex;
-                                thread_data[i].table = 0; // use osmline table
-                                pthread_create(&thread_data[i].thread, NULL, &nominatim_indexThread, (void *)&thread_data[i]);
-                            }
-                            // Monitor threads to give user feedback
-                            sleepcount = 0;
-                            while (count < tuples)
-                            {
-                                usleep(1000);
-
-                                // Aim for one update per second
-                                if (sleepcount++ > 500)
-                                {
-                                    rankPerSecond = ((float)rankCountTuples + (float)count) / MAX(difftime(time(0), rankStartTime),1);
-                                    fprintf(stderr, "  Done %i in %i @ %f per second - Interpolation Lines ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, ((float)(rankTotalTuples - (rankCountTuples + count)))/(float)rankPerSecond);
-                                    sleepcount = 0;
-                                }
-                            }
-
-                            // Wait for everything to finish
-                            for (i = 0; i < num_threads; i++)
-                            {
-                                pthread_join(thread_data[i].thread, NULL);
-                            }
-                            rankCountTuples += tuples;
-                        }
-                        // Finished sector
-                        rankPerSecond = (float)rankCountTuples / MAX(difftime(time(0), rankStartTime),1);
-                        fprintf(stderr, "  Done %i in %i @ %f per second - ETA (seconds): %f\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond, ((float)(rankTotalTuples - rankCountTuples))/rankPerSecond);
-                        PQclear(resPlaces);
-                    }
-                    if (rankTotalTuples-rankCountTuples < num_threads*20 && iSector < nTuples)
-                    {
-                        iSector = nTuples - 1;
-                    }
-                }
-                PQclear(resSectors);
-            }
-            // Finished rank
-            fprintf(stderr, "\r  Done %i tuples in %i seconds- FINISHED\n", rankCountTuples,(int)(difftime(time(0), rankStartTime)));
-            if (writer)
-            {
-                nominatim_exportXMLEnd(writer);
-            }
-        }
-        fprintf(stderr, "Starting rank %d\n", rank);
-        rankCountTuples = 0;
-        rankPerSecond = 0;
-
-        paramRank = PGint32(rank);
-        paramValues[0] = (char *)&paramRank;
-        paramLengths[0] = sizeof(paramRank);
-        paramFormats[0] = 1;
-//        if (rank < 16)
-//            resSectors = PQexecPrepared(conn, "index_nosectors", 1, paramValues, paramLengths, paramFormats, 1);
-//        else
-        resSectors = PQexecPrepared(conn, "index_sectors", 1, paramValues, paramLengths, paramFormats, 1);
-
-        if (PQresultStatus(resSectors) != PGRES_TUPLES_OK)
-        {
-            fprintf(stderr, "index_sectors: SELECT failed: %s", PQerrorMessage(conn));
-            PQclear(resSectors);
-            exit(EXIT_FAILURE);
-        }
-        if (PQftype(resSectors, 0) != PG_OID_INT4)
-        {
-            fprintf(stderr, "Sector value has unexpected type\n");
-            PQclear(resSectors);
-            exit(EXIT_FAILURE);
-        }
-        if (PQftype(resSectors, 1) != PG_OID_INT8)
-        {
-            fprintf(stderr, "Sector value has unexpected type\n");
-            PQclear(resSectors);
-            exit(EXIT_FAILURE);
-        }
-        
-        rankTotalTuples = 0;
-        for (iSector = 0; iSector < PQntuples(resSectors); iSector++)
-        {
-            rankTotalTuples += PGint64(*((uint64_t *)PQgetvalue(resSectors, iSector, 1)));
-        }
-
-        rankStartTime = time(0);
-
-        for (iSector = 0; iSector <= PQntuples(resSectors); iSector++)
-        {
-            if (iSector > 0)
-            {
-                resPlaces = PQgetResult(conn);
-                if (PQresultStatus(resPlaces) != PGRES_TUPLES_OK)
-                {
-                    fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn));
-                    PQclear(resPlaces);
-                    exit(EXIT_FAILURE);
-                }
-                if (PQftype(resPlaces, 0) != PG_OID_INT8)
-                {
-                    fprintf(stderr, "Place_id value has unexpected type\n");
-                    PQclear(resPlaces);
-                    exit(EXIT_FAILURE);
-                }
-                resNULL = PQgetResult(conn);
-                if (resNULL != NULL)
-                {
-                    fprintf(stderr, "Unexpected non-null response\n");
-                    exit(EXIT_FAILURE);
-                }
-            }
-
-            if (iSector < PQntuples(resSectors))
-            {
-                sector = PGint32(*((uint32_t *)PQgetvalue(resSectors, iSector, 0)));
-//                fprintf(stderr, "\n Starting sector %d size %ld\n", sector, PGint64(*((uint64_t *)PQgetvalue(resSectors, iSector, 1))));
-
-                // Get all the place_id's for this sector
-                paramRank = PGint32(rank);
-                paramValues[0] = (char *)&paramRank;
-                paramLengths[0] = sizeof(paramRank);
-                paramFormats[0] = 1;
-                paramSector = PGint32(sector);
-                paramValues[1] = (char *)&paramSector;
-                paramLengths[1] = sizeof(paramSector);
-                paramFormats[1] = 1;
-                if (rankTotalTuples-rankCountTuples < num_threads*1000)
-                {
-                    iResult = PQsendQueryPrepared(conn, "index_nosector_places", 1, paramValues, paramLengths, paramFormats, 1);
-                }
-                else
-                {
-                    iResult = PQsendQueryPrepared(conn, "index_sector_places", 2, paramValues, paramLengths, paramFormats, 1);
-                }
-                if (!iResult)
-                {
-                    fprintf(stderr, "index_sector_places: SELECT failed: %s", PQerrorMessage(conn));
-                    PQclear(resPlaces);
-                    exit(EXIT_FAILURE);
-                }
-            }
-
-            if (iSector > 0)
-            {
-                count = 0;
-                rankPerSecond = 0;
-                tuples = PQntuples(resPlaces);
-
-                if (tuples > 0)
-                {
-                    // Spawn threads
-                    for (i = 0; i < num_threads; i++)
-                    {
-                        thread_data[i].res = resPlaces;
-                        thread_data[i].tuples = tuples;
-                        thread_data[i].count = &count;
-                        thread_data[i].count_mutex = &count_mutex;
-                        thread_data[i].writer = writer;
-                        thread_data[i].writer_mutex = &writer_mutex;
-                        thread_data[i].table = 1;  // use placex table
-                        pthread_create(&thread_data[i].thread, NULL, &nominatim_indexThread, (void *)&thread_data[i]);
-                    }
-
-                    // Monitor threads to give user feedback
-                    sleepcount = 0;
-                    while (count < tuples)
-                    {
-                        usleep(1000);
-
-                        // Aim for one update per second
-                        if (sleepcount++ > 500)
-                        {
-                            rankPerSecond = ((float)rankCountTuples + (float)count) / MAX(difftime(time(0), rankStartTime),1);
-                            fprintf(stderr, "  Done %i in %i @ %f per second - Rank %i ETA (seconds): %f\n", (rankCountTuples + count), (int)(difftime(time(0), rankStartTime)), rankPerSecond, rank, ((float)(rankTotalTuples - (rankCountTuples + count)))/rankPerSecond);
-                            sleepcount = 0;
-                        }
-                    }
-
-                    // Wait for everything to finish
-                    for (i = 0; i < num_threads; i++)
-                    {
-                        pthread_join(thread_data[i].thread, NULL);
-                    }
-
-                    rankCountTuples += tuples;
-                }
-
-                // Finished sector
-                rankPerSecond = (float)rankCountTuples / MAX(difftime(time(0), rankStartTime),1);
-                fprintf(stderr, "  Done %i in %i @ %f per second - ETA (seconds): %f\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond, ((float)(rankTotalTuples - rankCountTuples))/rankPerSecond);
-
-                PQclear(resPlaces);
-            }
-            if (rankTotalTuples-rankCountTuples < num_threads*20 && iSector < PQntuples(resSectors))
-            {
-                iSector = PQntuples(resSectors) - 1;
-            }
+            run_indexing(rank, 1, conn, num_threads, thread_data, structuredoutputfile);
         }
-        // Finished rank
-        fprintf(stderr, "\r  Done %i in %i @ %f per second - FINISHED                      \n\n", rankCountTuples, (int)(difftime(time(0), rankStartTime)), rankPerSecond);
-
-        PQclear(resSectors);
+        run_indexing(rank, 0, conn, num_threads, thread_data, structuredoutputfile);
     }
-    
+            
 
-    if (rank_max == 30)
+    if (rank == 30)
     {
         // Close all connections
         for (i = 0; i < num_threads; i++)
index 80763eaae53c90855d96e18523b12baf2a2b76f3..9b095ce7b9636067c2df0c1b249d1a114a572845 100644 (file)
@@ -1090,13 +1090,12 @@ BEGIN
   END IF;
   
   IF OLD.indexed_status = 2 and NEW.indexed_status=0 THEN
-    -- do the reparenting: (finally here, so that ALL places in placex, that are needed for reparenting, are up to date)
+    -- do the reparenting: (finally here, because ALL places in placex, that are needed for reparenting, need to be up to date)
     -- (the osm interpolationline in location_property_osmline was marked for reparenting in placex_insert/placex_delete with index_status = 2 
     -- => index.c: sets index_status back to 0
     -- => triggers this function)
     place_centroid := ST_PointOnSurface(NEW.linegeo);
-    -- mark descendants for reparenting
-    UPDATE placex SET indexed_status = 2 WHERE parent_place_id = OLD.place_id;
+    -- marking descendants for reparenting is not needed, because there are actually no descendants for interpolation lines
     NEW.parent_place_id = get_interpolation_parent(NEW.osm_id, NEW.street, null, NEW.partition, place_centroid, NEW.linegeo); -- addr_place (3rd param) is not necessarily needed
     return NEW;
   END IF;
@@ -1156,14 +1155,6 @@ BEGIN
   END IF;
 
   IF NEW.indexed_status != 0 OR OLD.indexed_status = 0 THEN
-  
-    -- if a node(=>house), which is part of a interpolation line, changes (e.g. the street attribute) => mark this line for reparenting 
-    -- (already here, because interpolation lines are reindexed before nodes, so in the second call it would be too late)
-    -- needed for test case features/db/import: Scenario: addr:street added to housenumbers
-    IF NEW.osm_type='N' and NEW.class='place' and NEW.type='house' THEN
-        -- Is this node part of an interpolation line? search for it in location_property_osmline and mark the interpolation line for reparenting
-        update location_property_osmline p set indexed_status = 2 from planet_osm_ways w where p.linegeo && NEW.geometry and p.osm_id = w.id and NEW.osm_id = any(w.nodes);
-    END IF;
     RETURN NEW;
   END IF;
 
@@ -1906,7 +1897,7 @@ BEGIN
   UPDATE placex set indexed_status = 100 where osm_type = OLD.osm_type and osm_id = OLD.osm_id and class = OLD.class and type = OLD.type;
 
   -- interpolations are special
-  IF OLD.class = 'place' and OLD.type = 'houses' THEN
+  IF OLD.osm_type='W' and OLD.class = 'place' and OLD.type = 'houses' THEN
     UPDATE location_property_osmline set indexed_status = 100 where osm_id = OLD.osm_id; -- osm_id = wayid (=old.osm_id)
   END IF;
 
@@ -1931,7 +1922,6 @@ BEGIN
 
   --DEBUG: RAISE WARNING '-----------------------------------------------------------------------------------';
   --DEBUG: RAISE WARNING 'place_insert: % % % % %',NEW.osm_type,NEW.osm_id,NEW.class,NEW.type,st_area(NEW.geometry);
-  RAISE WARNING 'X3366 - place_isnert';
   -- filter wrong tupels
   IF ST_IsEmpty(NEW.geometry) OR NOT ST_IsValid(NEW.geometry) OR ST_X(ST_Centroid(NEW.geometry))::text in ('NaN','Infinity','-Infinity') OR ST_Y(ST_Centroid(NEW.geometry))::text in ('NaN','Infinity','-Infinity') THEN  
     INSERT INTO import_polygon_error values (NEW.osm_type, NEW.osm_id, NEW.class, NEW.type, NEW.name, NEW.country_code, 
@@ -1960,12 +1950,6 @@ BEGIN
     
     -- To paraphrase, if there isn't an existing item
     IF existingline.osm_id IS NULL THEN
-      IF existing.osm_type IS NOT NULL THEN
-        -- pathological case caused by the triggerless copy into place during initial import
-        -- force delete even for large areas, it will be reinserted later
-        UPDATE place set geometry = ST_SetSRID(ST_Point(0,0), 4326) where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type;
-        DELETE from place where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type;
-      END IF;
       -- insert new line into location_property_osmline, use function insert_osmline
       i = insert_osmline(NEW.osm_id, NEW.housenumber, NEW.street, NEW.addr_place, NEW.postcode, NEW.country_code, NEW.geometry);
       RETURN NEW;
@@ -2002,7 +1986,6 @@ BEGIN
     
     -- for interpolations invalidate all nodes on the line
     update placex p set indexed_status = 2 from planet_osm_ways w where w.id = NEW.osm_id and p.osm_type = 'N' and p.osm_id = any(w.nodes);
-    RAISE WARNING 'X3399 - updated nodes of interpolation line';
     RETURN NULL;
   
   ELSE -- insert to placex
@@ -2170,6 +2153,7 @@ BEGIN
         admin_level = NEW.admin_level,
         geometry = NEW.geometry
         where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type;
+        
 
       IF NEW.class in ('place','boundary') AND NEW.type in ('postcode','postal_code') THEN
           IF NEW.postcode IS NULL THEN
@@ -2195,6 +2179,14 @@ BEGIN
         indexed_status = 2,    
         geometry = NEW.geometry
         where place_id = existingplacex.place_id;
+        
+      -- if a node(=>house), which is part of a interpolation line, changes (e.g. the street attribute) => mark this line for reparenting 
+      -- (already here, because interpolation lines are reindexed before nodes, so in the second call it would be too late)
+      -- needed for test case features/db/import: Scenario: addr:street added to housenumbers
+      IF NEW.osm_type='N' and NEW.class='place' and NEW.type='house' THEN
+          -- Is this node part of an interpolation line? search for it in location_property_osmline and mark the interpolation line for reparenting
+          update location_property_osmline p set indexed_status = 2 from planet_osm_ways w where p.linegeo && NEW.geometry and p.osm_id = w.id and NEW.osm_id = any(w.nodes);
+      END IF;
 
     END IF;
 
@@ -2202,7 +2194,7 @@ BEGIN
     RETURN NULL;
   END IF;
 
-END; 
+END;
 $$ LANGUAGE plpgsql;
 
 
index 76a4324ff91868b5d2ecf3f2af8f4dc8e1e5851e..b4aecdd9b72b5fb53fcee6ba017ec074846e4588 100644 (file)
@@ -84,6 +84,7 @@ GRANT SELECT ON location_property_aux TO "{www-user}";
 CREATE TABLE location_property_tiger (linegeo GEOMETRY, place_id BIGINT, partition INTEGER, parent_place_id BIGINT, startnumber INTEGER, endnumber INTEGER, interpolationtype TEXT, postcode TEXT);
 GRANT SELECT ON location_property_tiger TO "{www-user}";
 
+drop table if exists location_property_osmline;
 CREATE TABLE location_property_osmline (
     linegeo GEOMETRY,
     place_id BIGINT NOT NULL,
@@ -99,9 +100,11 @@ CREATE TABLE location_property_osmline (
     calculated_country_code VARCHAR(2),
     geometry_sector INTEGER,
     indexed_status INTEGER,
-    indexed_date TIMESTAMP);
-CREATE UNIQUE INDEX idx_osmline_place_id ON location_property_osmline (place_id) {ts:search-index};
-CREATE INDEX idx_osmline_parent_place_id ON location_property_osmline (parent_place_id) {ts:search-index};
+    indexed_date TIMESTAMP){ts:search-data};
+CREATE UNIQUE INDEX idx_osmline_place_id ON location_property_osmline USING BTREE (place_id) {ts:search-index};
+CREATE INDEX idx_osmline_parent_place_id ON location_property_osmline USING BTREE (parent_place_id) {ts:search-index};
+CREATE INDEX idx_osmline_geometry_sector ON location_property_osmline USING BTREE (geometry_sector) {ts:address-index};
+CREATE INDEX idx_osmline_linegeo ON location_property_osmline USING GIST (linegeo) {ts:search-index};
 GRANT SELECT ON location_property_osmline TO "{www-user}";
 
 drop table IF EXISTS search_name;
index 0dcb12bdbb978bc18a4dc71edda737f416e1810e..c282d73a27ac84652116da2ecc8cbc762adcbc81 100644 (file)
@@ -18,7 +18,10 @@ Feature: Reverse geocoding
           | xml    | 4
         When looking up coordinates 53.9788769,13.0830313
         And results contain valid boundingboxes
-
+    
+    Scenario: Reverse geocoding for odd interpolated housenumber
+    
+    Scenario: Reverse geocoding for even interpolated housenumber
 
     @Tiger
     Scenario: TIGER house number
index 4075ba47b531a1392b4e3a4c75aa55c1aa88eec6..ac72f852c9b009869b1fd13ca9085b38323d69c6 100644 (file)
@@ -37,7 +37,6 @@ Feature: Update of address interpolations
           | object | parent_place_id | startnumber | endnumber
           | W10    | W3              | 2           | 6
 
-    @Fail
     Scenario: addr:street added to housenumbers
       Given the scene parallel-road
       And the place nodes