Menu
Simba Technologies
Simba Technologies

SimbaEngine X SDK 10.1.15
Build a C++ ODBC Driver in 5 Days (Windows)

Data Retrieval

In the Data Store Interface (DSI), the following methods perform the actual task of retrieving data from your data store:

  • Each MetadataSource implementation of GetMetadata()
  • TabbedUnicodeFileReader::GetData()

Both methods provide a way to uniquely identify a column within the current row. For MetadataSource, the Simba SQL Engine passes in a unique column tag (see DSIOutputMetadataColumnTag). For QSTable, the Simba SQL Engine will pass in the column index .

In addition, both methods accept the following three parameters:

  • in_data

    The SQLData into which you must copy the value of your cell. This class is a wrapper around a buffer managed by the Simba SQL Engine. To access the buffer, you call its GetBuffer() method. The data you copy into the buffer must be formatted as a SQL Type (see https://msdn.microsoft.com/en-us/library/ms710150%28VS.85%29.aspx for a list of data types and definitions). Therefore, if your data is not stored as SQL Types, you will need to write code to convert from your native format.

    The type of this parameter is governed by the metadata for the column that is returned by the class. Thus, if you set the SQL Type of column 1 in QSTable:: InitializeColumns() to SQL_INTEGER, then when TabbedUnicodeFileReader::GetData() is called for column 1, you will be passed a SQLData that wraps an int data type. For MetadataSource, the type is associated with the column tag (see DSIOutputMetadataColumnTag.h).
  • Example:

    If SqlData was of type SQL_INTEGER:

    simba_int32 value = 5;

    //This is one way

    memcpy(in_data->GetBuffer(), &value, sizeof(simba_int32));

    // This is another way; both work equally well

    *reinterpret_cast<simba_int32*>(in_data->GetBuffer()) = 5;

    When working with variable length data, for example character or binary data, you must call SetLength() before calling GetBuffer(). Not doing so may result in a heap violation. See QSTypeUtilities.h for an example on how to handle character or binary data.

  • in_offset

    Character, wide character and binary data types can be retrieved in parts. This value specifies where, in the current column, the value should be copied from. The value is usually 0.
  • in_maxSize

    The maximum size (in bytes) that can be copied into the in_data parameter. For character or binary data, copying data that is greater than this size can result in a data truncation warning or a heap violation.

SqlData Types

SqlData objects represent the SQL types and encapsulate the data in a buffer. To get the underlying SQL type that a SqlData object represents, use GetMetadata()->GetSqlType(). This retrieves the associated SQL_* type.

For information on how SQL types map to C++ types, see SQL Data Types in Developing Drivers for Data Stores Without SQL

Data Conversion in Practice

In the QuickStart example, when GetData() is called the values are read from the tabbed Unicode file (in TabbedUnicodeFileReader::GetData), converted to simba_wstrings (in QSTable::ReadWholeColumnAsString) and then converted to the requested SQL data type (in QSTable::ConvertData). This works well because the data source is a text file and a good cross-platform example.

For your data source, if you’re already getting data of the correct type—integers, for example—then ideally you should skip the conversion to strings so you can achieve better performance. Be aware of which data types map to which SQL Types, as well as how to represent them in the expected format. Then you can set the buffer in an appropriate manner.

NULL Values

To represent a null value, directly set the SqlData object as null:

in_data->SetNull(true);