Skip to content

Commit 4885929

Browse files
committed
separate out table definitions to own module, some cleanup around their naming and creation
1 parent 4204845 commit 4885929

File tree

1 file changed

+49
-151
lines changed

1 file changed

+49
-151
lines changed

rdflib_sqlalchemy/store.py

Lines changed: 49 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import hashlib
55
import logging
66
import re
7-
import sys
87

98
import sqlalchemy
109
from rdflib import (
@@ -13,24 +12,31 @@
1312
RDF,
1413
URIRef
1514
)
16-
from rdflib.graph import Graph
17-
from rdflib.graph import QuotedGraph
18-
from rdflib.plugins.stores.regexmatching import PYTHON_REGEX
19-
from rdflib.plugins.stores.regexmatching import REGEXTerm
15+
from rdflib.graph import Graph, QuotedGraph
16+
from rdflib.plugins.stores.regexmatching import PYTHON_REGEX, REGEXTerm
2017
from rdflib.store import Store
21-
from rdflib.term import Node
2218
from six import text_type
2319
from six.moves import reduce
24-
from sqlalchemy import Column, Table, MetaData, Index, types
20+
from sqlalchemy import MetaData
2521
from sqlalchemy.engine import reflection
2622
from sqlalchemy.sql import select, expression
2723

2824
from rdflib_sqlalchemy import __version__
29-
from rdflib_sqlalchemy.termutils import REVERSE_TERM_COMBINATIONS
30-
from rdflib_sqlalchemy.termutils import TERM_INSTANTIATION_DICT
31-
from rdflib_sqlalchemy.termutils import constructGraph
32-
from rdflib_sqlalchemy.termutils import type2TermCombination
33-
from rdflib_sqlalchemy.termutils import statement2TermCombination
25+
from rdflib_sqlalchemy.tables import (
26+
create_asserted_statements_table,
27+
create_literal_statements_table,
28+
create_namespace_binds_table,
29+
create_quoted_statements_table,
30+
create_type_statements_table,
31+
TABLE_NAME_TEMPLATES,
32+
)
33+
from rdflib_sqlalchemy.termutils import (
34+
REVERSE_TERM_COMBINATIONS,
35+
TERM_INSTANTIATION_DICT,
36+
constructGraph,
37+
type2TermCombination,
38+
statement2TermCombination,
39+
)
3440

3541

3642
_logger = logging.getLogger(__name__)
@@ -49,8 +55,6 @@
4955

5056
INTERNED_PREFIX = "kb_"
5157

52-
MYSQL_MAX_INDEX_LENGTH = 200
53-
5458
Any = None
5559

5660

