🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.lang.prolog
1 messages
1 total messages Started by Christoph Draxler Tue, 22 Dec 1992 12:47
Prolog to SQL compiler v.1.1 (part 1/2)
#2159
Author: Christoph Draxler
Date: Tue, 22 Dec 1992 12:47
905 lines
29679 bytes
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).
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads