1/* Part of SWISH 2 3 Author: Jan Wielemaker 4 E-mail: J.Wielemaker@cs.vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (C): 2017, VU University Amsterdam 7 CWI 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(swish_projection, 37 [ projection/1 38 ]). 39:- use_module(library(lists)). 40:- use_module(library(apply)). 41:- use_module(library(debug)). 42:- use_module(library(error)).
53:- multifile 54 reserved_var/1. % +VarName
asc
, desc
Var:ascending
Var:descending
If ordering is specified for multiple variables, the result set is ordered starting with the left-most variable for which ordering is defined.
89projection(_). 90 91swishgoal_expansion((Projection,Body), Aggregate) :- 92 nonvar(Projection), 93 Projection = projection(Spec), 94 must_be(list, Spec), 95 aggregation(Spec, Vars, Body, Aggregate), 96 !, 97 ignore(set_projection(Vars)). 98swishgoal_expansion(projection(Vars), true) :- 99 set_projection(Vars). 100 101set_projection(Vars) :- 102 nb_current('$variable_names', Bindings), 103 debug(projection, 'Got ~p; Asking ~p', [Bindings, Vars]), 104 preverse_vars(Bindings, NewVars, SelectedBindings), 105 maplist(select_binding(Bindings), Vars, SelectedBindings), 106 debug(projection, 'Filtered ~p', [NewVars]), 107 b_setval('$variable_names', NewVars).
115preverse_vars([], L, L). 116preverse_vars([Name=Var|T0], [Name=Var|T], L) :- 117 reserved_var(Name), 118 !, 119 preverse_vars(T0, T, L). 120preverse_vars([_|T0], T, L) :- 121 preverse_vars(T0, T, L). 122 123reserved_var('_residuals'). 124reserved_var('_swish__permahash'). 125 126select_binding(Bindings, Var, Name=Var) :- 127 member(Name=X, Bindings), 128 Var == X, 129 !.
136aggregation(Projection, Vars, Goal0, Goal) :- 137 modifiers(Projection, Vars, Unique, Order), 138 munique(Unique, Goal0, Goal1), 139 morder(Order, Goal1, Goal). 140 141munique([], Goal, Goal) :- 142 !. 143munique(Vars, Goal0, distinct(Term, Goal0)) :- 144 Term =.. [v|Vars]. 145 146morder([], Goal, Goal) :- 147 !. 148morder(Vars, Goal0, order_by(Vars, Goal0)). 149 150modifiers(Projection, Vars, Unique, Order) :- 151 phrase(annotations(Projection, Vars), Annot), 152 Annot \== [], 153 partition(unique_anot, Annot, Unique, Order). 154 155unique_anot(distinct(_)). 156 157annotations([], []) --> 158 []. 159annotations([H|T], [V|VT]) --> 160 annotations1(H, V), 161 annotations(T, VT). 162 163annotations1(V, V) --> {var(V)}, !. 164annotations1(+V, V) --> !, [asc(V)]. 165annotations1(-V, V) --> !, [desc(V)]. 166annotations1(V:Ann, V) --> !, var_annotations(Ann, V). 167annotations1(V, V) --> []. 168 169var_annotations(Var, _) --> {var(Var), instantiation_error(Var)}. 170var_annotations(A+B, V) --> !, var_annotations(A,V), var_annotations(B,V). 171var_annotations(Anot, V) --> 172 { var_annotation(Anot, Can), 173 Term =.. [Can,V] 174 }, 175 [ Term ]. 176 177var_annotation(Anot, Cann) :- 178 var_anot1(Anot, Cann), 179 !, 180 ( var_anot1(Anot, Cann2), 181 Cann \== Cann2 182 -> domain_error(projection_annotation, Anot) 183 ; true 184 ). 185var_annotation(Anot, _Cann) :- 186 domain_error(projection_annotation, Anot). 187 188var_anot1(Anot, Cann) :- 189 var_annot(Long, Cann), 190 sub_atom(Long, 0, _, _, Anot). 191 192var_annot(ascending, asc). 193var_annot(descending, desc). 194var_annot(distinct, distinct). 195 196:- multifile sandbox:safe_primitive/1. 197 198sandbox:safe_primitive(swish_projection:projection(_))
Define the projection
This module redefines variables that are included in the SWISH result set.