fs_value fn_numeric_multiply(fs_query *q, fs_value a, fs_value b) { a = fs_value_promote(q, a, b); b = fs_value_promote(q, b, a); if (a.attr == b.attr && a.attr != FS_RID_NULL && a.attr != fs_c.empty) { fs_value v = fs_value_blank(); v.attr = a.attr; if (a.attr == fs_c.xsd_double || a.attr == fs_c.xsd_float) { v.fp = a.fp * b.fp; v.valid = fs_valid_bit(FS_V_FP); return v; } else if (a.attr == fs_c.xsd_decimal) { fs_decimal_multiply(&a.de, &b.de, &v.de); v.valid = fs_valid_bit(FS_V_DE); return v; } else if (a.attr == fs_c.xsd_integer) { v.in = a.in * b.in; v.valid = fs_valid_bit(FS_V_IN); return v; } } return fs_value_error(FS_ERROR_INVALID_TYPE, "non-numeric arguments to fn:numeric-multiply"); }
fs_value fn_numeric_divide(fs_query *q, fs_value a, fs_value b) { a = fs_value_promote(q, a, b); b = fs_value_promote(q, b, a); if (a.attr == b.attr && a.attr != FS_RID_NULL && a.attr != fs_c.empty) { fs_value v = fs_value_blank(); if (a.attr == fs_c.xsd_integer) { fs_decimal_init_from_int64(&a.de, a.in); fs_decimal_init_from_int64(&b.de, b.in); a.attr = fs_c.xsd_decimal; } v.attr = a.attr; if (a.attr == fs_c.xsd_double || a.attr == fs_c.xsd_float) { v.fp = a.fp / b.fp; v.valid = fs_valid_bit(FS_V_FP); return v; } else if (a.attr == fs_c.xsd_decimal) { if (fs_decimal_divide(&a.de, &b.de, &v.de)) { return fs_value_error(FS_ERROR_INVALID_TYPE, "divide by zero"); } v.valid = fs_valid_bit(FS_V_DE); return v; } } return fs_value_error(FS_ERROR_INVALID_TYPE, "non-numeric arguments to fn:numeric-divide"); }
fs_value fn_equal(fs_query *q, fs_value a, fs_value b) { #if 0 fs_value_print(a); printf(" = "); fs_value_print(b); printf("\n"); #endif if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (b.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return b; } fs_value term_equal = fn_rdfterm_equal(q, a, b); if (term_equal.in == 1) { return term_equal; } if (a.attr == fs_c.xsd_datetime) return fn_datetime_equal(q, a, b); if (fs_is_numeric(&a) && fs_is_numeric(&b)) return fn_numeric_equal(q, a, b); if (FS_IS_LITERAL(a.rid) && FS_IS_LITERAL(b.rid) && (a.attr == fs_c.empty || a.attr == fs_c.xsd_string) && (b.attr == fs_c.empty || b.attr == fs_c.xsd_string)) { return fs_value_boolean(!strcmp(a.lex, b.lex)); } return fs_value_boolean(0); }
fs_value fs_value_resource(fs_query *q, fs_resource *r) { fs_value v = fs_value_blank(); v.lex = r->lex; if (r->rid == FS_RID_NULL) { return fs_value_rid(FS_RID_NULL); } if (r->attr == fs_c.xsd_integer) { v = fn_cast_intl(q, v, fs_c.xsd_integer); } else if (r->attr == fs_c.xsd_float || r->attr == fs_c.xsd_double) { v = fn_cast_intl(q, v, fs_c.xsd_double); } else if (r->attr == fs_c.xsd_decimal) { v = fn_cast_intl(q, v, fs_c.xsd_decimal); } else if (r->attr == fs_c.xsd_boolean) { if (!strcmp(r->lex, "true") || !strcmp(r->lex, "1")) { v = fs_value_boolean(1); } else { v = fs_value_boolean(0); } } else if (r->attr == fs_c.xsd_datetime) { v = fs_value_datetime_from_string(r->lex); } if (fs_is_error(v)) { v = fs_value_blank(); v.lex = r->lex; } v.rid = r->rid; v.attr = r->attr; v.valid |= fs_valid_bit(FS_V_RID) | fs_valid_bit(FS_V_ATTR); return v; }
int fs_value_equal(fs_value a, fs_value b) { if ((a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) && (b.valid & fs_valid_bit(FS_V_TYPE_ERROR))) { return 1; } if (a.valid & fs_valid_bit(FS_V_RID) && b.valid & fs_valid_bit(FS_V_RID)) { return a.rid == b.rid; } if (a.attr != b.attr) { return 0; } if (a.attr == fs_c.xsd_double || a.attr == fs_c.xsd_float) { return a.fp == b.fp; } else if (a.attr == fs_c.xsd_decimal) { return fs_decimal_equal(&a.de, &b.de); } else if (a.attr == fs_c.xsd_integer) { return a.in == b.in; } else if (a.attr == fs_c.xsd_boolean) { return (a.in ? 1: 0) == (b.in ? 1: 0); } else if (a.attr == fs_c.xsd_datetime) { return a.in == b.in; } else if (a.attr == fs_c.xsd_string && a.lex && b.lex) { return !strcmp(a.lex, b.lex); } else if (a.attr == b.attr && a.lex && b.lex) { return !strcmp(a.lex, b.lex); } return 0; }
fs_value fs_value_datetime_from_string(const char *s) { fs_value v = fs_value_blank(); v.attr = fs_c.xsd_datetime; struct tm td; memset(&td, 0, sizeof(struct tm)); GTimeVal gtime; if (g_time_val_from_iso8601(s, >ime)) { v.in = gtime.tv_sec; v.valid = fs_valid_bit(FS_V_IN); v.lex = (char *)s; return v; } char *ret = strptime(s, "%Y-%m-%d", &td); if (ret) { v.in = timegm(&td); v.valid = fs_valid_bit(FS_V_IN); return v; } return fs_value_error(FS_ERROR_INVALID_TYPE, "cannot convert value to xsd:dateTime"); }
fs_value fn_less_than_equal(fs_query *q, fs_value a, fs_value b) { #if 0 fs_value_print(a); printf(" <= "); fs_value_print(b); printf("\n"); #endif if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (b.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return b; } /* URIs and bNodes don't compare */ if (FS_IS_URI_BN(a.rid) || FS_IS_URI_BN(b.rid)) { return fs_value_boolean(0); } /* If it's simply the same term it must be <= itsself */ fs_value term_eq = fn_rdfterm_equal(q, a, b); if (term_eq.in == 1) { return term_eq; } if (a.attr == fs_c.xsd_datetime && b.attr == fs_c.xsd_datetime) return fn_not(q, fn_datetime_greater_than(q, a, b)); if (fs_is_numeric(&a) && fs_is_numeric(&b)) return fn_logical_or(q, fn_numeric_less_than(q, a, b), fn_numeric_equal(q, a, b)); if (a.lex && b.lex) return fn_not(q, fn_numeric_equal(q, fn_compare(q, a, b), fs_value_integer(1))); return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); }
fs_value fn_uri(fs_query *q, fs_value a) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (a.valid & fs_valid_bit(FS_V_RID) && FS_IS_BNODE(a.rid)) { fs_value v = fs_value_blank(); v.lex = g_strdup_printf("bnode:b%llx", FS_BNODE_NUM(a.rid)); fs_query_add_freeable(q, v.lex); v.rid = fs_hash_uri_ignore_bnode(v.lex); v.valid = fs_valid_bit(FS_V_RID); v.attr = FS_RID_NULL; return v; } if (a.lex) { return fs_value_uri(a.lex); } a = fs_value_fill_lexical(q, a); fs_value v = fs_value_uri(a.lex); return v; }
void fs_value_print(fs_value v) { if (v.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { printf("error"); if (v.lex) { printf("(%s)", v.lex); } return; } if (v.attr == fs_c.xsd_double) { printf("db"); } else if (v.attr == fs_c.xsd_float) { printf("fl"); } else if (v.attr == fs_c.xsd_decimal) { printf("de"); } else if (v.attr == fs_c.xsd_integer) { printf("in"); } else if (v.attr == fs_c.xsd_boolean) { printf("bl"); } else if (v.attr == fs_c.xsd_string) { printf("st"); } else if (v.attr == fs_c.xsd_datetime) { printf("dt"); } else if (v.attr == fs_c.empty || v.attr == FS_RID_NULL) { if (v.rid == FS_RID_NULL) { printf("NULL"); } else if (FS_IS_BNODE(v.rid)) { printf("bnode"); } else if (FS_IS_URI(v.rid)) { printf("uri"); } else { printf("plain"); } } else { printf("attr:%llx", v.attr); } if (v.valid & fs_valid_bit(FS_V_RID)) { printf(" rid:%llx", v.rid); } if (v.lex) { printf(" l:%s", v.lex); } if (v.valid & fs_valid_bit(FS_V_FP)) { printf(" f:%f", v.fp); } if (v.valid & fs_valid_bit(FS_V_DE)) { char *dlex = fs_decimal_to_lex(&v.de); printf(" d:%s", dlex); free(dlex); } if (v.valid & fs_valid_bit(FS_V_IN)) { printf(" i:%lld", (long long)v.in); } }
fs_value fn_bound(fs_query *q, fs_value a) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (a.valid & fs_valid_bit(FS_V_RID)) { return fs_value_boolean(a.rid != FS_RID_NULL); } return fs_value_boolean(1); }
fs_value fn_is_literal(fs_query *q, fs_value a) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (a.valid & fs_valid_bit(FS_V_RID)) { return fs_value_boolean(FS_IS_LITERAL(a.rid)); } return fs_value_boolean(a.attr != FS_RID_NULL); }
fs_value fs_value_promote(fs_query *q, fs_value a, fs_value b) { if (!fs_is_numeric(&a) || !fs_is_numeric(&b)) { return fs_value_error(FS_ERROR_INVALID_TYPE, "cannot promote non-numeric value"); } if (a.attr == b.attr) { return a; } if (a.attr == fs_c.xsd_double || b.attr == fs_c.xsd_double) { if (a.attr != fs_c.xsd_double) { a = fn_cast_intl(q, a, fs_c.xsd_double); } return a; } if (a.attr == fs_c.xsd_float || b.attr == fs_c.xsd_float) { if (a.attr != fs_c.xsd_float) { a = fn_cast_intl(q, a, fs_c.xsd_float); } return a; } if (a.attr == fs_c.xsd_decimal || b.attr == fs_c.xsd_decimal) { if (a.attr != fs_c.xsd_decimal) { a.valid |= fs_valid_bit(FS_V_DE); if (a.attr == fs_c.xsd_integer || a.attr == fs_c.xsd_boolean) { fs_decimal_init_from_int64(&a.de, a.in); } else { fs_error(LOG_ERR, "cannot convert type for dt %lld", a.attr); fs_decimal_init_from_int64(&a.de, 0); } a.attr = fs_c.xsd_decimal; } return a; } if (a.attr == fs_c.xsd_integer || b.attr == fs_c.xsd_integer) { if (a.attr != fs_c.xsd_integer) { if (a.valid & fs_valid_bit(FS_V_IN)) { a.attr = fs_c.xsd_integer; } else { fs_error(LOG_ERR, "cannot convert type for dt %lld", a.attr); a.in = 0; } } return a; } return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); }
fs_binding *fs_binding_apply_filters(fs_query *q, int block, fs_binding *b, raptor_sequence *constr) { fs_binding *ret = fs_binding_copy(b); if (!constr) { /* if there's no constriants then we don't need to do anything */ return ret; } for (int col=0; b[col].name; col++) { ret[col].vals->length = 0; } int length = fs_binding_length(b); fs_binding *restore = q->bt; q->bt = b; /* TODO should prefetch lexical vals here */ /* expressions that have been optimised out will be replaces with NULL, * so we have to be careful here */ /* --------------------------- */ /* PREFETCH should go here XXX */ /* --------------------------- */ for (int row=0; row<length; row++) { for (int c=0; c<raptor_sequence_size(constr); c++) { rasqal_expression *e = raptor_sequence_get_at(constr, c); if (!e) continue; fs_value v = fs_expression_eval(q, row, block, e); #ifdef DEBUG_FILTER rasqal_expression_print(e, stdout); printf(" -> "); fs_value_print(v); printf("\n"); #endif if (v.valid & fs_valid_bit(FS_V_TYPE_ERROR) && v.lex) { q->warnings = g_slist_prepend(q->warnings, v.lex); } fs_value result = fn_ebv(v); /* its EBV is not true, so we skip to the next one */ if (result.valid & fs_valid_bit(FS_V_TYPE_ERROR) || !result.in) { continue; } for (int col=0; b[col].name; col++) { if (b[col].bound) { fs_rid_vector_append(ret[col].vals, b[col].vals->data[row]); } } } } q->bt = restore; return ret; }
fs_value fn_datatype(fs_query *q, fs_value a) { #if 0 printf("datatype("); fs_value_print(a); printf(")\n"); #endif if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (a.valid & fs_valid_bit(FS_V_RID) && FS_IS_URI_BN(a.rid)) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } if (a.attr == FS_RID_NULL) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } if (FS_IS_LITERAL(a.attr) && a.attr != fs_c.empty) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } else { if (a.attr == fs_c.xsd_string || a.attr == fs_c.empty) { return fs_value_uri(XSD_STRING); } else if (a.attr == fs_c.xsd_double) { return fs_value_uri(XSD_DOUBLE); } else if (a.attr == fs_c.xsd_float) { return fs_value_uri(XSD_FLOAT); } else if (a.attr == fs_c.xsd_decimal) { return fs_value_uri(XSD_DECIMAL); } else if (a.attr == fs_c.xsd_integer) { return fs_value_uri(XSD_INTEGER); } else if (a.attr == fs_c.xsd_boolean) { return fs_value_uri(XSD_BOOLEAN); } else if (a.attr == fs_c.xsd_datetime) { return fs_value_uri(XSD_DATETIME); } } fs_rid_vector *r = fs_rid_vector_new(1); r->data[0] = a.attr; fs_resource res; if (fs_query_link(q)) { fsp_resolve(fs_query_link(q), FS_RID_SEGMENT(a.attr, fsp_link_segments(fs_query_link(q))), r, &res); fs_rid_vector_free(r); return fs_value_uri(res.lex); } return fs_value_uri("error:unresloved"); }
fs_value fn_is_blank(fs_query *q, fs_value a) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (a.valid & fs_valid_bit(FS_V_RID)) { if (a.rid == FS_RID_NULL) return fs_value_boolean(0); return fs_value_boolean(FS_IS_BNODE(a.rid)); } return fs_value_boolean(0); }
fs_value fn_is_iri(fs_query *q, fs_value a) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (a.valid & fs_valid_bit(FS_V_RID)) { return fs_value_boolean(FS_IS_URI(a.rid)); } if (a.attr == FS_RID_NULL) { return fs_value_boolean(1); } return fs_value_boolean(0); }
static int orow_compare_sub(const struct order_row *a, const struct order_row *b) { int mod = 0; for (int i=0; i<a->width; i++) { fs_value va = a->vals[i]; fs_value vb = b->vals[i]; if (va.valid & fs_valid_bit(FS_V_DESC)) { mod = -1; } else { mod = 1; } #ifdef DEBUG_ORDER fs_value_print(va); printf(" <=> "); fs_value_print(vb); #endif int order = fs_order_by_cmp(va, vb); if (order == 0) { continue; } return order * mod; } return 0; }
fs_value fn_lang_matches(fs_query *q, fs_value l, fs_value p) { if (fs_is_error(l)) { return l; } if (fs_is_error(p)) { return p; } if (l.valid & fs_valid_bit(FS_V_RID) && l.rid == FS_RID_NULL) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } if (l.lex && l.lex[0] == '\0') { return fs_value_boolean(0); } if (p.lex && p.lex[0] == '*' && p.lex[1] == '\0') { return fs_value_boolean(1); } if (l.lex && p.lex) { /* TODO implement RFC3066 */ return fs_value_boolean(!strncasecmp(l.lex, p.lex, strlen(p.lex))); } return fs_value_boolean(0); }
fs_value fn_not_equal(fs_query *q, fs_value a, fs_value b) { #if 0 fs_value_print(a); printf(" != "); fs_value_print(b); printf("\n"); #endif if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (b.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return b; } if (a.attr == fs_c.xsd_datetime) return fn_not(q, fn_datetime_equal(q, a, b)); if (fs_is_numeric(&a) && fs_is_numeric(&b)) return fn_not(q, fn_numeric_equal(q, a, b)); if ((a.attr == fs_c.empty || a.attr == fs_c.xsd_string) && (b.attr == fs_c.empty || b.attr == fs_c.xsd_string)) { return fs_value_boolean(strcmp(a.lex, b.lex)); } if ((FS_IS_URI_BN(a.rid) && FS_IS_LITERAL(b.rid)) || (FS_IS_LITERAL(a.rid) && FS_IS_URI_BN(b.rid))) { /* ones a URI/bNode and ones a literal, definatly different */ return fs_value_boolean(1); } if ((!FS_IS_URI(a.rid) && a.attr != fs_c.empty && FS_IS_LITERAL(a.attr) && !FS_IS_LITERAL(b.attr)) || (!FS_IS_URI(a.rid) && !FS_IS_LITERAL(a.attr) && b.attr != fs_c.empty && FS_IS_LITERAL(b.attr))) { /* one has a lang tag and one doesn't, definatly different */ return fs_value_boolean(1); } if (FS_IS_URI(a.attr) || FS_IS_URI(b.attr)) { /* at least one argument has an unknown datatype */ return fs_value_boolean(0); } return fn_not(q, fn_rdfterm_equal(q, a, b)); }
fs_value fn_greater_than(fs_query *q, fs_value a, fs_value b) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (b.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return b; } if (a.attr == fs_c.xsd_datetime && b.attr == fs_c.xsd_datetime) return fn_datetime_greater_than(q, a, b); if (fs_is_numeric(&a)) return fn_numeric_greater_than(q, a, b); if (a.lex && b.lex) return fn_numeric_equal(q, fn_compare(q, a, b), fs_value_integer(1)); return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); }
fs_value fs_value_error(fs_error e, const char *msg) { fs_value v = fs_value_blank(); v.valid = fs_valid_bit(FS_V_TYPE_ERROR); v.lex = (char *)msg; return v; }
int fs_is_error(fs_value a) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return 1; } return 0; }
fs_value fs_value_fill_rid(fs_query *q, fs_value a) { if (a.valid & fs_valid_bit(FS_V_RID)) { return a; } if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { a.rid = FS_RID_NULL; } fs_value_fill_lexical(q, a); a.rid = fs_hash_literal(a.lex, a.attr); a.valid |= fs_valid_bit(FS_V_RID); return a; }
static fs_value cast_boolean(fs_value a) { if (a.valid & fs_valid_bit(FS_V_IN)) { return a; } if (a.valid & fs_valid_bit(FS_V_FP)) { a.valid |= fs_valid_bit(FS_V_IN); a.in = a.fp; return a; } if (a.valid & fs_valid_bit(FS_V_DE)) { a.valid |= fs_valid_bit(FS_V_IN); fs_decimal_to_int64(&a.de, &a.in); return a; } if (a.lex) { if (!strcmp(a.lex, "true")) { a.valid |= fs_valid_bit(FS_V_IN); a.in = 1; return a; } else if (!strcmp(a.lex, "false")) { a.valid |= fs_valid_bit(FS_V_IN); a.in = 0; return a; } } return fs_value_error(FS_ERROR_INVALID_TYPE, "bad integer cast"); }
fs_value fs_value_integer(long long i) { fs_value v = fs_value_blank(); v.attr = fs_c.xsd_integer; v.valid = fs_valid_bit(FS_V_IN); v.in = i; return v; }
fs_value fs_value_datetime(time_t d) { fs_value v = fs_value_blank(); v.attr = fs_c.xsd_datetime; v.valid = fs_valid_bit(FS_V_IN); v.in = d; return v; }
fs_value fs_value_float(double f) { fs_value v = fs_value_blank(); v.attr = fs_c.xsd_float; v.valid = fs_valid_bit(FS_V_FP); v.fp = f; return v; }
fs_value fn_lang(fs_query *q, fs_value a) { if (a.valid & fs_valid_bit(FS_V_TYPE_ERROR)) { return a; } if (a.valid & fs_valid_bit(FS_V_RID) && FS_IS_URI_BN(a.rid)) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } if (a.attr == FS_RID_NULL) { return fs_value_error(FS_ERROR_INVALID_TYPE, NULL); } if (FS_IS_URI(a.attr)) { return fs_value_plain(""); } else { if (a.attr == fs_c.lang_en) { return fs_value_plain("en"); } else if (a.attr == fs_c.lang_fr) { return fs_value_plain("fr"); } else if (a.attr == fs_c.lang_de) { return fs_value_plain("de"); } else if (a.attr == fs_c.lang_es) { return fs_value_plain("es"); } else if (a.attr == fs_c.empty) { return fs_value_plain(""); } } fs_rid_vector *r = fs_rid_vector_new(1); r->data[0] = a.attr; fs_resource res; if (fs_query_link(q)) { fsp_resolve(fs_query_link(q), FS_RID_SEGMENT(a.attr, fsp_link_segments(fs_query_link(q))), r, &res); fs_rid_vector_free(r); fs_query_add_freeable(q, res.lex); return fs_value_plain(res.lex); } return fs_value_plain("???"); }
fs_value fs_value_decimal(double d) { fs_value v = fs_value_blank(); v.attr = fs_c.xsd_decimal; v.valid = fs_valid_bit(FS_V_DE); fs_decimal_init_from_double(&v.de, d); return v; }
fs_value fs_value_uri(const char *s) { fs_value v = fs_value_blank(); v.rid = fs_hash_uri(s); v.lex = (char *)s; v.valid = fs_valid_bit(FS_V_RID); v.attr = FS_RID_NULL; return v; }