Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions OFL.g4
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ hashtagListMatch: HASHTAG ':' '(' string (',' string)* ')';

typeMatch: TYPE ':' OSMTYPE;
idMatch: ID ':' NUMBER;
typeIdMatch: ID ':' OSMID;
typeIdMatch: ID ':' osmid;
idRangeMatch: ID ':' '(' range_int ')';
idListMatch: ID ':' '(' NUMBER (',' NUMBER)* ')';
typeIdListMatch: ID ':' '(' OSMID (',' OSMID)* ')';
typeIdListMatch: ID ':' '(' osmid (',' osmid)* ')';
osmid: OSMID | SHORT_OSMID;

geometryMatch: GEOMETRY ':' GEOMETRY_TYPE;
areaRangeMatch: AREA ':' '(' range_dec ')';
Expand Down Expand Up @@ -102,7 +103,9 @@ CHANGESET_CREATEDBY: 'changeset.created_by';
HASHTAG: 'hashtag';

OSMTYPE: 'node' | 'way' | 'relation';
OSMTYPE_SHORT: 'n' | 'w' | 'r';
OSMID: OSMTYPE '/' NUMBER;
SHORT_OSMID: OSMTYPE_SHORT NUMBER;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe for consistency change this to

Suggested change
SHORT_OSMID: OSMTYPE_SHORT NUMBER;
OSMID_SHORT: OSMTYPE_SHORT NUMBER;

GEOMETRY_TYPE: 'point' | 'line' | 'polygon' | 'other';

NUMBER: NUMERAL+;
Expand Down
259 changes: 132 additions & 127 deletions ohsome_filter_to_sql/OFLLexer.py

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions ohsome_filter_to_sql/OFLListener.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,15 @@ def exitTypeIdListMatch(self, ctx:OFLParser.TypeIdListMatchContext):
pass


# Enter a parse tree produced by OFLParser#osmid.
def enterOsmid(self, ctx:OFLParser.OsmidContext):
pass

# Exit a parse tree produced by OFLParser#osmid.
def exitOsmid(self, ctx:OFLParser.OsmidContext):
pass


# Enter a parse tree produced by OFLParser#geometryMatch.
def enterGeometryMatch(self, ctx:OFLParser.GeometryMatchContext):
pass
Expand Down
846 changes: 451 additions & 395 deletions ohsome_filter_to_sql/OFLParser.py

Large diffs are not rendered by default.

16 changes: 14 additions & 2 deletions ohsome_filter_to_sql/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import sys
from collections import deque
from typing import Any

from antlr4 import CommonTokenStream, InputStream, ParserRuleContext, ParseTreeWalker
from antlr4.error.ErrorListener import ErrorListener
Expand Down Expand Up @@ -133,7 +134,8 @@ def exitIdMatch(self, ctx: ParserRuleContext):
self.stack.append(f"osm_id = {id}")

def exitTypeIdMatch(self, ctx: ParserRuleContext):
type_, id = ctx.getChild(2).getText().split("/")
matched_text = ctx.getChild(2).getText()
id, type_ = handle_short_hand_or_normal_osm_id(matched_text)
self.stack.append(f"(osm_type = '{type_}' AND osm_id = {id})")

def exitIdRangeMatch(self, ctx: ParserRuleContext):
Expand Down Expand Up @@ -167,7 +169,7 @@ def exitTypeIdListMatch(self, ctx: ParserRuleContext):
# skip comma in list in between brackets
if child == ",":
continue
type_, id = child.split("/")
id, type_ = handle_short_hand_or_normal_osm_id(child)
values.append(f"(osm_id = {id} AND osm_type = '{type_}')")
if len(values) > 1:
values_as_string = "(" + " OR ".join(values) + ")"
Expand Down Expand Up @@ -278,6 +280,16 @@ def unescape(string: str):
return string


def handle_short_hand_or_normal_osm_id(matched_text: str) -> tuple[str, int]:
matched_text = matched_text.replace("(", "").replace(")", "")
if "/" in matched_text:
type_, id = matched_text.split("/")
else:
type_short_mapping = {"n": "node", "w": "way", "r": "relation"}
type_ = type_short_mapping[matched_text[0]]
id = matched_text[1:]
return id, type_

