Ejemplo n.º 1
0
SerdStatus
sord_erase(SordModel* sord, SordIter* iter)
{
	if (sord->n_iters > 1) {
		error(sord->world, SERD_ERR_BAD_ARG, "erased with many iterators\n");
	}

	SordQuad tup;
	sord_iter_get(iter, tup);

	SORD_WRITE_LOG("Remove " TUP_FMT "\n", TUP_FMT_ARGS(tup));

	SordNode* quad = NULL;
	for (unsigned i = 0; i < NUM_ORDERS; ++i) {
		if (sord->indices[i]) {
			if (zix_btree_remove(sord->indices[i], tup, (void**)&quad,
			                     i == iter->order ? &iter->cur : NULL)) {
				return (i == 0) ? SERD_ERR_NOT_FOUND : SERD_ERR_INTERNAL;
			}
		}
	}
	iter->end = zix_btree_iter_is_end(iter->cur);

	free(quad);

	for (int i = 0; i < TUP_LEN; ++i)
		sord_drop_quad_ref(sord, tup[i], (SordQuadIndex)i);

	--sord->n_quads;
	return SERD_SUCCESS;
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
static SerdStatus
write_statement(SordModel*         sord,
                SerdWriter*        writer,
                SordQuad           tup,
                SerdStatementFlags flags)
{
	const SordNode* s  = tup[SORD_SUBJECT];
	const SordNode* p  = tup[SORD_PREDICATE];
	const SordNode* o  = tup[SORD_OBJECT];
	const SordNode* d  = sord_node_get_datatype(o);
	const SerdNode* ss = sord_node_to_serd_node(s);
	const SerdNode* sp = sord_node_to_serd_node(p);
	const SerdNode* so = sord_node_to_serd_node(o);
	const SerdNode* sd = sord_node_to_serd_node(d);

	const char* lang_str = sord_node_get_language(o);
	size_t      lang_len = lang_str ? strlen(lang_str) : 0;
	SerdNode    language = SERD_NODE_NULL;
	if (lang_str) {
		language.type    = SERD_LITERAL;
		language.n_bytes = lang_len;
		language.n_chars = lang_len;
		language.buf     = (const uint8_t*)lang_str;
	};

	// TODO: Subject abbreviation

	if (sord_node_is_inline_object(s) && !(flags & SERD_ANON_CONT)) {
		return SERD_SUCCESS;
	}

	SerdStatus st = SERD_SUCCESS;
	if (sord_node_is_inline_object(o)) {
		SordQuad  sub_pat  = { o, 0, 0, 0 };
		SordIter* sub_iter = sord_find(sord, sub_pat);

		SerdStatementFlags start_flags = flags
			| ((sub_iter) ? SERD_ANON_O_BEGIN : SERD_EMPTY_O);

		st = serd_writer_write_statement(
			writer, start_flags, NULL, ss, sp, so, sd, &language);

		if (!st && sub_iter) {
			flags |= SERD_ANON_CONT;
			for (; !st && !sord_iter_end(sub_iter); sord_iter_next(sub_iter)) {
				SordQuad sub_tup;
				sord_iter_get(sub_iter, sub_tup);
				st = write_statement(sord, writer, sub_tup, flags);
			}
			sord_iter_free(sub_iter);
			serd_writer_end_anon(writer, so);
		}
	} else {
		st = serd_writer_write_statement(
			writer, flags, NULL, ss, sp, so, sd, &language);
	}

	return st;
}
Ejemplo n.º 4
0
bool
sord_iter_next(SordIter* iter)
{
	if (iter->end)
		return true;

	const SordNode** key;
	iter->end = sord_iter_forward(iter);
	if (!iter->end) {
		switch (iter->mode) {
		case ALL:
			// At the end if the cursor is (assigned above)
			break;
		case SINGLE:
			iter->end = true;
			SORD_ITER_LOG("%p reached single end\n", (void*)iter);
			break;
		case RANGE:
			SORD_ITER_LOG("%p range next\n", (void*)iter);
			// At the end if the MSNs no longer match
			key = (const SordNode**)zix_btree_get(iter->cur);
			assert(key);
			for (int i = 0; i < iter->n_prefix; ++i) {
				const int idx = orderings[iter->order][i];
				if (!sord_id_match(key[idx], iter->pat[idx])) {
					iter->end = true;
					SORD_ITER_LOG("%p reached non-match end\n", (void*)iter);
					break;
				}
			}
			break;
		case FILTER_RANGE:
			// Seek forward to next match, stopping if prefix changes
			sord_iter_seek_match_range(iter);
			break;
		case FILTER_ALL:
			// Seek forward to next match
			sord_iter_seek_match(iter);
			break;
		}
	} else {
		SORD_ITER_LOG("%p reached index end\n", (void*)iter);
	}

	if (iter->end) {
		SORD_ITER_LOG("%p Reached end\n", (void*)iter);
		return true;
	} else {
#ifdef SORD_DEBUG_ITER
		SordQuad tup;
		sord_iter_get(iter, tup);
		SORD_ITER_LOG("%p Increment to " TUP_FMT "\n",
		              (void*)iter, TUP_FMT_ARGS(tup));
#endif
		return false;
	}
}
Ejemplo n.º 5
0
static SordIter*
sord_iter_new(const SordModel* sord, ZixBTreeIter* cur, const SordQuad pat,
              SordOrder order, SearchMode mode, int n_prefix)
{
	SordIter* iter = (SordIter*)malloc(sizeof(SordIter));
	iter->sord        = sord;
	iter->cur         = cur;
	iter->order       = order;
	iter->mode        = mode;
	iter->n_prefix    = n_prefix;
	iter->end         = false;
	iter->skip_graphs = order < GSPO;
	for (int i = 0; i < TUP_LEN; ++i) {
		iter->pat[i] = pat[i];
	}

	switch (iter->mode) {
	case ALL:
	case SINGLE:
	case RANGE:
		assert(
			sord_quad_match_inline((const SordNode**)zix_btree_get(iter->cur),
			                       iter->pat));
		break;
	case FILTER_RANGE:
		sord_iter_seek_match_range(iter);
		break;
	case FILTER_ALL:
		sord_iter_seek_match(iter);
		break;
	}

#ifdef SORD_DEBUG_ITER
	SordQuad value;
	sord_iter_get(iter, value);
	SORD_ITER_LOG("New %p pat=" TUP_FMT " cur=" TUP_FMT " end=%d skip=%d\n",
	              (void*)iter, TUP_FMT_ARGS(pat), TUP_FMT_ARGS(value),
	              iter->end, iter->skip_graphs);
#endif

	++((SordModel*)sord)->n_iters;
	return iter;
}
Ejemplo n.º 6
0
bool
sord_write_iter(SordIter*   iter,
                SerdWriter* writer)
{
	if (!iter) {
		return false;
	}

	SordModel* model = (SordModel*)sord_iter_get_model(iter);
	SerdStatus st    = SERD_SUCCESS;
	for (; !st && !sord_iter_end(iter); sord_iter_next(iter)) {
		SordQuad tup;
		sord_iter_get(iter, tup);
		st = write_statement(model, writer, tup, 0);
	}
	sord_iter_free(iter);

	return !st;
}
Ejemplo n.º 7
0
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;
}