?? fastdb.htm
字號:
<TR><TD>lower</TD><TD>string</TD><TD>string</TD><TD>lowercase string</TD</TR><TR><TD>real</TD><TD>integer</TD><TD>real</TD><TD>conversion of integer to real</TD</TR><TR><TD>string</TD><TD>integer</TD><TD>string</TD><TD>conversion of integer to string</TD</TR><TR><TD>string</TD><TD>real</TD><TD>string</TD><TD>conversion of real to string</TD</TR><TR><TD>upper</TD><TD>string</TD><TD>string</TD><TD>uppercase string</TD</TR></TABLE><P>FastDB allows user to define its own functions and operators.Function should have at least one but no more than 3 parameters of string, integer, boolean, reference or user defined (raw binary) type. It should return value of integer, real, string orboolean type.<P>User functions should be registered by the <code>USER_FUNC(f)</code> macro, which creates a static object of the <code>dbUserFunction</code> class, binding the function pointer and the function name.<P>There are two ways of implementing these functions in application.First can be used only for functions with one argument. This argument should be of <code>int8, real8,char*</code> types. And the function return type should be <code>int8, real8, char*</code> or <code>bool</code>.If function has more than one parameters or it can accept parameters of different types (polymorphism)then parameters should be passed as reference to <code>dbUserFunctionArgument</code> structure.This structure contains <code>type</code> field, which value can be used in function implementation todetect type of passed argument and union with argument value.The following table contains mapping between argument types and where the value should be taken from:<P><TABLE BORDER ALIGN=CENTER><TR><TH>Argument type</TH><TH>Argument value</TH><TH>Argument value type</TH></TR><TR><TD><code>dbUserFunctionArgument::atInteger</code></TD><TD><code>u.intValue</code></TD><TD><code>int8</code></TD></TR><TR><TD><code>dbUserFunctionArgument::atBoolean</code></TD><TD><code>u.boolValue</code></TD><TD><code>bool</code></TD></TR><TR><TD><code>dbUserFunctionArgument::atString</code></TD><TD><code>u.strValue</code></TD><TD><code>char const*</code></TD></TR><TR><TD><code>dbUserFunctionArgument::atReal</code></TD><TD><code>u.realValue</code></TD><TD><code>real8</code></TD></TR><TR><TD><code>dbUserFunctionArgument::atReference</code></TD><TD><code>u.oidValue</code></TD><TD><code>oid_t</code></TD></TR><TR><TD><code>dbUserFunctionArgument::atRawBinary</code></TD><TD><code>u.rawValue</code></TD><TD><code>void*</code></TD></TR></TABLE><P>For example the followingstatements make it possible to use the <code>sin</code> function in SQLstatements:<PRE> #include <math.h> ... USER_FUNC(sin);</PRE>Functions can be used onlywithin the application, where they are defined. Functions are not accessiblefrom other applications and interactive SQL. If a function returns a stringtype , the returned string should be copied by means of the operator<code>new</code>, becauseFastDB will call the destructor after copying the returned value.<P>In FastDB, the function argument can (but not necessarily must) be enclosed in parentheses. So both of the following expressions are valid:<PRE> '$' + string(abs(x)) length string y</PRE><P>Functions with two argument can be also used as operators. Consider the following example, in which function <code>contains</code> which performs case insensitive search for substring is defined:<PRE> bool contains(dbUserFunctionArgument& arg1, dbUserFunctionArgument& arg2) { assert(arg1.type == dbUserFunctionArgument::atString && arg2.type == dbUserFunctionArgument::atString); return stristr(arg1.u.strValue, arg2.u.strValue) != NULL; } USER_FUNC(contains); dbQuery q1, q2; q1 = "select * from TestTable where name contains 'xyz'"; q2 = "select * from TestTable where contains(name, 'xyz')";</PRE>In this example, queries <code>q1</code> and <code>q2</code> are equivalent.<P><H2><A NAME = "cpp">C++ interface</A></H2>One of the primary goals of FastDB is to provide a flexible and convenientapplication language interface. Anyone who has to use ODBC or similar SQL interfaces will understand what I am speaking about.In FastDB, a query can be written in C++ in the following way:<P><PRE> dbQuery q; dbCursor<Contract> contracts; dbCursor<Supplier> suppliers; int price, quantity; q = "(price >=",price,"or quantity >=",quantity, ") and delivery.year=1999"; // input price and quantity values if (contracts.select(q) != 0) { do { printf("%s\n", suppliers.at(contracts->supplier)->company); } while (contracts.next()); } </PRE><H3><A NAME = "table">Table</A></H3>Data in FastDB is stored in tables which correspond to C++ classeswhereas the table records correspond to class instances. The following C++ types are accepted as atomic components ofFastDB records:<P><TABLE BORDER ALIGN="center"><TR><TH>Type</TH><TH>Description</TH></TR><TR><TD>bool</TD><TD>boolean type (<code>true,false</code>)</TD></TR><TR><TD>int1</TD><TD>one byte signed integer (-128..127)</TD></TR><TR><TD>int2</TD><TD>two bytes signed integer (-32768..32767)</TD></TR><TR><TD>int4</TD><TD>four bytes signed integer (-2147483648..2147483647)</TD></TR><TR><TD>int8</TD><TD>eight bytes signed integer (-2**63..2**63-1)</TD></TR><TR><TD>real4</TD><TD>four bytes ANSI floating point type</TD></TR><TR><TD>real8</TD><TD>eight bytes ANSI double precision floating point type</TD></TR><TR><TD>char const*</TD><TD>zero terminated string</TD></TR><TR><TD>dbReference<T></TD><TD>reference to class T</TD></TR><TR><TD>dbArray<T></TD><TD>dynamic array of elements of type T</TD></TR></TABLE><P>In addition to types specified in the table above, FastDB records canalso contain nested structures of these components. FastDB doesn't support unsigned types to simplify the query language,to eliminate bugs caused by signed/unsigned comparisonand to reduce the size of the database engine.<P>Unfortunately C++ provides no wayto get metainformation about a class at runtime (RTTI is not supported by all compilers and also doesn't provide enough information).Therefore the programmer has to explicitly enumerate class fields to be included in the database table (it also makes mapping between classes and tables more flexible). FastDB provides a set of macros and classes to make such mapping as simple as possible.<P>Each C++ class or structure, which will be used in the database, should contain a special method describing its fields. The macro <code>TYPE_DESCRIPTOR(</code><I>field_list</I><code>)</code> will construct this method. The single argument of this macro is - enclosed in parentheses -a list of class field descriptors.If you want to define some methods for the classand make them available for the database, then the macro <code>CLASS_DESCRIPTOR(</code><I>name, field_list</I><code>)</code>should be used instead of <code>TYPE_DESCRIPTOR</code>. The class name isneeded to get references to member functions.<P>The following macros can be used for the construction of fielddescriptors:<DL><DT><B>FIELD(</B>name<B>)</B><DD>Non-indexed field with specified name.<DT><B>KEY(</B>name, index_type<B>)</B><DD>Indexed field. <I>index_type</I> should be a combination of <code>HASHED</code> and <code>INDEXED</code> flags.When the <code>HASHED</code> flag is specified, FastDB will create a hash tablefor the table using this field as a key. When the <code>INDEXED</code> flag is specified, FastDB will create a (special kind of index) T-tree for the table using this field as a key. <DT><B>UDT(</B>name, index_type, comparator<B>)</B><DD>User defined raw binary type. Database deals with this type just as with sequence of bytes of specified size.This field can be used in query (compared with query parameter of the same type), may be indexed and used in <code>order by</code> clause. Comparison is performed by means of<code>comparator</code> function provided by programmer. Comparator functions receives threearguments: two pointers to the compared raw binary objects and size of binary object.The semantic of <I>index_type</I> is the same as of <code>KEY</code> macro.<DT><B>RAWKEY(</B>name, index<B>)</B><DD>Raw binary type with predefined comparator.This macro is just specialized version of <code>UDT</code> macro with <code>memcmp</code>used as comparator.<DT><B>RAWFIELD(</B>name<B>)</B><DD>One more specialization of <code>UDT</code> macrofor raw binary fields with predefined comparator <code>memcmp</code> and without indices.<DT><B>SUPERCLASS(</B>name<B>)</B><DD>Specifies information about the base class(parent) of the current class.<DT><B>RELATION(</B>reference, inverse_reference<B>)</B><DD>Specifies <I>one-to-one, one-to-many</I> or <I>many-to-many</I>relationships between classes (tables). Both <I>reference</I>and <I>inverse_reference</I>fields should be of reference or of array of reference type.<code>inverse_reference</code> is a field of the referenced tablecontaining the inverse reference(s) to the current table. Inverse referencesare automatically updated by FastDB and are used for query optimization(see <A HREF="#inverse">Inverse references</A>).<DT><B>OWNER(</B>reference, inverse_reference<B>)</B><DD>Specifies <I>one-to-many</I> or <I>many-to-many</I>relationship between classes (tables) of owner-member type. When owner record is removed all referenced member records are also removed(cascade delete). If member record has reference to owner class, it should be declared with RELATION macro.<DT><B>METHOD(</B>name<B>)</B><DD>Specifies a method of the class.The method should be a parameterless instance member functionreturning aboolean, numeric, reference or string type. Methods should be specified after all other attributes of the class. </DL><P>Although only atomic fields can be indexed, an index type can be specified for structures. The index will be created for components of the structureonly if such type of index is specified in the index type mask of the structure. This allows the programmers to enable or disable indices for structure fields depending on the role of the structure in the record.<P>The following example illustrates the creation of a type descriptor in the header file:<P><PRE>class dbDateTime { int4 stamp; 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>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -