Example #1
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;
}
Example #2
0
/**
 * rasqal_service_execute:
 * @svc: rasqal service
 *
 * Execute a rasqal sparql protocol service
 *
 * Return value: query results or NULL on failure
 */
rasqal_query_results*
rasqal_service_execute(rasqal_service* svc)
{
  rasqal_query_results* results = NULL;
  unsigned char* result_string = NULL;
  size_t result_length;
  raptor_iostream* read_iostr = NULL;
  raptor_uri* read_base_uri = NULL;
  rasqal_variables_table* vars_table = NULL;
  rasqal_query_results_formatter* read_formatter = NULL;
  raptor_uri* retrieval_uri = NULL;
  raptor_stringbuffer* uri_sb = NULL;
  size_t len;
  unsigned char* str;
  raptor_world* raptor_world_ptr = rasqal_world_get_raptor(svc->world);
  
  if(!svc->www) {
    svc->www = raptor_new_www(raptor_world_ptr);

    if(!svc->www) {
      rasqal_log_error_simple(svc->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                              "Failed to create WWW");
      goto error;
    }
  }
    
  svc->started = 0;
  svc->final_uri = NULL;
  svc->sb = raptor_new_stringbuffer();
  svc->content_type = NULL;
  
  if(svc->format)
    raptor_www_set_http_accept(svc->www, svc->format);
  else
    raptor_www_set_http_accept(svc->www, DEFAULT_FORMAT);

  raptor_www_set_write_bytes_handler(svc->www,
                                     rasqal_service_write_bytes, svc);
  raptor_www_set_content_type_handler(svc->www,
                                      rasqal_service_content_type_handler, svc);


  /* Construct a URI to retrieve following SPARQL protocol HTTP
   *  binding from concatenation of
   *
   * 1. service_uri
   * 2. '?'
   * 3. "query=" query_string
   * 4. "&default-graph-uri=" background graph URI if any
   * 5. "&named-graph-uri=" named graph URI for all named graphs
   * with URI-escaping of the values
   */

  uri_sb = raptor_new_stringbuffer();
  if(!uri_sb) {
    rasqal_log_error_simple(svc->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                            "Failed to create stringbuffer");
    goto error;
  }

  str = raptor_uri_as_counted_string(svc->service_uri, &len);
  raptor_stringbuffer_append_counted_string(uri_sb, str, len, 1);

  raptor_stringbuffer_append_counted_string(uri_sb,
                                            (const unsigned char*)"?", 1, 1);

  if(svc->query_string) {
    raptor_stringbuffer_append_counted_string(uri_sb,
                                              (const unsigned char*)"query=", 6, 1);
    raptor_stringbuffer_append_uri_escaped_counted_string(uri_sb,
                                                          svc->query_string,
                                                          svc->query_string_len,
                                                          1);
  }


  if(svc->data_graphs) {
    rasqal_data_graph* dg;
    int i;
    int bg_graph_count;
    
    for(i = 0, bg_graph_count = 0;
        (dg = (rasqal_data_graph*)raptor_sequence_get_at(svc->data_graphs, i));
        i++) {
      unsigned char* graph_str;
      size_t graph_len;
      raptor_uri* graph_uri;
      
      if(dg->flags & RASQAL_DATA_GRAPH_BACKGROUND) {

        if(bg_graph_count++) {
          if(bg_graph_count == 2) {
            /* Warn once, only when the second BG is seen */
            rasqal_log_warning_simple(svc->world,
                                      RASQAL_WARNING_LEVEL_MULTIPLE_BG_GRAPHS,
                                      NULL,
                                      "Attempted to add multiple background graphs");
          }
          /* always skip after first BG */
          continue;
        }
        
        raptor_stringbuffer_append_counted_string(uri_sb,
                                                  (const unsigned char*)"&default-graph-uri=", 19, 1);
        graph_uri = dg->uri;
      } else {
        raptor_stringbuffer_append_counted_string(uri_sb,
                                                  (const unsigned char*)"&named-graph-uri=", 17, 1);
        graph_uri = dg->name_uri;
      }
      
      graph_str = raptor_uri_as_counted_string(graph_uri, &graph_len);
      raptor_stringbuffer_append_uri_escaped_counted_string(uri_sb,
                                                            (const char*)graph_str, graph_len, 1);
    }
  }
  

  str = raptor_stringbuffer_as_string(uri_sb);

  retrieval_uri = raptor_new_uri(raptor_world_ptr, str);
  if(!retrieval_uri) {
    rasqal_log_error_simple(svc->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                            "Failed to create retrieval URI %s",
                            raptor_uri_as_string(retrieval_uri));
    goto error;
  }

  raptor_free_stringbuffer(uri_sb); uri_sb = NULL;
  
  if(raptor_www_fetch(svc->www, retrieval_uri)) {
    rasqal_log_error_simple(svc->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                            "Failed to fetch retrieval URI %s",
                            raptor_uri_as_string(retrieval_uri));
    goto error;
  }

  vars_table = rasqal_new_variables_table(svc->world);
  if(!vars_table) {
    rasqal_log_error_simple(svc->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                            "Failed to create variables table");
    goto error;
  }
  
  results = rasqal_new_query_results(svc->world, NULL, 
                                     RASQAL_QUERY_RESULTS_BINDINGS, 
                                     vars_table);
  /* (results takes a reference/copy to vars_table) */
  rasqal_free_variables_table(vars_table); vars_table = NULL;

  if(!results) {
    rasqal_log_error_simple(svc->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                            "Failed to create query results");
    goto error;
  }
  
  result_length = raptor_stringbuffer_length(svc->sb);  
  result_string = raptor_stringbuffer_as_string(svc->sb);
  read_iostr = raptor_new_iostream_from_string(raptor_world_ptr,
                                               result_string, result_length);
  if(!read_iostr) {
    rasqal_log_error_simple(svc->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                            "Failed to create iostream from string");
    rasqal_free_query_results(results);
    results = NULL;
    goto error;
  }
    
  read_base_uri = svc->final_uri ? svc->final_uri : svc->service_uri;
  read_formatter = rasqal_new_query_results_formatter(svc->world,
                                                      /* format name */ NULL,
                                                      svc->content_type,
                                                      /* format URI */ NULL);
  if(!read_formatter) {
    rasqal_log_error_simple(svc->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                            "Failed to create query formatter for type %s",
                            svc->content_type);
    rasqal_free_query_results(results);
    results = NULL;
    goto error;
  }

  if(rasqal_query_results_formatter_read(svc->world,
                                         read_iostr, read_formatter,
                                         results, read_base_uri)) {
    rasqal_log_error_simple(svc->world, RAPTOR_LOG_LEVEL_ERROR, NULL,
                            "Failed to read from query formatter");
    rasqal_free_query_results(results);
    results = NULL;
    goto error;
  }


  error:
  if(retrieval_uri)
    raptor_free_uri(retrieval_uri);

  if(uri_sb)
    raptor_free_stringbuffer(uri_sb);

  if(read_formatter)
    rasqal_free_query_results_formatter(read_formatter);
  
  if(read_iostr)
    raptor_free_iostream(read_iostr);
  
  if(vars_table)
    rasqal_free_variables_table(vars_table);

  if(svc->final_uri) {
    raptor_free_uri(svc->final_uri);
    svc->final_uri = NULL;
  }

  if(svc->content_type) {
    RASQAL_FREE(cstring, svc->content_type);
    svc->content_type = NULL;
  }

  if(svc->sb) {
    raptor_free_stringbuffer(svc->sb);
    svc->sb = NULL;
  }
  
  return results;
}
Example #3
0
/**
 * rasqal_query_results_get_triple:
 * @query_results: #rasqal_query_results query_results
 *
 * Get the current triple in the result.
 *
 * The return value is a shared #raptor_statement.
 * 
 * Return value: #raptor_statement or NULL if failed or results exhausted
 **/
raptor_statement*
rasqal_query_results_get_triple(rasqal_query_results* query_results)
{
  rasqal_query* query;
  int rc;
  rasqal_triple *t;
  rasqal_literal *s, *p, *o;
  raptor_statement *rs = NULL;
  unsigned char *nodeid;
  int skipped;
  
  RASQAL_ASSERT_OBJECT_POINTER_RETURN_VALUE(query_results, rasqal_query_results, NULL);

 if(query_results->failed || query_results->finished)
    return NULL;
  
  if(!rasqal_query_results_is_graph(query_results))
    return NULL;
  
  query = query_results->query;
  if(!query)
    return NULL;
  
  if(query->verb == RASQAL_QUERY_VERB_DESCRIBE)
    return NULL;

 
  /* ensure we have a row to work on */
  if(rasqal_query_results_ensure_have_row_internal(query_results))
    return NULL;

  skipped = 0;
  while(1) {
    if(skipped) {
      rc = rasqal_query_results_next(query_results);
      if(rc) {
        rs = NULL;
        break;
      }
      query_results->current_triple_result = -1;
    }
    
    if(query_results->current_triple_result < 0)
      query_results->current_triple_result = 0;

    t = (rasqal_triple*)raptor_sequence_get_at(query->constructs,
                                               query_results->current_triple_result);

    rs = &query_results->result_triple;

    s = rasqal_literal_as_node(t->subject);
    if(!s) {
      rasqal_log_warning_simple(query_results->world,
                                RASQAL_WARNING_LEVEL_BAD_TRIPLE,
                                &query->locator,
                                "Triple with unbound subject skipped");
      skipped = 1;
      continue;
    }

    /* raptor v2 terms are copied, not shared */
    if(rs->subject) {
      raptor_free_term(rs->subject);
      rs->subject = NULL;
    }

    switch(s->type) {
      case RASQAL_LITERAL_URI:
        rs->subject = raptor_new_term_from_uri(query_results->world->raptor_world_ptr,
                                               s->value.uri);
        break;

      case RASQAL_LITERAL_BLANK:
        nodeid = rasqal_prefix_id(query_results->result_count,
                                  (unsigned char*)s->string);
        rasqal_free_literal(s);
        if(!nodeid) {
          rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_FATAL,
                                  &query->locator,
                                  "Could not prefix subject blank identifier");
          return NULL;
        }
        s = rasqal_new_simple_literal(query_results->world, RASQAL_LITERAL_BLANK,
                                      nodeid);
        if(!s) {
          rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_FATAL,
                                  &query->locator,
                                  "Could not create a new subject blank literal");
          return NULL;
        }
        rs->subject = raptor_new_term_from_blank(query_results->world->raptor_world_ptr,
                                                 nodeid);
        break;

      case RASQAL_LITERAL_QNAME:
      case RASQAL_LITERAL_PATTERN:
      case RASQAL_LITERAL_XSD_STRING:
      case RASQAL_LITERAL_BOOLEAN:
      case RASQAL_LITERAL_INTEGER:
      case RASQAL_LITERAL_DOUBLE:
      case RASQAL_LITERAL_FLOAT:
      case RASQAL_LITERAL_VARIABLE:
      case RASQAL_LITERAL_DECIMAL:
      case RASQAL_LITERAL_DATETIME:
      case RASQAL_LITERAL_UDT:
      case RASQAL_LITERAL_INTEGER_SUBTYPE:
        /* QNames should be gone by the time expression eval happens
         * Everything else is removed by rasqal_literal_as_node() above. 
         */

      case RASQAL_LITERAL_STRING:
        /* string [literal] subjects are not RDF */

      case RASQAL_LITERAL_UNKNOWN:
      default:
        /* case RASQAL_LITERAL_STRING: */
      rasqal_log_warning_simple(query_results->world,
                                RASQAL_WARNING_LEVEL_BAD_TRIPLE,
                                &query->locator,
                                "Triple with non-URI/blank node subject skipped");
        skipped = 1;
        break;
    }
    if(skipped) {
      if(s)
        rasqal_free_literal(s);
      continue;
    }
    

    p = rasqal_literal_as_node(t->predicate);
    if(!p) {
      rasqal_log_warning_simple(query_results->world,
                                RASQAL_WARNING_LEVEL_BAD_TRIPLE,
                                &query->locator,
                                "Triple with unbound predicate skipped");
      rasqal_free_literal(s);
      skipped = 1;
      continue;
    }
    switch(p->type) {
      case RASQAL_LITERAL_URI:
        /* raptor v2 terms are copied, not shared */
        if(rs->predicate) {
          raptor_free_term(rs->predicate);
          rs->predicate = NULL;
        }
        rs->predicate = raptor_new_term_from_uri(query_results->world->raptor_world_ptr,
                                                 p->value.uri);
        break;

      case RASQAL_LITERAL_QNAME:
      case RASQAL_LITERAL_PATTERN:
      case RASQAL_LITERAL_XSD_STRING:
      case RASQAL_LITERAL_BOOLEAN:
      case RASQAL_LITERAL_INTEGER:
      case RASQAL_LITERAL_DOUBLE:
      case RASQAL_LITERAL_FLOAT:
      case RASQAL_LITERAL_VARIABLE:
      case RASQAL_LITERAL_DECIMAL:
      case RASQAL_LITERAL_DATETIME:
      case RASQAL_LITERAL_UDT:
      case RASQAL_LITERAL_INTEGER_SUBTYPE:
        /* QNames should be gone by the time expression eval happens
         * Everything else is removed by rasqal_literal_as_node() above. 
         */

      case RASQAL_LITERAL_BLANK:
      case RASQAL_LITERAL_STRING:
        /* blank node or string [literal] predicates are not RDF */

      case RASQAL_LITERAL_UNKNOWN:
      default:
      rasqal_log_warning_simple(query_results->world,
                                RASQAL_WARNING_LEVEL_BAD_TRIPLE,
                                &query->locator,
                                "Triple with non-URI predicate skipped");
        skipped = 1;
        break;
    }
    if(skipped) {
      rasqal_free_literal(s);
      if(p)
        rasqal_free_literal(p);
      continue;
    }

    o = rasqal_literal_as_node(t->object);
    if(!o) {
      rasqal_log_warning_simple(query_results->world,
                                RASQAL_WARNING_LEVEL_BAD_TRIPLE,
                                &query->locator,
                                "Triple with unbound object skipped");
      rasqal_free_literal(s);
      rasqal_free_literal(p);
      skipped = 1;
      continue;
    }

    /* raptor v2 terms are copied, not shared */
    if(rs->object) {
      raptor_free_term(rs->object);
      rs->object = NULL;
    }

    switch(o->type) {
      case RASQAL_LITERAL_URI:
        rs->object = raptor_new_term_from_uri(query_results->world->raptor_world_ptr,
                                              o->value.uri);
        break;

      case RASQAL_LITERAL_BLANK:
        nodeid = rasqal_prefix_id(query_results->result_count,
                                  (unsigned char*)o->string);
        rasqal_free_literal(o);
        if(!nodeid) {
          rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_FATAL,
                                  &query->locator,
                                  "Could not prefix blank identifier");
          rasqal_free_literal(s);
          rasqal_free_literal(p);
          return NULL;
        }
        o = rasqal_new_simple_literal(query_results->world, RASQAL_LITERAL_BLANK,
                                      nodeid);
        if(!o) {
          rasqal_log_error_simple(query_results->world, RAPTOR_LOG_LEVEL_FATAL,
                                  &query->locator,
                                  "Could not create a new subject blank literal");
          rasqal_free_literal(s);
          rasqal_free_literal(p);
          return NULL;
        }
        rs->object = raptor_new_term_from_blank(query_results->world->raptor_world_ptr,
                                                nodeid);
        break;

      case RASQAL_LITERAL_STRING:
        rs->object = raptor_new_term_from_literal(query_results->world->raptor_world_ptr,
                                                  o->string,
                                                  o->datatype,
                                                  (const unsigned char*)o->language);
        break;

      case RASQAL_LITERAL_QNAME:
      case RASQAL_LITERAL_PATTERN:
      case RASQAL_LITERAL_XSD_STRING:
      case RASQAL_LITERAL_BOOLEAN:
      case RASQAL_LITERAL_INTEGER:
      case RASQAL_LITERAL_DOUBLE:
      case RASQAL_LITERAL_FLOAT:
      case RASQAL_LITERAL_VARIABLE:
      case RASQAL_LITERAL_DECIMAL:
      case RASQAL_LITERAL_DATETIME:
      case RASQAL_LITERAL_UDT:
      case RASQAL_LITERAL_INTEGER_SUBTYPE:
        /* QNames should be gone by the time expression eval happens
         * Everything else is removed by rasqal_literal_as_node() above. 
         */

      case RASQAL_LITERAL_UNKNOWN:
      default:
        rasqal_log_warning_simple(query_results->world,
                                  RASQAL_WARNING_LEVEL_BAD_TRIPLE,
                                  &query->locator,
                                  "Triple with unknown object skipped");
        skipped = 1;
        break;
    }
    if(skipped) {
      rasqal_free_literal(s);
      rasqal_free_literal(p);
      if(o)
        rasqal_free_literal(o);
      continue;
    }
    
    /* dispose previous triple if any */
    if(query_results->triple) {
      rasqal_free_triple(query_results->triple);
      query_results->triple = NULL;
    }

    /* for saving s, p, o for later disposal */
    query_results->triple = rasqal_new_triple(s, p, o);

    /* got triple, return it */
    break;
  }
  
  return rs;
}
Example #4
0
/*
 * rasqal_regex_match:
 * @world: world
 * @locator: locator
 * @pattern: regex pattern
 * @regex_flags: regex flags string
 * @subject: input string
 * @subject_len: input string length
 *
 * INTERNAL - Test if a string matches a regex pattern.
 *
 * Intended to be used for executing #RASQAL_EXPR_STR_MATCH and
 * #RASQAL_EXPR_STR_NMATCH operations (unused: formerly RDQL)
 *
 * Return value: <0 on error, 0 for no match, >0 for match
 *
 */
