eyedbodl --gencode=C++ <odlfile>or
eyedbodl --gencode=C++ --package=<package> -d <database>For instance, to generate the schema-oriented C++ API for the person.odl schema:
eyedbodl --gencode=C++ person.odlFor a given package.odl ODL file, the generated files are as follows:
-package=package : Package nameFor instance to generate a schema-oriented C++ API in the directory tmp, prefixing the runtime classes with pp, suffixing C++ files with .cpp, we invoke eyedbodl as follows:
-output-dir=dirname : Output directory for generated files
-output-file-prefix=prefix : Ouput file prefix (default is the package name)
-class-prefix=prefix : Prefix to be put at the begining of each runtime class
-db-class-prefix=prefix : Prefix to be put at the begining of each database class
-attr-style=implicit : Attribute methods have the attribute name
-attr-style=explicit : Attribute methods have the attribute name prefixed by get/set (default)
-schema-name=schname : Schema name (default is package)
-export : Export class instances in the .h file
-dynamic-attr : Uses a dynamic fetch for attributes in the get and set methods
-down-casting=yes : Generates the down casting methods (the default)
-down-casting=no : Does not generate the down casting methods
-attr-cache=yes : Use a second level cache for attribute value
-attr-cache=no : Does not use a second level cache for attribute value (the default)
-namespace=namespace : Define classes with the namespace namespace
-c-suffix=suffix : Use suffix as the C file suffix
-h-suffix=suffix : Use suffix as the H file suffix
-gen-class-stubs : Generates a file class_stubs.h for each class
-class-enums=yes : Generates enums within a class
-class-enums=no : Do not generate enums within a class (default)
-gencode-error-policy=status : Status oriented error policy (the default)
-gencode-error-policy=exception : Exception oriented error policy
-rootclass=rootclass : Use rootclass name for the root class instead of the package name
-no-rootclass : Does not use any root class
eyedbodl --gencode C++ --output-dir=tmp --class-prefix=pp \ --c-suffix=.cpp person.odl
class person { public: static void init(); static void release(); static eyedb::Status updateSchema(eyedb::Database *db); static eyedb::Status updateSchema(eyedb::Schema *m); };
Person(eyedb::Database * = 0); Person(const Person& x); Person& operator=(const Person& x);
Person *p = new Person(&db);does nearly the same things as:
eyedb::Class *cls = db.getSchema()->getClass("Person"); eyedb::Object *o = cls->newObj(&db);The major difference is that in the second case, an eyedb::Object instance (in fact an eyedb::Struct instance) is created while in the first case an Person (which inherits from eyedb::Struct) instance is created.
Person *p1 = new Person(&db); Person p2 = *p1;
Person *p1 = new Person(&db); Person *p2 = new Person(&db); *p2 = *p1;
class Person : public Root { // ... virtual Person *asPerson() {return this;} virtual const Person *asPerson() const {return this;} virtual Employee *asEmployee() {return (Employee *)0;} virtual const Employee *asEmployee() const {return (const Employee *)0;} // ... };These methods are very useful to process safe down casting. The down casting may be used in several cases. For instance, if you instantiate an Employee object as follows:
extern void display(Person *); Employee *empl = new Employee(&db); display(empl);the display function expects a Person instance: when calling it with an Employee instance, we do not make any mistake as the Employee class inherits from the Person class.
void display(Person *p) { cout << "name : " << p->getName() << endl; cout << "age : " << p->getAge() << endl; if (p->asEmployee()) cout << "salary : " << p->asEmployee()->getSalary() << endl;Note that the call to this down casting method cost nearly nothing. Without the help of the down casting method, the previous code becomes:
void display(Person *p) { cout << "name : " << p->getName() << endl; cout << "age : " << p->getAge() << endl; if (!strcmp(p->getClass()->getName(), "Employee")) cout << "salary : " << ((Employee *)p)->getSalary() << endl;which is rather less efficient and less elegant.
eyedb::OQL q(&db, "select Person.age < %d", given_age); eyedb::ObjectArray obj_arr(eyedb::True); q.execute(obj_arr); for (int i = 0; i < obj_arr.getCount(); i++) { Person *p = (Person *)obj_arr[i]; cout << "name: " << p->getName() << endl; }The cast:
Person *p = (Person *)obj_arr[i];is legal according to the context but is not safe because neither static (i.e. compiler level) check nor runtime check is performed.
inline Person *Person_c(eyedb::Object *o) { Root *x = personDatabase::asRoot(o); if (!x) return (Person *)0; return x->asPerson(); }This function allows you to perform compiler and runtime check as follows:
for (int i = 0; i < obj_arr.getCount(); i++) { Person *p = Person_c(obj_arr[i]); if (p) cout << "name: " << p->getName() << endl; }in the case of the loaded object is not a real Person instance, the Person_c function returns a null pointer.
attribute Address addr;can be described as {primitive type = Address, property = literal, array = nil}
1. literal basic or user enum type : int32 age, CivilState cstate.All those type families support in an orthogonal way an multi-dimenstion array modifier.
2. literal string : string<32> town, string name,string country.
3. literal user type : Address addr
4. object basic, user or system type : Person *spouse
5. object collection type : array<Person *> children, set<Car *» cars.
<attribute primitive type> get<attribute name>(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) constfor instance for the age attribute:
eyedb::_int32 getAge(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const;Every selector method has the two following optional arguments:
const char *get<attribute name>(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const char get<attribute name>(unsigned int a0, eyedb::Bool *isnull = 0, eyedb::Status *status = 0) constfor instance for the name attribute:
const char *getName(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; char getName(unsigned int a0, eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const;The first selector method is to get the full string value of the attribute while the second one is to get a specific character within this string value. The argument a0 is the number of the character.
<attribute primitive type>* get<attribute name>(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const <attribute primitive type>* get<attribute name>(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) constfor instance for the addr attribute:
Address *getAddr(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) ; const Address *getAddr(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const;Note than the returned value cannot be a null pointer as this is literal attribute fully included in the instance.
<attribute primitive type>* get<attribute name>(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const <attribute primitive type>* get<attribute name>(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) constfor instance for the spouse attribute:
Person *getSpouse(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) ; const Person *getSpouse(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; eyedb::Oid getSpouseOid(eyedb::Status *status = 0);Note that:
<collection type>* get<attribute name>Coll(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) ; unsigned int get<attribute name>Count(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; const <collection type>* get<attribute name>Coll(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; eyedb::Oid get<attribute name>Oid(eyedb::Status *status = 0); const <collection object type>* get<attribute name>At(unsigned int ind, eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; <collection object type>* get<attribute name>At(unsigned int ind, eyedb::Bool *isnull = 0, eyedb::Status *status = 0); eyedb::Oid get<attribute name>OidAt(unsigned int ind, eyedb::Status *status = 0) const;where <collection type> can be:
eyedb::Oid get<attribute name>Oid(eyedb::Status *status = 0);For the cars attribute the following code is generated:
eyedb::CollSet *getCarsColl(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) ; unsigned int getCarsCount(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; const eyedb::CollSet *getCarsColl(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; const Car *getCarsAt(unsigned int ind, eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; Car *getCarsAt(unsigned int ind, eyedb::Bool *isnull = 0, eyedb::Status *status = 0); eyedb::Oid getCarsOidAt(unsigned int ind, eyedb::Status *status = 0) const;Let have a look to each method:
eyedb::CollSet *getCarsColl(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) ; const eyedb::CollSet *getCarsColl(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const;returns the collection object (const and not const methods).
unsigned int getCarsCount(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const;returns the collection item count.
const Car *getCarsAt(unsigned int ind, eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; Car *getCarsAt(unsigned int ind, eyedb::Bool *isnull = 0, eyedb::Status *status = 0);returns the #ind element in the collection. As the collection is not ordered, the index of the element to get depends on the load ordering and is not specified. These array-oriented methods are generated for user convenience because it is somewhat easier to scan an array that to scan an unordered set.
eyedb::Oid getCarsOidAt(unsigned int ind, eyedb::Status *status = 0) const;returns the #ind oid in the collection. The remark about the index of the element is the same as above.
<collection type>* get<attribute name>Coll(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) ; unsigned int get<attribute name>Count(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; const <collection type>* get<attribute name>Coll(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; eyedb::Oid get<attribute name>Oid(eyedb::Status *status = 0); const <collection object type>* retrieve<attribute name>At(unsigned int ind, eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; <collection object type>* retrieve<attribute name>At(unsigned int ind, eyedb::Bool *isnull = 0, eyedb::Status *status = 0); eyedb::Oid retrieve<attribute name>OidAt(unsigned int ind, eyedb::Status *status = 0) const;where <collection type> can be:
eyedb::Oid get<attribute name>Oid(eyedb::Status *status = 0);For the children attribute the following code is generated:
eyedb::CollArray *getChildrenColl(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) ; unsigned int getChildrenCount(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; const eyedb::CollArray *getChildrenColl(eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; const Person *retrieveChildrenAt(unsigned int ind, eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; Person *retrieveChildrenAt(unsigned int ind, eyedb::Bool *isnull = 0, eyedb::Status *status = 0); eyedb::Oid retrievedChildrenOidAt(unsigned int ind, eyedb::Status *status = 0) const;Only the last three method templates differ from the corresponding Car method templates:
const Person *retrievedChildrenAt(unsigned int ind, eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const; Person *retrievedChildrenAt(unsigned int ind, eyedb::Bool *isnull = 0, eyedb::Status *status = 0);returns the #ind element in the collection. As this collection is ordered, the index of the element to get is fully pertinent.
eyedb::Oid retrievedChildrenOidAt(unsigned int ind, eyedb::Status *status = 0) const;returns the #ind oid in the collection. As this collection is ordered, the index of the element to get is fully pertinent.
eyedb::_int32 getX(unsigned int a0, unsigned int a1, eyedb::Bool *isnull = 0, eyedb::Status *status = 0) const;A call to getX(1, 3) returns the attribute value x[1][3].
unsigned int getXCount(eyedb::Status * = 0) const;For instance, for the other_addrs literal user type attribute, the following code is generated:
Address *getOtherAddrs(unsigned int a0, eyedb::Bool *isnull = 0, eyedb::Status * = 0) ; const Address *getOtherAddrs(unsigned int a0, eyedb::Bool *isnull = 0, eyedb::Status * = 0) const; unsigned int getOtherAddrsCount(eyedb::Status * = 0) const;
eyedb::Status set<attribute name>(<attribute primitive type>);for instance for the age attribute:
eyedb::Status setAge(eyedb::_int32);
eyedb::Status set<attribute name>(const char *); eyedb::Status set<attribute name>(unsigned int a0, char);for instance for the name attribute:
eyedb::Status setName(const char *); eyedb::Status setName(unsigned int a0, char);
eyedb::Status set<attribute name>(<attribute primitive type>*);for instance for the addr attribute:
eyedb::Status setAddr(Address*);
eyedb::Status set<attribute name>(<attribute primitive type>*); eyedb::Status set<attribute name>Oid(const eyedb::Oid &);for instance for the spouse attribute:
eyedb::Status setSpouse(Person*); eyedb::Status setSpouseOid(const eyedb::Oid &);
eyedb::Status set<attribute name>Coll(<collection type>*); eyedb::Status set<attribute name>Oid(const eyedb::Oid &); eyedb::Status addTo<attribute name>Coll(<collection object type>*, unsigned int magorder = 0); eyedb::Status rmvFrom<attribute name>Coll(<collection object type>*); eyedb::Status addTo<attribute name>Coll(const eyedb::Oid &, unsigned int magorder = 0); eyedb::Status rmvFrom<attribute name>Coll(const eyedb::Oid &);where <collection type> can be:
eyedb::Status set<attribute name>Oid(const eyedb::Oid &);For the cars attribute, the following code is generated:
eyedb::Status setCarsColl(eyedb::CollSet*); eyedb::Status addToCarsColl(Car*, unsigned int magorder = 0); eyedb::Status addToCarsColl(const eyedb::Oid &, unsigned int magorder = 0); eyedb::Status rmvFromCarsColl(Car*); eyedb::Status rmvFromCarsColl(const eyedb::Oid &);Let have a look to each method:
eyedb::Status setCarsColl(eyedb::CollSet *coll);sets the cars attribute collection to the input argument coll.
eyedb::Status addToCarsColl(Car *car, unsigned int magorder = 0);adds the car instance to the collection attribute cars. If the collection is not yet created, this method call will create one using the magorder argument for its magnitude order value.
eyedb::Status addToCarsColl(const eyedb::Oid &car_oid, unsigned int magorder = 0);adds the instance of Car whose oid is car_oid to the collection attribute cars. If the collection is not yet created, this method call will create one using the magorder argument for its magnitude order value.
eyedb::Status rmvFromCarsColl(Car *car);removes the car instance from the collection attribute cars. If the instance is not found, an error is raised.
eyedb::Status rmvFromCarsColl(const eyedb::Oid &car_oid);removes the instance of Car whose oid is car_oid from the collection attribute cars. If the instance is not found, an error is raised.
eyedb::Status set<attribute name>Coll(<collection type>*); eyedb::Status set<attribute name>Oid(const eyedb::Oid &); eyedb::Status setIn<attribute name>CollAt(int where, <collection object type>*, unsigned int magorder = 0); eyedb::Status setIn<attribute name>CollAt(int where, const eyedb::Oid &, unsigned int magorder = 0); eyedb::Status unsetIn<attribute name>CollAt(int where);where <collection type> can be:
eyedb::Status set<attribute name>Oid(const eyedb::Oid &);For the children attribute, the following code is generated:
eyedb::Status setChildrenColl(eyedb::CollArray*); eyedb::Status setChildrenOid(const eyedb::Oid &); eyedb::Status setInChildrenCollAt(int where, Person*, unsigned int magorder = 0); eyedb::Status unsetInChildrenCollAt(int where); eyedb::Status setInChildrenCollAt(int where, const eyedb::Oid &, unsigned int magorder = 0);Let have a look to each method:
eyedb::Status setChildrenColl(eyedb::CollSet *coll);sets the children attribute collection to the input argument coll.
eyedb::Status setInChildrenCollAt(int where, Person *person, unsigned int magorder = 0);adds the person instance to the collection attribute children at position where. If the collection is not yet created, this method call will create one using the magorder argument for its magnitude order value.
eyedb::Status setInChildrenCollAt(int where, const eyedb::Oid &person_oid, unsigned int magorder = 0);adds the instance of Person whose oid is person_oid to the collection attribute children at position where.. If the collection is not yet created, this method call will create one using the magorder argument for its magnitude order value.
eyedb::Status unsetInChildrenCollAt(int where);removes the instance found at position where from the collection attribute children.
eyedb::Status setX(unsigned int a0, unsigned int a1, eyedb::_int32);A call to setX(2, 24) sets the attribute value x[2][24].
eyedb::Status setOtherAddrs(unsigned int a0, Address *); eyedb::Status setOtherAddrsCount(unsigned int count);
virtual eyedb::Status change_address(const char * street, const char * town, char * &oldstreet, char * &oldtown, eyedb::_int32 &retarg); static eyedb::Status getPersonCount(eyedb::Database *db, eyedb::_int32 &retarg);
#include "person.h" int main(int argc, char *argv[]) { eyedb::init(argc, argv); person::init(); // ... person::release(); eyedb::release(); return 0; }A few remarks about this code:
eyedb::Connection conn; conn.open(); const char *dbname = argv[1]; person::Database db(dbname); db.open(&conn, eyedb::Database::DBRW);
EyeDB manual