dtl


variant_row

Category: utilities Component type: type

Description

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.

Definition

Defined in the variant_row.h header file.

Refinement of

None.

Associated types

variant_field, TypeTranslation.

Example 1:

// 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;


};

Example 2:

Example: Reading a set of records from an Oracle stored procedure.


// 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 

Example 3:

Example: Using a DynamicDBView to insert records into the database. Illustrates writing NULL values to the database.

// 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!
}

Public base classes

None.

Notation

X A type that is a model of variant_row
a Object of type X

Expression semantics

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 _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..    

Notes

[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.

See also

variant_field, DynamicDBView, DynamicIndexedDBView


[DTL Home]

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.

This site written using the ORB. [The ORB]

1