void sord_free(SordModel* sord) { if (!sord) return; // Free nodes SordQuad tup; SordIter* i = sord_begin(sord); for (; !sord_iter_end(i); sord_iter_next(i)) { sord_iter_get(i, tup); for (int t = 0; t < TUP_LEN; ++t) { sord_drop_quad_ref(sord, tup[t], (SordQuadIndex)t); } } sord_iter_free(i); // Free quads ZixBTreeIter* t = zix_btree_begin(sord->indices[DEFAULT_ORDER]); for (; !zix_btree_iter_is_end(t); zix_btree_iter_increment(t)) { free(zix_btree_get(t)); } zix_btree_iter_free(t); // Free indices for (unsigned o = 0; o < NUM_ORDERS; ++o) if (sord->indices[o]) zix_btree_free(sord->indices[o]); free(sord); }
SordIter* sord_find(SordModel* sord, const SordQuad pat) { if (!pat[0] && !pat[1] && !pat[2] && !pat[3]) return sord_begin(sord); SearchMode mode; int n_prefix; const SordOrder index_order = sord_best_index(sord, pat, &mode, &n_prefix); SORD_FIND_LOG("Find " TUP_FMT " index=%s mode=%d n_prefix=%d\n", TUP_FMT_ARGS(pat), order_names[index_order], mode, n_prefix); if (pat[0] && pat[1] && pat[2] && pat[3]) mode = SINGLE; // No duplicate quads (Sord is a set) ZixBTree* const db = sord->indices[index_order]; ZixBTreeIter* cur = NULL; zix_btree_lower_bound(db, pat, &cur); if (zix_btree_iter_is_end(cur)) { SORD_FIND_LOG("No match found\n"); zix_btree_iter_free(cur); return NULL; } const SordNode** const key = (const SordNode**)zix_btree_get(cur); if (!key || ( (mode == RANGE || mode == SINGLE) && !sord_quad_match_inline(pat, key) )) { SORD_FIND_LOG("No match found\n"); zix_btree_iter_free(cur); return NULL; } return sord_iter_new(sord, cur, pat, index_order, mode, n_prefix); }
static int check_properties(SordModel* model, URIs* uris) { int st = 0; SordIter* i = sord_begin(model); for (; !sord_iter_end(i); sord_iter_next(i)) { SordQuad quad; sord_iter_get(i, quad); const SordNode* subj = quad[SORD_SUBJECT]; const SordNode* pred = quad[SORD_PREDICATE]; const SordNode* obj = quad[SORD_OBJECT]; bool is_any_property = false; SordIter* t = sord_search(model, pred, uris->rdf_type, NULL, NULL); for (; !sord_iter_end(t); sord_iter_next(t)) { if (is_descendant_of(model, uris, sord_iter_get_node(t, SORD_OBJECT), uris->rdf_Property, uris->rdfs_subClassOf)) { is_any_property = true; break; } } sord_iter_free(t); const bool is_ObjectProperty = sord_ask( model, pred, uris->rdf_type, uris->owl_ObjectProperty, 0); const bool is_FunctionalProperty = sord_ask( model, pred, uris->rdf_type, uris->owl_FunctionalProperty, 0); const bool is_InverseFunctionalProperty = sord_ask( model, pred, uris->rdf_type, uris->owl_InverseFunctionalProperty, 0); const bool is_DatatypeProperty = sord_ask( model, pred, uris->rdf_type, uris->owl_DatatypeProperty, 0); if (!is_any_property) { st = error("Use of undefined property", quad); } if (!sord_ask(model, pred, uris->rdfs_label, NULL, NULL)) { st = errorf("Property <%s> has no label\n", sord_node_get_string(pred)); } if (is_DatatypeProperty && sord_node_get_type(obj) != SORD_LITERAL) { st = error("Datatype property with non-literal value", quad); } if (is_ObjectProperty && sord_node_get_type(obj) == SORD_LITERAL) { st = error("Object property with literal value", quad); } if (is_FunctionalProperty && sord_count(model, subj, pred, NULL, NULL) > 1) { st = error("Functional property with several objects", quad); } if (is_InverseFunctionalProperty && sord_count(model, NULL, pred, obj, NULL) > 1) { st = error("Inverse functional property with several subjects", quad); } if (sord_node_equals(pred, uris->rdf_type) && !sord_ask(model, obj, uris->rdf_type, uris->rdfs_Class, NULL) && !sord_ask(model, obj, uris->rdf_type, uris->owl_Class, NULL)) { st = error("Type is not a rdfs:Class or owl:Class", quad); } if (sord_node_get_type(obj) == SORD_LITERAL && !literal_is_valid(model, uris, obj, sord_node_get_datatype(obj))) { st = error("Literal does not match datatype", quad); } SordIter* r = sord_search(model, pred, uris->rdfs_range, NULL, NULL); for (; !sord_iter_end(r); sord_iter_next(r)) { const SordNode* range = sord_iter_get_node(r, SORD_OBJECT); if (!check_type(model, uris, obj, range)) { st = error("Object not in property range", quad); fprintf(stderr, "note: Range is <%s>\n", sord_node_get_string(range)); } } sord_iter_free(r); SordIter* d = sord_search(model, pred, uris->rdfs_domain, NULL, NULL); if (d) { const SordNode* domain = sord_iter_get_node(d, SORD_OBJECT); if (!check_type(model, uris, subj, domain)) { st = error("Subject not in property domain", quad); fprintf(stderr, "note: Domain is <%s>\n", sord_node_get_string(domain)); } sord_iter_free(d); } } sord_iter_free(i); return st; }