6 #include "knowrob/knowrob.h"
7 #include "knowrob/storage/redland/RedlandModel.h"
8 #include "knowrob/storage/StorageError.h"
9 #include "knowrob/storage/StorageManager.h"
10 #include "knowrob/semweb/OntologyParser.h"
11 #include "knowrob/semweb/xsd.h"
12 #include "knowrob/formulas/Bottom.h"
13 #include "knowrob/terms/IRIAtom.h"
14 #include "knowrob/terms/Numeric.h"
15 #include "knowrob/terms/String.h"
16 #include "knowrob/terms/Blank.h"
17 #include "knowrob/queries/AnswerYes.h"
19 #define REDLAND_SETTING_HOST "host"
20 #define REDLAND_SETTING_PORT "port"
21 #define REDLAND_SETTING_USER "user"
22 #define REDLAND_SETTING_PASSWORD "password"
23 #define REDLAND_SETTING_DB "db"
24 #define REDLAND_SETTING_STORAGE "storage"
25 #define REDLAND_SETTING_ORIGIN "origin"
29 #define KNOWROB_RDF_NEW_URI(val) \
30 librdf_new_node_from_uri_string(world_, (const unsigned char*)(val).data())
31 #define KNOWROB_RDF_NEW_BLANK(val) \
32 librdf_new_node_from_blank_identifier(world_, (const unsigned char*)(val).data())
33 #define KNOWROB_RDF_NEW_LITERAL(val, xsdType) \
34 librdf_new_node_from_typed_literal(world_, (const unsigned char*)(val), nullptr, xsdType())
42 switch (storageType) {
57 static int logRedlandMessage([[maybe_unused]]
void *user_data, librdf_log_message *message) {
58 switch (message->level) {
59 case LIBRDF_LOG_DEBUG:
60 KB_INFO(
"[redland] {}", librdf_log_message_message(message));
63 KB_INFO(
"[redland] {}", librdf_log_message_message(message));
66 KB_WARN(
"[redland] {}", librdf_log_message_message(message));
68 case LIBRDF_LOG_FATAL:
69 case LIBRDF_LOG_ERROR:
70 KB_ERROR(
"[redland] {}", librdf_log_message_message(message));
73 KB_WARN(
"[redland]: {}", librdf_log_message_message(message));
92 void RedlandModel::finalize() {
94 librdf_free_node(pair.second);
103 librdf_free_model(
model_);
126 #define REDLAND_REQUIRE_UNINITIALIZED(name, field, val) do {\
127 if(isInitialized()) { KB_WARN("attempted to change property {} after initialization.", name); } \
128 else { (field) = val; } } while(0)
176 KB_WARN(
"RedlandModel already initialized.");
186 librdf_world_open(
world_);
187 librdf_world_set_logger(
world_,
nullptr, logRedlandMessage);
194 const char *storageName =
origin_.has_value() ?
origin_.value().c_str() :
"knowrob";
195 KB_INFO(
"[redland] using storage of type \"{}\" with name \"{}\" and options \"{}\".",
206 static const char *modelOptions =
nullptr;
224 KB_WARN(
"RedlandModel already initialized.");
235 if (o_host)
host_ = o_host.value();
236 if (o_port)
port_ = o_port.value();
237 if (o_user)
user_ = o_user.value();
238 if (o_password)
password_ = o_password.value();
240 if (o_origin)
origin_ = o_origin.value();
243 if (o_storage.value() ==
"hashes") {
245 }
else if (o_storage.value() ==
"mysql") {
247 }
else if (o_storage.value() ==
"postgresql") {
249 }
else if (o_storage.value() ==
"sqlite") {
252 KB_WARN(
"Unknown storage type \"{}\", falling back to memory.", o_storage.value());
260 using OptPair_o = std::pair<std::string, std::optional<std::string>>;
261 std::vector<std::pair<std::string, std::string>> opts;
263 OptPair_o{
"host",
host_},
264 OptPair_o{
"port",
port_},
266 OptPair_o{
"user",
user_},
269 if (
option.second.has_value()) {
277 opts.emplace_back(
"hash-type",
"memory");
280 opts.emplace_back(
"hash-type",
"bdb");
286 opts.emplace_back(
"contexts",
"yes");
287 std::stringstream ss;
288 for (std::size_t i = 0; i < opts.size(); i++) {
289 ss << opts[i].first <<
"='" << opts[i].second <<
'\'';
290 if (i < opts.size() - 1) {
298 static const char *modelName =
nullptr;
299 auto rdf_uri = librdf_new_uri(
301 (
const unsigned char *) uri().c_str());
302 int returnCode = librdf_model_load(
308 librdf_free_uri(rdf_uri);
309 return returnCode == 0;
312 static inline TermPtr termFromNode(librdf_node *node) {
313 if (!node)
return nullptr;
315 switch (librdf_node_get_type(node)) {
316 case LIBRDF_NODE_TYPE_RESOURCE: {
317 auto uri = librdf_node_get_uri(node);
323 case LIBRDF_NODE_TYPE_BLANK:
324 return Blank::Tabled((
const char *) librdf_node_get_blank_identifier(node));
325 case LIBRDF_NODE_TYPE_LITERAL: {
326 auto literal_value = (
const char *) librdf_node_get_literal_value(node);
327 auto datatype_uri = librdf_node_get_literal_value_datatype_uri(node);
330 auto u_uri_str = librdf_uri_to_string(datatype_uri);
331 std::string_view uri_str((
const char *) u_uri_str);
333 knowrobTerm = std::make_shared<Double>(std::stod(literal_value));
335 knowrobTerm = std::make_shared<Integer>(std::stoll(literal_value));
337 knowrobTerm = std::make_shared<Integer>(std::string_view(literal_value) ==
"true");
342 knowrobTerm = std::make_shared<String>(literal_value);
353 auto raptorTriple = librdf_new_statement(
world_);
358 librdf_free_statement(raptorTriple);
365 for (
auto &knowrobTriple: *triples) {
366 auto raptorTriple = librdf_new_statement(
world_);
370 librdf_free_statement(raptorTriple);
376 auto raptorTriple = librdf_new_statement(
world_);
379 auto ret = librdf_model_context_remove_statement(
model_,
getContextNode(knowrobTriple), raptorTriple);
380 librdf_free_statement(raptorTriple);
385 bool allRemoved =
true;
386 for (
auto &knowrobTriple: *triples) {
388 auto raptorTriple = librdf_new_statement(
world_);
390 auto ret = librdf_model_context_remove_statement(
model_,
getContextNode(*knowrobTriple), raptorTriple);
394 librdf_free_statement(raptorTriple);
400 auto stream = librdf_model_find_statements_in_context(
402 if (!stream)
return false;
404 std::vector<librdf_statement *> toRemove;
405 while (!librdf_stream_end(stream)) {
406 auto next = librdf_stream_get_object(stream);
407 toRemove.push_back(librdf_new_statement_from_statement(next));
408 librdf_stream_next(stream);
410 librdf_free_stream(stream);
412 for (
auto statement: toRemove) {
413 librdf_model_remove_statement(
model_, statement);
414 librdf_free_statement(statement);
419 static void batch_(librdf_model *model, librdf_node *context, std::shared_ptr<RaptorContainer> &triples,
421 auto stream = librdf_model_find_statements_in_context(
422 model,
nullptr, context);
424 while (!librdf_stream_end(stream)) {
425 auto statement = librdf_stream_get_object(stream);
426 triples->add(statement->subject, statement->predicate, statement->object, context);
432 librdf_stream_next(stream);
434 librdf_free_stream(stream);
439 auto contexts = librdf_model_get_contexts(
model_);
440 while (!librdf_iterator_end(contexts)) {
441 batch_(
model_, (librdf_node *) librdf_iterator_get_object(contexts), triples, callback);
442 librdf_iterator_next(contexts);
444 if (triples->size() > 0) {
448 librdf_free_iterator(contexts);
454 if (triples->size() > 0) {
461 auto raptorTriple = librdf_new_statement(
world_);
463 auto result = librdf_model_contains_statement(
model_, raptorTriple);
464 librdf_free_statement(raptorTriple);
469 auto triples = std::make_shared<RaptorContainer>(1);
470 auto rdf_query = librdf_new_statement(
world_);
473 auto stream = librdf_model_find_statements(
model_, rdf_query);
474 while (!librdf_stream_end(stream)) {
475 auto rdf_statement = librdf_stream_get_object(stream);
476 triples->add(rdf_statement->subject, rdf_statement->predicate, rdf_statement->object);
477 auto &triple = *triples->begin();
480 if (
query.filter(*triple)) visitor(triple);
485 librdf_stream_next(stream);
487 librdf_free_stream(stream);
491 auto queryObj = librdf_new_query(
495 (
unsigned char *) queryString.data(),
501 auto results = librdf_query_execute(queryObj,
model_);
504 librdf_free_query(queryObj);
507 while (!librdf_query_results_finished(results)) {
508 auto bindings = std::make_shared<Bindings>();
511 int bindings_count = librdf_query_results_get_bindings_count(results);
512 for (
int i = 0; i < bindings_count; ++i) {
513 auto name = std::string_view(librdf_query_results_get_binding_name(results, i));
514 if (name.empty() || name[0] ==
'_') {
521 auto node = librdf_query_results_get_binding_value(results, i);
529 auto knowrobTerm = termFromNode(node);
531 bindings->set(std::make_shared<Variable>(name), knowrobTerm);
533 KB_WARN(
"Failed to process binding for variable \"{}\".", name);
535 librdf_free_node(node);
538 librdf_query_results_next(results);
540 librdf_free_query_results(results);
541 librdf_free_query(queryObj);
550 auto contextNode = librdf_new_node_from_uri_string(
552 (
const unsigned char *) origin.data());
565 return xsdURIs_[
static_cast<int>(xsdType)];
572 auto atomic = std::static_pointer_cast<Atomic>(
term);
575 }
else if (
term->isBlank()) {
577 }
else if (
term->isString()) {
579 }
else if (
term->isNumeric()) {
580 auto numeric = std::static_pointer_cast<Numeric>(
atomic);
583 KB_WARN(
"Failed to convert term {} to raptor term.", *
term);
588 raptor_term *subject, *
predicate, *object;
591 librdf_statement_set_subject(raptorTriple, subject);
595 librdf_statement_set_predicate(raptorTriple,
predicate);
599 librdf_statement_set_object(raptorTriple,
object);
604 raptor_term *subject, *
predicate, *object;
616 switch (triple.
xsdType().value()) {
627 librdf_statement_set_subject(raptorTriple, subject);
628 librdf_statement_set_predicate(raptorTriple,
predicate);
629 librdf_statement_set_object(raptorTriple,
object);
#define REDLAND_SETTING_DB
#define KNOWROB_RDF_NEW_BLANK(val)
#define REDLAND_SETTING_USER
#define REDLAND_SETTING_PORT
#define REDLAND_SETTING_ORIGIN
#define REDLAND_REQUIRE_UNINITIALIZED(name, field, val)
#define REDLAND_SETTING_PASSWORD
#define KNOWROB_RDF_NEW_LITERAL(val, xsdType)
#define REDLAND_SETTING_HOST
#define KNOWROB_RDF_NEW_URI(val)
#define REDLAND_SETTING_STORAGE
#define KNOWROB_BUILTIN_STORAGE(Name, Type)
static std::shared_ptr< Blank > Tabled(std::string_view stringForm)
static uint32_t batchSize()
static std::shared_ptr< IRIAtom > Tabled(std::string_view stringForm)
static constexpr std::string_view ORIGIN_USER
void setHashesStorage(RedlandHashType hashType, std::string_view dir=".")
bool sparql(std::string_view queryString, const BindingsHandler &callback) const override
RedlandURI & xsdURI(XSDType xsdType)
bool insertAll(const TripleContainerPtr &triples) override
std::optional< std::string > port_
librdf_world * ownedWorld_
bool contains(const Triple &triple) override
void setDatabase(std::string_view database)
bool insertOne(const Triple &triple) override
std::map< std::string, librdf_node *, std::less<> > contextNodes_
std::optional< std::string > storageDir_
librdf_storage * storage_
RedlandURI xsdURIs_[static_cast< int >(XSDType::LAST)]
bool isInitialized() const
bool isPersistent() const override
void setPassword(std::string_view password)
std::optional< std::string > host_
void batchOrigin(std::string_view origin, const TripleHandler &callback) override
void setUser(std::string_view user)
std::optional< std::string > password_
void batch(const TripleHandler &callback) const override
std::string getStorageOptions() const
std::optional< std::string > origin_
void setRaptorWorld(librdf_world *world)
bool removeAllWithOrigin(std::string_view origin) override
void match(const TriplePattern &query, const TripleVisitor &visitor) override
bool load(const URI &uri, semweb::TripleFormat tripleFormat)
void setStorageHashType(RedlandHashType hashType)
std::optional< std::string > database_
void setHost(std::string_view host)
std::string storageOptions_
RedlandStorageType storageType_
void knowrobToRaptor(const Triple &triple, raptor_statement *raptorTriple)
bool removeAll(const TripleContainerPtr &triples) override
std::optional< std::string > user_
static constexpr std::string_view QUERY_LANGUAGE_SPARQL
librdf_node * getContextNode(std::string_view origin)
std::optional< RedlandHashType > hashType_
void setStorageType(RedlandStorageType storageType)
bool removeOne(const Triple &triple) override
void setStorageDirectory(std::string_view dir=".")
void set(librdf_world *world, std::string_view uri)
bool query(const SPARQLQuery &query, const BindingsHandler &callback) const
virtual std::string_view valueAsString() const =0
virtual std::optional< std::string_view > graph() const =0
virtual std::string_view subject() const =0
bool isSubjectBlank() const
virtual std::string_view predicate() const =0
std::string createStringValue() const
bool isObjectBlank() const
auto objectOperator() const
auto & propertyTerm() const
auto & subjectTerm() const
auto & objectTerm() const
std::string_view tripleFormatMimeType(TripleFormat format)
bool isDoubleType(std::string_view iri)
bool isBooleanType(std::string_view iri)
bool isIntegerType(std::string_view iri)
std::function< void(const TriplePtr &)> TripleVisitor
std::shared_ptr< TripleContainer > TripleContainerPtr
std::string_view xsdTypeToIRI(XSDType type)
std::shared_ptr< Term > TermPtr
std::function< void(const BindingsPtr &)> BindingsHandler
std::function< void(const TripleContainerPtr &)> TripleHandler
XSDType
The XSDType enum Enumeration of the XSD types.