Skip to content

Commit

Permalink
feat: add support for query datasets (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
noahgorstein authored Jun 27, 2023
1 parent fcff786 commit 651c341
Show file tree
Hide file tree
Showing 2 changed files with 326 additions and 0 deletions.
19 changes: 19 additions & 0 deletions stardog/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,12 @@ def __query(self, query, method, content_type=None, **kwargs):
"timeout": kwargs.get("timeout"),
"reasoning": kwargs.get("reasoning"),
"prettify": kwargs.get("prettify"),
"default-graph-uri": kwargs.get("default_graph_uri"),
"named-graph-uri": kwargs.get("named_graph_uri"),
"using-graph-uri": kwargs.get("using_graph_uri"),
"using-named-graph-uri": kwargs.get("using_named_graph_uri"),
"remove-graph-uri": kwargs.get("remove_graph_uri"),
"insert-graph-uri": kwargs.get("insert_graph_uri"),
}

# query bindings
Expand Down Expand Up @@ -375,6 +381,9 @@ def select(self, query, content_type=content_types.SPARQL_JSON, **kwargs):
values
content_type (str, optional): Content type for results.
Defaults to 'application/sparql-results+json'
default_graph_uri (str, list[str], optional): URI(s) to be used as the default graph (equivalent to FROM)
named_graph_uri (str, list[str], optional): URI(s) to be used as named graphs (equivalent to FROM NAMED)
Returns:
dict: If content_type='application/sparql-results+json'
Expand Down Expand Up @@ -407,6 +416,8 @@ def graph(self, query, content_type=content_types.TURTLE, **kwargs):
values
content_type (str): Content type for results.
Defaults to 'text/turtle'
default_graph_uri (str, list[str], optional): URI(s) to be used as the default graph (equivalent to FROM)
named_graph_uri (str, list[str], optional): URI(s) to be used as named graphs (equivalent to FROM NAMED)
Returns:
str: Results in format given by content_type
Expand Down Expand Up @@ -437,6 +448,8 @@ def paths(self, query, content_type=content_types.SPARQL_JSON, **kwargs):
values
content_type (str): Content type for results.
Defaults to 'application/sparql-results+json'
default_graph_uri (str, list[str], optional): URI(s) to be used as the default graph (equivalent to FROM)
named_graph_uri (str, list[str], optional): URI(s) to be used as named graphs (equivalent to FROM NAMED)
Returns:
dict: if content_type='application/sparql-results+json'.
Expand All @@ -463,6 +476,8 @@ def ask(self, query, **kwargs):
reasoning (bool, optional): Enable reasoning for the query
bindings (dict, optional): Map between query variables and their
values
default_graph_uri (str, list[str], optional): URI(s) to be used as the default graph (equivalent to FROM)
named_graph_uri (str, list[str], optional): URI(s) to be used as named graphs (equivalent to FROM NAMED)
Returns:
bool: Result of ask query
Expand All @@ -486,6 +501,10 @@ def update(self, query, **kwargs):
reasoning (bool, optional): Enable reasoning for the query
bindings (dict, optional): Map between query variables and their
values
using_graph_uri (str, list[str], optional): URI(s) to be used as the default graph (equivalent to USING)
using_named_graph_uri (str, list[str], optional): URI(s) to be used as named graphs (equivalent to USING NAMED)
remove_graph_uri (str, optional): URI of the graph to be removed from
insert_graph_uri (str, optional): URI of the graph to be inserted into
Examples:
>>> conn.update('delete where {?s ?p ?o}')
Expand Down
307 changes: 307 additions & 0 deletions test/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,313 @@ def test_user_impersonation(conn_string, db, user):
admin_impersonating_user.select('select * {?s :name "Luke Skywalker"}')


@pytest.mark.dbname("pystardog-test-database")
@pytest.mark.conn_dbname("pystardog-test-database")
def test_select_with_default_graph_uri(db, conn: connection.Connection):

