Class: cSQLExecutor

Properties  Events  Methods    Index of Classes

Provides the API for executing SQL Statements from DataFlex

Hierarchy

cObject
---cBaseSQLExecutor
------cSQLExecutor

Library: Common (Windows and Web Application) Class Library

Package: cSQLExecutor.pkg

Description

The cSQLExecutor class provides the API for executing SQL Statements from DataFlex. It can be used as a global singleton object for executing queries within only a single line of code or with an instance per connection or per prepared statement.

Result sets are immediately fetched and made available in native types (structs, arrays, variants) using a flexible and smart API. Prepared statements with named parameters are supported. There are APIs for querying the result set structure and the parameters to build dynamic applications.

If an ODBC error occurs, OnSQLError is called and the global Err flag will be set.


To get full Studio support, use @SQL strings or include queries from separate files using Include_Text.

The engine of the cSQLExecutor is inside the runtime and is exposed in the abstract cBaseSQLExecutor class. The runtime works directly with ODBC and relies on the connectivity kits to manage the connection. This means that the cSQLExecutor works with the ODBC based drivers (MS SQL, DB2 and ODBC).

Using the cSQLExecutor Class / Object


Setting up the Database Connection


The database connection to the SQL database can be setup by using a Managed Connection. The psConnectionID property of cSQLExecutor should be set to one of the Connection IDs defined in the SQL Connection Manager of your workspace.

Example

Set psConnectionId of ghoSQLExecutor to "MyConnectionID"

pbIsConnected can be checked to test if a connection is initialized.

Singleton


The simplest way to use the cSQLExecutor is to create a singleton instance within your project. This can be done using the template available in the Create New dialog in the DataFlex Studio: File Menu > New > Other > SQL Executor.

This will create a .pkg file that can be included in a program.

Example

Use cSQLExecutor.pkg

Object oSQLExecutor is a cSQLExecutor
    Move Self to ghoSQLExecutor
    //Set psConnectionId to "SQLDATA"
End_Object


ghoSQLExecutor is a predefined global variable that can be used to access the SQLExecutor object throughout the program.


Use in WebApps

When a cSQLExecutor object is placed above a cWebApp object, as in the example below, error "This program is a webapp program and cannot be run standalone. This program must be run under DataFlex 23.0 WebApp Application Server" is displayed. The error occurs because cSQLExecutor uses ComponentType metadata tag and the file is seen as a Windows project.

Use cSQLExecutor.pkg
Object oSQLExecutor is a cSQLExecutor
    Move Self to ghoSQLExecutor
End_Object

Object oWebApp is a cWebApp


Include a PKG file with the desired code instead:

Use MycSQLExecutorObject.pkg

Object oWebApp is a cWebApp



Result Sets


The result sets of a query can be fetched into the following types:
- String
- Variant
- Struct
- tWebRow
- tDataSourceRow

The destination array for String and Variant should be defined as a two-dimensional array and the array for Structs, tWebRow and tDataSourceRow should be defined as one dimensional array.

String Array Example

This query will result in a two dimensional array of [100][3] i.e. 100 rows with 3 columns of type string.

String[][] aResults

// Fetch results into aResults
Get SQLExecDirect of ghoSQLExecutor @SQL"SELECT
    Name,  
    City,
    Zip
    FROM Customer" to aResults

// Test for errors
If (not(Err)) Begin
    // Process results here..
End


Variant Array Example

This query will result in a two dimensional array of [100][4] i.e. 100 rows with 4 columns. Note that in this case the column Customer_Number will be of type Integer and the Name, City and Zip column are of type String.

Variant[][] aResults

// Fetch results into aResults
Get SQLExecDirect of ghoSQLExecutor @SQL"SELECT
    Name,  
    City,
    Zip
    FROM Customer" to aResults

// Test for errors
If (not(Err)) Begin
    // Process results here..
End  


Struct Array Example

This query will result in a one dimensional array of [100] i.e. 100 rows of struct tResult holding the data.

//Define the struct
Struct tResult
    String  Name
    String  City
    String  Zip
End_Struct

tResult[] aResults

// Fetch results into aResults
Get SQLExecDirect of ghoSQLExecutor @SQL"SELECT
    Name,  
    City,
    Zip
    FROM Customer" to aResults

// Test for errors
If (not(Err)) Begin
    // Process results here..
End  


Use with Grids

The cSQLExecutor class also embeds the possibility of fetching result set data directly into tDataSource and tWebRow to make the use of grids very convenient. In combination with the column info, one can make the grids dynamic with a few lines of code.

tDataSoureRow Array Example

This query will result in a one dimensional array of [100] i.e. 100 rows of struct tDataSourceRow holding the data.

tDataSourceRow[] aDataSourceRows

// Fetch results into aDataSourceRows
Get SQLExecDirect of ghoSQLExecutor @SQL"SELECT           
    Name,  
    City,
    Zip
    FROM Customer" to aDataSourceRows

// Test for errors
If (not(Err)) Begin
    // Process results here..
End


tDataSoureRow Array Example with Static Grid

// the grid object  
Object oCJGrid1 is a cCJGrid
    Set Size to 192 517
    Set Location to 6 10

    Object oCJGridColumn1 is a cCJGridColumn
        Set piWidth to 300
        Set psCaption to "Name"
    End_Object

    Object oCJGridColumn1 is a cCJGridColumn
        Set piWidth to 200
        Set psCaption to "City"
    End_Object

    Object oCJGridColumn1 is a cCJGridColumn
        Set piWidth to 60
        Set psCaption to "Zip"
    End_Object        
