]> git.openstreetmap.org Git - nominatim.git/commitdiff
Merge remote-tracking branch 'upstream/master'
authorSarah Hoffmann <lonvia@denofr.de>
Sun, 5 Oct 2014 20:16:43 +0000 (22:16 +0200)
committerSarah Hoffmann <lonvia@denofr.de>
Sun, 5 Oct 2014 20:16:43 +0000 (22:16 +0200)
1  2 
sql/functions.sql
utils/setup.php

diff --combined sql/functions.sql
index 54f46cfe933b64fbd5f33dfc9a6ac336ade93539,dc69280446a333d4352175049c53c31d69c1f130..72e52130c9baf76a67a80ba6b3b192ae04bea7e8
@@@ -791,7 -791,7 +791,7 @@@ LANGUAGE plpgsql
  CREATE OR REPLACE FUNCTION create_interpolation(wayid BIGINT, interpolationtype TEXT) RETURNS INTEGER
    AS $$
  DECLARE
-   
    newpoints INTEGER;
    waynodes BIGINT[];
    nodeid BIGINT;
    originalnumberrange INTEGER;
    housenum INTEGER;
    linegeo GEOMETRY;
+   splitline GEOMETRY;
+   sectiongeo GEOMETRY;
    search_place_id BIGINT;
    defpostalcode TEXT;
  
-   havefirstpoint BOOLEAN;
-   linestr TEXT;
  BEGIN
+   IF interpolationtype = 'odd' OR interpolationtype = 'even' THEN
+     stepsize := 2;
+   ELSEIF interpolationtype = 'all' THEN
+     stepsize := 1;
+   ELSEIF interpolationtype ~ '^\d+$' THEN
+     stepsize := interpolationtype::INTEGER;
+   ELSE
+     RETURN 0;
+   END IF;
+   select nodes from planet_osm_ways where id = wayid INTO waynodes;
+   IF array_upper(waynodes, 1) IS NULL THEN
+     RETURN 0;
+   END IF;
+   select postcode, geometry from placex where osm_type = 'W' and osm_id = wayid 
+     INTO defpostalcode, linegeo;
+   IF ST_GeometryType(linegeo) != 'ST_LineString' THEN
+     RETURN 0;
+   END IF;
+   startnumber := NULL;
    newpoints := 0;
-   IF interpolationtype = 'odd' OR interpolationtype = 'even' OR interpolationtype = 'all' THEN
-     select postcode from placex where osm_type = 'W' and osm_id = wayid INTO defpostalcode;
-     select nodes from planet_osm_ways where id = wayid INTO waynodes;
- --RAISE WARNING 'interpolation % % %',wayid,interpolationtype,waynodes;
-     IF array_upper(waynodes, 1) IS NOT NULL THEN
-       havefirstpoint := false;
-       FOR nodeidpos in 1..array_upper(waynodes, 1) LOOP
-         -- If there is a place of a type other than place/house, use that because
-         -- it is guaranteed to be the original node. For place/house types use the
-         -- one with the smallest id because the original node was created first.
-         -- Ignore all nodes marked for deletion. (Might happen when the type changes.)
-         select place_id from placex where osm_type = 'N' and osm_id = waynodes[nodeidpos]::BIGINT and indexed_status < 100 order by (type = 'house'),place_id limit 1 INTO search_place_id;
-         IF search_place_id IS NULL THEN
-           -- if no such node exists, create a record of the right type
-           select * from placex where osm_type = 'N' and osm_id = waynodes[nodeidpos]::BIGINT and type = 'house' limit 1 INTO nextnode;
-           select ST_SetSRID(ST_Point(lon::float/10000000,lat::float/10000000),4326) from planet_osm_nodes where id = waynodes[nodeidpos] INTO nextnode.geometry;
-           IF nextnode.geometry IS NULL THEN
-             -- we don't have any information about this point, most likely
-             -- because an excerpt was updated and the node never imported
-             -- because the interpolation is outside the region of the excerpt.
-             -- Give up.
-             RETURN newpoints;
+   FOR nodeidpos in 1..array_upper(waynodes, 1) LOOP
+     -- If there is a place of a type other than place/house, use that because
+     -- it is guaranteed to be the original node. For place/house types use the
+     -- one with the smallest id because the original node was created first.
+     -- Ignore all nodes marked for deletion. (Might happen when the type changes.)
+     select place_id from placex where osm_type = 'N' and osm_id = waynodes[nodeidpos]::BIGINT and indexed_status < 100 order by (type = 'house'),place_id limit 1 INTO search_place_id;
+     IF search_place_id IS NOT NULL THEN
+       select * from placex where place_id = search_place_id INTO nextnode;
+         IF nodeidpos < array_upper(waynodes, 1) THEN
+           -- Make sure that the point is actually on the line. That might
+           -- be a bit paranoid but ensures that the algorithm still works
+           -- should osm2pgsql attempt to repair geometries.
+           splitline := split_line_on_node(linegeo, nextnode.geometry);
+           sectiongeo := ST_GeometryN(splitline, 1);
+           IF ST_GeometryType(ST_GeometryN(splitline, 2)) = 'ST_LineString' THEN
+             linegeo := ST_GeometryN(splitline, 2);
            END IF;
          ELSE
