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;
}
示例#2
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;
}
示例#3
0
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;
}
示例#4
0
/* 
 * 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;
}
示例#5
0
/**
 * 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;
}
示例#6
0
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;
}
示例#7
0
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;
}
示例#8
0
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;
}
示例#9
0
/**
 * 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;
}
示例#10
0
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;
}
示例#11
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;
}
示例#12
0
/**
 * 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;
}
示例#14
0
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;
}
示例#15
0
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);
}