graph1 = "http://graph1"
graph1_content = """
@prefix ex: <http://example.com/> .
<ex:a> <ex:b> <ex:c> .
<ex:d> <ex:e> <ex:f> .
"""
graph2 = "http://graph2"
graph2_content = """
@prefix ex: <http://example.com/> .
<ex:g> <ex:h> <ex:i> .
"""

conn.begin()
conn.clear()
conn.add(
content=content.Raw(content=graph1_content, content_type=content_types.TURTLE),
graph_uri=graph1,
)
conn.add(
content=content.Raw(content=graph2_content, content_type=content_types.TURTLE),
graph_uri=graph2,
)
conn.commit()

response = conn.select(
query="select * { ?s ?p ?o }",
default_graph_uri=[graph1],
)
assert len(response["results"]["bindings"]) == 2

response = conn.select(
query="select * { ?s ?p ?o }",
default_graph_uri=[graph2],
)
assert len(response["results"]["bindings"]) == 1

response = conn.select(
query="select * { ?s ?p ?o }",
default_graph_uri=[graph1, graph2],
)
assert len(response["results"]["bindings"]) == 3


@pytest.mark.dbname("pystardog-test-database")
@pytest.mark.conn_dbname("pystardog-test-database")
def test_select_with_named_graph_uri(db, conn: connection.Connection):

graph1 = "http://graph1"
graph1_content = """
@prefix ex: <http://example.com/> .
<ex:a> <ex:b> <ex:c> .
<ex:d> <ex:e> <ex:f> .
"""
graph2 = "http://graph2"
graph2_content = """
@prefix ex: <http://example.com/> .
<ex:g> <ex:h> <ex:i> .
"""

conn.begin()
conn.clear()
conn.add(
content=content.Raw(content=graph1_content, content_type=content_types.TURTLE),
graph_uri=graph1,
)
conn.add(
content=content.Raw(content=graph2_content, content_type=content_types.TURTLE),
graph_uri=graph2,
)
conn.commit()

response = conn.select(
query="select * { GRAPH ?g { ?s ?p ?o }}",
named_graph_uri=[graph1],
)
assert len(response["results"]["bindings"]) == 2

response = conn.select(
query="select * { GRAPH ?g { ?s ?p ?o }}",
named_graph_uri=[graph2],
)
assert len(response["results"]["bindings"]) == 1

response = conn.select(
query="select * { GRAPH ?g { ?s ?p ?o }}",
named_graph_uri=[graph1, graph2],
)
assert len(response["results"]["bindings"]) == 3


@pytest.mark.dbname("pystardog-test-database")
@pytest.mark.conn_dbname("pystardog-test-database")
def test_update_with_using_graph_uri(db, conn: connection.Connection):

graph1 = "http://graph1"
graph1_content = """
@prefix ex: <http://example.com/> .
<ex:a> <ex:b> <ex:c> .
<ex:d> <ex:e> <ex:f> .
"""
graph2 = "http://graph2"
graph2_content = """
@prefix ex: <http://example.com/> .
<ex:g> <ex:h> <ex:i> .
"""

insert_into_graph1 = f"""
INSERT {{
GRAPH <{graph1}> {{
?s <urn:z> ?o
}}
}}
WHERE {{
?s ?p ?o
}}
"""

graph3 = "http://graph3"
insert_into_graph3 = f"""
INSERT {{
GRAPH <{graph3}> {{
?s ?p ?o
}}
}}
WHERE {{
?s ?p ?o
}}
"""

conn.begin()
conn.clear()
conn.add(
content=content.Raw(content=graph1_content, content_type=content_types.TURTLE),
graph_uri=graph1,
)
conn.add(
content=content.Raw(content=graph2_content, content_type=content_types.TURTLE),
graph_uri=graph2,
)
conn.commit()

# update graph1
response = conn.select(
query="select * { ?s ?p ?o }",
default_graph_uri=[graph1],
)
assert len(response["results"]["bindings"]) == 2

conn.begin()
conn.update(
query=insert_into_graph1,
using_graph_uri=[graph1],
)
conn.commit()

response = conn.select(
query="select * { ?s ?p ?o }",
default_graph_uri=[graph1],
)
assert len(response["results"]["bindings"]) == 4

# create/update graph3 with contents of graph1 and graph2
response = conn.select(
query="select * { ?s ?p ?o }",
default_graph_uri=[graph2],
)
assert len(response["results"]["bindings"]) == 1

conn.begin()
conn.update(
query=insert_into_graph3,
using_graph_uri=[graph1, graph2],
)
conn.commit()

response = conn.select(
query="select * { ?s ?p ?o }",
default_graph_uri=[graph3],
)
assert len(response["results"]["bindings"]) == 5


@pytest.mark.dbname("pystardog-test-database")
@pytest.mark.conn_dbname("pystardog-test-database")
def test_update_with_using_named_graph_uri(db, conn: connection.Connection):

graph1 = "http://graph1"
graph1_content = """
@prefix ex: <http://example.com/> .
<ex:a> <ex:b> <ex:c> .
<ex:d> <ex:e> <ex:f> .
"""
graph2 = "http://graph2"
graph2_content = """
@prefix ex: <http://example.com/> .
<ex:g> <ex:h> <ex:i> .
"""

graph3 = "http://graph3"
insert_into_graph3 = f"""
INSERT {{
GRAPH <{graph3}> {{
?s ?p ?o
}}
}}
WHERE {{
GRAPH ?g {{
?s ?p ?o
}}
}}
"""

conn.begin()
conn.clear()
conn.add(
content=content.Raw(content=graph1_content, content_type=content_types.TURTLE),
graph_uri=graph1,
)
conn.add(
content=content.Raw(content=graph2_content, content_type=content_types.TURTLE),
graph_uri=graph2,
)
conn.commit()

conn.begin()
conn.update(
query=insert_into_graph3,
using_named_graph_uri=[graph1, graph2],
)
conn.commit()

response = conn.select(
query="select * { ?s ?p ?o }",
default_graph_uri=[graph3],
)
assert len(response["results"]["bindings"]) == 3


@pytest.mark.dbname("pystardog-test-database")
@pytest.mark.conn_dbname("pystardog-test-database")
def test_update_with_insert_graph_uri(db, conn: connection.Connection):

the_graph = "http://my-graph"
query = """
INSERT DATA {
<ex:a> <ex:b> <ex:c> .
<ex:d> <ex:e> <ex:f> .
}
"""

conn.begin()
conn.update(query=query, insert_graph_uri=the_graph)
conn.commit()

response = conn.select(
query="select * { ?s ?p ?o }",
default_graph_uri=[the_graph],
)
assert len(response["results"]["bindings"]) == 2


@pytest.mark.dbname("pystardog-test-database")
@pytest.mark.conn_dbname("pystardog-test-database")
def test_update_with_remove_graph_uri(db, conn: connection.Connection):

the_graph = "http://my-graph"
insert_data = """
INSERT DATA {
<ex:a> <ex:b> <ex:c> .
<ex:d> <ex:e> <ex:f> .
}
"""

delete_data = """
DELETE DATA {
<ex:a> <ex:b> <ex:c> .
<ex:d> <ex:e> <ex:f> .
}
"""

# first insert data
conn.begin()
conn.update(query=insert_data, insert_graph_uri=the_graph)
conn.commit()

response = conn.select(
query="select * { ?s ?p ?o }",
default_graph_uri=[the_graph],
)
assert len(response["results"]["bindings"]) == 2

# now remove it
conn.begin()
conn.update(query=delete_data, remove_graph_uri=the_graph)
conn.commit()

response = conn.select(
query="select * { ?s ?p ?o }",
default_graph_uri=[the_graph],
)
assert len(response["results"]["bindings"]) == 0


@pytest.mark.dbname("pystardog-test-database")
@pytest.mark.conn_dbname("pystardog-test-database")
def test_queries(db, conn):
Expand Down

0 comments on commit 651c341

Please sign in to comment.