-           select * from placex where place_id = search_place_id INTO nextnode;
+           sectiongeo = linegeo;
          END IF;
+         endnumber := substring(nextnode.housenumber,'[0-9]+')::integer;
  
- --RAISE WARNING 'interpolation node % % % ',nextnode.housenumber,ST_X(nextnode.geometry),ST_Y(nextnode.geometry);
-       
-         IF havefirstpoint THEN
-           -- add point to the line string
-           linestr := linestr||','||ST_X(nextnode.geometry)||' '||ST_Y(nextnode.geometry);
-           endnumber := ('0'||substring(nextnode.housenumber,'[0-9]+'))::integer;
-           IF startnumber IS NOT NULL and startnumber > 0 AND endnumber IS NOT NULL and endnumber > 0 AND @(startnumber - endnumber) < 1000 THEN
- --RAISE WARNING 'interpolation end % % ',nextnode.place_id,endnumber;
-             IF startnumber != endnumber THEN
-               linestr := linestr || ')';
- --RAISE WARNING 'linestr %',linestr;
-               linegeo := ST_GeomFromText(linestr,4326);
-               linestr := 'LINESTRING('||ST_X(nextnode.geometry)||' '||ST_Y(nextnode.geometry);
-               IF (startnumber > endnumber) THEN
-                 housenum := endnumber;
-                 endnumber := startnumber;
-                 startnumber := housenum;
-                 linegeo := ST_Reverse(linegeo);
-               END IF;
-               orginalstartnumber := startnumber;
-               originalnumberrange := endnumber - startnumber;
- -- Too much broken data worldwide for this test to be worth using
- --              IF originalnumberrange > 500 THEN
- --                RAISE WARNING 'Number block of % while processing % %', originalnumberrange, prevnode, nextnode;
- --              END IF;
-               IF (interpolationtype = 'odd' AND startnumber%2 = 0) OR (interpolationtype = 'even' AND startnumber%2 = 1) THEN
-                 startnumber := startnumber + 1;
-                 stepsize := 2;
-               ELSE
-                 IF (interpolationtype = 'odd' OR interpolationtype = 'even') THEN
-                   startnumber := startnumber + 2;
-                   stepsize := 2;
-                 ELSE -- everything else assumed to be 'all'
-                   startnumber := startnumber + 1;
-                   stepsize := 1;
-                 END IF;
-               END IF;
-               endnumber := endnumber - 1;
-               delete from placex where osm_type = 'N' and osm_id = prevnode.osm_id and type = 'house' and place_id != prevnode.place_id;
-               FOR housenum IN startnumber..endnumber BY stepsize LOOP
-                 -- this should really copy postcodes but it puts a huge burdon on the system for no big benefit
-                 -- ideally postcodes should move up to the way
-                 insert into placex (osm_type, osm_id, class, type, admin_level, housenumber, street, addr_place, isin, postcode,
-                   country_code, parent_place_id, rank_address, rank_search, indexed_status, geometry)
-                   values ('N',prevnode.osm_id, 'place', 'house', prevnode.admin_level, housenum, prevnode.street, prevnode.addr_place, prevnode.isin, coalesce(prevnode.postcode, defpostalcode),
-                   prevnode.country_code, prevnode.parent_place_id, prevnode.rank_address, prevnode.rank_search, 1, ST_LineInterpolatePoint(linegeo, (housenum::float-orginalstartnumber::float)/originalnumberrange::float));
-                 newpoints := newpoints + 1;
- --RAISE WARNING 'interpolation number % % ',prevnode.place_id,housenum;
-               END LOOP;
-             END IF;
-             havefirstpoint := false;
+         IF startnumber IS NOT NULL AND endnumber IS NOT NULL
+            AND @(startnumber - endnumber) < 1000 AND startnumber != endnumber
+            AND ST_GeometryType(linegeo) = 'ST_LineString' THEN
+           IF (startnumber > endnumber) THEN
+             housenum := endnumber;
+             endnumber := startnumber;
+             startnumber := housenum;
+             sectiongeo := ST_Reverse(sectiongeo);
            END IF;
