home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.prolog
- Path: sparky!uunet!spool.mu.edu!yale.edu!ira.uka.de!fauern!lrz-muenchen.de!mac_server.cis.uni-muenchen.de!user
- From: draxler@cis.uni-muenchen.de (Christoph Draxler)
- Subject: Prolog to SQL compiler v.1.1 (part 1/2)
- Message-ID: <draxler-221292134855@mac_server.cis.uni-muenchen.de>
- Followup-To: comp.lang.prolog
- Sender: news@news.lrz-muenchen.de (Mr. News)
- Organization: CIS - Centrum fuer Informations- und Sprachverarbeitung
- Date: Tue, 22 Dec 1992 12:47:04 GMT
- Lines: 905
-
- Here it is, just before Christmas: a new version of the Prolog to SQL
- compiler.
-
- New features include:
-
- - a rudimentary type system for consistency checks for comparison
- operations and quoted output of constant strings
-
- - SQL queries may be output on the screen or returned as Prolog atoms
-
- Have fun with the compiler (and note: there`s a report with tons of
- benchmarks available). I am eager to know of your experiences with the
- compiler, so please send me any comments, criticism et al!
-
-
- Christoph Draxler
- University of Munich
- draxler@cis.uni-muenchen.de
-
-
- --- CODE BEGINS HERE
- -----------------------------------------------------------
-
-
-
- %
- --------------------------------------------------------------------------------------
- %
- % This Prolog to SQL compiler may be distributed free of charge provided
- that it is
- % not used in commercial applications without written consent of the
- author, and
- % that the copyright notice remains unchanged.
- %
- % (C) Copyright by Christoph Draxler, Munich
- % Version 1.1 of Dec. 21st 1992
- %
- % I would like to keep in my hands the further development and distribution
- of the
- % compiler. This does not mean that I don't want other people to suggest or
- even
- % implement improvements - quite on the contrary: I greatly appreciate
- contributions
- % and if they make sense to me I will incorporate them into the compiler
- (with due
- % credits given!).
- %
- % For further development of the compiler, address your requests, comments
- and
- % criticism to the author:
- %
- % Christoph Draxler
- % CIS Centre for Information and Speech Processing
- % Ludwig-Maximilians-University Munich
- % Leopoldstr. 139
- % D 8000 Munich 40
- % Tel : ++49 / +89 / 36 40 72
- % Fax : ++49 / +89 / 361 61 99
- % Mail: draxler@cis.uni-muenchen.de
- %
- %
- % A report describing the implementation is available upon request from the
- % author.
- %
- %
- % RELEASE INFORMATION
- % ===================
- %
- % Current version is v. 1.1 of Dec. 21st 1992.
- %
- % - The compiler now features a rudimentary type system (to check the
- validity of
- % comparison operations and to quote strings in the output.
- % - Furthermore, the compiler now also returns the SQL query as a Prolog
- atom
- % (but may conflict with the maximum length limits for atom names). SQL
- queries
- % as atoms are needed in some DB-Interfaces of Prolog.
- %
- % Version 1.0 Sept. 3 1992
- %
- --------------------------------------------------------------------------------------
-
-
-
-
-
-
-
-
- %
- --------------------------------------------------------------------------------------
- %
- % Top level predicate translate/3 organizes the compilation and constructs
- a
- % Prolog term representation of the SQL query.
- %
- %
- --------------------------------------------------------------------------------------
-
-
- translate(ProjectionTerm,DatabaseGoal,SQLQueryTerm):-
- % --- initialize variable identifiers and range variables for relations
- -----
- init_gensym(var),
- init_gensym(rel),
-
- % --- tokenize projection term and database goal
- ----------------------------
- tokenize_term(DatabaseGoal,TokenDatabaseGoal),
- tokenize_term(ProjectionTerm,TokenProjectionTerm),
-
- % --- lexical analysis: reordering of goals for disjunctive normalized
- form -
- disjunction(TokenDatabaseGoal,Disjunction),
-
- % --- code generation
- ---------------------------------------------------------------
- query_generation(Disjunction,TokenProjectionTerm,SQLQueryTerm).
-
-
-
-
-
- % --- disjunction(Goal,Disjunction)
- ----------------------------------------------------
- %
- % turns original goal into disjunctive normalized form by computing all
- conjunctions
- % and collecting them in a list
- %
- %
- --------------------------------------------------------------------------------------
-
- disjunction(Goal,Disjunction):-
- findall(Conjunction,linearize(Goal,Conjunction),Disjunction).
-
-
-
-
- % --- linearize(Goal,ConjunctionList)
- --------------------------------------------------
- %
- % Returns a conjunction of base goals for a complex disjunctive or
- conjunctive goal
- % Yields several solutions upon backtracking for disjunctive goals
- %
- %
- --------------------------------------------------------------------------------------
-
- linearize(((A,B),C),(LinA,(LinB,LinC))):-
- % --- transform left-linear to right-linear conjunction (',' is
- associative) ----
- linearize(A,LinA),
- linearize(B,LinB),
- linearize(C,LinC).
-
- linearize((A,B),(LinA,LinB)):-
- A \= (_,_),
- % --- make sure A is not a conjunction
- ------------------------------------------
- linearize(A,LinA),
- linearize(B,LinB).
-
- linearize((A;B),LinA):-
- linearize(A,LinA).
-
- linearize((A;B),LinB):-
- linearize(B,LinB).
-
- linearize(not A, not LinA):-
- linearize(A,LinA).
-
- linearize(Var^A, Var^LinA):-
- linearize(A,LinA).
-
- linearize(A,A):-
- A \= (_,_),
- A \= (_;_),
- A \= _^_,
- A \= not(_).
-
-
-
-
- % --- tokenize_term(Term,TokenizedTerm)
- -------------------------------------------------
- %
- % If Term is a
- %
- % - variable, then this variable is instantiated with a unique identifier
- % of the form var(VarId), and TokenizedTerm is bound to the same term
- var(VarId).
- %
- % - constant, then TokenizedTerm is bound to const(Term).
- %
- % - complex term, then the term is decomposed, its arguments are
- tokenized,
- % and TokenizedTerm is bound to the result of the composition of the
- original
- % functor and the tokenized arguments.
- %
- %
- --------------------------------------------------------------------------------------
-
- tokenize_term(var(VarId),var(VarId)):-
- var(VarId),
- % --- uninstantiated variable: instantiate it with unique identifier.
- gensym(var,VarId).
-
- tokenize_term(var(VarId),var(VarId)):-
- nonvar(VarId).
-
- tokenize_term(Constant,const(Constant)):-
- nonvar(Constant),
- functor(Constant,_,0).
-
- tokenize_term(Term,TokenizedTerm):-
- nonvar(Term),
- Term \= var(_),
- Term \= const(_),
- Term =.. [Functor|Arguments],
- Arguments \= [],
- tokenize_arguments(Arguments,TokenArguments),
- TokenizedTerm =.. [Functor|TokenArguments].
-
-
-
- % --- tokenize_arguments(Arguments,TokenizedArguments)
- ---------------------------------
- %
- % organizes tokenization of arguments by traversing list and calling
- tokenize_term
- % for each element of the list.
- %
- %
- --------------------------------------------------------------------------------------
-
- tokenize_arguments([],[]).
-
- tokenize_arguments([FirstArg|RestArgs],[TokFirstArg|TokRestArgs]):-
- tokenize_term(FirstArg,TokFirstArg),
- tokenize_arguments(RestArgs,TokRestArgs).
-
-
-
-
-
-
-
- % --- query_generation(ListOfConjunctions, ProjectionTerm, ListOfQueries)
- --------------
- %
- % For each Conjunction translate the pair (ProjectionTerm,Conjunction) to
- an SQL query
- % and connect each such query through a UNION-operator to result in the
- ListOfQueries.
- %
- % A Conjunction consists of positive or negative subgoals. Each subgoal is
- translated
- % as follows:
- % - the functor of a goal that is not a comparison operation is translated
- to
- % a relation name with a range variable
- % - negated goals are translated to NOT EXISTS-subqueries with *
- projection
- % - comparison operations are translated to comparison operations in the
- WHERE-clause
- % - aggregate function terms are translated to aggregate function
- (sub)queries
- %
- % The arguments of a goal are translated as follows:
- % - variables of a goal are translated to qualified attributes
- % - variables occurring in several goals are translated to equality
- comparisons
- % (equi join) in the WHERE-clause
- % - constant arguments are translated to equality comparisons in the
- WHERE-clause
- %
- % Special treatment of arithmetic functions:
- % - arithmetic functions are identified through the Prolog is/2 operator
- % - an arithmetic function may contain an unbound variable only on its
- left side
- % - the right side of the is/2 operator may consist of
- % * bound variables (bound through occurrence within a positive database
- goal, or
- % bound through preceeding arithmetic function), or of
- % * constants (numbers, i.e. integers, reals)
- %
- % The following RESTRICTION holds:
- %
- % - the binding of variables follows Prolog: variables are bound by
- positive base goals
- % and on the left side of the is/2 predicate - comparison operations,
- negated goals
- % and right sides of the is/2 predicate do not return variable bindings
- and may even
- % require all arguments to be bound for a safe evaluation.
- %
- %
- --------------------------------------------------------------------------------------
-
- query_generation([],_,[]).
-
- query_generation([Conjunction|Conjunctions],ProjectionTerm,[Query|Queries]):-
- projection_term_variables(ProjectionTerm,InitDict),
- translate_conjunction(Conjunction,SQLFrom,SQLWhere,InitDict,Dict),
- translate_projection(ProjectionTerm,Dict,SQLSelect),
- Query = query(SQLSelect,SQLFrom,SQLWhere),
- query_generation(Conjunctions,ProjectionTerm,Queries).
-
-
-
- % --- translate_goal(Goal,SQLFrom,SQLWhere,Dict,NewDict)
- -------------------------------
- %
- % translates a
- %
- % - positive database goal to the associated FROM- and WHERE clause of an
- SQL query
- % - a negated goal to a negated existential subquery
- % - an arithmetic goal to an arithmetic expression or an aggregate
- function query
- % - a comparison goal to a comparison expression
- % - a negated comparison goal to a comparison expression with the
- opposite comparison
- % operator
- %
- %
- --------------------------------------------------------------------------------------
-
- translate_goal(SimpleGoal,[SQLFrom],SQLWhere,Dict,NewDict):-
- % --- positive goal binds variables - these bindings are held in the
- dictionary -----
- functor(SimpleGoal,Functor,Arity),
- translate_functor(Functor,Arity,SQLFrom),
- SimpleGoal =.. [Functor|Arguments],
- translate_arguments(Arguments,SQLFrom,1,SQLWhere,Dict,NewDict).
-
- translate_goal(Result is Expression,[],SQLWhere,Dict,NewDict):-
- translate_arithmetic_function(Result,Expression,SQLWhere,Dict,NewDict).
-
- translate_goal(not NegatedGoals,[],SQLNegatedSubquery,Dict,Dict):-
- % --- negated goals do not bind variables - hence Dict is returned
- unchanged --------
- functor(NegatedGoals,Functor,_),
- not comparison(Functor,_),
- translate_conjunction(NegatedGoals,SQLFrom,SQLWhere,Dict,_),
- SQLNegatedSubquery =
- [negated_existential_subquery([*],SQLFrom,SQLWhere)].
-
- translate_goal(not ComparisonGoal,[],SQLCompOp,Dict,Dict):-
- % --- comparison operations do not bind variables - Dict is returned
- unchanged ------
- ComparisonGoal =.. [ComparisonOperator,LeftArg,RightArg],
- comparison(ComparisonOperator,SQLOperator),
- negated_comparison(SQLOperator,SQLNegOperator),
- translate_comparison(LeftArg,RightArg,SQLNegOperator,Dict,SQLCompOp).
-
- translate_goal(ComparisonGoal,[],SQLCompOp,Dict,Dict):-
- % --- comparison operations do not bind variables - Dict is returned
- unchanged ------
- ComparisonGoal =.. [ComparisonOperator,LeftArg,RightArg],
- comparison(ComparisonOperator,SQLOperator),
- translate_comparison(LeftArg,RightArg,SQLOperator,Dict,SQLCompOp).
-
-
-
-
- % --- translate_conjunction(Conjunction,SQLFrom,SQLWhere,Dict,NewDict)
- -----------------
- %
- % translates a conjunction of goals (represented as a list of goals
- preceeded by
- % existentially quantified variables) to FROM- and WHERE-clause of an SQL
- query.
- % A dictionary containing the associated SQL table and attribute names is
- built up
- % as an accumulator pair (arguments Dict and NewDict)
- %
- %
- --------------------------------------------------------------------------------------
-
- translate_conjunction(var(VarId)^Goal,SQLFrom,SQLWhere,Dict,NewDict):-
- % --- add info on existentially quantified variables to dictionary here
- -------------
- add_to_dictionary(VarId,_,_,_,existential,Dict,TmpDict),
- translate_conjunction(Goal,SQLFrom,SQLWhere,TmpDict,NewDict).
-
- translate_conjunction(Goal,SQLFrom,SQLWhere,Dict,NewDict):-
- Goal \= (_,_),
- translate_goal(Goal,SQLFrom,SQLWhere,Dict,NewDict).
-
- translate_conjunction((Goal,Conjunction),SQLFrom,SQLWhere,Dict,NewDict):-
- translate_goal(Goal,FromBegin,WhereBegin,Dict,TmpDict),
- translate_conjunction(Conjunction,FromRest,WhereRest,TmpDict,NewDict),
- append(FromBegin,FromRest,SQLFrom),
- append(WhereBegin,WhereRest,SQLWhere).
-
-
-
-
-
- % ---
- translate_arithmetic_function(Result,Expression,SQLWhere,Dict,NewDict)
- -----------
- %
- % Arithmetic functions (left side of is/2 operator is bound to value of
- expression on
- % right side) may be called with either
- %
- % - Result unbound: then Result is bound to the value of the evaluation of
- Expression
- % - Result bound: then an equality condition is returned between the value
- of Result
- % and the value of the evaluation of Expression.
- %
- % Only the equality test shows up in the WHERE clause of an SQLquery.
- %
- %
- --------------------------------------------------------------------------------------
-
- translate_arithmetic_function(var(VarId),Expression,[],Dict,NewDict):-
- % assigment of value of arithmetic expression to variable - does not
- % show up in WHERE-part, but expression corresponding to
- % variable must be stored in Dict for projection translation
-
- evaluable_expression(Expression,Dict,ArithExpression,Type),
- add_to_dictionary(VarId,is,ArithExpression,Type,all,Dict,NewDict).
-
-
- translate_arithmetic_function(var(VarId),Expression,ArithComparison,Dict,Dict):-
- % --- test whether left side evaluates to right side: return equality
- comparison ----
- % Left side consists of qualified attribute, i.e. range variable must
- not be
- % arithmetic operator is/2
-
- lookup(VarId,Dict,PrevRangeVar,PrevAtt,PrevType),
- not (PrevRangeVar = is),
-
- % test whether type of attribute is numeric - if not, there's no sense
- in
- % continuing the translation
-
- type_compatible(PrevType,number),
- evaluable_expression(Expression,Dict,ArithExpression,ExprType),
- type_compatible(ExprType,number),
- ArithComparison = [comp(att(PrevRangeVar,PrevAtt),'=',ArithExpression)].
-
-
- translate_arithmetic_function(var(VarId),Expression,ArithComparison,Dict,Dict):-
- % --- test whether left side evaluates to right side: return equality
- comparison ----
- % Left side consists of arithmetic expression, i.e. VarId is stored in
- Dict as
- % belonging to arithmetic expression which is expressed as
- RangeVar-argument
- % of lookup returning is/2. Type information is implicit through the
- is/2 functor
-
- lookup(VarId,Dict,is,LeftExpr,Type),
- type_compatible(Type,number),
- evaluable_expression(Expression,Dict,RightExpr,ExprType),
- type_compatible(ExprType,number),
- ArithComparison = [comp(LeftExpr,'=',RightExpr)].
-
-
- translate_arithmetic_function(const(Constant),Expression,ArithComparison,Dict,Dict):-
- % --- is/2 used to test whether left side evaluates to right side
- -------------------
- get_type(const(Constant),ConstantType),
- type_compatible(ConstantType,number),
- evaluable_expression(Expression,Dict,ArithExpression,ExprType),
- type_compatible(ExprType,number),
- ArithComparison = [comp(const(Constant),'=',ArithExpression)].
-
-
-
- % --- translate_comparison(LeftArg,RightArg,CompOp,Dict,SQLComparison)
- ---------
- %
- % translates the left and right arguments of a comparison term into the
- % appropriate comparison operation in SQL. The result type of each
- % argument expression is checked for type compatibility
- %
- %
- ------------------------------------------------------------------------------
-
- translate_comparison(LeftArg,RightArg,CompOp,Dict,Comparison):-
- evaluable_expression(LeftArg,Dict,LeftTerm,LeftArgType),
- evaluable_expression(RightArg,Dict,RightTerm,RightArgType),
- type_compatible(LeftArgType,RightArgType),
- Comparison = [comp(LeftTerm,CompOp,RightTerm)].
-
-
-
-
-
-
-
- % --- translate_functor(Functor,QualifiedTableName)
- ------------------------------------
- %
- % translate_functor searches for the matching relation table name for
- % a given functor and creates a unique range variable to result in
- % a unique qualified relation table name.
- %
- %
- --------------------------------------------------------------------------------------
-
- translate_functor(Functor,Arity,rel(TableName,RangeVariable)):-
- relation(Functor,Arity,TableName),
- gensym(rel,RangeVariable).
-
-
-
-
- % --- translate_arguments(Arguments,RelTable,ArgPos,Conditions,Dict)
- -------------------
- %
- % translate_arguments organizes the translation of term arguments. One
- % term argument after the other is taken from the list of term arguments
- % until the list is exhausted.
- %
- %
- --------------------------------------------------------------------------------------
-
- translate_arguments([],_,_,[],Dict,Dict).
-
- translate_arguments([Arg|Args],SQLTable,Position,SQLWhere,Dict,NewDict):-
- translate_argument(Arg,SQLTable,Position,Where,Dict,TmpDict),
- NewPosition is Position + 1,
-
- translate_arguments(Args,SQLTable,NewPosition,RestWhere,TmpDict,NewDict),
- append(Where,RestWhere,SQLWhere).
-
-
-
-
- % --- translate_argument(Argument,RelTable,Position,Condition,Dict)
- --------------------
- %
- % The first occurrence of a variable leads to its associated SQL attribute
- information
- % to be recorded in the Dict. Any further occurrence creates an equi-join
- condition
- % between the current attribute and the previously recorded attribute.
- % Constant arguments always translate to equality comparisons between an
- attribute and
- % the constant value.
- %
- %
- --------------------------------------------------------------------------------------
-
- translate_argument(var(VarId),rel(SQLTable,RangeVar),Position,[],Dict,NewDict):-
- attribute(Position,SQLTable,Attribute,Type),
- add_to_dictionary(VarId,RangeVar,Attribute,Type,all,Dict,NewDict).
-
- translate_argument(var(VarId),rel(SQLTable,RangeVar),Position,AttComparison,Dict,Dict):-
- % --- Variable occurred previously - retrieve first occurrence data from
- dictionary -
- lookup(VarId,Dict,PrevRangeVar,PrevAtt,PrevType),
- attribute(Position,SQLTable,Attribute,Type),
- type_compatible(PrevType,Type),
- AttComparison =
- [comp(att(RangeVar,Attribute),=,att(PrevRangeVar,PrevAtt))].
-
- translate_argument(const(Constant),rel(SQLTable,RangeVar),Position,ConstComparison,Dict,Dict):-
- % --- Equality comparison of constant value and attribute in table
- ------------------
- attribute(Position,SQLTable,Attribute,Type),
- get_type(const(Constant),ConstType),
- type_compatible(ConstType,Type),
- ConstComparison = [comp(att(RangeVar,Attribute),=,const(Constant))].
-
-
-
-
-
- % --- projection_term_variables(ProjectionTerm,Dict)
- -----------------------------------
- %
- % extracts all variables from the ProjectionTerm and places them into the
- % Dict as a dict/4 term with their Identifier, a non instantiated RangeVar
- and
- % Attribute argument, and the keyword existential for the type of
- quantification
- %
- %
- --------------------------------------------------------------------------------------
-
- projection_term_variables(const(_),[]).
-
- projection_term_variables(var(VarId),[dict(VarId,_,_,existential)]).
-
- projection_term_variables(ProjectionTerm,ProjectionTermVariables):-
- ProjectionTerm =.. [Functor|ProjectionTermList],
- not (Functor = var),
- not (ProjectionTermList = []),
- projection_list_vars(ProjectionTermList,ProjectionTermVariables).
-
-
- projection_list_vars([],[]).
- projection_list_vars([var(VarId)|RestArgs],[dict(VarId,_,_,existential)|RestVars]):-
- projection_list_vars(RestArgs,RestVars).
- projection_list_vars([const(_)|RestArgs],Vars):-
- projection_list_vars(RestArgs,Vars).
-
-
-
-
-
-
- %
- --------------------------------------------------------------------------------------
- % RESTRICTION! ProjectionTerm underlies the following restrictions:
- %
- % - ProjectionTerm must have a functor other than the built-in
- % operators, i.e. ',',';', etc. are not allowed
- %
- % - only variables and constants are allowed as arguments,
- % i.e. no structured terms
- %
- %
- --------------------------------------------------------------------------------------
-
- translate_projection(var(VarId),Dict,SelectList):-
- projection_arguments([var(VarId)],SelectList,Dict).
-
- translate_projection(const(Const),_,[const(Const)]).
-
- translate_projection(ProjectionTerm,Dict,SelectList):-
- ProjectionTerm =.. [Functor|Arguments],
- not (Functor = var),
- not (Functor = const),
- not (Arguments = []),
- projection_arguments(Arguments,SelectList,Dict).
-
-
-
- projection_arguments([],[],_).
-
- projection_arguments([Arg|RestArgs],[Att|RestAtts],Dict):-
- retrieve_argument(Arg,Att,Dict),
- projection_arguments(RestArgs,RestAtts,Dict).
-
-
-
-
- % - retrieve_argument(Argument,SQLAttribute,Dictionary)
- --------------------------------
- %
- % retrieves the mapping of an argument to the appropriate SQL construct,
- i.e.
- %
- % - qualified attribute names for variables in base goals
- % - arithmetic expressions for variables in arithmetic goals
- % - constant values for constants
- %
- %
- --------------------------------------------------------------------------------------
-
- retrieve_argument(var(VarId),Attribute,Dict):-
- lookup(VarId,Dict,TableName,AttName,_),
- (
- TableName = is ->
- Attribute = AttName
- ;
- Attribute = att(TableName,AttName)
- ).
-
- retrieve_argument(const(Constant),const(Constant),_).
-
-
-
-
-
- % --- lookup(Key,Dict,Value)
- -----------------------------------------------------------
-
- lookup(VarId,Dict,RangeVar,Attribute,Type):-
- member(dict(VarId,RangeVar,Attribute,Type,Quant),Dict),
- (
- Quant = all ->
- true
- ;
- nonvar(RangeVar),
- nonvar(Attribute)
- ).
-
-
-
- % --- add_to_dictionary(Key,RangeVar,Attribute,Quantifier,Dict,NewDict)
- ----------------
-
- add_to_dictionary(Key,RangeVar,Attribute,Type,_,Dict,Dict):-
- member(dict(Key,RangeVar,Attribute,Type,existential),Dict).
-
- add_to_dictionary(Key,RangeVar,Attribute,Type,Quantifier,Dict,NewDict):-
- not member(dict(Key,_,_,_,_),Dict),
- NewDict = [dict(Key,RangeVar,Attribute,Type,Quantifier)|Dict].
-
-
-
-
- % --- aggregate_function(AggregateFunctionTerm,Dict,AggregateFunctionQuery)
- ------------
- %
- % aggregate_function discerns five Prolog aggregate function terms: count,
- avg, min,
- % max, and sum. Each such term is has two arguments: a variable indicating
- the attribute
- % over which the function is to be computed, and a goal argument which must
- contain in
- % at least one argument position the variable:
- %
- % e.g. avg(Seats,plane(Type,Seats))
- %
- % These aggregate function terms correspond to the SQL built-in aggregate
- functions.
- %
- % RESTRICTION: AggregateGoal may only be conjunction of (positive or
- negative) base
- % goals
- %
- %
- --------------------------------------------------------------------------------------
-
- aggregate_function(AggregateFunctionTerm,Dict,AggregateFunctionExpression):-
- AggregateFunctionTerm =..[AggFunctor,AggVar,AggGoal],
- aggregate_functor(AggFunctor,SQLFunction),
- conjunction(AggGoal,AggConjunction),
-
- aggregate_query_generation(SQLFunction,AggVar,AggConjunction,Dict,AggregateFunctionExpression).
-
-
- conjunction(Goal,Conjunction):-
- disjunction(Goal,[Conjunction]).
-
-
-
-
- % ---
- aggregate_query_generation(Function,FunctionVariable,AggGoal,Dict,AggregateQuery)
-
- %
- % compiles the function variable (representing the attribute over which the
- aggregate
- % function is to be computed) and the aggregate goal (representing the
- selection and
- % join conditions for the computation of the aggregate function) to an SQL
- aggregate
- % function subquery.
- %
- %
- --------------------------------------------------------------------------------------
-
- aggregate_query_generation(count,const('*'),AggGoal,Dict,AggregateQuery):-
- translate_conjunction(AggGoal,SQLFrom,SQLWhere,Dict,TmpDict),
-
- % ATTENTION! It is assumed that in count(*) aggregate query terms there
- cannot be
- % free variables because '*' stands for "all arguments"
-
- AggregateQuery =
- agg_query(Function,(count,[const(*)]),SQLFrom,SQLWhere,[]).
-
-
- aggregate_query_generation(Function,FunctionVariable,AggGoal,Dict,AggregateQuery):-
- translate_conjunction(AggGoal,SQLFrom,SQLWhere,Dict,TmpDict),
-
- % --- only variables occurring in the aggregate goal are relevant to the
- translation
- % of the function variable and the free variables in the goal.
- % Thus subtract from TmpDict all entries of Dict
- set_difference(TmpDict,Dict,AggDict),
-
- translate_projection(FunctionVariable,AggDict,SQLSelect),
- translate_grouping(FunctionVariable,AggDict,SQLGroup),
- AggregateQuery =
- agg_query(Function,SQLSelect,SQLFrom,SQLWhere,SQLGroup).
-
-
-
-
- % --- translate_grouping(FunctionVariable,Dict,SQLGroup)
- -------------------------------
- %
- % finds the free variables in the aggregate function term and collects
- their
- % corresponding SQL qualified attributes in the SQLGroup list.
- %
- %
- --------------------------------------------------------------------------------------
-
- translate_grouping(FunctionVariable,Dict,SQLGroup):-
- free_vars(FunctionVariable,Dict,FreeVariables),
- translate_free_vars(FreeVariables,SQLGroup).
-
-
-
-
- % --- free_vars(FunctionVariable,Dict,FreeVarList)
- -------------------------------------
- %
- % A Variable is free if it neither occurs as the FunctionVariable, nor is
- stored as
- % existentially quantified (through ^/2 in the original goal) in the
- dictionary
- %
- % FreeVars contains for each variable the relevant attribute and relation
- information
- % contained in the dictionary
- %
- %
- --------------------------------------------------------------------------------------
-
- free_vars(FunctionVariable,Dict,FreeVarList):-
- projection_term_variables(FunctionVariable,FunctionVariableList),
- findall((Var,Table,Attribute),
- (member(dict(Var,Table,Attribute,all),Dict),
- not member(dict(Var_,_,_),FunctionVariableList)
- ),
- FreeVarList).
-
-
- % --- function_variable_list(FunctionVariable,FunctionVariableList)
- --------------------
- %
- % extracts the list of variables which occur in the function variable term
- %
- % RESTRICTION: FunctionVariable may only contain one single variable.
- %
- %
- --------------------------------------------------------------------------------------
-
- function_variable_list(var(VarId),[VarId]).
-
-
-
-
- % --- translate_free_vars(FreeVars,SQLGroup)
- -------------------------------------------
- %
- % translates dictionary information on free variables to SQLGroup of
- aggregate
- % function query
- %
- %
- --------------------------------------------------------------------------------------
-
- translate_free_vars([],[]).
- translate_free_vars([(VarId,Table,Attribute)|FreeVars],[att(Table,Attribute)|SQLGroups]):-
- translate_free_vars(FreeVars,SQLGroups).
-
-
-
-
- % --- evaluable_expression(ExpressionTerm,Dictionary,Expression,Type)
- --------------------
- %
- % evaluable_expression constructs SQL arithmetic expressions with qualified
- attribute names
- % from the Prolog arithmetic expression term and the information stored in
- the dictionary.
- %
- % The type of an evaluable function is returned in the argument Type.
- %
- % The dictionary is not changed because it is used for lookup only.
- %
-
- evaluable_expression(AggregateFunctionTerm,Dictionary,AggregateFunctionExpression,number):-
-
- aggregate_function(AggregateFunctionTerm,Dictionary,AggregateFunctionExpression).
-
- evaluable_expression(LeftExp + RightExp,Dictionary,LeftAr +
- RightAr,number):-
- evaluable_expression(LeftExp,Dictionary,LeftAr,number),
- evaluable_expression(RightExp,Dictionary,RightAr,number).
-
- evaluable_expression(LeftExp - RightExp,Dictionary,LeftAr -
- RightAr,number):-
- evaluable_expression(LeftExp,Dictionary,LeftAr,number),
- evaluable_expression(RightExp,Dictionary,RightAr,number).
-
- evaluable_expression(LeftExp * RightExp,Dictionary,LeftAr *
- RightAr,number):-
- evaluable_expression(LeftExp,Dictionary,LeftAr,number),
- evaluable_expression(RightExp,Dictionary,RightAr,number).
-
- evaluable_expression(LeftExp / RightExp,Dictionary, LeftAr /
- RightAr,number):-
- evaluable_expression(LeftExp,Dictionary,LeftAr,number),
- evaluable_expression(RightExp,Dictionary,RightAr,number).
-
- evaluable_expression(var(VarId),Dictionary,att(RangeVar,Attribute),Type):-
- lookup(VarId,Dictionary,RangeVar,Attribute,Type),
- RangeVar \= is.
-
- evaluable_expression(var(VarId),Dictionary,ArithmeticExpression,Type):-
- lookup(VarId,Dictionary,is,ArithmeticExpression,Type).
-
- evaluable_expression(const(Const),_,const(Const),ConstType):-
- get_type(const(Const),ConstType).
-