static int rasqal_join_rowsource_reset(rasqal_rowsource* rowsource, void *user_data) { rasqal_join_rowsource_context* con; int rc; con = (rasqal_join_rowsource_context*)user_data; con->state = JS_START; con->failed = 0; rc = rasqal_rowsource_reset(con->left); if(rc) return rc; return rasqal_rowsource_reset(con->right); }
static int rasqal_distinct_rowsource_reset(rasqal_rowsource* rowsource, void *user_data) { rasqal_distinct_rowsource_context *con; con = (rasqal_distinct_rowsource_context*)user_data; return rasqal_rowsource_reset(con->rowsource); }
static rasqal_row* rasqal_graph_rowsource_read_row(rasqal_rowsource* rowsource, void *user_data) { rasqal_graph_rowsource_context *con; rasqal_row* row = NULL; con = (rasqal_graph_rowsource_context*)user_data; if(con->finished) return NULL; while(1) { row = rasqal_rowsource_read_row(con->rowsource); if(row) break; if(rasqal_graph_next_dg(con)) { con->finished = 1; break; } if(rasqal_rowsource_reset(con->rowsource)) { con->finished = 1; break; } } /* If a row is returned, put the GRAPH variable value as first literal */ if(row) { rasqal_row* nrow; int i; nrow = rasqal_new_row_for_size(rowsource->world, 1 + row->size); if(!nrow) { rasqal_free_row(row); row = NULL; } else { nrow->rowsource = rowsource; nrow->offset = row->offset; /* Put GRAPH variable value (or NULL) first in result row */ nrow->values[0] = rasqal_new_literal_from_literal(con->var->value); /* Copy (size-1) remaining variables from input row */ for(i = 0; i < row->size; i++) nrow->values[i + 1] = rasqal_new_literal_from_literal(row->values[i]); rasqal_free_row(row); row = nrow; } } return row; }
static int rasqal_graph_rowsource_reset(rasqal_rowsource* rowsource, void *user_data) { rasqal_graph_rowsource_context *con; con = (rasqal_graph_rowsource_context*)user_data; con->finished = 0; con->dg_offset = -1; con->offset = 0; rasqal_graph_next_dg(con); return rasqal_rowsource_reset(con->rowsource); }
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; }