Subsections


Quick Reference Manual

This OQL quick reference manual presents consise information about the builtin and library functions and methods, the special variables, and the eyedboql tool. The standard library source code is presented and it provides a quick reference card containing all the language constructs.


Builtin and Library Functions and Methods

OQL provides a few builtin and library functions. The builtin functions are written in C++ and cannot be overriden while the library functions are written in OQL and may be redefined by the user. The code for the library functions can be found in the section The Standard Library Package. The EYEDB system classes object, database, connection and EyeDB contains builtin class and instance methods that can be accessed from OQL. Some of these methods are briefly introduced in this section.


Type Predicat Functions


is_int(x)		: returns true if x is an int

is_double(x) : returns true if x isa double; otherwise, returns false
is_string(x) : returns true if x isa string; otherwise, returns false
is_oid(x) : returns true if x isan oid; otherwise, returns false
is_num(x) : returns true if x isan number (int, float or char);otherwise, returns false
is_bool(x) : returns true if x isa bool; otherwise, returns false
is_bag(x) : returns true if x isa bag; otherwise, returns false
is_set(x) : returns true if x isa set; otherwise, returns false
is_array(x) : returns true if x isa array; otherwise, returns false
is_list(x) : returns true if x isa list; otherwise, returns false
is_coll(x) : returns true if x isa collection; otherwise, returns false
is_struct(x) : returns true if x isa struct; otherwise, returns false
is_empty(x) : returns true if x isnil; otherwise, returns false

Collection Conversion Functions

The collection conversion functions take one collection argument and convert this collection to another collection type and returns the converted collection.


toset(coll)		: converts coll to a set

tolist(coll) : converts coll to a list
tobag(coll) : converts coll to a bag
toarray(coll) : converts coll to a array
listtoset(coll) : checks that coll is a list then converts coll to a set
bagtoset(coll) : checks that coll is a bag then converts coll to a set
arraytoset(coll) : checks that coll is a array then converts coll to a set
listtobag(coll) : checks that coll is a list then converts coll to a bag
settobag(coll) : checks that coll is a set then converts coll to a bag
arraytobag(coll) : checks that coll is a array then converts coll to a bag
bagtolist(coll) : checks that coll is a bag then converts coll to a list
settolist(coll) : checks that coll is a set then converts coll to a list
arraytolist(coll) : checks that coll is a array then converts coll to a list
bagtoarray(coll) : checks that coll is a bag then converts coll to a array
settoarray(coll) : checks that coll is a set then converts coll to a array
listtoarray(coll) : checks that coll is a set then converts coll to a array

Sort Functions

These functions are used to sort collection of sortable atom of homogeneous types: int, char, float or string.


sort(coll)		: coll must a be a collection of homogeneoussortable atoms;

sorts and returns this collection
rsort(coll) : coll must a be a collection of homogeneoussortable atoms;
reverse sorts and returns this collection
isort(coll, idx) : coll must a be a collection of listor array
of homogeneous sortable atoms;
idx must be of int type;
sorts the collection of collections according to the
#idx elementof the inner collection
risort(coll, idx) : same as previous function, but perform a reverse sort

Collection Miscelleanous Functions


first(coll)		: returns the first element of coll

car(coll) : returns the first element of coll
last(coll) : returns the last element of coll
cdr(coll) : returns all elements of coll but the first
getn(coll, n) : returns at most n elements of coll
count(coll) : returns the count of elements of coll
identical to coll[!], but less efficient
sum(coll) : returns the sum of the numbers of coll
avg(coll) : returns the float average of the numbers coll
distinct(coll) : eliminates duplicates of coll
flatten(coll) : recursive flattening of coll
flatten1(coll) : one level flattening of coll
min(coll) : returns the minimal number of coll
max(coll) : returns the maximal number of coll
forone(coll, f, data) : if f(e, data) for one elemente
of coll, returns true;
otherwise returns false;
forall(coll, f, data) : if f(e, data) for all elemente
of coll, returns true;
otherwiser returns false;

String Function Functions


tolower(str)		: converts (and returns) string str into lowercase

toupper(str) : converts (and returns) string str into uppercase
tocap(str) : converts the first character and each characterfollowing
a _ of str into an uppercase
strlen(str) : returns the length of str;
same as str[!], but less efficient
substring(str, from, len) : returns the sub-string of str
from the #from to the
from+len characters;
same as str[from:from+len] but less efficient

Query Functions


delete_from(class)		: deletes all the instances of a given class

get_from(class) : gets all the instances of a given class

Useful Functions


assert(cond)		: throws an exception is cond is not true

