?? fastdb.htm
字號:
public: int year() { return localtime((time_t*)&stamp)->tm_year + 1900; } ... CLASS_DESCRIPTOR(dbDateTime, (KEY(stamp,INDEXED|HASHED), METHOD(year), METHOD(month), METHOD(day), METHOD(dayOfYear), METHOD(dayOfWeek), METHOD(hour), METHOD(minute), METHOD(second)));}; class Detail { public: char const* name; char const* material; char const* color; real4 weight; dbArray< dbReference<Contract> > contracts; TYPE_DESCRIPTOR((KEY(name, INDEXED|HASHED), KEY(material, HASHED), KEY(color, HASHED), KEY(weight, INDEXED), RELATION(contracts, detail)));};class Contract { public: dbDateTime delivery; int4 quantity; int8 price; dbReference<Detail> detail; dbReference<Supplier> supplier; TYPE_DESCRIPTOR((KEY(delivery, HASHED|INDEXED), KEY(quantity, INDEXED), KEY(price, INDEXED), RELATION(detail, contracts), RELATION(supplier, contracts)));};</PRE>Type descriptors should be defined for all classes used in the database.In addition to defining type descriptors, it is necessary to establisha mapping between C++ classes and database tables. The macro <code>REGISTER(</code>name<code>)</code> will do it. Unlike the<code>TYPE_DESCRIPTOR</code> macro, the <code>REGISTER</code> macro shouldbe used in the implementation file and not in the header file. It constructsa descriptor of the table associated with the class. If you are going to workwith multiple databases from one application, it is possible to registera table in a concrete database by means of the<code>REGISTER_IN(</code>name,database</code<code>)</code> macro. The parameter <code>database</code> of this macro should be a pointer to the<code>dbDatabase</code> object. You can register tablesin the database as follows:<P><PRE>REGISTER(Detail);REGISTER(Supplier);REGISTER(Contract);</PRE>The table (and correspondent class) can be used only with one database at each moment of time. When you open a database, FastDB imports intothe database all classes defined in the application.If a class with the same name already exists in the database, its descriptor stored in the database is compared with thedescriptor of this class in the application. If the class definitionsdiffer, FastDB tries to convert records from the table to the new format. Any kind of conversion between numeric types (integer toreal, real to integer, with extension or truncation) is allowed. Also,addition of new fields can be easily handled. But removal of fieldsis only possible for empty tables (to avoid accidental data destruction).<P>After loading all class descriptors, FastDB checks if all indices specified in the application class descriptor are already present in the database, constructs new indices andremoves indices, which are no more used. Reformatting the table and adding/removing indices is only possible when no more than oneapplication accesses the database. So when the first application is attachedto the database, it can perform table conversion. All other applicationscan only add new classes to the database.<P>There is one special internal database <code>Metatable</code>, whichcontains information about other tables in the database. C++ programmersneed not access this table, because the format of database tables is specifiedby C++ classes. But in an interactive SQL program, it may be necessary toexamine this table to get information about record fields.<P>Starting from version 2.30 FastDB supports autoincrement fields(fields unique value to which are assigned automaticaly by database).To be able to use them you should:<P><OL><LI>Recompile FastDB and your application with <code>-DAUTOINCREMENT_SUPPROT</code> flags (add this flag to <code>DEFS</code> variables in FastDB makefile).<BR><B>Attention</B>: database files created by FastDB compiled without this option will be incompatible with FastDB compiled with <code>DAUTOINCREMENT_SUPPORT</code>.<LI>If you want to use other than 0 initial counter value, you shouldasssign value to <code>dbTableDescriptor::initialAutoincrementCount</code>.It will be shared between all tables, so all table will have the same initial value of autoincrement counter.<LI>Autoincrement fields should be of int4 type and should be declaredwith <code>AUTOINCREMENT</code> flag:<PRE> class Record { int4 rid; char const* name; ... TYPE_DESCRIPTOR((KEY(rid, AUTOINCREMENT|INDEXED), FIELD(name), ...)); }</PRE> <LI>When record with autoincrement field is inserted in the databasethere is no need to specify value of autoincremented field (it will beignored). After successful insertion of record this field will beassigned unique value (which is guaranteed to be not used before thistable):<PRE> Record rec; // no rec.rid should be specified rec.name = "John Smith"; insert(rec); // rec.rid now assigned unique value int newRecordId = rec.rid; // and can be used to reference this record</PRE><LI>When record is removed the value will not be reused.When transaction is aborted, table autoincrement counter is also rolled back.</OL><P><H3><A NAME = "query">Query</A></H3>The class query is used to serve two purposes: <OL><LI>to construct a query and bind query parameters<LI>to cache compiled queries</OL>FastDB provides overloaded '<code>=</code>' and '<code>,</code>' C++ operatorsto construct query statements with parameters. Parameters can be specified directly in places where they are used, eliminating any mapping betweenparameter placeholders and C variables. In the following sample query,pointers to the parameters <code>price</code> and <code>quantity</code> are stored in the query, so that the query can be executed several timeswith different parameter values. C++ overloaded functions make it possibleto automatically determine the type of the parameter, requiring no extra informationto be supplied by the programmer (such reducing the possibility of a bug). <PRE> dbQuery q; int price, quantity; q = "price >=",price,"or quantity >=",quantity;</PRE> Since the <code>char*</code> type can be used both for specifying a fractionof a query (such as "price >=") and for a parameter of string type,FastDB uses a special rule to resolve this ambiguity. This rule is based on theassumption that there is no reason for splitting a query text into two stringslike ("price ",">=") or specifying more than one parameter sequentially("color=",color,color). So FastDB assumes the first string to be a fractionof the query text and switches to <I>operand mode</I>after it. In <I>operand mode</I>, FastDB treats the <code>char*</code> argumentas a query parameter and switches back to query <I>text mode</I>, and so on...It is also possible not to use this "syntax sugar" and constructquery elements explicitly by the <code>dbQuery::append(dbQueryElement::ElementType type, void const* ptr)</code>method. Before appending elements to the query,it is necessary to reset the query by the <code>dbQuery::reset()</code> method('<code>operator=</code>' does it automatically).<P>It is not possible to use C++ numeric constants as query parameters, becauseparameters are accessed by reference. But it is possible to use stringconstants, because strings are passed by value. There two possible ways of specifying string parameters in a query: using a string buffer or apointer to pointer to string:<P><PRE> dbQuery q; char* type; char name[256]; q = "name=",name,"and type=",&type; scanf("%s", name); type = "A"; cursor.select(q); ... scanf("%s", name); type = "B"; cursor.select(q); ...</PRE><P>Query variables can neither be passed to a function as a parameternor be assigned to another variable.When FastDB compiles the query, it saves the compiled tree in this object. The next time the query will be used, no compilation is needed and the already compiledtree can be used. It saves some time needed for query compilation.<P>FastDB provides two approaches to integrate user-defined types in databases.The first - the definition of class methods - was already mentioned. The other approach deals only with query construction. Programmers shoulddefine methods, which will not do actual calculations, but insteadreturn an expression (in terms of predefined database types), whichperforms the necessary calculation. It is better to describe it by example.FastDB has no builtin datetime type. Instead of this, a normal C++class <code>dbDateTime</code> can be used by the programmer. This class definesmethods allowing to specify datetime fields in ordered lists andto compare two dates using normal relational operators:<P><PRE>class dbDateTime { int4 stamp; public: ... dbQueryExpression operator == (char const* field) { dbQueryExpression expr; expr = dbComponent(field,"stamp"),"=",stamp; return expr; } dbQueryExpression operator != (char const* field) { dbQueryExpression expr; expr = dbComponent(field,"stamp"),"<>",stamp; return expr; } dbQueryExpression operator < (char const* field) { dbQueryExpression expr; expr = dbComponent(field,"stamp"),">",stamp; return expr; } dbQueryExpression operator <= (char const* field) { dbQueryExpression expr; expr = dbComponent(field,"stamp"),">=",stamp; return expr; } dbQueryExpression operator > (char const* field) { dbQueryExpression expr; expr = dbComponent(field,"stamp"),"<",stamp; return expr; } dbQueryExpression operator >= (char const* field) { dbQueryExpression expr; expr = dbComponent(field,"stamp"),"<=",stamp; return expr; } friend dbQueryExpression between(char const* field, dbDateTime& from, dbDateTime& till) { dbQueryExpression expr; expr=dbComponent(field,"stamp"),"between",from.stamp,"and",till.stamp; return expr; } friend dbQueryExpression ascent(char const* field) { dbQueryExpression expr; expr=dbComponent(field,"stamp"); return expr; } friend dbQueryExpression descent(char const* field) { dbQueryExpression expr; expr=dbComponent(field,"stamp"),"desc"; return expr; } };</PRE>All these methods receive as their parameter a name of a field in the record.This name is used to contract the full name of the record's component.This can be done by class <code>dbComponent</code>, which constructor takesthe name of the structure field and the name of the component of the structureand returns a compound name separated by a '.' symbol.The class <code>dbQueryExpression</code> is used to collect expression items.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -