+ All Categories
Home > Documents > Automatic Translation of First-order Predicate Logic to SQL

Automatic Translation of First-order Predicate Logic to SQL

Date post: 01-Jun-2018
Category:
Upload: ybng
View: 281 times
Download: 12 times
Share this document with a friend
31
ATLS Automatic Translation of First-order Predicate Logic to SQL Ana -Mar ia Ca rc al et e Sebastian Del ek ta Y ub in Ng Balarabe Og be ha Arj un Saraf Wil li am Smi th Supervisor: Dr Fariba Sadri Executive Summary ATLS (pronounced  ‘atlas’) is a system for automated translation of rst order predicate logic queries into Structured Query Language (SQL). The system consists of two components: the com- mand line translator and the web user interface. At Imperial College during the rst year, logic is taught in the rst term and databases are taught in the second term focu sing on the relat iona l mode l. Predi cate logic is closer to the relational model than SQL, so students that have no prior experience with SQL will be able to use ATLS. Also, people who prefer logic, such as academics will be able to use this system over direct SQL. In orde r to use the syst em, users are able to connect to a dat abase of the ir choi ce. Usi ng a simple mapping between predicate logic and SQL, they can construct predicate formulas, using the database schema displayed on the web interface, that they can translate and run on the connected database. SQL is the most widely used database querying language; however, queries can also be ex- pres sed in rst- orde r (pre dicat e) logi c sometimes more succi nctly and intuitiv ely . In prac tice, most Relational Database Management Systems (RDBMSs) use some variant of the SQL standard which means that SQL quer ies written for a range of RDBMSs will differ subt ly . This is a good reason for reasoning about databases in predicate logic since it provides a means for users to reason about a database without subjecting themselves to the nuances of the specic SQL implementation that is in use in the RDBMS in quest ion. This allo ws users to express queri es in a very genera l manner only worrying about the correctness of the logical formula and not about the correctness of the SQL query with regards to a particular RDBMS. ATLS thus forms a bridge between these two paradigms by allowing users to convert their abstracted predicate formulas into runnable SQL queries.
Transcript
Page 1: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 1/31

ATLS

Automatic Translation of First-order Predicate Logic to SQL

Ana-Maria Carcalete Sebastian Delekta Yubin NgBalarabe Ogbeha Arjun Saraf William Smith

Supervisor: Dr Fariba Sadri

Executive Summary

ATLS (pronounced ‘atlas’) is a system for automated translation of first order predicate logic

queries into Structured Query Language (SQL). The system consists of two components: the com-

mand line translator and the web user interface.

At Imperial College during the first year, logic is taught in the first term and databases are taught

in the second term focusing on the relational model. Predicate logic is closer to the relational

model than SQL, so students that have no prior experience with SQL will be able to use ATLS.

Also, people who prefer logic, such as academics will be able to use this system over direct SQL.

In order to use the system, users are able to connect to a database of their choice. Using a

simple mapping between predicate logic and SQL, they can construct predicate formulas, using the

database schema displayed on the web interface, that they can translate and run on the connected

database.SQL is the most widely used database querying language; however, queries can also be ex-

pressed in first-order (predicate) logic sometimes more succinctly and intuitively. In practice,

most Relational Database Management Systems (RDBMSs) use some variant of the SQL standard

which means that SQL queries written for a range of RDBMSs will differ subtly. This is a good

reason for reasoning about databases in predicate logic since it provides a means for users to reason

about a database without subjecting themselves to the nuances of the specific SQL implementation

that is in use in the RDBMS in question. This allows users to express queries in a very general

manner only worrying about the correctness of the logical formula and not about the correctness

of the SQL query with regards to a particular RDBMS. ATLS thus forms a bridge between these

two paradigms by allowing users to convert their abstracted predicate formulas into runnable SQL

queries.

Page 2: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 2/31

Contents

Executive Summary   1

1 Introduction   3

1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.2 Objectives   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.3 Achievements   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2 Translation from Predicate Logic to SQL   4

2.1 Background Research  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2.1.1 Datalog   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2.1.2 Tuple Relational Calculus   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2.2 Syntax  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2.3 General interpretation of formulas   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2.4 Quantification   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.4.1 Existential quantifier   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.4.2 Universal quantifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2.5 Negation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.6 Comparison operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2.7 Binary connectives   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3 Design and Implementation   12

3.1 Choice of tools   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

3.2 Architecture overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3.3 Front-end   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3.3.1 Design   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3.3.2 Implementation  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

3.3.3 Middleware   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

3.4 Translation   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.5 Technical challenges   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.6 Risk management   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

4 Project Management   21

4.1 Design methodology   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

4.2 Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

4.3 Team organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

5 Evaluation   23

5.1 Testing and translation correctness   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

5.2 Usability testing  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245.3 Performance Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

5.4 Project management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

5.5 Evaluating deliverables   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

6 Conclusion and Future Extensions   27

6.1 Conclusion   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

6.2 Front-end   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

6.3 Translation   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

A Appendices   29

A.1 Hallway testing   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

A.2 Sample Translations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

References   31

2

Page 3: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 3/31

1 Introduction

1.1 Motivation

Predicate logic and databases are some of the fundamental topics in the study of computer science. Some ideas

about how the former can be used to discuss the latter are straightforward—predicate logic, with appropriately

defined predicates, allows us to express set membership, term equality, or truth/false values, all of which areimportant theoretical ideas underpinning relational databases.

The goal of the project was to implement a tool that allows a user to manage a database using the language of 

predicate logic rather than SQL, the factual standard for relational database management systems. It might be

the case that a database user finds it more intuitive to express a database concept using the language of logic

rather than SQL; eg., if they are unfamiliar with joins, they may prefer to write queries such as

e ∈  employee ∧ e.name =  n ∧ p ∈  project ∧ p.manager =  e

rather than ... FROM employee JOIN project ON employee.id = project.manager.

Three main user groups that can benefit from the proposed tool have been identified:

•   Academics, who may prefer to query a database using predicate logic simply be reason of their special-

ization; indeed, our supervisor, a logic lecturer, has suggested that she often forgets the exact SQL rules

to retrieve the information she needs.

•   Students, who may want to verify their familiarity with either predicate logic or SQL, using the other as a

benchmark. It may also be that they are unfamiliar with SQL but want to use a relational database—this

would be the case for first-year students of Computing at Imperial College, who are familiarized with

predicate logic in their first term but do not see SQL until the second.

•  Working professionals  with knowledge of predicate logic, who for personal reasons prefer it over SQL

for database management.

1.2 Objectives

The objectives that we were looking to fulfil can be grouped under three main headings.

•   Functionality.  The tool should provide extensive support for database querying using correspondences

between predicate logic and SQL that are as intuitive as possible. The resulting code should be correct

and free of redundancies, and use as many features of SQL as necessary to make the translation natural.

•   Portability. The tool should support users on different platforms or web browsers, and provide translation

that can be ran on various relational databases.

•  Ease of use.  The tool should be quick to start with, without the need for extensive explanations or going

through tutorials. If required, the installation should be quick and intuitive.

After considering some of the possible design choices (see Section 3), a prioritized list of features was devel-

oped:

1. Basic command-line compiler supporting conjunction, quantification, and predicates

2. A graphical user interface

3. Extended compiler supporting joins, negation, NULL values

4. Support for multiple database standards

5. Support for non-logic operations, eg. sorting

6. SQL query optimizer

3

Page 4: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 4/31

7. Support for write operations

1.3 Achievements

The outcome of the project is a web application that allows the user to connect to a database of their choice and

enter a read-only query provided in the language of first-order predicate logic, which is translated to SQL and

executed.

The features include:

•   A full compiler from predicate logic to SQL, complete with syntax checker and semantic analyzer, capa-

ble of recognizing quantification, negation, joins, and nested subqueries

•   A portable web interface, working with the major browsers, including a text editor with syntax highlight-

ing and autocompletion

•   Database support for connecting to and querying multiple commercially available relational databases

are supported, including MySQL, SQL Server, Oracle, and Postgres

•  Offline support for locally hosted databases

2 Translation from Predicate Logic to SQL

2.1 Background Research

2.1.1 Datalog

Datalog is a logic based programming that is a subset of Prolog. It is based on first order logic and as such,

most first order logic can be easily converted to datalog. Once the predicate is in datalog then conversion toSQL is relatively easy.

The power of Datalog, or rather deductive databases in general, comes from the fact that  deductions  can be

made using rules and facts, for example by writing

ancestor(X,Z) :-   parent(X,Y),   parent(Y,Z).

we can query for all ancestor-descendant pairs with

?-   ancestor(A,B).

A   =   john,   B   =   ann;

 % ...

which might correspond to (with appropriate attributes added) the SQLSELECT   parent1.parent, parents2.child

FROM   parents   AS   parents1, parents   AS   parents2

 WHERE   parents1.child   =   parent2.parent

Clearly the expressive power of deduction is far superior in Datalog. It would be desirable to add the ability for

the user to define their own predicates in this way, however there is no way of doing this in SQL with read-only