-         END IF;
+           orginalstartnumber := startnumber;
+           originalnumberrange := endnumber - startnumber;
  
-         IF NOT havefirstpoint THEN
-           startnumber := ('0'||substring(nextnode.housenumber,'[0-9]+'))::integer;
-           IF startnumber IS NOT NULL AND startnumber > 0 THEN
-             havefirstpoint := true;
-             linestr := 'LINESTRING('||ST_X(nextnode.geometry)||' '||ST_Y(nextnode.geometry);
-             prevnode := nextnode;
+           startnumber := startnumber + stepsize;
+           -- correct for odd/even
+           IF (interpolationtype = 'odd' AND startnumber%2 = 0) OR (interpolationtype = 'even' AND startnumber%2 = 1) THEN
+             startnumber := startnumber - 1;
            END IF;
- --RAISE WARNING 'interpolation start % % ',nextnode.place_id,startnumber;
+           endnumber := endnumber - 1;
+           delete from placex where osm_type = 'N' and osm_id = prevnode.osm_id and type = 'house' and place_id != prevnode.place_id;
+           FOR housenum IN startnumber..endnumber BY stepsize LOOP
+             -- this should really copy postcodes but it puts a huge burden on
+             -- the system for no big benefit ideally postcodes should move up to the way
+             insert into placex (osm_type, osm_id, class, type, admin_level,
+               housenumber, street, addr_place, isin, postcode,
+               country_code, parent_place_id, rank_address, rank_search,
+               indexed_status, geometry)
+               values ('N', prevnode.osm_id, 'place', 'house', prevnode.admin_level,
+               housenum, prevnode.street, prevnode.addr_place, prevnode.isin, coalesce(prevnode.postcode, defpostalcode),
+               prevnode.country_code, prevnode.parent_place_id, prevnode.rank_address, prevnode.rank_search,
+               1, ST_LineInterpolatePoint(sectiongeo, (housenum::float-orginalstartnumber::float)/originalnumberrange::float));
+             newpoints := newpoints + 1;
+ --RAISE WARNING 'interpolation number % % ',prevnode.place_id,housenum;
+           END LOOP;
          END IF;
-       END LOOP;
+         startnumber := substring(nextnode.housenumber,'[0-9]+')::integer;
+         prevnode := nextnode;
      END IF;
-   END IF;
+   END LOOP;
  
  --RAISE WARNING 'interpolation points % ',newpoints;
  
@@@ -936,11 -922,6 +922,11 @@@ DECLAR
  BEGIN
    --DEBUG: RAISE WARNING '% %',NEW.osm_type,NEW.osm_id;
  
 +  -- remove operator tag for most places, messes too much with search_name indexes
 +  IF NEW.class not in ('amenity', 'shop') THEN
 +    NEW.name := delete(NEW.name, 'operator');
 +  END IF;
 +
    -- just block these
    IF NEW.class in ('landuse','natural') and NEW.name is null THEN
  --    RAISE WARNING 'empty landuse %',NEW.osm_id;
@@@ -2074,11 -2055,6 +2060,11 @@@ BEGI
      --DEBUG: RAISE WARNING '%', existingplacex;
    END IF;
  
 +  -- remove operator tag for most places, messes too much with search_name indexes
 +  IF NEW.class not in ('amenity', 'shop') THEN
 +    NEW.name := delete(NEW.name, 'operator');
 +  END IF;
 +
    -- Just block these - lots and pointless
    IF NEW.class in ('landuse','natural') and NEW.name is null THEN
      -- if the name tag was removed, older versions might still be lurking in the place table
  
    END IF;
  
 +  -- refuse to update multiplpoygons with too many objects, too much of a performance hit
 +  IF ST_NumGeometries(NEW.geometry) > 2000 THEN
 +    RAISE WARNING 'Dropping update of % % because of geometry complexity.', NEW.osm_type, NEW.osm_id;
 +    RETURN NULL;
 +  END IF;
 +
    IF coalesce(existing.name::text, '') != coalesce(NEW.name::text, '')
       OR coalesce(existing.extratags::text, '') != coalesce(NEW.extratags::text, '')
       OR coalesce(existing.housenumber, '') != coalesce(NEW.housenumber, '')
