dtl
![]() |
![]() |
Category: containers | Component type: type |
The DBView Container is a semi-Container with the property that elements are bound to an underlying database. We say that DBView is a semi-Container because it implements all properties and methods of an STL container except for the empty(), size() and max_size() methods. We do not implement empty(), size() or max_size() for this container because we cannot guarantee invariance for these functions; e.g. after a programmer calls the size() function a second user may insert more records into the database on the back-end, therby invalidating the fixed count the programmer might expect.
Defined in the DBView.h header file.
semi-Container
The types defined by Container and the additional iterator types listed below.
1. Define an object to hold the rows from your query.
2. Define an association between fields in your query and fields in your object. This is what we call a 'BCA', which is short for Bind Column Addresses. In the example below, this is done via the functor "BCAExample". The job of the BCA is to equate SQL fields with object fields via the '==' operator which will then establish ODBC bindings to move data to or from a user query.
3. Create a view to select records from. This view is built from the template DBView and establishes which table(s) you want to access, what fields you want to look at (via the BCA), and an optional where clause to further limit the set of records that you are working with. The DBView template forms a semi-Container in the STL sense.1.
4. Use the DBView container
to obtain an iterator to SELECT, INSERT, UPDATE or DELETE records
from your view. These iterators may be used to either populate
STL containers or apply algorithms from the Standard Template
library.
In all the examples that follow we will assume that our database contains a table called DB_EXAMPLE of the form
SQL> desc db_example;
Name Type
------------------------------- --------
INT_VALUE INTEGER
STRING_VALUE VARCHAR
DOUBLE_VALUE FLOAT
EXAMPLE_LONG INTEGER
EXAMPLE_DATE DATE
// STEP 1 ////
// "Example" class to hold rows from our database table
class Example
{
public: // tablename.columnname:
int exampleInt; // DB_EXAMPLE.INT_VALUE
string exampleStr; // DB_EXAMPLE.STRING_VALUE
double exampleDouble; // DB_EXAMPLE.DOUBLE_VALUE
long exampleLong; // DB_EXAMPLE.EXAMPLE_LONG
TIMESTAMP_STRUCT exampleDate; // DB_EXAMPLE.EXAMPLE_DATE
Example(int exInt, const string &exStr, double exDouble, long exLong,
const TIMESTAMP_STRUCT &exDate) :
exampleInt(exInt), exampleStr(exStr), exampleDouble(exDouble), exampleLong(exLong),
exampleDate(exDate)
{ }
};
// STEP 2 ////
// Create an association between table columns and fields in our object
template<> class dtl::DefaultBCA<Example>
{
public:
void operator()(BoundIOs &cols, Example &rowbuf)
{
cols["INT_VALUE"] == rowbuf.exampleInt;
cols["STRING_VALUE"] == rowbuf.exampleStr;
cols["DOUBLE_VALUE"] == rowbuf.exampleDouble;
cols["EXAMPLE_LONG"] == rowbuf.exampleLong;
cols["EXAMPLE_DATE"] == rowbuf.exampleDate;
}
}
// STEP 3 & 4
// Read the contents of the DB_EXAMPLE table and return a vector of the
// resulting rows
vector<Example> ReadData() {
// Read the data
vector<Example> results;
DBView<Example> view("DB_EXAMPLE");
DBView<Example>::select_iterator read_it = view.begin();
for ( ; read_it != view.end(); read_it++)
{
results.push_back(*read_it);
}
return results;
}
1 See http://www.sgi.com/tech/stl/Container.html for the definition of an STL container, we
call DBView a semi container because it supports all
standard container methods except size(), max_size() and
empty(). We explain why these were left out by design in the
documentation for the DBView template.
//BPA Functor to bind SQL parameters to a data object
// "Example" class to hold rows from our database table
class Example
{
public: // tablename.columnname:
int exampleInt; // DB_EXAMPLE.INT_VALUE
string exampleStr; // DB_EXAMPLE.STRING_VALUE
double exampleDouble; // DB_EXAMPLE.DOUBLE_VALUE
long exampleLong; // DB_EXAMPLE.EXAMPLE_LONG
TIMESTAMP_STRUCT exampleDate; // DB_EXAMPLE.EXAMPLE_DATE
Example(int exInt, const string &exStr, double exDouble, long exLong,
const TIMESTAMP_STRUCT &exDate) :
exampleInt(exInt), exampleStr(exStr), exampleDouble(exDouble), exampleLong(exLong),
exampleDate(exDate)
{ }
};
// Create an association between table columns and fields in our object
class BCAExampleObj
{
public:
void operator()(BoundIOs &cols, Example &rowbuf)
{
cols["INT_VALUE"] == rowbuf.exampleInt;
cols["STRING_VALUE"] == rowbuf.exampleStr;
cols["DOUBLE_VALUE"] == rowbuf.exampleDouble;
cols["EXAMPLE_LONG"] == rowbuf.exampleLong;
cols["EXAMPLE_DATE"] == rowbuf.exampleDate;
}
}
class ExampleParamObj
{
public:
int lowIntValue;
int highIntValue;
string strValue;
TIMESTAMP_STRUCT dateValue;
};
class BPAParamObj
{
public:
void operator()(BoundIOs &boundIOs, ExampleParamObj ¶mObj)
{
boundIOs[0] == paramObj.lowIntValue;
boundIOs[1] == paramObj.highIntValue;
boundIOs[2] == paramObj.strValue;
boundIOs[3] == paramObj.dateValue;
}
};
// read some Example objects from the database and return a vector of
// the results, use BPA to set join parameters
vector<Example> ReadData()
{
vector<Example> results;
// construct view
DBView<Example, ExampleParamObj>
view("DB_EXAMPLE", BCAExampleObj(),
"WHERE INT_VALUE BETWEEN (?) AND (?) AND "
"STRING_VALUE = (?) OR EXAMPLE_DATE < (?) ORDER BY EXAMPLE_LONG",
BPAParamObj());
// loop through query results and add them to our vector
// in this loop, read_it.GetLastCount() records read from DB
DBView<Example, ExampleParamObj>::select_iterator read_it = view.begin();
// set parameter values for the WHERE clause in our SQL query
read_it.Params().lowIntValue = 2;
read_it.Params().highIntValue = 8;
read_it.Params().strValue = "Example";
TIMESTAMP_STRUCT paramDate = {2000, 1, 1, 0, 0, 0, 0};
read_it.Params().dateValue = paramDate;
for ( ; read_it != view.end(); read_it++)
{
cout << "Reading element #" << read_it.GetLastCount() << endl;
results.push_back(*read_it);
cout << "read_it->exampleInt = " << read_it->exampleInt << endl;
cout << "read_it->exampleStr = " << read_it->exampleStr << endl;
}
return results;
}
// Using a DBView to insert rows into a database
// ... Class definitions for Example and BCAExample as per our ReadData example .....
// Specialization of DefaultInsValidate for Example
// This defines a business rule we wish to enforce for all
// Example objects before they are allowed to be inserted into the database
template<> class dtl::DefaultInsValidate<Example>
{
public:
bool operator()(Example &rowbuf) {
// data is valid if rowbuf.exampleStr is nonempty and
// rowbuf.exampleDouble is
// between 0 and 100 (like a percentage)
return (rowbuf.exampleStr.length() > 0 && rowbuf.exampleDouble >= 0.0
&& rowbuf.exampleLong <= 100.0);
}
};
// Insert rows from the vector<Example> parameter into the database
void WriteData(const vector<Example> &examples)
{
DBView<Example> view("DB_EXAMPLE");
// loop through vector and write Example objects to DB
// write_it.GetCount() records written in loop
DBView<Example>::insert_iterator write_it = view;
for (vector<Example>::const_iterator ex_it = examples.begin(); ex_it != examples.end(); ex_it++, write_it++)
{
*write_it = *ex_it;
cout << "Writing element #" << write_it.GetCount() + 1<< endl;
}
}
None.
Parameter | Description | Default |
---|---|---|
DataObj | The type of object that will be written to the DBView. This object will be bound through use of the BCA to the appropriate columns in the database. The set of value types of an DBView::insert_iterator consists of a single type, DataObj. | |
ParamObj | The type of object that will be used to specify the postfix parameters to the DBView. | DefaultParamObj<DataObj> |
X | A type that is a model of DBView |
a | Object of type X |
t | Object of type X::value_type |
p, q | Object of type X::iterator |
In addition to the types defined in a semi-Container , the following types are defined.:
Iterator type | X::select_iterator | An input iterator to read records from the view |
Iterator type | X::insert_iterator | An output iterator to insert records into the view |
Iterator type | X::update_iterator | An output iterator to update records in the view |
Iterator type | X::delete_iterator | An ouput iterator to delete records from the view |
Name | Expression | Precondition | Semantics | Postcondition |
---|---|---|---|---|
Default constructor | X a(const string &tableList, const BCA &bca_functor = DefaultBCA<DataObj>(), const string &postfix = "", const BPA &bpa_functor = DefaultBPA<ParamObj>(), const SelVal sel_val = DefaultSelVal<DataObj>(), const InsVal ins_val = DefaultInsVal<DataObj>(), DBConnection &connection = DBConnection::GetDefaultConnection()) |
Creates an empty container bound to a
table, using the database connection specified in the
connection object. The actual queries run againt this
table are built by the select, insert, update and delete
iterators (see these iterators for details) but
essentially follow the following format: "SELECT " + <columns listed in bca_fn()> + " FROM " + tableList + postfix In the SQL clause, users may also specify dynamic parameters through the use of SQL '(?)' syntax. In this case BPA is a class that is used to hold these runtime parameters and bpa_functor is a functor used to associate fields in the parameters class with parameter fields in the query. |
The size of the container is 0. Rows are operated on by obtaining the appropriate iterator from the container. |
Member | Where defined | Description |
---|---|---|
value_type | Container | The type of object, T, stored in the DBView. In this case T = DataObj |
pointer | Container | Pointer to T. |
reference | Container | Reference to T |
const_reference | Container | Const reference to T |
size_type | Container | An unsigned integral type. |
difference_type | Container | A signed integral type. |
iterator | Container | Iterator used to iterate through a DBView. The default iterator for DBView is the select_iterator. |
const_iterator | Container | Const iterator used to iterate through a DBView. (iterator and const_iterator are the same type.) |
reverse_iterator | Reversible Container | Iterator used to iterate backwards through a DBView. |
const_reverse_iterator | Reversible Container | Const iterator used to iterate backwards through a DBView. (Reverse_iterator and const_reverse_iterator are the same type.) |
iterator begin() | Container | Returns an iterator pointing to the beginning of the DBView. |
const_iterator begin() const | Container | Returns a const_iterator pointing to the beginning of the DBView. |
iterator end() | Container | Returns a const_iterator pointing to the end of the DBView. |
const_iterator end() const | Container | Returns a const_iterator pointing to the end of the DBView. |
X a(const string &tableList, const BCA &bca_functor = DefaultBCA<DataObj>(), const string &postfix = "", const BPA &bpa_functor = DefaultBPA<ParamObj>(), const SelVal sel_val = DefaultSelVal<DataObj>(), const InsVal ins_val = DefaultInsVal<DataObj>(), DBConnection &connection = DBConnection::GetDefaultConnection()) |
Container | Creates an empty DBView. |
DBView(const DBView&) | Container | The copy constructor. |
DBView& operator=(const DBView&) | Container | The assignment operator |
void set_io_handler(IOHandler<DataObj, ParamObj>) | DBView | Sets the IOHandler for this view. Iterators created from this view will then use this handler by default until set by the iterator's version of this method. The IOHandler will try to handle exceptions thrown by such iterators and tell the code which caught the exception whether to suppress the error or still throw. |
template<class UserHandler> const UserHandler & get_io_handler(UserHandler *dummy) const | DBView | Returns the current IOHandler for this object cast to the actual type of the handler based on the dummy pointer passed in. If the dynamic cast of the IOHandler object fails, an exception will be thrown. |
IOHandler<DataObj, ParamObj> &get_io_handler() const | DBView | Returns the current IOHandler for this object as a raw IOHandler object. You must cast to the actual type of the handler to be able to access any of your handler's public members. |
void swap(DBView&) | Container | Swaps the contents of two DBView's. |
Multiple Associative Container, BCA, BPA, InsVal, SelVal, DB_iterator
Copyright © 2001, 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.