View source with raw comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2010-2018, University of Amsterdam
    7                              VU University Amsterdam
    8    All rights reserved.
    9
   10    Redistribution and use in source and binary forms, with or without
   11    modification, are permitted provided that the following conditions
   12    are met:
   13
   14    1. Redistributions of source code must retain the above copyright
   15       notice, this list of conditions and the following disclaimer.
   16
   17    2. Redistributions in binary form must reproduce the above copyright
   18       notice, this list of conditions and the following disclaimer in
   19       the documentation and/or other materials provided with the
   20       distribution.
   21
   22    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   23    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   24    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   25    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   26    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   27    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   28    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   29    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   30    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   32    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   33    POSSIBILITY OF SUCH DAMAGE.
   34*/
   35
   36:- module(sparql_runtime,
   37          [ sparql_true/1,              % +Expression
   38            sparql_eval/2,              % +Expression, -Value
   39            sparql_eval_raw/2,          % +Expression, -Value
   40            sparql_simplify/2,          % :Goal, -SimpleGoal
   41            sparql_subquery/3,          % +Proj, +Query, +Sols
   42            sparql_update/1,            % +UpdateRequest
   43            sparql_find/5,              % ?From, ?To, ?F, ?T, :Q
   44            sparql_minus/2,             % :Pattern1, :Pattern2
   45            sparql_group/1,             % :Query
   46            sparql_group/3,             % :Query, +OuterVars, +InnerVars
   47            sparql_service/5,           % +Silent, +URL, +Prefixes, +Vars, +QText
   48            sparql_reset_bnodes/0
   49          ]).   50:- use_module(library(semweb/rdf_db)).   51:- use_module(library(semweb/rdf11), [rdf_lexical_form/2]).   52:- use_module(library(xsdp_types)).   53:- use_module(library(lists)).   54:- use_module(library(apply)).   55:- use_module(library(assoc)).   56:- use_module(library(ordsets)).   57:- use_module(library(uri)).   58:- use_module(library(dcg/basics)).   59:- use_module(library(semweb/sparql_client)).   60:- use_module(library(debug)).   61:- use_module(library(error)).   62:- if(exists_source(library(uuid))).   63:- use_module(library(uuid)).   64:- endif.   65
   66:- discontiguous
   67    term_expansion/2.   68
   69:- meta_predicate
   70    sparql_find(?, ?, ?, ?, 0),
   71    sparql_minus(0, 0),
   72    sparql_group(0),
   73    sparql_group(0, +, +),
   74    sparql_subquery(+, 0, +),
   75    sparql_update(:).

SPARQL runtime support

See also
- rdfql_runtime.pl merges this module with generic predicates as well as runtime libraries for other query languages.
- These routines are part of the entailment modules. See ../entailment/README.txt */
   85:- thread_local
   86    bnode_store/2.
 sparql_true(+Term)
Generated from FILTER Term, where Term must be converted to a boolean as 'Effective Boolean Value'.
   93sparql_true(Term) :-
   94    typed_eval(boolean, Term, Result),
   95    !,
   96    true(Result).
   97
   98true(boolean(true)).
 eval(+Term, -Result)
  102eval(Var, unbound(Var)) :-
  103    var(Var),
  104    !.
  105eval(literal(Literal), Result) :-
  106    !,
  107    eval_literal(Literal, Result).
  108eval(Atom, iri(Atom)) :-
  109    atom(Atom),
  110    !.
  111eval(built_in(Term), Result) :-
  112    !,
  113    op(Term, Result).
  114eval(Term, Result) :-
  115    sparql_op(Term),
  116    !,
  117    op(Term, Result).
  118eval(function(Term), Result) :-
  119    !,
  120    (   xsd_cast(Term, Type, Value0)
  121    ->  eval(Value0, Value),
  122        eval_cast(Type, Value, Result)
  123    ;   eval_function(Term, Result)
  124    ).
  125eval(Term, Term).                       % Result of sub-eval
 eval(+Type, +Term, -Result) is semidet
Evaluate Term, converting the resulting argument to Type.
  131typed_eval(no_eval, Term, Term).
  132typed_eval(any, Term, Result) :-
  133    eval(Term, Result).
  134typed_eval(simple_literal, Term, Result) :-
  135    eval(Term, Result).
  136typed_eval(boolean, Term, Result) :-
  137    eval(Term, Result0),
  138    effective_boolean_value(Result0, Result).
  139typed_eval(numeric, Term, Result) :-
  140    eval(Term, Result),
  141    Result = numeric(_,_).
  142
  143
  144eval_literal(type(Type, Atom), Value) :-
  145    !,
  146    eval_typed_literal(Type, Atom, Value).
  147eval_literal(lang(Lang, Atom), lang(Lang, Atom)) :- !.
  148eval_literal(Atom, simple_literal(Atom)) :-
  149    atom(Atom),
  150    !.
  151
  152eval_typed_literal(Type, Atom, numeric(Type, Value)) :-
  153    xsdp_numeric_uri(Type, Generic),
  154    !,
  155    numeric_literal_value(Generic, Atom, Value).
  156eval_typed_literal(Type, Atom, Value) :-
  157    eval_known_typed_literal(Type, Atom, Value0),
  158    !,
  159    Value = Value0.
  160eval_typed_literal(Type, Atom, type(Type, Atom)).
 eval_known_typed_literal(+Type, +Plain, -Typed) is semidet
Map known datatypes to a value that is suitable for comparison using Prolog standard order of terms. Note that the mapped time representations can all be compared.
  168:- rdf_meta eval_known_typed_literal(r, +, t).  169
  170eval_known_typed_literal(xsd:boolean,    Atom, boolean(Atom)).
  171eval_known_typed_literal(xsd:string,     Atom, string(Atom)).
  172eval_known_typed_literal(xsd:gYear,      Atom, time(xsd:gYear, Atom)).
  173eval_known_typed_literal(xsd:gYearMonth, Atom, time(xsd:gYearMonth, Atom)).
  174eval_known_typed_literal(xsd:date,       Atom, time(xsd:date, Atom)).
  175eval_known_typed_literal(xsd:dateTime,   Atom, time(xsd:dateTime, Atom)).
 numeric_literal_value(+Literal, -Value) is semidet