diff --combined utils/setup.php
index e588bb084a5ff285e60e62ee38be4978eada8843,c07bccefc949664b0cff92a327bbe88b4f05eac6..cece86867417969914b5137a4bdf1d156419b28a
@@@ -89,6 -89,8 +89,8 @@@
        $aDSNInfo = DB::parseDSN(CONST_Database_DSN);
        if (!isset($aDSNInfo['port']) || !$aDSNInfo['port']) $aDSNInfo['port'] = 5432;
  
+       $fPostgisVersion = (float) CONST_Postgis_Version;
        if ($aCMDResult['create-db'] || $aCMDResult['all'])
        {
                echo "Create DB\n";
                        pgsqlRunScript('CREATE EXTENSION hstore');
                }
  
-               $fPostgisVersion = (float) CONST_Postgis_Version;
                if ($fPostgisVersion < 2.0) {
                        pgsqlRunScriptFile(CONST_Path_Postgresql_Postgis.'/postgis.sql');
                        pgsqlRunScriptFile(CONST_Path_Postgresql_Postgis.'/spatial_ref_sys.sql');
                {
                        $osm2pgsql .= ' --flat-nodes '.CONST_Osm2pgsql_Flatnode_File;
                }
 +              $osm2pgsql .= ' --tablespace-slim-index ssd --tablespace-main-index ssd --tablespace-main-data ssd --tablespace-slim-data data';
                $osm2pgsql .= ' -lsc -O gazetteer --hstore';
 -              $osm2pgsql .= ' -C '.$iCacheMemory;
 +              $osm2pgsql .= ' -C 25000';
                $osm2pgsql .= ' -P '.$aDSNInfo['port'];
                $osm2pgsql .= ' -d '.$aDSNInfo['database'].' '.$aCMDResult['osm-file'];
                passthruCheckReturn($osm2pgsql);
                if ($aCMDResult['enable-debug-statements']) $sTemplate = str_replace('--DEBUG:', '', $sTemplate);
                if (CONST_Limit_Reindexing) $sTemplate = str_replace('--LIMIT INDEXING:', '', $sTemplate);
                pgsqlRunScript($sTemplate);
+               if ($fPostgisVersion < 2.0) {
+                       echo "Helper functions for postgis < 2.0\n";
+                       $sTemplate = file_get_contents(CONST_BasePath.'/sql/postgis_15_aux.sql');
+               } else {
+                       echo "Helper functions for postgis >= 2.0\n";
+                       $sTemplate = file_get_contents(CONST_BasePath.'/sql/postgis_20_aux.sql');
+               }
+               pgsqlRunScript($sTemplate);
        }
  
        if ($aCMDResult['create-minimal-tables'])
                $sSQL .= "select 'P',nextval('seq_postcodes'),'place','postcode',postcode,calculated_country_code,";
                $sSQL .= "ST_SetSRID(ST_Point(x,y),4326) as geometry from (select calculated_country_code,postcode,";
                $sSQL .= "avg(st_x(st_centroid(geometry))) as x,avg(st_y(st_centroid(geometry))) as y ";
 -              $sSQL .= "from placex where postcode is not null group by calculated_country_code,postcode) as x";
 +              $sSQL .= "from placex where postcode is not null and calculated_country_code not in ('ie') group by calculated_country_code,postcode) as x";
                if (!pg_query($oDB->connection, $sSQL)) fail(pg_last_error($oDB->connection));
  
                $sSQL = "insert into placex (osm_type,osm_id,class,type,postcode,calculated_country_code,geometry) ";
        {
                showUsage($aCMDOptions, true);
        }
+       else
+       {
+               echo "Setup finished.\n";
+       }
  
        function pgsqlRunScriptFile($sFilename)
        {