/* SLV2 * Copyright (C) 2007 Dave Robillard * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #define _XOPEN_SOURCE 500 #include #include #include #include #include #include #include "slv2/collections.h" #include "slv2/plugin.h" #include "slv2/util.h" #include "slv2_internal.h" static const char* slv2_query_prefixes = "PREFIX rdf: \n" "PREFIX rdfs: \n" "PREFIX doap: \n" "PREFIX foaf: \n" "PREFIX lv2: \n" "PREFIX lv2ev: \n"; /** Create a new SLV2Value from a librdf_node, or return NULL if impossible */ SLV2Value slv2_value_from_librdf_node(SLV2World world, librdf_node* node) { SLV2Value result = NULL; librdf_uri* datatype_uri = NULL; SLV2ValueType type = SLV2_VALUE_STRING; switch (librdf_node_get_type(node)) { case LIBRDF_NODE_TYPE_RESOURCE: type = SLV2_VALUE_URI; result = slv2_value_new_librdf_uri(world, librdf_node_get_uri(node)); break; case LIBRDF_NODE_TYPE_LITERAL: datatype_uri = librdf_node_get_literal_value_datatype_uri(node); if (datatype_uri) { if (!strcmp((const char*)librdf_uri_as_string(datatype_uri), "http://www.w3.org/2001/XMLSchema#integer")) type = SLV2_VALUE_INT; else if (!strcmp((const char*)librdf_uri_as_string(datatype_uri), "http://www.w3.org/2001/XMLSchema#decimal")) type = SLV2_VALUE_FLOAT; else fprintf(stderr, "Unknown datatype %s\n", librdf_uri_as_string(datatype_uri)); } result = slv2_value_new(world, type, (const char*)librdf_node_get_literal_value(node)); break; case LIBRDF_NODE_TYPE_BLANK: type = SLV2_VALUE_STRING; result = slv2_value_new(world, type, (const char*)librdf_node_get_blank_identifier(node)); break; case LIBRDF_NODE_TYPE_UNKNOWN: default: fprintf(stderr, "Unknown RDF node type %d\n", librdf_node_get_type(node)); break; } return result; } SLV2Values slv2_query_get_variable_bindings(SLV2World world, librdf_query_results* results, int variable) { SLV2Values result = NULL; if (!librdf_query_results_finished(results)) result = slv2_values_new(); while (!librdf_query_results_finished(results)) { librdf_node* node = librdf_query_results_get_binding_value(results, variable); if (node == NULL) { fprintf(stderr, "SLV2 ERROR: Variable %d bound to NULL.\n", variable); librdf_query_results_next(results); continue; } SLV2Value val = slv2_value_from_librdf_node(world, node); if (val) raptor_sequence_push(result, val); librdf_free_node(node); librdf_query_results_next(results); } return result; } size_t slv2_query_count_bindings(librdf_query_results* results) { size_t count = 0; while (!librdf_query_results_finished(results)) { ++count; librdf_query_results_next(results); } return count; } librdf_query_results* slv2_plugin_query(SLV2Plugin plugin, const char* sparql_str) { slv2_plugin_load_if_necessary(plugin); librdf_uri* base_uri = slv2_value_as_librdf_uri(plugin->plugin_uri); char* query_str = slv2_strjoin(slv2_query_prefixes, sparql_str, NULL); //printf("******** Query \n%s********\n", query_str); librdf_query* query = librdf_new_query(plugin->world->world, "sparql", NULL, (const unsigned char*)query_str, base_uri); if (!query) { fprintf(stderr, "ERROR: Could not create query\n"); return NULL; } // FIXME: locale kludges to work around librdf bug char* locale = strdup(setlocale(LC_NUMERIC, NULL)); setlocale(LC_NUMERIC, "POSIX"); librdf_query_results* results = librdf_query_execute(query, plugin->rdf); setlocale(LC_NUMERIC, locale); free(locale); librdf_free_query(query); free(query_str); return results; } /** Query a single variable */ SLV2Values slv2_plugin_query_variable(SLV2Plugin plugin, const char* sparql_str, unsigned variable) { assert(variable < INT_MAX); librdf_query_results* results = slv2_plugin_query(plugin, sparql_str); SLV2Values ret = slv2_query_get_variable_bindings(plugin->world, results, (int)variable); librdf_free_query_results(results); return ret; } /** Run a query and count number of matches. * * More efficient than slv2_plugin_simple_query if you're only interested * in the number of results (ie slv2_plugin_num_ports). * * Note the result of this function is probably meaningless unless the query * is a SELECT DISTINCT. */ unsigned slv2_plugin_query_count(SLV2Plugin plugin, const char* sparql_str) { librdf_query_results* results = slv2_plugin_query(plugin, sparql_str); unsigned ret = 0; if (results) { ret = slv2_query_count_bindings(results); librdf_free_query_results(results); } return ret; }