def ohsome_filter_to_sql(filter: str) -> str:
listener = OFLToSql()
tree = build_tree(filter)
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
([] ([64] ([2 64] ([84 2 64] type : node)) and ([107 64] ([79 107 64] ([116 79 107 64] natural) = ([118 79 107 64] tree)))) <EOF>)
([] ([66] ([2 66] ([86 2 66] type : node)) and ([109 66] ([81 109 66] ([118 81 109 66] natural) = ([120 81 109 66] tree)))) <EOF>)
Original file line number Diff line number Diff line change
@@ -1 +1 @@
([] ([64] ([2 64] ([89 2 64] id : ( node/1 , way/2 ))) and ([107 64] ([84 107 64] type : way))) <EOF>)
([] ([66] ([2 66] ([91 2 66] id : ( ([203 91 2 66] node/1) , ([205 91 2 66] way/2) ))) and ([109 66] ([86 109 66] type : way))) <EOF>)
Original file line number Diff line number Diff line change
@@ -1 +1 @@
([] ([64] ([79 64] ([116 79 64] natural) = ([118 79 64] tree))) <EOF>)
([] ([66] ([81 66] ([118 81 66] natural) = ([120 81 66] tree))) <EOF>)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
id:n4540889804

(osm_type = 'node' AND osm_id = 4540889804)

[<Record count=8>]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
id:(r4540889804)

(osm_id = 4540889804 AND osm_type = 'relation')

[<Record count=0>]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
id:w4540889804

(osm_type = 'way' AND osm_id = 4540889804)

[<Record count=0>]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
id:r4540889804

(osm_type = 'relation' AND osm_id = 4540889804)

[<Record count=0>]
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
id:(node/4540889804, way/1136431018, )

line 1:37 missing OSMID at ')'
line 1:37 missing {OSMID, SHORT_OSMID} at ')'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"2299538076": {"results": [{"count": 0}], "query": "SELECT COUNT(*) FROM contributions WHERE (osm_id = 4540889804 AND osm_type = 'relation')", "args": [], "limit": 0, "timeout": null, "record_class": null}, "3010097021": {"results": [{"count": 0}], "query": "SELECT COUNT(*) FROM contributions WHERE (osm_type = 'relation' AND osm_id = 4540889804)", "args": [], "limit": 0, "timeout": null, "record_class": null}, "3569995583": {"results": [{"count": 0}], "query": "SELECT COUNT(*) FROM contributions WHERE (osm_type = 'way' AND osm_id = 4540889804)", "args": [], "limit": 0, "timeout": null, "record_class": null}, "2392719313": {"results": [{"count": 8}], "query": "SELECT COUNT(*) FROM contributions WHERE (osm_type = 'node' AND osm_id = 4540889804)", "args": [], "limit": 0, "timeout": null, "record_class": null}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"2299538076": {"results": [{"count": 0}], "query": "SELECT COUNT(*) FROM contributions WHERE (osm_id = 4540889804 AND osm_type = 'relation')", "args": [], "limit": 0, "timeout": null, "record_class": null}, "437655465": {"results": [{"count": 0}], "query": "SELECT COUNT(*) FROM contributions WHERE (osm_id = 4540889804 AND osm_type = 'way')", "args": [], "limit": 0, "timeout": null, "record_class": null}, "2355357960": {"results": [{"count": 8}], "query": "SELECT COUNT(*) FROM contributions WHERE (osm_id = 4540889804 AND osm_type = 'node')", "args": [], "limit": 0, "timeout": null, "record_class": null}}
33 changes: 33 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,21 @@ async def test_type_id_list_match_invalid(filter):
verify(filter + "\n\n" + str(e.value))


@pytest.mark.parametrize(
"filter",
(
"id:n4540889804",
"id:w4540889804",
"id:r4540889804",
"id:(r4540889804)",
),
)
@asyncpg_recorder.use_cassette
async def test_short_type_id_list_match(db_con, filter):
sql = ohsome_filter_to_sql(filter)
assert await validate_and_verify(db_con, sql, filter)


@pytest.mark.parametrize(
"filter",
(
Expand Down Expand Up @@ -667,3 +682,21 @@ async def test_climate_action_navigator_examples(db_con, filter):
async def test_strings(str, out):
assert unescape(str) == out
# fmt: on

@pytest.mark.parametrize(
"filters",
(
("id:(node/4540889804)", "id:(n4540889804)"),
("id:(way/4540889804)", "id:(w4540889804)"),
("id:(relation/4540889804)", "id:(r4540889804)"),
),
)
@asyncpg_recorder.use_cassette
async def test_shorthand_osm_type_comparison(db_con, filters):
sql_where_clause_1 = ohsome_filter_to_sql(filters[0])
sql_where_clause_2 = ohsome_filter_to_sql(filters[1])
sql_1 = "SELECT COUNT(*) FROM contributions WHERE " + sql_where_clause_1
sql_2 = "SELECT COUNT(*) FROM contributions WHERE " + sql_where_clause_2
results_1: list[Record] = await db_con.fetch(sql_1)
results_2: list[Record] = await db_con.fetch(sql_2)
assert results_1 == results_2