operations. This approach will therefore not be pursued; however, Datalog provides some hints about how the

queries can be structured and interpreted.

2.1.2 Tuple Relational Calculus

Tuple Relational Calculus (TRC) is a  declarative query language. It constructs queries by stating logical

conditions which all tuples in the result must satisfy.

4

Page 5: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 5/31

In TRC,   range relations  correspond to database tables. There are also tuple variables  which range over the

relations (these correspond to rows in a database table). A general TRC query is of the form:

{τ   | F (τ )},   (1)

where τ   = (τ 1, . . . , τ  m) is a tuple of variables (or a set thereof) and  F (τ ) is a formula of first-order logic. The

query 1 will return the set of all such tuples τ   that F (τ ) evaluates to .

This information can be used to construct some simple queries; for example, the SQL code

SELECT   name, course

FROM   students

 WHERE   age   >= 20   AND   course   =   ’Computing’

could be written in TRC as

{s.name, s.course |   s ∈  students ∧ s.age ≥  20 ∧ s.course =  “Computing”   

}.   (2)

The result is the set of tuples  T    =  {τ 1, . . .}  with  τ i   = (namei, coursei  such that the condition  F (τ i)  → .

Clearly more complex conditions F  can be supported using the full range of predicate logic syntax, eg.:

{s.name | s ∈  students ∧ ∧∀s(s ∈ students ∧ s.age ≤  s.age)}.   (3)

The theoretical ideas of query interpretation in TRC play a crucial role in the development of our translation

framework, presented in the subsequent sections.

2.2 Syntax

The starting point for the formalization of the logic syntax accepted for translation was the usual syntax of 

formulae of first-order predicate logic, as can be found eg. in [2]. The rules are restricted by specifying a

precise syntax for variables and constants (where constants are decimal numbers or strings in double quotes).

They are also extended by replacing every occurrence of a relation or function symbol in predicate logic with

either a mathematical expression math-expr  or a predicate expression  predicate-expr  consisting of relation,

attribute, and argument variables. We will also write  ◦ϕ1, . . . , ϕn  to abbreviate ◦ϕ1(. . . ◦ ϕn(. . .) . . .)  where

◦ ∈ {∀, ∃}.

A partial BNF grammar for those points of interest is:

variable   ::= (non-empty string of alphanumeric characters and ‘ ’, not starting with ‘ ’ )

var-list    ::=   variable | variable ‘,’ var-list 

constant    ::=   numeric-constant  | string-constant 

math-bin-op   ::= ‘<’ | ‘≤’ | ‘>’ | ‘≥’ | ‘=’ | ‘ = ’

math-var    ::=   numeric-constant  | variable

math-expr    ::=   math-var  math-bin-op math-var 

 predicate-expr    ::=   relation ‘.’ attribute ‘(’ variable ‘,’ var-list  ‘)’

quantified-expr    ::=   quantifier  var-list  expression

Note that the definition of  predicate-expr  and var-list  forces the arity of the predicate symbol to be at least 2— this requirement will resurface soon.

5

Page 6: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 6/31

In the examples that follow, consider a simple university administration database consisting of the following

relations:

employee (eid, name, address, department, salary, dob) project (pid, title, manager, cost)

2.3 General interpretation of formulas

Within Structured Query Language (SQL), originally based on relational algebra and Tuple Relational Calculus,

two distinct languages can be outlined.[7] One is Data Definition Language (DDL), used for defining data

structures (in particular database schemas) and consisting of such SQL keywords as  CREATE,  DROP or  ALTER.

The other is Data Manipulation Language (DML) which uses  SELECT, INSERT, or DELETE among others. For

the purposes of our project, we have decided to restrict the scope to read-only logical queries that will translate

to SQL code of the form  SELECT ... FROM .... However, given an appropriately defined extension of the

language of logic accepted for translation (most likely by the way of special “keyword predicates”), support for

database modification could also be achieved.

The way the desired implementation should interpret logic formulas stems from the rules of the tuple relational

calculus: given a logical query, we want to retrieve all tuples that fulfill it. This is also the interpretation in

the target language, SQL. A TRC query to retrieve names and addresses of all employees in the Department of 

Computing who earn more than  £ 50,000 will be written as follows.

{e.name, e.address | e ∈  employee ∧ e.department =  ‘Computing’ ∧ e.salary >  50000}

An example of a translation might be:

SELECT   name, address

FROM   employee

 WHERE   department   =   ’Computing’   AND   salary   > 50000

Two issues arise when shifting from a TRC query to logic. Firstly, a TRC input is composed of two different

expressions. One is the tuple variable T    =   {e.name, e.address}  of attributes in the desired output, whichcorresponds to the  SELECT  operator in SQL. The other is  F   =   “e   ∈   employee . . .”, the condition formula,

corresponding to FROM and  WHERE. To preserve the rules of predicate logic as far as we can, we would prefer

the user to worry about one kind of input only. Therefore, we have decided that the output tuple is automatically

instantiated to be the set of types of all free variables in the query,  f v(F ). Note that this implies that the order

of attributes in the SELECT statement cannot be guaranteed. Also, as the SQL language does not allow empty

SELECT statements, we additionally require that f v(W ) = ∅.

This decision requires that the type of variables can be inferred from the query. In the example above, the

“inference” is by an explicit set operator in “e  ∈  employee” (to find out the table from which a tuple comes)

and dot dereference, as in  e.salary (so type of  s  is employee.salary). However, predicate logic has no well-

devised way of dealing with set inclusion or ordering. Hence we will need our own interpretation.

One way of resolving this introduces an explicit predicate   _from_relation, which would accept a tuple

variable and relation name and check ownership, eg.   _from_relation(e, employee). However, as we don’t

have a “dot dereference” operator in logic, to extract an attribute from a tuple  e we will need another predicate,

say:  _get(e, name, n) that unifies a fresh variable n with the attribute  name from tuple e.

However, the constructed translation is due to work on datasets that already provide a convenient interpretation

of set membership: keys. Consider a relation r   = (k, a1, a2, . . .)   with a single-column primary key  k   and

non-key attributes ai, i = 1, 2, · · · . We express the fact that a variable  ϕ is the value of attribute ai by writing:

r.ai(κ, ϕ),   (4)

where κ  is the key variable. Thus, if we want to instantiate  s  to be the salary attribute of a tuple whose key isκ, we write

employee.salary(κ, s).

6

Page 7: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 7/31

By default, the first position in a predicate’s tuple argument is occupied by the key, hence  κ   is instantiated

automatically and can be used in any context where we need to refer to the tuple’s key. However, we still need

a way of instantiating  κ  when we don’t use any other attributes (such as salary). As a key is a perfectly valid

attribute, we are allowed to use expression (4), writing  r.k(κ, κ),  or employee.eid(κ, κ), where “eid” is the

name of the key in the table. This is an acceptable solution, but to eliminate the redundancy and the need to

type out the name of the key we permit shortening  r.k(κ, κ) to just r(κ).1

The utility of this approach is more evident in the case of keys composed of multiple columns, k = (k1, . . . , kn).Request for an attribute is now of the form  r.ai(κ1, . . . , κn, ϕ). Note that each of the n key variables κi  is thus

instantiated. Using the knowledge of the database’s schema, we can decide whether the arity of the predicate is

correct—for a relation with an  n-column primary key, the arity must be  n + 1. As in the n  = 1 case above, the

keys can be instantiated by themselves, without the need to refer to any other attribute. This is done either via

n expressions of the form  r.ki(κ1, . . . , κn, κi) for all i, which treats κi as regular attributes, or more concisely

by r(κ1, . . . , κn).

We allow replacing any variable that is a predicate argument with a constant. Writing  r.a(. . . , C , . . .), where C 

is a key or attribute constant, is semantically equivalent to r.a(. . . , ϕ , . . .) ∧ ϕ =  C , where ϕ is a fresh variable

not occurring anywhere else in the query with the restriction that  ϕ is considered bound.

2.4 Quantification

2.4.1 Existential quantifier

Consider the case of an existential quantification W  = ∃xP x at the topmost level (ie., not in a nested formula).

According to the rules borrowed from TRC, the query returns a set of all tuples (with attributes restricted to the

types of  f v(W )) such that the query evaluates to true. It is obvious that the variable x is bound and x ∈ f v(W ),

so its type will not be returned.

To request the names of all employees, we might call:

∃x(employee.name(x, n))   (5)

Note f v(W ) =  {n}, whose type is employee.name—this is the only attribute that can be returned. Consider

all possible substitutions of the variable n. If an employee John Doe exists in the relation, then

W [n → “John Doe”] = ∃x(employee.name(x, “John Doe”)) →

with the primary key of the tuple substituted for   x. Hence the tuple containing John Doe, restricted to

πemployee.name , will be returned. A translation to SQL is

SELECT   name

FROM   employee

The role of ∃ in binding the variables is clear. However, it is partially redundant for just ensuring the existence

of a tuple. After all, the query

employee.name(x, n),   (6)

with f v(W ) = {x, n}, also has a truth/falsity interpretation for a particular substitution. Eg.,

W [x → 16f5a3, n → “Jane Roe”] =  employee.name(16f5a3, “Jane Roe”) →

if there is a tuple with primary key   16f5a3  and   name  attribute “Jane Roe”, and evaluates to  ⊥  otherwise.

The only difference between (5) and (6) is the variable binding—the latter has the key variable  x  as free and

therefore will be translated as

1This demonstrates the requirement that the query for a database can only exists in a model where the schema of every relation

mentioned in the query is given—otherwise the key name would remain unknown.

7

Page 8: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 8/31

SELECT   eid, name

FROM   employee

Consider now requesting the name and salary for every employee. As the name and salary must come from the

same tuple every time, we have to use the same instantiation of the primary key variable. An example query is

∃x(employee.name(x, n) ∧ employee.salary(x, s)).   (7)

The free variables n and s, whose types evaluate to employee.name and employee.salary, are bound to the same

tuple identified uniquely by  x, the primary key variable. For a particular substitution of  x  there is at most one

possible substitution n, s →   . . . for which the query evaluates to true and the values will be returned. The

translation is

SELECT   name, salary

FROM   employee

The existential quantification can also occur in a nested formula. We have up to now considered simple query

conditions—name equal to John Doe or salary greater than £ 50,000. The existence of some other tuple may also

be such a condition. Suppose we wish to find all dates of birth shared by some employees. This is expressed as

∃x(employee.dob(x, d) ∧ ∃y(employee.dob(y, d) ∧ x = y))   (8)

The nested quantification should be read as “...and there exists a different employee whose birthday is the

same”. That the birthday is the same is expressed by the fact that the first occurrence of the variable  d is unified

with the nested occurrence, hence a single substitution replaces both. We also need x = y  to prevent trivial pairs

of employees with themselves from being considered. Such a nested quantification is most readily expressed

by a nested SELECT:

SELECT   employee1.dob

FROM   employee   AS   employee1

 WHERE   (EXISTS   (SELECT   employee2.eid,

employee2.dob

FROM   employee   AS   employee2 WHERE   employee1.eid   <>   employee2.eid

AND   employee2.dob   =   employee1.dob))

Note that binding issues dictate that y is not returned. Also, as we are running a query that depends on the result

of a different query ran on the same table, the tables have to be aliased.

A query with similar semantics and no nested quantifiers can be constructed that allows for the variable  y  to be

returned. The discussion is relegated until the section that concerns the JOIN operator.

It was remarked at the end of the previous section that variables as predicate arguments can be replaced with

constants. Thus, instead of writing

∃x(employee.name(x, n) ∧ n =  “John Doe”),

we may write

∃x(employee.name(x, “John Doe”)).

Note that these are not exactly equivalent, as the latter does not have  n  as a free variable—hence it will not be

returned. Indeed, it does not have it as a variable at all, which means it cannot be referred to in other contexts.

2.4.2 Universal quantifier

Consider a case of  negated  universal quantification W  = ¬∀xP x. This formula of predicate logic is equivalent

to ∃x¬P x. Consider its TRC representation for some set of tuples T    = types(f v(W )):

{T | ¬P (x)}.   (9)

8

Page 9: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 9/31

Call a  domain  of a TRC expression the set of all values that appear in the expression or in any tuple of any

relation occuring in the expression [5]. An expression is safe if its result can only come from its own domain.

The query (9) is therefore unsafe, because—as any query involving outermost negation—it can be satisfied by

an infinitely large answer set. Using  non-negated  universal quantification on the outermost level, W  = ∀xP x,

also produces outermost negation, the result being the complement  ◦C  of the result set of (9). Therefore we

consider any query involving outermost universal quantification to be  ill-defined .

However, there is nothing in the way of using universal quantification in nested formulas. Consider the query:find names of employees whose all projects were within the budget of  £ 100,000. This might be expressed as:

∃x(employee.name(x, n) ∧ ∀y(project.manager(y, x) ∧ project.cost(y, c) ∧ c ≤  100000))   (10)

which is equivalent to

∃x(employee.name(x, n) ∧ ¬ ∃y¬(project.manager(y, x) ∧ project.cost(y, c) ∧ c ≤  100000)   

(†)

)

It is not immediately clear how to treat the part indicated by  (†). This is discussed in the next section on

negation.

2.5 Negation

Consider the (†) expression from the previous section:

∃y¬(project.manager(y, x) ∧ project.cost(y, c) ∧ c ≤  100000)   (11)

A straightforward reasoning might suggest that at least one of the three predicates project.manager (y, x),

project.cost(y, c),  c   ≤   100000  has to be false to falsify the whole conjunction. However, it is unclear how

to represent in SQL the fact that ¬project.manager(y, x) while keeping it true that project.cost(y, c) and stay-

ing true to the desired semantics. We interpret query (11) as saying that there exists a project whose cost isgreater than  £ 100,000. Indeed, we only really wish to negate the predicate c  ≤   100000—not the other two,

which might impact the interpretation of variables, especially if they occur in other predicates in the outer

scope! This is equivalent to saying that the set containing all projects except  those with cost less or equal to

£ 100,000 is not empty. We thus have a way of finding a condition for negating the parenthesized expression in

(11) without breaking unification. This is achieved with SQL’s  EXCEPT operator:

SELECT   project.pid

FROM   project

EXCEPT SELECT   project.pid

FROM   project

 WHERE   project.cost   <= 100000

will select projects with cost greater than £ 100,000. We can revisit query (10) now and apply this idea to arrive

at:

SELECT   employee1.name

FROM   employee   AS   employee1

 WHERE   (NOT   ((EXISTS

(SELECT   project1.pid,

project1.cost

FROM   project   AS   project1

 WHERE   project1.manager   =   employee1.eid

EXCEPT SELECT   project1.pid,

project1.cost

FROM   project   AS   project1 WHERE   project1.cost   <= 100000

AND   project1.manager   =   employee1.eid))))

9

Page 10: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 10/31

We further implement the use of negation to approximate the SQL’s treatment of  NULL (Codd’s ω). Although

there is no formally agreed interpretation of NULL, [4] notes that it is closest to “something that might be

present in the [Universe of Discourse], but we do not know its value at present”. SQL implements three valued

logic, in which some comparisons involving NULL result in the value Unknown. We restrict our treatment to the

simple comparisons “x  IS (NOT) NULL”, which ensures that the computation results is a standard boolean.

NULL comparison is simply done by negating the appropriate predicate with the ¬ operator. For example,

∃x, s(employee.name(x, n) ∧ ¬emp.salary(x, s)),

which returns names of all employees whose salary is missing, translates to

SELECT   emp.name

FROM   emp

 WHERE   emp.salary   IS NULL

Negations over mathematical operations are translated directly, eg.  ¬(c ≤  100000) becomes

NOT   (c   <= 100000)

2.6 Comparison operators

Supported comparison operators include  =, =, <, ≤, >, ≥. In a translation to an SQL query, those operators

will affect the  WHERE clause. Suppose we want to get the names of all employees in the Department of Com-

puting. The query

∃x, d(emp.name(x, n) ∧ employee.department(x, d) ∧ d =   ‘Computing’))

