]> git.openstreetmap.org Git - nominatim.git/commitdiff
Merge remote-tracking branch 'upstream/master'
authorSarah Hoffmann <lonvia@denofr.de>
Thu, 17 Jun 2021 13:30:36 +0000 (15:30 +0200)
committerSarah Hoffmann <lonvia@denofr.de>
Thu, 17 Jun 2021 13:30:36 +0000 (15:30 +0200)
33 files changed:
.github/workflows/ci-tests.yml
docs/admin/Customization.md
docs/admin/Import.md
docs/admin/Migration.md
lib-php/Result.php
lib-php/SearchDescription.php
lib-php/admin/query.php [deleted file]
lib-sql/functions/place_triggers.sql
nominatim/clicmd/refresh.py
nominatim/clicmd/replication.py
nominatim/clicmd/setup.py
nominatim/db/status.py
nominatim/tokenizer/legacy_tokenizer.py
nominatim/tools/database_import.py
nominatim/tools/postcodes.py
test/bdd/db/import/addressing.feature
test/bdd/db/import/country.feature
test/bdd/db/import/interpolation.feature
test/bdd/db/import/linking.feature
test/bdd/db/import/parenting.feature
test/bdd/db/import/postcodes.feature
test/bdd/db/import/search_name.feature
test/bdd/db/query/normalization.feature
test/bdd/db/query/search_simple.feature
test/bdd/db/update/linked_places.feature
test/bdd/db/update/naming.feature
test/bdd/steps/http_responses.py
test/bdd/steps/steps_api_queries.py
test/python/mocks.py
test/python/test_cli.py
test/python/test_tokenizer_legacy.py
test/python/test_tools_postcodes.py
vagrant/Install-on-Ubuntu-20.sh

index b60507bc4511599922d981dbbae2b4135c8ae222..1c5fc735df32a0621513c9567a2878ea93b917d5 100644 (file)
@@ -82,7 +82,7 @@ jobs:
                 files: ./Nominatim/coverage*.xml
                 directory: ./
                 name: codecov-umbrella
-                fail_ci_if_error: true
+                fail_ci_if_error: false
                 path_to_write_report: ./coverage/codecov_report.txt
                 verbose: true
 
index 646465afd1efed1a80e3b32ff38aa62c968b86ab..373356383325a241ae1d75ca293239e5ea424b64 100644 (file)
@@ -85,7 +85,7 @@ To do so, you have access to the following command:
 nominatim special-phrases --import-from-csv <csv file>
 ```
 
-Note that the 2 previous import commands will update the phrases from your database.
+Note that the two previous import commands will update the phrases from your database.
 This means that if you import some phrases from a csv file, only the phrases
 present in the csv file will be kept into the database. All other phrases will
 be removed.
index 3701df9285112d2ca2cad3bbc193495d97d4a5b9..39c45a6e83b865bf26f14e873ce445dbd5e9762f 100644 (file)
@@ -40,7 +40,7 @@ all commands from the project directory.
 
 ### Configuration setup in `.env`
 
-The Nominatim server can be customized via an `.env` configuration file in the
+The Nominatim server can be customized via an `.env` configuration file in the 
 project directory. This is a file in [dotenv](https://github.com/theskumar/python-dotenv)
 format which looks the same as variable settings in a standard shell environment.
 You can also set the same configuration via environment variables. All
@@ -48,7 +48,7 @@ settings have a `NOMINATIM_` prefix to avoid conflicts with other environment
 variables.
 
 There are lots of configuration settings you can tweak. Have a look
-at `settings/env.default` for a full list. Most should have a sensible default.
+at `Nominatim/settings/env.default` for a full list. Most should have a sensible default.
 
 #### Flatnode files
 
@@ -193,12 +193,15 @@ can be found in the development section.
     [Geofabrik](https://download.geofabrik.de).
 
 Download the data to import. Then issue the following command
-from the **build directory** to start the import:
+from the **project directory** to start the import:
 
 ```sh
 nominatim import --osm-file <data file> 2>&1 | tee setup.log
 ```
 
+The **project directory** is the one that you have set up at the beginning.
+See [creating the project directory](Import#creating-the-project-directory).
+
 ### Notes on full planet imports
 
 Even on a perfectly configured machine
index 0ca6ebf29b660399ba42528607a84c2addfa45cf..fc309af1c3d9d69a089d40b280bea11dc240a747 100644 (file)
@@ -124,6 +124,14 @@ configuration file, run the following command after updating:
 ./utils/setup.php --setup-website
 ```
 
+### Update SQL code
+
+To update the SQL code to the leatest version run:
+
+```
+./utils/setup.php --create-functions --enable-diff-updates --create-partition-functions
+```
+
 ## 3.4.0 -> 3.5.0
 
 ### New Wikipedia/Wikidata importance tables
index be103074040da27e56dfc9a914baa868cc3da8e3..774b7ca60b4c0a9ea51c913638d39c42c3cd5fc5 100644 (file)
@@ -55,6 +55,27 @@ class Result
             }
         )));
     }
