dtl
Category: utilities | Component type: type |
The variant_row class provides a mechanism to hold an arbitrary number of fields with values of arbitrary types. This class is used primarily by dynamic queries where the number and the types of the fields returned by a query are unknown.
Defined in the variant_row.h header file.
None.
variant_field, TypeTranslation.
// Manipulating fields in a variant_row
void variant_row_example(void) {
TIMESTAMP_STRUCT test_date = {1999, 9, 29, 0, 0, 0, 0};
vector<TypeTranslation> types;
vector<string> names;
int i;
string s;
TypeTranslation vt0=TypeTranslation(typeid(int).name(), C_INT, SQL_INTEGER, SQL_C_SLONG,
TypeTranslation::TYPE_PRIMITIVE, sizeof(int)),
vt1=TypeTranslation(typeid(string).name(), C_STRING, SQL_VARCHAR, SQL_C_CHAR,
TypeTranslation::TYPE_COMPLEX, sizeof(string));
types.push_back(vt0);
names.push_back("int");
types.push_back(vt1);
names.push_back("string");
variant_row r(types, names);
r["int"] = (int)r["int"] + 5;
i = (int)r["int"];
s = (string) r["int"];
r["int"] = test_date;
s = (string) r["int"];
// Print out the column names
vector<string> colNames = r.GetNames();
for (vector<string>::iterator name_it = colNames.begin(); name_it != colNames.end(); name_it++)
{
cout << (*name_it) << " ";
}
cout << endl;
// Print out all column values
for (i = 0; i < r.size(); i++)
cout << r[i] << " ";
cout << endl;
};
// Oracle stored procedure we wish to test
// for more information on this example, see the following Oracle documentation
#if 0
Create or replace package ExampleInfo as
Type ExampleRec is record
(
INT_VALUE integer,
STRING_VALUE varchar2(50)
);
Type ExampleCursor is ref cursor return
ExampleRec;
End ExampleInfo;
Create or replace procedure ExampleInfoProc
(LONG_CRITERIA IN integer, empcursor IN OUT
ExampleInfo.ExampleCursor)
As
Begin
Open empcursor For
select INT_VALUE, STRING_VALUE
from db_example
where EXAMPLE_LONG = LONG_CRITERIA;
End;
#endif
class ProcBCA {
public:
void operator()(BoundIOs &cols, variant_row &row)
{
cols["INT_VALUE"] >> row._int();
cols["STRING_VALUE"] >> row._string();
cols.BindVariantRow(row);
}
};
class ProcParams {
public:
long long_criteria;
};
class ProcBPA {
public:
void operator()(BoundIOs &cols, ProcParams &row)
{
cols[0] << row.long_criteria;
}
};
// Read the contents of a table and print the resulting rows
// *** you must have Oracle ODBC driver version 8.1.5.3.0 for this to work ***
// The reason why is that the stored procedure shown above returns a "cursor"
// to pass back multiple rows which is only supported in Oracle ODBC driver
// version 8.1.5.3.0 or higher. (Merant drivers for Oracle also support this syntax.)
void StoredProcReadData() {
// Note: ExampleInfoProc takes an integer as an input parameter to determine
// what records to return, and returns a cursor to a set of rows as an
// output parameter. The output cursor is bound implicitly as a set of columns.
DBView<variant_row, ProcParams> view("{call ExampleInfoProc(?)}",
ProcBCA(), "", ProcBPA());
variant_row s(view.GetDataObj());
// Print out the column names
vector<string> colNames = s.GetNames();
for (vector<string>::iterator name_it = colNames.begin(); name_it != colNames.end(); ++name_it)
cout << (*name_it) << " ";
cout << endl;
// Print out all rows and columns from our query
DBView<variant_row, ProcParams>::sql_iterator print_it = view.begin();
print_it.Params().long_criteria = 22;
for (; print_it != view.end(); ++print_it)
{
variant_row r = *print_it;
for (size_t i = 0; i < r.size(); ++i)
cout << r[i] << " ";
cout << endl;
}
}
// Using a DynamicDBView to insert records into the database.
// this example also shows how to set NULL fields in a variant_row
// Insert two rows into a table with unknown fields
void SimpleDynamicWrite() {
TIMESTAMP_STRUCT paramDate = {2012, 12, 23, 0, 0, 0, 0};
// Mayan DOOMSDAY! End of the Mayan 5126 year long calendar cycle starting from May 1, 3094 B.C.
// Date is 13.13.13.0.0.0.0 4 Ahaw, 3 K'ank'in
DynamicDBView<> view("DB_EXAMPLE", "*");
DynamicDBView<>::insert_iterator write_it = view;
// NOTE: We need to construct r from the view itself since we
// don't know what fields the table will contain.
// We therefore make a call to the DataObj() function to have the
// table return us a template row with the correct number of fields
// and field types.
variant_row r(view.GetDataObj());
// Prepare the number of the beast!
// Set all fields to the value 6,
// except for the last column which is a date and cannot
// currently accept numeric values
for (size_t i = 0; i < r.size()-1; i++)
{
r[i] = 6;
}
r[i] = paramDate; // set the Doomsdate
// insert the number
*write_it = r;
write_it++;
// Prepare the number of angels who stand before
// the throne of God!
// Set all fields to the value 7,
// except for the last column which is a date and cannot
// currently accept numeric values
for (i = 0; i < r.size()-1; i++)
{
r[i] = 7;
}
r[i] = paramDate;
// insert the number
*write_it = r;
write_it++;
// Insert Purgatory (the void) into the database.
// Set all fields to NULL
for (i = 0; i < r.size()-1; i++)
{
r[i] = NullField();
}
r[i] = NullField();
// insert the number
*write_it = r;
write_it++;
// For more on this example - see the *REAL* DTL homepage!
}
None.
X | A type that is a model of variant_row |
a | Object of type X |
Name | Expression | Precondition | Semantics | Postcondition |
---|---|---|---|---|
Default constructor |
X a() |
Creates an empty variant_row. The type and number of fields is not set so an empty variant_row cannot be used until is has been copy or assignment constructed from another row. | The row is empty. | |
Alterante constructor |
X a(vector<TypeTranslation> &types, vector<string> &names) |
Creates a variant_row to hold an array of types as specified in types with field names given by names. In practice, you should never need to use this. Instead we recommend that you get any raw rowbuf object that you need by calling the DataObj() method of DynamicDBView or DynamicIndexedDBView to get a variant_row constructed for you that matches the columns in your query. See [1] for details about TypeTranslation. | The row is initialized to be able to hold the given types and access these fields using the specified names. | |
Copy constructor |
X a(const X &b) |
Creates a variant_row to hold an array of types as specified in b. The types, field names and values stored in b are copied into a. | The row is initialized to be able to hold the types and fields given in b. The data held in b is copied to a. | |
Assignment operator | const X & operator=(const X &b) | Assigns to the variant_row to hold an array of types as specified in b. The types, field names and values stored in b are copied into a. | The row is initialized to be able to hold the types and fields given in b. The data held in b is copied to a. | |
Get field types |
vector<TypeTranslation> GetTypes() |
Returns a vector listing the type of each field in variant_row in the order that these fields occur. See [1] for details about TypeTranslation. | ||
Get field names |
vector<string> GetFields() |
Returns a vector listing the name of each field in variant_row in the order that these fields occur. | ||
Get number of fields |
size_t size() |
Returns the number of fields in the variant_row. | ||
Get field by number |
variant_field operator[](int i) const variant_field operator[](int i) const |
Retrieves field number i from the variant_row object. Fields are numbered starting at 0. The field is returned as a variant_field object. | ||
Get field by name |
variant_field operator[](const string &f) const variant_field operator[](const string &f) const |
Retrieves the field with the name given by the string f from the variant_row object. Fields are numbered starting at 0. The field is returned as a variant_field object. | ||
Variant field creators for the appropriate types |
TypeTranslationField _short() TypeTranslationField _unsigned_short() TypeTranslationField _int() TypeTranslationField _unsigned_int() TypeTranslationField _long() TypeTranslationField _unsigned_long() TypeTranslationField _double() TypeTranslationField _float() TypeTranslationField _string() TypeTranslationField _wstring() TypeTranslationField _tstring() (see Unicode docs) TypeTranslationField _tchar_star() (binds to a fixed length string of type TCHAR[BoundIO::MINSTRBUFLEN]) TypeTranslationField _jtime_c() TypeTranslationField _timestamp() TypeTranslationField _bool() TypeTranslationField _blob() |
Creates an "empty" variant_field for use in binding columns or parameters. Using these functions, in a BCA or BPA, the user can say something like: boundIOs[paramNum] >> var_row._typename() This provides the user a syntax to construct a variant_row on the fly in the BCA or BPA. When binding columns, the user must then conclude the BCA by calling boundIOs.BindVariantRow(vr) to commit the structure of the variant_row to the BoundIOs. |
||
Set field to null |
void SetNull(int i) void SetNull(const string &fieldName) |
Sets the field with the given index to null. | ||
Make field non-null. |
void ClearNull(int i) void ClearNull(const string &fieldName) |
Makes the field with the given index non-null. | ||
Make all fields non-null | void ClearNulls() | Makes all fields non-null. | ||
Null field check |
void IsNull(int i) void IsNull(const string &fieldName) |
Returns whether the field with the given index is null. | ||
Comparison operators |
friend bool operator==(const variant_row &vr1, const variant_row &vr2) friend bool operator!=(const variant_row &vr1, const variant_row &vr2) friend bool operator<(const variant_row &vr1, const variant_row &vr2) friend bool operator>(const variant_row &vr1, const variant_row &vr2) friend bool operator<=(const variant_row &vr1, const variant_row &vr2) friend bool operator>=(const variant_row &vr1, const variant_row &vr2) |
These operators return whether the specified relationship between the two variant_row's is satisifed. The fields of the row are compared in order from vr[0] (most significant) to vr[vr.size() - 1] (least significant). In teh case of nulls, a null value for a field is considered to be less than a non-null one and two null values are treated as equal.. |
[1] TypeTranslation is an internal structure that is used by the library to translate between C types and SQL types. Details of the mapping that we use may be found in bind_basics.h and bind_basics.cpp. Typically, one would not read types directly off of this vector but would instead use type information functions exposed by the variant_field object.
variant_field, DynamicDBView, DynamicIndexedDBView
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.