The basic concept of the EYEDB object model is the class which, as in any
traditional object model, model a set
of objects of similar properties (attributes) and behaviors (methods).
The attributes can be basic types, user types, references, arrays, collections.
The methods can be defined in C++ or in OQL (Object Query Language).
ODL allows one to specify classes, attributes, methods, triggers, constraints,
enumerate types, indexes and implementation hints.
We are going to introduced in details all the features of ODL.
// this is a simple line comments /* this is a multi line comments */
byte | 1-byte integer |
char | 1-byte character |
short | 2-byte integer |
int | 4-byte integer |
long | 8-byte integer |
double | 8-byte floating point |
oid | 8-byte internal object identifier |
enum | 4-byte integer |
class C { attribute byte b; attribute char c; attribute short s; attribute int i; attribute long l; attribute double d; attribute oid o; };Notes :
class C { byte b; char c; // ... };
class C { attribute char c1, c2, c3; // NOT correct // ... };
enum E1 { A, // A == 0 B, // B == 1 C // C == 2 }; enum E2 { D = 3, // D == 3 E, // E == 4 F = 100, // F == 100 G, // G == 101 H // H == 102 }; class C { attribute int i; E1 e1; E2 e2; };
class C { attribute byte b_a[4]; // fixed length mono-dimensional array attribute char str[]; // variable size mono-dimensional array attribute int i_a[3][4][8]; // multi-dimensional fixed size array attribute long l_a[][4][8]; // multi-dimensional variable size array };One particular interesting array type is the array of characters, which can be denoted as string as follows:
class C { attribute string s; // <=> char s[] (unlimited size string) attribute string<32> bs; // <=> char bs[32] (bounded string) };Note that in a multi-dimensional array, only the extreme left dimension can be variable:
class C { attribute long l_a1[][4][8]; // correct attribute long l_a2[4][][8]; // NOT correct attribute long l_a2[4][8][]; // NOT correct };
class C1 { attribute int i; }; class C { attribute C1 l_c1; // literal attribute included in C attribute C1 *o_c1; // object attribute referenced by C (or &oc1_1) };Let c an instance of the class C.
Do not confuse the * ODL meaning and the * C/C++ meaning: in C/C++, the * type modifier denotes an address to an area of the indicated type instances: it is a pointer to an address. This pointer can be incremented and decremented to change its location in the area. |
In ODL, the * denotes a reference to one and only one object, it is why the & token is also accepted, although the meaning of this token is a little bit different in C++. |
So, in ODL the construct C1 **oc1 makes no sense, in the same manner that the construct C1 &&oc1 makes no sense in C++. |
class C { attribute C1 l_c1_1[2]; attribute C1 l_c1_2[]; attribute C1 l_c1_3[][10][20]; attribute C1 *o_c1_1[4]; attribute C1 *o_c1_2[]; attribute C1 *o_c1_3[][4][5]; };
class C { attribute set<int> i_lset; // literal set of int attribute set<C1> l_c1_lset; // literal set of C1 literals attribute set<C1 *> o_c1_lset; // literal set of C1 objects attribute set<int> *i_oset; // object set of int attribute set<C1> *l_c1_oset; // object set of C1 literals attribute set<C1 *> *o_c1_oset; // object set of C1 objects attribute bag<C1 *> o_c1_lbag; // literal bag of C1 objects attribute array<C1 *> o_c1_larr; // literal array of C1 objects attribute bag<C1 *> o_c1_lbag[]; // array of literal bag of C1 objects // multi-dimensional array of literal bag of set of array of C1 objects attribute bag<set<array<set<C1 *> > > > x[2][3][4]; };The differences between an array collection (i.e. array<type> and an attribute array (i.e. type []) are:
class C1 { attribute string c1; }; class C2 extends C1 { attribute string c2; }; class C3 extends C2 { attribute string c3; };As in usual object conception, an object of class C2 includes the two attributes c1 and c2 and an object of class C3 includes the three attributes c1, c2 and c3.
class C4 { attribute C1 *oc1; attribute C2 *oc2; attribute C3 *oc3; attribute C1 lc1; attribute C2 lc2; attribute C3 lc3; };The attribute oc1 may be of type C1, C2 or C3.
class C { attribute string s1; attribute string s2; attribute string s3; constraint<notnull> on s1; constraint<notnull> on s2; constraint<unique> on s2; constraint<unique> on s3; };The attribute s1 must not be null.
class C2 extends C { attribute string c2; };When one creates an C2 object, the attributes s1 and s2 must not be null and the attributes s2 and s3 must be unique.
class C { attribute string s1; attribute string s2; attribute string s3; constraint<notnull, propagate = off> on s1; constraint<notnull> on s2; constraint<unique, propagate = off> on s2; constraint<unique> on s3; }; class C2 extends C { attribute string c2; };The notnull constraint on C::s1 and the unique constraint on C1::s2 will not be propagated to C2, but the notnull constraint on C::s1 and the unique constraint on C::s3 will be propagated to C2.
class C1 { attribute string s1; attribute int i1; }; class C { attribute C1 c1; constraint<notnull> on c1.s1; constraint<unique> on c1.i1; };
class A { attribute string sa; attribute B *b; }; class B { attribute string sb; attribute A *a; };In the previous case, EYEDB maintains only partially the referential integrity: for instance, one cannot create an object A with an attribute b which refers an non-existent B object. But, if the referenced B object is removed, the attribute b will still referenced the removed object.
class A { attribute string sa; relationship B *b inverse B::b; // or inverse b }; class B { attribute string sb; relationship A *a inverse A::b; // or inverse a };Note attribute has been replaced by relationship in this case: this is mandatory.
class A { attribute string sa; relationship set<B *> b_set inverse a; }; class B { attribute string sb; relationship A *a inverse b_set;; };and a many-to-many relationship:
class A { attribute string sa; relationship set<B *> b_set inverse a_set; }; class B { attribute string sb; relationship set<A *> a_set inverse b_set;; };
class C1 { attribute string c1; }; class C2 { attribute string c2; int perform(in int size, in string str, out double, in C1 &, inout C2 &); };Note that the & symbol may be replaced by the * symbol or no symbol as anyhow only a persistent object (not a litteral) may be passed to a method call.
class C2 { attribute string c2; int perform(in int size, in string str, out double, in C1 &, inout C2 &); int perform(in double, out string mystr); };One can define OQL methods in ODL. In this case, the name of the arguments must be given:
class C2 { attribute string c2; int append(in string s) %oql{ this.s2 += s; return strlen(this.s); %}; };The OQL this variable denotes the calling instance.
class C { static int perform1(in string); // or classmethod int perform2(in string); instmethod int perform3(in string); // <=> int perform3(in string) };If you want to execute a method on the client side, you must use the keyword client as follows:
class C { instmethod<client> int perform1(in string); classmethod<client> int perform2(in string); instmethod<server> int perform3(in string); // <=> int perform3(...) classmethod<server> int perform4(in string); // <=> classmethod perform3(...) };
class C { attribute string s; // C++ triggers trigger<create_before> c_b(); trigger<create_after> c_a(); trigger<update_before> u_b(); trigger<update_after> u_a(); trigger<load_before> l_a(); trigger<load_after> l_b(); trigger<remove_before> r_b(); trigger<remove_after> r_a(); trigger<create_before> c_b2(); // one can have several create_before triggers // OQL trigger trigger<create_before> l_a2() %oql{ if (strlen(this.s) > 100) throw "invalid length"; %}; };
class C { attribute string s; attribute int i; index on s; index on i; };Note that we cannot define one index on several attributes.
class C { attribute string s; attribute int i; index on s; index on i; }; class C2 extends C { attribute long l; };Indexes are created for C::s, C::i, C2::s and C2::i.
class C { attribute string s; attribute int i; index<propagate=off> on s; index<propagate=off> on i; }; class C2 extends C { attribute long l; };Indexes are created only for only C::s and C::i.
class C1 { attribute int i; attribute double d; }; class C { attribute string s; C1 c1; // literal composite type index on s; index on c1.i; index on c1.d; };
class C { attribute string<32> s; attribute int i; index<type = btree> on s; // default is hash: change to btree index<type = hash> on i; // default is btree: change to hash };Important note: one cannot create a BTree index on a non bounded string. One can set implementation parameters for indexes as follows:
class C { attribute string<32> s; attribute int i; index<type = btree, hints = "degree = 64;"> on s; index<type = hash, hints = "key_count = 4096; initial_size = 4096; extend_coef = 1; size_max = 4096;"> on i; };
EyeDB manual