/** * rasqal_row_compatible_check: * @map: row compatible map object * @first_row: first row * @second_row: second row * * Test if two rows have SPARQL Algebra "Compatible Mappings" * * "Two solution mappings μ1 and μ2 are compatible if, for every * variable v in dom(μ1) and in dom(μ2), μ1(v) = μ2(v)." * -- SPARQL Query Language 20080115, 12.3 Basic Graph Patterns * * interpretation: * for all variables in both rows * the values for both rows must either * a) be the same defined value * b) both be undefined */ int rasqal_row_compatible_check(rasqal_row_compatible* map, rasqal_row *first_row, rasqal_row *second_row) { int i; int count = map->variables_count; int compatible = 1; /* If no variables in common, always compatible */ if(!map->variables_in_both_rows_count) return 1; for(i = 0; i < count; i++) { #ifdef RASQAL_DEBUG rasqal_variable *v = rasqal_variables_table_get(map->variables_table, i); const unsigned char *name = v->name; #endif rasqal_literal *first_value = NULL; rasqal_literal *second_value = NULL; int offset1 = map->defined_in_map[i<<1]; int offset2 = map->defined_in_map[1 + (i<<1)]; if(offset1 >= 0) first_value = first_row->values[offset1]; if(offset2 >= 0) second_value = second_row->values[offset2]; #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1 RASQAL_DEBUG5("row variable #%d - %s has first row offset #%d second row offset #%d\n", i, name, offset1, offset2); #endif /* do not test if both are NULL */ if(!first_value && !second_value) continue; if(!first_value || !second_value) { #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1 RASQAL_DEBUG3("row variable #%d - %s has (one NULL, one value)\n", i, name); #endif /* compatible if one is NULL and the other is not */ continue; } if(!rasqal_literal_equals(first_value, second_value)) { RASQAL_DEBUG3("row variable #%d - %s has different values\n", i, name); /* incompatible if not equal values */ compatible = 0; break; } else { #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1 RASQAL_DEBUG3("row variable #%d - %s has same values\n", i, name); #endif } } return compatible; }
/** * rasqal_free_variable: * @v: #rasqal_variable object * * Destructor - Destroy a Rasqal variable object. * **/ void rasqal_free_variable(rasqal_variable* v) { if(!v) return; #ifdef RASQAL_DEBUG_VARIABLE_USAGE v->usage--; RASQAL_DEBUG3("Variable %s usage decreased to %d\n", v->name, v->usage); if(v->usage) return; #else if(--v->usage) return; #endif if(v->name) RASQAL_FREE(char*, v->name); if(v->value) rasqal_free_literal(v->value); if(v->expression) rasqal_free_expression(v->expression); RASQAL_FREE(rasqal_variable, v); }
/** * rasqal_rowsource_reset: * @rowsource: rasqal rowsource * * INTERNAL - Reset a rowsource to regenerate the same set of rows * * Return value: query or NULL **/ int rasqal_rowsource_reset(rasqal_rowsource* rowsource) { rowsource->finished = 0; rowsource->count = 0; if(rowsource->handler->reset) return rowsource->handler->reset(rowsource, rowsource->user_data); if(rowsource->flags & RASQAL_ROWSOURCE_FLAGS_SAVED_ROWS) { RASQAL_DEBUG3("%s rowsource %p resetting to use saved rows\n", rowsource->handler->name, rowsource); rowsource->offset = 0; } else { RASQAL_DEBUG3("WARNING: %s rowsource %p has no reset and there are no saved rows\n", rowsource->handler->name, rowsource); } return 0; }
/** * rasqal_new_variable_from_variable: * @v: #rasqal_variable to copy * * Copy Constructor - Create a new Rasqal variable from an existing one * * This adds a new reference to the variable, it does not do a deep copy * * Return value: a new #rasqal_variable or NULL on failure. **/ rasqal_variable* rasqal_new_variable_from_variable(rasqal_variable* v) { if(!v) return NULL; v->usage++; #ifdef RASQAL_DEBUG_VARIABLE_USAGE RASQAL_DEBUG3("Variable %s usage increased to %d\n", v->name, v->usage); #endif return v; }
/** * rasqal_rowsource_read_row: * @rowsource: rasqal rowsource * * Read a query result row from the rowsource. * * If a row is returned, it is owned by the caller. * * Return value: row or NULL when no more rows are available **/ rasqal_row* rasqal_rowsource_read_row(rasqal_rowsource *rowsource) { rasqal_row* row = NULL; if(rowsource->finished) return NULL; if(rasqal_rowsource_ensure_variables(rowsource)) return NULL; if(rowsource->handler->read_row) row = rowsource->handler->read_row(rowsource, rowsource->user_data); else { if(!rowsource->rows_sequence) { rowsource->rows_sequence = rasqal_rowsource_read_all_rows(rowsource); rowsource->offset = 0; } if(rowsource->rows_sequence) /* remove and return row from sequence at offset */ row = (rasqal_row*)raptor_sequence_delete_at(rowsource->rows_sequence, rowsource->offset++); } if(!row) rowsource->finished = 1; else { rowsource->count++; /* Generate a group around all rows if there are no groups returned */ if(rowsource->generate_group && row->group_id < 0) row->group_id = 0; } #ifdef RASQAL_DEBUG RASQAL_DEBUG3("%s rowsource %p read row: ", rowsource->handler->name, rowsource); if(row) rasqal_row_print(row, stderr); else fputs("NONE", stderr); fputs("\n", stderr); #endif return row; }
/* * rasqal_world_register_query_result_format_factory: * @world: rasqal world * @register_factory: pointer to function to call to register the factory * * INTERNAL - Register a query result format via a factory. * * All strings set in the @factory method are shared with the * #rasqal_query_result_format_factory * * Return value: new factory object or NULL on failure **/ rasqal_query_results_format_factory* rasqal_world_register_query_results_format_factory(rasqal_world* world, int (*register_factory)(rasqal_query_results_format_factory*)) { rasqal_query_results_format_factory *factory = NULL; factory = RASQAL_CALLOC(rasqal_query_results_format_factory*, 1, sizeof(*factory)); if(!factory) return NULL; factory->world = world; if(raptor_sequence_push(world->query_results_formats, factory)) return NULL; /* on error, factory is already freed by the sequence */ /* Call the factory registration function on the new object */ if(register_factory(factory)) /* factory is owned and freed by the query_results_formats sequence */ return NULL; factory->desc.flags = 0; if(factory->get_rowsource) factory->desc.flags |= RASQAL_QUERY_RESULTS_FORMAT_FLAG_READER; if(factory->write) factory->desc.flags |= RASQAL_QUERY_RESULTS_FORMAT_FLAG_WRITER; if(raptor_syntax_description_validate(&factory->desc)) { rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR, NULL, "Result query result format description failed to validate\n"); goto tidy; } #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1 RASQAL_DEBUG3("Registered query result format %s with context size %d\n", factory->desc.names[0], factory->context_length); #endif return factory; /* Clean up on failure */ tidy: rasqal_free_query_results_format_factory(factory); return NULL; }
/* * rasqal_query_language_register_factory: * @factory: pointer to function to call to register the factory * * INTERNAL - Register a query language syntax handled by a query factory * * Return value: new factory or NULL on failure **/ RASQAL_EXTERN_C rasqal_query_language_factory* rasqal_query_language_register_factory(rasqal_world *world, int (*factory) (rasqal_query_language_factory*)) { rasqal_query_language_factory *query = NULL; query = (rasqal_query_language_factory*)RASQAL_CALLOC(rasqal_query_language_factory, 1, sizeof(*query)); if(!query) goto tidy; query->world = world; if(raptor_sequence_push(world->query_languages, query)) return NULL; /* on error, query is already freed by the sequence */ /* Call the query registration function on the new object */ if(factory(query)) return NULL; /* query is owned and freed by the query_languages sequence */ if(raptor_syntax_description_validate(&query->desc)) { rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR, NULL, "Query language format description failed to validate\n"); goto tidy; } #if defined(RASQAL_DEBUG) && RASQAL_DEBUG > 1 RASQAL_DEBUG3("Registered query language %s with context size %d\n", query->names[0], query->context_length); #endif return query; /* Clean up on failure */ tidy: if(query) rasqal_free_query_language_factory(query); return NULL; }
/** * rasqal_rowsource_ensure_variables: * @rowsource: rasqal rowsource * * INTERNAL - Ensure that the variables in the rowsource are defined * * Return value: non-0 on failure */ int rasqal_rowsource_ensure_variables(rasqal_rowsource *rowsource) { int rc = 0; if(rowsource->updated_variables) return 0; rowsource->updated_variables++; if(rowsource->handler->ensure_variables) rc = rowsource->handler->ensure_variables(rowsource, rowsource->user_data); #ifdef RASQAL_DEBUG if(!rc) { RASQAL_DEBUG3("%s rowsource %p header: ", rowsource->handler->name, rowsource); rasqal_rowsource_print_header(rowsource, stderr); } #endif return rc; }
static int rasqal_rowsource_visitor_set_requirements(rasqal_rowsource* rowsource, void *user_data) { unsigned int flags = *(unsigned int*)user_data; if(rowsource->handler->set_requirements) return rowsource->handler->set_requirements(rowsource, rowsource->user_data, flags); if(flags & RASQAL_ROWSOURCE_REQUIRE_RESET) { if(!rowsource->handler->reset) { /* If there is no reset handler, it is handled by this module and it is needed * it is handled by this module */ RASQAL_DEBUG3("setting %s rowsource %p to save rows\n", rowsource->handler->name, rowsource); rowsource->flags |= RASQAL_ROWSOURCE_FLAGS_SAVE_ROWS; return 1; } } return 0; }
rasqal_rowsource* rasqal_new_aggregation_rowsource(rasqal_world *world, rasqal_query* query, rasqal_rowsource* rowsource, raptor_sequence* exprs_seq, raptor_sequence* vars_seq) { rasqal_aggregation_rowsource_context* con; int flags = 0; int size; int i; if(!world || !query || !rowsource || !exprs_seq || !vars_seq) goto fail; exprs_seq = rasqal_expression_copy_expression_sequence(exprs_seq); vars_seq = rasqal_variable_copy_variable_sequence(vars_seq); size = raptor_sequence_size(exprs_seq); if(size != raptor_sequence_size(vars_seq)) { RASQAL_DEBUG3("expressions sequence size %d does not match vars sequence size %d\n", size, raptor_sequence_size(vars_seq)); goto fail; } con = (rasqal_aggregation_rowsource_context*)RASQAL_CALLOC(rasqal_aggregation_rowsource_context, 1, sizeof(*con)); if(!con) goto fail; con->rowsource = rowsource; con->exprs_seq = exprs_seq; con->vars_seq = vars_seq; /* allocate per-expr data */ con->expr_count = size; con->expr_data = (rasqal_agg_expr_data*)RASQAL_CALLOC(rasqal_agg_expr_data, sizeof(rasqal_agg_expr_data), size); if(!con->expr_data) goto fail; /* Initialise per-expr data */ for(i = 0; i < size; i++) { rasqal_expression* expr = (rasqal_expression *)raptor_sequence_get_at(exprs_seq, i); rasqal_variable* variable = (rasqal_variable*)raptor_sequence_get_at(vars_seq, i); rasqal_agg_expr_data* expr_data = &con->expr_data[i]; expr_data->expr = rasqal_new_expression_from_expression(expr); expr_data->variable = variable; /* Prepare expression arguments sequence in per-expr data */ if(expr->args) { /* list of #rasqal_expression arguments already in expr * #RASQAL_EXPR_FUNCTION and #RASQAL_EXPR_GROUP_CONCAT */ expr_data->exprs_seq = rasqal_expression_copy_expression_sequence(expr->args); } else { /* single argument */ expr_data->exprs_seq = raptor_new_sequence((raptor_data_free_handler)rasqal_free_expression, (raptor_data_print_handler)rasqal_expression_print); raptor_sequence_push(expr_data->exprs_seq, rasqal_new_expression_from_expression(expr->arg1)); } } return rasqal_new_rowsource_from_handler(world, query, con, &rasqal_aggregation_rowsource_handler, query->vars_table, flags); fail: if(rowsource) rasqal_free_rowsource(rowsource); if(exprs_seq) raptor_free_sequence(exprs_seq); if(vars_seq) raptor_free_sequence(vars_seq); return NULL; }
static int rasqal_builtin_agg_expression_execute_step(void* user_data, raptor_sequence* literals) { rasqal_builtin_agg_expression_execute* b; rasqal_literal* l; int i; b = (rasqal_builtin_agg_expression_execute*)user_data; if(b->error) return 1; if(b->expr->op == RASQAL_EXPR_COUNT) { /* COUNT(*) : counts every row (does not care about literals) */ if(b->expr->arg1->op == RASQAL_EXPR_VARSTAR) b->count++; /* COUNT(expr list) : counts rows with non-empty sequence of literals */ else if(raptor_sequence_size(literals) > 0) b->count++; return 0; } /* Other aggregate functions count every row */ b->count++; for(i = 0; (l = (rasqal_literal*)raptor_sequence_get_at(literals, i)); i++) { rasqal_literal* result = NULL; if(b->expr->op == RASQAL_EXPR_SAMPLE) { /* Sample chooses the first literal it sees */ if(!b->l) b->l = rasqal_new_literal_from_literal(l); break; } if(b->expr->op == RASQAL_EXPR_GROUP_CONCAT) { const unsigned char* str; int error = 0; str = (const unsigned char*)rasqal_literal_as_string_flags(l, 0, &error); if(!error) { if(raptor_stringbuffer_length(b->sb)) raptor_stringbuffer_append_counted_string(b->sb, b->separator, 1, 1); raptor_stringbuffer_append_string(b->sb, str, 1); } continue; } if(!b->l) result = rasqal_new_literal_from_literal(l); else { if(b->expr->op == RASQAL_EXPR_SUM || b->expr->op == RASQAL_EXPR_AVG) { result = rasqal_literal_add(b->l, l, &b->error); } else if(b->expr->op == RASQAL_EXPR_MIN) { int cmp = rasqal_literal_compare(b->l, l, 0, &b->error); if(cmp <= 0) result = rasqal_new_literal_from_literal(b->l); else result = rasqal_new_literal_from_literal(l); } else if(b->expr->op == RASQAL_EXPR_MAX) { int cmp = rasqal_literal_compare(b->l, l, 0, &b->error); if(cmp >= 0) result = rasqal_new_literal_from_literal(b->l); else result = rasqal_new_literal_from_literal(l); } else { RASQAL_FATAL2("Builtin aggregation operation %d is not implemented", b->expr->op); } rasqal_free_literal(b->l); if(!result) b->error = 1; } b->l = result; #if RASQAL_DEBUG > 1 RASQAL_DEBUG3("Aggregation step result %s (error=%d)\n", (result ? (const char*)rasqal_literal_as_string(result) : "(NULL)"), b->error); #endif if(b->error) break; } return b->error; }
/** * rasqal_rowsource_read_row: * @rowsource: rasqal rowsource * * Read a query result row from the rowsource. * * If a row is returned, it is owned by the caller. * * Return value: row or NULL when no more rows are available **/ rasqal_row* rasqal_rowsource_read_row(rasqal_rowsource *rowsource) { rasqal_row* row = NULL; if(!rowsource || rowsource->finished) return NULL; if(rowsource->flags & RASQAL_ROWSOURCE_FLAGS_SAVED_ROWS) { /* return row from saved rows sequence at offset */ row = (rasqal_row*)raptor_sequence_get_at(rowsource->rows_sequence, rowsource->offset++); #ifdef RASQAL_DEBUG RASQAL_DEBUG3("%s rowsource %p returned saved row: ", rowsource->handler->name, rowsource); if(row) rasqal_row_print(row, stderr); else fputs("NONE", stderr); fputs("\n", stderr); #endif if(row) row = rasqal_new_row_from_row(row); /* row is owned by us */ } else { if(rasqal_rowsource_ensure_variables(rowsource)) return NULL; if(rowsource->handler->read_row) { row = rowsource->handler->read_row(rowsource, rowsource->user_data); /* row is owned by us */ if(row && rowsource->flags & RASQAL_ROWSOURCE_FLAGS_SAVE_ROWS) { if(!rowsource->rows_sequence) { rowsource->rows_sequence = raptor_new_sequence((raptor_data_free_handler)rasqal_free_row, (raptor_data_print_handler)rasqal_row_print); rowsource->offset = 0; } /* copy to save it away */ row = rasqal_new_row_from_row(row); raptor_sequence_push(rowsource->rows_sequence, row); } } else { if(!rowsource->rows_sequence) { raptor_sequence* seq; seq = rasqal_rowsource_read_all_rows(rowsource); if(rowsource->rows_sequence) raptor_free_sequence(rowsource->rows_sequence); /* rows_sequence now owns all rows */ rowsource->rows_sequence = seq; rowsource->offset = 0; } if(rowsource->rows_sequence) { /* return row from sequence at offset */ row = (rasqal_row*)raptor_sequence_get_at(rowsource->rows_sequence, rowsource->offset++); if(row) row = rasqal_new_row_from_row(row); /* row is owned by us */ } } } if(!row) { rowsource->finished = 1; if(rowsource->flags & RASQAL_ROWSOURCE_FLAGS_SAVE_ROWS) rowsource->flags |= RASQAL_ROWSOURCE_FLAGS_SAVED_ROWS; } else { rowsource->count++; /* Generate a group around all rows if there are no groups returned */ if(rowsource->generate_group && row->group_id < 0) row->group_id = 0; } #ifdef RASQAL_DEBUG RASQAL_DEBUG3("%s rowsource %p returned row: ", rowsource->handler->name, rowsource); if(row) rasqal_row_print(row, stderr); else fputs("NONE", stderr); fputs("\n", stderr); #endif return row; }
static void rasqal_sparql_xml_sax2_end_element_handler(void *user_data, raptor_xml_element* xml_element) { rasqal_rowsource_sparql_xml_context* con; raptor_qname* name; int i; rasqal_sparql_xml_read_state state=STATE_unknown; con=(rasqal_rowsource_sparql_xml_context*)user_data; name=raptor_xml_element_get_name(xml_element); for(i=STATE_first; i <= STATE_last; i++) { if(!strcmp((const char*)raptor_qname_get_local_name(name), sparql_xml_element_names[i])) { state=(rasqal_sparql_xml_read_state)i; con->state=state; } } if(state == STATE_unknown) { fprintf(stderr, "UNKNOWN element %s\n", raptor_qname_get_local_name(name)); con->failed++; } con->depth--; #ifdef TRACE_XML if(con->trace) { pad(stderr, con->depth); fprintf(stderr, "End Element %s (%d)\n", raptor_qname_get_local_name(name), con->state); } #endif switch(con->state) { case STATE_head: /* Only now is the full number of variables known */ con->variables_count = rasqal_variables_table_get_named_variables_count(con->vars_table); con->rowsource->size = con->variables_count; break; case STATE_literal: if(1) { rasqal_literal* l; unsigned char* lvalue; raptor_uri* datatype_uri=NULL; char* language_str=NULL; lvalue=(unsigned char*)RASQAL_MALLOC(cstring, con->value_len+1); memcpy(lvalue, con->value, con->value_len + 1); if(con->datatype) datatype_uri = raptor_new_uri(con->world->raptor_world_ptr, (const unsigned char*)con->datatype); if(con->language) { size_t language_len = strlen(con->language); language_str=(char*)RASQAL_MALLOC(cstring, language_len + 1); memcpy(language_str, con->language, language_len + 1); } l = rasqal_new_string_literal_node(con->world, lvalue, language_str, datatype_uri); rasqal_row_set_value_at(con->row, con->result_offset, l); rasqal_free_literal(l); RASQAL_DEBUG3("Saving row result %d string value at offset %d\n", con->offset, con->result_offset); } break; case STATE_bnode: if(1) { rasqal_literal* l; unsigned char* lvalue; lvalue=(unsigned char*)RASQAL_MALLOC(cstring, con->value_len+1); memcpy(lvalue, con->value, con->value_len + 1); l = rasqal_new_simple_literal(con->world, RASQAL_LITERAL_BLANK, lvalue); rasqal_row_set_value_at(con->row, con->result_offset, l); rasqal_free_literal(l); RASQAL_DEBUG3("Saving row result %d bnode value at offset %d\n", con->offset, con->result_offset); } break; case STATE_uri: if(1) { raptor_uri* uri; rasqal_literal* l; uri = raptor_new_uri(con->world->raptor_world_ptr, (const unsigned char*)con->value); l = rasqal_new_uri_literal(con->world, uri); rasqal_row_set_value_at(con->row, con->result_offset, l); rasqal_free_literal(l); RASQAL_DEBUG3("Saving row result %d uri value at offset %d\n", con->offset, con->result_offset); } break; case STATE_result: if(con->row) { RASQAL_DEBUG2("Saving row result %d\n", con->offset); raptor_sequence_push(con->results_sequence, con->row); } con->row=NULL; break; case STATE_unknown: case STATE_sparql: case STATE_variable: case STATE_results: case STATE_binding: default: break; } if(con->value) { RASQAL_FREE(cstring, con->value); con->value=NULL; } }