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; }
static int #else static void #endif rasqal_rowsource_groupby_tree_print_node(void *object, FILE *fh) { rasqal_groupby_tree_node* node = (rasqal_groupby_tree_node*)object; fputs("Group\n Key Sequence of literals: ", fh); if(node->literals) /* sequence of literals */ raptor_sequence_print(node->literals, fh); else fputs("None", fh); fputs("\n Value Sequence of rows:\n", fh); if(node->rows) { int i; int size = raptor_sequence_size(node->rows); /* sequence of rows */ for(i = 0; i < size; i++) { rasqal_row* row = (rasqal_row*)raptor_sequence_get_at(node->rows, i); fprintf(fh, " Row %d: ", i); rasqal_row_print(row, fh); fputc('\n', fh); } } else fputs("None\n", fh); #ifdef HAVE_RAPTOR2_API return 0; #endif }
static int #else static void #endif rasqal_engine_rowsort_map_print_row(void *object, FILE *fh) { if(object) rasqal_row_print((rasqal_row*)object, fh); else fputs("NULL", fh); #ifdef HAVE_RAPTOR2_API return 0; #endif }
/** * rasqal_rowsource_print_row_sequence: * @rowsource: rowsource associated with rows * @seq: query result sequence of #rasqal_row * @fp: FILE* handle to print to * * INTERNAL - Print a result set header with row values from a sequence */ void rasqal_rowsource_print_row_sequence(rasqal_rowsource* rowsource, raptor_sequence* seq, FILE* fh) { int size = raptor_sequence_size(seq); int i; rasqal_rowsource_print_header(rowsource, fh); for(i = 0; i < size; i++) { rasqal_row *row = (rasqal_row*)raptor_sequence_get_at(seq, i); rasqal_row_print(row, fh); fputs("\n", fh); } }
/** * 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_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_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; }
static void roqet_query_walk(rasqal_query *rq, FILE *fh, int indent) { rasqal_query_verb verb; int i; rasqal_graph_pattern* gp; raptor_sequence *seq; verb = rasqal_query_get_verb(rq); roqet_write_indent(fh, indent); fprintf(fh, "query verb: %s\n", rasqal_query_verb_as_string(verb)); i = rasqal_query_get_distinct(rq); if(i != 0) { roqet_write_indent(fh, indent); fprintf(fh, "query asks for distinct results\n"); } i = rasqal_query_get_limit(rq); if(i >= 0) { roqet_write_indent(fh, indent); fprintf(fh, "query asks for result limits %d\n", i); } i = rasqal_query_get_offset(rq); if(i >= 0) { roqet_write_indent(fh, indent); fprintf(fh, "query asks for result offset %d\n", i); } seq = rasqal_query_get_bound_variable_sequence(rq); if(seq && raptor_sequence_size(seq) > 0) { fprintf(fh, "query bound variables (%d): ", raptor_sequence_size(seq)); i = 0; while(1) { rasqal_variable* v = (rasqal_variable*)raptor_sequence_get_at(seq, i); if(!v) break; if(i > 0) fputs(", ", fh); roqet_query_write_variable(fh, v); i++; } fputc('\n', fh); } gp = rasqal_query_get_query_graph_pattern(rq); if(!gp) return; seq = rasqal_query_get_construct_triples_sequence(rq); if(seq && raptor_sequence_size(seq) > 0) { roqet_write_indent(fh, indent); fprintf(fh, "query construct triples (%d) {\n", raptor_sequence_size(seq)); i = 0; while(1) { rasqal_triple* t = rasqal_query_get_construct_triple(rq, i); if(!t) break; roqet_write_indent(fh, indent + 2); fprintf(fh, "triple #%d { ", i); rasqal_triple_print(t, fh); fputs(" }\n", fh); i++; } roqet_write_indent(fh, indent); fputs("}\n", fh); } /* look for binding rows */ seq = rasqal_query_get_bindings_variables_sequence(rq); if(seq) { roqet_write_indent(fh, indent); fprintf(fh, "bindings variables (%d): ", raptor_sequence_size(seq)); i = 0; while(1) { rasqal_variable* v = rasqal_query_get_bindings_variable(rq, i); if(!v) break; if(i > 0) fputs(", ", fh); roqet_query_write_variable(fh, v); i++; } fputc('\n', fh); seq = rasqal_query_get_bindings_rows_sequence(rq); fprintf(fh, "bindings rows (%d) {\n", raptor_sequence_size(seq)); i = 0; while(1) { rasqal_row* row; row = rasqal_query_get_bindings_row(rq, i); if(!row) break; roqet_write_indent(fh, indent + 2); fprintf(fh, "row #%d { ", i); rasqal_row_print(row, fh); fputs("}\n", fh); i++; } } fputs("query ", fh); roqet_graph_pattern_walk(gp, -1, fh, indent); }
/** * 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; }
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; }