dtl
Category: containers | Component type: type |
RandomDBView is a Random Access Container with the property that elements are bound to an underlying database. Rows in the table can be accessed and modified using random access iterators provided by the container. To provide random access to the elements in the table, the container uses an ODBC static cursor to guarantee a particular ordering for the rows. Rows can be inserted or deleted from the table by using the insert() and erase() methods. The specifics of how rows are updated or deleted can be controlled by the user via the SetKey() method which specifies what kind of key to use when updating or deleting rows. Please note that when making changes to the table via insert(), erase() or the non-const iterator, these changes will not be visible until the ReQuery() method is called (see [1] for details).
Defined in the RandomDBView.h header file.
The types defined by Random Access Container .
//Create a quick DBView called db_example.
//Rows in this view will be of type db_example_row.
//See DTL_TABLE for details.
DTL_TABLE3(db_example,
int, int_value,
string, string_value,
double, double_value
);
// Random access container example
void RandomDBViewExample()
{
RandomDBView<db_example_row> view(db_example);
cout << "Objects read from DB:" << endl;
copy(view.begin(), view.end(), ostream_iterator<db_example_row>(cout, "\n"));
cout << "\nElements in reverse order:" << endl;
copy(view.rbegin(), view.rend(), ostream_iterator<db_example_row>(cout, "\n"));
// modify the third row in the table
RandomDBView<db_example_row>::iterator it = view.begin();
db_example_row row(it[2]);
row.int_value++;
*it = row;
// NOTE THAT FOR THE MODIFIED ROW TO SHOW UP WE MUST CALL ReQuery().
// Note that there is no guarantee that the third row will show the updated record,
// since other users may have modified the database or the DB may return records in a different
// order. See the ReQuery() function for details.
cout << "Show updated result row:" << endl;
view.ReQuery();
cout << it[2] << endl;
// show distance functions
cout << "Distance from first to last: " << view.end() - view.begin() << endl;
cout << "Container size: " << view.size() << endl;
// insert and delete rows
db_example_row row_insert(it[2]);
row_insert.int_value = 666;
view.insert(row_insert);
view.erase(it+(ptrdiff_t)2);
cout << "Show result set with inserted/deleted row:" << endl;
view.ReQuery();
copy(view.begin(), view.end(), ostream_iterator<db_example_row>(cout, "\n"));
// show container comparison operators
RandomDBView<db_example_row> view2(view);
cout << boolalpha;
cout << "view == view2 : " << (view == view2) << endl;
cout << "view < view2 : " << (view < view2) << endl;
}
// Random access DBView built from a DynamicDBView
void RandomDynamicDBView()
{
DynamicDBView<> dynamic_view("DB_EXAMPLE", "*");
RandomDBView<variant_row, variant_row> random_view(dynamic_view);
cout << "Items from DB:" << endl;
copy(random_view.begin(), random_view.end(), ostream_iterator<variant_row>(cout, "\n"));
cout << "\n\n";
cout << "Items from DB in reverse order:" << endl;
copy(random_view.rbegin(), random_view.rend(), ostream_iterator<variant_row>(cout, "\n"));
// insert and delete rows
variant_row row_insert(random_view[2]);
row_insert["INT_VALUE"] = 666;
random_view.insert(row_insert);
random_view.erase(random_view.begin()+(ptrdiff_t)2);
cout << "Show result set with inserted/deleted row:" << endl;
random_view.ReQuery();
copy(random_view.begin(), random_view.end(), ostream_iterator<variant_row>(cout, "\n"));
}
RandomDBView
Parameter | Description | Default |
---|---|---|
DataObj | The type of object that will be written to the RandomDBView. This object will be bound through use of the BCA to the appropriate columns in the database. | |
ParamObj | The type of object that will be used to specify the postfix parameters to the RandomDBView. | DefaultParamObj<DataObj> |
As defined in a Random Access Container .
Name | Expression | Precondition | Semantics | Postcondition |
---|---|---|---|---|
Main constructor |
RandomDBView(const DBView<DataObj, ParamObj>) |
Creates a random access container bound to a table as specified using a DBView to control the paramaters. |
Member | Where defined | Description |
---|---|---|
RandomDBView(const DBView<DataObj, ParamObj>) |
RandomDBView | Creates a random access container bound to a table as specified using a DBView to control the paramaters. |
void insert(const DataObj& x) | RandomDBView | Inserts x. The inserted element will not be visible until ReQuery() is called. |
template <class InputIterator> void insert(InputIterator first, InputIterator last) | RandomDBView | Inserts the range [first, last). The inserted elements will not be visible until ReQuery() is called. |
void erase(iterator pos) | RandomDBView | Erases the element at position pos. The erased element will not be removed until ReQuery() is called. |
void erase(iterator first, iterator last) | RandomDBView | Erases the elements in the range [first, last). The erased elements will not be removed until ReQuery() is called. |
void ReQuery() | RandomDBView | Close the static ODBC cursor used by the random access iterators. Force re-query of the database to reflect updated/inserted/deleted records by this and other users. Note that ReQuery() will affect any copies made of the RandomDBView since these copies will point to the same ODBC cursor. After a ReQuery() operation any active iterators against the container will be invalidated in the following sense. Iterators that were created prior to a ReQuery() will continue to point to the same row number in the recordset, but this does not gurantee that they will have the same meaning as before. Why? Because after a ReQuery(), rows may be added/deleted/updated in the result set. Also, after a ReQuery(), there is no guarantee that the database will return records in the same order that it did before (although it most likely will, but if you need to guarantee an order then it would be best to add a unique ORDER BY clause to your query). |
void SetKey(const tstring &KeyFields) | RandomDBView | Set the key fields to use when updating or erasing records from the table. Argument is a comma delimited list of fields "field1, field2, ..., fieldN". Note that this will override the default set of key fields that were specified in the DBView that was used to create the RandomDBView. By default, the container will attempt to automatically determine a unique identifier for rows in the table using the autokeys functionality. See Key Mode for more details. |
Member | Where defined | Description |
---|---|---|
value_type | Container | The type of object, DataObj, stored in the RandomDBView. |
pointer | Container | Pointer to DataObj. |
reference | Container | Reference to DataObj |
const_reference | Container | Const reference to DataObj |
size_type | Container | An unsigned integral type. |
difference_type | Container | A signed integral type. |
iterator | Container | Iterator used to iterate through a RandomDBView. Please note that if changes are made to the table via this iterator, the changes will not be visible until the ReQuery() method is called. This means that algorithms which read back changes they have made to the container will not work with this iterator. See [1] |
const_iterator | Container | Const iterator used to iterate through a RandomDBView. |
reverse_iterator | Reversible Container | Iterator used to iterate backwards through a RandomDBView. Please note that if changes are made to the table via this iterator, the changes will not be visible until the ReQuery() method is called. This means that algorithms which read back changes they have made to the container will not work with this iterator. See [1] |
const_reverse_iterator | Reversible Container | Const iterator used to iterate backwards through a RandomDBView. |
iterator begin() | Container | Returns an iterator pointing to the beginning of the RandomDBView. |
iterator end() | Container | Returns an iterator pointing to the end of the RandomDBView. |
const_iterator begin() const | Container | Returns a const_iterator pointing to the beginning of the RandomDBView. |
const_iterator end() const | Container | Returns a const_iterator pointing to the end of the RandomDBView. |
reverse_iterator rbegin() | Reversible Container | Returns a reverse_iterator pointing to the beginning of the reversed RandomDBView. |
reverse_iterator rend() | Reversible Container | Returns a reverse_iterator pointing to the end of the reversed RandomDBView. |
const_reverse_iterator rbegin() const | Reversible Container | Returns a const_reverse_iterator pointing to the beginning of the reversed RandomDBView. |
const_reverse_iterator rend() const | Reversible Container | Returns a const_reverse_iterator pointing to the end of the reversed RandomDBView. |
size_type size() const | Container | Returns the size of the RandomDBView. |
size_type max_size() const | Container | Same as size(). |
bool empty() const | Container | true if the RandomDBView's size is 0. |
const_reference operator[](size_type n) const | Random Access Container | Returns the n'th element. |
RandomDBView(const DBView & view) | RandomDBView | Creates a RandomDBView using the table and parameters specified by the given DBView. |
RandomDBView(const RandomDBView&) | Container | The copy constructor. |
~RandomDBView() | Container | The destructor. |
RandomDBView& operator=(const RandomDBView&) | Container | The assignment operator |
void swap(RandomDBView&) | Container | Swaps the contents of two RandomDBViews. |
bool operator==(const RandomDBView&, const RandomDBView&) |
Forward Container | Tests two RandomDBViews for equality. |
bool operator<(const RandomDBView&, const RandomDBView&) |
Forward Container | Lexicographical comparison. |
bool operator>(const RandomDBView&, const RandomDBView&) |
Forward Container | Lexicographical comparison. |
bool operator<=(const RandomDBView&, const RandomDBView&) |
Forward Container | Lexicographical comparison. |
bool operator>=(const RandomDBView&, const RandomDBView&) |
Forward Container | Lexicographical comparison. |
void insert(const DataObj& x) | RandomDBView | Inserts x. The inserted element will not be visible until ReQuery() is called. |
template <class InputIterator> void insert(InputIterator first, InputIterator last) | RandomDBView | Inserts the range [first, last). The inserted elements will not be visible until ReQuery() is called. |
void erase(iterator pos) | RandomDBView | Erases the element at position pos. The erased element will not be removed until ReQuery() is called. |
void erase(iterator first, iterator last) | RandomDBView | Erases the elements in the range [first, last). The erased elements will not be removed until ReQuery() is called. |
void ReQuery() | RandomDBView | Close the static ODBC cursor used by the random access iterators. Force re-query of the database to reflect updated/inserted/deleted records by this and other users. Note that ReQuery() will affect any copies made of the RandomDBView since these copies will point to the same ODBC cursor. After a ReQuery() operation any active iterators against the container will be invalidated in the following sense. Iterators that were created prior to a ReQuery() will continue to point to the same row number in the recordset, but this does not gurantee that they will have the same meaning as before. Why? Because after a ReQuery(), rows may be added/deleted/updated in the result set. Also, after a ReQuery(), there is no guarantee that the database will return records in the same order that it did before (although it most likely will, but if you need to guarantee an order then it would be best to add a unique ORDER BY clause to your query). |
void SetKey(const tstring &KeyFields) | RandomDBView | Set the key fields to use when updating or erasing records from the table. Argument is a comma delimited list of fields "field1, field2, ..., fieldN". Note that this will override the default set of key fields that were specified in the DBView that was used to create the RandomDBView. By default, the container will attempt to automatically determine a unique identifier for rows in the table using the autokeys functionality. See Key Mode for more details. |
When we designed RandomDBView we built the container to work against a "static ODBC scrollable cursor" as the underlying cursor for retrieving rows. Using such a cursor gives us a defined and repeatable ordering for the records which was what we needed to obtain random access iterators. Unfortunately, static ODBC cursors have the limitation that if you try to update records directly via the cursor, some ODBC drivers will show the updated records but other drivers will not. To avoid amiguity, we had the container apply updates via an independently executed query so that we could specify how changes would show up rather than having the behavior be ODBC driver dependent. Unfortunately, this means that our non-const random iterators are not quite standard compliant since changes don't show up until a special ReQuery() method is called.
One possible solution to this problem would be to add logging to the container. The idea here would be that when users make a change to a row, we log the updated row. Then, when the iterator goes to retrieve a row via operator * we would simply check whether a more recent version of the row exists in the change log and show it rather than the original. The problems with this approach are twofold:
Random Access Container, DBView
Copyright © 2002, Michael Gradman and Corwin Joy.
Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appears in all copies and that both that copyright notice and this permission notice appear in supporting documentation. Corwin Joy and Michael Gradman make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.