View source with formatted 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(:).   76
   77/** <module> SPARQL runtime support
   78
   79@see    rdfql_runtime.pl merges this module with generic predicates as well
   80        as runtime libraries for other query languages.
   81@see    These routines are part of the _entailment_ modules.  See
   82        ../entailment/README.txt
   83*/
   84
   85:- thread_local
   86    bnode_store/2.   87
   88%!  sparql_true(+Term)
   89%
   90%   Generated from FILTER Term, where Term must be converted to a
   91%   boolean as 'Effective Boolean Value'.
   92
   93sparql_true(Term) :-
   94    typed_eval(boolean, Term, Result),
   95    !,
   96    true(Result).
   97
   98true(boolean(true)).
   99
  100%!  eval(+Term, -Result)
  101
  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
  126
  127%!  eval(+Type, +Term, -Result) is semidet.
  128%
  129%   Evaluate Term, converting the resulting argument to Type.
  130
  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)).
  161
  162%!  eval_known_typed_literal(+Type, +Plain, -Typed) is semidet.
  163%
  164%   Map known datatypes to a value   that is suitable for comparison
  165%   using Prolog standard order of terms.  Note that the mapped time
  166%   representations can all be compared.
  167
  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)).
  176
  177%!  numeric_literal_value(+Literal, -Value) is semidet.
  178%
  179%   Convert a SPARQL numeric literal into  its value for the purpose
  180%   of comparison-by-value.
  181%
  182%   @tbd    Move this into the rdf_db library.  There we can achieve
  183%           better performance and we can do more efficient
  184%           matching.
  185
  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)).
  238
  239%!  sparql_op(+ListOfDelcs)
  240
  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].
  248
  249
  250%!  expand_op(+In, -Clause) is det.
  251%
  252%   Expand SPARQL operators into a nice clause.
  253
  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).
  296
  297%!  op(+Operator, -Result) is semidet.
  298%
  299%   @param Operator Term of the format Op(Arg...) where each Arg
  300%                   is embedded in its type.
  301%   @param Result   Result-value, embedded in its type.
  302
  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                 *******************************/
  675
  676%!  time_part(+Part, +Type, +String, -Value) is semidet.
  677
  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) }.
  713
  714%!  seconds_xsd_duration(+Seconds, -XSDDuration)
  715%
  716%   @see http://docs.oracle.com/cd/E13214_01/wli/docs92/xref/xqdurfunc.html#wp1183764
  717%   @tbd    Implement other direction and move this to XSD or datetime
  718%           library.
  719
  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,_)).
  801
  802%!  string_op1(+A1, -R, +Op)
  803
  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).
  810
  811%!  string_op_string(+A, -R)
  812
  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).
  819
  820%!  string_int_op_string(+S0, +I, -S)
  821
  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).
  828
  829%!  string_int_int_op_string(+S0, +I, -S)
  830
  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).
  837
  838%!  string_op2(+A1, +A2, -R, +Op)
  839%
  840%   Define operations on strings.
  841
  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    ).
  877
  878%!  iri(+Spec, +Base, -IRI)
  879
  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).
  886
  887%!  argument_compatible(+A1, +A2, -Bool, +Op)
  888
  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), !.
  921
  922
  923%!  atom_op(+Op, +Atom, -Result).
  924
  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    ).
  941
  942%!  atom_op(+Op, +Atom, +Arg, -Result).
  943
  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    ).
  960
  961%!  atom_op(+Op, +Atom, +A1, +A2, -Result).
  962
  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:
  976
  977%!  combine_types_div(+TypeLeft, +TypeRight, -Type)
  978
  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).
  987
  988%!  combine_types(+TypeLeft, +TypeRight, -Type)
  989
  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).
 1010
 1011
 1012%!  rdf_equal(+RDFTerm, +RDFTerm, -Boolean)
 1013%
 1014%   RDF Term equivalence. Described as   lexical equivalence, except
 1015%   where we have the logic to do value equivalence.
 1016
 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).
 1035
 1036%!  boolean_value(+Content, -Bool)
 1037%
 1038%   Convert the value from literal(xsd:boolean, Content) into
 1039%   either 'true' or 'false'.
 1040
 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                 *******************************/
 1054
 1055%!  xsd_cast(+Term, -Type, -Arg)
 1056%
 1057%   Deals with xsd:dateTime(?a), casting ?a to   the XML Schema type
 1058%   dateTime. Supported types are the numeric types, xsd:boolean and
 1059%   xsd:dateTime.
 1060
 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).
 1072
 1073%!  eval_cast(+Type, +Value, -Result)
 1074%
 1075%   Cast Value to Type, resulting  in   a  typed  literal. Currently
 1076%   casts plain literals to the requested type and numeric values to
 1077%   other numeric values.
 1078
 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    ).
 1093
 1094
 1095%!  eval_function(+Term, -Result)
 1096%
 1097%   Eval user-defined function.  User-defined functions are of the
 1098%   form sparql:function(Term, Result).
 1099
 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                 *******************************/
 1127
 1128%!  not(+Bool, -Negated)
 1129
 1130not(true, false).
 1131not(false, true).
 1132not(error, error).
 1133
 1134%!  bound(X)
 1135%
 1136%   Does not evaluate args.  If the argument is a function it
 1137%   is always bound.
 1138
 1139bound(X) :- nonvar(X).
 1140
 1141%!  str(+RDFTerm, -Atom)
 1142%
 1143%   Extract lexical representation from RDFTerm.
 1144
 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).
 1171
 1172
 1173%!  lang(+RDFTerm, -Lang)
 1174%
 1175%   Extract language specification from an RDFTerm
 1176
 1177lang(lang(Lang,_), Lang) :- !.
 1178lang(string(_), '').
 1179lang(simple_literal(_), '').
 1180lang(type(_,_), '').
 1181lang(numeric(_,_), '').
 1182
 1183%!  datatype(+RDFTerm, -IRI)
 1184%
 1185%   Extract type specification from an RDFTerm
 1186
 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).
 1200
 1201
 1202%!  sparql_and(+A, +B, -Result)
 1203
 1204sparql_and(true, true,  true) :- !.
 1205sparql_and(true, error, error) :- !.
 1206sparql_and(error, true, error) :- !.
 1207sparql_and(_,    _,     false).
 1208
 1209%!  sparql_or(+A, +B, -Result)
 1210
 1211sparql_or(true,  _,     true) :- !.
 1212sparql_or(_,     true,  true) :- !.
 1213sparql_or(false, false, false) :- !.
 1214sparql_or(_,     _,     error).
 1215
 1216%!  isiri(+IRI)
 1217%
 1218%   True if IRI is an IRI.  We get the argument un-evaluated.
 1219
 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)). 1254
 1255%!  regex(+Haystack, +Needle, +Flags) is semidet.
 1256
 1257regex(String, Pattern, '') :-
 1258    !,
 1259    re_match(Pattern, String).
 1260regex(String, Pattern, Flags) :-
 1261    re_match(Pattern/Flags, String).
 1262
 1263%!  compiled_regex(+Compiled, +Text) is semidet.
 1264%
 1265%   Test using a regex that has been   prepared. Compiled is a regex
 1266%   blob created by regex_obj/3.
 1267
 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)).
 1289
 1290
 1291%!  regex_replace(+Input, +Pattern, +Replace, +Flags, -Result)
 1292
 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
 1298
 1299%!  regex(+String, +Pattern, +Flags)
 1300%
 1301%   TBD:
 1302%           - Avoid XPCE
 1303%           - Complete flags
 1304
 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)).
 1326
 1327%!  compiled_regex(+Compiled, +Text) is semidet.
 1328%
 1329%   Test using a regex that has   been  prepared. Compiled takes the
 1330%   following forms:
 1331%
 1332%     - XPCE object
 1333
 1334compiled_regex(@(Regex), String) :-
 1335    send(@(Regex), search, string(String)).
 1336
 1337%!  regex_replace(+Input, +Pattern, +Replace, +Flags, -Result)
 1338
 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
 1359
 1360
 1361%!  effective_boolean_value(+Expr, -Bool)
 1362%
 1363%   See SPARQL document, section 11.2.2: Effecitive Boolean Value
 1364
 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)).
 1378
 1379%!  sparql_eval(+Expr, -Results)
 1380%
 1381%   Evaluate a SPARQL expression.
 1382
 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]).
 1392
 1393%!  sparql_eval_raw(+Expr, -Result)
 1394%
 1395%   Same as sparql_eval/2, but return the raw result.
 1396
 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).
 1418
 1419%!  is_rdf(+Term)
 1420%
 1421%   True if Term is a valid RDF term.
 1422
 1423is_rdf(IRI) :- atom(IRI).
 1424is_rdf(Var) :- var(Var), !, fail.
 1425is_rdf(literal(_)).
 1426
 1427
 1428                 /*******************************
 1429                 *     PROPERTY PATH SUPPORT    *
 1430                 *******************************/
 1431
 1432%!  sparql_find(?From, ?To, ?F, ?T, :Q) is nondet.
 1433%
 1434%   Implement *(PropertyPath). We should probably collect translated
 1435%   queries in a dynamic predicate to   avoid the copy_term. Also, Q
 1436%   will quite often  be  simple.  In  that   case  we  can  map  to
 1437%   rdf_reachable/3,  although  one  of   the    problems   is  that
 1438%   rdf_reachable/3 uses rdf_has/3, and does not deal with graphs.
 1439%
 1440%   We should be a bit  smarter   here  and  choose between forward,
 1441%   backward, two-sided breath-first, etc.  based   on  which  start
 1442%   point is given.
 1443%
 1444%   @tbd    Maybe a thing for using tor?  Planning most likely more
 1445%           important than the iteration speed.
 1446
 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).
 1476
 1477
 1478%!  query_graph(+Query, -Graph) is semidet.
 1479%
 1480%   True when Query is associated with graph.  Note that property
 1481%   paths are always executed in a single graph.
 1482
 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).
 1504
 1505
 1506%!  rdf_current_node(?Graph, -Resource)
 1507%
 1508%   True when Resource is a resource in Graph.  This means it is
 1509%   either a subject or an object of a triple in Graph.
 1510
 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).
 1522
 1523
 1524%!  rdf_current_node(-Resource)
 1525%
 1526%   Generates all known resources on backtracing.   This is there to
 1527%   support {?s :p* ?o}. A highly dubious query.
 1528
 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).
 1535
 1536
 1537%!  sparql_minus(:QLeft, :QRight)
 1538%
 1539%   Realise SPARQL =MINUS=.  This is defined to
 1540%
 1541%       - Take the variables of QLeft
 1542%       - Determine the result-set for these variables for
 1543%         both QLeft and QRight
 1544%       - Substract those from QLeft that are in QRight
 1545%
 1546%   @tbd:   Both the result set and the minus set are in standard
 1547%           order of terms, so we can do ordered subtraction.
 1548
 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                 *******************************/
 1579
 1580%!  sparql_group(:Goal)
 1581%
 1582%   Same as call.  Intended to keep groups together to avoid invalid
 1583%   optimizations.
 1584
 1585sparql_group(Goal) :-
 1586    call(Goal).
 1587
 1588%!  sparql_group(:Goal, +OuterVars, +InnerVars)
 1589%
 1590%   Execute a group that contains non-steadfast variables, which
 1591%   asks for delayed unification of the output arguments.
 1592
 1593sparql_group(Goal, OuterVars, InnerVars) :-
 1594    call(Goal),
 1595    OuterVars = InnerVars.
 1596
 1597
 1598                 /*******************************
 1599                 *            SERVICE           *
 1600                 *******************************/
 1601
 1602%!  sparql_service(+Silent, +URL, +Prefixes, +Bindings, +QText)
 1603%
 1604%   Execute a remote SPARQL SERVICE request
 1605%
 1606%   @arg Silent is one of `silent` or `error`
 1607%   @arg URL is the address of the SPARQL server
 1608%   @arg Prefixes is a list `Prefix-URL`
 1609%   @arg Bindings is a list `VarName=Var`
 1610%   @arg QText is a string holding the remote query
 1611
 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                 *******************************/
 1670
 1671%!  sparql_reset_bnodes
 1672%
 1673%   Reset the database for the BNODE(str) function
 1674
 1675sparql_reset_bnodes :-
 1676    retractall(bnode_store(_,_)).
 1677
 1678
 1679                 /*******************************
 1680                 *            SIMPLIFY          *
 1681                 *******************************/
 1682
 1683%!  sparql_simplify(:Goal, -Simple) is det.
 1684%
 1685%   Simplify goals to the SPARQL runtime functions before they are
 1686%   handed to the general optimizer and runtime evaluation.
 1687
 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).
 1695
 1696
 1697%!  simplify_true(+Expr, -Goal) is semidet.
 1698%
 1699%   Simplify a boolean expression  resulting   from  a SPARQL FILTER
 1700%   statement. Ideally, this should be   a simple partial evaluation
 1701%   of sparql_true/1.
 1702
 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(_)).
 1752
 1753%!  simplify_test(+Expr0, -Expr) is det.
 1754%
 1755%   Perform analysis on specific tests.   Currently  optimizes regex
 1756%   tests.
 1757
 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).
 1764
 1765%!  simplify_eval(+Expr, +Value, -Goal) is semidet.
 1766
 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                 *******************************/
 1786
 1787%!  sparql_subquery(+Proj, :Query, +Solutions) is nondet.
 1788%
 1789%   Execute a SPARQL subquery.
 1790%
 1791%   @param  Proj is a list of variables that are shared with the
 1792%           outer query.
 1793%   @tbd    Call the optimizer.
 1794%   @tbd    Sub queries must be evaluated before the outer query,
 1795%           so we must move them to the head of the query
 1796%           evaluation.  Not doing so causes no harm, but leads
 1797%           to repetitive execution of the subquery.
 1798
 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                 *******************************/
 1819
 1820%!  sparql_update(:Updates) is det.
 1821%
 1822%   Handle SPARQL update requests.
 1823%
 1824%   @tbd    Realise authorization rules
 1825
 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).
 1881
 1882%!  insert_triple(+Graph, +Triple) is det.
 1883
 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).
 1894
 1895%!  delete_triple(+Graph, +Triple) is det.
 1896%
 1897%   Delete matching triples
 1898
 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).
 1908
 1909%!  delete_triples(+Graph:atom, +SimpleTriplePattern:compound) is det.
 1910
 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    ).
 1948
 1949%!  graph(+Spec, -Graph)
 1950
 1951graph(G:L, Graph) :-
 1952    atom(G),
 1953    !,
 1954    (   integer(L)
 1955    ->  Graph = (G:L)
 1956    ;   Graph = G
 1957    ).
 1958graph(G, G).
 1959
 1960%!  clear_db(+Clear)
 1961%
 1962%   Note that CLEAR ALL cannot use rdf_reset_db  because we are in a
 1963%   transaction.
 1964
 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)