dtl


variant_field

Category: utilities Component type: type

Description

The variant_field class provides a mechanism to access data fields within a variant_row. variant_field is designed to hold values of arbitrary types. In addition variant_field provides the ability for users to cast values between types and assign values back to the variant_row that created a given variant object. 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_row, 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: 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_field
a Object of type X

Expression semantics

Name Expression Precondition Semantics Postcondition
Default constructor
X a()
  Creates an empty variant_field. The type and variant_row parent pointer is not set so an empty variant_field cannot be used until is has been copy or assignment constructed from a variant_row class. The row is empty.
Copy constructor
X a(const X &b)
  Creates a variant_field to hold an arbitrary type with the given variant_row parent specified in b. The types, and values stored in b are copied into a. The row is initialized to be able to hold the types and values given in b. The data held in b is copied to a.
Assignment operator
variant_field & 
operator=(const variant_field &b)
  Assigns a variant_field to hold an arbitrary type with the given variant_row parent specified in b. The types, and values stored in b are copied into a. The row is initialized to be able to hold the types and values given in b. The data held in b is copied to a.
Assign data to a variant_field
template<typename T> const variant_field & 
operator=(const T &other)
  Assigns a value to a variant_field. The field's type information is updated to reflect the type of the object passed in and the value of the object is copied to the field's internal data. IN ADDITION, THE NEW VALUE HELD BY THE FIELD IS COPIED BACK TO THE PARENT variant_row. So, if the parent variant_row requires a string for the given field, when a copy operation to the variant_row is attempted, first the data will be cast to a string, then that string data will be copied into the variant_row data. This allows for transparent and type-safe assignment into the variant_row object. This copy process is internal to the variant_row object. For example, if the source variant_field object contains a double but the target variant_row field requires a string any casts done to obtain a string will be internal to variant_row and will not affect the data or type held by the variant_field object. There are some restrictions, see [1].  
Cast operator
template <class T> operator T()
  Casts the variant data held in the class to a desired target type. Thus, the class might hold a string as its variant data, but we want to cast it to a double. Suppose a is a variant_field that holds a string as its internal data. The expresssion (double) a will try to convert the string held internally into a number to return. There are some restrictions, see [1].  
Determine if field holds a NULL value
bool IsNull()
  Returns true if the data held by the field represents a NULL value.  
Get an enumerated value listing the type of data held by the field
char type()
  Returns an enumeration listing the type of the data held by the variant_field. This enumeration is listed in bind_basics.h as follows, but is subject to change so check this file for the latest version:

// short, unsigned short, int, unsigned int, long, unsigned long
// double, float, struct TIMESTAMP_STRUCT, char *, string, wstring, blob

enum {C_UNKNOWN=0, C_SHORT='n', C_USHORT='N', C_INT='i', C_UINT='I', C_LONG='l',
C_ULONG='L', C_DOUBLE='d', C_FLOAT='f',
C_TIMESTAMP='t', C_CHAR_STAR='C'-'A'+1, C_STRING='s', C_WSTRING='w',C_BLOB='S'};

 
Test if the value held by the field matches a particular type
template<typename T> bool is_type()
  This method can be used to test if this variant_field
holds a value of type T. It takes no arguments,
so it can only be used with explicit template
instantiation, e.g.:
if ( a.is_type<int>() )
 
Steam operator
ostream &operator<<(ostream &o, const variant_field &vf)
  Stream the value held by the variant_field to a standard ostream.  
Null check bool IsNull()   Is this field null?  
Set field to null void SetNull()   Set this field to null  
Make field non-null void ClearNull()   Make this field non-null.  
Null field assignment const variant_field &operator=(const NullField &null)  

Convenience assignment operator to set the destination field to null. Gives clean syntax to make a field have the null value, as in:

var_row[fieldName] = NullField();

Essentially equivalent to SetNull().

 
Is null comparison

bool operator==(const NullField &null)

friend bool operator==(const NullField &null, const variant_field &vf)

Returns whether the given field is null. Equivalent to a call to IsNull().    
Is not null comparison

bool operator!=(const NullField &null)

friend bool operator!=(const NullField &null, const variant_field &vf)

Returns whether the given field is non-null. Equivalent to a call to !IsNull().    

Notes

[1] The allowable types that can be assigned into and cast from variant_field is currently a limited set of types covering the common data types seen in SQL data fields. See variant.h and bind_basics.h for the current list of types supported by this class.

See also

variant_row, 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