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

📄 fastdb.htm

📁 俄罗斯牛人KK的作品,著名的ORDBMS,这里上传最新的3.39版本源代码.希望了解对象关系数据库的同好,请不要错过.
💻 HTM
📖 第 1 页 / 共 5 页
字号:
	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 takes
the name of the structure field and the name of the component of the structure
and returns a compound name separated by a '.' symbol.
The class <code>dbQueryExpression</code> is used to collect expression items.
The expression is automatically enclosed in parentheses, eliminating conflicts
with operator precedence.<P>

So, assuming a record containing a field <code>delivery</code>
of dbDateTime type, it is possible
to construct queries like these:

<PRE>
        dbDateTime from, till;
        q1 = between("delivery", from, till),"order by",ascent("delivery");
        q2 = till &gt;= "delivery"; 
</PRE>

In addition to these methods, some class specific method can be defined
in such way, for example the method <code>overlaps</code> for a region type.
The benefit of this approach is that a database engine will work
with predefined types and is able to apply indices and other optimizations
to proceed such query. And from the other side, the encapsulation of the class
implementation is preserved, so programmers should not rewrite all queries
when a class representation is changed.<P>

Variables of the following C++ types can be used as query parameters:<P>

<TABLE BORDER ALIGN="center">
<TR><TD WIDTH=50%>int1</TD><TD WIDTH=50%>bool</TD></TR>
<TR><TD>int2</TD><TD>char const*</TD></TR>
<TR><TD>int4</TD><TD>char **</TD></TR>
<TR><TD>int8</TD><TD>char const**</TD></TR>
<TR><TD>real4</TD><TD>dbReference&lt;T&gt;</TD></TR>
<TR><TD>real8</TD><TD>dbArray&lt; dbReference&lt;T&gt; &gt;</TD></TR>
</TABLE><P>



<H3><A NAME = "cursor">Cursor</A></H3>
Cursors are used to access records returned by a select statement. 
FastDB provides typed cursors, i.e. cursors associated with concrete tables.
There are two kinds of cursors in FastDB: readonly cursors and cursors for 
update. Cursors in FastDB are represented by the  C++ template class 
<code>dbCursor&lt;T&gt;</code>, 
where <code>T</code> is the name of a C++ class associated with
the database table. The cursor type should be specified in the constructor
of the cursor. By default, a read-only cursor is created.
To create a cursor for update, you should pass a parameter 
<code>dbCursorForUpdate</code> to the constructor.<P>

A query is executed either by the cursor
<code>select(dbQuery& q)</code> method.
Or by the <code>select()</code> method, 
which can be used to iterate through
all records in the table. Both methods return the number of selected records
and set the current position to the first record (if available).
A cursor can be scrolled in forward or backward direction.
The methods <code>next(), prev(), first(), last()</code> can be used to 
change the current position of the cursor. 
If no operation can be performed as there are no (more) records
available, these methods return <code>NULL</code>
and the cursor position is not changed.<P>

A cursor for class T contains an instance of class T, used for fetching the
current record. That is why table classes should have a default constructor
(constructor without parameters), which has no side effects. 
FastDB optimizes fetching records from the database, copying only data from
fixed parts of the object. String bodies are not copied, instead
of this  the correspondent field points directly into the database. The same is
true for arrays: their components have the same representation in the
database as in the application (arrays of scalar types or arrays of nested 
structures of scalar components).<P>

An application should not change
elements of strings and arrays in a database directly.
When an array method needs to update an array body,
it creates an in-memory copy of the array and updates this 
copy. If the programmer wants to update a string field, she/he should assign
to the pointer a new value, 
but don't change the string directly in the database.
It is recommended to use the <code>char const*</code> type instead of the
<code>char*</code> type for string components, 
to enable the compiler to detect the illegal usage of strings.<P>

The cursor class provides the 
<code>get()</code> method for obtaining a pointer to 
the current record (stored inside the cursor). Also the overloaded 
'<code>operator-&gt;</code>'
can be used to access components of the current record.
If a cursor is opened for update,
the current record can be changed and stored in the database
by the <code>update()</code> method or can be removed.
If the current record is removed, the next record becomes the
current. If there is no next record, then the previous record
(if it exists)  becomes the current. The method <code>removeAll()</code>
removes all records in the table.
Whereas the method <code>removeAllSelected</code> only removes 
all records selected by the cursor.<P>

When records are updated, the size of the database may increase.
Thus an extension of the database section in the virtual memory 
is needed. As a result of such remapping, base addresses of the section can be
changed and all pointers to database fields kept by applications will become 
invalid. FastDB automatically updates current records in all opened 
cursors when a database section is remapped. So, when a database is updated, 
the programmer should access record fields only through the cursor 
<code>-&gt;</code> method. She/he should  not use pointer variables.<P>

Memory used for the current selection can be released by the
<code>reset()</code> method.
This method is automatically called by the <code>select(), 
dbDatabase::commit(), dbDatabase::rollback()</code> methods
and the cursor destructor, so in most cases there is no need to
call the <code>reset()</code> method explicitly.<P>

Cursors can also be used to access records by reference. The method
<code>at(dbReference&lt;T&gt; const& ref)</code> sets the cursor to the record
pointed to by the reference. In this case, the selection consists exactly of
one record and the <code>next(), prev()</code> methods will always return 
<code>NULL</code>. Since cursors and references in FastDB are strictly 
typed, all necessary checking can be done statically by the compiler and 
no dynamic type checking is needed. The only kind of checking,
which is done at runtime, is checking for null references.
The object identifier of the current record in the cursor can be obtained by
the <code>currentId()</code> method.<P> 

