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( , , , , ), 71 sparql_minus( , ), 72 sparql_group( ), 73 sparql_group( , , ), 74 sparql_subquery( , , ), 75 sparql_update( ).
85:- thread_local
86 bnode_store/2.
93sparql_true(Term) :- 94 typed_eval(boolean, Term, Result), 95 !, 96 true(Result). 97 98true(boolean(true)).
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
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)).
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)).
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)).
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].
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).
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 *******************************/
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) }.
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,_)).
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).
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).
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).
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).
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 ).
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).
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), !.
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 ).
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 ).
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:
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).
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).
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).
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 *******************************/
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).
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 ).
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 *******************************/
1130not(true, false). 1131not(false, true). 1132not(error, error).
1139bound(X) :- nonvar(X).
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).
1177lang(lang(Lang,_), Lang) :- !. 1178lang(string(_), ''). 1179lang(simple_literal(_), ''). 1180lang(type(_,_), ''). 1181lang(numeric(_,_), '').
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).
1204sparql_and(true, true, true) :- !. 1205sparql_and(true, error, error) :- !. 1206sparql_and(error, true, error) :- !. 1207sparql_and(_, _, false).
1211sparql_or(true, _, true) :- !. 1212sparql_or(_, true, true) :- !. 1213sparql_or(false, false, false) :- !. 1214sparql_or(_, _, error).
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)).
1257regex(String, Pattern, '') :- 1258 !, 1259 re_match(Pattern, String). 1260regex(String, Pattern, Flags) :- 1261 re_match(Pattern/Flags, String).
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)).
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
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)).
1334compiled_regex(@(Regex), String) :-
1335 send(@(Regex), search, string(String)).
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
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)).
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]).
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).
1423is_rdf(IRI) :- atom(IRI). 1424is_rdf(Var) :- var(Var), !, fail. 1425is_rdf(literal(_)). 1426 1427 1428 /******************************* 1429 * PROPERTY PATH SUPPORT * 1430 *******************************/
We should be a bit smarter here and choose between forward, backward, two-sided breath-first, etc. based on which start point is given.
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).
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).
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).
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).
MINUS
. This is defined to
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 -> 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 *******************************/
1585sparql_group(Goal) :-
1586 call(Goal).
1593sparql_group(Goal, OuterVars, InnerVars) :- 1594 call(Goal), 1595 OuterVars = InnerVars. 1596 1597 1598 /******************************* 1599 * SERVICE * 1600 *******************************/
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 *******************************/
1675sparql_reset_bnodes :- 1676 retractall(bnode_store(_,_)). 1677 1678 1679 /******************************* 1680 * SIMPLIFY * 1681 *******************************/
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).
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(_)).
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).
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 *******************************/
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 *******************************/
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).
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).
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).
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 ).
1951graph(G:L, Graph) :- 1952 atom(G), 1953 !, 1954 ( integer(L) 1955 -> Graph = (G:L) 1956 ; Graph = G 1957 ). 1958graph(G, G).
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)
SPARQL runtime support
rdfql_runtime.pl
merges this module with generic predicates as well as runtime libraries for other query languages.../entailment/README.txt
*/