int
rasqal_regex_match(rasqal_world* world, raptor_locator* locator,
                   const char* pattern,
                   const char* regex_flags,
                   const char* subject, size_t subject_len)
{
  int flag_i = 0; /* regex_flags contains i */
  const char *p;
#ifdef RASQAL_REGEX_PCRE
  pcre* re;
  int compile_options = PCRE_UTF8;
  int exec_options = 0;
  const char *re_error = NULL;
  int erroffset = 0;
#endif
#ifdef RASQAL_REGEX_POSIX
  regex_t reg;
  int compile_options = REG_EXTENDED;
  int exec_options = 0;
#endif
  int rc = 0;

  for(p = regex_flags; p && *p; p++)
    if(*p == 'i')
      flag_i++;
      
#ifdef RASQAL_REGEX_PCRE
  if(flag_i)
    compile_options |= PCRE_CASELESS;
    
  re = pcre_compile(RASQAL_GOOD_CAST(const char*, pattern), compile_options,
                    &re_error, &erroffset, NULL);
  if(!re) {
    rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR, locator,
                            "Regex compile of '%s' failed - %s", pattern, re_error);
    rc = -1;
  } else {
    rc = pcre_exec(re, 
                   NULL, /* no study */
                   subject,
                   RASQAL_BAD_CAST(int, subject_len), /* PCRE API is an int */
                   0 /* startoffset */,
                   exec_options /* options */,
                   NULL, 0 /* ovector, ovecsize - no matches wanted */
                   );
    if(rc >= 0)
      rc = 1;
    else if(rc != PCRE_ERROR_NOMATCH) {
      rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR, locator,
                              "Regex match failed - returned code %d", rc);
      rc= -1;
    } else
      rc = 0;
  }
  pcre_free(re);
  
#endif
    
#ifdef RASQAL_REGEX_POSIX
  if(flag_i)
    compile_options |= REG_ICASE;
    
  rc = regcomp(&reg, RASQAL_GOOD_CAST(const char*, pattern), compile_options);
  if(rc) {
    rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR,
                            locator,
                            "Regex compile of '%s' failed", pattern);
    rc = -1;
  } else {
    rc = regexec(&reg, RASQAL_GOOD_CAST(const char*, subject),
                 0, NULL, /* nmatch, regmatch_t pmatch[] - no matches wanted */
                 exec_options /* eflags */
                 );
    if(!rc)
      rc = 1;
    else if (rc != REG_NOMATCH) {
      rasqal_log_error_simple(world, RAPTOR_LOG_LEVEL_ERROR, locator,
                              "Regex match failed - returned code %d", rc);
      rc = -1;
    } else
      rc = 0;
  }
  regfree(&reg);
#endif

#ifdef RASQAL_REGEX_NONE
  rasqal_log_warning_simple(world, RASQAL_WARNING_LEVEL_MISSING_SUPPORT, locator,
                            "Regex support missing, cannot compare '%s' to '%s'",
                            match_string, pattern);
  rc = -1;
#endif

  return rc;
}