It is possible to restrict the number of records returned by a select statement.
The cursor class has the two methods
<code>setSelectionLimit(size_t lim)</code> and
<code>unsetSelectionLimit()</code>,
which can be used to set/unset the limit
of numbers of records returned by the query. In some situations,
a  programmer may want to receive
only one record or only few first records;  so the query execution
time and size of consumed memory can be reduced by limiting the size of 
selection. But if you specify an order for selected records, 
the query with the restriction to 
<I>k</I> records will not return the first <I>k</I> records
with the smallest value of the key. Instead of this, arbitrary <I>k</I>
records will be taken and then sorted.<P>

So all operations with database data can be performed by means of
cursors. The only exception is the insert operation, for which 
FastDB provides an overloaded insert function:

<PRE>
        template&lt;class T&gt;
        dbReference&lt;T&gt; insert(T const& record);
</PRE>

This function will insert a record at the end of the table and return
a reference of the created object.
The order of insertion is strictly specified in FastDB
and applications can use this assumption about the record order in the
table. For applications widely using references for navigation between
objects, it is necessary to have some <I>root</I> object, from which a
traversal by references can be made. A good candidate for such root object
is the first record in the table (it is also the oldest record in the 
table). This record can be accessed by execution of the <code>select()</code>
method without parameter. The current record in the cursor will
be the first record in the table.<P>


The C++ API of FastDB defines a special <code>null</code> variable
of reference type.
It is possible to compare the <code>null</code> variable with references 
or assign it to the reference:<P>

<PRE>
        void update(dbReference&lt;Contract&gt; c) {
            if (c != null) { 
	        dbCursor&lt;Contract&gt; contract(dbCursorForUpdate);
		contract.at(c);
		contract-&gt;supplier = null;
            }
        }
</PRE>

<A NAME="relative-parameter-binding">
Query parameters usually are bound to C++ variables. In most cases in is convenient and 
flexible mechanism. But in multithreaded application, there is no warranty that the same 
query will not be executed at the same moment of time by another thread with different values
of parameters. One solution is to use synchronization primitives (critical sections or mutexes)
to prevent concurrent execution of the query. But this will lead to performance degradation.
FastDB is able to perform read requests in parallel, increasing total system throughput.
The other solution is to use delayed parameter binding. This approach is illustrated by the 
following example:<P>  

<PRE>
dbQuery q;

struct QueryParams { 
    int         salary;
    int         age;
    int         rank;
};

void open()
{
    QueryParams* params = (QueryParams*)NULL;
    q = "salary > ", params->salary, "and age < ", params->age, "and rank =", params->rank;
}

void find(int salary, int age, int rank) 
{ 
    QueryParams params;
    params.salary = salary;
    params.age = age;
    params.rank = rank;
    dbCursor&lt;Person&gt; cusor;
    if (cursor.select(q, &params) &gt; 0) { 
        do { 
	    cout &lt;&lt; cursor->name &lt;&lt; NL;
        } while (cursor.next());
    }
}
</PRE>

So in this example function <code>open</code> binds query parameters just to offsets of 
fields in structure. Later in <code>find</code> functions, actual pointer to the structure
with parameters is passed to the <code>select</code> structure. Function <code>find</code>
can be concurrently executed by several threads and only one compiled version of the query
is used by all these threads. This mechanism is available since version 2.25.<P>
</A>

<H3><A NAME = "database">Database</A></H3>
The class <code>dbDatabase</code> controls the application interactions
with the database. It performs synchronization of concurrent accesses to the
database, transaction management, memory allocation, error handling,...<P>

The constructor of <code>dbDatabase</code> objects allows programmers to specify
some database parameters:

<PRE>
    dbDatabase(dbAccessType type = dbAllAccess,
	       size_t dbInitSize = dbDefaultInitDatabaseSize,
	       size_t dbExtensionQuantum = dbDefaultExtensionQuantum,
	       size_t dbInitIndexSize = dbDefaultInitIndexSize,
	       int nThreads = 1);
</PRE>

The following database access type are supported:<P>

<TABLE BORDER>
<TR><TH>Access type</TH><TH>Description</TH></TR>
<TR><TD><code>dbDatabase::dbReadOnly</code></TD><TD>Read only mode</TD></TR>
<TR><TD><code>dbDatabase::dbAllAccess</code></TD><TD>Normal mode</TD></TR>
<TR><TD><code>dbDatabase::dbConcurrentRead</code></TD><TD>Read only mode in which application can access the database 
concurrently with application updating the same database in <code>dbConcurrentUpdate</code> mode</TD></TR>
<TR><TD><code>dbDatabase::dbConcurrentUpdate</code></TD><TD>Mode to be used in conjunction with
<code>dbConcurrentRead</code> to perform updates in the database without blocking read applications for a long time</TD></TR>
</TABLE><P>

When the database is opened in readonly  mode, no new class definitions can be added to the database and definitions
of existing classes and indices can not be altered.<P>

<code>dbConcurrentUpdate</code> and <code>dbConcurrentRead</code> modes should be used together when 
database is mostly accessed in readonly mode and updates should not block readers for a long time. 
In this mode update of the database can be performed concurrently with read accesses (readers will not see 
changed data until transaction is committed). Only 

⌨️ 快捷键说明

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