assert_msg(cond, msg) : throws the exception message msg if cond is not true
interval(from, to) : returns a list composed of the numberfrom from to to

Native Methods of the Class object

The native methods of the class object allows us to perform a few action such as getting the oid of an instance getOid(), getting the database of an instance getDatabase() or converts the instance to its string representation toString(). For instance, to apply this last method to the first Person instance: first(select Person).toString().

All the native methods of the class object are instance methods.

oid getOid()		 : returns the oid of the object

string toString() : returns the string representation of the object
database *getDatabase() : returns the database instance ofthe object
void setDatabase(in database *) : changes the database of the object
void store() : stores the object in the database
object *clone() : clones the object; returns the clone
int getCTime() : returns the creation time of the object (seconds from 1/1/1970)
int getMTime() : returns the last modification time of the object
string getStringCTime() : returns the string representation ofthe creation time of the object
string getStringMTime() : returns the string representation ofthe creation time of the object
bool isRemoved() : returns true if the object is removed;false otherwise
bool isModify() : returns true if the object is modified;false otherwise

Native Methods of the Class connection

All the native methods of the class connection are instance methods. an object obtained using the new operator, They can be applied on a database object that can be either the current connection oql$db->getConnection() either an object obtained using the new operator, for instance: new <> connection().

void open()		 : opens a new connection with default host and port

void open(in string host, in string port) : opens a new connectionusing host and port
void close() : closes the connection

Native Methods of the Class database

The following methods are the instance methods of the class database: They can be applied on a database object that can be either oql$db either an object obtained using the new operator, for instance: new <> database(name : "foo").

void open(		in connection *conn,

in int mode) : opens a new database using the connection
conn and the open flag mode mode
void open( in connection *conn,
in int mode,
in string userauth,
in string passwdauth) : opens a new database using the connection conn,
the open flag mode mode and the authentication
userauth/passwdauth
void close() : closes the database
connection *getConnection() : returns the connection tied tothe database
int getOpenMode() : returns the open flag mode of the database
int getVersionNumber() : returns the version number of the database
string getVersion() : returns the string version of the database

void removeObject(in oid) : removes the object whose oid is given

void transactionBegin() : begins a new transaction
void transactionBegin(in string mode) : begins a new transactionin mode mode
void transactionCommit() : commits the current transaction
void transactionAbort() : abort the current transaction

bool isInTransaction() : returns true ifa transaction is in progress;
false otherwiser

Native Methods of the Class EyeDB

All the native methods of the class EyeDB are class methods.


string getConfigValue(in string s)		 : returns thestring value of the configuration variable s

int getVersionNumber() : returns the EYEDB current version number
string getVersion() : returns the EYEDB current stringversion
string getArchitecture() : returns the architecture of the current server
string getDefaultCompiler() : returns the C++ compiler used tocompile the current server


Special Variables

The following variables are predefined or have a special meaning:

oql$variables		 : list containing the name of all variables

oql$functions : list containing the name of all functions
oql$result : the result atom of the last statement
oql$db : object atom instance of the classdatabase denoting the current database
oql$minint : the minimal integer 0x8000000000000000
oql$maxint : the maximal integer 0x7FFFFFFFFFFFFFFF
oql$minfloat : the minimal float 4.94065645841246544e-324
oql$maxfloat : the maximal float 1.79769313486231570e+308

The eyedboql Tool

eyedboql is a tool that allows you to execute interactively OQL statements. This tool is similar to the Oracle sqlplus and Sybase isql well known tools.

Running eyedboql

The simplest way to run eyedboql is to type eyedboql as follows (assuming that $ is your shell prompt):
$ eyedboql
Welcome to eyedboql.
  Type `\help' to display the command list.
  Type `\copyright' to display the copyright.
?
The string ``? `` is the default prompt for eyedboql.

In an eyedboql session, anything you type is interpreted as an OQL construct (or a part of an OQL construct),
Nevertheless, if the first word of an input line begins with the escape character ``
'', this word is interpreted as an eyedboql internal command. There are about 30 internal commands, but you need to know only of few of them to use eyedboql.

The purpose of the main internal commands is:
- to create or delete databases,
- to open a database,
- to begin, commit or abort a transaction,
- to set the current user and password,
- to execute the contents of a file,
- to display the string representation of an object,
- to display the HTML representation of an object in a WEB browser,
- to change the prompts and the escape character.


Executing Statements

eyedboql allows us to execute OQL statements in an interactive way. For instance, to perform the addition 1+3:
$ eyedboql
Welcome to eyedboql.
  Type `\help' to display the command list.
  Type `\copyright' to display the copyright.