End_Object

// further in the code
tDataSourceRow[] aDataSourceRows

// Fetch results into aDataSourceRows
Get SQLExecDirect of ghoSQLExecutor @SQL"SELECT           
    Name,  
    City,
    Zip
    FROM Customer" to aDataSourceRows

// Test for errors
If (not(Err)) Begin
    //Initialize the grids i.e. fill
    Send InitializeData of oCJGrid1 aDataSourceRows
End


tWebRow Array Example

This query will result in a one dimensional array of [100] i.e. 100 rows of struct tWebRow holding the data.

tWebRow[] aWebRows

// Fetch results into aWebRows

Get SQLExecDirect of ghoSQLExecutor @SQL"SELECT           
    Name,  
    City,
    Zip
    FROM Customer" to aWebRows

// Test for errors
If (not(Err)) Begin
    // Process results here..
End



Multiple Result Sets


In case of multiple result sets, the destination array for String and Variant should be defined as a three-dimensional array and the array for Structs, tWebRow and tDataSourceRow should be defined as two-dimensional array.

Multiple Result Set String Array Example:

This query will result in a three dimensional array of [2][n][n]i.e. 2 result sets with 1 result set i.e. [0][0][n] of 4905 rows of Strings holding the data and a second result set i.e. [1][0][n] of 10 rows.

The array has the following format: [RESULT SET][ROW][DATA].

String[][][] aStrings

// Fetch results into aStrings
Get SQLExecDirect of ghoSQLExecutor @SQL"
    SELECT * FROM OrderDetail
    SELECT TOP 10 NAME, City, Zip FROM Customer" to aStrings

// Test for errors
If (not(Err)) Begin
    // Process results here..
End


Multiple Result Set tDataSourceRow Array Example:

This query will result in a two dimensional array of [2][n] i.e. 2 result sets with 1 result set i.e. [0][n] of 4905 rows of tDataSourceRow holding the data and a second result set i.e. [1][n] of 10 rows.

The array has the following format: [RESULT SET][ROW].

tDataSourceRow[][] aDataSourceRows

// Fetch results into aDataSourceRows
Get SQLExecDirect of ghoSQLExecutor @SQL"
    SELECT * FROM OrderDetail
    SELECT top 10 NAME, City, Zip FROM Customer" to aDataSourceRows

// Test for errors
If (not(Err)) Begin
    //Initialize the grids i.e. fill, lets take two grids for example
    Send InitializeData of oCJGrid1 aDataSourceRows[0] // result set 1
    Send InitializeData of oCJGrid2 aDataSourceRows[1] // result set 2
End



Parameterized Queries


To use named parameters in a query, parameter name should have the $ sign as prefix and be enclosed in curly brackets i.e. ${param_name}. The named parameter query should always be prepared first. After the prepare, the parameters can bet set and the parameter information can be retrieved.

The following procedure and function are available for parameterized queries:
- Procedure SQLSetParameter String sParamName Variant Value
- Function SQLParameterInfo Returns tSQLParamInfo[]

The tSQLParamInfo struct is defined in cSQLExecutor.pkg:

Struct tSQLParamInfo
    String sName
    String sValue
End_Struct



SQLSetParameter Example

String[][] aStrings

// Prepare the query
Send SQLPrepare of ghoSQLExecutor @SQL"SELECT
    Name,  
    City,
    Zip FROM Customer
    WHERE City = @City"

// Test for errors
If (not(Err)) Begin
    // Set the parameter value
    Send SQLSetParameter of ghoSQLExecutor "City" "Miami"

    // Get the result set
    Get SQLExecute of ghoSQLExecutor to aStrings

    // Process results here..
End


SQLGetParameterInfo Example

tParamInfo[] aParamsInfo

// Prepare the query
Send SQLPrepare of ghoSQLExecutor @SQL"SELECT
    Name,  
    City,
    Zip FROM Customer
    WHERE City = ${City}"

// Test for errors
If (not(Err)) Begin
    // Set the parameter value
    Send SQLSetParameter of ghoSQLExecutor "City" "Miami"

    // Get the parameters info
    Get SQLParameterInfo of ghoSQLExecutor to aParamsInfo

    // Process results here..
End

Querying Result Set Structure


SQLColumnInfo returns the column information for the result set into a array of tSQLColumnInfo structs. If you want to put the results into a grid the column information for example can be used to initialize your grid columns. Always call SQLColumnInfo after a SQLExecute or SQLExecDirect.

The tSQLColumnInfo struct is defined in cSQLExecutor.pkg:

Struct tSQLColumnInfo
    String  sName      // column name (returned)
    Integer iType      // SQL data type of column
    Integer iSize      // Data size of column in table
    Integer iDigits    // Number of digits after the decimal separator
    Boolean bNullable  // Whether column is nullable
End_Struct


SQLColumnInfo Example

This query will result in a aColumnsInfo array with 3 elements holding the information for the columns Name, City and Zip.

String[][] aResults
tSQLColumnInfo[] aSQLColumnsInfo

// Fetch results into aResults
Get SQLExecDirect of ghoSQLExecutor @SQL"SELECT
    Name,  
    City,
    Zip
    FROM Customer" to aResults

// Test for errors
If (not(Err)) Begin
    // Get the columns info
    Get SQLColumnInfo of ghoSQLExecutor to aSQLColumnsInfo

    // Process results here..
End