To use this client, you must first compile it: eyedbodl has generated a makefile called Makefile.<<package>>
which can be used as is or can help you to design your own makefile.
A template C++ file (template_<<package>>.cc
) has also been generated, closed to the previous minimal client program, which can be compiled with the generated makefile.
Example 4.2, “The Makefile generated by eyedbodl” shows the generated Makefile.person
(<<datadir>>
is the data directory, usually /usr/share
):
Example 4.2. The Makefile generated by eyedbodl
# # Makefile.person # # person package # # Example of template Makefile that can help you to compile # the generated C++ file and the template program # Generated by eyedbodl at Sat Jan 28 17:53:48 2006 # include <<datadir>>/eyedb/Makefile.eyedb CXXFLAGS += $(EYEDB_CXXFLAGS) $(EYEDB_CPPFLAGS) LDFLAGS += ${EYEDB_LDFLAGS} LDLIBS += ${EYEDB_LDLIBS} # if you use gcc GCC_FLAGS = -Wl,-R$(EYEDB_LIBDIR) # Example for compiling a client program: client_program = template_person $(client_program): person.o $(client_program).o $(CXX) $(LDFLAGS) $(GCC_FLAGS) -o $@ $^ $(LDLIBS)
Important note: you need a recent version of GNU make to use this makefile. This makefile does not work with the standard SUN make.
Once compiled, you can execute the program as follows:
% ./persontest foo
We are going now to add a function to manipulate Person
instances:
create a person named "john wayne"
create a person named "mary poppins"
mary them
create 3 "john wayne" children named "baby1", "baby2" and "baby3"
These operations are performed in the function create
, listed in Example 4.3, “A C++ function to create objects”
Example 4.3. A C++ function to create objects
static void create(eyedb::Database *db) { db->transactionBegin(); // starts a new transaction Person *john = new Person(db); john->setFirstname("john"); john->setLastname("wayne"); john->setAge(32); john->getAddr()->setStreet("courcelles"); john->getAddr()->setTown("Paris"); Person *mary = new Person(db); mary->setFirstname("mary"); mary->setLastname("poppins"); mary->setAge(30); mary->getAddr()->setStreet("courcelles"); mary->getAddr()->setTown("Paris"); // mary them john->setSpouse(mary); // creates children for (int i = 0; i < 5; i++) { std::string name = std::string("baby") + str_convert(i+1); Person *child = new Person(db); child->setFirstname(name.c_str()); child->setLastname(name.c_str()); child->setAge(1+i); john->addToChildrenColl(child); child->release(); // release the allocated pointer } // store john and all its related instances within the database john->store(eyedb::FullRecurs); // release the allocated pointers mary->release(); john->release(); db->transactionCommit(); // commits the current transaction }
A few remarks about this code:
all operations - setting, getting attributes, storing, querying instances in a database - must be performed within a transaction. A transaction is initiated using the Database::transactionBegin
method and is committed (resp. aborted) using the Database::transactionCommit
(resp. Database::transactionAbort
) method.
to store any instance in the database, you need to call the store
(or realize
) method on this instance. In our case, we use the argument FullRecurs
indicating that we want all related instances (through relationship or indirect attribute) to be stored in the database.
all runtime pointers allocated with the new
operator must be deleted using the release
method. The delete
operator is forbidden: if you try to use it, an exception will be thrown at runtime.
We are now going to query and display all the person instances. The corresponding code is given in Example 4.4, “A C++ function to query objects”.
Example 4.4. A C++ function to query objects
static void read(eyedb::Database *db, const char *s) { db->transactionBegin(); eyedb::OQL q(db, "select Person.lastname ~ \"%s\"", s); eyedb::ObjectArray obj_arr; q.execute(obj_arr); for (int i = 0; i < obj_arr.getCount(); i++) { Person *p = Person_c(obj_arr[i]); if (p) printf("person = %s %s, age = %d\n", p->getFirstname(), p->getLastname(), p->getAge()); } db->transactionCommit(); }
An OQL construct can be used within the C++ code using the OQL(Database *, const char *fmt, ...) constructor. For instance, in the above example, assuming s
is equal to baby
, the following code will send the query select Person.lastname ~ "baby" to the OQL interpreter:
eyedb::OQL q(db, "select Person.lastname ~ \"%s\"", s);
This interpreter will perform the query and returned all the found objects. The returned objects can be found using the OQL::execute
method as follows:
eyedb::ObjectArray obj_arr; q.execute(obj_arr);
The returned objects are of type eyedb::Object
, so you cannot use the Person
methods such as getFirstname()
, getAge()
\ldots To use them, you need to perform a down-cast using the Person\_c
static function as follows:
for (int i = 0; i < obj_arr.getCount(); i++) { Person *p = Person_c(obj_arr[i]); if (p) ...
If the object obj_arr[i]
is not of type Person
, the returned pointer will be null. It is why we make a test on the value of p
. If p
is not null, we can use all the Person
methods as follows:
printf("person = %s %s, age = %d\n", p->getFirstname(), p->getLastname(), p->getAge());
To have more information about the C++ binding, please refer to the EyeDB C++ binding manual.