will translate to

SELECT   emp.name

FROM   emp

 WHERE   emp.department   =   ’Computing’

Conversely, asking for names of employees not  in the Department will modify the query with ... ∧ d =  ‘Computing’,

and the SQL will read

-- as above

 WHERE   emp.department   <>   ’Computing’

Both of these can be expressed more succinctly as

... ∧ employee.department(x, ‘Computing’)   and   ... ∧ ¬employee.department(x, ‘Computing’),

which modifies the set of explicitly named variables in the query.

The operators can include comparisons between any combination of variables or constants. For example, to get

all names that at least two employees have, we may write

∃x,y,n2(employee.name(x, n1) ∧ employee.name(y, n2) ∧ n1  =  n2 ∧ x = y),

where the comparison is between variables and which will translate to

SELECT   emp1.name

FROM   emp   AS   emp1,

emp   AS   emp2

 WHERE   emp1.name   =   emp2.name

AND   emp1.eid   <>   emp2.eid

The use of inequality operators is naturally restricted to values that typically support it in databases. The

compiler is not at all concerned with verifying this usage, so it is treated by a straightforward translation of  ≤to <=, etc.

10

Page 11: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 11/31

2.7 Binary connectives

Predicate logic allows ∧, ∨, ⇒, ⇔ as connectives between clauses.

Suppose we wish to find all possible pairs of employee names and project titles. The desired SQL will be

SELECT   emp.name,

project.title

FROM   emp,

project

where the comma operator between table names  emp  and  project realizes the Cartesian product,  ×, in rela-

tional algebra. This is most intuitively expressed as a conjunction of predicates over different relations:

∃x(employee.name(x, n) ∧ project.title(y, t)).   (12)

In modern SQL,  CROSS JOIN is typically used instead of the comma.[4] Note that this query does not use the

keys of either relation for the join. More typically, we carry out a join on tables based on some condition. To

find the names of employees with the projects they manage, we may write

∃x(employee.name(x, n) ∧ project.title(y, t) ∧ project.manager(y, x))   (13)

which now includes a condition that project’s  manager  attribute is equal to the key of the  employee tuple. SQL

expresses it with the extra clause:

-- as above

 WHERE   project.manager   =   employee.eid

The detail of the implementation is that it will consume the predicates in the conjunction of query ( 13) from

left to right and consider them pairwise. Hence, when the portion employee.name(x, n) ∧ project.title(y, t) is

analyzed, the result is a simple Cartesian product as there are no attributes or variables in common, just as in

(12). If we reorder query (13) to read

∃x(employee.name(x, n) ∧ project.manager(y, x) ∧ project.title(y, t))   (14)

it will first consider employee.name(x, n)∧project.manager(y, x), where the predicates have different attributes

but share a variable, x. This case will return an equi-join, where the join is based on equality constraints only:

SELECT   emp.name,

project.title

FROM   emp

JOIN   project   ON   (emp.eid   =   project.manager)

Even though the semantics behind both queries is the same, we factually violate the well-established law that

a ∧ b ≡  b ∧ a.

Consider a conjunction of attributes  a1, a2   in relations  r1   = (k1, a1, . . .), r2   = (k2, a2, . . .)  whose keys arek1, k2, respectively:

r1.a1(  τ 1) ∧ r2.a2(  τ 2),   (15)

where   τ 1,  τ 2 are tuples of variables, key or non-key.

•   If    τ 1 ∩   τ 2   =  ∅, the attributes don’t share variables, hence the join is unconstrained and will result in a

Cartesian cross join

FROM   r1, r2

between the relations.

•   If    τ 1 ∩    τ 2     ϕ, we need to join the entities that are the types of  ϕ  in the two attributes. For example,

ϕ might be a key variable in r1, representing k1, and a non-key variable in r2, representing a2, in which

case the join is expressed as

FROM   r1   JOIN   r2   ON   r1.k1   =   r2.a2

11

Page 12: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 12/31

The interpretation thus depends on the position of  ϕ in each of the tuples   τ 1,  τ 2. Note also that once again

we need to have the full knowledge of a schema for a table to carry out a translation, otherwise the key

names are unknown.

The assumption so far was that  r1   =   r2   in all cases. However, when  r1   =   r2   and a1   =   a2, we are poten-

tially running a query on the same table twice—hence the SQL code will need aliasing to resolve ambiguities.

Consider the request for all pairs of (distinct) employees that work in the same department.

∃d(employee.department(x, d) ∧ employee.department(y, d) ∧ x = y)   (16)

A possible translation is

SELECT   emp1.eid,

emp2.eid

FROM   emp   AS   emp1

JOIN   emp   AS   emp2   ON   (emp1.dep   =   emp2.dep)

 WHERE   emp1.eid   <>   emp2.eid

The other binary connectives—∨, ⇒, ⇔—are not implemented directly. Instead we rely on the laws of predi-

cate logic, whereby  P  ∨ Q  ≡ ¬(¬P  ∧ ¬Q), P   ⇒  Q  ≡ ¬P  ∨ Q, P   ⇔  Q  ≡  (P  ∧ Q) ∨ (¬P  ∧ ¬Q). The ∨operator can be used in queries such as

∃d(employee.department(x, d) ∧ (d =   ‘Computing’ ∨ d =  ‘Mathematics’))   (17)

which returns all employees from either Computing or Mathematics and translates to

SELECT   employee.eid

FROM   employee

 WHERE  (employee.department   =   ’Computing’)

OR   (employee.department   =   ’Mathematics’)

3 Design and Implementation

3.1 Choice of tools

The initial meeting with the supervisor helped us clarify the goals and settle on some of the questions crucial

to the success of the project. The developed tool was meant to support a user’s experience in database querying

and management—as there exists a plethora of tools and standards of doing this, the scope of the project

was possibly very large. The tool could be, for example, a wrapper around a command-line interface such as

psql used to query a database, or a plugin for available database management tools, such as MySQL or Toad.

However, as portability was one of our objectives, we did not want to commit to supporting one particular

standard or software piece. Hence we decided to develop a standalone tool.

The next decision was that between a native desktop application or a web interface. Desktop software would

be more appropriate for users who do not want to rely on an Internet connection for proper functionality. In the

present day, this is becoming an increasingly less valid concern. Also, none of us had extensive prior experience

with writing desktop applications, and it would likely consume some time to produce even a rudimentary

version. Conversely, we had prior experience with web applications, which allow excellent portability and easy

continuous deployment of revisions. Hence we decided on the latter.

The next step was deciding on the main implementation language. After a brief discussion, where the require-

ment to build a compiler-like tool emerged, we have narrowed down the choices to three: Haskell, Python,

and Java. All of us had prior experience with Java, however we did not know how it would support a web

application and also were not satisfied with development speed it provides. Haskell had parser and compiler

tools available, but our experience was limited to toy programs and we were not sure how that would impact

the velocity. Even though only one member of the team had prior experience with Python, it was generallyregarded as the easiest general purpose language to pick up, and provides excellent development speed and

support for web programming. We decided to use it for our tool, also as a consequence of learning interests of 

team members.

12

Page 13: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 13/31

3.2 Architecture overview

Figure 1: Overview of project architecture

Broadly, the project can be split into a user interface and a translator. The core of the tool, the translator, was

reduced to the problem of creating a compiler that takes predicate logic formulas as input and returns SQL

queries as output. Naturally, this task was split into creating a scanner, a parser and the actual translator. This

was different from creating a standard compiler due to the fact that semantic analysis of the formula required a

connection to the user’s database in order to check the correctness of the relations, keys and other details. To

make the tool usable, we decided on creating a user-friendly web interface that allows users to do the following:

•  Connect to a database with the relevant details.

•  View the database schema.

•   Input predicate logic formulas (that can be built from the database schema).

•   View the result of translating the query.

•   View the result of running the translated query on the connected database.

3.3 Front-end

The user interface for this project is a key element. It provides access to the translator in a more use friendly

manor than a command line interface. To make it useable to as many people as possible (and with minimum

effort in both development and usage) the user interface is a JavaScript web application.

3.3.1 Design

The first step in designing the user interface was to create a list of functional requirements, features that are

necessary for the interface. The initial list was created by discussing with our supervisor what was required.

The list of requirements evolved over time as designs materialised and usability was evaluated.

The first mocks of the layout of the user interface were done on paper and whiteboards to allow us to quickly

discuss and change it. These designs were then translated into basic HTML and CSS layouts that showed

potential problems that were visible on paper, such as too much negative space or the page being too crowded.The first implemented design2 was a very simple layout, consisting of two editors, a results panel, and a toolbar.

2https://gitlab.doc.ic.ac.uk/g1436227/fopl-ui/commit/02567756

13

Page 14: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 14/31

When a user accesses the interface, she will be prompted to enter the database connection settings. Once a

connection has been successfully established, she can enter the logic query into the top editor. Logical symbols

can be enter by hitting the buttons displayed at the top of the window. To facilitate editing queries, the symbols

are also found under the expected key shortcuts, eg.  Ctrl+Shift+6 will enter the symbol ∧ (with the lookalike

ASCII caret ˆ found under Shift+6). Two processing options are provided: SQL will translate the logical query

into SQL and display it in the bottom text window, and  RUN  will additionaly run the query on the database and

display the results in the result tab to the right of the editors.

Figure 2: Initial design of the user interface

The colours were picked to match the editors default theme. The next design3 had more space to make give

better boundaries between the individual areas of the program. It also had adjustable sizes and a tab control tohide some of the content when it was not needed. As noted in a meeting with our supervisor, the user needs the

ability to continuously refer to the schema of the database—which we somehow missed in the initial design.

Upon connecting to the database, the user now sees the schema, complete with the keys indicated and data

types displayed.

Figure 3: Second iteration of the UI design3

https://gitlab.doc.ic.ac.uk/g1436227/fopl-ui/commit/e5389978

14

Page 15: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 15/31

The final design4 is fully customizable, allowing the user to modify the layout according to their preferences.

This was the best way of laying out the application because everyone had his or her own opinion of what is the

correct layout. It was inspired in parts by JetBrains IntelliJ IDEA5 and Microsoft Visual Studio6, two popular

integrated development environments. We kept all the functionality of the previous iteration, adding some minor

improvements to the user experience, such as syntax highlighting or tracking the opening parenthesis when

constructing a query. Clicking on an attribute name in the schema will place it in the editor, and autocompletion

suggests the full names of tables, attributes, or previously used variables.

Figure 4: Final iteration of the user interface

3.3.2 Implementation

One of the first decisions made about the user interface was that it would be a web application. This meant

that if any real time user interaction was wanted then JavaScript would have to be involved, even if indirectly.

JavaScript is used to provide AJAX

7

, a method of loading data asynchronously after the page has loaded, andthe rich syntax highlighted text editors. The JavaScript could have been abstracted to some other language such

