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.