dtl
  
| Category: functors | Component type: concept | 
A BPA is a function object (this can be a wrapped function pointer if you use cb_ptr_fun()) that is called to create an association between the parameters in a SQL statement and the fields in a user defined parameter object that is used to hold individual values to pass to the query.
Each possible form of information flow between boundIO and DataObj/ParamObj corresponds to whether the parameter passed in to the query is an input, output, or input/output parameter. The user must be able to define the direction of information flow for parameters in cases such as stored procedure calls. The new binding syntax DTL provides shows the flow of information very clearly:
| Expressions | Parameter Type | Description | 
|  
       boundIOs[colName] << dataObj.member boundIOs[paramNum] << paramObj.member  | 
    INPUT | The DataObj/ParamObj member supplies data needed by the SQL query. | 
|  
       boundIOs[colName] >> dataObj.member boundIOs[paramNum] >> paramObj.member  | 
    OUTPUT | The DataObj/ParamObj member receives data back from the SQL query. | 
|  
       boundIOs[colName] == dataObj.member boundIOs[paramNum] == paramObj.member  | 
    INPUT/OUTPUT | The DataObj/ParamObj member both supplies data to and receives back data from the SQL query. | 
You should always use this new syntax with any BCA's and BPA's you define. To maintain backwards compatibility with BCA's and BPA's for select_iterator's, insert_iterator's, delete_iterator's, and update_iterator's, the use of "boundIOs[colName] == dataObj.member" and "boundIOs[paramNum] == paramObj.member" is still legal. The direction of information flow can be inferred from the type of iterator used in those cases. However, the directional syntax is mandatory for sql_iterators as no information flow semantics can be inferred from a general SQL query. Examples in this documentation may use both forms of syntax where legal.
None.
//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;
}
//Function object to bind SQL parameters to a data object
class BPAExampleObj
{
public:
	void operator()(BoundIOs &boundIOs, ParamObjExample ¶mObj)
	{
	  boundIOs[0] << paramObj.lowIntValue;
	  boundIOs[1] << paramObj.highIntValue;
	  boundIOs[2] << paramObj.strValue;
	  boundIOs[3] << paramObj.dateValue;
	}
};
| X | A type that is a model of BPA | 
| a | Object of type X | 
| Name | Expression | Precondition | Semantics | Postcondition | 
|---|---|---|---|---|
| Default constructor | X a()  | 
        Construct the function object. | ||
| Copy constructor | X a(constX &b)  | 
        Copy construct the BPA. | ||
| Assignment operator | X& operator=(const X&b)  | 
        Assignment copy | ||
| Bind columns operator | void operator()(BoundIOs &boundIOs, ParamObj ¶mbuf)  | 
        This operator takes a BoundIOs object and a reference
        to a parambuf holding
        a user defined parameter object. The job of the bind
        parameters operator is to create an association between
        parameters in a SQL view as designated by a "(?)" and
        fields in a user defined parameter object. This
        association is usually created by invoking the following
        cantrip: boundIOs[SQL Parameter Number] == parambuf.FieldName for each parameter in the SQL query. For details on this syntax see BoundIOs. The parameters to be bound must be statically allocated members of the ParamObj (there are some exceptions - see BoundIOs for details). At the end of the operation, all parameters to be bound in the SQL query must be in the BoundIOs container. When operator() is called, the BoundIOs container will not be empty, but will typically contain any previously bound fields from the BCA.  | 
        BoundIOs contains a complete list of parameter in the SQL query which are bound to the ParamObj. | 
None.
BCA, BoundIOs, DBView, IndexedDBView
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.