Convert a SPARQL numeric literal into its value for the purpose of comparison-by-value.
To be done
- Move this into the rdf_db library. There we can achieve better performance and we can do more efficient matching.
  186numeric_literal_value(Type, Text, Value) :-
  187    rdf_equal(Type, xsd:integer),
  188    !,
  189    atom(Text),
  190    atom_number(Text, Value),
  191    integer(Value).
  192numeric_literal_value(Type, Text, Value) :-
  193    rdf_equal(Type, xsd:decimal),
  194    !,
  195    atom(Text),
  196    atom_number(Text, Value).
  197numeric_literal_value(_, Text, Value) :-
  198    atom(Text),
  199    atom_number(Text, Value),
  200    !.
  201numeric_literal_value(_, Text, Value) :-
  202    catch(rdf_text_to_float(Text, Value), _, fail).
  203
  204rdf_text_to_float(Text, Value) :-
  205    atom_codes(Text, Codes),
  206    optional_sign(Codes, Rest, Sign),
  207    (   Rest = [0'.|_]
  208    ->  number_codes(NonnegValue, [0'0|Rest])
  209    ;   last(Rest, 0'.)
  210    ->  append(Rest, [0'0], NonnegCodes),
  211        number_codes(NonnegCodes, NonnegValue)
  212    ),
  213    Value is NonnegValue*Sign.
  214
  215optional_sign([0'+|Rest], Rest, 1) :- !.
  216optional_sign([0'-|Rest], Rest, -1) :- !.
  217optional_sign(Rest, Rest, 1).
  218
  219
  220%       Evaluation of function arguments
  221
  222eval_any(Term, Value) :-
  223    eval(Term, Value),
  224    !.
  225eval_any(_, boolean(error)).
  226
  227eval_boolean(Term, Bool) :-
  228    eval(Term, Value),
  229    effective_boolean_value(Value, Bool),
  230    !.
  231eval_boolean(_, boolean(error)).
  232
  233eval_numeric(Term, Numeric) :-
  234    eval(Term, Numeric),
  235    Numeric = numeric(_,_),
  236    !.
  237eval_numeric(_, boolean(error)).
 sparql_op(+ListOfDelcs)
  241term_expansion((:- sparql_op(Decls)), Clauses) :-
  242    maplist(decl_op, Decls, Clauses).
  243
  244decl_op(Term, op_decl(Gen, Args)) :-
  245    functor(Term, Name, Arity),
  246    functor(Gen,  Name, Arity),
  247    Term =.. [Name|Args].
 expand_op(+In, -Clause) is det
Expand SPARQL operators into a nice clause.
  254expand_op((op(Op,Result) :- Body),
  255          [(op(Op1,Result) :- Body1), sparql_op(Op1)]) :-
  256    rdf_global_term(Op, Op0),
  257    functor(Op0, Name, Arity),
  258    functor(Op1, Name, Arity),
  259    (   op_decl(Op1, Types)
  260    ->  true
  261    ;   Op0 =.. [Name|Args],
  262        maplist(op_arg_type, Args, Types)
  263    ),
  264    Op0 =.. [Name|Args0],
  265    Op1 =.. [Name|Args1],
  266    maplist(convert_goal, Types, Args1, Args0, ConvertList),
  267    list_to_conj(ConvertList, Convert),
  268    mkconj(Convert, Body, Body1).
  269
  270op_arg_type(Var,               any) :- var(Var), !.
  271op_arg_type(boolean(_),        boolean) :- !.
  272op_arg_type(numeric(_,_),      numeric) :- !.
  273op_arg_type(simple_literal(_), simple_literal) :- !.
  274op_arg_type(_,                 any).
  275
  276list_to_conj([], true).
  277list_to_conj([G], G) :- !.
  278list_to_conj([H|T], G) :-
  279    list_to_conj(T, G1),
  280    mkconj(H, G1, G).
  281
  282mkconj(true, G, G) :- !.
  283mkconj(G, true, G) :- !.
  284mkconj(G1,G2,(G1,G2)).
  285
  286convert_goal(no_eval, Arg, Arg, true).
  287convert_goal(any, Arg0, Arg1, eval_any(Arg0, Arg1)).
  288convert_goal(simple_literal, Arg0, Arg1, eval_any(Arg0, Arg1)).
  289convert_goal(boolean, Arg0, Arg1, eval_boolean(Arg0, Arg1)).
  290convert_goal(numeric, Arg0, Arg1, eval_numeric(Arg0, Arg1)).
  291
  292term_expansion((op(Op,Result) :- Body), Clauses) :-
  293    expand_op((op(Op,Result) :- Body), Clauses).
  294term_expansion((op(Op,Result)), Clauses) :-
  295    expand_op((op(Op,Result) :- true), Clauses).
 op(+Operator, -Result) is semidet
Arguments:
Operator- Term of the format Op(Arg...) where each Arg is embedded in its type.
Result- Result-value, embedded in its type.
  303:- rdf_meta op(t,t).  304:- discontiguous op/2, op_decl/2, sparql_op/1.  305
  306:- sparql_op([ bound(no_eval)
  307             ]).  308
  309% SPARQL Unary operators
  310op(not(boolean(X)), boolean(Result)) :-
  311    not(X, Result).
  312op(+(numeric(Type, X)), numeric(Type, X)).
  313op(-(numeric(Type, X)), numeric(Type, Result)) :-
  314    Result is -X.
  315
  316% SPARQL Tests, defined in section 11.4
  317op(bound(X), boolean(Result)) :-
  318    (bound(X) -> Result = true ; Result = false).
  319op(isiri(X), boolean(Result)) :-
  320    (isiri(X) -> Result = true ; Result = false).
  321op(isuri(X), boolean(Result)) :-
  322    (isiri(X) -> Result = true ; Result = false).
  323op(isblank(X), boolean(Result)) :-
  324    (isblank(X) -> Result = true ; Result = false).
  325op(isliteral(X), boolean(Result)) :-
  326    (isliteral(X) -> Result = true ; Result = false).
  327
  328:- sparql_op([ iri(any, no_eval),
  329               str(no_eval)
  330             ]).  331
  332% SPARQL Accessors
  333op(str(X), simple_literal(Str)) :-
  334    str(X, Str).
  335op(lang(X), simple_literal(Lang)) :-
  336    lang(X, Lang).
  337op(datatype(X), Type) :-
  338    datatype(X, Type).
  339op(strdt(simple_literal(Lex), iri(Type)), type(Type, Lex)).
  340op(strlang(simple_literal(Lex), simple_literal(Lang)), lang(Lang, Lex)).
  341:- if(current_predicate(uuid/1)).  342op(uuid, iri(URNUUID)) :-
  343    uuid(UUID),
  344    atom_concat('urn:uuid:', UUID, URNUUID).
  345op(struuid, simple_literal(UUID)) :-
  346    uuid(UUID).
  347:- endif.  348op(bnode, iri(Id)) :-
  349    rdf_bnode(Id).
  350op(bnode(simple_literal(Id)), iri(BNode)) :-
  351    id_to_bnode(Id, BNode).
  352op(iri(Spec, Base), iri(URI)) :-
  353    iri(Spec, Base, URI).
  354
  355% SPARQL Binary operators
  356% Logical connectives, defined in section 11.4
  357op(and(boolean(A), boolean(B)), boolean(Result)) :-
  358    sparql_and(A, B, Result).
  359op(or(boolean(A), boolean(B)), boolean(Result)) :-
  360    sparql_or(A, B, Result).
  361
  362:- sparql_op([ coalesce(no_eval)
  363             ]).  364
  365% SPARQL functional forms
  366op(if(Test, V1, V2), Result) :-
  367    typed_eval(boolean, Test, TestResult),
  368    (   TestResult == boolean(true)
  369    ->  eval(V1, Result)
  370    ;   TestResult == boolean(false)
  371    ->  eval(V2, Result)
  372    ).
  373op(coalesce(List), Result) :-
  374    member(Expr, List),
  375    ground(Expr),
  376    eval(Expr, Result),
  377    \+ invalid(Result),
  378    !.
  379
  380invalid('$null$').
  381invalid(boolean(error)).
  382
  383% XPath Tests
  384op(X = Y, boolean(Result)) :-
  385    (   equal(X, Y)
  386    ->  Result = true
  387    ;   Result = false
  388    ).
  389op(X \= Y, boolean(Result)) :-
  390    (   equal(X, Y)
  391    ->  Result = false
  392    ;   Result = true
  393    ).
  394
  395equal(X, X) :- !.
  396equal(numeric(_, X), numeric(_, Y)) :- X =:= Y.
  397equal(boolean(A), boolean(B)) :-
  398    eq_bool(A, B, true).
  399
  400op(X < Y, boolean(Result)) :-
  401    (   lt(X,Y)
  402    ->  Result = true
  403    ;   functor(X, Name, Arity),
  404        functor(Y, Name, Arity)
  405    ->  Result = false
  406    ).
  407op(X > Y, boolean(Result)) :-
  408    (   gt(X,Y)
  409    ->  Result = true
  410    ;   functor(X, Name, Arity),
  411        functor(Y, Name, Arity)
  412    ->  Result = false
  413    ).
  414op(X =< Y, boolean(Result)) :-
  415    (   leq(X,Y)
  416    ->  Result = true
  417    ;   functor(X, Name, Arity),
  418        functor(Y, Name, Arity)
  419    ->  Result = false
  420    ).
  421op(X >= Y, boolean(Result)) :-
  422    (   geq(X,Y)
  423    ->  Result = true
  424    ;   functor(X, Name, Arity),
  425        functor(Y, Name, Arity)
  426    ->  Result = false
  427    ).
  428
  429lt(numeric(_, X), numeric(_, Y)) :- X < Y.
  430lt(simple_literal(X), simple_literal(Y)) :- X @< Y.
  431lt(string(X), string(Y)) :- X @< Y.
  432lt(time(T, X), time(T, Y)) :- X @< Y.
  433lt(type(T, X), type(T, Y)) :- X @< Y.
  434
  435gt(numeric(_, X), numeric(_, Y)) :- X > Y.
  436gt(simple_literal(X), simple_literal(Y)) :- X @> Y.
  437gt(string(X), string(Y)) :- X @> Y.
  438gt(time(T, X), time(T, Y)) :- X @> Y.
  439gt(type(T, X), type(T, Y)) :- X @> Y.
  440
  441leq(numeric(_, X), numeric(_, Y)) :- X =< Y.
  442leq(simple_literal(X), simple_literal(Y)) :- X @=< Y.
  443leq(string(X), string(Y)) :- X @=< Y.
  444leq(time(T, X), time(T, Y)) :- X @=< Y.
  445leq(type(T, X), type(T, Y)) :- X @=< Y.
  446
  447geq(numeric(_, X), numeric(_, Y)) :- X >= Y.
  448geq(simple_literal(X), simple_literal(Y)) :- X @>= Y.
  449geq(string(X), string(Y)) :- X @>= Y.
  450geq(time(T, X), time(T, Y)) :- X @>= Y.
  451geq(type(T, X), type(T, Y)) :- X @>= Y.
  452
  453% arithmetic
  454op(numeric(TX, X) * numeric(TY, Y), numeric(Type, Result)) :-
  455    Result is X * Y,
  456    combine_types(TX, TY, Type).
  457op(numeric(TX, X) / numeric(TY, Y), numeric(Type, Result)) :-
  458    Y =\= 0,
  459    Result is X / Y,
  460    combine_types_div(TX, TY, Type).
  461op(numeric(TX, X) + numeric(TY, Y), numeric(Type, Result)) :-
  462    Result is X + Y,
  463    combine_types(TX, TY, Type).
  464op(numeric(TX, X) - numeric(TY, Y), numeric(Type, Result)) :-
  465    Result is X - Y,
  466    combine_types(TX, TY, Type).
  467% arithmetic to support aggregates
  468op(min(numeric(TX, X), numeric(TY, Y)), numeric(Type, Result)) :-
  469    (   X < Y
  470    ->  Type = TX, Result = X
  471    ;   X > Y
  472    ->  Type = TY, Result = Y
  473    ;   combine_types(TX, TY, Type),
  474        (   Type == TX
  475        ->  Result = X
  476        ;   Result = Y
  477        )
  478    ).
  479op(max(numeric(TX, X), numeric(TY, Y)), numeric(Type, Result)) :-
  480    (   X > Y
  481    ->  Type = TX, Result = X
  482    ;   X < Y
  483    ->  Type = TY, Result = Y
  484    ;   combine_types(TX, TY, Type),
  485        (   Type == TX
  486        ->  Result = X
  487        ;   Result = Y
  488        )
  489    ).
  490
  491% SPARQL Tests, defined in section 11.4
  492
  493op(in(Value, List), boolean(Result)) :-
  494    sparql_in(Value, List, Result).
  495op(not_in(Value, List), boolean(Result)) :-
  496    sparql_in(Value, List, R0),
  497    not(R0, Result).
  498
  499sparql_in(Value, List, Result) :-
  500    (   memberchk(Value, List)
  501    ->  Result = true
  502    ;   member(E, List),
  503        eval(E, EV),
  504        rdf_equal(Value, EV)
  505    ->  Result = true
  506    ;   Result = false
  507    ).
  508
  509
  510% SPARQL builtin string functions (1.1)
  511
  512:- sparql_op([ strlen(any),
  513               substr(any, numeric),
  514               substr(any, numeric, numeric),
  515               ucase(any),
  516               lcase(any),
  517               strstarts(any, any),
  518               strends(any, any),
  519               contains(any, any),
  520               strbefore(any, any),
  521               strafter(any, any),
  522               encode_for_uri(any),
  523               concat(no_eval)
  524             ]).  525
  526op(strlen(A), numeric(xsd:integer, Len)) :-
  527    string_op(A, Len, strlen).
  528op(substr(A, numeric(xsd:integer, Start)), R) :-
  529    string_int_op_string(A, Start, R, substr).
  530op(substr(A, numeric(xsd:integer, Start), numeric(xsd:integer, Len)), R) :-
  531    string_int_int_op_string(A, Start, Len, R, substr).
  532op(ucase(A), U) :-
  533    string_op_string(A, U, ucase).
  534op(lcase(A), U) :-
  535    string_op_string(A, U, lcase).
  536op(strstarts(String, Starts), boolean(True)) :-
  537    argument_compatible(String, Starts, True, strstarts).
  538op(strends(String, Starts), boolean(True)) :-
  539    argument_compatible(String, Starts, True, strends).
  540op(contains(String, Starts), boolean(True)) :-
  541    argument_compatible(String, Starts, True, contains).
  542op(strbefore(A1, A2), R) :-
  543    string_string_op(A1, A2, R, strbefore).
  544op(strafter(A1, A2), R) :-
  545    string_string_op(A1, A2, R, strafter).
  546op(encode_for_uri(S), simple_literal(URI)) :-
  547    str_value(S, Text),
  548    uri_encoded(path, Text, IRI),
  549    uri_iri(URI, IRI).
  550op(concat(List), R) :-
  551    maplist(eval, List, Evaluated),
  552    maplist(str_text, Evaluated, StrList),
  553    atomic_list_concat(StrList, Lex),
  554    (   maplist(is_string, Evaluated)
  555    ->  R = string(Lex)
  556    ;   maplist(is_lang(L), Evaluated)
  557    ->  R = lang(L, Lex)
  558    ;   R = simple_literal(Lex)
  559    ).
  560op(langmatches(simple_literal(Lang),
  561               simple_literal(Pat)),
  562   boolean(Result)) :-
  563    (lang_matches(Lang, Pat) -> Result = true ; Result = false).
  564op(regex(A, simple_literal(Pat)), boolean(Result)) :-
  565    string_op(A, Result, regex(Pat, '')).
  566op(regex(A, simple_literal(Pat), simple_literal(Flags)), boolean(Result)) :-
  567    string_op(A, Result, regex(Pat, Flags)).
  568op(compiled_regex(Regex, A), boolean(Result)) :-
  569    string_op(A, Result, compiled_regex(Regex)).
  570op(replace(simple_literal(Input),
  571           simple_literal(Pattern),
  572           simple_literal(Replace),
  573           simple_literal(Flags)),
  574   simple_literal(Result)) :-
  575    regex_replace(Input, Pattern, Replace, Flags, Result).
  576op(replace(string(Input),
  577           simple_literal(Pattern),
  578           simple_literal(Replace),
  579           simple_literal(Flags)),
  580   string(Result)) :-
  581    regex_replace(Input, Pattern, Replace, Flags, Result).
  582op(replace(lang(Lang, Input),
  583           simple_literal(Pattern),
  584           simple_literal(Replace),
  585           simple_literal(Flags)),
  586   lang(Lang, Result)) :-
  587    regex_replace(Input, Pattern, Replace, Flags, Result).
  588
  589% SPARQL builtin numeric functions (1.1, 17.4.4)
  590
  591:- sparql_op([ isnumeric(any)
  592             ]).  593
  594op(isnumeric(A), boolean(True)) :-
  595    ( A = numeric(_,_) ->  True = true ; True = false ).
  596op(abs(numeric(T, A1)), numeric(T, R)) :-
  597    R is abs(A1).
  598op(round(numeric(T, A1)), numeric(T, R)) :-
  599    R is round(A1).
  600op(ceil(numeric(T, A1)), numeric(T, R)) :-
  601    R is ceil(A1).
  602op(floor(numeric(T, A1)), numeric(T, R)) :-
  603    R is floor(A1).
  604op(rand, numeric(xsd:double, R)) :-
  605    R is random_float.
  606
  607% SPARQL builtin date and time functions (1.1, 17.4.5)
  608
  609op(now, time(xsd:dateTime, Date)) :-
  610    get_time(Now),
  611    format_time(atom(Date), '%FT%T.%3f%:z', Now).
  612op(year(time(Type, DateTime)), numeric(xsd:integer, Year)) :-
  613    time_part(year, Type, DateTime, Year).
  614op(month(time(Type, DateTime)), numeric(xsd:integer, Month)) :-
  615    time_part(month, Type, DateTime, Month).
  616op(day(time(Type, DateTime)), numeric(xsd:integer, Day)) :-
  617    time_part(day, Type, DateTime, Day).
  618op(hours(time(Type, DateTime)), numeric(xsd:integer, Hours)) :-
  619    time_part(hours, Type, DateTime, Hours).
  620op(minutes(time(Type, DateTime)), numeric(xsd:integer, Minutes)) :-
  621    time_part(minutes, Type, DateTime, Minutes).
  622op(seconds(time(Type, DateTime)), numeric(xsd:decimal, Seconds)) :-
  623    time_part(seconds, Type, DateTime, Seconds).
  624op(timezone(time(Type, DateTime)), type(xsd:dayTimeDuration, Timezone)) :-
  625    time_part(tzs, Type, DateTime, TZs),
  626    phrase(tz_offset(TZOffset), TZs),
  627    xsd_duration_seconds(Timezone, TZOffset).
  628op(tz(time(Type, DateTime)), simple_literal(TZ)) :-
  629    time_part(tz, Type, DateTime, TZ).
  630
  631% SPARQL builtin hash functions (1.1, 17.4.6)
  632
  633:- sparql_op([ md5(any),
  634               sha1(any),
  635               sha256(any),
  636               sha384(any),
  637               sha512(any)
  638             ]).  639
  640op(md5(String), simple_literal(Hash)) :-
  641    string_hash(String, Hash, md5).
  642op(sha1(String), simple_literal(Hash)) :-
  643    string_hash(String, Hash, sha1).
  644op(sha256(String), simple_literal(Hash)) :-
  645    string_hash(String, Hash, sha256).
  646op(sha384(String), simple_literal(Hash)) :-
  647    string_hash(String, Hash, sha384).
  648op(sha512(String), simple_literal(Hash)) :-
  649    string_hash(String, Hash, sha512).
  650
  651
  652                 /*******************************
  653                 *   HASH SUPPORT FUNCTIONS     *
  654                 *******************************/
  655
  656string_hash(simple_literal(S), Hash, Algorithm) :-
  657    atom_hash(Algorithm, S, Hash).
  658string_hash(string(S), Hash, Algorithm) :-
  659    atom_hash(Algorithm, S, Hash).
  660
  661atom_hash(md5, S, Hash) :-
  662    !,
  663    rdf_atom_md5(S, 1, Hash).
  664atom_hash(SHA, S, Hash) :-
  665    sha_hash(S, HashCodes,
  666             [ algorithm(SHA),
  667               encoding(utf8)
  668             ]),
  669    hash_atom(HashCodes, Hash).
  670
  671
  672                 /*******************************
  673                 *    TIME SUPPORT FUNCTIONS    *
  674                 *******************************/
 time_part(+Part, +Type, +String, -Value) is semidet
  678:- if(current_predicate(sub_string/5)).  679time_part(year, _Type, String, Value) :-
  680    !,
  681    sub_string(String, 0, 4, _, Digits),
  682    number_string(Value, Digits).
  683time_part(month, _Type, String, Value) :-
  684    !,
  685    sub_string(String, 5, 2, _, Digits),
  686    number_string(Value, Digits).
  687time_part(day, _Type, String, Value) :-
  688    !,
  689    sub_string(String, 8, 2, _, Digits),
  690    number_string(Value, Digits).
  691:- endif.  692time_part(Part, _Type, DateTime, Value) :-
  693    atom_codes(DateTime, Codes),
  694    phrase(time_dcg(Part, Value), Codes, _).
  695
  696time_dcg(year,  Year)  --> digits4(Year).
  697time_dcg(month, Month) --> time_dcg(year, _),    "-", digits2(Month).
  698time_dcg(day,   Day)   --> time_dcg(month, _),   "-", digits2(Day).
  699time_dcg(hours, Hours) --> time_dcg(day, _),     "T", digits2(Hours).
  700time_dcg(minutes, Min) --> time_dcg(hours, _),   ":", digits2(Min).
  701time_dcg(seconds, Sec) --> time_dcg(minutes, _), ":", number(Sec).
  702time_dcg(tzs,     TZs) --> time_dcg(seconds, _),      string_without("", TZs).
  703time_dcg(tz,      TZ)  --> time_dcg(tzs, TZs), { atom_codes(TZ, TZs) }.
  704
  705tz_offset(TZOffset) -->
  706    "Z", !, { TZOffset = 0 }.
  707tz_offset(TZOffset) -->
  708    "+", digits2(Hours), ":", digits2(Minutes),
  709    { TZOffset is Hours*3600+Minutes*60 }.
  710tz_offset(TZOffset) -->
  711    "-", digits2(Hours), ":", digits2(Minutes),
  712    { TZOffset is -(Hours*3600+Minutes*60) }.
 seconds_xsd_duration(+Seconds, -XSDDuration)
See also
- http://docs.oracle.com/cd/E13214_01/wli/docs92/xref/xqdurfunc.html#wp1183764
To be done
- Implement other direction and move this to XSD or datetime library.
  720xsd_duration_seconds(XSDDuration, Secs) :-
  721    var(XSDDuration),
  722    !,
  723    must_be(number, Secs),
  724    phrase(xsd_duration(Secs), Codes),
  725    atom_codes(XSDDuration, Codes).
  726
  727xsd_duration(Secs) -->
  728    { Secs < 0, !, PosSecs is -Secs },
  729    "-",
  730    xsd_duration(PosSecs).
  731xsd_duration(Secs) -->
  732    { Secs =:= 0 },
  733    !,
  734    "PT0S".
  735xsd_duration(Secs) -->
  736    "P",
  737    xsd_duration_days(Secs, Rem),
  738    xsd_duration_time(Rem).
  739
  740xsd_duration_days(Secs, Rem) -->
  741    { Days is Secs // (24*3600),
  742      Days > 0,
  743      !,
  744      Rem is Secs - Days*24*3600
  745    },
  746    integer(Days),
  747    "D".
  748xsd_duration_days(Secs, Secs) --> "".
  749
  750xsd_duration_time(Secs) -->
  751    { Secs =:= 0 },
  752    !.
  753xsd_duration_time(Secs) -->
  754    "T",
  755    xsd_duration_hours(Secs, S1),
  756    xsd_duration_minutes(S1, S2),
  757    xsd_duration_seconds(S2).
  758
  759xsd_duration_hours(Secs, Rem) -->
  760    { Hours is Secs // 3600,
  761      Hours > 0,
  762      !,
  763      Rem is Secs - Hours*3600
  764    },
  765    integer(Hours),
  766    "H".
  767xsd_duration_hours(Secs, Secs) --> "".
  768
  769xsd_duration_minutes(Secs, Rem) -->
  770    { Min is Secs // 60,
  771      Min > 0,
  772      !,
  773      Rem is Secs - Min*60
  774    },
  775    integer(Min),
  776    "M".
  777xsd_duration_minutes(Secs, Secs) --> "".
  778
  779xsd_duration_seconds(Secs) -->
  780    { Secs =:= 0 },
  781    !.
  782xsd_duration_seconds(Secs) -->
  783    number(Secs),
  784    "S".
  785
  786
  787digits4(Value) -->
  788    digit(D1),digit(D2),digit(D3),digit(D4),
  789    { number_codes(Value, [D1,D2,D3,D4]) }.
  790digits2(Value) -->
  791    digit(D1),digit(D2),
  792    { number_codes(Value, [D1,D2]) }.
  793
  794
  795                 /*******************************
  796                 *  STRING SUPPORT PRIMITIVES   *
  797                 *******************************/
  798
  799is_string(string(_)).
  800is_lang(L, lang(L,_)).
 string_op1(+A1, -R, +Op)
  804string_op(simple_literal(A), R, Op) :-
  805    atom_op(Op, A, R).
  806string_op(lang(_, A), R, Op) :-
  807    atom_op(Op, A, R).
  808string_op(string(A), R, Op) :-
  809    atom_op(Op, A, R).
 string_op_string(+A, -R)
  813string_op_string(simple_literal(A), simple_literal(R), Op) :-
  814    atom_op(Op, A, R).
  815string_op_string(lang(L,A), lang(L,R), Op) :-
  816    atom_op(Op, A, R).
  817string_op_string(string(A), string(R), Op) :-
  818    atom_op(Op, A, R).
 string_int_op_string(+S0, +I, -S)
  822string_int_op_string(simple_literal(S0), I, simple_literal(S), Op) :-
  823    atom_op(Op, S0, I, S).
  824string_int_op_string(lang(L, S0), I, lang(L, S), Op) :-
  825    atom_op(Op, S0, I, S).
  826string_int_op_string(string(S0), I, string(S), Op) :-
  827    atom_op(Op, S0, I, S).
 string_int_int_op_string(+S0, +I, -S)
  831string_int_int_op_string(simple_literal(S0), I1, I2, simple_literal(S), Op) :-
  832    atom_op(Op, S0, I1, I2, S).
  833string_int_int_op_string(lang(L, S0), I1, I2, lang(L, S), Op) :-
  834    atom_op(Op, S0, I1, I2, S).
  835string_int_int_op_string(string(S0), I1, I2, string(S), Op) :-
  836    atom_op(Op, S0, I1, I2, S).
 string_op2(+A1, +A2, -R, +Op)
Define operations on strings.
  842string_string_op(simple_literal(A1), simple_literal(A2), Result, Op) :-
  843    (   atom_op(Op, A1, A2, R)
  844    ->  Result = simple_literal(R)
  845    ;   Result = simple_literal('')
  846    ).
  847string_string_op(simple_literal(A1), string(A2), Result, Op) :-
  848    (   atom_op(Op, A1, A2, R)
  849    ->  Result = simple_literal(R)
  850    ;   Result = simple_literal('')
  851    ).
  852string_string_op(string(A1), simple_literal(A2), Result, Op) :-
  853    (   atom_op(Op, A1, A2, R)
  854    ->  Result = string(R)
  855    ;   Result = simple_literal('')
  856    ).
  857string_string_op(string(A1), string(A2), Result, Op) :-
  858    (   atom_op(Op, A1, A2, R)
  859    ->  Result = string(R)
  860    ;   Result = simple_literal('')
  861    ).
  862string_string_op(lang(L, A1), lang(L, A2), Result, Op) :-
  863    (   atom_op(Op, A1, A2, R)
  864    ->  Result = lang(L, R)
  865    ;   Result = simple_literal('')
  866    ).
  867string_string_op(lang(L, A1), string(A2), Result, Op) :-
  868    (   atom_op(Op, A1, A2, R)
  869    ->  Result = lang(L, R)
  870    ;   Result = simple_literal('')
  871    ).
  872string_string_op(lang(L, A1), simple_literal(A2), Result, Op) :-
  873    (   atom_op(Op, A1, A2, R)
  874    ->  Result = lang(L, R)
  875    ;   Result = simple_literal('')
  876    ).
 iri(+Spec, +Base, -IRI)
  880iri(simple_literal(URI0), Base, URI) :-
  881    !,
  882    uri_normalized(URI0, Base, URI).
  883iri(string(URI0), Base, URI) :-
  884    uri_normalized(URI0, Base, URI).
  885iri(iri(URI), _, URI).
 argument_compatible(+A1, +A2, -Bool, +Op)
  889argument_compatible(simple_literal(A1), simple_literal(A2), Bool, Op) :-
  890    !,
  891    arg_compatible(Op, A1, A2, Bool).
  892argument_compatible(simple_literal(A1), string(A2), Bool, Op) :-
  893    !,
  894    arg_compatible(Op, A1, A2, Bool).
  895argument_compatible(string(A1), simple_literal(A2), Bool, Op) :-
  896    !,
  897    arg_compatible(Op, A1, A2, Bool).
  898argument_compatible(string(A1), string(A2), Bool, Op) :-
  899    !,
  900    arg_compatible(Op, A1, A2, Bool).
  901argument_compatible(lang(L,A1), lang(L,A2), Bool, Op) :-
  902    !,
  903    arg_compatible(Op, A1, A2, Bool).
  904argument_compatible(lang(_,A1), simple_literal(A2), Bool, Op) :-
  905    !,
  906    arg_compatible(Op, A1, A2, Bool).
  907argument_compatible(lang(_,A1), string(A2), Bool, Op) :-
  908    !,
  909    arg_compatible(Op, A1, A2, Bool).
  910argument_compatible(_, _, boolean(error), _).
  911
  912arg_compatible(Op, A1, A2, Bool) :-
  913    (   arg_compatible(Op, A1, A2)
  914    ->  Bool = true
  915    ;   Bool = false
  916    ).
  917
  918arg_compatible(strstarts, A1, A2) :- sub_atom(A1, 0, _, _, A2).
  919arg_compatible(strends,   A1, A2) :- sub_atom(A1, _, _, 0, A2).
  920arg_compatible(contains,  A1, A2) :- sub_atom(A1, _, _, _, A2), !.
 atom_op(+Op, +Atom, -Result)
  925atom_op(strlen, A, Len) :-
  926    atom_length(A, Len).
  927atom_op(ucase, A, U) :-
  928    upcase_atom(A, U).
  929atom_op(lcase, A, U) :-
  930    downcase_atom(A, U).
  931atom_op(compiled_regex(Regex), Data, Matches) :-
  932    (   compiled_regex(Regex, Data)
  933    ->  Matches = true
  934    ;   Matches = false
  935    ).
  936atom_op(regex(Pat, Flags), Data, Matches) :-
  937    (   regex(Data, Pat, Flags)
  938    ->  Matches = true
  939    ;   Matches = false
  940    ).
 atom_op(+Op, +Atom, +Arg, -Result)
  944atom_op(substr, Atom, Start, Sub) :-
  945    S is Start - 1,
  946    (   sub_atom(Atom, S, _, 0, Sub0)
  947    ->  Sub = Sub0
  948    ;   Sub = ''                    % is this ok?
  949    ).
  950atom_op(strbefore, Atom, Search, Before) :-
  951    (   Search == ''
  952    ->  Before = ''
  953    ;   sub_atom(Atom, BL, _, _, Search)
  954    ->  sub_atom(Atom, 0, BL, _, Before)
  955    ).
  956atom_op(strafter, Atom, Search, After) :-
  957    (   sub_atom(Atom, _, _, AL, Search)
  958    ->  sub_atom(Atom, _, AL, 0, After)
  959    ).
 atom_op(+Op, +Atom, +A1, +A2, -Result)
  963atom_op(substr, Atom, Start, Len, Sub) :-
  964    S is Start - 1,
  965    (   sub_atom(Atom, S, Len, _, Sub0)
  966    ->  Sub = Sub0
  967    ;   sub_atom(Atom, S, _, 0, Sub0)
  968    ->  Sub = Sub0
  969    ;   Sub = ''                    % is this ok?
  970    ).
  971
  972
  973%       Numeric types follows the Xpath definitions of
  974%       http://www.w3.org/TR/xpath-functions/#numeric-functions
  975%       TBD:
 combine_types_div(+TypeLeft, +TypeRight, -Type)
  979combine_types_div(TX, TY, T) :-
  980    rdf_equal(xsd:integer, IntType),
  981    xsdp_numeric_uri(TX, IntType),
  982    xsdp_numeric_uri(TY, IntType),
  983    !,
  984    rdf_equal(xsd:decimal, T).
  985combine_types_div(TX, TY, T) :-
  986    combine_types(TX, TY, T).
 combine_types(+TypeLeft, +TypeRight, -Type)
  990%combine_types(T, T, T) :- !.
  991combine_types(TL, TR, T) :-
  992    xsdp_numeric_uri(TL, STL),
  993    xsdp_numeric_uri(TR, STR),
  994    promote_types(STL, STR, T).
  995
  996promote_types(TL, TR, T) :-
  997    type_index(TL, IL),
  998    type_index(TR, IR),
  999    TI is max(IL, IR),
 1000    type_index(T, TI),
 1001    !.
 1002
 1003term_expansion(type_index(NS:Local, I), type_index(URI, I)) :-
 1004    rdf_global_id(NS:Local, URI).
 1005
 1006type_index(xsd:integer, 1).
 1007type_index(xsd:decimal, 2).
 1008type_index(xsd:float,   3).
 1009type_index(xsd:double,  4).
 rdf_equal(+RDFTerm, +RDFTerm, -Boolean)
RDF Term equivalence. Described as lexical equivalence, except where we have the logic to do value equivalence.
 1017:- rdf_meta rdf_equal(t,t,-). 1018
 1019rdf_equal(X, X, boolean(true)) :- !.
 1020rdf_equal(boolean(A), boolean(B),  boolean(Eq)) :-
 1021    !,
 1022    eq_bool(A, B, Eq).
 1023rdf_equal(_, _, boolean(false)).
 1024
 1025
 1026eq_bool(X, X, true) :- !.
 1027eq_bool(true, false, false) :- !.
 1028eq_bool(false, true, false) :- !.
 1029eq_bool(X, Y, true) :-
 1030    boolean_value(X, V1),
 1031    boolean_value(Y, V2),
 1032    V1 == V2,
 1033    !.
 1034eq_bool(_, _, false).
 boolean_value(+Content, -Bool)
Convert the value from literal(xsd:boolean, Content) into either 'true' or 'false'.
 1041boolean_value(true,  true) :- !.
 1042boolean_value(false, false) :- !.
 1043boolean_value('0',   false) :- !.
 1044boolean_value('',    false) :- !.
 1045boolean_value(False, false) :-
 1046    downcase_atom(False, false),
 1047    !.
 1048boolean_value(_,     true).
 1049
 1050
 1051                 /*******************************
 1052                 *             CASTS            *
 1053                 *******************************/
 xsd_cast(+Term, -Type, -Arg)
Deals with xsd:dateTime(?a), casting ?a to the XML Schema type dateTime. Supported types are the numeric types, xsd:boolean and xsd:dateTime.
 1061term_expansion(xsd_cast(term,type,arg), Clauses) :-
 1062    findall(Clause, xsd_cast_clause(Clause), Clauses).
 1063
 1064xsd_cast_clause(xsd_cast(Term, Type, Arg)) :-
 1065    (   xsdp_numeric_uri(Type, _)
 1066    ;   rdf_equal(xsd:dateTime, Type)
 1067    ;   rdf_equal(xsd:boolean, Type)
 1068    ),
 1069    Term =.. [Type,Arg].
 1070
 1071xsd_cast(term,type,arg).
 eval_cast(+Type, +Value, -Result)
Cast Value to Type, resulting in a typed literal. Currently casts plain literals to the requested type and numeric values to other numeric values.
 1079eval_cast(Type, simple_literal(Value), Result) :-
 1080    atom(Value),
 1081    !,
 1082    eval_typed_literal(Type, Value, Result).
 1083eval_cast(Type, numeric(_, Value0), numeric(Type, Value)) :-
 1084    xsdp_numeric_uri(Type, Generic),
 1085    (   rdf_equal(Generic, xsd:integer)
 1086    ->  Value is integer(Value0)
 1087    ;   (   rdf_equal(Generic, xsd:float)
 1088        ;   rdf_equal(Generic, xsd:double)
 1089        )
 1090    ->  Value is float(Value0)
 1091    ;   Value = Value0
 1092    ).
 eval_function(+Term, -Result)
Eval user-defined function. User-defined functions are of the form sparql:function(Term, Result).
 1100:- multifile
 1101    sparql:function/2,
 1102    sparql:current_function/1. 1103
 1104eval_function(Term0, Result) :-
 1105    Term0 =.. [F|Args0],
 1106    eval_args(Args0, Args),
 1107    Term =.. [F|Args],
 1108    sparql:function(Term, Result0),
 1109    !,
 1110    eval(Result0, Result).
 1111eval_function(Term, boolean(error)) :-
 1112    sparql:current_function(Term),
 1113    !.
 1114eval_function(Term, _) :-
 1115    functor(Term, Name, Arity),
 1116    throw(error(existence_error(sparql_function, Name/Arity), _)).
 1117
 1118eval_args([], []).
 1119eval_args([H0|T0], [H|T]) :-
 1120    sparql_eval(H0, H),
 1121    eval_args(T0, T).
 1122
 1123
 1124                 /*******************************
 1125                 *      SUPPORT PREDICATES      *
 1126                 *******************************/
 not(+Bool, -Negated)
 1130not(true, false).
 1131not(false, true).
 1132not(error, error).
 bound(X)
Does not evaluate args. If the argument is a function it is always bound.
 1139bound(X) :- nonvar(X).
 str(+RDFTerm, -Atom)
Extract lexical representation from RDFTerm.
 1145str(Var, _) :-
 1146    var(Var), !, fail.
 1147str(literal(X), Str) :-
 1148    !,
 1149    str_literal(X, Str).
 1150str(IRI, IRI) :-
 1151    atom(IRI),
 1152    !,
 1153    \+ rdf_is_bnode(IRI).
 1154str(Expr, Str) :-
 1155    eval(Expr, Value),
 1156    str_value(Value, Str).
 1157
 1158str_value(simple_literal(X), X).
 1159str_value(lang(_, X), X).
 1160str_value(boolean(X), X).
 1161str_value(string(X), X).
 1162str_value(iri(IRI), IRI).
 1163
 1164str_literal(type(_, Str), Str) :- !.
 1165str_literal(lang(_, Str), Str) :- !.
 1166str_literal(Str, Str).
 1167
 1168str_text(simple_literal(X), X).
 1169str_text(lang(_, X), X).
 1170str_text(string(X), X).
 lang(+RDFTerm, -Lang)
Extract language specification from an RDFTerm
 1177lang(lang(Lang,_), Lang) :- !.
 1178lang(string(_), '').
 1179lang(simple_literal(_), '').
 1180lang(type(_,_), '').
 1181lang(numeric(_,_), '').
 datatype(+RDFTerm, -IRI)
Extract type specification from an RDFTerm
 1187:- rdf_meta
 1188    datatype(t,t). 1189
 1190datatype(0, _) :- !, fail.
 1191datatype(literal(type(Type, _)), iri(Type)) :- !.
 1192datatype(numeric(Type, _), iri(Type)) :- !.
 1193datatype(boolean(_), iri(xsd:boolean)) :- !.
 1194datatype(time(Type, _), iri(Type)) :- !.
 1195datatype(string(_), iri(xsd_string)) :- !.
 1196datatype(Expr, Type) :-
 1197    eval(Expr, Value),
 1198    Value \== Expr,
 1199    datatype(Value, Type).
 sparql_and(+A, +B, -Result)
 1204sparql_and(true, true,  true) :- !.
 1205sparql_and(true, error, error) :- !.
 1206sparql_and(error, true, error) :- !.
 1207sparql_and(_,    _,     false).
 sparql_or(+A, +B, -Result)
 1211sparql_or(true,  _,     true) :- !.
 1212sparql_or(_,     true,  true) :- !.
 1213sparql_or(false, false, false) :- !.
 1214sparql_or(_,     _,     error).
 isiri(+IRI)
True if IRI is an IRI. We get the argument un-evaluated.
 1220isiri(IRI) :-
 1221    atom(IRI),
 1222    !,
 1223    \+ rdf_is_bnode(IRI).
 1224isiri(literal(_)) :- !, fail.
 1225isiri(Expr) :-
 1226    eval(Expr, Value),
 1227    Value = iri(IRI),
 1228    \+ rdf_is_bnode(IRI).
 1229
 1230isblank(IRI) :-
 1231    atom(IRI),
 1232    !,
 1233    rdf_is_bnode(IRI).
 1234isblank(literal(_)) :- !, fail.
 1235isblank(Expr) :-
 1236    eval(Expr, Value),
 1237    Value = iri(IRI),
 1238    rdf_is_bnode(IRI).
 1239
 1240isliteral(literal(_)) :- !.
 1241isliteral(Atom) :-
 1242    atom(Atom), !, fail.
 1243isliteral(Expr) :-
 1244    eval(Expr, Value),
 1245    Value \= iri(_).
 1246
 1247
 1248                 /*******************************
 1249                 *     REGULAR EXPRESSIONS      *
 1250                 *******************************/
 1251
 1252:- if(exists_source(library(pcre))). 1253:- use_module(library(pcre)).
 regex(+Haystack, +Needle, +Flags) is semidet
 1257regex(String, Pattern, '') :-
 1258    !,
 1259    re_match(Pattern, String).
 1260regex(String, Pattern, Flags) :-
 1261    re_match(Pattern/Flags, String).
 compiled_regex(+Compiled, +Text) is semidet
Test using a regex that has been prepared. Compiled is a regex blob created by regex_obj/3.
 1268compiled_regex(Regex, String) :-
 1269    re_match(Regex, String).
 1270
 1271regex_obj(Pattern, Flags, Regex) :-
 1272    flag_options(Flags, Options),
 1273    re_compile(Pattern, Regex, Options).
 1274
 1275flag_options(Flags, Options) :-
 1276    atom_chars(Flags, Chars),
 1277    maplist(re_flag_option, Chars, Options).
 1278
 1279re_flag_option(Flag, Option) :-
 1280    re_flag_option_(Flag, Option),
 1281    !.
 1282re_flag_option(Flag, _) :-
 1283    existence_error(re_flag, Flag).
 1284
 1285re_flag_option_(i, caseless(true)).
 1286re_flag_option_(m, multiline(true)).
 1287re_flag_option_(x, extended(true)).
 1288re_flag_option_(s, dotall(true)).
 regex_replace(+Input, +Pattern, +Replace, +Flags, -Result)
 1293regex_replace(Input, Pattern, Replace, Flags, Result) :-
 1294    re_replace(Pattern/Flags, Replace, Input, ResultS),
 1295    atom_string(Result, ResultS).
 1296
 1297:- else.                                        % XPCE based version
 regex(+String, +Pattern, +Flags)
TBD:
 1305:- dynamic
 1306    pattern_cache/3.                % Pattern, Flags, Regex
 1307
 1308regex(String, Pattern, Flags) :-
 1309    with_mutex(sparql_regex,
 1310               ( regex_obj(Pattern, Flags, Regex),
 1311                 send(Regex, search, string(String)))).
 1312
 1313regex_obj(Pattern, Flags, Regex) :-
 1314    pattern_cache(Pattern, Flags, Regex),
 1315    !.
 1316regex_obj(Pattern, Flags, Regex) :-
 1317    make_regex(Pattern, Flags, Regex),
 1318    asserta(pattern_cache(Pattern, Flags, Regex)).
 1319
 1320make_regex(Pattern, i, Regex) :-
 1321    !,
 1322    new(Regex, regex(Pattern, @(off))).
 1323make_regex(Pattern, _, Regex) :-
 1324    !,
 1325    new(Regex, regex(Pattern)).
 compiled_regex(+Compiled, +Text) is semidet
Test using a regex that has been prepared. Compiled takes the following forms:
 1334compiled_regex(@(Regex), String) :-
 1335    send(@(Regex), search, string(String)).
 regex_replace(+Input, +Pattern, +Replace, +Flags, -Result)
 1339regex_replace(Input, Pattern, Replace0, Flags, Result) :-
 1340    dollar_replace(Replace0, Replace),
 1341    with_mutex(sparql_regex,
 1342               locked_replace(Input, Pattern, Replace, Flags, Result)).
 1343
 1344dollar_replace(Replace0, Replace) :-
 1345    sub_atom(Replace0, _, _, _, $),
 1346    !,
 1347    regex_replace(Replace0, '\\$([0-9])', '\\\\1', '', Replace).
 1348dollar_replace(Replace, Replace).
 1349
 1350
 1351locked_replace(Input, Pattern, Replace, Flags, Result) :-
 1352    regex_obj(Pattern, Flags, Regex),
 1353    new(S, string('%s', Input)),
 1354    send(Regex, for_all, S,
 1355         message(@(arg1), replace, @(arg2), Replace)),
 1356    get(S, value, Result).
 1357
 1358:- endif.                                       % regex pcre/xpce
 effective_boolean_value(+Expr, -Bool)
See SPARQL document, section 11.2.2: Effecitive Boolean Value
 1365effective_boolean_value(boolean(X), boolean(True)) :-
 1366    !,
 1367    True = X.
 1368effective_boolean_value(string(X),  boolean(True)) :-
 1369    !,
 1370    (X == '' -> True = false ; True = true).
 1371effective_boolean_value(simple_literal(X),  boolean(True)) :-
 1372    !,
 1373    (X == '' -> True = false ; True = true).
 1374effective_boolean_value(numeric(_, X),  boolean(True)) :-
 1375    !,
 1376    (X =:= 0 -> True = false ; True = true).
 1377effective_boolean_value(_,  boolean(error)).
 sparql_eval(+Expr, -Results)
Evaluate a SPARQL expression.
 1383sparql_eval(Expr, Expr) :-
 1384    is_rdf(Expr),
 1385    !.
 1386sparql_eval(Expr, Result) :-
 1387    eval(Expr, Result0),
 1388    !,
 1389    to_rdf(Result0, Result).
 1390sparql_eval(Expr, '$null$') :-
 1391    debug(sparql(eval), '~p --> NULL', [Expr]).
 sparql_eval_raw(+Expr, -Result)
Same as sparql_eval/2, but return the raw result.
 1397sparql_eval_raw(Expr, Result) :-
 1398    (   eval(Expr, Result0)
 1399    ->  Result = Result0
 1400    ;   Result = '$null$',
 1401        debug(sparql(eval), '~p --> NULL', [Expr])
 1402    ).
 1403
 1404:- rdf_meta
 1405    to_rdf(+,t). 1406
 1407to_rdf(numeric(Type, Value), literal(type(Type, Atom))) :-
 1408    !,
 1409    atom_number(Atom, Value).
 1410to_rdf(boolean(Val), literal(type(xsd:boolean, Val))) :- !.
 1411to_rdf(type(T, Val), literal(type(T, Val))) :- !.
 1412to_rdf(lang(L, Val), literal(lang(L, Val))) :- !.
 1413to_rdf(simple_literal(L), literal(L)) :- !.
 1414to_rdf(string(L), literal(type(xsd:string, L))) :- !.
 1415to_rdf(time(Type, D), literal(type(Type, D))) :- !.
 1416to_rdf(iri(IRI), IRI) :- !.
 1417to_rdf(X, X) :- is_rdf(X).
 is_rdf(+Term)
True if Term is a valid RDF term.
 1423is_rdf(IRI) :- atom(IRI).
 1424is_rdf(Var) :- var(Var), !, fail.
 1425is_rdf(literal(_)).
 1426
 1427
 1428                 /*******************************
 1429                 *     PROPERTY PATH SUPPORT    *
 1430                 *******************************/
 sparql_find(?From, ?To, ?F, ?T, :Q) is nondet
Implement *(PropertyPath). We should probably collect translated queries in a dynamic predicate to avoid the copy_term. Also, Q will quite often be simple. In that case we can map to rdf_reachable/3, although one of the problems is that rdf_reachable/3 uses rdf_has/3, and does not deal with graphs.

We should be a bit smarter here and choose between forward, backward, two-sided breath-first, etc. based on which start point is given.

To be done
- Maybe a thing for using tor? Planning most likely more important than the iteration speed.
 1447sparql_find(From, To, F, T, Q) :-
 1448    empty_assoc(Visited),
 1449    (   nonvar(From)
 1450    ->  sparql_find_f(From, To, F, T, Q, Visited)
 1451    ;   nonvar(To)
 1452    ->  sparql_find_b(From, To, F, T, Q, Visited)
 1453    ;   query_graph(Q, Graph)
 1454    ->  rdf_current_node(Graph, From),
 1455        sparql_find_f(From, To, F, T, Q, Visited)
 1456    ;   rdf_current_node(From),
 1457        sparql_find_f(From, To, F, T, Q, Visited)
 1458    ).
 1459
 1460sparql_find_f(Place, Place, _, _, _, _).
 1461sparql_find_f(From, To, F, T, Q, Visited) :-
 1462    copy_term(t(F,T,Q), t(From, Tmp, Q2)),
 1463    call(Q2),
 1464    \+ get_assoc(Tmp, Visited, _),
 1465    put_assoc(Tmp, Visited, true, V2),
 1466    sparql_find_f(Tmp, To, F, T, Q, V2).
 1467
 1468
 1469sparql_find_b(Place, Place, _, _, _, _).
 1470sparql_find_b(From, To, F, T, Q, Visited) :-
 1471    copy_term(t(F,T,Q), t(Tmp, To, Q2)),
 1472    call(Q2),
 1473    \+ get_assoc(Tmp, Visited, _),
 1474    put_assoc(Tmp, Visited, true, V2),
 1475    sparql_find_b(From, Tmp, F, T, Q, V2).
 query_graph(+Query, -Graph) is semidet
True when Query is associated with graph. Note that property paths are always executed in a single graph.
 1483query_graph(V, _) :-
 1484    var(V), !, fail.
 1485query_graph(_:Q, G) :-
 1486    query_graph(Q, G).
 1487query_graph((A,B), G) :-
 1488    (   query_graph(A, G)
 1489    ;   query_graph(B, G)
 1490    ).
 1491query_graph((A;B), G) :-
 1492    (   query_graph(A, G)
 1493    ;   query_graph(B, G)
 1494    ).
 1495query_graph((A->B), G) :-
 1496    (   query_graph(A, G)
 1497    ;   query_graph(B, G)
 1498    ).
 1499query_graph((A*->B), G) :-
 1500    (   query_graph(A, G)
 1501    ;   query_graph(B, G)
 1502    ).
 1503query_graph(rdf(_,_,_,G:_), G).
 rdf_current_node(?Graph, -Resource)
True when Resource is a resource in Graph. This means it is either a subject or an object of a triple in Graph.
 1511rdf_current_node(Graph, R) :-
 1512    rdf_graph(Graph),
 1513    setof(R,
 1514          ( rdf(S,_,O,Graph),
 1515            (   R = S
 1516            ;   atom(O),
 1517                R = O
 1518            )
 1519          ),
 1520          Rs),
 1521    member(R, Rs).
 rdf_current_node(-Resource)
Generates all known resources on backtracing. This is there to support {?s :p* ?o}. A highly dubious query.
 1529rdf_current_node(From) :-
 1530    rdf_subject(From).
 1531rdf_current_node(From) :-
 1532    findall(R, (rdf(_,_,R), \+ (atom(R), rdf_subject(R))), Rs),
 1533    sort(Rs, Set),
 1534    member(From, Set).
 sparql_minus(:QLeft, :QRight)
Realise SPARQL MINUS. This is defined to
To be done
- : Both the result set and the minus set are in standard order of terms, so we can do ordered subtraction.
 1549sparql_minus(QLeft, QRight) :-
 1550    term_variables(QLeft,  VarsLeft0),  sort(VarsLeft0,  VarsLeft),
 1551    term_variables(QRight, VarsRight0), sort(VarsRight0, VarsRight),
 1552    ord_intersection(VarsLeft, VarsRight, VarsCommon),
 1553    (   VarsCommon == []
 1554    ->  QLeft
 1555    ;   ord_subtract(VarsLeft, VarsCommon, ExtraLeft),
 1556        VLeft =.. [v|ExtraLeft],
 1557        VCommon =.. [v|VarsCommon],
 1558        findall(VCommon-VLeft, (QLeft,cond_bind_null(VarsLeft)), AllSols),
 1559        AllSols \== [],
 1560        sort(AllSols, AllSorted),
 1561        findall(VCommon, (QRight,cond_bind_null(VarsCommon)), MinusSols),
 1562        sort(MinusSols, MinusSorted),
 1563        member(VCommon-VLeft, AllSorted),
 1564        \+ memberchk(VCommon, MinusSorted)
 1565    ).
 1566
 1567cond_bind_null([]).
 1568cond_bind_null([H|T]) :-
 1569    (   var(H)
 1570    ->  H = '$null$'
 1571    ;   true
 1572    ),
 1573    cond_bind_null(T).
 1574
 1575
 1576                 /*******************************
 1577                 *         SPARQL GROUP         *
 1578                 *******************************/
 sparql_group(:Goal)
Same as call. Intended to keep groups together to avoid invalid optimizations.
 1585sparql_group(Goal) :-
 1586    call(Goal).
 sparql_group(:Goal, +OuterVars, +InnerVars)
Execute a group that contains non-steadfast variables, which asks for delayed unification of the output arguments.
 1593sparql_group(Goal, OuterVars, InnerVars) :-
 1594    call(Goal),
 1595    OuterVars = InnerVars.
 1596
 1597
 1598                 /*******************************
 1599                 *            SERVICE           *
 1600                 *******************************/
 sparql_service(+Silent, +URL, +Prefixes, +Bindings, +QText)
Execute a remote SPARQL SERVICE request
Arguments:
Silent- is one of silent or error
URL- is the address of the SPARQL server
Prefixes- is a list Prefix-URL
Bindings- is a list VarName=Var
QText- is a string holding the remote query
 1612sparql_service(Silent, URL, Prefixes, Bindings, QText) :-
 1613    parse_url(URL, Options),
 1614    maplist(prefix_line, Prefixes, PrefLines),
 1615    partition(bound_binding, Bindings, In, Out),
 1616    maplist(proj, Out, Proj),
 1617    atomics_to_string(Proj, " ", Projection),
 1618    format(string(SubSel), 'SELECT ~w WHERE {', [Projection]),
 1619    maplist(binding_line, In, BindLines),
 1620    append([ PrefLines, [SubSel], BindLines, [QText], ["}"] ], Lines),
 1621    atomics_to_string(Lines, "\n", Query),
 1622    debug(sparql(service), 'SERVICE:~n~w', [Query]),
 1623    maplist(binding_var, Out, Vars),
 1624    Row =.. [row|Vars],
 1625    (   Silent == error
 1626    ->  sparql_query(Query, Row, Options)
 1627    ;   catch(sparql_query(Query, Row, Options), _, true)
 1628    ).
 1629
 1630prefix_line(Pref-URL, Line) :-
 1631    format(string(Line), 'PREFIX ~w: <~w>', [Pref, URL]).
 1632
 1633bound_binding(_Name = Var) :-
 1634    ground(Var).
 1635
 1636proj(Name=_, Proj) :-
 1637    format(string(Proj), '?~w', [Name]).
 1638
 1639binding_line(Name=IRI, Line) :-
 1640    atom(IRI),
 1641    !,
 1642    with_output_to(string(QIRI),
 1643                   turtle:turtle_write_uri(current_output, IRI)),
 1644    format(string(Line), 'BIND(~s as ?~w)', [QIRI, Name]).
 1645binding_line(Name=Literal, Line) :-
 1646    rdf_lexical_form(Literal, Lex),
 1647    (   Lex = ^^(String,Type)
 1648    ->  with_output_to(
 1649            string(QString),
 1650            turtle:turtle_write_quoted_string(current_output, String)),
 1651        with_output_to(
 1652            string(QType),
 1653            turtle:turtle_write_uri(current_output, Type)),
 1654        format(string(Line), 'BIND(~s^^<~w> as ?~w)',
 1655               [QString, QType, Name])
 1656    ;   Lex = @(String,Lang)
 1657    ->  with_output_to(
 1658            string(QString),
 1659            turtle:turtle_write_quoted_string(current_output, String)),
 1660        format(string(Line), 'BIND(~s@~w as ?~w)',
 1661               [QString, Lang, Name])
 1662    ).
 1663
 1664binding_var(_Name=Var, Var).
 1665
 1666
 1667                 /*******************************
 1668                 *             BNODES           *
 1669                 *******************************/
 sparql_reset_bnodes
Reset the database for the BNODE(str) function
 1675sparql_reset_bnodes :-
 1676    retractall(bnode_store(_,_)).
 1677
 1678
 1679                 /*******************************
 1680                 *            SIMPLIFY          *
 1681                 *******************************/
 sparql_simplify(:Goal, -Simple) is det
Simplify goals to the SPARQL runtime functions before they are handed to the general optimizer and runtime evaluation.
 1688sparql_simplify(sparql_true(E), G) :-
 1689    simplify_true(E, G),
 1690    !.
 1691sparql_simplify(sparql_eval(E, V), G) :-
 1692    simplify_eval(E, V, G),
 1693    !.
 1694sparql_simplify(Goal, Goal).
 simplify_true(+Expr, -Goal) is semidet
Simplify a boolean expression resulting from a SPARQL FILTER statement. Ideally, this should be a simple partial evaluation of sparql_true/1.
 1703simplify_true(Var, Var) :-              % E.g., FILTER(?a)
 1704    var(Var),
 1705    !,
 1706    fail.
 1707simplify_true(or(A0,B0), (A;B)) :-
 1708    !,
 1709    simplify_true(A0, A),
 1710    simplify_true(B0, B).
 1711simplify_true(and(A0,B0), (A,B)) :-
 1712    !,
 1713    simplify_true(A0, A),
 1714    simplify_true(B0, B).
 1715simplify_true(A0=B0, A=B) :-
 1716    !,
 1717    peval(A0, A, IsResource),
 1718    peval(B0, B, IsResource),
 1719    IsResource == true.             % at least one is a resource
 1720simplify_true(A0\=B0, A\=B) :-
 1721    !,
 1722    peval(A0, A, IsResource),
 1723    peval(B0, B, IsResource),
 1724    IsResource == true.             % at least one is a resource
 1725simplify_true(Expr, sparql_true(PExpr)) :-
 1726    simplify_expression(Expr, PExpr).
 1727
 1728simplify_expression(Var, Var) :-
 1729    var(Var),
 1730    !.
 1731simplify_expression(Term0, Term) :-
 1732    ground(Term0),
 1733    !,
 1734    eval(Term0, Term).
 1735simplify_expression(Term0, Term) :-
 1736    list_arg(Term0),
 1737    !,
 1738    Term0 =.. [Name,Args0],
 1739    maplist(simplify_expression, Args0, Args),
 1740    Term =.. [Name,Args].
 1741simplify_expression(Term0, Term) :-
 1742    compound(Term0),
 1743    !,
 1744    Term0 =.. [Name|Args0],
 1745    maplist(simplify_expression, Args0, Args),
 1746    Term1 =.. [Name|Args],
 1747    simplify_test(Term1, Term).
 1748simplify_expression(Term, Term).
 1749
 1750list_arg(concat(_)).
 1751list_arg(coalesce(_)).
 simplify_test(+Expr0, -Expr) is det
Perform analysis on specific tests. Currently optimizes regex tests.
 1758simplify_test(regex(String, simple_literal(Pattern), simple_literal(Flags)),
 1759              compiled_regex(Regex, String)) :-
 1760    atom(Pattern), atom(Flags),
 1761    !,
 1762    regex_obj(Pattern, Flags, Regex).
 1763simplify_test(Expr, Expr).
 simplify_eval(+Expr, +Value, -Goal) is semidet
 1767simplify_eval(Expr, Var, Goal) :-
 1768    simplify_expression(Expr, Expr1),
 1769    Goal = sparql_eval(Expr1, Var).
 1770
 1771peval(Var, Var, IsResource) :-
 1772    var(Var),
 1773    !,
 1774    (   get_attr(Var, annotations, Annot),
 1775        memberchk(resource, Annot)
 1776    ->  IsResource = true
 1777    ;   true
 1778    ).
 1779peval(Resource, Resource, true) :-
 1780    atom(Resource).
 1781
 1782
 1783                 /*******************************
 1784                 *      SUBQUERY EVALUATION     *
 1785                 *******************************/
 sparql_subquery(+Proj, :Query, +Solutions) is nondet
Execute a SPARQL subquery.
Arguments:
Proj- is a list of variables that are shared with the outer query.
To be done
- Call the optimizer.
- Sub queries must be evaluated before the outer query, so we must move them to the head of the query evaluation. Not doing so causes no harm, but leads to repetitive execution of the subquery.
 1799sparql_subquery(Proj, Query, Solutions) :-
 1800    vars_in_bindings(Proj, Vars),
 1801    Reply =.. [row|Vars],
 1802    sparql:select_results(Solutions, Reply, Query),
 1803    debug(sparql(subquery), 'SubQuery result: ~q', [Proj]),
 1804    unify_projection(Proj).
 1805
 1806vars_in_bindings([], []).
 1807vars_in_bindings([_Outer=Var|T0], [Var|T]) :-
 1808    vars_in_bindings(T0, T).
 1809
 1810
 1811unify_projection([]).
 1812unify_projection([V=V|T]) :-
 1813    unify_projection(T).
 1814
 1815
 1816                 /*******************************
 1817                 *            UPDATE            *
 1818                 *******************************/
 sparql_update(:Updates) is det
Handle SPARQL update requests.
To be done
- Realise authorization rules
 1826sparql_update(Module:Updates) :-
 1827    rdf_transaction(update(Updates, Module), 'SPARQL').
 1828
 1829update([], _).
 1830update([H|T], M) :-
 1831    update(H, M),
 1832    update(T, M).
 1833update(insert_data(Quads), _) :-
 1834    materialize_bnodes(Quads),
 1835    maplist(insert_triple(user), Quads).
 1836update(delete_data(Quads), _) :-
 1837    maplist(delete_triple(user), Quads).
 1838update(delete_where(Quads), _):-
 1839    maplist(delete_triples(user), Quads).
 1840update(add(_Silent, From, To), _) :-    % TBD: Error of From does not exist
 1841    db(From, FromDB),
 1842    db(To, ToDB),
 1843    forall(rdf(S,P,O,FromDB:Line),
 1844           rdf_assert(S,P,O,ToDB:Line)).
 1845update(move(_Silent, From, To), _) :-
 1846    db(From, FromGraph),
 1847    db(To, ToGraph),
 1848    rdf_retractall(_,_,_,ToGraph),
 1849    forall(rdf(S,P,O,FromGraph:Line),
 1850           ( rdf_retractall(S,P,O,FromGraph:Line),
 1851             rdf_assert(S,P,O,ToGraph:Line)
 1852           )).
 1853update(copy(_Silent, From, To), _) :-
 1854    db(From, FromGraph),
 1855    db(To, ToGraph),
 1856    rdf_retractall(_,_,_,ToGraph),
 1857    forall(rdf(S,P,O,FromGraph:Line),
 1858           rdf_assert(S,P,O,ToGraph:Line)).
 1859update(modify(With, Modify, _Using, Query), Module) :-
 1860    db(With, Graph),
 1861    forall(Module:Query,
 1862           modify(Modify, Graph)).
 1863update(load(_Silent, URI, Into), _) :-
 1864    (   Into = graph(Graph)
 1865    ->  rdf_load(URI, [graph(Graph), multifile(true)])
 1866    ;   rdf_load(URI)
 1867    ).
 1868update(clear(_Silent, Clear), _) :-
 1869    clear_db(Clear).
 1870
 1871db(default, user).
 1872db(graph(G), G).
 1873
 1874modify(delete(Delete), Graph) :-
 1875    maplist(delete_triple(Graph), Delete).
 1876modify(insert(Insert), Graph) :-
 1877    maplist(insert_triple(Graph), Insert).
 1878modify(replace(Delete, Insert), Graph) :-
 1879    maplist(delete_triple(Graph), Delete),
 1880    maplist(insert_triple(Graph), Insert).
 insert_triple(+Graph, +Triple) is det
 1884insert_triple(Graph, rdf(S0,P,O0)) :-
 1885    !,
 1886    modify_subject(S0, S),
 1887    modify_object(O0, O),
 1888    rdf_assert(S,P,O, Graph).
 1889insert_triple(_, rdf(S0,P,O0,G0)) :-
 1890    graph(G0, G),
 1891    modify_subject(S0, S),
 1892    modify_object(O0, O),
 1893    rdf_assert(S,P,O,G).
 delete_triple(+Graph, +Triple) is det
Delete matching triples
 1899delete_triple(Graph, rdf(S,P,O0)) :-
 1900    !,
 1901    modify_object(O0, O),
 1902    rdf_retractall(S,P,O,Graph).
 1903delete_triple(_, rdf(S,P,O0,G0)) :-
 1904    !,
 1905    graph(G0, G),
 1906    modify_object(O0, O),
 1907    rdf_retractall(S,P,O,G).
 delete_triples(+Graph:atom, +SimpleTriplePattern:compound) is det
 1911delete_triples(G0, Triple):-
 1912    (   Triple = rdf(S,P,O),
 1913        G = G0
 1914    ;   Triple = rdf(S,P,O,G)
 1915    ),
 1916    forall(
 1917        rdf(S,P,O),
 1918        delete_triple(G, rdf(S,P,O))
 1919    ).
 1920
 1921materialize_bnodes(Term) :-
 1922    term_variables(Term, Vars),
 1923    assign_bnodes(Vars, 0).
 1924
 1925assign_bnodes([], _).
 1926assign_bnodes([bnode(Id)|T], Id) :-
 1927    Id2 is Id + 1,
 1928    assign_bnodes(T, Id2).
 1929
 1930modify_subject(bnode(Id), BNode) :-
 1931    !,
 1932    id_to_bnode(Id, BNode).
 1933modify_subject(S, S).
 1934
 1935modify_object(literal(_Q,V), literal(V)) :- !.
 1936modify_object(bnode(Id), BNode) :-
 1937    !,
 1938    id_to_bnode(Id, BNode).
 1939modify_object(O, O).
 1940
 1941id_to_bnode(Id, BNode):-
 1942    (   bnode_store(Id, BN)
 1943    ->  BN = BNode
 1944    ;   rdf_bnode(BN),
 1945        asserta(bnode_store(Id, BN))
 1946    ->  BN = BNode
 1947    ).
 graph(+Spec, -Graph)
 1951graph(G:L, Graph) :-
 1952    atom(G),
 1953    !,
 1954    (   integer(L)
 1955    ->  Graph = (G:L)
 1956    ;   Graph = G
 1957    ).
 1958graph(G, G).
 clear_db(+Clear)
Note that CLEAR ALL cannot use rdf_reset_db because we are in a transaction.
 1965clear_db(all) :-
 1966    rdf_retractall(_,_,_).
 1967clear_db(default) :-
 1968    rdf_retractall(_,_,_,user).
 1969clear_db(named) :-
 1970    forall((rdf_graph(Graph), Graph \== user),
 1971           rdf_retractall(_,_,_,Graph)).
 1972clear_db(graph(Graph)) :-
 1973    rdf_retractall(_,_,_,Graph)