@@ -274,21 +278,6 @@ def createTerm(
274278
return rt
275279

276280

277-
class TermType(types.TypeDecorator):
278-
"""Term typology."""
279-
280-
impl = types.Text
281-
282-
def process_bind_param(self, value, dialect):
283-
"""Process bound parameters."""
284-
if isinstance(value, (QuotedGraph, Graph)):
285-
return text_type(value.identifier)
286-
elif isinstance(value, Node):
287-
return text_type(value)
288-
else:
289-
return value
290-
291-
292281
class SQLGenerator(object):
293282
"""SQL statement generator."""
294283

@@ -530,7 +519,7 @@ def __init__(self, identifier=None, configuration=None, engine=None):
530519
self.engine = engine
531520

532521
# Use only the first 10 bytes of the digest
533-
self._internedId = "{prefix}{identifier_hash}".format(
522+
self._interned_id = "{prefix}{identifier_hash}".format(
534523
prefix=INTERNED_PREFIX,
535524
identifier_hash=hashlib.sha1(self.identifier.encode("utf8")).hexdigest()[:10],
536525
)
@@ -561,6 +550,13 @@ def __init__(self, identifier=None, configuration=None, engine=None):
561550
if configuration:
562551
self.open(configuration)
563552

553+
@property
554+
def table_names(self):
555+
return [
556+
table_name_template.format(self._interned_id)
557+
for table_name_template in TABLE_NAME_TEMPLATES
558+
]
559+
564560
def _get_node_pickler(self):
565561
if getattr(self, "_node_pickler", False) \
566562
or self._node_pickler is None:
@@ -616,13 +612,14 @@ def create_all(self):
616612
self.metadata.create_all(self.engine)
617613

618614
inspector = reflection.Inspector.from_engine(self.engine)
619-
tbls = inspector.get_table_names()
620-
for tn in [tbl % (self._internedId) for tbl in table_name_prefixes]:
621-
if tn not in tbls:
622-
sys.stderr.write("table %s Doesn't exist\n" % (tn))
623-
# The database exists, but one of the partitions doesn't exist
615+
existing_table_names = inspector.get_table_names()
616+
for table_name in self.table_names:
617+
if table_name not in existing_table_names:
618+
_logger.critical("create_all() - table %s Doesn't exist!", table_name)
619+
# The database exists, but one of the tables doesn't exist
624620
return 0
625-
# Everything is there (the database and the partitions)
621+
622+
# Everything is there (the database and all of the tables)
626623
return 1
627624

628625
def close(self, commit_pending_transaction=False):
@@ -648,9 +645,7 @@ def destroy(self, configuration):
648645
self.metadata.drop_all(self.engine)
649646
trans.commit()
650647
except Exception:
651-
e = sys.exc_info()[1]
652-
msg = e.args[0] if len(e.args) > 0 else ""
653-
_logger.debug("unable to drop table: %s " % (msg))
648+
_logger.exception("unable to drop table.")
654649
trans.rollback()
655650

656651
def _get_build_command(self, triple, context=None, quoted=False):
@@ -713,12 +708,9 @@ def add(self, triple, context=None, quoted=False):
713708
try:
714709
connection.execute(statement, params)
715710
except Exception:
716-
e = sys.exc_info()[1]
717-
msg = e.args[0] if len(e.args) > 0 else ""
718-
_logger.debug(
719-
"Add failed %s with commands %s params %s" % (
720-
msg, str(statement), repr(params)
721-
)
711+
_logger.exception(
712+
"Add failed with statement: %s, params: %s",
713+
str(statement), repr(params)
722714
)
723715
raise
724716

@@ -744,23 +736,24 @@ def addN(self, quads):
744736
connection.execute(command["statement"], command["params"])
745737
trans.commit()
746738
except Exception:
747-
e = sys.exc_info()[1]
748-
msg = e.args[0] if len(e.args) > 0 else ""
749-
_logger.debug("AddN failed %s" % msg)
739+
_logger.exception("AddN failed.")
750740
trans.rollback()
751741
raise
752742

753743
def remove(self, triple, context):
754744
"""Remove a triple from the store."""
755745
subject, predicate, obj = triple
746+
756747
if context is not None:
757748
if subject is None and predicate is None and object is None:
758749
self._remove_context(context)
759750
return
751+
760752
quoted_table = self.tables["quoted_statements"]
761753
asserted_table = self.tables["asserted_statements"]
762754
asserted_type_table = self.tables["type_statements"]
763755
literal_table = self.tables["literal_statements"]
756+
764757
with self.engine.connect() as connection:
765758
trans = connection.begin()
766759
try:
@@ -799,9 +792,7 @@ def remove(self, triple, context):
799792

800793
trans.commit()
801794
except Exception:
802-
e = sys.exc_info()[1]
803-
msg = e.args[0] if len(e.args) > 0 else ""
804-
_logger.debug("Removal failed %s" % msg)
795+
_logger.exception("Removal failed.")
805796
trans.rollback()
806797

807798
def triples(self, triple, context=None):
@@ -899,7 +890,6 @@ class membership columns: member,klass,context termComb
899890

900891
q = union_select(selects, select_type=TRIPLE_SELECT_NO_ORDER)
901892
with self.engine.connect() as connection:
902-
# _logger.debug("Triples query : %s" % str(q))
903893
res = connection.execute(q)
904894
# TODO: False but it may have limitations on text column. Check
905895
# NOTE: SQLite does not support ORDER BY terms that aren't
@@ -1034,13 +1024,9 @@ def __len__(self, context=None):
10341024
ASSERTED_LITERAL_PARTITION), ]
10351025
q = union_select(selects, distinct=False, select_type=COUNT_SELECT)
10361026

1037-
# _logger.debug("Length query : %s" % str(q))
1038-
10391027
with self.engine.connect() as connection:
10401028
res = connection.execute(q)
10411029
rt = res.fetchall()
1042-
# _logger.debug(rt)
1043-
# _logger.debug(len(rt))
10441030
return reduce(lambda x, y: x + y, [rtTuple[0] for rtTuple in rt])
10451031

10461032
def contexts(self, triple=None):
@@ -1145,9 +1131,7 @@ def _remove_context(self, identifier):
11451131
connection.execute(table.delete(clause))
11461132
trans.commit()
11471133
except Exception:
1148-
e = sys.exc_info()[1]
1149-
msg = e.args[0] if len(e.args) > 0 else ""
1150-
_logger.debug("Context removal failed %s" % msg)
1134+
_logger.exception("Context removal failed.")
11511135
trans.rollback()
11521136

11531137
# Optional Namespace methods
@@ -1208,9 +1192,7 @@ def bind(self, prefix, namespace):
12081192
prefix=prefix, uri=namespace)
12091193
connection.execute(ins)
12101194
except Exception:
1211-
e = sys.exc_info()[1]
1212-
msg = e.args[0] if len(e.args) > 0 else ""
1213-
_logger.debug("Namespace binding failed %s" % msg)
1195+
_logger.exception("Namespace binding failed.")
12141196

12151197
def prefix(self, namespace):
12161198
"""Prefix."""
@@ -1250,93 +1232,9 @@ def namespaces(self):
12501232
def _create_table_definitions(self):
12511233
self.metadata = MetaData()
12521234
self.tables = {
1253-
"asserted_statements":
1254-
Table(
1255-
"%s_asserted_statements" % self._internedId, self.metadata,
1256-
Column("id", types.Integer, nullable=False, primary_key=True),
1257-
Column("subject", TermType, nullable=False),
1258-
Column("predicate", TermType, nullable=False),
1259-
Column("object", TermType, nullable=False),
1260-
Column("context", TermType, nullable=False),
1261-
Column("termcomb", types.Integer,
1262-
nullable=False, key="termComb"),
1263-
Index("%s_A_termComb_index" % self._internedId,
1264-
"termComb"),
1265-
Index("%s_A_s_index" % self._internedId, "subject", mysql_length=MYSQL_MAX_INDEX_LENGTH),
1266-
Index("%s_A_p_index" % self._internedId, "predicate", mysql_length=MYSQL_MAX_INDEX_LENGTH),
1267-
Index("%s_A_o_index" % self._internedId, "object", mysql_length=MYSQL_MAX_INDEX_LENGTH),
1268-
Index("%s_A_c_index" % self._internedId, "context", mysql_length=MYSQL_MAX_INDEX_LENGTH)),
1269-
"type_statements":
1270-
Table("%s_type_statements" % self._internedId, self.metadata,
1271-
Column("id", types.Integer, nullable=False, primary_key=True),
1272-
Column("member", TermType, nullable=False),
1273-
Column("klass", TermType, nullable=False),
1274-
Column("context", TermType, nullable=False),
1275-
Column("termcomb", types.Integer, nullable=False,
1276-
key="termComb"),
1277-
Index("%s_T_termComb_index" % self._internedId,
1278-
"termComb"),
1279-
Index("%s_member_index" % self._internedId, "member", mysql_length=MYSQL_MAX_INDEX_LENGTH),
1280-
Index("%s_klass_index" % self._internedId, "klass", mysql_length=MYSQL_MAX_INDEX_LENGTH),
1281-
Index("%s_c_index" % self._internedId, "context", mysql_length=MYSQL_MAX_INDEX_LENGTH)),
1282-
"literal_statements":
1283-
Table(
1284-
"%s_literal_statements" % self._internedId, self.metadata,
1285-
Column("id", types.Integer, nullable=False, primary_key=True),
1286-
Column("subject", TermType, nullable=False),
1287-
Column("predicate", TermType, nullable=False),
1288-
Column("object", TermType),
1289-
Column("context", TermType, nullable=False),
1290-
Column("termcomb", types.Integer, nullable=False,
1291-
key="termComb"),
1292-
Column("objlanguage", types.String(255),
1293-
key="objLanguage"),
1294-
Column("objdatatype", types.String(255),
1295-
key="objDatatype"),
1296-
Index("%s_L_termComb_index" % self._internedId,
1297-
"termComb"),
1298-
Index("%s_L_s_index" % self._internedId, "subject", mysql_length=MYSQL_MAX_INDEX_LENGTH),
1299-
Index("%s_L_p_index" % self._internedId, "predicate", mysql_length=MYSQL_MAX_INDEX_LENGTH),
1300-
Index("%s_L_c_index" % self._internedId, "context", mysql_length=MYSQL_MAX_INDEX_LENGTH)),
1301-
"quoted_statements":
1302-
Table(
1303-
"%s_quoted_statements" % self._internedId, self.metadata,
1304-
Column("id", types.Integer, nullable=False, primary_key=True),
1305-
Column("subject", TermType, nullable=False),
1306-
Column("predicate", TermType, nullable=False),
1307-
Column("object", TermType),
1308-
Column("context", TermType, nullable=False),
1309-
Column("termcomb", types.Integer, nullable=False,
1310-
key="termComb"),
1311-
Column("objlanguage", types.String(255),
1312-
key="objLanguage"),
1313-
Column("objdatatype", types.String(255),
1314-
key="objDatatype"),
1315-
Index("%s_Q_termComb_index" % self._internedId,
1316-
"termComb"),
1317-
Index("%s_Q_s_index" % self._internedId, "subject", mysql_length=MYSQL_MAX_INDEX_LENGTH),
1318-
Index("%s_Q_p_index" % self._internedId, "predicate", mysql_length=MYSQL_MAX_INDEX_LENGTH),
1319-
Index("%s_Q_o_index" % self._internedId, "object", mysql_length=MYSQL_MAX_INDEX_LENGTH),
1320-
Index("%s_Q_c_index" % self._internedId, "context", mysql_length=MYSQL_MAX_INDEX_LENGTH)),
1321-
"namespace_binds":
1322-
Table(
1323-
"%s_namespace_binds" % self._internedId, self.metadata,
1324-
Column("prefix", types.String(20), unique=True,
1325-
nullable=False, primary_key=True),
1326-
Column("uri", types.Text),
1327-
Index("%s_uri_index" % self._internedId, "uri", mysql_length=MYSQL_MAX_INDEX_LENGTH))
1235+
"asserted_statements": create_asserted_statements_table(self._interned_id, self.metadata),
1236+
"type_statements": create_type_statements_table(self._interned_id, self.metadata),
1237+
"literal_statements": create_literal_statements_table(self._interned_id, self.metadata),
1238+
"quoted_statements": create_quoted_statements_table(self._interned_id, self.metadata),
1239+
"namespace_binds": create_namespace_binds_table(self._interned_id, self.metadata),
13281240
}
1329-
if __version__ > "0.2":
1330-
for table in ["type_statements", "literal_statements",
1331-
"quoted_statements", "asserted_statements"]:
1332-
self.tables[table].append_column(
1333-
Column("id", types.Integer, nullable=False, primary_key=True))
1334-
1335-
1336-
table_name_prefixes = [
1337-
"%s_asserted_statements",
1338-
"%s_type_statements",
1339-
"%s_quoted_statements",
1340-
"%s_namespace_binds",
1341-
"%s_literal_statements"
1342-
]

0 commit comments

Comments
 (0)