©Copyright by Kazimierz Subieta.

Query Evaluation Procedure eval

by Kazimierz Subieta (February 2006)

Back to Description of SBA and SBQL.

Previously, in the section devoted to the syntax, semantics and pragmatics of query languages we have described our approach to the operational semantics, in particular, to semantic rules implemented within an abstract evaluation machine. The machine has the form of the recursive procedure eval. In this section we provide more detailed description of this procedure.

·        The procedure eval has a query as a parameter. The query is represented in the abstract syntax. In implementation the query has the form of a syntactic tree, which is the most convenient for quick and univocal recognizing its structure. The procedure eval makes no changes to the syntactic tree.

·        In real implementation, before the procedure eval is called, the syntactic tree is processed by a strong type checker and by optimization modules, see Fig.25 (eval is some abstraction over the interpreter of queries/programs module). The strong type checker removes some ambiguities, for instance, maps literals into values of corresponding types, resolves automatic dereferences, coercions and ellipses, and makes other changes to the tree. Then, optimization modules can make significant changes of the tree aiming query optimization. All these changes, however, do not influence the result returned by the query, hence we neglect them during our description of eval.

·        The procedure eval will operate on three basic data structures that are introduced in SBA: the object store, the ENVS stack and the QRES stack, see Fig.25.

·        It may change the state of ENVS, but for queries with no side effects the initial state and the final state of ENVS is the same.

·        Assuming no side effects in queries, the procedure makes no changes in the object store.

·        The procedure makes no change in the initial part of the QRES state, i.e. in these sections that were on QRES when the procedure started. At the end of the procedure, QRES is augmented by the new top section with the result of the processed query, Fig.26.

·        The result from the top of QRES is then “consumed” by some agent external to the query, for instance, by a print procedure, by a user graphical interface, by an update command, etc. After such operation the stack returns to the initial state.


Fig.26. QRES changed by the procedure eval and by a query result consumer


Fig.27 presents an example of a syntactic tree for a simple query. A node of the tree contains information on its kind and may contain the information from the query. Each node contains also some free space (a grey box) that can be filled in by a type checker or by optimization modules. We explain the kind and role of this information later. A tree may contain some elements that are implicit in the query, for instance, the algebraic dereference (deref) operator.


Fig.27. Syntactic tree of the query: Emp where name = “Poe”

The procedure eval follows the orthogonality and compositionality principles, which say (in the case of queries) that the semantics of a query is some function of the semantics of its direct subqueries. The principles imply simple and intuitive recursive definition of the semantics.

The definition of eval considers a few cases that are recognized in the syntactic tree. We present the procedure in the form of a pseudo-code. Our goal is to illustrate the formal semantics rather than to present details of all the operators that we would like to introduce in SBQL. For the purposes of standardization the procedure eval can be refined precisely, but this requires some agreement on the pseudo-code that will be used for the specification. The agreement is similar to the standardization of syntax in the form of BNF grammars.

The most simple SBQL queries are literal and names. During parsing or type checking literals are changed into values of proper types. This operation can be written as application of the function lexval: L → V, where L is the set of literals, V is the set of object store values. Concerning names occurring in queries, they are bound on ENVS and the corresponding function is bind: N Result, where N is the set of all names, Result is the set of all query results, as defined previously. Other cases include unary algebraic operators, binary algebraic operators, naming operators (unary algebraic operators parameterized by a name), non-algebraic operators and structure/collection construction operators. The corresponding parts of the eval procedure will be explained subsequently for particular operators or their kinds. Below we present the beginning and some frame of the procedure. Stack operators push, pop, top will be parameterized by the name of the stack. We also distinguish symbols of operators occurring in queries and the operators themselves as mathematical beings. Operators will be underlined: if S is a symbol denoting an operator, the S is the operator itself.


procedure eval( q : query )


temp1, temp2: Result; //two local variables for temporary results of the type Result

case q is recognized as literal l L:

push( QRES, lexval( l ) );

case q is recognized as name n N:

push( QRES, bind( n ) );

case q is recognized as q1 : // the query q consists of a unary algebraic operator applied to a subquery q1

eval( q1 );

temp1 := top( QRES ); pop( QRES );

push( QRES, ( temp1 ) );

case q is recognized as qleft qright: // the query q consists of a binary algebraic operator joining subqueries qleft and qright

eval( qleft );

eval( qright );

temp2 := top( QRES ); pop( QRES );

temp1 := top( QRES ); pop( QRES );

push( QRES, ( temp1, temp2 ) );

case q is recognized as q1 as n: //the query q is the assignment of an auxiliary name n to elements of the collection returned by q1

.... // semantics will be explained later

case q is recognized as q1 group as n: //the query q is the assignment of an auxiliary name n to the entire result returned by q1

.... // semantics will be explained later

case q is recognized as qleft θ qright: // the query q consists of a non- algebraic operator θ joining subqueries qleft and qright

.... // semantics will be explained later

case q is recognized as if condition then q1: //conditional query: if condition is false, push the empty bag on QRES

eval( condition );

temp1 := top( QRES ); pop( QRES );

if ( temp1 ) then eval( q1 ) else push(QRES, Ø );

case q is recognized as if condition then q1 else q2 //conditional query

eval( condition );

temp1 := top( QRES ); pop( QRES );

if ( temp1 ) then eval( q1 ) else eval( q2 );

case q is recognized as struct( querySeq ): //the constructor of structures

.... // semantics will be explained later

case q is recognized as bag( querySeq ): //the constructor of bags

.... // semantics will be explained later

case q is recognized as sequence( querySeq ): //the constructor of sequences

.... // semantics will be explained later

...// perhaps other cases



In the following we subdivide SBQL query operators into algebraic and non-algebraic. The subdivision is based on a very simple rule:

·        Algebraic operators do not deal with the ENVS stack; they act on the QRES stack only. Algebraic operators can be unary, binary and perhaps may have more arguments. In SBQL all operators having more than two arguments can be reduced to the composition of unary and binary operators. For instance, the ternary operator if condition then q1 else q2 can be understood as a composition of three binary and one unary operators: bag(if condition then q1, if not condition then q2); providing q1 and q2 return bags. Similarly, bag( q1, q2, q3, q4 ) can be understood as bag( q1, bag( q2, bag( q3, q4 ))). If an algebraic operator is binary, then in the query qleft qright the order of evaluation of qleft and qright does not matter. We would like to emphasize (due to frequent misunderstanding) that we are talking on the order of evaluation, not about the order of arguments. In general, qleft qright is not equivalent to qright qleft (this holds of course for some operators, but not for all), but this means that we can call the eval procedure first to qright and then to qleft and still the semantics of the query can be correctly determined.

·        Non-algebraic operators deal with both ENVS and QRES. Non-algebraic operators are the core of SBA and SBQL. The fundamental difference with algebraic operators is that in the query qleft θ qright , where θ is a non-algebraic operator, the order of evaluating queries qleft, qright is fixed. The procedure eval must be first called on the qleft argument, and then, the procedure eval is called many times for the qright argument. We present this part of the eval procedure a bit later, after discussion and introducing some new notions.

The definition of other algebraic operators that are present in the above procedure eval body is simple and straightforward; we return to them a bit later.

Last modified: July 14, 2006