as Dart8 or CoffeeScript9, both of which compile to JavaScript, however the benefit of them was negated by the

simplicity of the application, the framework being used and an ES6 transpiler10.

The application was developed using CommonJS11 as a method of splitting the code into separate modules.

This made encapsulation easier because modules could hide internal representations and just provide a public

interface. CommonJS was designed for server side JavaScript so a tool called browserify12 was used to compile

all the modules into a single file that could be used by browsers.

The framework used for the application was AngularJS.13There are other similar frameworks such as Em-

ber.js14 and Backbone.js15 available but members of the group already had experience using angular giving

advantages in terms of speed of development and avoiding pitfalls. AngularJS provides a modular model-view-controller architecture that allows easy testing and strong bindings to HTML. Components in angular are called

directives.16

4https://gitlab.doc.ic.ac.uk/g1436227/fopl-ui/commit/master5

https://www.jetbrains.com/idea/6

http://www.visualstudio.com/7

https://en.wikipedia.org/wiki/Ajax_%28programming%298https://www.dartlang.org/9

http://coffeescript.org/10

https://github.com/thlorenz/es6ify11http://wiki.commonjs.org/wiki/Modules/1.012

http://browserify.org/13https://angularjs.org/14http://emberjs.com/15

http://backbonejs.org/16https://docs.angularjs.org/guide/directive

15

Page 16: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 16/31

The main controller links together shared data (such as the database settings and error list) and events from the

components. This allowed all the components to communicate without being directly coupled to each other. All

AJAX requests were handled through the ”Api” service that wrapped the ”$http” service provided by angular.

The first component is the database settings panel; it collects the settings from the user and allows them to test

them. The settings and the validity of the settings are stored in the shared data in the main controller. The

database schema directive watches the settings and when they change it clears the current schema, if they are

valid it loads the schema based on those settings. The schema is displayed in a tree control provided by theangular-ui-tree17 package. When one of the attributes is clicked it send a signal to the main controller, this is

relayed to the editor and the corresponding predicate is inserted. The editor and sql viewer are small wrapper

directives around angular-ui-ace18 handling things like resizing. The editor also runs the predicate using the

Api service, it tells the main controller about the results and any errors. The error and results directives are

wrappers around the angular-ui-grid19 directive.

We used a text editor called ACE.20 It provided most of the required functionality out of the box but we made

some custom modifications to better suit our needs. We created a regular expression based syntax highlighter

that highlighted the predicate queries and modified the editor code to support mixed-width characters, which

was needed to properly display the logic symbols.

The dynamic layout was done using a code based on library called dock-spawn.21

It structures the window asa series of panels, tab controls and splitters, and allows the panels to be rearranged and resized, providing a

customisable interface. We converted it to the CommonJS module system and fixed some bugs in the modular-

ized code. The panels are easily extensible which allowed it to be integrated with AngularJS and ACE with no

major problems.

The style sheets are written using SCSS,22 an extension to standard CSS that has features such as variables

and functions. This allowed the styles to use common variables and facilitated making the large changes that

happened during the development of the project.

The development packages are managed using NPM,23 the node package manager. It automatically installs

all the dependencies required to build the frontend assets. The third party assets are managed using bower; 24

another package manager targeted more at client side packages. The frontend assets are compiled using grunt,25

a task automation tool. Grunt was configured to either produce a release build, that combines all the assets and

minifies them, or to watch the source files and automatically recompile when they change, which is very useful

during development.

3.3.3 Middleware

In between the JavaScript user interface and the Python translator is a lightweight middleware layer that acts as

an adapter, converting the AJAX HTTP requests into the relevant executions in the translation and converting

the results from the translator into JSON for the app to display.

The middleware layer was originally written in PHP26 because it is easy to setup and available from most host-ing providers. It implemented a lightweight MVC style architecture, with a router taking the model (serialized

as JSON), finding the appropriate controller and executing it, returning the result as JSON. Whilst this was easy

to setup and work with initially, we started having problems when more information was being passed between

the components.

17https://github.com/JimLiu/angular-ui-tree

18https://github.com/angular-ui/ui-ace19

https://github.com/angular-ui/ng-grid20

http://ace.c9.io/21https://github.com/coderespawn/dock-spawn/commit/eaf12d5822

http://sass-lang.com/23https://www.npmjs.com/24http://bower.io/25

http://gruntjs.com/26http://php.net/

16

Page 17: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 17/31

We decided that it would be easier to recode the middleware in Python, allowing us to import the translator

directly. We kept the format of all the requests and responses the same but changed the URLs to be more

descriptive; the modular design of the frontend application made this a very simple change.

For managing connections to user databases and query execution we are using sqlalchemy,27 a dedicated Python

SQL toolkit. It allows an effortless management of multiple relational database standards with a single common

interface. We are thus able to support various commercially available relational database systems. As the trans-

lator uses only standard (ANSI) SQL, the functionality of generated queries is not implementation-dependent.

The final middleware layer is a very lightweight Python program using a micro framework called Flask. 28

”app.py” bootstraps the application and maps the http requests to translator and the results to JSON. ”custom -

 json.py” is a custom JSON serializer that handles the schema and sqlachemy types. ”translate.py” is a small

wrapper around the translator that changes the output of the translator into the correct format.

27www.sqlalchemy.org28

http://flask.pocoo.org/

17

Page 18: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 18/31

3.4 Translation

The initial attempt at implementing the translation consisted of a simple one-pass interpreter tried over trivial

examples. However, as more functional queries were proposed, it became apparent that support will be needed

for variable analysis, scope resolution, unification etc. Therefore we decided to implement a compiler from

predicate logic formulas to SQL.

Python is not a very common choice for compiler construction, with languages like C++ or Java being the

preferred choice. Consequently the range of tools available is rather limited. Our choice for the lexer and

parser was PLY—a Python implementation of the familiar lex and yacc tools. [1]

A sample definition of lexer tokens is

1 t_LESS   =   u’<’

2 t_LEQ   =   u’\u2264’   #   ≤3

4   def   t_STRINGCONSTANT(t):

5   r’(\’[ˆ\’]*\’|"[ˆ"]*")’

6 t.type   =   reserved.get(t.value,   ’STRINGCONSTANT’)

7 t.value   =   str(t.value)

8   return   t

where   t_LESS   and  t_LEQ  are simple fixed-length tokens, and   t_STRINGCONSTANT   builds a custom token

object according to the recipe in the definition, having recognized the pattern from the regex on line 5.

The PLY parser is capable of LALR(1), which is sufficient for the purposes of our grammar. Unlike parsing

tools such as Java’s ANTLR, PLY does not support automatic generation of abstract syntax trees—it merely

provides a bare-bones syntax recognizer. Therefore, the grammar rules must be accompanied by specifications

of the code that constructs the AST representation. Consider the following code that handles mathematical

expressions.

1   def   p_binoperation(p):

2   ’’’binoperation : identifier binoperator identifier’’’3 p[0]   =  BinaryOperationNode(p[2], [p[1], p[3]])

The AST node constructor for the binary operations uses the BNF definition binop ::=  id  binoperator  id ,

declared on line 2. The argument  p  is the array of terminal and nonterminal elements on the right-hand side of 

the rule. The elements of the rule are accessible by referring to the index number. Here, a BinaryOperationNode

is created, using the  p[2] operator argument as well as the list of children—identifiers  p[1] and  p[3]. The

result is stored in the place of the nonterminal symbol on the left hand side,  p[0]. An abstract syntax tree for a

sample query is presented below.

Quantifier   {type=∃, ids=[x, s]}Binop   {type=∧}

Predicate   {relation=emp, attribute=name}Variable   {id=x}Variable   {id=n}

Binop   {type=∧}Predicate   {relation=emp, attribute=salary}

Variable   {id=x}Variable   {id=s}

Mathop   {operator=≥}Variable   {id=s}Numconst   {val=50000}

Figure 5: Sample AST for the query ∃x, s(emp.name(x, n) ∧ emp.salary(x, s) ∧ s > 50000).

After the AST has been constructed we run basic semantic analysis over the query. This involves verifying

it against the obtained database schema and determine whether (a) all relations and attributes mentioned in

18

Page 19: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 19/31

the query are available, and (b) that the predicates have correct arity. We considered extending the semantic

analysis stage to other possible errors such as type checking, but decided that such errors should be returned on

the database end as predicate logic is by default not many-sorted.

Identifier Bound value

emp.name   <PredicateNode@0x14b4f50>

emp.salary   <PredicateNode@0x14b4f90>

n   <VariableNode@0x14b4e90>

s   <BindingVariableNode@0x14b71d0>

x   <BindingVariableNode@0x14b7150>

Table 1: Top-level symbol table for the query from Fig-

ure 5.

In order to facilitate variable analysis, a symbol

table is generated once the AST construction is

complete. This allows us to uniquely identify the

entity that a variable represents. Note that therules of the grammar allow writing formulas with

the shape

◦x(. . . ◦ x(P x) . . .),

that is, reusing a variable symbol in a different

binding within a subformula. For this reason the

