⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fastdb.htm

📁 俄罗斯牛人KK的作品,著名的ORDBMS,这里上传最新的3.39版本源代码.希望了解对象关系数据库的同好,请不要错过.
💻 HTM
📖 第 1 页 / 共 5 页
字号:
The method should be a parameterless instance member function
returning a
boolean, 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 structure
only 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)-&gt;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&lt; dbReference&lt;Contract&gt; &gt; 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&lt;Detail&gt;   detail;
    dbReference&lt;Supplier&gt; 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 establish
a 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 should
be used in the implementation file and not in the header file. It constructs
a descriptor of the table associated with the class. If you are going to work
with multiple databases from one application, it is possible to register
a 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 tables
in 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 into
the 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 the
descriptor of this class in the application. If the class definitions
differ, FastDB tries to convert records from the table to the new 
format. Any kind of conversion between numeric types (integer to
real, real to integer, with extension or truncation) is allowed. Also,
addition of new fields can be easily handled. But removal of fields
is 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 and
removes indices, which are no more used. Reformatting the table and 
adding/removing indices is only possible when no more than one
application accesses the database. So when the first application is attached
to the database, it can perform table conversion. All other applications
can only add new classes to the database.<P>

There is one special internal database  <code>Metatable</code>, which
contains information about other tables in the database. C++ programmers
need not access this table, because the format of database tables is specified
by C++ classes. But in an interactive SQL program, it may be necessary to
examine 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 should
asssign 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 declared
with <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 database
there is no need to specify value of autoincremented field (it will be
ignored). After successful insertion of record this field will be
assigned unique value (which is guaranteed to be not used before this
table):

<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++ operators
to construct query statements with parameters. Parameters can be specified  
directly in places where they are used, eliminating any mapping between
parameter 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 times
with different parameter values. C++ overloaded functions make it possible
to automatically determine the type of the parameter, 
requiring no extra information
to 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 fraction
of 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 the
assumption that there is no reason for splitting a query text into two strings
like ("price ",">=") or specifying more than one parameter sequentially
("color=",color,color). So FastDB assumes the first string to be a fraction
of the query text and switches to <I>operand mode</I>
after it. In <I>operand mode</I>, FastDB treats the <code>char*</code> argument
as 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 construct
query 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, because
parameters are accessed by reference. But it is possible to use string
constants, because strings are passed by value. There two possible ways of 
specifying string parameters in a query: using a string buffer or a
pointer 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 parameter
nor 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 compiled
tree 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 should
define methods, which will not do actual calculations, but instead
return an expression (in terms of predefined database types), which
performs 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 defines
methods allowing to specify datetime fields in ordered lists and
to 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 &lt; (char const* field) { 
	dbQueryExpression expr;
	expr = dbComponent(field,"stamp"),">",stamp;
	return expr;
    }
    dbQueryExpression operator &lt;= (char const* field) { 
	dbQueryExpression expr;
	expr = dbComponent(field,"stamp"),">=",stamp;
	return expr;
    }
    dbQueryExpression operator &gt; (char const* field) { 
	dbQueryExpression expr;
	expr = dbComponent(field,"stamp"),"<",stamp;
	return expr;
    }
    dbQueryExpression operator &gt;= (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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -