1598 lines
35 KiB
Prolog
1598 lines
35 KiB
Prolog
/*
|
|
|
|
----
|
|
This file is part of SECONDO.
|
|
|
|
Copyright (C) 2012, University Hagen, Faculty of Mathematics and
|
|
Computer Science, Database Systems for New Applications.
|
|
|
|
SECONDO is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
SECONDO is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with SECONDO; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
----
|
|
|
|
//paragraph [10] title: [{\Large \bf ] [}]
|
|
//characters [1] formula: [$] [$]
|
|
//[ae] [\"{a}]
|
|
//[oe] [\"{o}]
|
|
//[ue] [\"{u}]
|
|
//[ss] [{\ss}]
|
|
//[Ae] [\"{A}]
|
|
//[Oe] [\"{O}]
|
|
//[Ue] [\"{U}]
|
|
//[**] [$**$]
|
|
//[star] [$*$]
|
|
//[->] [$\rightarrow$]
|
|
//[toc] [\tableofcontents]
|
|
//[=>] [\verb+=>+]
|
|
//[newpage] [\newpage]
|
|
//[_] [\_]
|
|
|
|
|
|
|
|
|
|
[10] Predicates for Large Query Optimization Algorithm ~Query Graph Decomposition and Materialization (QGDM)~
|
|
|
|
|
|
By Gero Willmes, January 2012
|
|
|
|
Implementations for my master thesis
|
|
|
|
|
|
|
|
|
|
[newpage]
|
|
|
|
[toc]
|
|
|
|
[newpage]
|
|
|
|
*/
|
|
|
|
|
|
/*
|
|
|
|
1 Predicates for Large Query Optimization Algorithm ~Query Graph Decomposition and Materialization (QGDM)~
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
1.1 qgdm
|
|
|
|
*/
|
|
|
|
/*
|
|
---- qgdm(+Query, -Stream2, -Select2, -Update, -Cost)
|
|
----
|
|
|
|
Description:
|
|
|
|
Main predicate which does the translation of a large predicate set query
|
|
using query graph decomposition and materializing (qgdm).
|
|
The signature is identical to translate1/5.
|
|
|
|
By Gero Willmes
|
|
|
|
Input:
|
|
|
|
~Query~: Query of Type 'select Args from Rels where Preds'
|
|
|
|
Output:
|
|
|
|
~Stream2~: Plan
|
|
|
|
~Select2~: Arguments of the select clause
|
|
|
|
~Update~: Update clause
|
|
|
|
~Cost~: Cost of the Plan
|
|
|
|
*/
|
|
|
|
qgdm(Select from Rels where Preds, Stream2, Select2, Update, Cost) :-
|
|
not( optimizerOption(immediatePlan) ),
|
|
not( optimizerOption(intOrders(_)) ),
|
|
set_prolog_flag(unknown, warning),
|
|
nl,nl,
|
|
write('Large predicate set optimization using query graph decomposition '),
|
|
write('and materializing (qgdm)'),nl,
|
|
|
|
%create query graph:
|
|
qgcreateNodeList(Rels,QGNodeList),
|
|
retractall(qgEdgeGlobal(_,_,_,_,_,_, _)),
|
|
createQGEdges(Preds,Rels,QGEdgeList),!,
|
|
|
|
initResultCost,
|
|
setRels(Rels),
|
|
setSelect(Select),
|
|
setMaxEdgesPerComponent(7),
|
|
|
|
%create spanning tree:
|
|
nl,write('Start Kruskal...'),
|
|
kruskal(QGEdgeList,QGNodeList,_, _ /*RemovedEdgeList*/, Stream),!,
|
|
nl,write('Kruskal finished'),
|
|
writeComponents,
|
|
resultCost(Cost),
|
|
|
|
splitSelect(Select, Select02, Update),
|
|
% Hook for CSE substitution
|
|
rewritePlanforCSE(Stream, Stream2, Select02, Select2),
|
|
!.
|
|
|
|
/*
|
|
|
|
1.2 completesCycle
|
|
|
|
*/
|
|
|
|
/*
|
|
---- completesCycle(+A,+B,+SpanTree)
|
|
----
|
|
|
|
Description:
|
|
|
|
Succeeds if the edge (A, B) completes a cycle in the ~SpanTree~
|
|
|
|
Input:
|
|
|
|
~A~: Node number
|
|
|
|
~B~: Node number
|
|
|
|
~SpanTree~: list of span tree edges
|
|
|
|
*/
|
|
|
|
%selection edges build a cycle in the query graph :
|
|
completesCycle(A,A,_).
|
|
|
|
%join edges build a cycle if there is already
|
|
%an existing path from A to B:
|
|
completesCycle(A,B,SpanTree):-
|
|
length(SpanTree,L),
|
|
L > 0,
|
|
A =\= B,
|
|
existsPath(A,B,SpanTree).
|
|
|
|
|
|
%there is no cycle if the spanning tree is empty
|
|
completesCycle(A,B,[]):-
|
|
A =\= B,
|
|
!,fail.
|
|
|
|
/*
|
|
|
|
1.3 completesCycle
|
|
|
|
*/
|
|
|
|
/*
|
|
---- completesCycle(+X, +SpanTree)
|
|
----
|
|
|
|
Description:
|
|
|
|
Succeeds if the edge ~X~ completes a cycle in the ~SpanTree~
|
|
~X~ must be of type qgEdge([_], A,B,[_], [_],[_],[_])
|
|
|
|
Input:
|
|
|
|
~X~: query graph edge of type qgEdge([_], A,B,[_], [_],[_],[_])
|
|
|
|
~SpanTree~: list of span tree edges
|
|
|
|
*/
|
|
|
|
completesCycle(X,SpanTree):-
|
|
X = qgEdge(_, A,B,_, _,_,_),!,
|
|
completesCycle(A,B,SpanTree).
|
|
|
|
|
|
:- dynamic selectionpredicate/1.
|
|
|
|
/*
|
|
|
|
1.4 kruskal
|
|
|
|
*/
|
|
|
|
/*
|
|
---- kruskal(+QGEdgeList,+QGNodeList,-SpanTree,-RemovedEdgeList, -Stream)
|
|
----
|
|
|
|
Description:
|
|
|
|
Extended kruskal algorithm
|
|
|
|
Input:
|
|
|
|
~QGEdgeList~: Edges of a query graph
|
|
|
|
~QGNodeList~: Nodes of a query graph
|
|
|
|
|
|
Output:
|
|
|
|
~SpanTree~: Edges of the minimum spanning tree calculated from the edges of the query graph
|
|
|
|
~RemovedEdgeList~: Edges which are member of the query graph but not member of the minimum spanning tree
|
|
|
|
~Stream~: Plan
|
|
|
|
*/
|
|
|
|
kruskal(QGEdgeList,QGNodeList,SpanTree,RemovedEdgeList, Stream):-
|
|
retractall(component(nodes(_),edges(_),_)),
|
|
retractall(selectionpredicate(_)),
|
|
retractall(notoptimizededge(_)),
|
|
retractall(mcomponent(_,_)),
|
|
retractall(map(_,_)),
|
|
|
|
splitEdges(QGEdgeList, JoinEdges, SelectionEdges),
|
|
globalizeSelectionPredicates(SelectionEdges),
|
|
|
|
nl,write('Create components...'),
|
|
createComponents(QGNodeList,_),!,
|
|
nl,write('Components created.'),
|
|
|
|
quicksort(JoinEdges, QGEdgeListSorted),!,
|
|
|
|
nl,write('Start Kruskal2...'),
|
|
kruskal2(QGEdgeListSorted,[], SpanTree,RemovedEdgeList),!,
|
|
nl,write('Kruskal2 finished.'),
|
|
|
|
writeComponents,
|
|
|
|
nl,write('Optimize all remaining components...'),
|
|
optimizeAllRemainingComponents,
|
|
nl,write('All remaining components are optimized.'),
|
|
|
|
nl,write('Materialize all components...'),
|
|
getTime((materializeAllComponents), Time),
|
|
nl,write('All components are materialized.'),
|
|
|
|
nl,write('Optimize all remaining edges...'),
|
|
optimizeAllRemainingEdges(RemovedEdgeList),
|
|
nl,write('All remaining edges optimized.'),
|
|
|
|
findall(Plan, component(nodes(_),edges(_),Plan),
|
|
ComponentList),
|
|
length(ComponentList, L),
|
|
nl,write('kruskal: '), write(L),
|
|
write(' resulting component(s)'),nl,
|
|
nl,write('Time for materializing all Components: '),
|
|
TimeInSeconds is Time/1000, write(TimeInSeconds), write(' seconds.'),
|
|
|
|
ComponentList = [Head|_],
|
|
Stream = Head.
|
|
|
|
/*
|
|
|
|
1.5 kruskal2
|
|
|
|
*/
|
|
|
|
/*
|
|
---- kruskal2(+QGEdgeList,+AkkSpanTree,-SpanTree,-RemovedEdgeList)
|
|
----
|
|
|
|
Description:
|
|
|
|
kruskal algorithm
|
|
|
|
Input:
|
|
|
|
~QGEdgeList~: Edges of a query graph
|
|
|
|
~AkkSpanTree~: Akkumulator for the spanning tree edges
|
|
|
|
Output:
|
|
|
|
~SpanTree~: Edges of the minimum spanning tree calculated from the edges of the query graph
|
|
|
|
~RemovedEdgeList~: Edges which are member of the query graph but not member of the minimum spanning tree
|
|
|
|
~Stream~: Plan
|
|
|
|
*/
|
|
|
|
kruskal2([],Akk, Akk,[]).
|
|
|
|
kruskal2([MaxSpanEdge|EdgeList], AkkSpanTree, SpanTree,
|
|
RemovedEdgeList):-
|
|
\+completesCycle(MaxSpanEdge,AkkSpanTree),!,
|
|
kruskal2(EdgeList,[MaxSpanEdge|AkkSpanTree], SpanTree,
|
|
RemovedEdgeList),!,
|
|
reoptimize(MaxSpanEdge).
|
|
|
|
kruskal2([MaxEdge|EdgeList],AkkSpanTree, SpanTree,
|
|
[MaxEdge|RemovedEdgeList]):-
|
|
completesCycle(MaxEdge,AkkSpanTree),!,
|
|
kruskal2(EdgeList,AkkSpanTree, SpanTree, RemovedEdgeList).
|
|
|
|
/*
|
|
|
|
1.6 extractSelectionPrecicates
|
|
|
|
*/
|
|
|
|
/*
|
|
---- extractSelectionPrecicates(+QGNode, -SelectionPredicates)
|
|
----
|
|
|
|
Description:
|
|
Retrieves all selection predicates for the specified query graph node ~QGNode~
|
|
|
|
*/
|
|
|
|
extractSelectionPredicates(QGNode, SelectionPredicates):-
|
|
QGNode = qgNode(NodeNumber,_,_),
|
|
findall(qgEdge(Pred, NodeNumber, NodeNumber, Plan, Size, Cost, Sel),
|
|
selectionpredicate(qgEdge(Pred, NodeNumber, NodeNumber,
|
|
Plan, Size, Cost, Sel)), SelectionPredicates),
|
|
findall(selectionpredicate(qgEdge(Pred, NodeNumber, NodeNumber,
|
|
Plan, Size, Cost, Sel)),
|
|
selectionpredicate(qgEdge(Pred, NodeNumber, NodeNumber,
|
|
Plan, Size, Cost, Sel)), SelectionPredicates2),
|
|
removeSelectionPredicates(SelectionPredicates2).
|
|
|
|
/*
|
|
|
|
1.7 firstNElements
|
|
|
|
*/
|
|
|
|
/*
|
|
---- firstNElements(+N, +InList, -OutList)
|
|
----
|
|
|
|
Description:
|
|
|
|
returns the first n elements of the list ~InList~ as ~OutList~
|
|
|
|
*/
|
|
|
|
firstNElements(N, InList, OutList):-
|
|
length(OutList, N),
|
|
append(OutList, _, InList).
|
|
|
|
/*
|
|
|
|
1.8 removeSelectionPredicates
|
|
|
|
*/
|
|
|
|
/*
|
|
---- removeSelectionPredicates(+List)
|
|
----
|
|
|
|
Description:
|
|
|
|
All global facts which correlate with the terms in ~List~ are removed.
|
|
~List~ elements must be of type 'selectionpredicate(qgEdge(Pred, NodeNo, NodeNo, Plan, Size, Cost, Sel))'
|
|
|
|
*/
|
|
removeSelectionPredicates([]).
|
|
removeSelectionPredicates([H|Rest]):-
|
|
H = selectionpredicate(qgEdge(_, NodeNo, NodeNo, _, _, _, _)),
|
|
retract(H),
|
|
removeSelectionPredicates(Rest).
|
|
|
|
/*
|
|
|
|
1.9 globalizeSelectionPredicates
|
|
|
|
*/
|
|
|
|
/*
|
|
---- globalizeSelectionPredicates(+QGEdgeList)
|
|
----
|
|
|
|
Description:
|
|
|
|
Creates global facts of type 'selectiopredicate(QGEdge)' from a list of query graph edges ~QGEdgeList~
|
|
~QGEdgeList~ elements must be of type 'qgEdge([_], NodeNumber, NodeNumber, [_], [_], [_], [_])'.
|
|
|
|
*/
|
|
|
|
globalizeSelectionPredicates([]).
|
|
globalizeSelectionPredicates([H|Rest]):-
|
|
H = qgEdge(_, NodeNumber, NodeNumber, _, _, _, _),
|
|
assert(selectionpredicate(H)),
|
|
globalizeSelectionPredicates(Rest).
|
|
|
|
qgedgeList2predList([], []).
|
|
qgedgeList2predList([qgEdge(Pred,_,_,_,_,_,_)|RestEdges], [Pred|RestPreds]):-
|
|
qgedgeList2predList(RestEdges, RestPreds).
|
|
|
|
/*
|
|
|
|
1.10 createComponents
|
|
|
|
*/
|
|
|
|
/*
|
|
---- createComponents(+QGNodeList,-ComponentList)
|
|
----
|
|
|
|
Description:
|
|
|
|
Creates a list of components ~ComponentList~ from a list of query graph nodes ~QGNodeList~.
|
|
A single component is a structure of type "component(nodes(QGNodeList), edges(QGEdgeList), Plan)".
|
|
Initially each component only has a single QGNode in its QGNodeList.
|
|
|
|
Input:
|
|
|
|
~QGNodeList~: List of query graph nodes
|
|
|
|
Output:
|
|
|
|
~ComponentList~: List of components
|
|
|
|
*/
|
|
|
|
createComponents([],[]).
|
|
|
|
createComponents([QGNode|QGNodeList],
|
|
[component(nodes([QGNode]), edges([]), Plan)|ComponentList]):-
|
|
QGNode = qgNode(_,rel(_,_),_),
|
|
Plan = 0,
|
|
extractSelectionPredicates(QGNode, SelectionPredicates),
|
|
assert(component(nodes([QGNode]),
|
|
edges(SelectionPredicates), Plan)),
|
|
createComponents(QGNodeList, ComponentList).
|
|
|
|
/*
|
|
|
|
1.11 reoptimize
|
|
|
|
*/
|
|
|
|
/*
|
|
---- reoptimize(+SpanEdge)
|
|
----
|
|
|
|
Description:
|
|
|
|
Retrieves the joinable Components and joins them. Two Components are joinable if they contain either the Source Node or the Target Node of the ~SpanEdge~
|
|
|
|
Input:
|
|
|
|
~SpanEdge~: Spanning tree edge
|
|
|
|
*/
|
|
|
|
reoptimize(SpanEdge):-
|
|
joinableComponents(SpanEdge, Component1, Component2),!,
|
|
joinComponents(SpanEdge, Component1, Component2).
|
|
|
|
/*
|
|
|
|
1.12 joinComponents
|
|
|
|
*/
|
|
|
|
/*
|
|
---- joinComponents(+SpanEdge, +Component1, +Component2)
|
|
----
|
|
|
|
Description:
|
|
|
|
Joins the components ~Component1~ and ~Component2~ to a new Component.
|
|
|
|
Input:
|
|
|
|
~SpanEdge~: Spanning tree edge
|
|
|
|
~Component1~: Joinable Component
|
|
|
|
~Component2~: Joinable Component
|
|
|
|
*/
|
|
|
|
joinComponents(SpanEdge, Component1, Component2):-
|
|
Component1 = component(nodes(NodeList1),edges(EdgeList1), Plan1),
|
|
Component2 = component(nodes(NodeList2),edges(EdgeList2),Plan2),
|
|
|
|
length(EdgeList1,EL1),
|
|
length(EdgeList2,EL2),
|
|
EL3 is EL1 + EL2,
|
|
getMaxEdgesPerComponent(Max),
|
|
EL3 +1 < Max,
|
|
|
|
append(EdgeList1, EdgeList2, JoinedEdgeList),
|
|
append(JoinedEdgeList, [SpanEdge], NewJoinedEdgeList),
|
|
|
|
%Add nodes:
|
|
append(NodeList1, NodeList2, JoinedNodeList),
|
|
|
|
%remove old components and save new component:
|
|
retract(component(nodes(NodeList1),edges(EdgeList1), Plan1)),
|
|
retract(component(nodes(NodeList2),edges(EdgeList2), Plan2)),
|
|
assert(component(nodes(JoinedNodeList), edges(NewJoinedEdgeList), 0)).
|
|
|
|
|
|
joinComponents(SpanEdge, Component1, Component2):-
|
|
Component1 = component(nodes(NodeList1),edges(EdgeList1), Plan1),
|
|
Component2 = component(nodes(NodeList2),edges(EdgeList2),Plan2),
|
|
|
|
length(EdgeList1,EL1),
|
|
length(EdgeList2,EL2),
|
|
EL3 is EL1 + EL2,
|
|
getMaxEdgesPerComponent(Max),
|
|
EL3 +1 =:= Max,
|
|
|
|
nl,write('Build resulting component of maximal size.'),
|
|
|
|
append(EdgeList1, EdgeList2, JoinedEdgeList),
|
|
append(JoinedEdgeList, [SpanEdge], NewJoinedEdgeList),
|
|
|
|
append(NodeList1, NodeList2, JoinedNodeList),
|
|
|
|
qgedgeList2predList(EdgeList1, PredList1),
|
|
qgedgeList2predList(EdgeList2, PredList2),
|
|
SpanEdge = qgEdge(Pred, _, _, _, _,_,_),
|
|
|
|
append(PredList1, PredList2, PredList3),
|
|
append(PredList3, [Pred], Preds),
|
|
|
|
getSelect(Select),
|
|
getRels(Rels),
|
|
|
|
Query = (Select from Rels where Preds),
|
|
translate(Query, Stream, _, _, Cost),
|
|
removePredinfos(Stream, NewJoinedEdgeList, ResultPlan, _, Stream),
|
|
incResultCost(Cost),
|
|
|
|
%remove old components and save new component:
|
|
retract(component(nodes(NodeList1),edges(EdgeList1), Plan1)),
|
|
retract(component(nodes(NodeList2),edges(EdgeList2), Plan2)),
|
|
assert(component(nodes(JoinedNodeList), edges(NewJoinedEdgeList),
|
|
ResultPlan)).
|
|
|
|
|
|
|
|
joinComponents(SpanEdge, Component1, Component2):-
|
|
Component1 = component(nodes(_),edges(EdgeList1),_),
|
|
Component2 = component(nodes(_),edges(EdgeList2),_),
|
|
|
|
length(EdgeList1,EL1),
|
|
length(EdgeList2,EL2),
|
|
EL3 is EL1 + EL2,
|
|
getMaxEdgesPerComponent(Max),
|
|
EL3 +1 > Max,
|
|
nl,write('Merging both components would cause a too large '),
|
|
write('resulting component. Optimize the bigger one ...'),
|
|
|
|
compareComponents(Component1, Component2, LargerComponent,_),
|
|
LargerComponent = component(nodes(NodeListLarger),
|
|
edges(EdgeListLarger),PlanLarger),
|
|
|
|
PlanLarger = 0,
|
|
|
|
largerList(EdgeList1, EdgeList2, LargerEdgeList),
|
|
qgedgeList2predList(LargerEdgeList, Preds),
|
|
|
|
getSelect(Select),
|
|
getRels(Rels),
|
|
|
|
Query = (Select from Rels where Preds),
|
|
translate(Query, Stream, _, _, Cost),
|
|
removePredinfos(Stream, LargerEdgeList, ResultPlan, _, Stream),
|
|
incResultCost(Cost),
|
|
|
|
%remove old components and save new component:
|
|
retract(LargerComponent),
|
|
assert(component(nodes(NodeListLarger),edges(EdgeListLarger),ResultPlan)),
|
|
|
|
%the SpanEdge was not optimized here, i.e. must be saved:
|
|
assert(notoptimizededge(SpanEdge)),
|
|
nl,write('Finished optimizing the bigger component.').
|
|
|
|
|
|
joinComponents(SpanEdge, Component1, Component2):-
|
|
Component1 = component(nodes(_),edges(EdgeList1),_),
|
|
Component2 = component(nodes(_),edges(EdgeList2),_),
|
|
|
|
length(EdgeList1,EL1),
|
|
length(EdgeList2,EL2),
|
|
EL3 is EL1 + EL2,
|
|
getMaxEdgesPerComponent(Max),
|
|
EL3 +1 > Max,
|
|
|
|
compareComponents(Component1, Component2, LargerComponent,_),
|
|
LargerComponent = component(nodes(_),edges(_),PlanLarger),
|
|
PlanLarger \= 0,
|
|
%the SpanEdge was not optimized here, i.e. must be saved:
|
|
assert(notoptimizededge(SpanEdge)).
|
|
|
|
/*
|
|
|
|
1.13 optimizeAllRemainingEdges
|
|
|
|
*/
|
|
|
|
/*
|
|
---- optimizeAllRemainingEdges(+NonSpanningEdgeList)
|
|
----
|
|
|
|
Description:
|
|
|
|
Optimizes all non spanning edges and all query graph edges which were not optimized yet.
|
|
Therefore the materialized components are used and a query over them is generated.
|
|
|
|
*/
|
|
optimizeAllRemainingEdges(NonSpanningEdges):-
|
|
findall(qgEdge(Pred,_,_,_,_,_,_),
|
|
notoptimizededge(qgEdge(Pred,_,_,_,_,_,_)), NotOptimizedEdges),
|
|
length(NotOptimizedEdges, NumberEdges),
|
|
length(NonSpanningEdges, NumberNonSpanningEdges),
|
|
getAllTemporaryRelNames(TemporaryRelNames),
|
|
length(TemporaryRelNames, NumberTempRels),
|
|
nl, write('Number of temporary relations: '),
|
|
write(NumberTempRels),
|
|
NumberOfRemainingEdges is NumberEdges + NumberNonSpanningEdges,
|
|
nl, write('Number of remaining edges to be optimized: '),
|
|
write(NumberOfRemainingEdges),
|
|
|
|
NumberOfRemainingEdges =< 10,
|
|
|
|
qgedgeList2predList(NotOptimizedEdges, NotOptimizedPreds1),
|
|
qgedgeList2predList(NonSpanningEdges, NotOptimizedPreds2),
|
|
append(NotOptimizedPreds1, NotOptimizedPreds2, NotOptimizedPreds),
|
|
nl, write('NotOptimizedPreds: '), write(NotOptimizedPreds),
|
|
getExternalPredNames(NotOptimizedPreds, PredsExternal),
|
|
|
|
getQuery(Query),
|
|
Query = (select Args from _ where _),
|
|
mapAttributes(PredsExternal, MappedPredsExternal),
|
|
NewQuery = (select Args from TemporaryRelNames where MappedPredsExternal),
|
|
%nl,write('New Query: '), write(NewQuery),
|
|
|
|
%this is done in predicate 'optimize/3'
|
|
retractall(removefilter(_)),
|
|
rewriteQuery(NewQuery, NewQueryR),
|
|
callLookup(NewQueryR, NewQuery2), !,
|
|
%nl,write('New Query2: '), write(NewQuery2),
|
|
translate(NewQuery2, Stream, _,_,Cost),
|
|
append(NotOptimizedEdges, NonSpanningEdges, AllNotOptimizedEdges),
|
|
removePredinfos(Stream, AllNotOptimizedEdges, ResultPlan, _, Stream),
|
|
%substituteTempRels(StreamWithoutPredInfo, TemporaryRelNames, ResultPlan),
|
|
incResultCost(Cost),
|
|
retractall(component(_,_,_)),
|
|
assert(component(nodes([]), edges([]), ResultPlan)),
|
|
retractall(notoptimizededge(_)),
|
|
!.
|
|
|
|
optimizeAllRemainingEdges(NonSpanningEdges):-
|
|
findall(qgEdge(Pred,_,_,_,_,_,_),
|
|
notoptimizededge(qgEdge(Pred,_,_,_,_,_,_)), NotOptimizedEdges),
|
|
length(NotOptimizedEdges, NumberEdges),
|
|
length(NonSpanningEdges, NumberNonSpanningEdges),
|
|
getAllTemporaryRelNames(TemporaryRelNames),
|
|
length(TemporaryRelNames, NumberTempRels),
|
|
nl, write('Number of temporary relations: '),write(NumberTempRels),
|
|
NumberOfRemainingEdges is NumberEdges + NumberNonSpanningEdges,
|
|
nl, write('Number of remaining edges to be optimized: '),
|
|
write(NumberOfRemainingEdges),
|
|
|
|
NumberOfRemainingEdges > 10,
|
|
|
|
qgedgeList2predList(NotOptimizedEdges, NotOptimizedPreds1),
|
|
qgedgeList2predList(NonSpanningEdges, NotOptimizedPreds2),
|
|
|
|
append(NotOptimizedPreds1, NotOptimizedPreds2, NotOptimizedPreds),
|
|
getExternalPredNames(NotOptimizedPreds, PredsExternal),
|
|
|
|
getQuery(Query),
|
|
Query = (select Args from _ where _),
|
|
mapAttributes(PredsExternal, MappedPredsExternal),
|
|
NewQuery = (select Args from TemporaryRelNames where MappedPredsExternal),
|
|
|
|
|
|
%this is done in predicate 'optimize/3'
|
|
retractall(removefilter(_)),
|
|
rewriteQuery(NewQuery, NewQueryR),
|
|
callLookup(NewQueryR, NewQuery2), !,
|
|
qgdm(NewQuery2, _, _,_,_),
|
|
!.
|
|
|
|
/*
|
|
|
|
1.14 optimizeAllRemainingComponents
|
|
|
|
*/
|
|
|
|
/*
|
|
---- optimizeAllRemainingComponents
|
|
----
|
|
|
|
Description:
|
|
|
|
Generates sub plans for all components which are not optimized yet.
|
|
A component of type 'component(nodes(QGNodes), edges(QGEdges), Plan)'
|
|
is considered as optimized if Plan is different from 0.
|
|
A component 'component(nodes(QGNodes), edges(QGEdges), 0)' is not considered as optimized.
|
|
|
|
*/
|
|
optimizeAllRemainingComponents:-
|
|
findall(component(nodes(QGNodes), edges(QGEdges), _),
|
|
component(nodes(QGNodes), edges(QGEdges), 0),
|
|
NotOptimizedComponentList),
|
|
length(NotOptimizedComponentList,Number),
|
|
nl,write(Number),
|
|
write(' remaining components have to be optimized...'),
|
|
optimizeRemainingComponents(NotOptimizedComponentList).
|
|
|
|
/*
|
|
|
|
1.15 optimizeRemainingComponents
|
|
|
|
*/
|
|
|
|
/*
|
|
---- optimizeRemainingComponents(+ComponentList)
|
|
----
|
|
|
|
Description:
|
|
|
|
Optimizes all components passed in the list ~ComponentList~
|
|
|
|
*/
|
|
optimizeRemainingComponents([]).
|
|
optimizeRemainingComponents([H|Rest]):-
|
|
nl,write('Optimize remaining component...'),
|
|
optimizeRemainingComponent(H),
|
|
nl,write('Finished optimizing remaining component.'),
|
|
optimizeRemainingComponents(Rest).
|
|
|
|
/*
|
|
|
|
1.16 optimizeRemainingComponent
|
|
|
|
*/
|
|
|
|
/*
|
|
---- optimizeRemainingComponent(+Component)
|
|
----
|
|
|
|
Description:
|
|
|
|
Optimizes the ~Component~ of tye 'component(nodes(QGNodes), edges(QGEdges), 0)'.
|
|
QGNodes is a list of query graph nodes. QGEdges is a list of query graph edges.
|
|
Optimizing means generating a sub plan for QGEdges. Finally the component is asserted as a global fact.
|
|
|
|
*/
|
|
|
|
optimizeRemainingComponent(Component):-
|
|
Component = component(nodes(NodeList),edges(EdgeList),_),
|
|
length(EdgeList,NumberEdges),
|
|
NumberEdges > 0,
|
|
qgedgeList2predList(EdgeList, Preds),
|
|
|
|
getSelect(Select),
|
|
getRels(Rels),
|
|
|
|
Query = (Select from Rels where Preds),
|
|
length(Preds, PL),
|
|
nl, write(PL), write(' Predicates in the query.'),
|
|
translate(Query, Stream, _, _, Cost),
|
|
removePredinfos(Stream, EdgeList, ResultPlan, _, Stream),
|
|
incResultCost(Cost),
|
|
|
|
%remove old components and save new component:
|
|
retract(Component),
|
|
assert(component(nodes(NodeList),edges(EdgeList),ResultPlan)).
|
|
|
|
optimizeRemainingComponent(Component):-
|
|
Component = component(nodes(NodeList),edges(EdgeList),0),
|
|
length(EdgeList,NumberEdges),
|
|
NumberEdges = 0,
|
|
NodeList = [QGNode],
|
|
QGNode = qgNode(_,rel(X,Y),_),
|
|
argument(N, rel(X,Y)),
|
|
arg(N) => Plan,
|
|
%remove old components and save new component:
|
|
retract(Component),
|
|
assert(component(nodes(NodeList),edges(EdgeList),Plan)).
|
|
|
|
/*
|
|
|
|
1.17 materializeAllComponents
|
|
|
|
*/
|
|
|
|
/*
|
|
---- materializeAllComponents
|
|
----
|
|
|
|
Description:
|
|
Materializes all components
|
|
|
|
*/
|
|
materializeAllComponents:-
|
|
findall(component(nodes(QGNodes), edges(QGEdges), Plan),
|
|
component(nodes(QGNodes), edges(QGEdges), Plan),ComponentList),
|
|
length(ComponentList,Number),
|
|
nl,write(Number),write(' components have to be materialized...'),
|
|
materializeComponents(ComponentList).
|
|
|
|
/*
|
|
|
|
1.18 materializeComponents
|
|
|
|
*/
|
|
|
|
/*
|
|
---- materializeComponents(+ComponentList)
|
|
----
|
|
|
|
Description:
|
|
|
|
Materializes all components passed in the list ~ComponentList~
|
|
|
|
*/
|
|
materializeComponents([]).
|
|
materializeComponents([H|Rest]):-
|
|
nl,write('Materialize one component...'),
|
|
materializeComponent(H),
|
|
nl,write('Finished materializing one component.'),
|
|
materializeComponents(Rest).
|
|
|
|
/* Special case: Component with 1 node and no edges:*/
|
|
materializeComponent(Component):-
|
|
Component = component(nodes(NodeList),edges(Edges),_),
|
|
length(NodeList, NumberNodes),
|
|
NumberNodes =:= 1,
|
|
length(Edges, NumberEdges),
|
|
NumberEdges =:= 0,
|
|
NodeList = [qgNode(_, rel(RelName,*),_)|_],
|
|
createRelationNameMap(NodeList,RelName),
|
|
assert(mcomponent(Component, relname(RelName))).
|
|
|
|
/* Special case: Component with 1 node and no edges and Alias Name:*/
|
|
materializeComponent(Component):-
|
|
Component = component(nodes(NodeList),edges(Edges),_),
|
|
length(NodeList, NumberNodes),
|
|
NumberNodes =:= 1,
|
|
length(Edges, NumberEdges),
|
|
NumberEdges =:= 0,
|
|
NodeList = [qgNode(_, rel(RelName,Alias),_)|_],
|
|
createRelationNameMap(NodeList,RelName as Alias),
|
|
assert(mcomponent(Component, relname(RelName as Alias))).
|
|
|
|
|
|
materializeComponent(Component):-
|
|
Component = component(nodes(NodeList),edges(_),Plan),
|
|
plan_to_atom(Plan, Atom),
|
|
newTempRel(X),
|
|
my_concat_atom(['let ', X, ' = ', Atom, ' consume '],'', Command),
|
|
nl,write('Command: '),write(Command),
|
|
secondo(Command),
|
|
|
|
card(X, CardX),
|
|
(CardX < 50 ->
|
|
createSamples(X, CardX, CardX);true),
|
|
|
|
createRelationNameMap(NodeList,X),
|
|
assert(mcomponent(Component, relname(X))).
|
|
|
|
createRelationNameMap([],_).
|
|
createRelationNameMap([QGNode|RestQGNodes],NewRelName):-
|
|
QGNode = qgNode(_,rel(A,_),_),
|
|
assert(map(A,NewRelName)),
|
|
createRelationNameMap(RestQGNodes, NewRelName).
|
|
|
|
|
|
getAllTemporaryRelNames(TempRelNames):-
|
|
findall(X, mcomponent(_, relname(X)), TempRelNames).
|
|
|
|
|
|
deleteAllTemporaryRelations:-
|
|
getAllTemporaryRelNames(TempRelNames),
|
|
nl,write('These temporary relations have to be deleted: '),
|
|
write(TempRelNames),
|
|
deleteTemporaryRelations(TempRelNames),
|
|
dropTempRels,
|
|
deleteTempRels.
|
|
|
|
|
|
deleteTemporaryRelations([]).
|
|
deleteTemporaryRelations([H|Rest]):-
|
|
drop_relation(H),
|
|
retractall(mcomponent(_,relname(H))),
|
|
deleteTemporaryRelations(Rest).
|
|
|
|
/*
|
|
|
|
1.19 largerList
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- largerList(+L1, +L2, -LLarger)
|
|
----
|
|
|
|
Description:
|
|
|
|
Returns the larger list ~LLarger~ of the two input lists
|
|
~L1~ and ~L2~.
|
|
|
|
*/
|
|
largerList(L1, L2, LLarger):-
|
|
length(L1, Length1),
|
|
length(L2, Length2),
|
|
Length1 > Length2,
|
|
LLarger = L1.
|
|
|
|
largerList(L1, L2, LLarger):-
|
|
length(L1, Length1),
|
|
length(L2, Length2),
|
|
Length1 =< Length2,
|
|
LLarger = L2.
|
|
|
|
/*
|
|
|
|
1.20 compareComponents
|
|
|
|
*/
|
|
|
|
/*
|
|
---- compareComponents(+C1, +C2, -CLarger, -CSmaller)
|
|
----
|
|
|
|
Description:
|
|
|
|
Returns the larger component ~CLarger~ and the smaller ~CSmaller~ of the two input components
|
|
~C1~ and ~C2~. Larger means that there are more query graph edges in the component
|
|
|
|
*/
|
|
compareComponents(C1, C2, CLarger, CSmaller):-
|
|
C1 = component(nodes(_),edges(EdgeList1), _),
|
|
C2 = component(nodes(_),edges(EdgeList2),_),
|
|
largerList(EdgeList1, EdgeList2, LargerEdgeList),
|
|
LargerEdgeList = EdgeList1,
|
|
CLarger = C1,
|
|
CSmaller = C2.
|
|
|
|
compareComponents(C1, C2, CLarger, CSmaller):-
|
|
C1 = component(nodes(_),edges(EdgeList1), _),
|
|
C2 = component(nodes(_),edges(EdgeList2),_),
|
|
largerList(EdgeList1, EdgeList2, LargerEdgeList),
|
|
LargerEdgeList = EdgeList2,
|
|
CLarger = C2,
|
|
CSmaller = C1.
|
|
|
|
/*
|
|
|
|
1.21 isIncidentEdgeToA
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- isIncidentEdgeToA(+SpanEdge, -Component)
|
|
----
|
|
|
|
Description:
|
|
|
|
A spanning tree edge is always incident to two components.
|
|
This predicate determines the first (or left) component to which an edge is incident.
|
|
|
|
Input:
|
|
|
|
~SpanEdge~: Spanning tree edge
|
|
|
|
Output:
|
|
|
|
~Component~: First (or left) incident Component
|
|
|
|
*/
|
|
|
|
isIncidentEdgeToA(SpanEdge, Component):-
|
|
SpanEdge = qgEdge(_, A,_,_, _,_,_),
|
|
member(qgNode(A,_,_), QGNodes),
|
|
component(nodes(QGNodes), edges(QGEdges),Plan),
|
|
Component = component(nodes(QGNodes), edges(QGEdges),Plan).
|
|
|
|
/*
|
|
|
|
1.22 isIncidentEdgeToB
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- isIncidentEdgeToB(+SpanEdge, -Component)
|
|
----
|
|
|
|
Description:
|
|
|
|
A spanning tree edge is always incident to two components.
|
|
This predicate determines the second (or right) component to which an edge is incident.
|
|
|
|
Input:
|
|
|
|
~SpanEdge~: Spanning tree edge
|
|
|
|
Output:
|
|
|
|
~Component~: Second (or right) incident Component
|
|
|
|
*/
|
|
|
|
isIncidentEdgeToB(SpanEdge, Component):-
|
|
SpanEdge = qgEdge(_, _,B,_, _,_,_),
|
|
member(qgNode(B,_,_), QGNodes),
|
|
component(nodes(QGNodes), edges(QGEdges), Plan),
|
|
Component = component(nodes(QGNodes), edges(QGEdges),Plan).
|
|
|
|
/*
|
|
|
|
1.23 joinableComponents
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- joinableComponents(+SpanEdge, -Component1, -Component2)
|
|
----
|
|
|
|
Description:
|
|
|
|
A spanning tree edge is always incident to two components.
|
|
This predicate determines the two components to which an edge is incident.
|
|
|
|
Input:
|
|
|
|
~SpanEdge~: Spanning tree edge
|
|
|
|
Output:
|
|
|
|
~Component1~: First (or left) incident Component
|
|
|
|
~Component2~: Second (or right) incident Component
|
|
|
|
*/
|
|
|
|
joinableComponents(SpanEdge, Component1, Component2):-
|
|
isIncidentEdgeToA(SpanEdge, Component1),
|
|
isIncidentEdgeToB(SpanEdge, Component2).
|
|
|
|
/*
|
|
|
|
1.24 countComponents
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- countComponents(-N)
|
|
----
|
|
|
|
Description:
|
|
|
|
Counts the number of global facts of type "component(nodes(QGNodes), Plan)"
|
|
|
|
Output:
|
|
|
|
~N~: Number of global facts of type "component(nodes(QGNodes),edges(QGEdges), Plan)"
|
|
|
|
*/
|
|
|
|
countComponents(N):-
|
|
findall(component(nodes(QGNodes), Plan),
|
|
component(nodes(QGNodes), edges(_),Plan), List),!,
|
|
length(List, N).
|
|
|
|
/*
|
|
|
|
1.25 reoptimizePlan
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- reoptimizePlan(+Plan1, +Plan2, +SpanEdge, -OptimizedPlan)
|
|
----
|
|
|
|
Description:
|
|
|
|
Calculates a new plan ~OptimizedPlan~ from ~Plan1~, ~Plan2~ and ~SpanEdge~
|
|
|
|
Input:
|
|
|
|
~Plan1~: First input plan
|
|
|
|
~Plan2~: Second input plan
|
|
|
|
~SpanEdge~: Spanning tree edge
|
|
|
|
Output:
|
|
|
|
~OptimizedPlan~: Resulting plan
|
|
|
|
*/
|
|
|
|
|
|
reoptimizePlan(Plan1, Plan2, SpanEdge, OptimizedPlan):-
|
|
SpanEdge = qgEdge(Pred,_,_,_,_,_,_),
|
|
join(Plan1, Plan2, Pred) => OptimizedPlan.
|
|
|
|
|
|
reoptimizePlan(Plan1, Plan2, SpanEdge, OptimizedPlan):-
|
|
SpanEdge = qgEdge(Pred,_,_,_,_,_,_),
|
|
%use standard join:
|
|
OptimizedPlan = symmjoin(Plan1, Plan2, Pred).
|
|
|
|
/*
|
|
|
|
1.26 splitEdges
|
|
|
|
*/
|
|
|
|
/*
|
|
---- splitEdges(+Edges, -JoinEdges, -SelectionEdges)
|
|
----
|
|
|
|
Description:
|
|
|
|
Splits a list of query graph edges ~Edges~ into 2 lists:
|
|
join edges ~JoinEdges~ and seleciton edges ~SelectionEdges~
|
|
|
|
*/
|
|
splitEdges(Edges, JoinEdges, SelectionEdges):-
|
|
splitEdges2(Edges, JoinEdges, SelectionEdges).
|
|
|
|
splitEdges2([], [], []).
|
|
|
|
splitEdges2([H|RestEdges],Joins, [H|RestSelections]):-
|
|
H = qgEdge(_,Source, Source,_,_,_,_),
|
|
splitEdges2(RestEdges, Joins,RestSelections).
|
|
|
|
splitEdges2([H|RestEdges],[H|RestJoins], Selections):-
|
|
H = qgEdge(_,Source, Target,_,_,_,_),
|
|
Source =\= Target,
|
|
splitEdges2(RestEdges, RestJoins, Selections).
|
|
|
|
/*
|
|
|
|
1.27 mapRelationNames
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- mapRelationNames(+QGEdgeList, -QGEdgeListTemp)
|
|
----
|
|
|
|
Description:
|
|
|
|
Maps all relation names of the input list of query graph edges ~QGEdge~ to temporary relation names
|
|
|
|
Input:
|
|
|
|
~QGedgeList~: List of query graph edges
|
|
|
|
Output:
|
|
|
|
~QGEdgeListTemp~: list of query graph edges with temporary relation names
|
|
|
|
*/
|
|
|
|
mapRelationNames([],[]).
|
|
|
|
mapRelationNames([QGEdge|RestEdges], [QGEdgeTemp|RestTempEdges]):-
|
|
mapRelationName(QGEdge, QGEdgeTemp),
|
|
mapRelationNames(RestEdges, RestTempEdges).
|
|
|
|
/*
|
|
|
|
1.28 mapRelationName
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- mapRelationName(+QGEdge, -QGEdgeTemp)
|
|
----
|
|
|
|
Description:
|
|
|
|
Replaces the relationnames in a query graph edge
|
|
qgEdge(pr(P, rel(A,[_]), rel(B,[_])), [_], [_], [_],[_], [_],[_]),
|
|
by the temporary relation name
|
|
|
|
Input:
|
|
|
|
~QGEdge~: Input query graph edge with relation names
|
|
|
|
Output:
|
|
|
|
~QGEdgeTemp~: query graph edge with temporary relation names
|
|
|
|
*/
|
|
|
|
mapRelationName(TermFragment, NewTermFragment) :-
|
|
TermFragment = pr(P, rel(A,_), rel(B,_)),
|
|
map(A, TempA),
|
|
map(B, TempB),
|
|
NewTermFragment = pr(P, rel(TempA,*), rel(TempB,*)),!.
|
|
|
|
mapRelationName(Term, Term2) :-
|
|
compound(Term), !,
|
|
Term =.. [Functor | Args],
|
|
embeddedmapRelationName(Args, Args2),
|
|
Term2 =.. [Functor | Args2].
|
|
|
|
mapRelationName(Term, Term).
|
|
|
|
embeddedmapRelationName([], []).
|
|
|
|
embeddedmapRelationName([Arg | Args], [Arg2 | Args2]) :-
|
|
mapRelationName(Arg, Arg2),
|
|
embeddedmapRelationName(Args, Args2).
|
|
|
|
|
|
:-dynamic resultCost/1.
|
|
incResultCost(Inc):-
|
|
resultCost(Old),
|
|
retractall(resultCost(_)),!,
|
|
New is Old+Inc,
|
|
asserta(resultCost(New)).
|
|
|
|
initResultCost:-
|
|
retractall(resultCost(_)),!,
|
|
asserta(resultCost(0)).
|
|
|
|
:-dynamic getSelect/1.
|
|
setSelect(Select):-
|
|
retractall(getSelect(_)),!,
|
|
asserta(getSelect(Select)).
|
|
|
|
:-dynamic getRels/1.
|
|
setRels(Rels):-
|
|
retractall(getRels(_)),!,
|
|
asserta(getRels(Rels)).
|
|
|
|
:-dynamic getMaxEdgesPerComponent/1.
|
|
setMaxEdgesPerComponent(Max):-
|
|
retractall(getMaxEdgesPerComponent(_)),!,
|
|
asserta(getMaxEdgesPerComponent(Max)).
|
|
|
|
:-dynamic getQuery/1.
|
|
setQuery(Query):-
|
|
retractall(getQuery(_)),!,
|
|
asserta(getQuery(Query)).
|
|
|
|
createPredicateMap(PredsExternal, PredsInternal):-
|
|
retractall(predmap(_,_)),
|
|
makeList(PredsExternal, PEList),
|
|
makeList(PredsInternal, PIList),
|
|
createPredicateMap2(PEList, PIList).
|
|
|
|
createPredicateMap2([],[]).
|
|
createPredicateMap2([PE|RestE],[PI|RestI]):-
|
|
assert(predmap(PE,PI)),
|
|
createPredicateMap2(RestE,RestI).
|
|
|
|
getExternalPredName(PredInternal, PredExternal):-
|
|
predmap(PredExternal, PredInternal).
|
|
|
|
getExternalPredNames([],[]).
|
|
getExternalPredNames([PI|RestI],[PE|RestE]):-
|
|
getExternalPredName(PI, PE),
|
|
getExternalPredNames(RestI, RestE).
|
|
|
|
/*
|
|
|
|
1.29 removePredinfos
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- removePredinfos(+Plan, +EdgeList, -ResultPlan, -ResultCost, +RawPlan)
|
|
----
|
|
|
|
Description:
|
|
|
|
Removes all predinfo(...) terms from ~Plan~ and returns a ~ResultPlan~ without predinfo(...) terms.
|
|
|
|
Input:
|
|
|
|
~Plan~: Input plan
|
|
|
|
~EdgeList~: join edges which are member of the spanning tree
|
|
|
|
~RawPlan~: Plan without any cost information (required by the cost/5 predicate to calculate the predicate cost within the term)
|
|
|
|
Output:
|
|
|
|
~ResultPlan~: Resulting plan
|
|
|
|
~ResultCost~: Resulting cost
|
|
|
|
*/
|
|
|
|
removePredinfos(Plan, EdgeList, ResultPlan, ResultCost, RawPlan):-
|
|
removePredinfos2(Plan, EdgeList, ResultPlan, RawPlan),
|
|
resultCost(ResultCost).
|
|
|
|
removePredinfos2(Plan, [], Plan,_).
|
|
|
|
removePredinfos2(AkkPlan, EdgeList, ResultPlan, RawPlan):-
|
|
EdgeList = [H|Rest],
|
|
removePredinfo(AkkPlan, NewPlan, RawPlan, H, _),
|
|
removePredinfos2(NewPlan, Rest, ResultPlan, RawPlan).
|
|
|
|
/*
|
|
|
|
1.30 removePredinfo
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- removePredinfo(+PlanFragment, +NewPlanFragment, +RawPlan, +Edge, -Cost)
|
|
----
|
|
Description:
|
|
|
|
Removes a predinfo(...) term from ~PlanFragment~ and returns a new new plan fragment ~NewPlanFragment~ without predinfo(...) term.
|
|
|
|
Input:
|
|
|
|
~Plan~: Input plan
|
|
|
|
~Edge~: join edge which is member of the spanning tree
|
|
|
|
~RawPlan~: Plan without any cost information (required by the cost/5 predicate to calculate the predicate cost within the term)
|
|
|
|
Output:
|
|
|
|
~NewPlanFragment~: Resulting plan
|
|
|
|
~Cost~: Resulting cost
|
|
|
|
*/
|
|
|
|
removePredinfo(PlanFragment, NewPlanFragment, _, _, _) :-
|
|
PlanFragment = predinfo(Plan, _, _),
|
|
NewPlanFragment = Plan,
|
|
!.
|
|
|
|
removePredinfo(Term, Term2,RawPlan,Edge, _) :-
|
|
compound(Term), !,
|
|
Term =.. [Functor | Args],
|
|
embeddedPredinfo(Args, Args2, RawPlan, Edge,_),
|
|
Term2 =.. [Functor | Args2].
|
|
|
|
|
|
removePredinfo(Term, Term,_, _,_).
|
|
|
|
embeddedPredinfo([], [],_,_,_).
|
|
|
|
embeddedPredinfo([Arg | Args], [Arg2 | Args2], RawPlan,Edge,_) :-
|
|
removePredinfo(Arg, Arg2,RawPlan,Edge, _),
|
|
embeddedPredinfo(Args, Args2, RawPlan,Edge, _).
|
|
|
|
/*
|
|
|
|
1.31 substituteTempRels
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- substituteTempRels(+Plan, +TempRelList, -ResultPlan)
|
|
----
|
|
|
|
Description:
|
|
|
|
Substitutes all temporary relations by the plan from mcomponent(component([_],[_],Plan), relname(X))
|
|
|
|
Input:
|
|
|
|
~Plan~: Input plan which contains temporary relation names.
|
|
|
|
~TempRelList~: list of temporary relnames
|
|
|
|
Output:
|
|
|
|
~ResultPlan~: Resulting plan tat contains no temporary rel names but plans
|
|
|
|
*/
|
|
|
|
|
|
substituteTempRels(Plan, TempRelList, ResultPlan):-
|
|
substituteTempRels2(Plan, TempRelList, ResultPlan).
|
|
|
|
substituteTempRels2(Plan, [], Plan).
|
|
|
|
substituteTempRels2(AkkPlan, TempRelList, ResultPlan):-
|
|
TempRelList = [H|Rest],
|
|
substituteTempRel(AkkPlan, NewPlan,H),
|
|
substituteTempRels2(NewPlan, Rest, ResultPlan).
|
|
|
|
/*
|
|
|
|
1.32 substituteTempRel
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- substituteTempRel(+PlanFragment, -NewPlanFragment, +TempRelName)
|
|
----
|
|
|
|
Description:
|
|
|
|
Substitutes a temporary relation name by the plan from mcomponent(component([_],[_],Plan), relname(X))
|
|
|
|
Input:
|
|
|
|
~PlanFragment~: Input plan
|
|
|
|
~TempRelName~: temporary relation name to be replaced by the plan
|
|
|
|
Output:
|
|
|
|
~NewPlanFragment~: Resulting plan fragement that contains no temporary rel name but plan.
|
|
|
|
*/
|
|
|
|
substituteTempRel(PlanFragment, NewPlanFragment, TempRelName) :-
|
|
PlanFragment = feedproject(rel(TempRelName,*),_),
|
|
mcomponent(component(_,_,Plan), relname(TempRelName)),
|
|
NewPlanFragment = Plan.
|
|
|
|
|
|
substituteTempRel(Term, Term2,TempRelName) :-
|
|
compound(Term), !,
|
|
Term =.. [Functor | Args],
|
|
embeddedsubstituteTempRel(Args, Args2, TempRelName),
|
|
Term2 =.. [Functor | Args2].
|
|
|
|
|
|
substituteTempRel(Term, Term,_).
|
|
|
|
embeddedsubstituteTempRel([], [],_).
|
|
|
|
embeddedsubstituteTempRel([Arg | Args], [Arg2 | Args2], TempRelName) :-
|
|
substituteTempRel(Arg, Arg2,TempRelName),
|
|
embeddedsubstituteTempRel(Args, Args2,TempRelName).
|
|
|
|
|
|
/*
|
|
|
|
1.33 mapAttributes
|
|
|
|
*/
|
|
|
|
|
|
/*
|
|
|
|
---- mapAttributes(+Preds,-MappedPreds)
|
|
----
|
|
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
Description
|
|
|
|
Maps all predicates in ~Preds~ to materialized names
|
|
(e.g. p5:plz = p6:plz [*] 2 is mapped to plz\_p5=plz\_p6 [*] 2)
|
|
This is neccessary because in temporary relations the attribute
|
|
names are changed when table alias names are used in the query
|
|
|
|
Input
|
|
|
|
~Preds~ Predicate List
|
|
|
|
Output
|
|
|
|
~MappedPreds~ Mapped Predicates
|
|
|
|
|
|
*/
|
|
|
|
mapAttributes([],[]).
|
|
|
|
mapAttributes([Attribute|Rest], [MappedAttribute|Rest2]):-
|
|
mapAttribute(Attribute, MappedAttribute),
|
|
mapAttributes(Rest, Rest2).
|
|
|
|
|
|
/*
|
|
|
|
1.34 mapAttribute
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
---- mapAttribute(-Predicate, +MappedPredicate)
|
|
----
|
|
|
|
Description:
|
|
|
|
Replaces an attribute of type <Alias>:<Column>
|
|
by <Column>[_]<Alias> in the Predicate
|
|
|
|
Input:
|
|
|
|
~Predicate~: Predicate
|
|
|
|
Output:
|
|
|
|
~MappedPredicate~: Predicate with mapped attribute names
|
|
|
|
|
|
*/
|
|
|
|
mapAttribute(Attribute, MappedAttribute) :-
|
|
Attribute = A:B,
|
|
|
|
map2Attribute(A:B, MappedAttribute),
|
|
!.
|
|
|
|
mapAttribute(Term, Term2) :-
|
|
compound(Term), !,
|
|
Term =.. [Functor | Args],
|
|
embeddedmapAttribute(Args, Args2),
|
|
Term2 =.. [Functor | Args2].
|
|
|
|
|
|
mapAttribute(Term, Term).
|
|
|
|
embeddedmapAttribute([], []).
|
|
|
|
embeddedmapAttribute([Arg | Args], [Arg2 | Args2]) :-
|
|
mapAttribute(Arg, Arg2),
|
|
embeddedmapAttribute(Args, Args2).
|
|
|
|
|
|
:-dynamic(component/3).
|
|
|
|
/*
|
|
|
|
if a component exists, which contains just a single node,
|
|
then the attribute name is not mapped
|
|
(because it was not physically materialized and
|
|
the attribute names did not change)
|
|
|
|
*/
|
|
|
|
map2Attribute(Attribute, MappedAttribute):-
|
|
Attribute = Alias:_,
|
|
findall(_, component(nodes([qgNode(_,rel(_,Alias),_)]),
|
|
edges(_),_), List),
|
|
length(List,1),
|
|
MappedAttribute = Attribute.
|
|
|
|
/*
|
|
|
|
in all other cases the attribute is mapped:
|
|
|
|
*/
|
|
|
|
map2Attribute(Attribute, MappedAttribute):-
|
|
Attribute = Alias:Column,
|
|
plan_to_atom(a(Alias:Column,_,l),MappedAttribute).
|
|
|