OQL - Object Query Language
The goal of this file is to help you get started with OQL. The examples presented in this file refer to classes defined in the file "O2 Tutorial".
Please note that the syntax in some of the examples might need minor adjustment before they will work with the current version of O2. If you find any errors, or places which are unclear, or if you have any suggestions or comments, please let us know (email to Michalis - mpetropo@cs.ucsd.edu). Your help is greatly appreciated.
Introduction
OQL is the way to access data in an O2 database. OQL is a powerful and easy-to-use SQL-like query language with special features dealing with complex objects, values and methods.
Using OQLWe've been able to create classes and write some programs. So far, O2 appears to be like an object-oriented programming language like C++ instead of a database system. Probably the main difference is that O2 supports queries. The queries that you'll be creating will look very similar to that of SQL.
In order to perform queries, you'll need to enter query mode. From within the O2 client, do the command:
SELECT <list of values>
FROM <list of
collections and variable assignments>
WHERE <condition>
The SELECT clause extracts those elements of a collection meeting a specific condition. By using the keyword DISTINCT duplicated elements in the resulting collection get eliminated. Collections in FROM can be either extents (persistent names - sets) or expressions that evaluate to a collection (a set). Strings are enclosed in double-quotes in OQL. We can rename a field by if we prefix the path with the desired name and a colon.
Example Query 1
Give the
names of people who are older than 26 years old:
SELECT SName: p.name
FROM p in People
WHERE
p.age > 26
(hit Ctrl-D)
Dot Notation & Path Expressions
We use the dot notation and path
expressions to access components of complex values.
Let variables t
and ta range over objects in extents (persistent names) of Tutors and TAs
(i.e., range over objects in sets Tutors and TAs).
ta.salary
-> real
t.students -> set of tuples of type tuple(name:
string, fee: real) representing students
t.salary -> real
Cascade of dots can be used if all names represent objects and not a collection.
Example of Illegal Use of Dot
t.students.name, where ta is a TA object.
This is illegal, because ta.students is a set of objects, not a single object.
Example Query 2
SELECT s.name
FROM Tutors t,
t.students s
Here we notice that the variable t that binds to the first collection of FROM is used to help us define the second collection s. Because students is a collection, we use it in the FROM list, like t.students above, if we want to access attributes of students.
Example Query 3
Give the names
of the Tutors which have a salary greater than $300 and have a
student paying more than $30:
SELECT t.name
FROM ( SELECT t FROM Tutors t WHERE t.salary > 300
) r, r.students s
WHERE s.fee >
30
Example Query 4
Give the names of
people who aren't TAs:
SELECT p.name
FROM p in People
WHERE not ( p.name
in SELECT t.name FROM t in TAs )
Set Operations and Aggregation
The standard O2C operators for sets are
+
(union), *
(intersection), and -
(difference). In OQL, the operators are written as
UNION, INTERSECT and EXCEPT , respectively.
Example Query 5
Give the names of TAs
with the highest salary:
SELECT t.name
FROM t in TAs
WHERE t.salary
= max ( select ta.salary from ta in TAs )
The GROUP BY operator creates a set of tuples with two fields. The first has the type of the specified GROUP BY attribute. The second field is the set of tuples that match that attribute. By default, the second field is called PARTITION.
Example Query
6
Give the names of the students and the average fee they
pay their Tutors:
SELECT sname, avgFee: AVG(SELECT p.s.fee FROM partition
p)
FROM t in Tutors, t.students s
GROUP BY sname: s.name
1. Initial collection
We begin from collection Tutors, but technically it is a bag of tuples of the form:
tuple(t: t1, s: tuple(name: string, fee: real) )
where t1 is a Tutor object and s denotes a student tuple. In general, there are fields for all of the variable bindings in the FROM clause.
2. Intermediate collection
The GROUP BY attribute s.name maps the tuples of the initial collection to the value of the name of the student. The intermediate collection is a set of tuples of type:
tuple( sname: string, partition: set( tuple(t: Tutor, s: tuple( name: string, fee: real ) ) ) )
For example:
tuple( sname = "Mike", partition = set( tuple(t1, tuple( "Mike", 10 ) ), tuple(t2, tuple( "Mike", 20 ) ) ) )
where t1,t2,... are all the tutors of student "Mike".
3. Output collection
Consists of student-average fee pairs, one for each tuple in the intermediate collection. The type of tuples in the output is:
tuple(sname: string, avgFee: real)
Note that in the subquery of the SELECT clause:
SELECT sname, avgFee: AVG(SELECT p.s.fee FROM partition p)
We let p range over all tuples in partition. Each of these tuples contains a Tutor object and a student tuple. Thus, p.s.fee extracts the fee from one of the student tuples.
A typical output tuple looks like this:
tuple(sname = "Mike", avgFee = 15)
The whole procedure of GROUP BY operator's evaluation is summarized in the following figure:
Instead of using query mode, you can incorporate these queries
in your O2 programs using the "o2query" command:
run body {
o2 real total_salaries;
o2query(
total_salaries, "sum ( SELECT ta->get_salary \
FROM
ta in TAs )" );
printf("TAs combined salary: %.2f\n",
total_salaries);
};
The first argument for
o2query is the variable in which you want to store the query results. The
second argument is a string that contains the query to be performed. If
your query string takes up several lines, be sure to backslash (\) the carriage
returns.
Change directory executing the
following:
cd
/software/nonrdist/o2_5.0/manuals
You can access the OQL User Manual by opening the
following file:
acroread
oql.pdf