+
+    public static function joinIdsByTableMinRank($aResults, $iTable, $iMinAddressRank)
+    {
+        return join(',', array_keys(array_filter(
+            $aResults,
+            function ($aValue) use ($iTable, $iMinAddressRank) {
+                return $aValue->iTable == $iTable && $aValue->iAddressRank >= $iMinAddressRank;
+            }
+        )));
+    }
+
+    public static function joinIdsByTableMaxRank($aResults, $iTable, $iMaxAddressRank)
+    {
+        return join(',', array_keys(array_filter(
+            $aResults,
+            function ($aValue) use ($iTable, $iMaxAddressRank) {
+                return $aValue->iTable == $iTable && $aValue->iAddressRank <= $iMaxAddressRank;
+            }
+        )));
+    }
+
     public static function sqlHouseNumberTable($aResults, $iTable)
     {
         $sHousenumbers = '';
index 8da49a9ff0bfc7d2d0343d21391462e8baa95b2b..67cfbad03041f69f3cc65e247f0c91653c25aeed 100644 (file)
@@ -447,23 +447,24 @@ class SearchDescription
 
             // Now search for housenumber, if housenumber provided. Can be zero.
             if (($this->sHouseNumber || $this->sHouseNumber === '0') && !empty($aResults)) {
+                $aHnResults = $this->queryHouseNumber($oDB, $aResults);
+
                 // Downgrade the rank of the street results, they are missing
-                // the housenumber.
+                // the housenumber. Also drop POI places (rank 30) here, they
+                // cannot be a parent place and therefore must not be shown
+                // as a result for a search with a missing housenumber.
                 foreach ($aResults as $oRes) {
-                    if ($oRes->iAddressRank >= 26) {
-                        $oRes->iResultRank++;
-                    } else {
-                        $oRes->iResultRank += 2;
+                    if ($oRes->iAddressRank < 28) {
+                        if ($oRes->iAddressRank >= 26) {
+                            $oRes->iResultRank++;
+                        } else {
+                            $oRes->iResultRank += 2;
+                        }
+                        $aHnResults[$oRes->iId] = $oRes;
                     }
                 }
 
-                $aHnResults = $this->queryHouseNumber($oDB, $aResults);
-
-                if (!empty($aHnResults)) {
-                    foreach ($aHnResults as $oRes) {
-                        $aResults[$oRes->iId] = $oRes;
-                    }
-                }
+                $aResults = $aHnResults;
             }
 
             // finally get POIs if requested
@@ -743,16 +744,33 @@ class SearchDescription
     private function queryHouseNumber(&$oDB, $aRoadPlaceIDs)
     {
         $aResults = array();
-        $sPlaceIDs = Result::joinIdsByTable($aRoadPlaceIDs, Result::TABLE_PLACEX);
+        $sRoadPlaceIDs = Result::joinIdsByTableMaxRank(
+            $aRoadPlaceIDs,
+            Result::TABLE_PLACEX,
+            27
+        );
+        $sPOIPlaceIDs = Result::joinIdsByTableMinRank(
+            $aRoadPlaceIDs,
+            Result::TABLE_PLACEX,
+            30
+        );
 
-        if (!$sPlaceIDs) {
+        $aIDCondition = array();
+        if ($sRoadPlaceIDs) {
+            $aIDCondition[] = 'parent_place_id in ('.$sRoadPlaceIDs.')';
+        }
+        if ($sPOIPlaceIDs) {
+            $aIDCondition[] = 'place_id in ('.$sPOIPlaceIDs.')';
+        }
+
+        if (empty($aIDCondition)) {
             return $aResults;
         }
 
         $sHouseNumberRegex = '\\\\m'.$this->sHouseNumber.'\\\\M';
-        $sSQL = 'SELECT place_id FROM placex ';
-        $sSQL .= 'WHERE parent_place_id in ('.$sPlaceIDs.')';
-        $sSQL .= "  AND housenumber ~* E'".$sHouseNumberRegex."'";
+        $sSQL = 'SELECT place_id FROM placex WHERE';
+        $sSQL .= "  housenumber ~* E'".$sHouseNumberRegex."'";
+        $sSQL .= ' AND ('.join(' OR ', $aIDCondition).')';
         $sSQL .= $this->oContext->excludeSQL(' AND place_id');
 
         Debug::printSQL($sSQL);
@@ -764,11 +782,11 @@ class SearchDescription
 
         $bIsIntHouseNumber= (bool) preg_match('/[0-9]+/', $this->sHouseNumber);
         $iHousenumber = intval($this->sHouseNumber);
-        if ($bIsIntHouseNumber && empty($aResults)) {
+        if ($bIsIntHouseNumber && $sRoadPlaceIDs && empty($aResults)) {
             // if nothing found, search in the interpolation line table
             $sSQL = 'SELECT distinct place_id FROM location_property_osmline';
             $sSQL .= ' WHERE startnumber is not NULL';
-            $sSQL .= '  AND parent_place_id in ('.$sPlaceIDs.') AND (';
+            $sSQL .= '  AND parent_place_id in ('.$sRoadPlaceIDs.') AND (';
             if ($iHousenumber % 2 == 0) {
                 // If housenumber is even, look for housenumber in streets
                 // with interpolationtype even or all.
@@ -792,9 +810,9 @@ class SearchDescription
         }
 
         // If nothing found then search in Tiger data (location_property_tiger)
-        if (CONST_Use_US_Tiger_Data && $bIsIntHouseNumber && empty($aResults)) {
+        if (CONST_Use_US_Tiger_Data && $sRoadPlaceIDs && $bIsIntHouseNumber && empty($aResults)) {
             $sSQL = 'SELECT place_id FROM location_property_tiger';
-            $sSQL .= ' WHERE parent_place_id in ('.$sPlaceIDs.') and (';
+            $sSQL .= ' WHERE parent_place_id in ('.$sRoadPlaceIDs.') and (';
             if ($iHousenumber % 2 == 0) {
                 $sSQL .= "interpolationtype='even'";
             } else {
diff --git a/lib-php/admin/query.php b/lib-php/admin/query.php
deleted file mode 100644 (file)
index 21121fb..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-@define('CONST_LibDir', dirname(dirname(__FILE__)));
-
-require_once(CONST_LibDir.'/init-cmd.php');
-require_once(CONST_LibDir.'/ParameterParser.php');
-ini_set('memory_limit', '800M');
-
-$aCMDOptions
-= array(
-   'Query database from command line. Returns search result as JSON.',
-   array('help', 'h', 0, 1, 0, 0, false, 'Show Help'),
-   array('quiet', 'q', 0, 1, 0, 0, 'bool', 'Quiet output'),
-   array('verbose', 'v', 0, 1, 0, 0, 'bool', 'Verbose output'),
-
-   array('search', '', 0, 1, 1, 1, 'string', 'Search for given term or coordinate'),
-   array('country', '', 0, 1, 1, 1, 'string', 'Structured search: country'),
-   array('state', '', 0, 1, 1, 1, 'string', 'Structured search: state'),
-   array('county', '', 0, 1, 1, 1, 'string', 'Structured search: county'),
-   array('city', '', 0, 1, 1, 1, 'string', 'Structured search: city'),
-   array('street', '', 0, 1, 1, 1, 'string', 'Structured search: street'),
-   array('amenity', '', 0, 1, 1, 1, 'string', 'Structured search: amenity'),
-   array('postalcode', '', 0, 1, 1, 1, 'string', 'Structured search: postal code'),
-
-   array('accept-language', '', 0, 1, 1, 1, 'string', 'Preferred language order for showing search results'),
-   array('bounded', '', 0, 1, 0, 0, 'bool', 'Restrict results to given viewbox'),
-   array('nodedupe', '', 0, 1, 0, 0, 'bool', 'Do not remove duplicate results'),
-   array('limit', '', 0, 1, 1, 1, 'int', 'Maximum number of results returned (default: 10)'),
-   array('exclude_place_ids', '', 0, 1, 1, 1, 'string', 'Comma-separated list of place ids to exclude from results'),
-   array('featureType', '', 0, 1, 1, 1, 'string', 'Restrict results to certain features (country, state,city,settlement)'),
-   array('countrycodes', '', 0, 1, 1, 1, 'string', 'Comma-separated list of countries to restrict search to'),
-   array('viewbox', '', 0, 1, 1, 1, 'string', 'Prefer results in given view box'),
-
-   array('project-dir', '', 0, 1, 1, 1, 'realpath', 'Base directory of the Nominatim installation (default: .)'),
-  );
-getCmdOpt($_SERVER['argv'], $aCMDOptions, $aCMDResult, true, true);
-
-loadSettings($aCMDResult['project-dir'] ?? getcwd());
-
-@define('CONST_Database_DSN', getSetting('DATABASE_DSN'));
-@define('CONST_Default_Language', getSetting('DEFAULT_LANGUAGE', false));
-@define('CONST_Log_DB', getSettingBool('LOG_DB'));
-@define('CONST_Log_File', getSetting('LOG_FILE', false));
-@define('CONST_NoAccessControl', getSettingBool('CORS_NOACCESSCONTROL'));
-@define('CONST_Places_Max_ID_count', getSetting('LOOKUP_MAX_COUNT'));
-@define('CONST_PolygonOutput_MaximumTypes', getSetting('POLYGON_OUTPUT_MAX_TYPES'));
-@define('CONST_Search_BatchMode', getSettingBool('SEARCH_BATCH_MODE'));
-@define('CONST_Search_NameOnlySearchFrequencyThreshold', getSetting('SEARCH_NAME_ONLY_THRESHOLD'));
-@define('CONST_Use_US_Tiger_Data', getSettingBool('USE_US_TIGER_DATA'));
-@define('CONST_MapIcon_URL', getSetting('MAPICON_URL', false));
-@define('CONST_TokenizerDir', CONST_InstallDir.'/tokenizer');
-
-require_once(CONST_LibDir.'/Geocode.php');
-
-$oDB = new Nominatim\DB;
-$oDB->connect();
-
-if (isset($aCMDResult['nodedupe'])) $aCMDResult['dedupe'] = 'false';
-
-$oParams = new Nominatim\ParameterParser($aCMDResult);
-
-$aSearchParams = array(
-                     'search',
-                     'amenity',
-                     'street',
-                     'city',
-                     'county',
-                     'state',
-                     'country',
-                     'postalcode'
-                 );
-
-if (!$oParams->hasSetAny($aSearchParams)) {
-    showUsage($aCMDOptions, true);
-    return 1;
-}
-
-$oGeocode = new Nominatim\Geocode($oDB);
-
-$oGeocode->setLanguagePreference($oParams->getPreferredLanguages(false));
-$oGeocode->loadParamArray($oParams);
-
-if ($oParams->getBool('search')) {
-    $oGeocode->setQuery($aCMDResult['search']);
-} else {
-    $oGeocode->setQueryFromParams($oParams);
-}
-
-$aSearchResults = $oGeocode->lookup();
-
-echo json_encode($aSearchResults, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)."\n";
index 5316374648ff5c5e6ac4ae56b081430319506cac..dd0f16623e55cacecbd6f7c5baddc611b5ac033a 100644 (file)
@@ -92,6 +92,14 @@ BEGIN
     -- Get the existing place_id
     select * from placex where osm_type = NEW.osm_type and osm_id = NEW.osm_id and class = NEW.class and type = NEW.type INTO existingplacex;
 
+    -- Pure postcodes are never queried from placex so we don't add them.
+    -- location_postcodes is filled from the place table directly.
+    IF NEW.class = 'place' AND NEW.type = 'postcode' THEN
+      -- Remove old placex entry.
+      DELETE FROM placex where osm_type = NEW.osm_type and osm_id = NEW.osm_id;
+      RETURN NEW;
+    END IF;
+
     -- Handle a place changing type by removing the old data
     -- My generated 'place' types are causing havok because they overlap with real keys
     -- TODO: move them to their own special purpose key/class to avoid collisions
@@ -201,7 +209,7 @@ BEGIN
         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.class = 'boundary' AND NEW.type = 'postal_code' THEN
           IF NEW.address is NULL OR NOT NEW.address ? 'postcode' THEN
               -- postcode was deleted, no longer retain in placex
               DELETE FROM placex where place_id = existingplacex.place_id;
index 386516d6ec9297073c5a29f124784a6b7541ecad..fbc23350c7212478f8c8b0c9fa484ec154f9f070 100644 (file)
@@ -52,13 +52,17 @@ class UpdateRefresh:
 
 
         if args.postcodes:
-            LOG.warning("Update postcodes centroid")
-            tokenizer = self._get_tokenizer(args.config)
-            postcodes.update_postcodes(args.config.get_libpq_dsn(),
-                                       args.project_dir, tokenizer)
-            indexer = Indexer(args.config.get_libpq_dsn(), tokenizer,
-                              args.threads or 1)
-            indexer.index_postcodes()
+            if postcodes.can_compute(args.config.get_libpq_dsn()):
+                LOG.warning("Update postcodes centroid")
+                tokenizer = self._get_tokenizer(args.config)
+                postcodes.update_postcodes(args.config.get_libpq_dsn(),
+                                           args.project_dir, tokenizer)
+                indexer = Indexer(args.config.get_libpq_dsn(), tokenizer,
+                                  args.threads or 1)
+                indexer.index_postcodes()
+            else:
+                LOG.error("The place table doesn\'t exist. " \
+                          "Postcode updates on a frozen database is not possible.")
 
         if args.word_counts:
             LOG.warning('Recompute frequency of full-word search terms')
index 69939430188838bb69f89bfe9ae041eb3cac1989..242b0f6a0b00c80bacc05ef01b97823e6bed2dfd 100644 (file)
@@ -116,6 +116,7 @@ class UpdateReplication:
                 if state is not replication.UpdateState.NO_CHANGES:
                     status.log_status(conn, start, 'import')
                 batchdate, _, _ = status.get_status(conn)
+                conn.commit()
 
             if state is not replication.UpdateState.NO_CHANGES and args.do_index:
                 index_start = dt.datetime.now(dt.timezone.utc)
@@ -127,6 +128,7 @@ class UpdateReplication:
                 with connect(args.config.get_libpq_dsn()) as conn:
                     status.set_indexed(conn, True)
                     status.log_status(conn, index_start, 'index')
+                    conn.commit()
             else:
                 index_start = None
 
index 3f59068618db15e95fe09588a570bc3529b6ba36..878c88260602a691052fff87156115b1196410bd 100644 (file)
@@ -52,10 +52,8 @@ class SetupAll:
 
     @staticmethod
     def run(args): # pylint: disable=too-many-statements
-        from ..tools import database_import
-        from ..tools import refresh
+        from ..tools import database_import, refresh, postcodes, freeze
         from ..indexer.indexer import Indexer
-        from ..tools import postcodes
         from ..tokenizer import factory as tokenizer_factory
 
         if args.osm_file and not Path(args.osm_file).is_file():
@@ -135,8 +133,12 @@ class SetupAll:
             LOG.warning('Create search index for default country names.')
             database_import.create_country_names(conn, tokenizer,
                                                  args.config.LANGUAGES)
+            conn.commit()
+            if args.no_updates:
+                freeze.drop_update_tables(conn)
         tokenizer.finalize_import(args.config)
 
+
         webdir = args.project_dir / 'website'
         LOG.warning('Setup website at %s', webdir)
         with connect(args.config.get_libpq_dsn()) as conn:
index c2ff63dbce91f80c37fd0a4b288cc71c3c0fedc1..71e587875cd4db6c633d98b44118d6bed3202112 100644 (file)
@@ -17,7 +17,10 @@ def compute_database_date(conn):
     """
     # First, find the node with the highest ID in the database
     with conn.cursor() as cur:
-        osmid = cur.scalar("SELECT max(osm_id) FROM place WHERE osm_type='N'")
+        if conn.table_exists('place'):
+            osmid = cur.scalar("SELECT max(osm_id) FROM place WHERE osm_type='N'")
+        else:
+            osmid = cur.scalar("SELECT max(osm_id) FROM placex WHERE osm_type='N'")
 
         if osmid is None:
             LOG.fatal("No data found in the database.")
index ec9100e9ba860fee8e5c8b9d9c6d114b90738e85..d6fbc2cda6987bc18d708970ed2d2e767c7ac8b2 100644 (file)
@@ -375,7 +375,7 @@ class LegacyNameAnalyzer:
                     cur,
                     """ INSERT INTO word (word_id, word_token, word, class, type,
                                           search_name_count, operator)
-                        (SELECT nextval('seq_word'), make_standard_name(name), name,
+                        (SELECT nextval('seq_word'), ' ' || make_standard_name(name), name,
                                 class, type, 0,
                                 CASE WHEN op in ('in', 'near') THEN op ELSE null END
                            FROM (VALUES %s) as v(name, class, type, op))""",
@@ -400,7 +400,7 @@ class LegacyNameAnalyzer:
             cur.execute(
                 """INSERT INTO word (word_id, word_token, country_code)
                    (SELECT nextval('seq_word'), lookup_token, %s
-                      FROM (SELECT ' ' || make_standard_name(n) as lookup_token
+                      FROM (SELECT DISTINCT ' ' || make_standard_name(n) as lookup_token
                             FROM unnest(%s)n) y
                       WHERE NOT EXISTS(SELECT * FROM word
                                        WHERE word_token = lookup_token and country_code = %s))
index 664d3c6b39ed2fafb57e45960c052ccd76401505..28a10ebeb742f907f4b4efc1c3b2abe9925d40fa 100644 (file)
@@ -199,7 +199,7 @@ def load_data(dsn, threads):
         conn.perform("""INSERT INTO placex ({0})
                          SELECT {0} FROM place
                          WHERE osm_id % {1} = {2}
-                           AND NOT (class='place' and type='houses')
+                           AND NOT (class='place' and (type='houses' or type='postcode'))
                            AND ST_IsValid(geometry)
                      """.format(_COPY_COLUMNS, place_threads, imod))
         sel.register(conn, selectors.EVENT_READ, conn)
index 195d407ee3b8c7e43c591c2d0b74cbc910d5e28c..cfd242e24d8d358cf48f77f2930e8a1a7171ef03 100644 (file)
@@ -163,17 +163,17 @@ def update_postcodes(dsn, project_dir, tokenizer):
 
             # Recompute the list of valid postcodes from placex.
             with conn.cursor(name="placex_postcodes") as cur:
-                cur.execute("""SELECT country_code, pc, ST_X(centroid), ST_Y(centroid)
-                               FROM (
-                                 SELECT country_code,
-                                        token_normalized_postcode(address->'postcode') as pc,
-                                        ST_Centroid(ST_Collect(ST_Centroid(geometry))) as centroid
-                                 FROM placex
-                                 WHERE address ? 'postcode' and geometry IS NOT null
-                                       and country_code is not null
-                                 GROUP BY country_code, pc) xx
-                               WHERE pc is not null
-                               ORDER BY country_code, pc""")
+                cur.execute("""
+                SELECT cc as country_code, pc, ST_X(centroid), ST_Y(centroid)
+                FROM (SELECT 
+                        COALESCE(plx.country_code, get_country_code(ST_Centroid(pl.geometry))) as cc,
+                        token_normalized_postcode(pl.address->'postcode') as pc,
+                        ST_Centroid(ST_Collect(COALESCE(plx.centroid, ST_Centroid(pl.geometry)))) as centroid 
+                        FROM place AS pl LEFT OUTER JOIN placex AS plx ON pl.osm_id = plx.osm_id AND pl.osm_type = plx.osm_type
+                    WHERE pl.address ? 'postcode' AND pl.geometry IS NOT null
+                    GROUP BY cc, pc) xx
+                WHERE pc IS NOT null AND cc IS NOT null
+                ORDER BY country_code, pc""")
 
                 collector = None
 
@@ -195,3 +195,11 @@ def update_postcodes(dsn, project_dir, tokenizer):
             conn.commit()
 
         analyzer.update_postcodes_from_db()
+
+def can_compute(dsn):
+    """
+        Check that the place table exists so that
+        postcodes can be computed.
+    """
+    with connect(dsn) as conn:
+        return conn.table_exists('place')
index 479ddd31d39f9011412d78ebeeb7591424628e14..b6345baff2df1ed051b3777229185cf4467797de 100644 (file)
@@ -17,10 +17,10 @@ Feature: Address computation
         Then place_addressline doesn't contain
             | object | address |
             | N1     | N2      |
-        When searching for "Square"
+        When sending search query "Square"
         Then results contain
-           | osm_type | osm_id | name              |
-           | N        | 1      | Square, East Farm |
+           | osm | display_name      |
+           | N1  | Square, East Farm |
 
     Scenario: given two place nodes, the closer one wins for the address
         Given the grid
@@ -347,10 +347,10 @@ Feature: Address computation
         And place_addressline doesn't contain
            | object | address |
            | W1     | R1      |
-        When searching for "Bolder"
+        When sending search query "Bolder"
         Then results contain
-           | osm_type | osm_id | name                    |
-           | N        | 1      | Bolder, Wonderway, Left |
+           | osm | display_name            |
+           | N1  | Bolder, Wonderway, Left |
 
     Scenario: addr:* tags do not produce addresslines when the parent has the address part
         Given the grid
@@ -371,10 +371,10 @@ Feature: Address computation
         And place_addressline doesn't contain
            | object | address |
            | N1     | R1      |
-        When searching for "Bolder"
+        When sending search query "Bolder"
         Then results contain
-           | osm_type | osm_id | name                     |
-           | N        | 1      | Bolder, Wonderway, Outer |
+           | osm | display_name             |
+           | N1  | Bolder, Wonderway, Outer |
 
     Scenario: addr:* tags on outside do not produce addresslines when the parent has the address part
         Given the grid
@@ -397,10 +397,10 @@ Feature: Address computation
         And place_addressline doesn't contain
            | object | address |
            | N1     | R1      |
-        When searching for "Bolder"
+        When sending search query "Bolder"
         Then results contain
-           | osm_type | osm_id | name                    |
-           | N        | 1      | Bolder, Wonderway, Left |
+           | osm | display_name            |
+           | N1  | Bolder, Wonderway, Left |
 
     Scenario: POIs can correct address parts on the fly
         Given the grid
@@ -425,11 +425,11 @@ Feature: Address computation
            | object | address |
            | N1     | R1      |
            | N2     | R2      |
-        When searching for "Bolder"
+        When sending search query "Bolder"
         Then results contain
-           | osm_type | osm_id | name                    |
-           | N        | 1      | Bolder, Wonderway, Left |
-        When searching for "Leftside"
+           | osm | display_name            |
+           | N1  | Bolder, Wonderway, Left |
+        When sending search query "Leftside"
         Then results contain
-           | osm_type | osm_id | name                       |
-           | N        | 2      | Leftside, Wonderway, Right |
+           | osm | display_name               |
+           | N2  | Leftside, Wonderway, Right |
index 21f95e1f38c6de3a16892a407e3780a59018dc02..354d5c2f7262224aad612346805fb582f612b475 100644 (file)
@@ -10,16 +10,16 @@ Feature: Country handling
             | osm  | class    | type          | name  | geometry   |
             | N1   | place    | town          | Wenig | country:de |
         When importing
-        When searching for "Wenig, Loudou"
+        When sending search query "Wenig, Loudou"
         Then results contain
-            | osm_type | osm_id | name |
-            | N        | 1      | Wenig, Deutschland |
-        When searching for "Wenig"
+            | osm | display_name |
+            | N1  | Wenig, Deutschland |
+        When sending search query "Wenig"
             | accept-language |
             | xy,en |
         Then results contain
-            | osm_type | osm_id | name |
-            | N        | 1      | Wenig, Loudou |
+            | osm | display_name |
+            | N1  | Wenig, Loudou |
     Scenario: OSM country relations outside expected boundaries are ignored
         Given the places
             | osm  | class    | type           | admin | name+name:xy | country | geometry |
@@ -28,20 +28,20 @@ Feature: Country handling
             | osm  | class    | type          | name  | geometry   |
             | N1   | place    | town          | Wenig | country:de |
         When importing
-        When searching for "Wenig"
+        When sending search query "Wenig"
             | accept-language |
             | xy,en |
         Then results contain
-            | osm_type | osm_id | name |
-            | N        | 1      | Wenig, Germany |
+            | osm | display_name |
+            | N1  | Wenig, Germany |
     Scenario: Pre-defined country names are used
         Given the places
             | osm  | class    | type          | name  | geometry   |
             | N1   | place    | town          | Ingb  | country:ch |
         When importing
-        And searching for "Ingb"
+        And sending search query "Ingb"
             | accept-language |
             | en,de |
         Then results contain
-            | osm_type | osm_id | name |
-            | N        | 1      | Ingb, Switzerland |
+            | osm | display_name |
+            | N1  | Ingb, Switzerland |
index 52971295c5ced00253e7f39b6151f3640fe51fb2..181e87eec56f3b471616cf883964f4e84eb4bd2b 100644 (file)
@@ -240,11 +240,11 @@ Feature: Import of address interpolations
         Then W11 expands to interpolation
           | parent_place_id | start | end |
           | W3              | 12    | 16 |
-        When searching for "16 Cloud Street"
+        When sending search query "16 Cloud Street"
         Then results contain
          | ID | osm_type | osm_id |
          | 0  | N        | 4 |
-        When searching for "14 Cloud Street"
+        When sending search query "14 Cloud Street"
         Then results contain
          | ID | osm_type | osm_id |
          | 0  | W        | 11 |
@@ -282,11 +282,11 @@ Feature: Import of address interpolations
         Then W11 expands to interpolation
           | parent_place_id | start | end |
           | W3              | 12    | 16 |
-        When searching for "16 Cloud Street"
+        When sending search query "16 Cloud Street"
         Then results contain
          | ID | osm_type | osm_id |
          | 0  | N        | 4 |
-        When searching for "14 Cloud Street"
+        When sending search query "14 Cloud Street"
         Then results contain
          | ID | osm_type | osm_id |
          | 0  | W        | 11 |
index e2696e637098dab0d316c487d0764e348e93ca9c..915c13b3a9e184376a12792ba3d49e38338af9e5 100644 (file)
@@ -47,7 +47,7 @@ Feature: Linking of places
          | W2     | R13 |
          | R13    | -   |
          | R23    | -   |
-        When searching for "rhein"
+        When sending search query "rhein"
         Then results contain
          | osm_type |
          | R |
@@ -98,7 +98,7 @@ Feature: Linking of places
          | object | linked_place_id |
          | W1     | - |
          | R1     | - |
-        When searching for "rhein"
+        When sending search query "rhein"
         Then results contain
           | ID | osm_type |
           |  0 | R |
@@ -119,7 +119,7 @@ Feature: Linking of places
          | object | linked_place_id |
          | W1     | -  |
          | W2     | R1 |
-        When searching for "rhein2"
+        When sending search query "rhein2"
         Then results contain
          | osm_type |
          | W |
@@ -172,13 +172,13 @@ Feature: Linking of places
         And placex contains
          | object | rank_address |
          | R13    | 16 |
-        When searching for ""
+        When sending search query ""
          | city |
          | Berlin |
         Then results contain
           | ID | osm_type | osm_id |
           |  0 | R | 13 |
-        When searching for ""
+        When sending search query ""
          | state |
          | Berlin |
         Then results contain
@@ -200,13 +200,13 @@ Feature: Linking of places
         And placex contains
          | object | rank_address |
          | R13    | 8 |
-        When searching for ""
+        When sending search query ""
          | state |
          | Berlin |
         Then results contain
           | ID | osm_type | osm_id |
           |  0 | R | 13 |
-        When searching for ""
+        When sending search query ""
          | city |
          | Berlin |
         Then results contain
index 62d65cef571d9bb0eafad56ae8ab70225401605a..b5210f9439b55a5f328d28f0141ac695629a6334 100644 (file)
@@ -18,13 +18,13 @@ Feature: Parenting of objects
          | object | parent_place_id |
          | N1     | W1 |
          | N2     | W1 |
-        When searching for "4 galoo"
+        When sending search query "4 galoo"
         Then results contain
-         | ID | osm_type | osm_id | langaddress |
+         | ID | osm_type | osm_id | display_name |
          | 0  | N        | 1      | 4, galoo, 12345 |
-        When searching for "5 galoo"
+        When sending search query "5 galoo"
         Then results contain
-         | ID | osm_type | osm_id | langaddress |
+         | ID | osm_type | osm_id | display_name |
          | 0  | N        | 2      | 5, galoo, 99999 |
 
     Scenario: Address without tags, closest street
index 3d1dc489482fb90cc65b730175398804473aff05..6102e99ba1b00925bbd754b700c9e80344736d9f 100644 (file)
@@ -148,11 +148,11 @@ Feature: Import of postcodes
            | country | postcode | geometry |
            | gb      | EH4 7EA  | country:gb |
            | gb      | E4 7EA   | country:gb |
-        When searching for "EH4 7EA"
+        When sending search query "EH4 7EA"
         Then results contain
-           | type     | placename |
+           | type     | display_name |
            | postcode | EH4 7EA      |
-        When searching for "E4 7EA"
+        When sending search query "E4 7EA"
         Then results contain
-           | type     | placename |
+           | type     | display_name |
            | postcode | E4 7EA      |
index 9e899053180b6cf025bd33940a493d846ffbbfa5..d393b8f3381a7a493d4597cd113b77d4a331287f 100644 (file)
@@ -48,18 +48,18 @@ Feature: Creation of search terms
         Then search_name contains
          | object | nameaddress_vector |
          | N1     | #Rose Street, Walltown |
-        When searching for "23 Rose Street, Walltown"
+        When sending search query "23 Rose Street, Walltown"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Rose Street |
-        When searching for "Walltown, Rose Street 23"
+         | osm | display_name |
+         | N1  | 23, Rose Street |
+        When sending search query "Walltown, Rose Street 23"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Rose Street |
-        When searching for "Rose Street 23, Walltown"
+         | osm | display_name |
+         | N1  | 23, Rose Street |
+        When sending search query "Rose Street 23, Walltown"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Rose Street |
+         | osm | display_name |
+         | N1  | 23, Rose Street |
 
     Scenario: Searching for unknown addr: tags also works for multiple words
         Given the scene roads-with-pois
@@ -73,18 +73,18 @@ Feature: Creation of search terms
         Then search_name contains
          | object | nameaddress_vector |
          | N1     | #Rose Street, rose, Little, Big, Town |
-        When searching for "23 Rose Street, Little Big Town"
+        When sending search query "23 Rose Street, Little Big Town"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Rose Street |
-        When searching for "Rose Street 23, Little Big Town"
+         | osm | display_name |
+         | N1  | 23, Rose Street |
+        When sending search query "Rose Street 23, Little Big Town"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Rose Street |
-        When searching for "Little big Town, Rose Street 23"
+         | osm | display_name |
+         | N1  | 23, Rose Street |
+        When sending search query "Little big Town, Rose Street 23"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Rose Street |
+         | osm | display_name |
+         | N1  | 23, Rose Street |
 
      Scenario: Unnamed POI has no search entry when it has known addr: tags
         Given the scene roads-with-pois
@@ -96,10 +96,10 @@ Feature: Creation of search terms
          | W1  | highway | residential | Rose Street | Walltown | :w-north |
         When importing
         Then search_name has no entry for N1
-        When searching for "23 Rose Street, Walltown"
+        When sending search query "23 Rose Street, Walltown"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Rose Street |
+         | osm | display_name |
+         | N1  | 23, Rose Street |
 
     Scenario: Unnamed POI must have a house number to get a search entry
         Given the scene roads-with-pois
@@ -128,23 +128,23 @@ Feature: Creation of search terms
         Then search_name contains
          | object | name_vector | nameaddress_vector |
          | N1     | #Walltown   | Strange, Town |
-        When searching for "23 Rose Street"
+        When sending search query "23 Rose Street"
         Then exactly 1 results are returned
         And results contain
-         | osm_type | osm_id | name |
-         | W        | 1      | Rose Street, Strange Town |
-        When searching for "23 Walltown, Strange Town"
+         | osm | display_name |
+         | W1  | Rose Street, Strange Town |
+        When sending search query "23 Walltown, Strange Town"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Walltown, Strange Town |
-        When searching for "Walltown 23, Strange Town"
+         | osm | display_name |
+         | N1  | 23, Walltown, Strange Town |
+        When sending search query "Walltown 23, Strange Town"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Walltown, Strange Town |
-        When searching for "Strange Town, Walltown 23"
+         | osm | display_name |
+         | N1  | 23, Walltown, Strange Town |
+        When sending search query "Strange Town, Walltown 23"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Walltown, Strange Town |
+         | osm | display_name |
+         | N1  | 23, Walltown, Strange Town |
 
     Scenario: Named POIs can be searched by housenumber when unknown addr:place is present
         Given the scene roads-with-pois
@@ -159,26 +159,26 @@ Feature: Creation of search terms
         Then search_name contains
          | object | name_vector      | nameaddress_vector      |
          | N1     | #Walltown, #Blue house | Walltown, Strange, Town |
-        When searching for "23 Walltown, Strange Town"
+        When sending search query "23 Walltown, Strange Town"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Blue house, 23, Walltown, Strange Town |
-        When searching for "Walltown 23, Strange Town"
+         | osm | display_name |
+         | N1  | Blue house, 23, Walltown, Strange Town |
+        When sending search query "Walltown 23, Strange Town"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Blue house, 23, Walltown, Strange Town |
-        When searching for "Strange Town, Walltown 23"
+         | osm | display_name |
+         | N1  | Blue house, 23, Walltown, Strange Town |
+        When sending search query "Strange Town, Walltown 23"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Blue house, 23, Walltown, Strange Town |
-        When searching for "Strange Town, Walltown 23, Blue house"
+         | osm | display_name |
+         | N1  | Blue house, 23, Walltown, Strange Town |
+        When sending search query "Strange Town, Walltown 23, Blue house"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Blue house, 23, Walltown, Strange Town |
-        When searching for "Strange Town, Walltown, Blue house"
+         | osm | display_name |
+         | N1  | Blue house, 23, Walltown, Strange Town |
+        When sending search query "Strange Town, Walltown, Blue house"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Blue house, 23, Walltown, Strange Town |
+         | osm | display_name |
+         | N1  | Blue house, 23, Walltown, Strange Town |
 
     Scenario: Named POIs can be found when unknown multi-word addr:place is present
         Given the scene roads-with-pois
@@ -193,14 +193,14 @@ Feature: Creation of search terms
         Then search_name contains
          | object | name_vector      | nameaddress_vector      |
          | N1     | #Moon sun, #Blue house | Moon, Sun, Strange, Town |
-        When searching for "23 Moon Sun, Strange Town"
+        When sending search query "23 Moon Sun, Strange Town"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Blue house, 23, Moon sun, Strange Town |
-        When searching for "Blue house, Moon Sun, Strange Town"
+         | osm | display_name |
+         | N1  | Blue house, 23, Moon sun, Strange Town |
+        When sending search query "Blue house, Moon Sun, Strange Town"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Blue house, 23, Moon sun, Strange Town |
+         | osm | display_name |
+         | N1  | Blue house, 23, Moon sun, Strange Town |
 
     Scenario: Unnamed POIs doesn't inherit parent name when addr:place is present only in parent address
         Given the scene roads-with-pois
@@ -215,16 +215,16 @@ Feature: Creation of search terms
         Then search_name contains
          | object | name_vector | nameaddress_vector |
          | N1     | #Walltown   | Strange, Town      |
-        When searching for "23 Rose Street, Walltown"
+        When sending search query "23 Rose Street, Walltown"
         Then exactly 1 result is returned
         And results contain
-         | osm_type | osm_id | name |
-         | W        | 1      | Rose Street, Strange Town |
-        When searching for "23  Walltown"
+         | osm | display_name |
+         | W1  | Rose Street, Strange Town |
+        When sending search query "23  Walltown"
         Then exactly 1 result is returned
         And results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Walltown, Strange Town |
+         | osm | display_name |
+         | N1  | 23, Walltown, Strange Town |
 
     Scenario: Unnamed POIs does inherit parent name when unknown addr:place and addr:street is present
         Given the scene roads-with-pois
@@ -236,11 +236,11 @@ Feature: Creation of search terms
          | W1  | highway | residential | Rose Street | :w-north |
         When importing
         Then search_name has no entry for N1
-        When searching for "23 Rose Street"
+        When sending search query "23 Rose Street"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Rose Street |
-        When searching for "23 Lily Street"
+         | osm | display_name |
+         | N1  | 23, Rose Street |
+        When sending search query "23 Lily Street"
         Then exactly 0 results are returned
 
     Scenario: An unknown addr:street is ignored
@@ -253,11 +253,11 @@ Feature: Creation of search terms
          | W1  | highway | residential | Rose Street | :w-north |
         When importing
         Then search_name has no entry for N1
-        When searching for "23 Rose Street"
+        When sending search query "23 Rose Street"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | 23, Rose Street |
-        When searching for "23 Lily Street"
+         | osm | display_name |
+         | N1  | 23, Rose Street |
+        When sending search query "23 Lily Street"
         Then exactly 0 results are returned
 
     Scenario: Named POIs get unknown address tags added in the search_name table
@@ -272,26 +272,26 @@ Feature: Creation of search terms
         Then search_name contains
          | object | name_vector | nameaddress_vector |
          | N1     | #Green Moss | #Rose Street, Walltown |
-        When searching for "Green Moss, Rose Street, Walltown"
+        When sending search query "Green Moss, Rose Street, Walltown"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Green Moss, 26, Rose Street |
-        When searching for "Green Moss, 26, Rose Street, Walltown"
+         | osm | display_name |
+         | N1  | Green Moss, 26, Rose Street |
+        When sending search query "Green Moss, 26, Rose Street, Walltown"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Green Moss, 26, Rose Street |
-        When searching for "26, Rose Street, Walltown"
+         | osm | display_name |
+         | N1  | Green Moss, 26, Rose Street |
+        When sending search query "26, Rose Street, Walltown"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Green Moss, 26, Rose Street |
-        When searching for "Rose Street 26, Walltown"
+         | osm | display_name |
+         | N1  | Green Moss, 26, Rose Street |
+        When sending search query "Rose Street 26, Walltown"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Green Moss, 26, Rose Street |
-        When searching for "Walltown, Rose Street 26"
+         | osm | display_name |
+         | N1  | Green Moss, 26, Rose Street |
+        When sending search query "Walltown, Rose Street 26"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Green Moss, 26, Rose Street |
+         | osm | display_name |
+         | N1  | Green Moss, 26, Rose Street |
 
     Scenario: Named POI doesn't inherit parent name when addr:place is present only in parent address
         Given the scene roads-with-pois
@@ -306,12 +306,12 @@ Feature: Creation of search terms
         Then search_name contains
          | object | name_vector | nameaddress_vector |
          | N1     | #Green Moss | Walltown |
-        When searching for "Green Moss, Rose Street, Walltown"
+        When sending search query "Green Moss, Rose Street, Walltown"
         Then exactly 0 result is returned
-        When searching for "Green Moss, Walltown"
+        When sending search query "Green Moss, Walltown"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | Green Moss, Walltown, Strange Town |
+         | osm | display_name |
+         | N1  | Green Moss, Walltown, Strange Town |
 
     Scenario: Named POIs inherit address from parent
         Given the scene roads-with-pois
index 8a324a229b86bfaa450a35d5d095bed647d483d3..350455891495f470a92954b0545a260c8c7531dd 100644 (file)
@@ -11,44 +11,44 @@ Feature: Import and search of names
         Then placex contains
           | object | class  | type     | name+name |
           | N1     | place  | locality | FooBar |
-        When searching for "FooBar"
+        When sending search query "FooBar"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
-        When searching for "foobar"
+         | ID | osm |
+         | 0  | N1 |
+        When sending search query "foobar"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
-        When searching for "fOObar"
+         | ID | osm |
+         | 0  | N1 |
+        When sending search query "fOObar"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
-        When searching for "FOOBAR"
+         | ID | osm |
+         | 0  | N1 |
+        When sending search query "FOOBAR"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
+         | ID | osm |
+         | 0  | N1 |
 
     Scenario: Multiple spaces in name
         Given the places
           | osm | class | type      | name |
           | N1  | place | locality  | one two  three |
         When importing
-        When searching for "one two three"
+        When sending search query "one two three"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
-        When searching for "one   two three"
+         | ID | osm |
+         | 0  | N1 |
+        When sending search query "one   two three"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
-        When searching for "one two  three"
+         | ID | osm |
+         | 0  | N1 |
+        When sending search query "one two  three"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
-        When searching for "    one two three"
+         | ID | osm |
+         | 0  | N1 |
+        When sending search query "    one two three"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
+         | ID | osm |
+         | 0  | N1 |
 
     Scenario: Special characters in name
         Given the places
@@ -59,58 +59,58 @@ Feature: Import and search of names
           | N4  | place | locality  | space |
           | N5  | place | locality  | mountain |
         When importing
-        When searching for "Jim-Knopf-Str"
+        When sending search query "Jim-Knopf-Str"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
-        When searching for "Jim Knopf-Str"
+         | ID | osm |
+         | 0  | N1 |
+        When sending search query "Jim Knopf-Str"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
-        When searching for "Jim Knopf Str"
+         | ID | osm |
+         | 0  | N1 |
+        When sending search query "Jim Knopf Str"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
-        When searching for "Jim/Knopf-Str"
+         | ID | osm |
+         | 0  | N1 |
+        When sending search query "Jim/Knopf-Str"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
-        When searching for "Jim-Knopfstr"
+         | ID | osm |
+         | 0  | N1 |
+        When sending search query "Jim-Knopfstr"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 1 |
-        When searching for "Smith/Weston"
+         | ID | osm |
+         | 0  | N1 |
+        When sending search query "Smith/Weston"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 2 |
-        When searching for "Smith Weston"
+         | ID | osm |
+         | 0  | N2 |
+        When sending search query "Smith Weston"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 2 |
-        When searching for "Smith-Weston"
+         | ID | osm |
+         | 0  | N2 |
+        When sending search query "Smith-Weston"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 2 |
-        When searching for "space mountain"
+         | ID | osm |
+         | 0  | N2 |
+        When sending search query "space mountain"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 3 |
-        When searching for "space-mountain"
+         | ID | osm |
+         | 0  | N3 |
+        When sending search query "space-mountain"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 3 |
-        When searching for "space/mountain"
+         | ID | osm |
+         | 0  | N3 |
+        When sending search query "space/mountain"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 3 |
-        When searching for "space\mountain"
+         | ID | osm |
+         | 0  | N3 |
+        When sending search query "space\mountain"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 3 |
-        When searching for "space(mountain)"
+         | ID | osm |
+         | 0  | N3 |
+        When sending search query "space(mountain)"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | N        | 3 |
+         | ID | osm |
+         | 0  | N3 |
 
     Scenario: Landuse with name are found
         Given the places
@@ -118,34 +118,32 @@ Feature: Import and search of names
           | R1  | natural  | meadow      | landuse1 | (0 0, 1 0, 1 1, 0 1, 0 0) |
           | R2  | landuse  | industrial  | landuse2 | (0 0, -1 0, -1 -1, 0 -1, 0 0) |
         When importing
-        When searching for "landuse1"
+        When sending search query "landuse1"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | R        | 1 |
-        When searching for "landuse2"
+         | ID | osm |
+         | 0  | R1 |
+        When sending search query "landuse2"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | R        | 2 |
+         | ID | osm |
+         | 0  | R2 |
 
     Scenario: Postcode boundaries without ref
         Given the places
           | osm | class    | type        | postcode | geometry |
           | R1  | boundary | postal_code | 12345    | (0 0, 1 0, 1 1, 0 1, 0 0) |
         When importing
-        When searching for "12345"
+        When sending search query "12345"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | R        | 1 |
+         | ID | osm |
+         | 0  | R1 |
 
     Scenario: Unprintable characters in postcodes are ignored
         Given the named places
             | osm  | class   | type   | address |
             | N234 | amenity | prison | 'postcode' : u'1234\u200e' |
         When importing
-        And searching for "1234"
-        Then results contain
-         | ID | osm_type |
-         | 0  | P        |
+        And sending search query "1234"
+        Then result 0 has not attributes osm_type
 
     Scenario Outline: Housenumbers with special characters are found
         Given the grid
@@ -158,10 +156,10 @@ Feature: Import and search of names
             | osm | class    | type | housenr | geometry |
             | N1  | building | yes  | <nr>    | 9        |
         When importing
-        And searching for "Main St <nr>"
+        And sending search query "Main St <nr>"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | <nr>, Main St |
+         | osm | display_name |
+         | N1  | <nr>, Main St |
 
     Examples:
         | nr |
@@ -186,10 +184,10 @@ Feature: Import and search of names
             | osm | class    | type | housenr   | geometry |
             | N1  | building | yes  | <nr-list> | 9        |
         When importing
-        And searching for "Main St <nr>"
+        And sending search query "Main St <nr>"
         Then results contain
-         | osm_type | osm_id | name |
-         | N        | 1      | <nr-list>, Main St |
+         | osm | display_name |
+         | N1  | <nr-list>, Main St |
 
     Examples:
         | nr-list    | nr |
index daf83cea04d7e25c606b4098db124c6aaba4e087..8c19fb7d3370bbab9dbf99d3482f4bdda1436aa3 100644 (file)
@@ -7,31 +7,29 @@ Feature: Searching of simple objects
           | osm | class | type    | name+name | geometry   |
           | N1  | place | village | Foo       | 10.0 -10.0 |
         When importing
-        And searching for "Foo"
+        And sending search query "Foo"
         Then results contain
-         | ID | osm | class | type    | centroid |
-         | 0  | N1  | place | village | 10 -10   |
+         | ID | osm | category | type    | centroid |
+         | 0  | N1  | place    | village | 10 -10   |
 
      Scenario: Updating postcode in postcode boundaries without ref
         Given the places
           | osm | class    | type        | postcode | geometry |
           | R1  | boundary | postal_code | 12345    | poly-area:1.0 |
         When importing
-        And searching for "12345"
+        And sending search query "12345"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | R        | 1 |
+         | ID | osm |
+         | 0  | R1 |
         When updating places
           | osm | class    | type        | postcode | geometry |
           | R1  | boundary | postal_code | 54321    | poly-area:1.0 |
-        And searching for "12345"
+        And sending search query "12345"
+        Then result 0 has not attributes osm_type
+        When sending search query "54321"
         Then results contain
-         | osm_type |
-         | P        |
-        When searching for "54321"
-        Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | R        | 1 |
+         | ID | osm |
+         | 0  | R1 |
 
     # github #1763
     Scenario: Correct translation of highways under construction
@@ -47,3 +45,30 @@ Feature: Searching of simple objects
         Then result addresses contain
          | amenity | road |
          | Bean    | The build |
+
+    Scenario: when missing housenumbers in search don't return a POI
+        Given the places
+         | osm | class   | type       | name        |
+         | N3  | amenity | restaurant | Wood Street |
+        And the places
+         | osm | class   | type       | name        | housenr |
+         | N20 | amenity | restaurant | Red Way     | 34      |
+        When importing
+        And sending search query "Wood Street 45"
+        Then exactly 0 results are returned
+        When sending search query "Red Way 34"
+        Then results contain
+         | osm |
+         | N20 |
+
+     Scenario: when the housenumber is missing the stret is still returned
+        Given the grid
+         | 1 |  | 2 |
+        Given the places
+         | osm | class   | type        | name        | geometry |
+         | W1  | highway | residential | Wood Street | 1, 2     |
+        When importing
+        And sending search query "Wood Street"
+        Then results contain
+         | osm |
+         | W1  |
index 42e62de57dc27955ab1fca4ddee1ca176c2c2c8f..7a0fa21a829667102a177e9abf3ad3671cd7c1a2 100644 (file)
@@ -10,7 +10,9 @@ Feature: Updates of linked places
             | osm | class    | type           | name | admin | geometry |
             | R1  | boundary | administrative | foo  | 8     | poly-area:0.1 |
         When importing
-        And searching for "foo" with dups
+        And sending search query "foo"
+         | dups |
+         | 1    |
         Then results contain
          | osm_type |
          | R |
@@ -20,7 +22,9 @@ Feature: Updates of linked places
         Then placex contains
          | object | linked_place_id |
          | N1     | - |
-        When searching for "foo" with dups
+        When sending search query "foo"
+         | dups |
+         | 1    |
         Then results contain
          | osm_type |
          | N |
@@ -33,7 +37,9 @@ Feature: Updates of linked places
             | osm | class    | type           | name | admin | geometry |
             | R1  | boundary | administrative | foo  | 8     | poly-area:0.1 |
         When importing
-        And searching for "foo" with dups
+        And sending search query "foo"
+         | dups |
+         | 1    |
         Then results contain
          | osm_type |
          | R |
@@ -41,7 +47,9 @@ Feature: Updates of linked places
         Then placex contains
          | object | linked_place_id |
          | N1     | - |
-        When searching for "foo" with dups
+        When sending search query "foo"
+         | dups |
+         | 1    |
         Then results contain
          | osm_type |
          | N |
@@ -51,7 +59,9 @@ Feature: Updates of linked places
             | osm | class | type | name | geometry |
             | N1  | place | city | foo  | 0 0 |
         When importing
-        And searching for "foo" with dups
+        And sending search query "foo"
+         | dups |
+         | 1    |
         Then results contain
          | osm_type |
          | N |
@@ -61,7 +71,9 @@ Feature: Updates of linked places
         Then placex contains
          | object | linked_place_id |
          | N1     | R1 |
-        When searching for "foo" with dups
+        When sending search query "foo"
+         | dups |
+         | 1    |
         Then results contain
          | osm_type |
          | R |
@@ -74,7 +86,9 @@ Feature: Updates of linked places
          | osm | class    | type           | name   | admin | geometry |
          | R1  | boundary | administrative | foobar | 8     | poly-area:0.1 |
         When importing
-        And searching for "foo" with dups
+        And sending search query "foo"
+         | dups |
+         | 1    |
         Then results contain
          | osm_type |
          | N |
@@ -84,7 +98,9 @@ Feature: Updates of linked places
         Then placex contains
          | object | linked_place_id |
          | N1     | R1 |
-        When searching for "foo" with dups
+        When sending search query "foo"
+         | dups |
+         | 1    |
         Then results contain
          | osm_type |
          | R |
index 4b5222fc61b086e36a404972b48e9b52ef7282c5..4023e3f9be29838ae2eced4f5c468968dc65f75a 100644 (file)
@@ -7,10 +7,10 @@ Feature: Update of names in place objects
           | osm | class    | type        | postcode | geometry |
           | R1  | boundary | postal_code | 12345    | poly-area:0.5 |
         When importing
-        And searching for "12345"
+        And sending search query "12345"
         Then results contain
-         | ID | osm_type | osm_id |
-         | 0  | R        | 1 |
+         | ID | osm |
+         | 0  | R1 |
         When updating places
           | osm | class    | type        | geometry |
           | R1  | boundary | postal_code | poly-area:0.5 |
index 247a397bd47b1ed7c7d5e886e4c95e1811759973..0920a7e2ff00b31b04ccd800e57ca6ed69c18138 100644 (file)
@@ -8,7 +8,9 @@ import xml.etree.ElementTree as ET
 
 from check_functions import Almost
 
-OSM_TYPE = {'N' : 'node', 'W' : 'way', 'R' : 'relation'}
+OSM_TYPE = {'N' : 'node', 'W' : 'way', 'R' : 'relation',
+            'n' : 'node', 'w' : 'way', 'r' : 'relation',
+            'node' : 'n', 'way' : 'w', 'relation' : 'r'}
 
 def _geojson_result_to_json_result(geojson_result):
     result = geojson_result['properties']
@@ -139,6 +141,9 @@ class GenericResponse:
                     assert self.result[i]['osm_type'] in (OSM_TYPE[value[0]], value[0]), \
                            BadRowValueAssert(self, i, 'osm_type', value)
                     self.assert_field(i, 'osm_id', value[1:])
+                elif name == 'osm_type':
+                    assert self.result[i]['osm_type'] in (OSM_TYPE[value[0]], value[0]), \
+                           BadRowValueAssert(self, i, 'osm_type', value)
                 elif name == 'centroid':
                     lon, lat = value.split(' ')
                     self.assert_field(i, 'lat', float(lat))
index 1b3da08b82f25913ad5721d3f7dec11f28d9574a..fc0a2156b5cd5e8dbc96de1e574879265c7d23ef 100644 (file)
@@ -55,29 +55,6 @@ def compare(operator, op1, op2):
         raise Exception("unknown operator '%s'" % operator)
 
 
-@when(u'searching for "(?P<query>.*)"(?P<dups> with dups)?')
-def query_cmd(context, query, dups):
-    """ Query directly via PHP script.
-    """
-    cmd = ['/usr/bin/env', 'php']
-    cmd.append(context.nominatim.src_dir  / 'lib-php' / 'admin' / 'query.php')
-    if query:
-        cmd.extend(['--search', query])
-    # add more parameters in table form
-    if context.table:
-        for h in context.table.headings:
-            value = context.table[0][h].strip()
-            if value:
-                cmd.extend(('--' + h, value))
-
-    if dups:
-        cmd.extend(('--dedupe', '0'))
-
-    outp, err = run_script(cmd, cwd=context.nominatim.website_dir.name,
-                           env=context.nominatim.test_env)
-
-    context.response = SearchResponse(outp, 'json')
-
 def send_api_query(endpoint, params, fmt, context):
     if fmt is not None and fmt.strip() != 'debug':
         params['format'] = fmt.strip()
index d86f0196810ceb662670ac80cccce327f885e394..e95d57721357b7c5c8e7896feaf6434248f98b6f 100644 (file)
@@ -49,6 +49,13 @@ class MockWordTable:
         self.conn.commit()
 
 
+    def add_country(self, country_code, word_token):
+        with self.conn.cursor() as cur:
+            cur.execute("INSERT INTO word (word_token, country_code) VALUES(%s, %s)",
+                        (word_token, country_code))
+        self.conn.commit()
+
+
     def add_postcode(self, word_token, postcode):
         with self.conn.cursor() as cur:
             cur.execute("""INSERT INTO word (word_token, word, class, type)
@@ -71,7 +78,18 @@ class MockWordTable:
         with self.conn.cursor() as cur:
             cur.execute("""SELECT word_token, word, class, type, operator
                            FROM word WHERE class != 'place'""")
-            return set((tuple(row) for row in cur))
+            result = set((tuple(row) for row in cur))
+            assert len(result) == cur.rowcount, "Word table has duplicates."
+            return result
+
+
+    def get_country(self):
+        with self.conn.cursor() as cur:
+            cur.execute("""SELECT country_code, word_token
+                           FROM word WHERE country_code is not null""")
+            result = set((tuple(row) for row in cur))
+            assert len(result) == cur.rowcount, "Word table has duplicates."
+            return result
 
 
     def get_postcodes(self):
index 1d775b1fd6d395ea67be61898187d03c194f0f16..d9e0104014eb74c529cfa6d198847ce415460fa6 100644 (file)
@@ -320,7 +320,7 @@ class TestCliWithDb:
         assert func_mock.called == 1
 
 
-    def test_refresh_postcodes(self, mock_func_factory):
+    def test_refresh_postcodes(self, mock_func_factory, place_table):
         func_mock = mock_func_factory(nominatim.tools.postcodes, 'update_postcodes')
         idx_mock = mock_func_factory(nominatim.indexer.indexer.Indexer, 'index_postcodes')
 
index 3cd18fcff53f910210932f56ecd5ed7300d64c98..35e24ca49ae0bcf46aedc70500a4a7cd35cb759a 100644 (file)
@@ -73,7 +73,7 @@ def analyzer(tokenizer_factory, test_config, monkeypatch, sql_preprocessor,
 @pytest.fixture
 def make_standard_name(temp_db_cursor):
     temp_db_cursor.execute("""CREATE OR REPLACE FUNCTION make_standard_name(name TEXT)
-                              RETURNS TEXT AS $$ SELECT ' ' || name; $$ LANGUAGE SQL""")
+                              RETURNS TEXT AS $$ SELECT '#' || lower(name) || '#'; $$ LANGUAGE SQL""")
 
 
 @pytest.fixture
@@ -209,18 +209,19 @@ def test_update_special_phrase_empty_table(analyzer, word_table, make_standard_n
     analyzer.update_special_phrases([
         ("König bei", "amenity", "royal", "near"),
         ("Könige", "amenity", "royal", "-"),
+        ("könige", "amenity", "royal", "-"),
         ("strasse", "highway", "primary", "in")
     ], True)
 
     assert word_table.get_special() \
-               == set(((' könig bei', 'könig bei', 'amenity', 'royal', 'near'),
-                       (' könige', 'könige', 'amenity', 'royal', None),
-                       (' strasse', 'strasse', 'highway', 'primary', 'in')))
+               == set(((' #könig bei#', 'könig bei', 'amenity', 'royal', 'near'),
+                       (' #könige#', 'könige', 'amenity', 'royal', None),
+                       (' #strasse#', 'strasse', 'highway', 'primary', 'in')))
 
 
 def test_update_special_phrase_delete_all(analyzer, word_table, make_standard_name):
-    word_table.add_special(' foo', 'foo', 'amenity', 'prison', 'in')
-    word_table.add_special(' bar', 'bar', 'highway', 'road', None)
+    word_table.add_special(' #foo#', 'foo', 'amenity', 'prison', 'in')
+    word_table.add_special(' #bar#', 'bar', 'highway', 'road', None)
 
     assert word_table.count_special() == 2
 
@@ -230,8 +231,8 @@ def test_update_special_phrase_delete_all(analyzer, word_table, make_standard_na
 
 
 def test_update_special_phrases_no_replace(analyzer, word_table, make_standard_name):
-    word_table.add_special(' foo', 'foo', 'amenity', 'prison', 'in')
-    word_table.add_special(' bar', 'bar', 'highway', 'road', None)
+    word_table.add_special(' #foo#', 'foo', 'amenity', 'prison', 'in')
+    word_table.add_special(' #bar#', 'bar', 'highway', 'road', None)
 
     assert word_table.count_special() == 2
 
@@ -241,8 +242,8 @@ def test_update_special_phrases_no_replace(analyzer, word_table, make_standard_n
 
 
 def test_update_special_phrase_modify(analyzer, word_table, make_standard_name):
-    word_table.add_special(' foo', 'foo', 'amenity', 'prison', 'in')
-    word_table.add_special(' bar', 'bar', 'highway', 'road', None)
+    word_table.add_special(' #foo#', 'foo', 'amenity', 'prison', 'in')
+    word_table.add_special(' #bar#', 'bar', 'highway', 'road', None)
 
     assert word_table.count_special() == 2
 
@@ -253,9 +254,31 @@ def test_update_special_phrase_modify(analyzer, word_table, make_standard_name):
     ], True)
 
     assert word_table.get_special() \
-               == set(((' prison', 'prison', 'amenity', 'prison', 'in'),
-                       (' bar', 'bar', 'highway', 'road', None),
-                       (' garden', 'garden', 'leisure', 'garden', 'near')))
+               == set(((' #prison#', 'prison', 'amenity', 'prison', 'in'),
+                       (' #bar#', 'bar', 'highway', 'road', None),
+                       (' #garden#', 'garden', 'leisure', 'garden', 'near')))
+
+
+def test_add_country_names(analyzer, word_table, make_standard_name):
+    analyzer.add_country_names('de', ['Germany', 'Deutschland', 'germany'])
+
+    assert word_table.get_country() \
+               == {('de', ' #germany#'),
+                   ('de', ' #deutschland#')}
+
+
+def test_add_more_country_names(analyzer, word_table, make_standard_name):
+    word_table.add_country('fr', ' #france#')
+    word_table.add_country('it', ' #italy#')
+    word_table.add_country('it', ' #itala#')
+
+    analyzer.add_country_names('it', ['Italy', 'IT'])
+
+    assert word_table.get_country() \
+               == {('fr', ' #france#'),
+                   ('it', ' #italy#'),
+                   ('it', ' #itala#'),
+                   ('it', ' #it#')}
 
 
 def test_process_place_names(analyzer, make_keywords):
index 8f54ad41369af5df80a601d0479c9659d0329da2..a34157690c8bd9350fe1881b442abdc970c4fdde 100644 (file)
@@ -26,6 +26,11 @@ class MockPostcodeTable:
                                geometry GEOMETRY(Geometry, 4326))""")
             cur.execute("""CREATE OR REPLACE FUNCTION token_normalized_postcode(postcode TEXT)
                            RETURNS TEXT AS $$ BEGIN RETURN postcode; END; $$ LANGUAGE plpgsql;
+
+                           CREATE OR REPLACE FUNCTION get_country_code(place geometry)
+                           RETURNS TEXT AS $$ BEGIN 
+                           RETURN null;
+                           END; $$ LANGUAGE plpgsql;
                         """)
         conn.commit()
 
@@ -58,15 +63,16 @@ def postcode_table(temp_db_conn, placex_table, word_table):
     return MockPostcodeTable(temp_db_conn)
 
 
-def test_postcodes_empty(dsn, postcode_table, tmp_path, tokenizer):
+def test_postcodes_empty(dsn, postcode_table, place_table,
+                         tmp_path, tokenizer):
     postcodes.update_postcodes(dsn, tmp_path, tokenizer)
 
     assert not postcode_table.row_set
 
 
-def test_postcodes_add_new(dsn, placex_table, postcode_table, tmp_path, tokenizer):
-    placex_table.add(country='xx', geom='POINT(10 12)',
-                     address=dict(postcode='9486'))
+def test_postcodes_add_new(dsn, postcode_table, tmp_path,
+                           insert_implicit_postcode, tokenizer):
+    insert_implicit_postcode(1, 'xx', 'POINT(10 12)', dict(postcode='9486'))
     postcode_table.add('yy', '9486', 99, 34)
 
     postcodes.update_postcodes(dsn, tmp_path, tokenizer)
@@ -74,10 +80,9 @@ def test_postcodes_add_new(dsn, placex_table, postcode_table, tmp_path, tokenize
     assert postcode_table.row_set == {('xx', '9486', 10, 12), }
 
 
-def test_postcodes_replace_coordinates(dsn, placex_table, postcode_table,
-                                       tmp_path, tokenizer):
-    placex_table.add(country='xx', geom='POINT(10 12)',
-                     address=dict(postcode='AB 4511'))
+def test_postcodes_replace_coordinates(dsn, postcode_table, tmp_path,
+                                       insert_implicit_postcode, tokenizer):
+    insert_implicit_postcode(1, 'xx', 'POINT(10 12)', dict(postcode='AB 4511'))
     postcode_table.add('xx', 'AB 4511', 99, 34)
 
     postcodes.update_postcodes(dsn, tmp_path, tokenizer)
@@ -85,10 +90,9 @@ def test_postcodes_replace_coordinates(dsn, placex_table, postcode_table,
     assert postcode_table.row_set == {('xx', 'AB 4511', 10, 12)}
 
 
-def test_postcodes_replace_coordinates_close(dsn, placex_table, postcode_table,
-                                             tmp_path, tokenizer):
-    placex_table.add(country='xx', geom='POINT(10 12)',
-                     address=dict(postcode='AB 4511'))
+def test_postcodes_replace_coordinates_close(dsn, postcode_table, tmp_path,
+                                             insert_implicit_postcode, tokenizer):
+    insert_implicit_postcode(1, 'xx', 'POINT(10 12)', dict(postcode='AB 4511'))
     postcode_table.add('xx', 'AB 4511', 10, 11.99999)
 
     postcodes.update_postcodes(dsn, tmp_path, tokenizer)
@@ -96,9 +100,9 @@ def test_postcodes_replace_coordinates_close(dsn, placex_table, postcode_table,
     assert postcode_table.row_set == {('xx', 'AB 4511', 10, 11.99999)}
 
 
-def test_postcodes_remove(dsn, placex_table, postcode_table, tmp_path, tokenizer):
-    placex_table.add(country='xx', geom='POINT(10 12)',
-                     address=dict(postcode='AB 4511'))
+def test_postcodes_remove(dsn, postcode_table, tmp_path,
+                          insert_implicit_postcode, tokenizer):
+    insert_implicit_postcode(1, 'xx', 'POINT(10 12)', dict(postcode='AB 4511'))
     postcode_table.add('xx', 'badname', 10, 12)
 
     postcodes.update_postcodes(dsn, tmp_path, tokenizer)
@@ -106,32 +110,27 @@ def test_postcodes_remove(dsn, placex_table, postcode_table, tmp_path, tokenizer
     assert postcode_table.row_set == {('xx', 'AB 4511', 10, 12)}
 
 
-def test_postcodes_ignore_empty_country(dsn, placex_table, postcode_table, tmp_path, tokenizer):
-    placex_table.add(country=None, geom='POINT(10 12)',
-                     address=dict(postcode='AB 4511'))
-
+def test_postcodes_ignore_empty_country(dsn, postcode_table, tmp_path,
+                                        insert_implicit_postcode, tokenizer):
+    insert_implicit_postcode(1, None, 'POINT(10 12)', dict(postcode='AB 4511'))
     postcodes.update_postcodes(dsn, tmp_path, tokenizer)
-
     assert not postcode_table.row_set
 
 
-def test_postcodes_remove_all(dsn, postcode_table, tmp_path, tokenizer):
+def test_postcodes_remove_all(dsn, postcode_table, place_table,
+                              tmp_path, tokenizer):
     postcode_table.add('ch', '5613', 10, 12)
-
     postcodes.update_postcodes(dsn, tmp_path, tokenizer)
 
     assert not postcode_table.row_set
 
 
-def test_postcodes_multi_country(dsn, placex_table, postcode_table, tmp_path, tokenizer):
-    placex_table.add(country='de', geom='POINT(10 12)',
-                     address=dict(postcode='54451'))
-    placex_table.add(country='cc', geom='POINT(100 56)',
-                     address=dict(postcode='DD23 T'))
-    placex_table.add(country='de', geom='POINT(10.3 11.0)',
-                     address=dict(postcode='54452'))
-    placex_table.add(country='cc', geom='POINT(10.3 11.0)',
-                     address=dict(postcode='54452'))
+def test_postcodes_multi_country(dsn, postcode_table, tmp_path,
+                                 insert_implicit_postcode, tokenizer):
+    insert_implicit_postcode(1, 'de', 'POINT(10 12)', dict(postcode='54451'))
+    insert_implicit_postcode(2, 'cc', 'POINT(100 56)', dict(postcode='DD23 T'))
+    insert_implicit_postcode(3, 'de', 'POINT(10.3 11.0)', dict(postcode='54452'))
+    insert_implicit_postcode(4, 'cc', 'POINT(10.3 11.0)', dict(postcode='54452'))
 
     postcodes.update_postcodes(dsn, tmp_path, tokenizer)
 
@@ -142,10 +141,9 @@ def test_postcodes_multi_country(dsn, placex_table, postcode_table, tmp_path, to
 
 
 @pytest.mark.parametrize("gzipped", [True, False])
-def test_postcodes_extern(dsn, placex_table, postcode_table, tmp_path,
-                          tokenizer, gzipped):
-    placex_table.add(country='xx', geom='POINT(10 12)',
-                     address=dict(postcode='AB 4511'))
+def test_postcodes_extern(dsn, postcode_table, tmp_path,
+                          insert_implicit_postcode, tokenizer, gzipped):
+    insert_implicit_postcode(1, 'xx', 'POINT(10 12)', dict(postcode='AB 4511'))
 
     extfile = tmp_path / 'xx_postcodes.csv'
     extfile.write_text("postcode,lat,lon\nAB 4511,-4,-1\nCD 4511,-5, -10")
@@ -160,10 +158,9 @@ def test_postcodes_extern(dsn, placex_table, postcode_table, tmp_path,
                                       ('xx', 'CD 4511', -10, -5)}
 
 
-def test_postcodes_extern_bad_column(dsn, placex_table, postcode_table,
-                                     tmp_path, tokenizer):
-    placex_table.add(country='xx', geom='POINT(10 12)',
-                     address=dict(postcode='AB 4511'))
+def test_postcodes_extern_bad_column(dsn, postcode_table, tmp_path, 
+                                     insert_implicit_postcode, tokenizer):
+    insert_implicit_postcode(1, 'xx', 'POINT(10 12)', dict(postcode='AB 4511'))
 
     extfile = tmp_path / 'xx_postcodes.csv'
     extfile.write_text("postode,lat,lon\nAB 4511,-4,-1\nCD 4511,-5, -10")
@@ -173,10 +170,9 @@ def test_postcodes_extern_bad_column(dsn, placex_table, postcode_table,
     assert postcode_table.row_set == {('xx', 'AB 4511', 10, 12)}
 
 
-def test_postcodes_extern_bad_number(dsn, placex_table, postcode_table,
-                                     tmp_path, tokenizer):
-    placex_table.add(country='xx', geom='POINT(10 12)',
-                     address=dict(postcode='AB 4511'))
+def test_postcodes_extern_bad_number(dsn, insert_implicit_postcode,
+                                     postcode_table, tmp_path, tokenizer):
+    insert_implicit_postcode(1, 'xx', 'POINT(10 12)', dict(postcode='AB 4511'))
 
     extfile = tmp_path / 'xx_postcodes.csv'
     extfile.write_text("postcode,lat,lon\nXX 4511,-4,NaN\nCD 4511,-5, -10\n34,200,0")
@@ -185,3 +181,33 @@ def test_postcodes_extern_bad_number(dsn, placex_table, postcode_table,
 
     assert postcode_table.row_set == {('xx', 'AB 4511', 10, 12),
                                       ('xx', 'CD 4511', -10, -5)}
+
+def test_can_compute(dsn, table_factory):
+    assert not postcodes.can_compute(dsn)
+    table_factory('place')
+    assert postcodes.can_compute(dsn)
+
+def test_no_placex_entry(dsn, tmp_path, temp_db_cursor, place_row, postcode_table, tokenizer):
+    #Rewrite the get_country_code function to verify its execution.
+    temp_db_cursor.execute("""
+        CREATE OR REPLACE FUNCTION get_country_code(place geometry)
+        RETURNS TEXT AS $$ BEGIN 
+        RETURN 'fr';
+        END; $$ LANGUAGE plpgsql;
+    """)
+    place_row(geom='SRID=4326;POINT(10 12)', address=dict(postcode='AB 4511'))
+    postcodes.update_postcodes(dsn, tmp_path, tokenizer)
+
+    assert postcode_table.row_set == {('fr', 'AB 4511', 10, 12)}
+
+@pytest.fixture
+def insert_implicit_postcode(placex_table, place_row):
+    """
+        Inserts data into the placex and place table
+        which can then be used to compute one postcode.
+    """
+    def _insert_implicit_postcode(osm_id, country, geometry, address):
+        placex_table.add(osm_id=osm_id, country=country, geom=geometry)
+        place_row(osm_id=osm_id, geom='SRID=4326;'+geometry, address=address)
+
+    return _insert_implicit_postcode
index 1e10f0412abd5fc3052f04123902316e2a4b7483..5fb5252917002ecb1f6830db04f78571cfcbaa8d 100755 (executable)
@@ -244,6 +244,9 @@ server {
 EOF_NGINX_CONF
 #DOCS:```
 
+# If you have some errors, make sure that php7.4-fpm.sock is well under
+# /var/run/ and not under /var/run/php. Otherwise change the Nginx configuration
+# to /var/run/php/php7.4-fpm.sock.
 #
 # Enable the configuration and restart Nginx
 #