symbol table is hierarchical—it is constructed on

a per-level basis, where the occurrence of a quantifier ◦ ∈ {∀, ∃} signals the introduction of a new scope level.

A sample top-level symbol table is presented to the right.

It is not feasible to directly use an abstract syntax tree to generate SQL code. This is because the AST, even with

the symbol table, still does not contain all the necessary information about, say, variable resolution. Therefore,a tree walker generates an  intermediate language struct   that will then be used by the SQL code generator.

Consider Figure 6, the intermediate language struct for the query

∃d(employee.department(x, d) ∧ employee.department(y, d) ∧ x = y ∧ employee.salary(y, s))   (18)

π-list:   {emp1@emp}.eid, {emp2@emp}.eid, {emp2@emp}.salary

σ-list: =

{emp2@emp}.eid{emp1@emp}.eid

1

emp2@empemp1@emp

1: {emp1@emp}.dep={emp2@emp}.dep

Figure 6: An intermediate language struct for query (18)

The IL struct consists of two items. The π-list, corresponding roughly to the relational algebra’s projection

operator, indicates the predicates that will be part of SQL’s SELECT query. Query (18) asks for the primary keys

of two employees and the salary of the latter, hence the  π-list consists of three items. The notation {p@r}.a

denotes attribute a  from table r  which is aliased as p.

The σ-list in turn is a list of   condition trees  that the code generator will use to construct   FROM  and  SELECT.

The condition tree can express various constraints, such as the need to carry out a join or make sure that twovariables compare in a particular way. The query contains x = y, which expresses that the primary keys of two

employees are different—this is indicated in the first tree with = at the root. Also, the two employees are part on

the same department—thus we need to carry out a join on the variable d, whose type is employee.department.

This is expressed in the second tree, with the join condition  1   at the root and the joined relations on the

branches.

The compiler uses the common technique of  stack-based intermediate representation [8], depicted in Figure 7.

The AST is visited in a bottom-up fashion, with a node accepting a  Visitor object, dispatching it to the node’s

children, and then processing the result of the visits to the children. The Visitor keeps an internal stack of 

intermediate language structs. The ∧  node in query dispatches the visitor to the two children nodes (predicate

nodes). When the control is returned, the visitor pops the two IL structs off the stack and combines them in anappropriate manner. This manner is dependent on the type of node that is currently visited. In the case of the

∧ node, the  σ-trees have to be inspected to resolve clashing variable names to possibly introduce a join or a

WHERE-type condition, and can then be combined to make sure that all conditions from the two children nodes

19

Page 20: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 20/31

are satisfied. Now, after aliases were possibly introduced, they can be applied to the two  π-lists, which are then

simply combined. The result is pushed back onto the stack.

. . .

. . .∧

emp.dep(y, d)emp.dep(x, d)

L1   L2

L3

1   # class AstVisitor:

2   def   visit_AndNode(self , node):

3 l2   =   self .stack.pop()4 l1   =   self .stack.pop()

5   # node-specific processing...

6 l3   =   self .combine(l1, l2)

7   self .stack.append(l3)

Figure 7: The visitor consumes the representations L1, L2 of subqueries and combines them into L3

Once the translation of the AST to the intermediate language has been completed, the topmost IL struct accepts

an SQL visitor that produces the final SQL query. Given that most of the semantic processing has been done at

the stage of translation to IL, the bulk of the SQL visitor’s functionality is string generation. Nonetheless, it is

also equipped with enough introspection power to appropriately process the  σ-trees—eg. to decide whether an

incoming condition is a  JOIN that should augment the  FROM stack, or a simple selection to be appended ontothe WHERE stack. The visitor is similarly stack-based, visiting child nodes and passing the result up to the parent

nodes. The usefulness becomes apparent in the processing of full subqueries of the form

-- ...

 WHERE NOT EXISTS   (SELECT   ...)

In such cases we create another instance of the visitor that processes the inner query and returns the result in

the form of the SQL string, which can be then appended to the top-level  WHERE operator.

3.5 Technical challenges

The biggest hurdle in the project was the implementation of the translator. Although we had prior experience

with a simple compiler project for a toy language, this time we did not have a reference compiler, nor a clearly

defined way of what the translation should result in. We owe the final result to lots of fundamental work,

pen-and-paper exercises, and discussion with the supervisor.

All our code is stored in two git repositories. Initially this caused some problems due to the .gitignore file being

wrong and temporary files being committed, and there were problems due to merging going badly. Once we

fixed the .gitignore file and added pre-commit hooks for testing these problems mostly resolved themselves.

We needed to be able to connect to a variety of different types of database server: PostgreSQL, MySQL, Mi-

crosoft SQL Server, etc. This caused problems initially because all three use different Python modules, needed

slightly different parameters for connecting and had different interfaces. Our initial attempt only supported

Postgres with a plan of creating a base class from that and extending it for each database server. During devel-

opment we found a library called sqlalchemy that encapsulated the different interfaces

Automated testing of the user interface proved difficult because there was no clear way of testing it automati-

cally. We tried some user interface automation testing libraries such as Selenium but found that the overhead

of managing the tests combined with the frequency of changes meant that it was not a viable option. As the

interface was fairly simply we have decided to test it manually in the end.

3.6 Risk management

The use of Agile methods has helped us immensely to contain the risks common to software projects. However,the tools provided by Agile are focused on  scheduling commitments. Shore and Warden in [6, p. 232] indicate

that this should not overshadow the main goal of delivering an “organizational success”, that is, a piece of 

software that delivers on the stakeholders’ needs and requirements.

20

Page 21: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 21/31

From the very beginning of the project, we relied heavily on efficient planning and evaluation. However, we

still faced some predicted risks with our project that ranged from technical to management risks.

One particular technical risk was the decision to use Python as the main programming language for our project

despite the fact that only two out of six group members had previous experience with it. However, our initial

decision to choose this based on its anecdotal ease of delivering results even by beginners proved itself correct

- by frequent group discussions and pair programming sessions we have eliminated any overhead stemming

from unfamiliarity with language features.

A risk that has emerged in the implementation stage were the breakdowns of Gitlab, the versioning system

used. These turned out far more frequent than expected, especially given that it was chosen for the in-house

support provided and history of reliability. Although the issues were quickly mitigated by the responsible staff,

we still found ourselves on occasion having to share code via Google Docs or makeshift projects set up in other

version control systems.

A crucial commitment in terms of deliverables was a functional compiler that supports a wide range of queries.

This objective proved difficult to fulfill; consequently, the suite of compiler tests that we developed in the initial

stage of the project was very helpful in containing this risk and qualitative tracking of the progress.

4 Project Management

4.1 Design methodology

In our initial meeting we made the decision to follow the Agile methodology. This allowed us to construct

our tool incrementally and respond to the requirements that were clarified over the duration of the project,

especially with regard to the functionality of the compiler.

We recognised that the most efficient way of discussing the project is via a face-to-face conversation. The

industry practice of holding a standup every day would not be feasible due to the differing schedules of team

members, hence we decided to hold it twice a week. Those meetings were used to discuss the achievements

since the last meeting, as well as define the tasks that should be completed before the next iteration and their

estimated manpower. On top of the team meetings we were also meeting our supervisor once a week to gather

feedback on the state of the project so far as well as to clarify requirements.

On occasion the team meetings converted into development sessions, mostly for the benefit of the work that

would impact different parts of the project. The benefit of that was that members assigned to different tasks

were often able to advise each other of a possible solution to a related problem, thus making the integration of 

those tasks far smoother.

We realized from the beginning that the project, although technically challenging, is rather narrow and precise in

its scope—the bulk of the work would be devoted to creating a functional compiler. As the development process

was very much explorative in terms of determining the actual workings of the tool, we were constantly updating

a list of possible extensions to our application—such as direct optimization of the resulting SQL queries to

produce more refined queries that are more intuitive to users. It was natural to think of the product utility as

built from the ground up. We have decided to use a simple cost-value approach to prioritizing requirements.

[3] In the spirit of the agile method, the insights from discussions at team meetings were further granulated

when subteams assigned to particular parts of the project individually decided on the prioritized feature and its

estimation while keeping to the team-wide agreement whenever a wider feature had to be delivered on time.

Although our supervisor has left us considerable latitude in terms of implementation, she had some very clear

ideas about what the project would ideally deliver, and we have taken these into account.

4.2 Tools

There are many applications available that implement Scrum and other agile methods but we decided to use

21

Page 22: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 22/31

value

cost

Functional

compiler for

predicates,   ∧,∨

Supporting multiple relations, nulls, joins

Web UI

Real-world database querying

SQL query optimization

Support for multiple database standards

Ad-hoc database management

Offline

support for

local databases

Figure 8: Cost-value diagram used in the initial planning stages

TargetProcess,29 a project management software that focuses on Scrum and Kanban software development

methodologies, to keep track of our work. It provides a powerful interactive scrum board that allows manage-

ment and planning of iterations, features, user stories, task allocation, bug logging, and others. When a feature

