{
// Check which tokens we have, get the ID numbers
$sSQL = 'SELECT word_id, word_token, type';
- $sSQL .= " info->>'cc' as country";
+ $sSQL .= " info->>'cc' as country, info->>'postcode' as postcode";
$sSQL .= ' FROM word WHERE word_token in (';
$sSQL .= join(',', $this->oDB->getDBQuotedList($aTokens)).')';
'H': // house number tokens
$oToken = new Token\HouseNumber($iId, $aWord['word_token']);
break;
+ 'P': // postcode tokens
+ // Postcodes are not normalized, so they may have content
+ // that makes SQL injection possible. Reject postcodes
+ // that would need special escaping.
+ if ($aWord['postcode'] === null
+ || pg_escape_string($aWord['postcode']) == $aWord['postcode']
+ ) {
+ continue;
+ }
+ $oToken = new Token\Postcode($iId, $aWord['postcode'], null);
default:
continue;
}
USING BTREE (word_token) {{db.tablespace.search_index}};
-- Used when updating country names from the boundary relation.
CREATE INDEX idx_word_country_names ON word
- USING btree((info->>'cc')) WHERE type = 'C';
+ USING btree((info->>'cc')) {{db.tablespace.address_index}}
+ WHERE type = 'C';
+-- Used when inserting new postcodes on updates.
+CREATE INDEX idx_word_postcodes ON word
+ USING btree((info->>'postcode')) {{db.tablespace.address_index}}
+ WHERE type = 'P'
GRANT SELECT ON word TO "{{config.DATABASE_WEBUSER}}";
DROP SEQUENCE IF EXISTS seq_word;
(SELECT pc, word FROM
(SELECT distinct(postcode) as pc FROM location_postcode) p
FULL JOIN
- (SELECT word FROM word
- WHERE class ='place' and type = 'postcode') w
+ (SELECT info->>'postcode' as word FROM word WHERE type = 'P') w
ON pc = word) x
WHERE pc is null or word is null""")
if postcode is None:
to_delete.append(word)
else:
- copystr.add(
- postcode,
- ' ' + self.name_processor.get_search_normalized(postcode),
- 'place', 'postcode', 0)
+ copystr.add(self.name_processor.get_search_normalized(postcode),
+ 'P', {'postcode': postcode})
if to_delete:
cur.execute("""DELETE FROM WORD
- WHERE class ='place' and type = 'postcode'
- and word = any(%s)
+ WHERE class ='P' and info->>'postcode' = any(%s)
""", (to_delete, ))
copystr.copy_out(cur, 'word',
- columns=['word', 'word_token', 'class', 'type',
- 'search_name_count'])
+ columns=['word_token', 'type', 'info'])
def update_special_phrases(self, phrases, should_replace):
with self.conn.cursor() as cur:
# no word_id needed for postcodes
- cur.execute("""INSERT INTO word (word, word_token, class, type,
- search_name_count)
- (SELECT pc, %s, 'place', 'postcode', 0
+ cur.execute("""INSERT INTO word (word_token, type, info)
+ (SELECT %s, 'P', json_build_object('postcode', pc)
FROM (VALUES (%s)) as v(pc)
WHERE NOT EXISTS
(SELECT * FROM word
- WHERE word = pc and class='place' and type='postcode'))
- """, (' ' + term, postcode))
+ WHERE type = 'P' and info->>postcode = pc))
+ """, (term, postcode))
self._cache.postcodes.add(postcode)