|
Oracle9i Lite C and C++ Object Kernel API Reference
Release 5.0.1 Part No. A95263-01 |
|
This document describes the Oracle Lite Stateless Object Database API. Each section of this document presents a different topic. These sections include:
The Stateless Object Database API provides an easy-to-use, error-resistant C++ interface. The following goals were used in its design:
Whenever possible, memory management should be automatic (to avoid memory leaks) and users should be presented with objects rather than raw data (to avoid memory corruption and use of wrong data types). Stateless Object Database API objects use reference counting to free resources when they are no longer in use.
Rather than attempting to expose all the functionality of the underlying database, Stateless Object Database API defines the most commonly used operations and assumes that some specialized tasks will still be done through the native interface.
Operations that can be implemented on top of the Stateless Object Database API without loss of performance and functionality are generally not included into the standard itself. The goal is to define a low-level interface with maximum performance and smallest footprint.
Using the Stateless Object Database API it is possible to perform each operation in a single expression rather than having to define temporary variables. Take for example, the following code to create an object:
DBClass c; DBObject o = cls.create(DBSetList() << "id" << 26000 << "name" << "Jane Doe");
Currently, there are C++ Stateless Object Database API libraries for the Palm OS and Windows 32, a Java library on top of Windows 32 OKAPI and a single-user, pure Java implementation that uses its own database format.
void helloSODA() {
try {
DBSession sess("HelloSODA"); // Connect to the database, creating it if necessary
// Create a new class
DBClass cls = sess.createClass("People", DBAttrList() <<
DBAttr("id", DB_INT) << DBAttr("name", DB_STRING));
// Create several objects. We can use identify columns by name or positions
DBObject o = cls.create(DBSetList() << "id" << 10 << "name" << "Alice");
cls.create(DBSetList() << 0 << 20 << 1 << "Bob");
// Note the automatic type conversion
cls.create(DBSetList() << "id" << "314"<< 1 << 3.14159265358);
// Execute a query (will return two objects)
DBCursor c = cls.createQuery(DBColumn("id") == 10 ||
DBColumn("name") == "Bob").execute();
DBObject ob;
while ((ob = c.next()) != DBNULL) {
DBString s = ob["name"];
FrmCustomAlert(1000, "Query", s, NULL);
}
// Delete an object
o.remove();
// Clean up so that create class is successful next time
sess.rollback();
} catch(DBException e) {
DBString s = e.getMessage();
FrmCustomAlert(1000, ÒErrorÓ, s, NULL);
}
}
The preceding program uses the Stateless Object Database API to retrieve the columns ÒidÓ and ÒnameÓ from an Oracle Lite database residing on the Palm OS.
The following sections provide a brief overview of the Stateless Object Database API classes. It does not describe each supported method. See the soda.h file for a complete interface definition.
This section describes the Stateless Object Database API classes.
This is a wrapper around const char * with automatic memory management. It is used by Stateless Object Database API to return and accept strings. When using this class keep a reference to DBString while using the character data and do explicit conversion to const char * when necessary. Consider this example:
DBException e=...;
printf("%s\n", e.getMessage());
Do this instead:
DBException e=...;
DBString s = e.getMessage();
printf("%s\n", (const char *)s);
This is a wrapper around all datatypes supported by the Stateless Object Database API. Its function is to simplify calling conventions of methods that can accept or return many different types. DBData has constructors that take basic types as arguments and cast operators that convert it back to basic types. Stateless Object Database API programs can often just work with primitive types and allow C++ to perform automatic conversions.
DBData can represent in array. In this case, [] operator can be used to retrieve and set its components. getSize() can be used to get the current array length and setSize() shrinks or expand the array.
When a DBData instance is created, it has 0 length and no particular type. The first set operation initializes the type to that of its operand. From then on, DBData attempts to cast new values to its intrinsic type. DBData(DBType type) constructor can be used to set the type immediately.
DBData can be compared using == or != with DB_NULL constant to check if it has been initialized. This feature is used to test for SQL-style null values.
Here is a small example using DBData:
DBData d; d[0] = "Hello"; d[1] = 5; // Cast to string d[3] = d[2] = d[1]; // d.getLength() == 4
Study the interactions between DBData, DBArrayElement, and DBObjectColumn for some interesting ways to override C++ operators.
Instances of DBObject represent rows in a database table. A DBObject behaves like an array of DBData that can be indexed (and changed) by using obj[ÒColumnNameÓ] or obj[0_based_column_position]. Multiple columns can be modified at once using set() methods that take the same arguments as create() methods in DBClass. An object can be removed from the table using remove() call and new objects come into existance via DBClass.create().
Instances of DBClass represent database tables. Stateless Object Database API programs generally use a DBClass to create new objects in a table. This can be done with one of two create methods. The first one takes separate lists of columns and values:
DBObject obj = cls.create(DBColList() << "c1" << 1, DBDataList() << 10 << "Hello");
In the second form, columns and their corresponding values alternate:
DBObject obj = cls.create(DBSetList() << "c1" << 10 << 1 << "Hello");
A class can be deleted with its remove method.
The Stateless Object Database API supports a 3-stage model for creating queries. First, DBQueryTree is built to describe the query's conditions. This tree can contain some conditions with ÒplaceholderÓ values to be supplied later.
Next, DBClass.createQuery() method is called to create a DBQuery object. This is the stage where search for suitable indexes and similar query optimization is done. Finally, DBQuery.execute is called, optionally with a list of real data to substitute for placeholders. It returns an instance of DBCursor, which provides sequential access to qualifying objects with first, last, prior, and next methods. A returned DBObject can be compared with DB_NULL to see if the end of result list is reached.
Through the use of operator overloading, a query tree is constructed as a regular C++ logical expression. Here is a sample:
DBQueryTree qt = (DBColumn("c1") < 5 || DBColumn(3) == "Hello") && DBColumn("name") == "John";
If placeholders are desired, DBMarker(place#) is substituted for the value. The same placeholder can occur more than once in a tree. For example:
DBQueryTree qt = DBColumn(DBColumn("firstName") == DBMarker(0) ||
DBColumn("lastName") == DBMarker(0) || DBColumn("id") == DBMarker(1) ||
alwaysReturn == true;
To run a query specified by this tree, you can use:
DBQuery q = cls.createQuery(qt); DBCursor c = q.execute(DBDataList() << "Jane" << 1000);
DBSession represents a database connection. Its commit() and rollback() methods perform as expected. The findClass method can be used to lookup an existing class. The createClass creates a new class. Its schema must be specified by a list of DBAttr objects. The constructor for DBAttr is as follows:
DBAttr(const DBString &name, DBType type, int dim=0, int prec=0, int scale=0);
Type can be one of the following values to specify storage type of the object in database:
DB_BYTE, DB_BOOL, DB_SHORT, DB_INT, DB_LONG, DB_FLOAT, DB_DOUBLE, DB_OBJECT, DB_BLOB, DB_STRING, DB_BINARY, DB_NUMBER, DB_DATE
Dim specifies the number of dimensions in the array. 0 means scalar, 1 is one-dimensional array and so on. Note that Palm currently supports only scalar DB_STRING and DB_BINARY and a scalar or 1D array for other types.
Any operation that can not be completed is rolled back and a DBException (reference-counted, not DBException) is thrown. The getErrorCode() method can be used to obtain an (implementation specific) error code and getMessage() returns a readable message. There are two methods to help with these decisions. getType() returns one of the following values:
| Value | Description |
|---|---|
| CONSTRAINT_TYPE | A constraint violation, such as for primary key. |
| SCHEMA_TYPE | The program and the database schema are out of sync with each other (for example, looking for a non-existent column) causes the error. |
| SYSTEM_TYPE | This is a system or Stateless Object Database API error (for example, out of memory) rather than the application. |
| TRANSACTION_TYPE | This error is caused by presence of concurrent transactions (for example, a deadlock). |
| UNKNOWN_TYPE | The error does not fall into any other category. |
| UNSUPPORTED_TYPE | This feature is unsupported by the particular Stateless Object Database API implementation. |
| USAGE_TYPE | The program is using the Stateless Object Database API incorrectly (for example, specifying data values for a query that has no markers). |
getAction() returns a suggested response to an error.
| Action | Description |
|---|---|
| EXIT_ACTION | Exit the program (or at least stop using the Stateless Object Database API) after doing normal cleanup, such as closing connections. USAGE_TYPE and SCHEMA_TYPE errors return this action since the calling program is problematic, or does not match the database. |
| PANIC_ACTION | The error is so severe that cleanup can not be done. An immediate exit, such as abort(), is best. |
| ROLLBACK_ACTION | The transaction that caused this error should be rolled back. |
| UNKNOWN_ACTION | The error has to be handled according to its context. If it is unknown, treat this the same as EXIT_ACTIN. |
| VALUE_ACTION | Retry the failing call with a different data value. |
Typically, a program would be constructed to use type for errors that are expected to occur and action to handle unexpected errors.
|
![]() Copyright © 2002 Oracle Corporation All rights reserved |
|