was proposed at a team meeting, it would be divided into tasks revised with the progression of the work. The

persons allocated to the task would use  planning poker  to decide an estimate of the manpower. As work on

the task was carried out, it would move between the progress lanes named  Proposed , Planned , In progress, and

Completed . The time estimation and actual development time were logged to allow us quantitative verification

of the project’s progress.

Even though TargetProcess provided excellent project management support, we feel that the tool was much

more involved that our needs would dictate—it was designed with far larger projects in mind. Initially we may

have spent too much time trying to understand the details of the system rather than simply hitting the ground

running. In the future we would consider simpler tools, such as the shoutout board Trello, for project of similarsize.

Figure 9: Snapshot of the TargetProcess Scrum board

Our tool of choice for version control was Git, primarily due to extensive previous experience of all mem-

bers of the group, as well as the support provided by departmental facilities. Two major branches were cre-

ated,  translator and  web_ui, to allow interference-free development of the largely independent parts of the

project. Git provides excellent support for versioning of different implementation ideas which we made exten-

sive use of during development. It also allowed us to enforce sanity checkpoints during development time by

preventing failing commits—section 5 includes more detail on testing procedures.

29www.targetprocess.com 

22

Page 23: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 23/31

For our continuous integration / deployment server we used Jenkins30, installed on our group virtual machine.

The user interface and the translator both had package managers that allowed them to be setup automatically.

This meant that the deployment server could be setup very quickly if it were ever lost. The continuous deploy-

ment system meant that we could quickly preview the global effect of a change on the system and we could

show it to users and our supervisor.

We used Google Drive for collaborative editing of coursework reports, storing reference articles etc. Discus-

sions were carried out using a dedicated Facebook group.

4.3 Team organization

We decided on a free form structure where we do not have a formal group leader but where we make decisions

based on everyone’s evaluation and consensus. Some decisions that directly affect the output of the application

were made after discussions with the supervisor on the topic.

After the first meeting with our supervisor we had a group meeting to decide how to split the project into self 

contained tasks that could be assigned to members of the group. For the first week we decided that we needed

to do more in-depth research on predicate-logic, but at the same we wanted to start working on the actual

application. So we delegated the work as follows:

•   Front-end: William Smith, Ana-Maria Carcalete

•   Back-end: Yubin Ng, Samuel Ogbeha

•   Translation: Sebastian Delekta, Arjun Saraf 

This work allocation was based on our estimations as to what parts of the project were most important at the

time along with previous experience of the group members. However, over the time, we kept changing the

priorities of most of these tasks, as it turned out that the translation of the implementation was the part of the

project that required most manpower.

Moreover, we scheduled to meet twice a week to discuss our progress, problems and to delegate new work.Usually the work was allocated such that it is completed within a week. However, we always had an active

Facebook conversation where one could mention the problem one is facing and seek help from everyone.

We made use of the practice of pair-programming in order for everyone to understand different aspects of the

project and advise each other on implementation points. This allowed a free flow of ideas throughout the team

and facilitated collaborative effort, allowing us to make the best use of development time.

5 Evaluation

5.1 Testing and translation correctness

To ensure that we were building the correct product, we decided to begin the project on a theoretical basis,

and to build up on the extensive research already done in the area of interfacing relational databases and logic.

This led us to create an extensive theoretical model for our project which included a comprehensive mapping

between the two languages that was our point of reference during the implementation.

Next, we had to ensure our implementation of this framework was correct, so before writing any translation

code we had meetings to discuss various problems and concepts and try to solve instances of them on paper

using our framework to see how robust it was. This involved pen-and-paper translations of multiple sample

queries, both in team meetings as well as those coming from our supervisor during the weekly catch-up.

Due to dealing with the very essence of programming languages, a compiler project must be made especiallyrobust to invalid inputs, and the expected output must be clarified as soon as it is feasible. Before attempting

30http://jenkins-ci.org/

23

Page 24: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 24/31

to write any code, we consulted our theory and wrote extensive unit tests to make sure that the developed

system would be robust. To make best possible use of the Python nosetests testing framework, we have added

pre-commit hooks to the codebase to make sure that failing tests prevent a commit to any of the branches.

Figure 10: A commit failing due to not passing all tests

The weekly meetings with our supervisor have provided us with lots of precious feedback about the imple-

mentation of the actual translation. We have prepared a separate suite of tests that are not used to validate

day-to-day code edits, but help us track the progress in the functionality of the compiler. It compares the result

of executing the output of the translator with the result of executing the expected query. Note the significance

of comparing the query results—even a non-optimal query can return the correct result, which would not be

the case if we attempted to do string comparisons of the generated query with the benchmark query. (Such

comparison is rather too involved anyway, as even the queries that are functionally the same can be written in

different ways by reordering arguments etc.)1   import   unittest

2   class   CompilerTest(unittest.TestCase):

3   # setup...

4   def   test_two_attributes(self ):

5 query   =   u’’’employee.name(x, n)’’’

6 correct_sql   =   "SELECT eid, name FROM employee"

7   assert   self .run(query)   ==   self .run(correct_sql)

Figure 11: Compiler unit test for query: employee.name(x, n)

5.2 Usability testing

As soon as the web interface was completed and basic compiler functionality was implemented, we created a

dedicated testing environment and began running ad-hoc usability studies on fellow students in the department.

We were deliberately vague in our introductory explanations as we wanted to determine whether the tool is in-

tuitive enough for the user to simply jump straight to query execution. We ran those brief sessions on volunteers

in the labs as time permitted, asking them to attempt retrieving certain information from a provided database

and to fill out a brief questionnaire afterwards. (See Appendix A.1) All queries that the users tried to execute,

even when failing, were logged to allow us to see what confused users the most about how queries should be

written.

This survey has allowed us to discover a few potential issues with the tool. Firstly, it was not at all clear what itexactly means to translate a predicate logic formula into an SQL query. Inspecting the log has shown that users

were often confused about restricting free variables to enforce projection and giving appropriate arguments to

the predicates. This is something we were aware of from the beginning, as we also had to get used to the idea

24

Page 25: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 25/31

of such translations. We thus became reassured that a concise but comprehensive help guide—or at the very

least a set of examples—will be necessary for the best user experience. More importantly, we discovered that

the user interface was not very user friendly. This was a surprise to us—we became victims of creator’s bias.

As the expected functionality was clear cut in our minds we thought the UI was perfectly intuitive.

Figure 12: A feedback sample from the usability study

The feedback from the users that grasped the basics of the application in the limited time was generally positive.

However they mostly welcomed the tool as a novelty rather than one of substantial help in database management

or related tasks. Some of the concerns raised were:

•   It is not clear how to write the query in logic in the first place. In spite of the introduction to the rules and

the examples we provided, some users have still struggled in trying to formulate a query in logic. This is

an important obstacle for the user to use the tool to their advantage, but we believe the learning curve to

not be very steep. In particular, all the queries that we asked the users to translate from English to logic

had their direct counterparts in the examples provided.

•   Given the exact rules of what constitutes an acceptable translation, the reasoning needed to reach it

is not much easier than formulating the SQL. This point has varied between different users, with many

mentioning that they would actually welcome logic queries as a viable alternative. Given the proliferation

of SQL as a de-facto standard, it was difficult to expect that everyone would welcome such a paradigm

shift, but it was positive to see that at least some people could notice the potential of the tool.

•   The tool needs to make more use of the richness of SQL to be practically useful. This was a very valid

criticism, which comes as a consequence of the sophistication of the compiler. Currently it is able to

translate logic only to a very limited subset of SQL.

25

Page 26: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 26/31

5.3 Performance Evaluation

One of our priorities was to make sure that our web application was highly responsive all the time. We used

client-side JavaScript and AngularJS framework for our front-end. In order to improve the user performance

and to make the web application more responsive, we used techniques such as AJAX that allowed to load data

dynamically and asynchronously. Moreover, we used lightweight JSON format for making the transfer of data

from frontend to backend and vice-versa fast to avoid redundantly using resources of the server. Thus, thisenhanced our productivity by making deployment faster.

The translator did not have a large performance requirement, if it had been slow then loading indicators could

have been added to the user interface. The majority of the time spent in the translator is actually during

communication with the database server, this is something cannot really be optimised however by caching the

schema some time could be saved for later queries. This caching strategy was not added because performance

was not an issue.

5.4 Project management

Along with evaluating our project we also evaluated our team and the progress we made each week. As wechoose to follow parts of the Scrum development method we used an online platform to keep track of our

progress during development and assign tasks to each member.

As Agile requires periodic development cycles we decided that the best time frame for one cycle is one week.

Our initial tasks were based on our project specifications and the first meeting with our supervisor. As the

project progressed we added more tasks to our online board according to what our supervisor requested.

Our progress chart shows that initially our progress was made slowly until we had a better idea on what the

project entitles. Also the chart shows that our initial tasks were rather large to fix this we further split one large

task into smaller parts. Some of our development cycles were affected by the amount of outside work we had

in that week, this can be observed as we had cycles where most of the work was done at the end of the week.

