Preliminary: January 30, 2002
1.0 Introduction
1.1 Thunderbolt
Engine API Overview
1.2 Thunderbolt Engine API
Interface Conventions
1.3 Writing Applications using Thunderbolt Engine API Interface
1.3.1 Calling from a C++ Program
1.4 Thunderbolt Engine API Concepts
Thunderbolt Engine API is the lowest level interface available for Thunderbolt Database applications. Thunderbolt Engine API provides functions to perform operations like opening and closing databases, data definition (create, alter, and drop tables, create views etc.), data manipulation (insert, update, and delete), and queries. Applications that need the power, performance and flexibility provided by the Thunderbolt Query Language (TQL) use this API. This is the API that underlies the Thunderbolt Native API Driver. Note: Because the Thunderbolt Engine API derives from the Thunderbolt Rapid Application Development system (RAD), and its predecessor 'D' the Data Language (DDL), some remnants of this history remain. For example, all of the API function names are in the form ddlxxx(). So, you may find some references to 'D'. Also, most API functions correspond to a particular 'D' command. For example, 'ddlFind()' API function corresponds to 'FIND' command. So, 'ddlFind()' API function document refers to the 'FIND' command description. |
1.2
Thunderbolt Engine API Interface Conventions
Thunderbolt Engine API has a set of interface
functions for various operations, and a structure called CONTROL
structure. CONTROL structure is a placeholder for database connection
handle and other information like errors and responses. The first argument
in calls to all API functions is a pointer to a control structure. A call
to ddlOpen() API function fills the CONTROL structure with a handle to the
opened database. All subsequent calls to that database use this CONTROL
structure.
typedef struct CONTROL{ int ddlHandle; /* context handle; do not change */ int Status; /* return 0 or error code */ char ErrorMessage[300]; /* return error string if Status is non-zero */ char ErrorMessage2[300]; char Response[300]; /* message in response to API call*/ char Response2[300]; long Ans1; /* return numeric Answer1 */ long Ans2; /* return numeric Answer2 */ long Ans3; /* return numeric Answer3 */ char Ans1str[300]; /* return string Answer1 */ char Ans2str[300]; /* return string Answer2 */ char Ans3str[300]; /* return string Answer3 */ }CONTROL;
Each API function can return up to three answers through the CONTROL structure. These answers can be either binary values or character strings. The answer pairs are: long Ans1; char Ans1str[300]; /* Answer1 */ long Ans2; char Ans2str[300]; /* Answer2 */ long Ans3; char Ans3str[300]; /* Answer3 */
The definition of the control structure is contained in an include file named "ddl_incl.h". Thunderbolt Engine API also includes a file called 'diag' with a list of diagnostic codes and their corresponding messages. Thunderbolt Engine uses this file to translate internal error codes in to messages understandable by users. |
1.3 Writing Applications using Thunderbolt Engine API
Interface
Following are the steps involved in using Thunderbolt Engine API:
1. Initialize Thunderbolt Engine API Driver
2. Open database connection
3. Do your operations on opened database
4. Close database connection
5. Unload Thunderbolt Engine API Driver
When you open a database, a connection handle will be returned in the CONTROL structure. You use this CONTROL structure for subsequent operations on the database.
For reading or writing a record, you have to define a buffer that matches the length of the record and pass it as argument to appropriate API calls.
1.3.1 Calling from a C++ Program
Here is an example C/C++ program showing opening a database, querying and reading the result records, writing a record to the database, and closing the database.
// Include Thunderbolt Engine header file #include "ddl_incl.h" /* This is the RD for this test program: RD CUSTOMER cust# x(6) name x(20) street x(15) city x(12) state x(2) zip x(5) */ // define a structure to hold CUSTOMER record // This structure is passed as a buffer to Thunderbolt API to read and write customer data struct CUSTOMER{ char custID[6]; char name[20]; char street[15]; char city[12]; char state[2]; char zip[5]; }; void main(int argc, char *argv[]) { // Declare a control structure // This holds your database handle static struct CONTROL ctl; struct CUSTOMER cust; // declare a customer buffer to read and write customer records char* dbName = "C:\WhamTech\DatabasePath\DatabaseName"; // fill database path + name // Initialize driver ddlBegin(&ctl); if(ctl.Status!=0) printf("\n\nBEGIN ERROR: %s\n\n",ctl.ErrorMessage); // Open Database connection ddlOpenR(&ctl,"/W", dbName); if(ctl.Status!=0){ printf("\n\nOPEN ERROR: %s\n",ctl.ErrorMessage); exit(1); } // Query for customers with name starting with 'B' ddlFind(&ctl,"/","A CUSTOMERS WHERE NAME SV \'B\'"); if(ctl.Status!=0) printf("\n\nFIND ERROR: %s\n\n",ctl.ErrorMessage); // sort results by name ddlSort(&ctl,"/U","A CUSTOMERS BY NAME"); if(ctl.Status!=0) printf("\n\nSORT ERROR: %s\n\n",ctl.ErrorMessage); // read results if(ctl.Response[0]!=0){ printf("\n-->Sort %s %%ANSWER1=%ld",ctl.Response,ctl.Ans1); for(int i=0;i< ctl.Ans1;++i){ ddlGetRec(&ctl,"/","A CUSTOMERS CUS_REC",(char*)&cust); if(ctl.Status!=0){printf("\n\nREAD ERROR: %s\n\n",ctl.ErrorMessage); break;} printf("\n%-6.6s %-20.21s %-15.16s %-12.13s %-2.2s %-5.5s",.cust,cust.name,cust.street,cust.city,cust.state,cust.zip); } } // // Write a customer record // // Initialize cust buffer ddlInitRec(&ctl,"/","customers",(char*)&cust); if(ctl.Status!=0){printf("\n\nINIT ERROR: %s\n\n",ctl.ErrorMessage); break;} // Set customer data to write char* myName = "MyName"; char* myStreet = "MyStreet"; char* myCity = "MyCity"; char* myState = "MyState"; char* myZip = "MyZip"; memcpy(cust.custID,"123456",6); memcpy(cust.name myName,strlen(myName)); memcpy(cust.street, myStreet,strlen(myStreet)); memcpy(cust.city,myCity,strlen(myCity)); memcpy(cust.state,myState,strlen(myState)); memcpy(cust.zip,myZip,strlen(myZip)); // Write a record ddlPutRec(&ctl,"/","CUSTOMERS CUSTOMERS",(char*)&cust); if(ctl.Status!=0){printf("\n\nWRITE ERROR: %s\n\n",ctl.ErrorMessage); break;} // Close Database connection ddlCloseR(&ctl); if(ctl.Status!=0){printf("\n\nCLOSE ERROR: %s\n\n",ctl.ErrorMessage); exit(1);} // Unload driver ddlEnd(&ctl); }
Thunderbolt
Engine API can be called from Visual Basic Versions 5.0 and above. However,
each entry point ddlXxx() has a special VB entry point ddlSXxx() which uses the
stdcall calling sequence required by VB 5 and above. For example, ddlOpen() is
called ddlSOpen() in Visual Basic.
Refer to the file vbsample.bas in the samples folder for definitions of the
CONTROL structure and function prototypes.
1.4 Thunderbolt Engine API Concepts
1.4.1 The Thunderbolt Paradigm
See the Thunderbolt Paradigm document.
1.4.2 Tables and Fields
See the Tables and Fields
document.
1.4.3 Indexes
See the Indexes document.
1.4.4 Collections
See the Collections document.
2.7 ddlCatRD() - concatenate two RDs
Prototype:
void ddlCatRD(
CONTROL *ctl,
char *OptnStr,
char *ArgList);
Permitted values in OptnStr: NA
Form of ArgList:
<rdname1> <rdname2>
<rdname3>
<rdname1>
is the name of the first source record description
<rdname2>
is the name of the second source record description
<rdname3>
is the name of the target record description
Description:
Creates a new record description <rdname3>, which is the logical
concatenation of <rdname1> and <rdname2>.
2.28 ddlDeleteB() - delete record
Prototype:
void ddlDeleteB(
CONTROL *ctl,
char *OptnStr,
char *ArgList);
Permitted values in OptnStr: NA
Form of ArgList:
<dgname> <rec#>
Description:
Deletes data record specified all key
index structures associated with that record.
See the DELETE command.
Value returned in Control.Ans1:
Number of records deleted [1 or 0]
2.48 ddlFindX() - isolate records in a collection
Prototype:
void ddlFindX(
CONTROL *ctl,
char *OptnStr,
char *ArgList,
float *Array,
int Length);
Permitted values in OptnStr: NA
Form of ArgList:
<cx> [<dgname>] <field>
Array is an array of values whose type depends on the type of
<field>
<field> type Array type
I
short
int
ID
long
int
F
float
FD
double
Length is the number of floating point values in Array.
Description:
Performs FIND <cx> [<dgname>] where
<field> EQ Array[0] OR <field> EQ Array[1] OR ...
Values returned in Control Structure:
Control.Ans1 | Total number of records selected |
void ddlFindXY(
CONTROL *ctl,
char *OptnStr,
char *ArgList,
float *Array1,
char *Arg2,
float *Array2,
int Length);
Permitted values in OptnStr: NA
Form of ArgList:
<cx> [<dgname>] <field1>
Array1 is an array of values whose type depends on the type of
<field1>
<field1> type Array1 type
I
short
int
ID
long
int
F
float
FD
double
Form of Arg2:
<field2>
Array2 is an array of values whose type depends on the type of
<field2>
<field2> type Array2 type
I
short
int
ID
long
int
F
float
FD
double
Length is the number of floating point values in each array.
Description:
Performs FIND <cx> [<dgname>] where
(<field1> EQ Array1[0] and <field2> EQ Array2[0]) OR
(<field1> EQ Array1[1] and <field2> EQ Array2[1]) OR
...
Values returned in Control Structure:
Control.Ans1 | Total number of records selected |
void ddlGetRDHandle(
CONTROL *ctl,
char *OptnStr,
char *ArgList);
Permitted values in OptnStr: NA
Form of ArgList:
<rdname> [<piPathName>]
<rdname>
is the ASCII name of the record description that describes Image;
<piPathName>
is the path and name of the .pi filefor an external RD
Description:
Searches for the requested RD.
Values returned in Control Structure:
Control.Ans1 | RD Handle |
Control.Ans2 | Number of fields in RD |
Control.Ans3 | Length of record |
void ddlGetRecB(
CONTROL *ctl,
char *OptnStr,
char *ArgList,
char *Image);
Permitted values in OptnStr: NA
Form of ArgList:
<dgname> <rdname>
[<piPathName>] <rec#>
Form of Image:
Image must reflect exactly the record described by rdname.
Description:
Reads a record from the open database. The contents
of the record are stored into a record image whose
form is described by the record description <rdname>.
ddlGetRecB() does not support data type TEXT.
When an external RD in specified [by (piPathName)], the RD is automatically
cached for possible future use.
Each call to ddlGetRecB() causes a physical read of
the database to ensure that the latest record is read.
Values returned in Control Structure:
Control.Ans1 |
0 - Invalid record number; or requested record is deleted 1 - Record was read successfully |
void ddlLimit( CONTROL *ctl, char *OptnStr, char *ArgList);
Permitted values in OptnStr:
/X - suppress calls to Print Callback
void ddlRereadRec(
CONTROL *ctl,
char *OptnStr,
char *ArgList,
char *Image);
Permitted values in OptnStr: NA
Form of ArgList:
<cx> <dgname> <rdname>
[<piPathName>]
Form of Image:
Image must reflect exactly the record described by rdname.
Description:
Rereads the last record read.
Each call to ddlRereadRec() causes a physical read of
the database to ensure that the latest record is read.
Values returned in Control Structure:
Control.Ans1 | 1 - record read successfully |
Control.Ans2 | record number of record |
void ddlRewriteRec(
CONTROL *ctl,
char *OptnStr,
char *ArgList,
char *Image);
Permitted values in OptnStr: NA
Form of ArgList:
<cx> <dgname> <rdname>
[<piPathName>]
Form of Image:
Image must reflect exactly the record described by rdname.
Description:
Modifies the last record read or written in the open database. The contents of
the modified record are contained
in a record image whose form is described by the record
description <rdname>.
The record image must be initialized to ASCII
blanks for X() data types, to ASCII zeros for N()
data types, and to binary zeros for binary data
types. This can be done easily with the ddlInitRec()
function.
X() and N() data types should never contain
binary zeros.
For fields in the database which are data type N(), it is suggested that the
corresponding field in the record description be data type X(), with a size
that allows for required sign and/or point.
ddlRewriteRec() does not support data type TEXT.
When an external RD in specified [by (piPathName)], the RD is automatically
cached for possible future use.
Values returned in Control Structure:
Control.Ans1 | 1 - record written successfully |
Control.Ans2 | record number of record |
void ddlRewriteB(
CONTROL *ctl,
char *OptnStr,
char *ArgList,
char *Image);
Permitted values in OptnStr: NA
Form of ArgList:
<dgname> <rdname> [<piPathName>]
<rec#>
Form of Image:
Image must reflect exactly the record described by rdname.
Description:
Rewrites the specified record.
The contents of the modified record are contained
in a record image whose form is described by the record
description <rdname>.
The record image must be initialized to ASCII
blanks for X() data types, to ASCII zeros for N()
data types, and to binary zeros for binary data
types. This can be done easily with the ddlInitRec()
function.
X() and N() data types should never contain
binary zeros.
For fields in the database which are data type N(), it is suggested that the
corresponding field in the record description be data type X(), with a size
that allows for required sign and/or point.
ddlRewriteB() does not support data type TEXT.
When an external RD in specified [by (piPathName)], the RD is automatically
cached for possible future use.
Values returned in Control Structure:
Control.Ans1 | 1 - record written successfully |
Control.Ans2 | record number of record |
void ddlUnlog( CONTROL *ctl, char *OptnStr, char *ArgList);
Permitted values in OptnStr:
/X - suppress calls to Print Callback
Form of ArgList: See Description
Description:
See the UNLOG command.
Note:
All printing performed by the ddlUnlog() function is achieved thru a user
callback, as specified in the ddlPrintCallback() function.
Copyright © 2019 , WhamTech, Inc. All rights reserved. This
document is provided for information purposes only and the contents hereof are
subject to change without notice. Names may be
trademarks of their respective owners.