<?php
+/**
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * This file is part of Nominatim. (https://nominatim.org)
+ *
+ * Copyright (C) 2022 by the Nominatim developer community.
+ * For a full list of authors see the git log.
+ */
namespace Nominatim;
if (empty($this->aName)) {
$this->bNameNeedsAddress = $bNeedsAddress;
} else {
- $this->bNameNeedsAddress |= $bNeedsAddress;
+ $this->bNameNeedsAddress &= $bNeedsAddress;
}
if ($bSearchable) {
$this->aName[$iId] = $iId;
// Sort by existence of the requested house number but only if not
// too many results are expected for the street, i.e. if the result
- // will be narrowed down by an address. Remeber that with ordering
+ // will be narrowed down by an address. Remember that with ordering
// every single result has to be checked.
if ($this->sHouseNumber && ($this->bRareName || !empty($this->aAddress) || $this->sPostcode)) {
- $sHouseNumberRegex = '\\\\m'.$this->sHouseNumber.'\\\\M';
- $aOrder[] = ' (';
- $aOrder[0] .= 'EXISTS(';
- $aOrder[0] .= ' SELECT place_id';
- $aOrder[0] .= ' FROM placex';
- $aOrder[0] .= ' WHERE parent_place_id = search_name.place_id';
- $aOrder[0] .= " AND housenumber ~* E'".$sHouseNumberRegex."'";
- $aOrder[0] .= ' LIMIT 1';
- $aOrder[0] .= ') ';
- // also housenumbers from interpolation lines table are needed
- if (preg_match('/[0-9]+/', $this->sHouseNumber)) {
- $iHouseNumber = intval($this->sHouseNumber);
- $aOrder[0] .= 'OR EXISTS(';
- $aOrder[0] .= ' SELECT place_id ';
- $aOrder[0] .= ' FROM location_property_osmline ';
- $aOrder[0] .= ' WHERE parent_place_id = search_name.place_id';
- $aOrder[0] .= ' AND startnumber is not NULL';
- $aOrder[0] .= ' AND '.$iHouseNumber.'>=startnumber ';
- $aOrder[0] .= ' AND '.$iHouseNumber.'<=endnumber ';
- $aOrder[0] .= ' LIMIT 1';
- $aOrder[0] .= ')';
+ $sHouseNumberRegex = $oDB->getDBQuoted('\\\\m'.$this->sHouseNumber.'\\\\M');
+
+ // Housenumbers on streets and places.
+ $sChildHnr = 'SELECT * FROM placex WHERE parent_place_id = search_name.place_id';
+ $sChildHnr .= ' AND housenumber ~* E'.$sHouseNumberRegex;
+ // Interpolations on streets and places.
+ if (preg_match('/^[0-9]+$/', $this->sHouseNumber)) {
+ $sIpolHnr = 'WHERE parent_place_id = search_name.place_id ';
+ $sIpolHnr .= ' AND startnumber is not NULL';
+ $sIpolHnr .= ' AND '.$this->sHouseNumber.'>=startnumber ';
+ $sIpolHnr .= ' AND '.$this->sHouseNumber.'<=endnumber ';
+ } else {
+ $sIpolHnr = false;
}
- $aOrder[0] .= ') DESC';
+ // Housenumbers on the object iteself for unlisted places.
+ $sSelfHnr = 'SELECT * FROM placex WHERE place_id = search_name.place_id';
+ $sSelfHnr .= ' AND housenumber ~* E'.$sHouseNumberRegex;
+
+ $sSql = '(CASE WHEN address_rank = 30 THEN EXISTS('.$sSelfHnr.') ';
+ $sSql .= ' ELSE EXISTS('.$sChildHnr.') ';
+ if ($sIpolHnr) {
+ $sSql .= 'OR EXISTS(SELECT * FROM location_property_osmline '.$sIpolHnr.') ';
+ if (CONST_Use_US_Tiger_Data) {
+ $sSql .= "OR (country_code = 'us' AND ";
+ $sSql .= ' EXISTS(SELECT * FROM location_property_tiger '.$sIpolHnr.')) ';
+ }
+ }
+ $sSql .= 'END) DESC';
+
+
+ $aOrder[] = $sSql;
}
if (!empty($this->aName)) {
return $aResults;
}
- $sHouseNumberRegex = '\\\\m'.$this->sHouseNumber.'\\\\M';
+ $sHouseNumberRegex = $oDB->getDBQuoted('\\\\m'.$this->sHouseNumber.'\\\\M');
$sSQL = 'SELECT place_id FROM placex WHERE';
- $sSQL .= " housenumber ~* E'".$sHouseNumberRegex."'";
+ $sSQL .= ' housenumber ~* E'.$sHouseNumberRegex;
$sSQL .= ' AND ('.join(' OR ', $aIDCondition).')';
$sSQL .= $this->oContext->excludeSQL(' AND place_id');
// 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 ('.$sRoadPlaceIDs.') AND (';
- if ($iHousenumber % 2 == 0) {
- // If housenumber is even, look for housenumber in streets
- // with interpolationtype even or all.
- $sSQL .= "interpolationtype='even'";
- } else {
- // Else look for housenumber with interpolationtype odd or all.
- $sSQL .= "interpolationtype='odd'";
- }
- $sSQL .= " or interpolationtype='all') and ";
- $sSQL .= $iHousenumber.'>=startnumber and ';
- $sSQL .= $iHousenumber.'<=endnumber';
+ $sSQL .= ' and parent_place_id in ('.$sRoadPlaceIDs.')';
+ $sSQL .= ' and ('.$iHousenumber.' - startnumber) % step = 0';
+ $sSQL .= ' and '.$iHousenumber.' between startnumber and endnumber';
$sSQL .= $this->oContext->excludeSQL(' AND place_id');
Debug::printSQL($sSQL);
// If nothing found then search in Tiger data (location_property_tiger)
if (CONST_Use_US_Tiger_Data && $sRoadPlaceIDs && $bIsIntHouseNumber && empty($aResults)) {
$sSQL = 'SELECT place_id FROM location_property_tiger';
- $sSQL .= ' WHERE parent_place_id in ('.$sRoadPlaceIDs.') and (';
- if ($iHousenumber % 2 == 0) {
- $sSQL .= "interpolationtype='even'";
- } else {
- $sSQL .= "interpolationtype='odd'";
- }
- $sSQL .= " or interpolationtype='all') and ";
- $sSQL .= $iHousenumber.'>=startnumber and ';
- $sSQL .= $iHousenumber.'<=endnumber';
+ $sSQL .= ' WHERE parent_place_id in ('.$sRoadPlaceIDs.')';
+ $sSQL .= ' and ('.$iHousenumber.' - startnumber) % step = 0';
+ $sSQL .= ' and '.$iHousenumber.' between startnumber and endnumber';
$sSQL .= $this->oContext->excludeSQL(' AND place_id');
Debug::printSQL($sSQL);