static int rasqal_sort_rowsource_init(rasqal_rowsource* rowsource, void *user_data) { rasqal_query *query = rowsource->query; rasqal_sort_rowsource_context *con; con = (rasqal_sort_rowsource_context*)user_data; if(con->order_seq) con->order_size = raptor_sequence_size(con->order_seq); else { RASQAL_DEBUG1("No order conditions for sort rowsource - passing through"); con->order_size = -1; } con->map = NULL; if(con->order_size > 0 ) { /* make a row:NULL map in order to sort or do distinct * FIXME: should DISTINCT be separate? */ con->map = rasqal_engine_new_rowsort_map(con->distinct, query->compare_flags, con->order_seq); if(!con->map) return 1; } con->seq = NULL; return 0; }
/** * rasqal_get_query_language_factory: * @name: the factory name or NULL for the default factory * @uri: the query syntax URI or NULL * * Get a query factory by name. * * Return value: the factory object or NULL if there is no such factory **/ rasqal_query_language_factory* rasqal_get_query_language_factory(rasqal_world *world, const char *name, const unsigned char *uri) { rasqal_query_language_factory *factory = NULL; /* return 1st query language if no particular one wanted - why? */ if(!name) { factory = (rasqal_query_language_factory*)raptor_sequence_get_at(world->query_languages, 0); if(!factory) { RASQAL_DEBUG1("No (default) query languages registered\n"); return NULL; } } else { int i; for(i = 0; (factory = (rasqal_query_language_factory*)raptor_sequence_get_at(world->query_languages, i)); i++) { int namei; const char* fname; for(namei = 0; (fname = factory->desc.names[namei]); namei++) { if(!strcmp(fname, name)) break; } if(fname) break; } } return factory; }
static rasqal_row* rasqal_join_rowsource_build_merged_row(rasqal_rowsource* rowsource, rasqal_join_rowsource_context* con, rasqal_row *right_row) { rasqal_row *row; int i; row = rasqal_new_row_for_size(rowsource->world, rowsource->size); if(!row) { if(right_row) rasqal_free_row(right_row); return NULL; } rasqal_row_set_rowsource(row, rowsource); row->offset = con->offset; #ifdef RASQAL_DEBUG RASQAL_DEBUG1("merge\n left row : "); rasqal_row_print(con->left_row, stderr); fputs("\n right row : ", stderr); if(right_row) rasqal_row_print(right_row, stderr); else fputs("NONE", stderr); fputs("\n", stderr); #endif for(i = 0; i < con->left_row->size; i++) { rasqal_literal *l = con->left_row->values[i]; row->values[i] = rasqal_new_literal_from_literal(l); } if(right_row) { for(i = 0; i < right_row->size; i++) { rasqal_literal *l = right_row->values[i]; int dest_i = con->right_map[i]; if(!row->values[dest_i]) row->values[dest_i] = rasqal_new_literal_from_literal(l); } rasqal_free_row(right_row); } #ifdef RASQAL_DEBUG fputs(" result row : ", stderr); if(row) rasqal_row_print(row, stderr); else fputs("NONE", stderr); fputs("\n", stderr); #endif return row; }
/* * rasqal_expression_evaluate_in_set: * @e: The expression to evaluate. * @eval_context: Evaluation context * * INTERNAL - Evaluate RASQAL_EXPR_IN and RASQAL_EXPR_NOT_IN (expr, * expr list) expression. * * Return value: A #rasqal_literal boolean value or NULL on failure. */ static rasqal_literal* rasqal_expression_evaluate_in_set(rasqal_expression *e, rasqal_evaluation_context *eval_context, int *error_p) { rasqal_world* world = eval_context->world; int size = raptor_sequence_size(e->args); int i; rasqal_literal* l1; int found = 0; l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; for(i = 0; i < size; i++) { rasqal_expression* arg_e; rasqal_literal* arg_literal; arg_e = (rasqal_expression*)raptor_sequence_get_at(e->args, i); arg_literal = rasqal_expression_evaluate2(arg_e, eval_context, error_p); if(!arg_literal) goto failed; found = (rasqal_literal_equals_flags(l1, arg_literal, eval_context->flags, error_p) != 0); #if RASQAL_DEBUG > 1 if(*error_p) RASQAL_DEBUG1("rasqal_literal_equals_flags() returned: FAILURE\n"); else RASQAL_DEBUG2("rasqal_literal_equals_flags() returned: %d\n", found); #endif rasqal_free_literal(arg_literal); if(*error_p) goto failed; if(found) /* found - terminate search */ break; } rasqal_free_literal(l1); if(e->op == RASQAL_EXPR_NOT_IN) found = !found; return rasqal_new_boolean_literal(world, found); failed: if(error_p) *error_p = 1; if(l1) rasqal_free_literal(l1); return NULL; }
/** * rasqal_engine_rowsort_map_add_row: * @map: row map * @row: row to add * * INTERNAL - Add a row o a rowsort_map for sorting * * return value: non-0 if the row was a duplicate (and not added) */ int rasqal_engine_rowsort_map_add_row(rasqal_map* map, rasqal_row* row) { /* map. after this, row is owned by map */ if(!rasqal_map_add_kv(map, row, NULL)) return 0; /* duplicate, and not added so delete it */ #ifdef RASQAL_DEBUG RASQAL_DEBUG1("Got duplicate row "); rasqal_row_print(row, DEBUG_FH); fputc('\n', DEBUG_FH); #endif rasqal_free_row(row); return 1; }
static rasqal_row* rasqal_rowsource_sparql_xml_read_row(rasqal_rowsource* rowsource, void *user_data) { rasqal_rowsource_sparql_xml_context* con; rasqal_row* row=NULL; con=(rasqal_rowsource_sparql_xml_context*)user_data; rasqal_rowsource_sparql_xml_process(con); if(!con->failed && raptor_sequence_size(con->results_sequence) > 0) { RASQAL_DEBUG1("getting row from stored sequence\n"); row=(rasqal_row*)raptor_sequence_unshift(con->results_sequence); } return row; }
static int rasqal_graph_next_dg(rasqal_graph_rowsource_context *con) { rasqal_query *query = con->rowsource->query; rasqal_data_graph *dg; con->finished = 0; while(1) { rasqal_literal *o; con->dg_offset++; dg = rasqal_query_get_data_graph(query, con->dg_offset); if(!dg) { con->finished = 1; break; } if(!dg->name_uri) continue; o = rasqal_new_uri_literal(query->world, raptor_uri_copy(dg->name_uri)); if(!o) { RASQAL_DEBUG1("Failed to create new URI literal\n"); con->finished = 1; break; } RASQAL_DEBUG2("Using data graph URI literal <%s>\n", rasqal_literal_as_string(o)); rasqal_rowsource_set_origin(con->rowsource, o); /* this passes ownership of o to con->var */ rasqal_variable_set_value(con->var, o); break; } return con->finished; }
static rasqal_row* rasqal_aggregation_rowsource_read_row(rasqal_rowsource* rowsource, void *user_data) { rasqal_aggregation_rowsource_context* con; rasqal_row* row; int error = 0; con = (rasqal_aggregation_rowsource_context*)user_data; if(con->finished) return NULL; /* Iterate over input rows until last row seen or group done */ while(1) { error = 0; if(con->saved_row) row = con->saved_row; else row = rasqal_rowsource_read_row(con->rowsource); if(!row) { /* End of input - calculate last aggregation result */ con->finished = 1; break; } if(con->last_group_id != row->group_id) { int i; if(!con->saved_row && con->last_group_id >= 0) { /* Existing aggregation is done - return result */ /* save current row for next time this function is called */ con->saved_row = row; row = NULL; #ifdef RASQAL_DEBUG RASQAL_DEBUG2("Aggregation ending group %d", con->last_group_id); fputc('\n', DEBUG_FH); #endif /* Empty distinct maps */ for(i = 0; i < con->expr_count; i++) { rasqal_agg_expr_data* expr_data = &con->expr_data[i]; if(expr_data->map) { rasqal_free_map(expr_data->map); expr_data->map = NULL; } } break; } /* reference is now in 'row' variable */ con->saved_row = NULL; #ifdef RASQAL_DEBUG RASQAL_DEBUG2("Aggregation starting group %d", row->group_id); fputc('\n', DEBUG_FH); #endif /* next time this function is called we continue here */ for(i = 0; i < con->expr_count; i++) { rasqal_agg_expr_data* expr_data = &con->expr_data[i]; if(!expr_data->agg_user_data) { /* init once */ expr_data->agg_user_data = rasqal_builtin_agg_expression_execute_init(rowsource->world, expr_data->expr); if(!expr_data->agg_user_data) { error = 1; break; } } /* Init map for each group */ if(expr_data->expr->flags & RASQAL_EXPR_FLAG_DISTINCT) { expr_data->map = rasqal_new_literal_sequence_sort_map(1 /* is_distinct */, 0 /* compare_flags */); if(!expr_data->map) { error = 1; break; } } } if(error) break; con->last_group_id = row->group_id; } /* end if handling change of group ID */ /* Bind the values in the input row to the variables in the table */ rasqal_row_bind_variables(row, rowsource->query->vars_table); /* Evaluate the expressions giving a sequence of literals to * run the aggregation step over. */ if(1) { int i; if(!con->step_count) { /* copy first value row from input rowsource */ for(i = 0; i < con->input_values_count; i++) { rasqal_literal* value; value = rasqal_new_literal_from_literal(row->values[i]); raptor_sequence_set_at(con->input_values, i, value); } } con->step_count++; for(i = 0; i < con->expr_count; i++) { rasqal_agg_expr_data* expr_data = &con->expr_data[i]; raptor_sequence* seq; /* SPARQL Aggregation uses ListEvalE() to evaluate - ignoring * errors and filtering out expressions that fail */ seq = rasqal_expression_sequence_evaluate(rowsource->query, expr_data->exprs_seq, /* ignore_errors */ 1, &error); if(error) continue; if(expr_data->map) { if(rasqal_literal_sequence_sort_map_add_literal_sequence(expr_data->map, seq)) { /* duplicate found * * The above function just freed seq so no data is lost */ continue; } } #ifdef RASQAL_DEBUG RASQAL_DEBUG1("Aggregation step over literals: "); raptor_sequence_print(seq, DEBUG_FH); fputc('\n', DEBUG_FH); #endif error = rasqal_builtin_agg_expression_execute_step(expr_data->agg_user_data, seq); /* when DISTINCTing, seq remains owned by the map * otherwise seq is local and must be freed */ if(!expr_data->map) raptor_free_sequence(seq); if(error) break; } } rasqal_free_row(row); row = NULL; if(error) break; } /* end while reading rows */ if(error) { /* Discard row on error */ if(row) { rasqal_free_row(row); row = NULL; } } else if (con->last_group_id >= 0) { int offset = 0; int i; /* Generate result row and reset for next group */ row = rasqal_new_row(rowsource); /* Copy scalar results through */ for(i = 0; i < con->input_values_count; i++) { rasqal_literal* result; /* Reset: get and delete any stored input rowsource literal */ result = (rasqal_literal*)raptor_sequence_delete_at(con->input_values, i); rasqal_row_set_value_at(row, offset, result); rasqal_free_literal(result); offset++; } /* Set aggregate results */ for(i = 0; i < con->expr_count; i++) { rasqal_literal* result; rasqal_agg_expr_data* expr_data = &con->expr_data[i]; rasqal_variable* v; /* Calculate the result because the input ended or a new group started */ result = rasqal_builtin_agg_expression_execute_result(expr_data->agg_user_data); #ifdef RASQAL_DEBUG RASQAL_DEBUG1("Aggregation ending group with result: "); if(result) rasqal_literal_print(result, DEBUG_FH); else fputs("NULL", DEBUG_FH); fputc('\n', DEBUG_FH); #endif v = rasqal_rowsource_get_variable_by_offset(rowsource, offset); result = rasqal_new_literal_from_literal(result); /* it is OK to bind to NULL */ rasqal_variable_set_value(v, result); rasqal_row_set_value_at(row, offset, result); if(result) rasqal_free_literal(result); offset++; if(rasqal_builtin_agg_expression_execute_reset(expr_data->agg_user_data)) { rasqal_free_row(row); row = NULL; break; } } con->step_count = 0; if(row) row->offset = con->offset++; } return row; }
/** * rasqal_query_results_execute_with_engine: * @query_results: the #rasqal_query_results object * @engine: execution factory * @store_results: non-0 to store query results * * INTERNAL - Create a new query results set executing a prepared query with the given execution engine * * return value: non-0 on failure **/ int rasqal_query_results_execute_with_engine(rasqal_query_results* query_results, const rasqal_query_execution_factory* engine, int store_results) { int rc = 0; size_t ex_data_size; rasqal_query* query; RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, 1); query = query_results->query; if(query->failed) return 1; query_results->execution_factory = engine; /* set executed flag early to enable cleanup on error */ query_results->executed = 1; /* ensure stored results are present if ordering or distincting are being done */ query_results->store_results = (store_results || rasqal_query_get_order_conditions_sequence(query) || query->distinct); ex_data_size = query_results->execution_factory->execution_data_size; if(ex_data_size > 0) { query_results->execution_data = RASQAL_CALLOC(data, 1, ex_data_size); if(!query_results->execution_data) return 1; } else query_results->execution_data = NULL; /* Update the current datetime once per query execution */ rasqal_world_reset_now(query->world); if(query_results->execution_factory->execute_init) { rasqal_engine_error execution_error = RASQAL_ENGINE_OK; int execution_flags = 0; if(query_results->store_results) execution_flags |= 1; rc = query_results->execution_factory->execute_init(query_results->execution_data, query, query_results, execution_flags, &execution_error); if(rc || execution_error != RASQAL_ENGINE_OK) { query_results->failed = 1; return 1; } } #ifdef RASQAL_DEBUG RASQAL_DEBUG1("After execute_init, query is now:\n"); rasqal_query_print(query, stderr); #endif /* Choose either to execute all now and store OR do it on demand (lazy) */ if(query_results->store_results) rc = rasqal_query_results_execute_and_store_results(query_results); return rc; }
static int rasqal_join_rowsource_init(rasqal_rowsource* rowsource, void *user_data) { rasqal_join_rowsource_context* con; rasqal_variables_table* vars_table; con = (rasqal_join_rowsource_context*)user_data; con->failed = 0; con->state = JS_START; con->constant_join_condition = -1; /* If join condition is a constant - optimize it away */ if(con->expr && rasqal_expression_is_constant(con->expr)) { rasqal_query *query = rowsource->query; rasqal_literal* result; int bresult; int error = 0; result = rasqal_expression_evaluate2(con->expr, query->eval_context, &error); #ifdef RASQAL_DEBUG RASQAL_DEBUG1("join expression condition is constant: "); if(error) fputs("type error", DEBUG_FH); else rasqal_literal_print(result, DEBUG_FH); fputc('\n', DEBUG_FH); #endif if(error) { bresult = 0; } else { error = 0; bresult = rasqal_literal_as_boolean(result, &error); #ifdef RASQAL_DEBUG if(error) RASQAL_DEBUG1("join boolean expression returned error\n"); else RASQAL_DEBUG2("join boolean expression result: %d\n", bresult); #endif rasqal_free_literal(result); } /* free expression always */ rasqal_free_expression(con->expr); con->expr = NULL; if(con->join_type == RASQAL_JOIN_TYPE_NATURAL) { if(!bresult) { /* Constraint is always false so row source is finished */ con->state = JS_FINISHED; } /* otherwise always true so no need to evaluate on each row * and deleting con->expr will handle that */ } con->constant_join_condition = bresult; } rasqal_rowsource_set_requirements(con->left, RASQAL_ROWSOURCE_REQUIRE_RESET); rasqal_rowsource_set_requirements(con->right, RASQAL_ROWSOURCE_REQUIRE_RESET); vars_table = con->left->vars_table; con->rc_map = rasqal_new_row_compatible(vars_table, con->left, con->right); if(!con->rc_map) return -1; #ifdef RASQAL_DEBUG RASQAL_DEBUG2("rowsource %p ", rowsource); rasqal_print_row_compatible(stderr, con->rc_map); #endif return 0; }
static rasqal_row* rasqal_join_rowsource_read_row(rasqal_rowsource* rowsource, void *user_data) { rasqal_join_rowsource_context* con; rasqal_row* row = NULL; rasqal_query *query = rowsource->query; con = (rasqal_join_rowsource_context*)user_data; if(con->failed || con->state == JS_FINISHED) return NULL; while(1) { rasqal_row *right_row; int bresult = 1; int compatible = 1; if(con->state == JS_START) { /* start / re-start left */ if(con->left_row) rasqal_free_row(con->left_row); con->left_row = rasqal_rowsource_read_row(con->left); #ifdef RASQAL_DEBUG RASQAL_DEBUG2("rowsource %p read left row : ", rowsource); if(con->left_row) rasqal_row_print(con->left_row, stderr); else fputs("NONE", stderr); fputs("\n", stderr); #endif con->state = JS_INIT_RIGHT; } if(con->state == JS_INIT_RIGHT) { /* start right */ if(!con->left_row) { con->state = JS_FINISHED; return NULL; } con->right_rows_joined_count = 0; rasqal_rowsource_reset(con->right); } right_row = rasqal_rowsource_read_row(con->right); #ifdef RASQAL_DEBUG RASQAL_DEBUG2("rowsource %p read right row : ", rowsource); if(right_row) rasqal_row_print(right_row, stderr); else fputs("NONE", stderr); fputs("\n", stderr); #endif if(!right_row && con->state == JS_READ_RIGHT) { /* right has finished */ /* restart left */ con->state = JS_START; /* if all right table returned no bindings, return left row */ if(!con->right_rows_joined_count) { /* otherwise return LEFT or RIGHT row only */ if(con->join_type == RASQAL_JOIN_TYPE_LEFT) { /* LEFT JOIN - add left row if expr fails or not compatible */ if(con->left_row) { con->right_rows_joined_count++; row = rasqal_join_rowsource_build_merged_row(rowsource, con, NULL); break; } } } /* restart left by continuing the loop */ continue; } /* state is always JS_READ_RIGHT at this point */ con->state = JS_READ_RIGHT; /* now may have both left and right rows so compute compatibility */ if(right_row) { compatible = rasqal_row_compatible_check(con->rc_map, con->left_row, right_row); RASQAL_DEBUG2("join rows compatible: %s\n", compatible ? "YES" : "NO"); } if(con->constant_join_condition >= 0) { /* Get constant join expression value */ bresult = con->constant_join_condition; } else if(con->expr) { /* Check join expression if present */ rasqal_literal *result; int error = 0; result = rasqal_expression_evaluate2(con->expr, query->eval_context, &error); #ifdef RASQAL_DEBUG RASQAL_DEBUG1("join expression result: "); if(error) fputs("type error", DEBUG_FH); else rasqal_literal_print(result, DEBUG_FH); fputc('\n', DEBUG_FH); #endif if(error) { bresult = 0; } else { error = 0; bresult = rasqal_literal_as_boolean(result, &error); #ifdef RASQAL_DEBUG if(error) RASQAL_DEBUG1("filter boolean expression returned error\n"); else RASQAL_DEBUG2("filter boolean expression result: %d\n", bresult); #endif rasqal_free_literal(result); } } if(con->join_type == RASQAL_JOIN_TYPE_NATURAL) { /* found a row if compatible and constraint matches */ if(compatible && bresult && right_row) { con->right_rows_joined_count++; /* consumes right_row */ row = rasqal_join_rowsource_build_merged_row(rowsource, con, right_row); break; } } else if(con->join_type == RASQAL_JOIN_TYPE_LEFT) { /* * { merge(mu1, mu2) | mu1 in Omega1 and mu2 in Omega2, and mu1 * and mu2 are compatible and expr(merge(mu1, mu2)) is true } */ if(compatible && bresult) { con->right_rows_joined_count++; /* No constraint OR constraint & compatible so return merged row */ /* Compute row only now it is known to be needed (consumes right_row) */ row = rasqal_join_rowsource_build_merged_row(rowsource, con, right_row); break; } #if 0 /* * { mu1 | mu1 in Omega1 and mu2 in Omega2, and mu1 and mu2 are * not compatible } */ if(!compatible) { /* otherwise return LEFT or RIGHT row only */ if(con->join_type == RASQAL_JOIN_TYPE_LEFT) { /* LEFT JOIN - add left row if expr fails or not compatible */ if(con->left_row) { con->right_rows_joined_count++; row = rasqal_join_rowsource_build_merged_row(rowsource, con, NULL); if(right_row) rasqal_free_row(right_row); break; } } } #endif /* * { mu1 | mu1 in Omega1 and mu2 in Omega2, and mu1 and mu2 are * compatible and for all mu2, expr(merge(mu1, mu2)) is false } */ /* The above is handled using check for * !con->right_rows_joined_count earlier, to generate a row * once. */ } /* end if LEFT JOIN */ if(right_row) rasqal_free_row(right_row); } /* end while */ if(row) { rasqal_row_set_rowsource(row, rowsource); row->offset = con->offset++; rasqal_row_bind_variables(row, rowsource->query->vars_table); } return row; }
/** * rasqal_expression_evaluate2: * @e: The expression to evaluate. * @eval_context: expression context * @error_p: pointer to error return flag * * Evaluate a #rasqal_expression tree in the context of a * #rasqal_evaluation_context to give a #rasqal_literal result or error. * * Return value: a #rasqal_literal value or NULL (a valid value). @error_p is set to non-0 on failure. **/ rasqal_literal* rasqal_expression_evaluate2(rasqal_expression* e, rasqal_evaluation_context* eval_context, int *error_p) { rasqal_world *world; int flags; rasqal_literal* result = NULL; rasqal_literal *l1; rasqal_literal *l2; /* pack vars from different switch cases in unions to save some stack space */ union { struct { int e1; int e2; } errs; struct { int dummy_do_not_mask_e; int free_literal; } flags; int e; } errs; union { struct { int b1; int b2; } bools; int b; int i; raptor_uri *dt_uri; const unsigned char *s; unsigned char *new_s; rasqal_variable *v; rasqal_expression *e; struct { void *dummy_do_not_mask; int found; } flags; rasqal_xsd_datetime* dt; struct timeval *tv; raptor_stringbuffer* sb; } vars; RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(e, rasqal_expression, NULL); RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(eval_context, rasqal_evaluation_context, NULL); RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(error_p, intp, NULL); world = eval_context->world; flags = eval_context->flags; errs.e = 0; #ifdef RASQAL_DEBUG RASQAL_DEBUG2("evaluating expression %p: ", e); rasqal_expression_print(e, stderr); fprintf(stderr, "\n"); #endif switch(e->op) { case RASQAL_EXPR_AND: errs.errs.e1 = 0; l1 = rasqal_expression_evaluate2(e->arg1, eval_context, &errs.errs.e1); if(errs.errs.e1) { vars.bools.b1 = 0; } else { vars.bools.b1 = rasqal_literal_as_boolean(l1, &errs.errs.e1); rasqal_free_literal(l1); } errs.errs.e2 = 0; l1 = rasqal_expression_evaluate2(e->arg2, eval_context, &errs.errs.e2); if(errs.errs.e2) { vars.bools.b2 = 0; } else { vars.bools.b2 = rasqal_literal_as_boolean(l1, &errs.errs.e2); rasqal_free_literal(l1); } /* See http://www.w3.org/TR/2005/WD-rdf-sparql-query-20051123/#truthTable */ if(!errs.errs.e1 && !errs.errs.e2) { /* No type error, answer is A && B */ vars.b = vars.bools.b1 && vars.bools.b2; /* don't need b1,b2 anymore */ } else { if((!vars.bools.b1 && errs.errs.e2) || (errs.errs.e1 && vars.bools.b2)) /* F && E => F. E && F => F. */ vars.b = 0; else /* Otherwise E */ goto failed; } result = rasqal_new_boolean_literal(world, vars.b); break; case RASQAL_EXPR_OR: errs.errs.e1 = 0; l1 = rasqal_expression_evaluate2(e->arg1, eval_context, &errs.errs.e1); if(errs.errs.e1) { vars.bools.b1 = 0; } else { vars.bools.b1 = rasqal_literal_as_boolean(l1, &errs.errs.e1); rasqal_free_literal(l1); } errs.errs.e2 = 0; l1 = rasqal_expression_evaluate2(e->arg2, eval_context, &errs.errs.e2); if(errs.errs.e2) { vars.bools.b2 = 0; } else { vars.bools.b2 = rasqal_literal_as_boolean(l1, &errs.errs.e2); rasqal_free_literal(l1); } /* See http://www.w3.org/TR/2005/WD-rdf-sparql-query-20051123/#truthTable */ if(!errs.errs.e1 && !errs.errs.e2) { /* No type error, answer is A || B */ vars.b = vars.bools.b1 || vars.bools.b2; /* don't need b1,b2 anymore */ } else { if((vars.bools.b1 && errs.errs.e2) || (errs.errs.e1 && vars.bools.b2)) /* T || E => T. E || T => T */ vars.b = 1; else /* Otherwise E */ goto failed; } result = rasqal_new_boolean_literal(world, vars.b); break; case RASQAL_EXPR_EQ: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } /* FIXME - this should probably be checked at literal creation * time */ if(!rasqal_xsd_datatype_check(l1->type, l1->string, flags) || !rasqal_xsd_datatype_check(l2->type, l2->string, flags)) { RASQAL_DEBUG1("One of the literals was invalid\n"); goto failed; } vars.b = (rasqal_literal_equals_flags(l1, l2, flags, &errs.e) != 0); #if RASQAL_DEBUG > 1 if(errs.e) RASQAL_DEBUG1("rasqal_literal_equals_flags returned: FAILURE\n"); else RASQAL_DEBUG2("rasqal_literal_equals_flags returned: %d\n", vars.b); #endif rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.e) goto failed; result = rasqal_new_boolean_literal(world, vars.b); break; case RASQAL_EXPR_NEQ: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } vars.b = (rasqal_literal_not_equals_flags(l1, l2, flags, &errs.e) != 0); #if RASQAL_DEBUG > 1 if(errs.e) RASQAL_DEBUG1("rasqal_literal_not_equals_flags returned: FAILURE\n"); else RASQAL_DEBUG2("rasqal_literal_not_equals_flags returned: %d\n", vars.b); #endif rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.e) goto failed; result = rasqal_new_boolean_literal(world, vars.b); break; case RASQAL_EXPR_LT: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } vars.b = (rasqal_literal_compare(l1, l2, flags, &errs.e) < 0); rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.e) goto failed; result = rasqal_new_boolean_literal(world, vars.b); break; case RASQAL_EXPR_GT: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } vars.b = (rasqal_literal_compare(l1, l2, flags, &errs.e) > 0); rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.e) goto failed; result = rasqal_new_boolean_literal(world, vars.b); break; case RASQAL_EXPR_LE: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } vars.b = (rasqal_literal_compare(l1, l2, flags, &errs.e) <= 0); rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.e) goto failed; result = rasqal_new_boolean_literal(world, vars.b); break; case RASQAL_EXPR_GE: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } vars.b = (rasqal_literal_compare(l1, l2, flags, &errs.e) >= 0); rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.e) goto failed; result = rasqal_new_boolean_literal(world, vars.b); break; case RASQAL_EXPR_UMINUS: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; result = rasqal_literal_negate(l1, &errs.e); rasqal_free_literal(l1); if(errs.e) goto failed; break; case RASQAL_EXPR_BOUND: result = rasqal_expression_evaluate_bound(e, eval_context, error_p); break; case RASQAL_EXPR_STR: result = rasqal_expression_evaluate_str(e, eval_context, error_p); break; case RASQAL_EXPR_LANG: result = rasqal_expression_evaluate_lang(e, eval_context, error_p); break; case RASQAL_EXPR_LANGMATCHES: result = rasqal_expression_evaluate_langmatches(e, eval_context, error_p); break; case RASQAL_EXPR_DATATYPE: result = rasqal_expression_evaluate_datatype(e, eval_context, error_p); break; case RASQAL_EXPR_ISURI: case RASQAL_EXPR_ISBLANK: case RASQAL_EXPR_ISLITERAL: case RASQAL_EXPR_ISNUMERIC: result = rasqal_expression_evaluate_istype(e, eval_context, error_p); break; case RASQAL_EXPR_PLUS: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } result = rasqal_literal_add(l1, l2, &errs.e); rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.e) goto failed; break; case RASQAL_EXPR_MINUS: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } result = rasqal_literal_subtract(l1, l2, &errs.e); rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.e) goto failed; break; case RASQAL_EXPR_STAR: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } result = rasqal_literal_multiply(l1, l2, &errs.e); rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.e) goto failed; break; case RASQAL_EXPR_SLASH: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } result = rasqal_literal_divide(l1, l2, &errs.e); rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.e) goto failed; break; case RASQAL_EXPR_REM: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } vars.i = rasqal_literal_as_integer(l2, &errs.errs.e2); /* error if divisor is zero */ if(!vars.i) errs.errs.e2 = 1; else vars.i = rasqal_literal_as_integer(l1, &errs.errs.e1) % vars.i; rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.errs.e1 || errs.errs.e2) goto failed; result = rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, vars.i); break; case RASQAL_EXPR_STR_EQ: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } vars.b = (rasqal_literal_compare(l1, l2, flags | RASQAL_COMPARE_NOCASE, &errs.e) == 0); rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.e) goto failed; result = rasqal_new_boolean_literal(world, vars.b); break; case RASQAL_EXPR_STR_NEQ: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; l2 = rasqal_expression_evaluate2(e->arg2, eval_context, error_p); if(*error_p || !l2) { rasqal_free_literal(l1); goto failed; } vars.b = (rasqal_literal_compare(l1, l2, flags | RASQAL_COMPARE_NOCASE, &errs.e) != 0); rasqal_free_literal(l1); rasqal_free_literal(l2); if(errs.e) goto failed; result = rasqal_new_boolean_literal(world, vars.b); break; case RASQAL_EXPR_TILDE: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; vars.i= ~ rasqal_literal_as_integer(l1, &errs.e); rasqal_free_literal(l1); if(errs.e) goto failed; result = rasqal_new_integer_literal(world, RASQAL_LITERAL_INTEGER, vars.i); break; case RASQAL_EXPR_BANG: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; vars.b = ! rasqal_literal_as_boolean(l1, &errs.e); rasqal_free_literal(l1); if(errs.e) goto failed; result = rasqal_new_boolean_literal(world, vars.b); break; case RASQAL_EXPR_STR_MATCH: case RASQAL_EXPR_STR_NMATCH: case RASQAL_EXPR_REGEX: result = rasqal_expression_evaluate_strmatch(e, eval_context, error_p); break; case RASQAL_EXPR_LITERAL: /* flatten any literal to a value as soon as possible - this * removes variables from expressions the first time they are seen. * (FLATTEN_LITERAL) */ result = rasqal_new_literal_from_literal(rasqal_literal_value(e->literal)); break; case RASQAL_EXPR_FUNCTION: rasqal_log_warning_simple(world, RASQAL_WARNING_LEVEL_NOT_IMPLEMENTED, eval_context->locator, "No function expressions support at present. Returning false."); result = rasqal_new_boolean_literal(world, 0); break; case RASQAL_EXPR_CAST: l1 = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); if(*error_p || !l1) goto failed; result = rasqal_literal_cast(l1, e->name, flags, &errs.e); rasqal_free_literal(l1); if(errs.e) goto failed; break; case RASQAL_EXPR_ORDER_COND_ASC: case RASQAL_EXPR_ORDER_COND_DESC: case RASQAL_EXPR_GROUP_COND_ASC: case RASQAL_EXPR_GROUP_COND_DESC: result = rasqal_expression_evaluate2(e->arg1, eval_context, error_p); break; case RASQAL_EXPR_COUNT: case RASQAL_EXPR_SUM: case RASQAL_EXPR_AVG: case RASQAL_EXPR_MIN: case RASQAL_EXPR_MAX: case RASQAL_EXPR_SAMPLE: case RASQAL_EXPR_GROUP_CONCAT: rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR, eval_context->locator, "Aggregate expressions cannot be evaluated in a general scalar expression."); errs.e = 1; goto failed; break; case RASQAL_EXPR_VARSTAR: /* constants */ break; case RASQAL_EXPR_SAMETERM: result = rasqal_expression_evaluate_sameterm(e, eval_context, error_p); break; case RASQAL_EXPR_CONCAT: result = rasqal_expression_evaluate_concat(e, eval_context, error_p); break; case RASQAL_EXPR_COALESCE: result = rasqal_expression_evaluate_coalesce(e, eval_context, error_p); break; case RASQAL_EXPR_IF: result = rasqal_expression_evaluate_if(e, eval_context, error_p); break; case RASQAL_EXPR_URI: case RASQAL_EXPR_IRI: result = rasqal_expression_evaluate_uri_constructor(e, eval_context, error_p); break; case RASQAL_EXPR_STRLANG: result = rasqal_expression_evaluate_strlang(e, eval_context, error_p); break; case RASQAL_EXPR_STRDT: result = rasqal_expression_evaluate_strdt(e, eval_context, error_p); break; case RASQAL_EXPR_BNODE: result = rasqal_expression_evaluate_bnode_constructor(e, eval_context, error_p); break; case RASQAL_EXPR_IN: result = rasqal_expression_evaluate_in_set(e, eval_context, error_p); break; case RASQAL_EXPR_NOT_IN: result = rasqal_expression_evaluate_in_set(e, eval_context, error_p); break; case RASQAL_EXPR_YEAR: case RASQAL_EXPR_MONTH: case RASQAL_EXPR_DAY: case RASQAL_EXPR_HOURS: case RASQAL_EXPR_MINUTES: case RASQAL_EXPR_SECONDS: result = rasqal_expression_evaluate_datetime_part(e, eval_context, error_p); break; case RASQAL_EXPR_CURRENT_DATETIME: case RASQAL_EXPR_NOW: result = rasqal_expression_evaluate_now(e, eval_context, error_p); break; case RASQAL_EXPR_TO_UNIXTIME: result = rasqal_expression_evaluate_to_unixtime(e, eval_context, error_p); break; case RASQAL_EXPR_FROM_UNIXTIME: result = rasqal_expression_evaluate_from_unixtime(e, eval_context, error_p); break; case RASQAL_EXPR_RAND: result = rasqal_expression_evaluate_rand(e, eval_context, error_p); break; case RASQAL_EXPR_STRLEN: result = rasqal_expression_evaluate_strlen(e, eval_context, error_p); break; case RASQAL_EXPR_UCASE: case RASQAL_EXPR_LCASE: result = rasqal_expression_evaluate_set_case(e, eval_context, error_p); break; case RASQAL_EXPR_STRSTARTS: case RASQAL_EXPR_STRENDS: case RASQAL_EXPR_CONTAINS: result = rasqal_expression_evaluate_str_prefix_suffix(e, eval_context, error_p); break; case RASQAL_EXPR_TIMEZONE: result = rasqal_expression_evaluate_datetime_timezone(e, eval_context, error_p); break; case RASQAL_EXPR_TZ: result = rasqal_expression_evaluate_datetime_tz(e, eval_context, error_p); break; case RASQAL_EXPR_ENCODE_FOR_URI: result = rasqal_expression_evaluate_encode_for_uri(e, eval_context, error_p); break; case RASQAL_EXPR_SUBSTR: result = rasqal_expression_evaluate_substr(e, eval_context, error_p); break; case RASQAL_EXPR_ABS: result = rasqal_expression_evaluate_abs(e, eval_context, error_p); break; case RASQAL_EXPR_ROUND: result = rasqal_expression_evaluate_round(e, eval_context, error_p); break; case RASQAL_EXPR_CEIL: result = rasqal_expression_evaluate_ceil(e, eval_context, error_p); break; case RASQAL_EXPR_FLOOR: result = rasqal_expression_evaluate_floor(e, eval_context, error_p); break; case RASQAL_EXPR_MD5: case RASQAL_EXPR_SHA1: case RASQAL_EXPR_SHA224: case RASQAL_EXPR_SHA256: case RASQAL_EXPR_SHA384: case RASQAL_EXPR_SHA512: result = rasqal_expression_evaluate_digest(e, eval_context, error_p); break; case RASQAL_EXPR_UNKNOWN: default: RASQAL_FATAL3("Unknown operation %s (%d)", rasqal_expression_op_label(e->op), e->op); } got_result: #ifdef RASQAL_DEBUG RASQAL_DEBUG2("result of %p: ", e); rasqal_expression_print(e, stderr); fputs( ": ", stderr); if(*error_p) fputs("FAILURE",stderr); else rasqal_literal_print(result, stderr); fputc('\n', stderr); #endif return result; failed: *error_p = 1; if(result) { rasqal_free_literal(result); result = NULL; } goto got_result; }
int main(int argc, char *argv[]) { const char *program = rasqal_basename(argv[0]); rasqal_rowsource *rowsource = NULL; raptor_sequence *seq = NULL; rasqal_world* world = NULL; rasqal_query* query = NULL; rasqal_row* row = NULL; int count; int failures = 0; rasqal_variables_table* vt; int rows_count; int i; raptor_sequence* vars_seq = NULL; world = rasqal_new_world(); if(!world || rasqal_world_open(world)) { fprintf(stderr, "%s: rasqal_world init failed\n", program); return(1); } query = rasqal_new_query(world, "sparql", NULL); /* test 1-row rowsource (2 variables) */ rows_count = 1; #ifdef RASQAL_DEBUG RASQAL_DEBUG2("Testing %d-row rowsource\n", rows_count); #endif vt = rasqal_new_variables_table(world); /* add 2 variables to table and 1 row sequence */ seq = rasqal_new_row_sequence(world, vt, test_1_rows, 2, &vars_seq); if(!seq) { fprintf(stderr, "%s: failed to create sequence of %d rows\n", program, rows_count); failures++; goto tidy; } rowsource = rasqal_new_rowsequence_rowsource(world, query, vt, seq, vars_seq); if(!rowsource) { fprintf(stderr, "%s: failed to create %d-row sequence rowsource\n", program, rows_count); failures++; goto tidy; } /* vars_seq and seq are now owned by rowsource */ vars_seq = seq = NULL; row = rasqal_rowsource_read_row(rowsource); if(!row) { fprintf(stderr, "%s: read_row returned no row for a %d-row sequence rowsource\n", program, rows_count); failures++; goto tidy; } #ifdef RASQAL_DEBUG RASQAL_DEBUG1("Result Row:\n "); rasqal_row_print(row, stderr); fputc('\n', stderr); #endif rasqal_free_row(row); row = NULL; count = rasqal_rowsource_get_rows_count(rowsource); if(count != rows_count) { fprintf(stderr, "%s: read_rows returned count %d instead of %d for a %d-row sequence rowsource\n", program, count, rows_count, rows_count); failures++; goto tidy; } row = rasqal_rowsource_read_row(rowsource); if(row) { fprintf(stderr, "%s: read_row returned > %d rows for a %d-row sequence rowsource\n", program, rows_count, rows_count); failures++; goto tidy; } rasqal_free_rowsource(rowsource); rowsource = NULL; rasqal_free_variables_table(vt); vt = NULL; /* test 3-row rowsource */ rows_count = 3; #ifdef RASQAL_DEBUG RASQAL_DEBUG2("Testing %d-row rowsource\n", rows_count); #endif vt = rasqal_new_variables_table(world); /* add 4 variables to table and 3 row sequence */ seq = rasqal_new_row_sequence(world, vt, test_3_rows, 4, &vars_seq); if(!seq) { fprintf(stderr, "%s: failed to create sequence of %d rows\n", program, rows_count); failures++; goto tidy; } rowsource = rasqal_new_rowsequence_rowsource(world, query, vt, seq, vars_seq); if(!rowsource) { fprintf(stderr, "%s: failed to create %d-row sequence rowsource\n", program, rows_count); failures++; goto tidy; } /* vars_seq and seq are now owned by rowsource */ vars_seq = seq = NULL; for(i = 0; i < rows_count; i++) { row = rasqal_rowsource_read_row(rowsource); if(!row) { fprintf(stderr, "%s: read_row returned no row for row %d in a %d-row sequence rowsource\n", program, i, rows_count); failures++; goto tidy; } #ifdef RASQAL_DEBUG RASQAL_DEBUG1("Result Row:\n "); rasqal_row_print(row, stderr); fputc('\n', stderr); #endif rasqal_free_row(row); row = NULL; } count = rasqal_rowsource_get_rows_count(rowsource); if(count != rows_count) { fprintf(stderr, "%s: read_rows returned count %d instead of %d for a %d-row sequence rowsource\n", program, count, rows_count, rows_count); failures++; goto tidy; } row = rasqal_rowsource_read_row(rowsource); if(row) { fprintf(stderr, "%s: read_row returned >%d rows for a %d-row sequence rowsource\n", program, rows_count, rows_count); failures++; goto tidy; } rasqal_free_rowsource(rowsource); rowsource = NULL; rasqal_free_variables_table(vt); vt = NULL; tidy: if(row) rasqal_free_row(row); if(seq) raptor_free_sequence(seq); if(rowsource) rasqal_free_rowsource(rowsource); if(vt) rasqal_free_variables_table(vt); if(query) rasqal_free_query(query); if(world) rasqal_free_world(world); return failures; }
static int rasqal_query_engine_algebra_execute_init(void* ex_data, rasqal_query* query, rasqal_query_results* query_results, int flags, rasqal_engine_error *error_p) { rasqal_engine_algebra_data* execution_data; rasqal_engine_error error; int rc = 0; rasqal_algebra_node* node; rasqal_algebra_aggregate* ae; execution_data = (rasqal_engine_algebra_data*)ex_data; /* initialise the execution_data fields */ execution_data->query = query; execution_data->query_results = query_results; if(!execution_data->triples_source) { execution_data->triples_source = rasqal_new_triples_source(execution_data->query); if(!execution_data->triples_source) { *error_p = RASQAL_ENGINE_FAILED; return 1; } } node = rasqal_algebra_query_to_algebra(query); if(!node) return 1; node = rasqal_algebra_query_add_group_by(query, node); if(!node) return 1; ae = rasqal_algebra_query_prepare_aggregates(query, node); if(!ae) return 1; if(ae) { node = rasqal_algebra_query_add_aggregation(query, ae, node); ae = NULL; if(!node) return 1; } node = rasqal_algebra_query_add_having(query, node); if(!node) return 1; node = rasqal_algebra_query_add_projection(query, node); if(!node) return 1; node = rasqal_algebra_query_add_modifiers(query, node); if(!node) return 1; node = rasqal_algebra_query_add_distinct(query,node); if(!node) return 1; execution_data->algebra_node = node; /* count final number of nodes */ execution_data->nodes_count = 0; rasqal_algebra_node_visit(query, execution_data->algebra_node, rasqal_engine_algebra_count_nodes, &execution_data->nodes_count); #ifdef RASQAL_DEBUG RASQAL_DEBUG1("algebra result: \n"); rasqal_algebra_node_print(node, DEBUG_FH); fputc('\n', DEBUG_FH); #endif RASQAL_DEBUG2("algebra nodes: %d\n", execution_data->nodes_count); error = RASQAL_ENGINE_OK; execution_data->rowsource = rasqal_algebra_node_to_rowsource(execution_data, node, &error); #ifdef RASQAL_DEBUG RASQAL_DEBUG1("rowsource (query plan) result: \n"); if(execution_data->rowsource) rasqal_rowsource_print(execution_data->rowsource, DEBUG_FH); else fputs("NULL", DEBUG_FH); fputc('\n', DEBUG_FH); #endif if(error != RASQAL_ENGINE_OK) rc = 1; return rc; }
static rasqal_rowsource* rasqal_algebra_graph_algebra_node_to_rowsource(rasqal_engine_algebra_data* execution_data, rasqal_algebra_node* node, rasqal_engine_error *error_p) { rasqal_query *query = execution_data->query; rasqal_rowsource *rs; rasqal_literal *graph = node->graph; rasqal_variable* v; if(!graph) { RASQAL_DEBUG1("graph algebra node has NULL graph\n"); return NULL; } /* This code checks that #1-#3 below are present and then executes parts #1 and #2 here. The graph rowsource created by rasqal_new_graph_rowsource() executes #3 http://www.w3.org/TR/2008/REC-rdf-sparql-query-20080115/#sparqlAlgebraEval SPARQL Query Language for RDF - Evaluation of a Graph Pattern #1 if IRI is a graph name in D eval(D(G), Graph(IRI,P)) = eval(D(D[IRI]), P) #2 if IRI is not a graph name in D eval(D(G), Graph(IRI,P)) = the empty multiset #3 eval(D(G), Graph(var,P)) = Let R be the empty multiset foreach IRI i in D R := Union(R, Join( eval(D(D[i]), P) , Omega(?var->i) ) the result is R */ v = rasqal_literal_as_variable(graph); if(!v && graph->type != RASQAL_LITERAL_URI) { /* value is neither a variable or URI literal - error */ RASQAL_DEBUG1("graph algebra node is neither variable or URI\n"); return NULL; } if(!v && graph->type == RASQAL_LITERAL_URI) { if(rasqal_query_dataset_contains_named_graph(query, graph->value.uri)) { /* case #1 - IRI is a graph name in D */ /* Set the origin of all triple patterns inside node->node1 to * URI graph->value.uri * * FIXME - this is a hack. The graph URI should be a parameter * to all rowsource constructors. */ rasqal_algebra_node_set_origin(query, node->node1, graph); rs = rasqal_algebra_node_to_rowsource(execution_data, node->node1, error_p); } else { /* case #2 - IRI is not a graph name in D - return empty rowsource */ rasqal_free_algebra_node(node->node1); node->node1 = NULL; rs = rasqal_new_empty_rowsource(query->world, query); } if(!rs || *error_p) rs = NULL; return rs; } /* case #3 - a variable */ rs = rasqal_algebra_node_to_rowsource(execution_data, node->node1, error_p); if(!rs || *error_p) return NULL; return rasqal_new_graph_rowsource(query->world, query, rs, v); }