Article View: comp.lang.prolog
Article #2159Prolog to SQL compiler v.1.1 (part 1/2)
From: Christoph Draxler
Date: Tue, 22 Dec 1992 12:47
Date: Tue, 22 Dec 1992 12:47
905 lines
29679 bytes
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).
Technical Details
Message-ID:
<draxler-221292134855@mac_server.cis.uni-muenchen.de>Path:
arc1-ca.pugleaf.net!sparky!uunet!spool.mu.edu!yale.edu!ira.uka.de!fauern!lrz-muenchen.de!mac_server.cis.uni-muenchen.de!userShow Full Headers
Complete Article Headers
Newsgroups: comp.lang.prolog Path: arc1-ca.pugleaf.net!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