Skip to content

Commit 78d4d44

Browse files
authored
Merge pull request #38 from INCATools/safe-rg
make ontology safe for relation graph; add view2table
2 parents 8282065 + beb2984 commit 78d4d44

6 files changed

Lines changed: 192 additions & 134 deletions

File tree

poetry.lock

Lines changed: 137 additions & 113 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ authors = ["cmungall <cjm@berkeleybop.org>"]
66

77
[tool.poetry.dependencies]
88
python = "^3.8"
9-
linkml = "^1.2.10"
9+
linkml = "^1.2.11"
1010
SQLAlchemy-Utils = "^0.38.2"
1111
click = "^8.1.3"
1212

src/semsql/builder/build.Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ $(TEMPLATE): $(THIS_DIR)/sql_schema/semsql.sql
3838
mv $@.tmp $@
3939
.PRECIOUS: $(TEMPLATE)
4040

41+
%-min.owl: %.owl
42+
robot remove -i $< --axioms "equivalent disjoint annotation" -o $@
43+
4144
# -- MAIN TARGET --
4245
# A db is constructed from
4346
# (1) triples loaded using rdftab
@@ -61,7 +64,7 @@ $(TEMPLATE): $(THIS_DIR)/sql_schema/semsql.sql
6164
# will be simplified in future. See:
6265
# - https://github.com/balhoff/relation-graph/issues/123
6366
# - https://github.com/balhoff/relation-graph/issues/25
64-
%-$(RGSUFFIX).tsv: %.owl
67+
%-$(RGSUFFIX).tsv: %-min.owl
6568
$(RG) --disable-owl-nothing true \
6669
--ontology-file $<\
6770
--output-file $@.ttl.tmp \

src/semsql/builder/cli.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import click
44
import logging
55
import semsql.builder.builder as builder
6+
from linkml_runtime import SchemaView
7+
from linkml_runtime.utils.formatutils import underscore
8+
from semsql.sqlutils.viewgen import get_viewdef
69
from sqlalchemy import text
710

811

@@ -68,6 +71,40 @@ def query(input, query):
6871
print(row)
6972

7073

74+
@main.command()
75+
@click.argument('inputs', nargs=-1)
76+
@click.option('--index/--no-index', default=True, help='Create indexes on each column')
77+
@click.option('--name', '-n', help='Name of class/view to materialize. If blank, will perform for ALL')
78+
def view2table(inputs, name: str, index: bool):
79+
"""
80+
Generates a command that turns a view into a table
81+
82+
See https://github.com/cmungall/semantic-sql/issues/9
83+
84+
Example usage:
85+
```
86+
semsql view2table src/linkml/rdf.yaml -n rdfs_label_statement | sqlite3 db/pato.db
87+
```
88+
"""
89+
for input in inputs:
90+
with open(input, 'r') as stream:
91+
sv = SchemaView(input)
92+
schema = sv.schema
93+
for cn, c in sv.all_classes().items():
94+
tn = underscore(cn)
95+
if name is None or str(cn) == name or tn == name:
96+
view = get_viewdef(c)
97+
if view is not None:
98+
print(f'DROP VIEW {tn};')
99+
print(f'CREATE TABLE {tn} AS {view};')
100+
if index:
101+
for sn in sv.class_slots(cn):
102+
colname = underscore(sn)
103+
print(f'CREATE INDEX {tn}_{colname} ON {tn}({colname});')
104+
else:
105+
logging.error(f'No view for {cn}')
106+
107+
71108

72109
if __name__ == '__main__':
73110
main()

src/semsql/sqlutils/view2table.py

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
import click
22
from typing import List
3+
4+
from linkml_runtime import SchemaView
35
from linkml_runtime.linkml_model import SchemaDefinition, ClassDefinitionName, SlotDefinitionName
4-
from linkml.utils.formatutils import underscore
5-
from linkml.utils.schemaloader import SchemaLoader
6-
from semsql import get_viewdef
7-
8-
def all_slots(schema: SchemaDefinition, cn: ClassDefinitionName) -> List[SlotDefinitionName]:
9-
c = schema.classes[cn]
10-
slots = list(c.slots)
11-
if c.is_a:
12-
slots += all_slots(schema, c.is_a)
13-
if c.mixins:
14-
for m in c.mixins:
15-
slots += all_slots(schema, m)
16-
return slots
6+
from linkml_runtime.utils.formatutils import underscore
7+
from semsql.sqlutils.viewgen import get_viewdef
8+
9+
10+
1711

1812
@click.command()
1913
@click.argument('inputs', nargs=-1)
@@ -32,16 +26,17 @@ def cli(inputs, name: str, index: bool):
3226
"""
3327
for input in inputs:
3428
with open(input, 'r') as stream:
35-
schema = SchemaLoader(input).schema
36-
for cn, c in schema.classes.items():
29+
sv = SchemaView(input)
30+
schema = sv.schema
31+
for cn, c in sv.all_classes().items():
3732
tn = underscore(cn)
3833
if name is None or str(cn) == name or tn == name:
39-
view = get_viewdef(schema, c)
34+
view = get_viewdef(c)
4035
if view is not None:
4136
print(f'DROP VIEW {tn};')
4237
print(f'CREATE TABLE {tn} AS {view};')
4338
if index:
44-
for sn in all_slots(schema, cn):
39+
for sn in sv.class_slots(cn):
4540
colname = underscore(sn)
4641
print(f'CREATE INDEX {tn}_{colname} ON {tn}({colname});')
4742

src/semsql/sqlutils/viewgen.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import click
2-
from typing import List
32
from linkml_runtime.linkml_model import SchemaDefinition, ClassDefinition
43
from linkml.utils.schemaloader import load_raw_schema, SchemaLoader
54
from linkml_runtime.utils.formatutils import underscore
65

76
VIEW_CODE = 'sqlview>>'
87

9-
def get_viewdef(schema: SchemaDefinition, c: ClassDefinition) -> str:
8+
def get_viewdef(c: ClassDefinition) -> str:
109
"""
1110
Return all VIEW definitions for a class
1211
:param schema:

0 commit comments

Comments
 (0)