? 1+3;
= 4
?
The string ``= '' preceedes the result atom (if any) of your statement; in the current example, the result atom is the evaluation of the expression statement 1+3;.


Execution Process

Each complete statement typed is sent to the OQL interpreter, A complete statement has a special meaning: it is any sequence of characters:
a. that end with a semi-colon and
b. which parenthesis are balanced and
c. which brakets are balanced and
d. which braces are balanced.

While the statement is not complete, eyedboql prompts the ``second prompt'' (``» '' by default) after each newline.
Once the statement is complete, it is sent to the OQL interpreter, then the atom result is display (if any) after the string ``= '' and the main prompt ``? '' is displayed again.

For instance, the input sequence of characters ``1+newline3newline;'' gives:
? 1+
>> 3
>> ;
= 4
while the input sequence ``{ a := 1+3;newlinec := 2+94;newlined := a+c}'' gives:
? { a := 1+3;
>> c := 2+94;
>> d := a+c}
?
Note that no ``= result atom'' is echoed because a compound statement does not return any atom.

This last example:
? while (true) {
>>   a++;
>>   b++;
>> }
>>
>> ;
?
shows the necessity of typing a semicolon after the while statement although a while statement does not need to end by a semi-colom in the OQL specifications.


Getting Started

By default in an eyedboql session, the database EYEDBDBM is opened in read-only mode. To use another database, one must use either the command line option -db either the
open
internal command.

To start to play with eyedboql one needs to know the following five internal commands:

  1. open
    database [rw$\vert$ro] local trsless: opens the database in read-write (rw) or read-only (ro or no option) mode. If local is there, database is opened in a local mode. If trsless is there database is opened in transaction-less mode.
    For instance ``
    open foo rw
    '' opens the database foo is read-write mode.

  2. print
    [sequence of oids] other options: if a sequence of oids is given: loads the object corresponding to each oid and displays its string representation,
    if no sequence of oids is given: loads the object corresponding to each oid returned by the last statement and displays its string representation.
    For instance, ``select Person;'' will return a bag containing the oid of each Person instance.
    The internal command ``
    print
    '' typed after that will loads and displays of the corresponding Person instances.
    The other options are one or more space-separated of the followings:
    
    		full		: loads and displays object using the full recursive mode
    
    ctime : displays the creation time of the object
    mtime : displays the last modification time of the object
    contents : displays the contents of collections
    native : displays the native attributes
    all : means ``ctime mtime contents native''
    For instance ``
    print full contents
    '' will load and display the objects and their collection contents in a full recursive mode.

  3. commit
    : commits the current transaction

  4. abort
    : aborts the current transaction

  5. quit
    or ^D: quits the current eyedboql session
Note that a transaction is started automatically before the first complete statement of the sesssion of before the complete statement immediately following
commit
or
abort
internal command.

Here is a commented example showing the use of these internal commands:

run eyedboql:
$ eyedboql
Welcome to eyedboql.
  Type `\help' to display the command list.
  Type `\copyright' to display the copyright.