Most of the new tasks were added to our planning board after each weekly meeting with our supervisor, although

there were times when we added new tasks after one of our team meetings.

Figure 13: Development cycle task process

5.5 Evaluating deliverables

A straightforward way of evaluating the success of a project is to revisit the requirements. Here we refer to

Section 1.2 where the key objectives of the project were defined.

26

Page 27: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 27/31

•   Functionality.  We have been successful in developing a translator capable of converting predicate logic

queries to SQL. Support is provided for quantification, negation, binary connectives, resulting in possibly

complex SQL queries that include joins. There are some minor issues that we have not managed to fully

look into due to time constraints, and are therefore not implemented—as an example, using an variable

from an outer scope inside an inner scope introduced by the general quantifier (∀) will be ignored. Two

major ideas that were not implemented are the query optimizer and support for write operations. The

former was not a firm requirement and we have mostly considered it as a possible extension of theprimary tool that supports querying. As for the optimization, some of our queries are still far from

optimal. As an example, because binary connectives are considered pairwise without regard for their

possible commutativity, a query of the form

r.a1(. . .) ∧ r.a2(. . .) ∧ . . . ∧ r.an(. . .)

will result in  n  − 2  joins, even though none are required. For the most part, this is not a performance

problem, given that the SQL client is most likely able to apply an optimization of its own. By way of 

this, our tool is perhaps more clearly useful as a query executor  rather than a  translator .

•  Ease of use.  This was one of our main concerns throughout the stages of the project, from the compiler

to the web front-end. The syntax of the logic accepted by the translator is not far removed from the usualsyntax, and we tried to not diverge too far from it. The results of the usability study suggest that, even

in spite of the learning curve being somewhat steep for some users, it did not seem to represent enough

of a hindrance that a user may give up on trying to use logic for database querying. The user interface

was designed with clarity in mind. End-users seemed to find their way around it easily, from entering

the database connection settings and establishing a connection to quickly formatting the query thanks to

syntax highlighting, autocompletion, and dedicated support for symbol insertion.

•   Portability. The tool is fully portable; using standard web frameworks and technologies it can run on any

major browser. Offline support is provided and a locally hosted database can be queried just as well as a

remote one. Third-party database library and using only ANSI SQL code in the translator allowed us to

support most relational database standards.

As a group we are satisfied with the outcome of the project. Given the time constraints, we have managed to

developed a usable tool that satisfied all crucial requirements, and which the targeted users are certain to find at

least somewhat useful.

6 Conclusion and Future Extensions

6.1 Conclusion

Overall we are satisfied with the outcome of the project. We managed to achieve our initial target of translating

predicate logic to SQL queries with a fully functioning web application as our front end. Although not all goals

were definitely met, we are confident that our target user groups will find it beneficial to their learning and

database management experience.

Developing ATLS was not an easy task. It required us to first strengthen our understanding of both predicate

logic and SQL, and to develop a large theoretical framework before any translation code could be attempted.

We believe it was the right approach and the implementation work would require much more effort otherwise.

6.2 Front-end

The core requirements of the user interface have been met however there is still room for improvement. Twomajor extensions were planned if there was extra time. The first extension is having a user account system

that would allow the customized layout and queries to be saved. This would mean that users could resume

working instantly instead of having to setup the editor to their preferred layout. The second extension was code

27

Page 28: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 28/31

completion. ACE has good support for code completion so the major work would be in the translator. It would

require the lexer and parser to support partial parsing. Then analysis of the final state of the parsing would need

to be performed to determine which tokens are valid, as well as checking what variables and predicates might

be valid in the context. Implementing dockspawn using native angular concepts would have created slightly

clean code in places, removing the need for some tight coupling.

During development of the user interface, two main areas proved difficult, changing requirements and testing.

Whilst the main functional requirements remained constant throughout the project, there were numerous smalladditions and changes made. This meant that code and layouts were having to be rewritten quite often. The

problem was mostly resolved with the final, fully customizable layout because the layout could be changed on

the spot without having to change any code. Overall, the frontend and middleware was fully rewritten at some

point during the projects duration.

Automated testing also proved difficult for the user interface because there was no clear way of testing it

automatically. We tried some user interface automation testing libraries such as Selenium but found that the

overhead of managing the tests combined with the frequency of changes meant that it was not a viable option.

As the interface was fairly simply we have decided to test it manually in the end.

If this system were to be used in production an SSL certificate would be required to prevent the database

connection details (and user account details) being stolen in transit.

6.3 Translation

Though we implemented the translation for all basic SQL qeuries, there is still a number of improvements and

possible extensions that would make our application even better.

For instance, we are only translating two joins, cross and equi-join, at the moment. Given sufficient time, we

can extend the translator to translate the remaining joins. Secondly, our produced queries are correct but not

always optimal as they follow a rigid formula in translation. Optimization of queries can be done on a case by

case basis but it takes a very long time.Additionally, as expected, our translator also suffers from producing queries which are not readable. This is

due to the same reasons as above. Our queries might not be user friendly and intuitive. This is something that

can be improved by optimizing the translator. Also, we also have not included support for some advance SQL

functions like sorting. Moreover, currently we only support read function, given enough time, we would like to

explore write function too.

28

Page 29: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 29/31

A Appendices

A.1 Hallway testing

Below is the interface presented to users during hallway testing.

A.2 Sample Translations

The following examples demonstrate some of the more involved queries accepted by ATLS. Note that in those

instances the generated code can often be simplified.

•  Suppose we want to obtain the name and department of the employee who has the highest salary. This

can be written in logic as:

29

Page 30: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 30/31

∃e, s(employee.name(e, n) ∧ employee.department(e, d) ∧ employee.salary(e, s)

∧¬∃x, y(employee.salary(x, y) ∧ employee.department(x, d) ∧ (s < y)))

Ann SQL translation generated by ATLS will be:

SELECT   employee.name, employee.department

FROM   employee   JOIN   employee   AS   employee1   ON   (employee.eid   =   employee1.eid)

 WHERE   (NOT   ((EXISTS   (SELECT   employee.eid, employee.salary, employee.department

FROM   employee

 WHERE   employee1.salary   <   employee.salary

AND   employee.department   =  employee.department))))

•   In another instance, we may want to obtain the name of all employees that are project managers of 

projects with a cost bigger than 100000. This can be written in logic as:

∃x(employee.name(x, n) ∧ ∀y(project.manager(y, x) →  (project.cost(y, c) ∧ c > 100000)))

The SQL generated by ATLS in this instance will be:

SELECT   employee1.name

FROM   employee   AS   employee1

 WHERE   (NOT   ((EXISTS   (SELECT   project1.pid, project1.cost

FROM   project   AS   project1

 WHERE   project1.manager   =   employee1.eid

EXCEPT SELECT   project1.pid, project1.cost

FROM   project   AS   project1

 WHERE   (NOT   (project1.cost   > 100000))

AND   project1.manager   =   employee1.eid))))

•   Again, we may want to obtain the name of all employees that are project managers of projects with a cost

greater than £ 100,000. We may write this in logic as:

∃x(employee.name(x, n) ∧ ∃y, z(project.manager(y, x) ∧ project.manager(z, x) ∧ z = y)

The SQL generated by ATLS for this formula will be:

SELECT   employee1.name

FROM   employee   AS   employee1

 WHERE   (EXISTS   (SELECT   project1.pid, project2.pid

FROM   project   AS   project1

JOIN   project   AS   project2   ON   (project1.manager   =   project2.manager)

 WHERE   (project2.pid   <>   project1.pid)AND   (project1.manager   =   employee1.eid

AND   project2.manager   =   employee1.eid)))

30

Page 31: Automatic Translation of First-order Predicate Logic to SQL

8/9/2019 Automatic Translation of First-order Predicate Logic to SQL

http://slidepdf.com/reader/full/automatic-translation-of-first-order-predicate-logic-to-sql 31/31

References

[1] David Beazley. PLY (Python Lex-Yacc). http://www.dabeaz.com/ply/.

[2] Ian Hodkinson. Predicate logic. C140 Logic lecture notes, Department of Computing, Imperial College

London, 2014.

[3] J. Karlsson and K. Ryan. A cost-value approach for prioritizing requirements.  Software, IEEE , 14(5):67–74, Sep 1997.

[4] Peter McBrien. SQL: An Implementation of the Relational Algebra.

http://www.doc.ic.ac.uk/ pjm/adb/lectures 2014/sql-lecture.pdf, 2014.

[5] Peng Ning. Database Management Systems: Tuple Relational Calculus.

http://discovery.csc.ncsu.edu/Courses/csc742-S02/T08 RelationalCalculus 6.pdf, 2014.

[6] James Shore and Shane Warden.  The Art of Agile Development . O’Reilly Media, Inc, 2008.

[7] Wikipedia. SQL. http://en.wikipedia.org/wiki/SQL, 2014.

[8] Steve Zdancewic. CIS 341: Compilers. Intermediate representations.http://www.seas.upenn.edu/ cis341/current/lectures/lec09.pdf.


Recommended