def check_location_property_osmline(context, oid, neg): """ Check that the given way is present in the interpolation table. """ with context.db.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur: cur.execute("""SELECT *, ST_AsText(linegeo) as geomtxt FROM location_property_osmline WHERE osm_id = %s AND startnumber IS NOT NULL""", (oid, )) if neg: assert cur.rowcount == 0, "Interpolation found for way {}.".format(oid) return todo = list(range(len(list(context.table)))) for res in cur: for i in todo: row = context.table[i] if (int(row['start']) == res['startnumber'] and int(row['end']) == res['endnumber']): todo.remove(i) break else: assert False, "Unexpected row " + str(res) DBRow(oid, res, context).assert_row(row, ('start', 'end')) assert not todo
def check_place_contents(context, table, exact): """ Check contents of place/placex tables. Each row represents a table row and all data must match. Data not present in the expected table, may be arbitry. The rows are identified via the 'object' column which must have an identifier of the form '<NRW><osm id>[:<class>]'. When multiple rows match (for example because 'class' was left out and there are multiple entries for the given OSM object) then all must match. All expected rows are expected to be present with at least one database row. When 'exactly' is given, there must not be additional rows in the database. """ with context.db.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur: expected_content = set() for row in context.table: nid = NominatimID(row['object']) query = 'SELECT *, ST_AsText(geometry) as geomtxt, ST_GeometryType(geometry) as geometrytype' if table == 'placex': query += ' ,ST_X(centroid) as cx, ST_Y(centroid) as cy' query += " FROM %s WHERE {}" % (table, ) nid.query_osm_id(cur, query) assert cur.rowcount > 0, "No rows found for " + row['object'] for res in cur: if exact: expected_content.add((res['osm_type'], res['osm_id'], res['class'])) DBRow(nid, res, context).assert_row(row, ['object']) if exact: cur.execute('SELECT osm_type, osm_id, class from {}'.format(table)) assert expected_content == set([(r[0], r[1], r[2]) for r in cur])
def check_location_postcode(context): """ Check full contents for location_postcode table. Each row represents a table row and all data must match. Data not present in the expected table, may be arbitry. The rows are identified via 'country' and 'postcode' columns. All rows must be present as excepted and there must not be additional rows. """ with context.db.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur: cur.execute( "SELECT *, ST_AsText(geometry) as geomtxt FROM location_postcode") assert cur.rowcount == len(list(context.table)), \ "Postcode table has {} rows, expected {}.".foramt(cur.rowcount, len(list(context.table))) results = {} for row in cur: key = (row['country_code'], row['postcode']) assert key not in results, "Postcode table has duplicate entry: {}".format( row) results[key] = DBRow((row['country_code'], row['postcode']), row, context) for row in context.table: db_row = results.get((row['country'], row['postcode'])) assert db_row is not None, \ "Missing row for country '{r['country']}' postcode '{r['postcode']}'.".format(r=row) db_row.assert_row(row, ('country', 'postcode'))
def check_search_name_contents(context, exclude): """ Check contents of place/placex tables. Each row represents a table row and all data must match. Data not present in the expected table, may be arbitry. The rows are identified via the 'object' column which must have an identifier of the form '<NRW><osm id>[:<class>]'. All expected rows are expected to be present with at least one database row. """ with context.db.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur: for row in context.table: nid = NominatimID(row['object']) nid.row_by_place_id( cur, 'search_name', ['ST_X(centroid) as cx', 'ST_Y(centroid) as cy']) assert cur.rowcount > 0, "No rows found for " + row['object'] for res in cur: db_row = DBRow(nid, res, context) for name, value in zip(row.headings, row.cells): if name in ('name_vector', 'nameaddress_vector'): items = [x.strip() for x in value.split(',')] with context.db.cursor() as subcur: subcur.execute( """ SELECT word_id, word_token FROM word, (SELECT unnest(%s::TEXT[]) as term) t WHERE word_token = make_standard_name(t.term) and class is null and country_code is null and operator is null UNION SELECT word_id, word_token FROM word, (SELECT unnest(%s::TEXT[]) as term) t WHERE word_token = ' ' || make_standard_name(t.term) and class is null and country_code is null and operator is null """, (list( filter(lambda x: not x.startswith('#'), items)), list( filter(lambda x: x.startswith('#'), items)))) if not exclude: assert subcur.rowcount >= len(items), \ "No word entry found for {}. Entries found: {!s}".format(value, subcur.rowcount) for wid in subcur: present = wid[0] in res[name] if exclude: assert not present, "Found term for {}/{}: {}".format( row['object'], name, wid[1]) else: assert present, "Missing term for {}/{}: {}".fromat( row['object'], name, wid[1]) elif name != 'object': assert db_row.contains(name, value), db_row.assert_msg( name, value)
def check_search_name_contents(context, exclude): """ Check contents of place/placex tables. Each row represents a table row and all data must match. Data not present in the expected table, may be arbitry. The rows are identified via the 'object' column which must have an identifier of the form '<NRW><osm id>[:<class>]'. All expected rows are expected to be present with at least one database row. """ tokenizer = tokenizer_factory.get_tokenizer_for_db( context.nominatim.get_test_config()) with tokenizer.name_analyzer() as analyzer: with context.db.cursor( cursor_factory=psycopg2.extras.DictCursor) as cur: for row in context.table: nid = NominatimID(row['object']) nid.row_by_place_id( cur, 'search_name', ['ST_X(centroid) as cx', 'ST_Y(centroid) as cy']) assert cur.rowcount > 0, "No rows found for " + row['object'] for res in cur: db_row = DBRow(nid, res, context) for name, value in zip(row.headings, row.cells): if name in ('name_vector', 'nameaddress_vector'): items = [x.strip() for x in value.split(',')] tokens = analyzer.get_word_token_info( context.db, items) if not exclude: assert len(tokens) >= len(items), \ "No word entry found for {}. Entries found: {!s}".format(value, len(tokens)) for word, token, wid in tokens: if exclude: assert wid not in res[name], \ "Found term for {}/{}: {}".format(nid, name, wid) else: assert wid in res[name], \ "Missing term for {}/{}: {}".format(nid, name, wid) elif name != 'object': assert db_row.contains(name, value), db_row.assert_msg( name, value)
def check_place_addressline(context): """ Check the contents of the place_addressline table. Each row represents a table row and all data must match. Data not present in the expected table, may be arbitry. The rows are identified via the 'object' column, representing the addressee and the 'address' column, representing the address item. """ with context.db.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur: for row in context.table: nid = NominatimID(row['object']) pid = nid.get_place_id(cur) apid = NominatimID(row['address']).get_place_id(cur) cur.execute(""" SELECT * FROM place_addressline WHERE place_id = %s AND address_place_id = %s""", (pid, apid)) assert cur.rowcount > 0, \ "No rows found for place %s and address %s" % (row['object'], row['address']) for res in cur: DBRow(nid, res, context).assert_row(row, ('address', 'object'))