open the database person in read-write mode:
? \open person rw
get the first person whose name is "john" and display it:
? john := first(select Person.name = "john");
= 66373.12.4008447:oid
? \print
66373.12.4008447:oid Person = { 
        name = "john";
        age = 32;
        addr Address = { 
                street = "clichy";
                town = "Paris";
                country = NULL;
        };
        cstate = Sir;
        *spouse 66891.12.2738687:oid;
        cars set<Car*> = set { 
                name       = "";
                count      = 4;
                dimension  = 1;
                reference  = true;
                magorder   = 4;
        };
        children array<Person*> = array { 
                name       = "";
                count      = 0;
                range      = [0,0[;
                dimension  = 1;
                reference  = true;
                magorder   = 4;
        };
        x = NULL;
};
change the name of john to "JOHNNY":
? john.name := "JOHNNY";
= "JOHNNY"
retrieve the person whose name is "JOHNNY" and compares it to john using assert : all is fine, no error is raised!
? assert(john = first(select Person.name = "JOHNNY"));
abort the transaction and look for the person whose name is "JOHNNY": no person is returned! this is ok as the transaction was aborted:
? \abort
? select Person.name = "JOHNNY";
= list()
change the name of john to "JOHNNY" again and commit the transaction:
? john.name := "JOHNNY";
= "JOHNNY"
? \commit
then retrieve again the person whose name is "JOHNNY" and compare it to john using assert: all is fine, no error is raised!
? assert(john = first(select Person.name = "JOHNNY"));
quit eyedboql session
? \quit
$
We are going to conclude this section by this important note:
as introduced previously, the current transaction will be committed (resp. aborted) by a
commit
(resp.
abort
) command.
If you quit eyedboql before committing (resp. aborting) the transaction, it will be automatically aborted, so all your changes will be lost.
This is the default behaviour. This behaviour can be changed by using the
commitonclose
internal command.


Command Line Options

The eyedboql command line options are as follows:

		Program Options:

-d <name>, -database=<name> Database name
-r, -read Open database in read mode
-w, -read-write Open database in read/write mode
-s, -strict-read Open database in strict read mode
-l, -local Open database in local mode
-c <command>, -command=<command> OQL command to execute
-p, -print Display all the objects loaded
-full Full recursive mode is used to display objects
-commit Commits the current transaction on close
-i, -interact Enter interpreter after executing file or commands
-e, -echo Echo each command
-admin Open database in admin mode
-h, -help Display this message
<file> File(s) to execute

Common Options:
-U <user>|@, -user=<user>|@ User name
-P [<passwd>], -passwd[=<passwd>] Password
-host=<host> eyedbd host
-port=<port> eyedbd port
-inet Use the tcp_port variable if port is not set
-dbm=<dbmfile> EYEDBDBM database file
-conf=<conffile> Configuration file
-logdev=<logfile> Output log file
-logmask=<mask> Output log mask
-logdate=on|off Control date display in output log
-logtimer=on|off Control timer display in output log
-logpid=on|off Control pid display in output log
-logprog=on|off Control progname display in output log
-error-policy=<value> Control error policy: status|exception|abort|stop|echo
-trans-def-mag=<magorder> Default transaction magnitude order
-arch Display the client architecture
-v, -version Display the version
-help-eyedb-options Display this message
For instance, to execute the statement ``delete_from(Person)'' on the database person:
$ eyedboql -d person -w -c "delete_from(Person)"
$
To execute the command ``persons := (select Person)'' and then enter the interactive mode of eyedboql:
$ eyedboql -d person -w -c "persons := (select Person)" -i
Welcome to eyedboql.
  Type `\help' to display the command list.
  Type `\copyright' to display the copyright.
?
To execute the file mylib.oql:
$ eyedboql -d person -w mylib.oql


The Standard Library Package

The stdlib.oql file contains a few basic library functions. It can be found in the directory libdir/eyedb/oql. It is automatically imported when opening an OQL session. The following code, extracted from this file, provides an interesting way to understand OQL.
//
// minimal and maximal integer values
//

oql$maxint := 0x7FFFFFFFFFFFFFFF;
oql$minint := 0x8000000000000000;

nulloid := 0:0:0:oid;
NULLOID := 0:0:0:oid;

//
// type predicat functions
//

define is_int(x)    as (typeof x == "integer");
define is_char(x)   as (typeof x == "char");
define is_float(x)  as (typeof x == "float");
define is_string(x) as (typeof x == "string");
define is_oid(x)    as (typeof x == "oid");
define is_object(x) as (typeof x == "object");
define is_num(x)    as (is_int(x) || is_float(x) || is_char(x));
define is_bool(x)   as (typeof x == "bool");
define is_bag(x)    as (typeof x == "bag");
define is_set(x)    as (typeof x == "set");
define is_array(x)  as (typeof x == "array");
define is_list(x)   as (typeof x == "list");
define is_coll(x)   as (is_list(x) || is_array(x) || is_set(x) || is_bag(x));
define is_struct(x) as (typeof x == "struct");
define is_empty(x)  as (typeof x == "nil");

//
// void(x): evaluates argument and returns nil
//

define void(x) as (x, nil);

function assert(|cond) {
  r := eval cond;
  if (!r)
    throw "assertion failed: '" + cond + "'";
}

function assert_msg(|cond, msg) {
  r := eval cond;
  if (!r)
    throw "assertion failed: '" + msg + "'";
}

//
// min(l): returns the minimal integer in a collection
//

function min(l) {
  msg := "function min(" + (string l) + "): ";
  if (!is_coll(l))
    throw msg + "collection expected";

  m := oql$maxint;

  for (x in l) {
    if (x != null) {
      if (!is_num(x))
        throw (msg + "numeric expected");
      if (x < m) 
        m := x;
    }
  }

  return m;
}

//
// max(l): returns the maximal integer in a collection
//

function max(l) {
  msg := "function max(" + (string l) + "): ";
  if (!is_coll(l))
    throw msg + "collection expected";
  m := oql$minint;
  for (x in l) {
    if (x != null) {
      if (!is_num(x))
        throw (msg + "numeric expected");
      if (x > m)
        m := x;
    }
  }
  return m;
}

//
// first(l): returns the first element in a list or array
//

function first(l) {
  if (!is_coll(l)) // if (!is_list(l) && !is_array(l))
    throw "function first: collection expected";

  start := 0;
  f := nil;
  for (x in l)
    if (start == 0) {
      start := 1;
      f := x;
      break;
    }
  return f;
}

car := &first;

//
// last(l): returns the last element in a list or array
//

function last(l) {
  if (!is_coll(l)) // if (!is_list(l) && !is_array(l))
    throw "function last: list or array expected";

  f := nil;
  for (x in l)
    f := x;
  return f;
}

//
// cdr(l): returns all elements in a collection except the first one
//

function cdr(l) {
  if (!is_coll(l)) // if (!is_list(l) && !is_array(l))
    throw "function cdr: list or array expected";

  r := list();
  n := 0;
  for (x in l) {
    if (n != 0)
      r += x;
    n++;
  }
  return r;
}

//
// getn(l, n): returns all elements in a collection
//

function getn(l, n) {
   rl := list();
   cnt := 0;

   for (x in l) {
     if (cnt++ >= n)
       break;
     rl += x;
   }

   return rl;
}

//
// getrange(l, f, nb): returns all elements in a collection from element from
//
// identical to l[f:f+nb]
//

function getrange(l, f, nb) {
  if (!is_list(l) && !is_array(l))
    throw "function getrange: list or array expected";

   rl := list();
   cnt := 0;

   max := f + nb;

   for (x in l) {
     if (cnt >= max)
       break;

     if (cnt >= f)
       rl += x;

     cnt++;
   }

   return rl;
}

//
// count(l): returns element count of a collection
//

function count(l) {
  if (typeof l == "nil")
    return 0;
  if (!is_coll(l))
    throw "function count: collection expected, got " + typeof(l);
  return l[!];
}

//
// interval(x, y): constructs an integer list bounded by 'x' and 'y'
//

function interval(x, y) {
  n := x-1;
  l := list();
  while (n++ < y)
    l += n;
  return l;
}

//
// sum(l): returns the sum of collection elements
//

function sum(l) {
  if (!is_coll(l))
    throw "function sum: collection expected";
  n := 0;
  for (x in l)
    n += x;
  return n;
}

//
// avg(l): returns the average of collection elements
//

function avg(l) {
  if (!is_coll(l))
    throw "function avg: collection expected";
  return float(sum(l))/count(l);
}

//
// is_in(l, z): returns true in element 'z' is in collection 'l'
//

function is_in(l, z) {
  for (x in l)
    if (x == z)
      return true;

  return false;
}

//
// distinct(l): returns distinct elements in a collection
//

function distinct(l) {
  if (is_list(l)) ll := list();
  else if (is_bag(l)) ll := bag();
  else if (is_array(l)) ll := array();
  else if (is_set(l)) ll := set();
  else throw "function distinct: collection expected";

  for (x in l)
    if (!is_in(ll, x))
      ll += x;

  return ll;
}

//
// flatten(l): full recursive flatten function
//

function flatten(l) {
  if (!is_coll(l))
    return l;
  ll := list();
  for (x in l)
    if (is_coll(x))
      ll += flatten(x);
    else
      ll += x;

  return ll;
}

//
// flatten1(l): 1-level recursive flatten function
//

function flatten1(l) {
  if (!is_coll(l))
    return l;

  ll := list();
  for (x in l)
    ll += x;
  return ll;
}
            
//
// tolower(s): returns lower case string
//

function tolower(s) {

  n := 0;
  x := "";
  delta := 'a' - 'A';

  while (s[n] != '\000') {
    if (s[n] >= 'A' && s[n] <= 'Z')
      x += string(char(s[n] + delta));
    else
      x += string(s[n]);
    n++;
  }

  return x;
}

//
// toupper(s): returns upper cased string
//

function toupper(s) {

  n := 0;
  x := "";
  delta := 'A' - 'a';

  while (s[n] != '\000') {
    if (s[n] >= 'a' && s[n] <= 'z')
      x += string(char(s[n] + delta));
    else x += string(s[n]);
    n++;
  }

  return x;
}

//
// tocap(s): returns capitalized word string
//

function tocap(s) {

  n := 1;
  x := "";
  delta := 'A' - 'a';

  s := tolower(s);

  if (s[0] >= 'a' && s[0] <= 'z')
    x += string(char(s[0] + delta));

  while (s[n] != '\000') {
    if (s[n] == '_')
      x += string(char(s[++n] + delta));
    else
      x += string(s[n]);
    n++;
  }

  return x;
}

//
// Collection Conversion Functions
//

//
// General Conversion Functions
//

function toset(l) {
  if (!is_coll(l))
    throw ("function toset: collection expected, got " + typeof(l));

  if (!is_set(l)) {
    s := set();
    for (x in l)
      s += x;
    return s;
  }

  return l;
}

function tolist(l) {
  if (!is_coll(l))
    throw ("function tolist: collection expected, got " +  typeof(l));

  if (!is_list(l)) {
    s := list();
    for (x in l)
      s += x;
    return s;
  }

  return l;
}

function tobag(l) {
  if (!is_coll(l))
    throw ("function tobag: collection expected, got " +  typeof(l));

  if (!is_bag(l)) {
    s := bag();
    for (x in l)
      s += x;
    return s;
  }

  return l;
}

function toarray(l) {
  if (!is_coll(l))
    throw ("function toarray: collection expected, got " +  typeof(l));

  if (!is_array(l)) {
    s := array();
    for (x in l)
      s += x;
    return s;
  }

  return l;
}

//
// toset family Conversion Functions
//

function listtoset(l) {
  if (!is_list(l))
    throw ("function listtoset: list expected, got " + typeof(l));
  return toset(l);
}

function bagtoset(l) {
  if (!is_bag(l))
    throw ("function bagtoset: bag expected, got " + typeof(l));
  return toset(l);
}

function arraytoset(l) {
  if (!is_array(l))
    throw ("function arraytoset: array expected, got " + typeof(l));
  return toset(l);
}


//
// tobag family Conversion Functions
//

function listtobag(l) {
  if (!is_list(l))
    throw ("function listtobag: list expected, got " + typeof(l));
  return tobag(l);
}

function settobag(l) {
  if (!is_set(l))
    throw ("function settobag: set expected, got " + typeof(l));
  return tobag(l);
}

function arraytobag(l) {
  if (!is_array(l))
    throw ("function arraytobag: array expected, got " + typeof(l));
  return tobag(l);
}

//
// tolist family Conversion Functions
//

function bagtolist(l) {
  if (!is_bag(l))
    throw ("function bagtolist: bag expected, got " + typeof(l));
  return tolist(l);
}

function settolist(l) {
  if (!is_set(l))
    throw ("function settolist: set expected, got " + typeof(l));
  return tolist(l);
}

function arraytolist(l) {
  if (!is_array(l))
    throw ("function arraytolist: array expected, got " + typeof(l));
  return tolist(l);
}

//
// toarray family Conversion Functions
//

function bagtoarray(l) {
  if (!is_bag(l))
    throw ("function bagtoarray: bag expected, got " + typeof(l));
  return toarray(l);
}

function settoarray(l) {
  if (!is_set(l))
    throw ("function settoarray: set expected, got " + typeof(l));
  return toarray(l);
}

function listtoarray(l) {
  if (!is_list(l))
    throw ("function listtoarray: list expected, got " + typeof(l));
  return toarray(l);
}

//
// strlen(s): same as s[!]
//

function strlen(s) {
  len := 0;
  while (s[len] != '\000')
    len++;
  return len;
}

//
// substring(str, f, len)
//

function substring(str, f, len) {
  s := "";
  n := 0;
  max := str[!] - f;
  while (n < len && n < max) {
    s += string(str[n+f]);
    n++;
  }

  return s;
}

//
// forone(l, fpred, data): returns true if and only if the function 'fpred'
// returns true for at least one element 'x' in list 'l'
//

function forone(l, fpred, data) {
  for (x in l)
    if (fpred(x, data)) return true;
  return false;
}
        
//
// forone(l, fpred, data): returns true if and only if the function 'fpred'
// returns true for all elements 'x' in list 'l'
//

function forall(l, fpred, data) {
  for (x in l)
    if (!fpred(x, data)) return false;
  return true;
}
        
//
// delete_from(cls): delete all instances of class 'cls'
//

function delete_from(|cls) {
  for (x in (eval "select " + cls))
    delete x;
}

//
// delete_(coll): delete contents of collection coll
//

function delete_(coll) {
  for (x in coll)
    delete x;
}

//
// get_from(cls): returns all instances of class 'cls'
//

function get_from(|cls) {
  eval "select " + cls;
}

//
// generates an unused global symbol
//

function gensym() {
  prefix := "::oql#_#_#";
  for (i := 0; ; i++) {
    varname := prefix + string(i);
    if (!(eval "isset " + varname)) {
      eval varname + " := 0";
      return ident(varname);
    }                        
  }                
}

//
// expression-like for-each function
//

function foreach_expr(|x, |coll, |expr, colltyp ? "list") {
  varname := "_#_#_R_#_#_";

  statement := "push " + varname + " := " + colltyp + "(); " +
    "for (" + x + " in " + coll + ") " +
    "{" + varname + " += " + expr + ";}" +
    "pop " + varname;

  return eval statement;
}

//
// expression-like for-C function
//

function for_expr(|start, |cond, |end, |expr, colltyp ? "list") {
  varname := "_#_#_R_#_#_";

  statement := "push " + varname + " := " + colltyp + "(); " +
    "for (" + start + "; " + cond + "; " + end + ")" +
    "{" + varname + " += " + expr + ";}" +
    "pop " + varname;
   
   return eval statement;
}

//
// expression-like while-C function
//

function while_expr(|cond, |expr, colltyp ? "list") {
  varname := "_#_#_R_#_#_";

  statement := "push " + varname + " := " + colltyp + "(); " +
    "while (" + cond + ")" +
    "{" + varname + " += " + expr + ";}" +
    "pop " + varname;
   
   return eval statement;
}

//
// expression-like do/while-C function
//

function do_while_expr(|expr, |cond, colltyp ? "list") {
  varname := "_#_#_R_#_#_";

  statement := "push " + varname + " := " + colltyp + "(); " +
    "do {" + varname + " += " + expr + ";}" +
    "while (" + cond + ");" +
    "pop " + varname;
  
   return eval statement;
}

function extentof(|classname) {
  return (select one class.name = classname).extent;
}

function countof(|classname) {
  return (select one class.name = classname).extent.count;
}

function objectcount(db := oql$db) {
     objcnt := 0;
     db->transactionBegin();
     for (cl in (select <db> x from class x where
                 x.type != "system" and x.name !~ "<"))
        objcnt += cl.extent.count;
     db->transactionCommit();
     return objcnt;
}

function ifempty(x, y) {
  if (is_empty(x)) 
    return y;
  return x;
}

function null_ifempty(x) {
  return ifempty(x, null);
}

function getone(x) {
  if (is_empty(x)) 
    return null;
  return first(flatten(x));
}

//
// database and transaction management
//

function open_db(db_name_or_id, strmode, user := null, passwd := null) {

  if (strmode == "r")
    mode := DBREAD;
  else if (strmode == "rw")
    mode := DBRW;
  else if (strmode == "rlocal")
    mode := DBREAD|DBOPENLOCAL;
  else if (strmode == "rwlocal")
    mode := DBRW|DBOPENLOCAL;
  else
    throw "invalid open mode: r, rw, rlocal or rwlocal expected, got " +
      strmode;

  if (is_int(db_name_or_id))
    db := new<> database(dbid : db_name_or_id);
  else
    db := new<> database(dbname : db_name_or_id);

  if (user == null)
    db.open(oql$db.getConnection(), mode);
  else
    db.open(oql$db.getConnection(), mode, user, passwd);

  return db;
}

function set_default(db) {
  db->setDefaultDatabase();
}

function begin(db := oql$db) {
  db->transactionBegin();
}

function begin_params(trsmode, lockmode, recovmode, magorder, ratioalrt, wait_timeout, db := oql$db) {
  db->transactionBegin(trsmode, lockmode, recovmode, magorder, ratioalrt, wait_timeout);
}

function commit(db := oql$db) {
  db->transactionCommit();
}

function abort(db := oql$db) {
  db->transactionAbort();
}

//
// miscellaneous
//

function print_function(f) {
  print "function " + (bodyof f) + "\n";
}

function print_functions() {
  cnt := 0;
  for (f in oql$functions) {
    if (cnt > 0) print "\n";
    print_function(f);
    cnt++;
  }
}

function print_variable(v) {
   print string(v) + " = " + string(eval string(v)) + ";\n";
}

function print_variables() {
  for (v in oql$variables) {
    print_variable(v);
    cnt++;
  }
}

function print_classes(system := false) {
  if (system)
    l := (select list(x, x.name) from class x order by x.name);
  else
    l :=  (select list(x, x.name) from class x where x.type = "user" and x.name !~ "<" order by x.name);

  for (c in l) {
    cls := c[0];
    clsname := c[1];
    print "class " + clsname;
    if (cls.parent != NULL && (system || cls.parent.type != "system"))
       print " extends " + cls.parent.name;
    print "\n";
  }
}

function print_obj(o, flags := 0) {
   print o->toString(flags);
}

function print_objs(l, flags := 0) {
   for (o in l)
     print_obj(o, flags);
}

//
// contents_ expression
//

function contents_(coll) {
  r := list();
  for (x in coll) {
   for (s in contents(x)) 
     r += s;
  }

  return r;
};

function println(s) {
  print(s+"\n");
}

function bench(|cmd) {
  t0 := time_stamp::local_time_stamp();
  r := eval cmd;
  t1 := time_stamp::local_time_stamp();
  us := t1->substract(t0).usecs;
  println("Elapsed time: " + string(us/1000.) + " ms");
  return r;
}

;


OQL Quick Reference Card

The following table presents all the OQL statements, expression types and the operators. For the operators common to C++ and OQL, the precedence and associativity is the same.
Quick Reference Card
Statements
expression statement expr ;
selection statement if ( cond_expr ) statement [else statement]
jump statements break [expr] ;
  return [expr] ;
iteration statements while ( cond_expr ) statement
  do statement while ( cond_expr )
  for ( [expr] ; [cond_expr] ; [expr] ) statement
  for ( var in expr ) statement
compound statement { statement }
function definition statement function identifier ([arglist]) compound_statement
empty statement ;
Arithmetic Expressions
add + expr + expr
substract - expr - expr
multiply * expr * expr
divide / expr / expr
shift left « expr « expr
shift right » expr » expr
modular % expr % expr
bitwise and & expr & expr
bitwise inclusive or | expr | expr
bitwise xor ^ expr ^ expr
complement ~ ~ expr
Assignment Expressions
simple assignment := lvalue := expr
add and assign += lvalue += expr
substract and assign -= lvalue -= expr
multiply and assign *= lvalue *= expr
divide and assign /= lvalue /= expr
shift left and assign « lvalue «= expr
shift right and assign » lvalue »= expr
inclusive OR and assign |= lvalue |= expr
exclusive OR and assign & lvalue &= expr
modulo and assign % lvalue %= expr
exclusive OR and assign ^ lvalue ^= expr
Auto Increment & Decrement Expressions
post increment ++ lvalue++
post decrement - lvalue-
pre increment ++ ++lvalue
pre increment - -lvalue
Logical Expressions
logical and && expr && expr
logical and and expr and expr
logical or || expr || expr
logical or or expr or expr
Comparison Expressions
not ! ! expr
not not not expr
equal = expr = expr
equal == expr == expr
not equal != expr != expr
less than < expr < expr
less <= expr <= expr
greater > expr > expr
greater than >= expr >= expr
match regular expression ~ expr ~ expr
match regular expression case insensitive ~~ expr ~~ expr
not match regular expression !~ expr !~ expr
not match regular expression case insensitive !~~ expr !~~ expr
match regular expression like expr like expr
Conditionnal Expressions
conditionnal expression ? : expr ? expr : expr
Expression Lists
comma sequencing , expr , expr
Array Expressions
subscripting [] expr [expr ]
interval subscriptiong [:] expr [expr :expr ]
Path Expressions
member selection . expr . expr
member selection -> expr -> expr
Function Call
function call () expr (expr_list)
Method Invocation
member selection () expr ->expr (arglist)
Eval/Unval Operators
eval eval eval expr
no eval unval unval expr
Identifier Expressions
scope :: :: identifier
is set isset isset identifier
unset unset unset identifier
reference of & & identifier
  refof refof identifier
value of * * identifier
value of valof valof identifier
scope of scopeof scopeof identifier
push onto symbol table push push identifier
push onto symbol table and assign push push expr
pop from symbol table pop pop identifier
Set Expressions
union union expr union expr
intersection intersect expr intersect expr
except except expr except expr
include < expr < expr
include or equal <= expr <= expr
contain > expr > expr
contain or equal >= expr >= expr
Object Creation
new new [new] new_construct
new new new< opt_expr > new_construct
Object Deletion
delete delete delete expr
Collection Expressions
contents contents contents expr
is in in expr in expr
add to collection add to add expr to expr
suppress from collection suppress from suppress expr from expr
set element in or get element from an indexed collection [] expr [ expr ]
append to an indexed collection append/to append expr to expr
empty collection empty empty expr
exists in collection in exists identifier in expr : expr
for all in collection for all for all identifier in expr : expr
for some in collection for for < expr , expr > in expr : expr
Exception Expressions
throw exception throw throw expr
Function Definition
define function define as define identifier [arglist as expr
Conversion
string conversion string string( expr )
integer conversion int int( expr )
character conversion char char( expr )
float conversion float float( expr )
identifier conversion ident ident( expr )
oid conversion oid oid( expr )
Query Expressions
database query select select expr [from {expr [as] identifier} [where expr]] [order by {expr}]
    select expr [from {identifier in expr} [where expr]] [order by {expr}]
Type Information Expressions
class of classof classof expr
typeof of typeof typeof expr
Miscellenaous Expressions
structure of structof structof expr
body of bodyof bodyof expr
length pf [!] expr [!]
import package import import expr

EyeDB manual