Connectivity Kits

Visual DataFlex applications can connect to other database formats by using a Connectivity Kit. There are several Connectivity Kits available from Data Access:

  • The SQL Server Connectivity Kit

  • The DB2 Connectivity Kit

  • The ODBC Connectivity Kit

  • The Pervasive.SQL Connectivity Kit

The Pervasive.SQL Connectivity Kit is based on the Btrieve API. All other Connectivity Kits are based on CLI/SQL.

This document describes all the Connectivity Kits. It describes how to convert data to one of the supported back ends. It also describes how to connect to data already present on one of the supported back ends. In addition, it provides information on how to adjust Visual DataFlex programs so that they take specific advantage of the connectivity options of Visual DataFlex.

Visual DataFlex

Data Access Corporation introduced DataFlex in 1981. It was the first fourth generation language (4GL) and DBMS available for Local Area Networks (LANs). In 1991, Data Access Corporation introduced DataFlex revision 3.0, the first commercially available object oriented 4GL and DBMS in the industry.

Today, DataFlex still comes with the closely integrated database but also includes an open database API to access industry leading databases like SQL Server, DB2, Oracle or Pervasive.SQL.

DataFlex offers a complete suite of products that let developers create real-world software solutions. It runs on DOS, LANs, Windows and all popular UNIX platforms. Visual DataFlex is available for Windows. The Visual DataFlex Web Application Server is available for Windows platforms using the Microsoft Internet Information Server.

DataFlex 3.1 and higher and Visual DataFlex are API enabled runtimes. All database access uses the same internal core functions in the “API” part of the runtime. Native DataFlex Embedded Database tables are accessed through a call to the API; the API then passes these requests to an internal DataFlex native driver. This driver is linked to the runtime.

The runtime also has the ability to load other database drivers dynamically. For example, the Connectivity Kit for SQL Server is loaded dynamically. This approach lets the basic DataFlex code remain the same even when the back-end data is within SQL Server. Installing a database and loading a driver into an existing DataFlex environment makes that environment capable of using the driver and accessing the back-end supported by that driver.

This flexible driver technique allows you to update drivers independent of the runtime, or vice versa.


SQL Server Connectivity Kit

The Microsoft® SQL Server™ Connectivity Kit is used to access SQL Server databases from Visual DataFlex programs or programs that use the Data Access Database API. SQL Server is a Relational Database Management System (RDBMS) from Microsoft. It runs on Windows platforms offering Client/Server functionality to database applications.

Many existing Visual DataFlex applications, without change, will be able to use SQL Server for data storage. Others require changes in order to perform well with SQL Server.

SQL Server

Microsoft SQL Server is a high-performance, Client/Server Relational Database Management System (RDBMS). It was designed to support high-volume transaction processing (i.e., online order entry, inventory, accounting, or manufacturing), as well as data warehousing and decision-support applications (i.e., sales analysis applications). SQL Server runs on Microsoft Windows Server-based networks and can be installed as a desktop database system on a Window Workstation.

A relational database can be viewed as a set of tables that can be manipulated in accordance with the relational model of data. It contains a set of objects used to store, manage, and access data. SQL is a standardized language for defining and manipulating data in a relational database.

In a database Client/Server environment, the following two processes communicate: the database client and the database server. The Client/Server architecture allows all data requests of a client to be executed by one or several servers. Thus, data manipulation is separated, carried out by the Client, and the server carries out data management/recording. This offers greater integrity and speed in the processing of information.

The Microsoft SQL Server Connectivity Kit uses the Call Level Interface (CLI) to connect DataFlex programs to SQL Server. CLI is an Application Programming Interface (API) in which functions are provided for applications to process dynamic SQL statements. CLI enables DataFlex to connect to SQL Server databases, issue SQL statements and return data and status information without being compiled against a specific database.

Visual DataFlex and SQL Server

The Data Access Database API expects database drivers to support a certain set of attributes for a table. These attributes may or may not be available in the supported back-end. If such an attribute is not available in the back-end it needs to be stored somewhere outside of the back-end database. The API uses so called “intermediate files” to store such information. The contents of an intermediate file are partly API defined and partly driver specific.

The SQL Server Connectivity Kit will use the SQL Server back-end for its attributes whenever possible. Some information can only be stored in the intermediate file because SQL Server does not support the attribute essential to DataFlex. The Microsoft SQL Server Connectivity Kit expects an intermediate file to be present for every table that is accessed through it.

A design goal of the SQL Server Connectivity Kit was that a DataFlex program should be able to switch the underlying database to SQL Server without the need to adjust that program.


DB2 Connectivity Kit

The DB2 Connectivity Kit is used to access DB2 Universal Database databases from DataFlex programs. DB2 is a relational database management system (RDBMS) from IBM. It runs on a variety of platforms offering client server functionality to database applications.

Many existing DataFlex applications, without change, will be able to use the DB2 Database Server for data storage. Others require changes in order to perform well with the DB2 Universal Database System.

DB2 Universal Database

DB2 is a multi user Relational Database Management System (RDBMS) that runs on a variety of operating systems. SQL is used to access data in a DB2 Universal Database. Client workstations communicate with a DB2 Universal Database server across a network

A relational database can be viewed as a set of tables that can be manipulated in accordance with the relational model of data. It contains a set of objects used to store, manage, and access data. SQL is a standardized language for defining and manipulating data in a relational database.

In a database Client/Server environment, the following two processes communicate: the database client and the database server. The Client/Server architecture allows all of the client’s data requisitions to be executed by one or several servers. Thus, data manipulation is separated, carried out by the Client, and data management/recording, carried out by the server, offering greater integrity, and speed in the processing of information.

The DB2 Connectivity Kit uses the DB2 Call Level Interface (CLI) to connect DataFlex programs to DB2. CLI is an Application Programming Interface (API) in which functions are provided to applications to process dynamic SQL statements. CLI enables DataFlex to connect to DB2 databases, issue SQL statements and get data and status information without being compiled against a specific database.

Visual DataFlex and DB2

The Data Access database API expects database drivers to support a certain set of attributes for a table. These attributes may or may not be available in the supported backend. If such an attribute is not available in the backend it needs to be stored somewhere outside of the backend database. The API uses intermediate files to store such information. The contents of an intermediate file are partly API defined and partly driver specific.

The DB2 driver will use the DB2 backend for its attributes whenever possible. The goal is to keep the intermediate file as small as possible. Some information can only be stored in the intermediate file because DB2 does not support an attribute that is essential to DataFlex. The DB2 driver expects an intermediate file to be present for every table that is accessed through it.

A design goal of the DB2 driver was that a DataFlex program should be able to switch the underlying database to DB2 without the need to adjust that program.


ODBC Connectivity Kit

The ODBC Connectivity Kit is used to access ODBC databases from DataFlex programs. ODBC (Open DataBase Connectivity) is an industry standard that allows programs to access multiple database types without the need to rewrite the code for the program or having to re-link the program. A variety of database management systems can be accessed through ODBC. These include enterprise database systems such as Oracle, Sybase, SQL Server, flat file systems like dBase, Paradox and even non-database systems like Excel and ASCII.

Many existing DataFlex applications, without change, will be able to use these non-DataFlex database systems. Some other DataFlex applications require changes in order to make them perform well with these database systems.

ODBC

ODBC or Open DataBase Connectivity defines a method of connecting to data sources that are open to as many applications and data sources as possible. To accomplish this, the application and the data source have agreed upon a common method to access the database. This agreement defines a complete set of API function calls and a complete SQL syntax set together forming ODBC.

The database side of this open connectivity is provided by drivers, contained in Dynamically Linked Libraries (DLLs). These drivers transform the ODBC API functions into functions supported by the particular data source being used. The ODBC SQL syntax is translated in a similar way into syntax accepted by the data source. The manufacturer of the database system usually produces these drivers, but there are many third party vendors as well.

The ODBC architecture consists of four major components. They are described as follows.

Data Source

A Data Source identifies the server and database therein that will be accessed. A Data Source defines the ODBC driver to use for the connection. Depending on the driver it also defines the location of the data, the server on which the data resides, the database in which the data resides and so forth.

Data Sources are created through the ODBC Administrator; the administrator can be started from the Administrative Tools option in the Windows Control Panel or from the Visual DataFlex Database Builder.

Driver

The driver is a DLL that sits between the driver manager and the data source. It processes ODBC function calls. It passes commands from the application to the data source, after possible translation. It also receives the result for the commands from the data source and passes it back to the application

Driver Manager

This DLL is generally provided by Microsoft as part the ODBC installation. It loads driver DLLs and directs function calls to them.

Application

A program that processes data.

Four components of ODBC architecture.

It is important to understand that ODBC is designed to expose database capabilities, not supplement them. Thus, application writers should not expect that ODBC would suddenly transform a simple database into a fully featured relational database engine. Nor are driver writers expected to implement functionality not found in the underlying database.

Visual DataFlex and ODBC

The Data Access Database API expects database drivers to support a certain set of attributes for a table. These attributes may or may not be available in the supported backend. If such an attribute is not available in the backend, it needs to be stored somewhere outside of the backend database. The API uses so called “intermediate files” to store such information. The contents of an intermediate file are partly API defined and partly driver specific.

The ODBC Connectivity Kit will use the backend for its attributes whenever possible. The goal is to keep the intermediate file as small as possible. Some information can only be stored in the intermediate file because ODBC does not support the attribute essential to DataFlex. The ODBC Connectivity Kit expects an intermediate file to be present for every table that is accessed through it.

A design goal of the ODBC client was that a DataFlex program should be able to switch the underlying database to ODBC without the need to adjust that program.


Pervasive.SQL Connectivity Kit

The Pervasive.SQL Connectivity Kit enables Visual DataFlex programs to store and retrieve data using Pervasive.SQL Database Engines. More technically, it enables DataFlex programs running on a DataFlex Database API-enabled runtime (e.g., Visual DataFlex or DataFlex Console Mode) to access data stored in a Pervasive.SQL database.

Pervasive.SQL is a Client/Server based database management system built around Pervasive Software's MicroKernel Database Engine.

In general, most existing DataFlex applications using the DataFlex Embedded Database will be able to use Pervasive.SQL for data storage, without changing the application. In some cases application changes may be necessary to achieve better performance.

The Connectivity Kit can be used to convert existing DataFlex data to the Pervasive.SQL format, and can also be used to access existing Pervasive.SQL data generated by other applications such as any of the popular accounting packages that use Pervasive.SQL as their database management system. In addition, the Connectivity Kit supports restructuring capabilities that enable Pervasive.SQL to be used as the database system in a DataFlex development environment.

Pervasive.SQL

Pervasive.SQL is a reliable, low-maintenance, high-performance; Client/Server based database management system (DBMS). Pervasive.SQL is built around the Micro Kernel Database Engine (MKDE), historically also know as the Btrieve engine.

The Pervasive.SQL engine consists of two database sub-engines:

  • MicroKernel Database Engine (MKDE) or transactional engine, which provides Btrieve and MicroKernel API support for Pervasive.SQL applications.

  • SQL Relational Database Engine (SRDE) or relational engine, which provides support for SQL-based applications.

The Pervasive.SQL Connectivity Kit uses the transactional interface to access the Pervasive.SQL data tables. The transactional (or Btrieve) interface provides the fastest way to access Pervasive.SQL data.

The Connectivity Kit creates and maintains tables in such a way that data created by the Connectivity Kit (through the transactional interface) can also be accessed by the relational interface. This makes it possible to access this data with any SQL (or ODBC) oriented application. The Connectivity Kit is also capable of connecting to any data that is created by external (SQL based) applications.

Pervasive.SQL is a Client/Server database management system. In a Client/Server database environment, the following two processes communicate:

  • The database client

  • The database server

The Client/Server architecture allows all data requests of a client to be executed by one or several servers. Thus, data manipulation is carried out by the client, and the server carries out data management/recording. This offers greater integrity and speed in the processing of information.

Pervasive.SQL servers can run on Microsoft Windows servers, Netware or Linux. Pervasive.SQL clients are available for Microsoft Windows and for Linux. The Pervasive.SQL Connectivity Kit can only be used with Windows clients.

In Pervasive.SQL V8.5 new security features were added that enable access to secured databases through the transactional engine. The Connectivity Kit fully supports these new security features and is capable of accessing Pervasive.SQL secured databases.

Visual DataFlex and Pervasive.SQL

The Data Access Database API expects database drivers to support a certain set of attributes for a table. These attributes will describe the structure of a table. For example: which fields and indexes make up the table and how they are defined.

Attributes required by the API may or may not be available in the supported back-end. If an attribute is not available in the back-end it needs to be stored somewhere outside of the back-end database. The API uses so called “intermediate files” to store such information. The contents of an intermediate file are partly API defined and partly driver specific.

The Pervasive.SQL Connectivity Kit will use the Pervasive.SQL back-end for its attributes whenever possible. Some information can only be stored in the intermediate file because Pervasive.SQL does not support the attribute that is essential to DataFlex. In general, an intermediate file must be present for every table that is accessed through the Connectivity Kit. In some specific circumstances an intermediate file can be omitted.

Most attributes needed by the database API define structural information about the tables that are to be accessed by the Connectivity Kit. This structural information about files, fields and indexes is stored in the Pervasive.SQL metadata tables. These metadata tables have a DDF extension and are also referred to as the DDF tables.

Most Pervasive.SQL tools, including the SQL interface, use the DDF tables to provide the structure information about a Pervasive.SQL table. The Pervasive.SQL Connectivity Kit is fully based on these DDF tables.

There are three DDF tables: FILE.DDF, FIELD.DDF, and INDEX.DDF. These tables are just data tables like any other Pervasive.SQL table. Their format has been predefined so that any tool can use these tables to read and write information about a Pervasive.SQL table to it.

  • FILE.DDF contains information about Pervasive.SQL tables at the table level and has one record for every table. It describes the table’s name, location, and optionally extra flags.

  • FIELD.DDF contains information about the tables’ fields. Every field needs to be defined in this table before it can be accessed by one of the tools. The information stored about a field includes the table it belongs to, the offset the field starts in the record, its length, the number of decimals (if it’s a number) and extra flags.

  • INDEX.DDF contains information about the defined indexes for the tables. There is one record per index segment. Each segment describes to which table the segment belongs, its index number, its segment number and extra flags specifying more information about the segment.

Pervasive.SQL Setup

Configuration of the Pervasive.SQL Server and Client components can be done from the Pervasive.SQL Control Center. Configuration settings can be changed in the ‘configuration’ branch in the tree view for every Pervasive.SQL engine.

The configuration parameters will be auto configured after initial installation and, in general, the Connectivity Kit will function with these initial settings. Most configuration parameters will re-configure themselves dynamically and don’t have to be changed after the initial installation. Some settings may need to be adjusted to get better performance.

Refer to the Pervasive.SQL documentation for further information on specific configuration settings.

Pervasive Client Cache

The Pervasive Client Cache was introduced in Pervasive.SQL V8.0. Earlier versions don’t have a client cache. Client caching is by default turned on.

It is recommended to switch off the client cache when using the Pervasive.SQL Connectivity Kit!

When using the client cache, updates of a record from one workstation may not immediately be visible on other workstations. There can be a considerable delay (up to 5 seconds) before a change is noted. This delay can cause data corruption.

When not updating the data, you may consider leaving the client cache on. For example, when running heavy reporting programs. This may increase performance significantly.

In Pervasive.SQL (earlier than V8.5), the client cache can be turned off with a setting of the client configuration.

In the Control Center select:

  • Configuration

  • Client

  • Performance tuning

  • Use Cache Engine

Note: You must turn the client cache off on all workstations!

In Pervasive.SQL V8.5 or later the client cache can be turned off with a setting at the server. In the Control Center select:

  • Configuration

  • Server

  • Access

  • Allow Cache Engine Connections

When using this server setting, you don’t have to switch off the client cache at the workstations.


Converting Data

To convert data to one of the supported back ends use Database Builder. You can convert from any supported back end to any other supported back end; you can convert Microsoft Access data to SQL Server for example.

Restrictions

In order to be able to convert data from one back end to another, the source data must comply with the rules and specifications of the target platform. If the source data does not follow the target database rules, it is impossible to convert the data. If such a case presents itself the only option is to adjust the source table definition and/or contents so it does comply with the target database rules. After adjusting the source table, the table can be converted. Adjusting a table’s definition will require adjusting programs that use the table.

Table Type

If the source table already is a standard table, it will be converted to a standard table.

The conversion wizard allows you to convert recnum tables to both standard and recnum tables. If the program that is using the source database uses the recnum programming style, the tables should be converted to recnum tables. If the program uses the RowId programming style, converting to standard tables is recommended.

When converting to a recnum table a record identity column will automatically be inserted in front of the “normal” columns. The record identity column will be called “recnum” and is automatically hidden. The “recnum” column will have the identity behavior for the SQL Server and DB2 Connectivity Kit, for the ODBC Connectivity Kit this depends on the settings in the database configuration file.

Null & Default Values

The CLI-SQL Connectivity Kits will use a configuration file to determine the “nullability” and default value of columns created in the conversion process. If no configuration file is found, the default settings will be used. You can specify a target setting per DataFlex type. For example, you can define that Numeric fields should be converted not to accept null values and use a default value of 0. See NULL Values and Defaults for more information.

If more control over the target settings is desired, convert the definition only and then adjust the “nullability” and default values to your specifications. After that, copy the data from the original table to the new converted table. This way a table that has column specific defaults can be created. The table definition can be adjusted through Database Builder or the SQL Server utilities.

We have found that null values can degrade finding performance considerably. It is recommended not to allow null values in indexed columns.

Table Character Format

DataFlex data is stored in OEM format. Non-DataFlex back ends may expect the data to be stored in ANSI format. When defining the conversion options you can define the table character format to be used in the converted table. For more information on this subject, see Character Formats (OEM or ANSI).

See Also

Data Conversion Wizards

Converting Data to SQL Server

Converting Data to ODBC

Converting Data to DB2


Converting Data to SQL Server

Before data can be converted to SQL Server, the SQL Server Connectivity Kit must be loaded. If you have setup the SQL Server CK as the main Connectivity Kit for the workspace, it will automatically be loaded when Database Builder opens the workspace. You can load Connectivity Kits using the Configure Drivers option in the Tools menu.

When the SQL Server Connectivity Kit is loaded, the Database menu of Database Builder will show SQL Server specific options. In order to convert, choose the “Convert to MS SQL Server…” option.

Restrictions

MS SQL has a number of rules and specifications that are different from DataFlex. In general, they are less restrictive but not in some cases. The DataFlex specifications can be found in the DataFlex documentation, the Microsoft SQL Server specifications can be found in the SQL Server documentation.

One restriction that you should be aware of is the maximum row size (record length). The row size in SQL Server is limited to 8060 bytes. The actual data for text type and image type columns is not included in this maximum. Information about the location of that data takes up 16 bytes per text or image column in the row size.

If a Visual DataFlex table to be converted results in a table that does not comply with SQL Server’s rules and restrictions, the table cannot be converted. You should adjust the definition of the table before you can convert it. This means you also need to adjust all Visual DataFlex programs using this table.

Dump & Load

SQL server includes a bulk copy utility called BCP. BCP can be used to transfer large amounts of data to a SQL Server database in a fast way. Bulk copy is much faster than any conventional way of moving data to SQL Server. The conversion will automatically use BCP by calling the BCP API directly.

Older version of the SQL Server Connectivity Kit offered the possibility to create a Dump file and load script during conversion. Version 4 of the SQL Server Connectivity Kit makes this superfluous.

If you are using Database Builder's Dump & Load option to dump and load data from SQL Server tables, you will have to manually call BCP to load the data from the .ASC and .FMT files created. See Dump & Load for SQL Server for more information.

See Also

Converting Data

Using Data Conversion Wizards


Converting Data to DB2

Before data can be converted to DB2, the DB2 Connectivity Kit must be loaded. If you have setup the DB2 CK as the main Connectivity Kit for the workspace, it will automatically be loaded when Database Builder opens the workspace. You can load Connectivity Kits using the Configure Drivers option in the Tools menu.

When the DB2 Connectivity Kit is loaded, the Database menu of Database Builder will show DB2 specific options. In order to convert, choose the “Convert to DB2…” option.

Restrictions

DB2 has a number of rules and specifications that are different from DataFlex. In general, they are less restrictive but not in some cases. The DataFlex specifications can be found in the DataFlex documentation, the DB2 specifications can be found in the DB2 documentation.

One restriction that you should be aware of is the maximum row size (record length). The maximum row size in DB2 depends on the page size defined for the database. Page size can be 4K, 8K, 16K and 32K. The maximum row size is: 4005 byes for 4K page size, 8101 bytes for 8K page size, 16293 bytes for 16K page size and 32677 bytes for 32 K page size. The actual data for BLOB, CLOB, LONG VARCHAR, DBCLOB and VARGRAPHIC type columns is not included in this maximum. Information about the location of that data takes up some space in the row.

If a DataFlex table to be converted results in a table that does not comply with this rule, the DataFlex table cannot be converted. You must make sure the database uses a page size that allows the records to be converted or you should adjust the definition of the DataFlex table before you can convert it. This means you also need to adjust all DataFlex programs using this table.

See Also

Converting Data

Using Data Conversion Wizards


Converting Data to ODBC

Before data can be converted to ODBC, the ODBC Connectivity Kit must be loaded. If you have setup the ODBC CK as the main Connectivity Kit for the workspace, it will automatically be loaded when Database Builder opens the workspace. You can load Connectivity Kits using the Configure Drivers option in the Tools menu.

When the ODBC Connectivity Kit is loaded, the Database menu of Database Builder will show ODBC specific options. In order to convert, choose the “Convert to ODBC…” option.

Restrictions

Using the ODBC Connectivity Kit, you can connect to a variety of database systems. These systems all have their own rules on what constructions are legal and which data can be put into which column. Some database systems are more restrictive than DataFlex on the columns that can be placed in an index; others do not allow indexed columns to have an offset greater than the defined page size, and so forth. If a table contains a construction that is illegal in the target platform, the conversion will not succeed.

There is no way to determine up-front through ODBC if a construction is legal in the target database system. Knowledge about the target database system can avoid a lot of frustration in this area and save a lot of time. If an illegal construction is present, the only solution is to change the data definition so that it is acceptable by the target database system. Usually, when the data definition changes, the programs need to be adjusted too.

Next to illegal constructions, it is possible that certain columns have values that cannot be accepted by the target database. Many database systems do not accept two (2) digit year dates for example. If you have such dates in your original DataFlex files, the data needs to be adjusted before it can be converted.

Create an ODBC Data Source

Before you can convert anything to ODBC, you need to create an ODBC data source for your target database system. The data source must be created with the ODBC administrator program. Refer to the documentation of the driver you are using for specific details on how to setup a data source.

There are two types of Data Sources, machine- and file Data Sources. Both types contain similar information, they differ in the way the information is stored. Because of these differences, they are used in a somewhat different manner.

Machine Data Sources are stored on the client system. Associated with the Data Source is all the information the ODBC Manager and database driver need to connect to the specified database. There are two Data Source subtypes, User- and System Data Sources. One specific user of the machine can use a User Data Source; all users that use the machine where the Data Source is defined can use a System Data Source.

File Data Sources are stored in a file with extension .dsn (in ASCII format). The file Data Source stores all the information the ODBC Manager and database driver need to connect to the specified database. The file can be manipulated like any other text file.

See Also

ODBC Data Sources

Converting Data

Using Data Conversion Wizards


Using Data Conversion Wizards

Database Builder uses wizards to setup the data conversion process. Most pages in the wizards are the same, except where the target database information is entered. This section will describe the conversion logic for every CLI/SQL based Connectivity Kit using the SQL Server Conversion wizard as example.

Welcome

Every wizard starts with a welcome page.

Select Source Tables

The first step in a conversion process is to select the source tables to convert. On the select source tables page you can also indicate of the original tables must be deleted after the conversion process completes.

Analyze Source Tables

The source tables to convert are analyzed on this page. The process checks if the tables can be opened, what table type they have (standard or recnum table), through which Connectivity Kit they are currently accessed and so forth.

Define Recnum Table Conversion

If the source tables contain one or more recnum tables, the next step is to define how the recnum tables must be converted. The page allows you to indicate if recnum tables must be converted to standard tables.

If recnum tables are not converted to standard tables, move on to the next page. You should not convert to standard tables if the programs that use the data are using the RECNUM programming style.

If recnum tables are converted to standard tables you should check the checkbox. This makes the grid available for editing. In the grid you can define what index must be used as primary index when the table is a standard table. The grid will be filled with a proposed index (the first smallest unique index of the table). If it proposes RECNUM this indicates this table does not have an index that can be used as primary index. Such a table will be converted to a recnum table.

Every table accessed by a CLI Connectivity Kit should have at least one unique index. System tables are an exception to this rule. Starting at version 4.1 of the CLI Connectivity Kit it is possible to use system tables that do not have an index at all. A system table is supposed to have one record and one record only. If the record in a system table with no index is updated, the Connectivity Kit will update all records (which should be this one record)_in the table, the same is true when deleting the record in the system table. When converting a system table, and using a 4.1 CLI Connectivity Kit, no index will be created.

Define Conversion Options

The Define conversion options page is Connectivity Kit specific. On this page you define the target options for the conversion.

For every Connectivity Kit the default connection settings will be used when the page is activated.

SQL Server Conversion Options

On the SQL Server Define conversion options page you define the server and database to convert the data to. This database must already exist on the target SQL Server database server. You can enter login information on the page either as a user name and password or by checking the NT Authentication checkbox. If you want to specify an owner of the table that will be converted you can also do that here, not specifying an owner will result in the default owner being used.

Uncheck the “Store data in ANSI format” checkbox if you want to store the data in OEM format. Be aware that most tools that are able to connect to SQL Server data (Crystal Reports e.g.) expect the data to be in ANSI format.

Check the “Convert definition only” checkbox if you do not want to copy the data in the source table to the target tables.

DB2 Conversion Options

On the DB2 Define conversion options page you define the database to convert the data to. This database must already exist. You can enter login information on the page as a user name and password. If you want to specify a schema of the table that will be converted you can also do that here, not specifying a schema will result in the user name being used.

Table spaces allow you to assign a physical location to logical objects (tables). They can be used to improve performance or to increase the page size, thus increasing the maximum size of a record that can be stored in the table space. You can specify what table space must be used to store table, index or long data. The index and long data table space will only be set when the table tables pace is also set.

Uncheck the “Store data in ANSI format” checkbox if you want to store the data in OEM format. Be aware that most tools that are able to connect to SQL Server data (Crystal Reports e.g.) expect the data to be in ANSI format.

Check the “Convert definition only” checkbox if you do not want to copy the data in the source table to the target tables.

ODBC Conversion Options

On the ODBC Define conversion options page you define the data source to convert the data to. This data source must already exist. You can select the type of data sources that will be displayed in the data source combo list by checking the “Show user data sources” and/or “Show system data sources” checkboxes. You can select a File Data Source by clicking the “File DSN” button.

If the database requires this you can enter login information on the page as a user name and password. If the database supports schemas you can specify a schema of the table that will be converted.

Uncheck the “Store data in ANSI format” checkbox if you want to store the data in OEM format. Be aware that most tools that are able to connect to SQL Server data (Crystal Reports e.g.) expect the data to be in ANSI format.

Check the “Convert definition only” checkbox if you do not want to copy the data in the source table to the target tables.

Conversion Summary

The Conversion summary page displays a summary of the conversion process that is about to begin. Next to showing the connection parameters this page will also check if a connection can be established. If the connection cannot be established the next button will be unavailable. The page will show the status of the selected source tables. If there are no tables to convert the next button will be unavailable.

Conversion Progress

The conversion progress page will show the overall and current action progress in two progress bars.

Wizard Completion

The Wizard completion page shows the end result of the conversion process. The result is summarized on this page. If you want more detailed information the “Show log file” button can be used to open the log file created by the conversion process.

See Also

Converting Data


Dump & Load for SQL Server

This is the second option displayed in the “Database” menu after the driver has been loaded.

Select this option if you already have an empty table in SQL Server and only need to move the data that is still in a DataFlex file. This option will dump the data from a DataFlex file and/or generate the script necessary to load that data into an already existing SQL Server table.

From the Dump & Load, set options dialogue you can setup the process. In the fields enter:

  1. The server name. If the server is running on the same computer, you can use “(local)” as the server name. Otherwise, specify the computer name where the database server resides.

  2. The user ID. If you select Use Windows NT authentication, this option is not available. See Chapter 9 - SQL Server Specific Commands and Techniques for more information on keeping user id’s and passwords outside the intermediate file.

  3. The password of the user. If you select Use Windows NT authentication, this option is not available. See Chapter 9 - SQL Server Specific Commands and Techniques for more information on keeping user id’s and passwords outside the intermediate file.

  4. The name of the database where the SQL Server tables must be placed.

  5. The schema is the owner name to use within the database where the tables must be placed.

  6. Check the Use “Windows NT authentication” checkbox if you want to use your Windows NT login information to login to SQL Server. You need to be running at least Windows NT on the client for this to work. Refer to the SQL Server documentation for more information about NT Authentication. See Chapter 9 - SQL Server Specific Commands and Techniques for more information on keeping user id’s and passwords outside the intermediate file.

  7. Select the Record Identity (RID) Method to be used by the tables. The record identity method defines the way record identities are handled. The default is to use “Identity Column” method; we recommend using this method. The other two options “None” and “External” are for advanced use.

  8. Check the “Create Load Script” checkbox if you want to generate the script that uses the bulk copy command to copy the data to an SQL Server table. See the Dump & Load section in the beginning of the chapter for more information.

  9. Check the “Create Dump File” checkbox if you want to generate the .ASC and .FMT files to hold data to be loaded to an existing SQL Server table. See the Dump & Load section in the beginning of the chapter for more information.

  10. Click the OK button to start generating the selected files.


Dump & Load for DB2

This is the second option displayed in the “Database” menu after the driver has been loaded.

Select this option if you already have an empty table in DB2 and only need to move the data that is still in a DataFlex file. This option will dump the data from a DataFlex file and/or generate the script necessary to load that data into an already existing DB2 table.

From the Dump & Load, set options dialogue you can setup the process. In the fields enter:

  1. The data source name. The DB2 database name.

  2. The user ID. See Chapter 9 – DB2 Specific Commands and Techniques for more information on keeping user id’s and passwords outside the intermediate file.

  3. The password of the user. If you enter a password you must also enter user identification. It is not recommended to supply this information here. If you do not supply the password during conversion, you will be prompted for the password every time the table(s) you convert is (are) opened. See Chapter 9 – DB2 Specific Commands and Techniques for more information on keeping user id’s and passwords outside the intermediate file.

  4. The schema name within the database where the tables must be placed.

  5. Select the Record Identity (RID) Method to be used by the tables. The record identity method defines the way record identities are handled. The default is to use “Identity Column” method; we recommend using this method. The other options “None”, “Dispenser table” and “External” are for advanced use.

  6. Check the “Create Load Script” checkbox if you want to generate the script that uses the bulk copy command to copy the data to a DB2 table. See the Dump & Load section in the beginning of the chapter for more information.

  7. Check the “Create Dump File” checkbox if you want to generate the .ASC file to hold data to be loaded to an existing DB2 table. See the Dump & Load section in the beginning of the chapter for more information.

  8. Uncheck “DB2 version 8 or higher” if you are not using DB2 version 8 or higher.

  9. Click the OK button to start generating the selected files.


Converting Data to Pervasive.SQL

Introduction

This chapter will guide you through the steps to take if you are using DataFlex embedded database and want to start using Pervasive.SQL, i.e. you need to convert your tables from DataFlex to Pervasive.SQL.

Pervasive.SQL has a number of rules and specifications that are different from DataFlex. It is important that you read and understand the issues in this chapter before you start converting data to Pervasive.SQL.

Setting up Pervasive.SQL Databases

The Connectivity Kit can be configured to operate in database mode or in non-database mode. This is determined by the DATABASE_MODE setting in the Connectivity Kit configuration file DFBTRDRV.INT. Depending on the chosen mode, the way the physical Pervasive.SQL tables are located will be different. This means that the setup in Pervasive Control Center and the conversion process will also be different.

In non-database mode the Connectivity Kit will locate Pervasive.SQL tables by specifying pathnames and/or search paths to the physical data files. It is not necessary to set up databases in Pervasive Control Center.

In database mode the Connectivity Kit will locate Pervasive.SQL tables by specifying a Pervasive.SQL database name. This database must be defined in the Control Center and will determine the location of the physical data files.

When using database mode it is possible to access Pervasive.SQL secured databases. Database mode is only supported on Pervasive.SQL version V8.5 or later.

Further information on database access mode and Pervasive.SQL secured databases can be found in the chapter: Database Mode and Security.

Before you can convert to Pervasive.SQL, you must have the metadata files FILE.DDF, FIELD.DDF and INDEX.DDF available to the Connectivity Kit. New empty DDFs will be created if you create a new database in Pervasive Control Center.

The Connectivity Kit installation program will also place a set of empty DDFs in your (Visual) DataFlex usr\new folder. You can copy these if you need a set with empty DDFs.

Before converting to Pervasive.SQL the Connectivity Kit must know where the DDFs are located. Also, the location where the Pervasive data files (BTR files) are to be created should be known.

When running in database mode the location will be specified by the database name. The location needs to be specified when setting up the database in Control Center.

When running in non-database mode the Connectivity Kit will use the data path of the workspace (Visual DataFlex) or the DFPATH (DataFlex Console Mode) to determine the location of the BTR and DDF files.

Limitations

The Pervasive.SQL Connectivity Kit also has certain limitations that do not exist when using the embedded DataFlex database.

Aggregate Number of Index Segments

DataFlex supports up to 16 indexes for a table, which may all have a maximum of 16 index segments. This is an aggregate of 256 index segments. The number of segments a Pervasive.SQL table can support depends on the page size of the Pervasive.SQL table. The maximum number of index segments for the maximum page size (4096) is 119 index segments. If you want to convert a DataFlex database table to Pervasive.SQL that uses more than 119 index segments, you’ll have to change your table.

Note that when you convert a DataFlex table to Pervasive.SQL with recnum support, this will consume one index segment.

Placement of Index Segments in Large Records

Pervasive.SQL has a limitation that prohibits you from having information in an index that is located beyond the page size of a Pervasive.SQL table. The Pervasive.SQL Connectivity Kit uses the maximum page size for Pervasive.SQL, (4096 bytes). This means that the Pervasive.SQL Connectivity Kit cannot convert this table if you have a field beyond this point that provides a segment of an index. This does not mean that the size of a record in Pervasive.SQL is limited to this size; all it means is that these fields cannot be part of an index.

Note that the limit of the page size might be a little less than 4096 because Pervasive.SQL uses some bytes to store internal information. The number of bytes it takes depends on the number of indexes defined for the table. It will take at least 8 bytes per index.

Check whether the Pervasive.SQL Connectivity Kit has been loaded

Before we can use the Connectivity Kit, we will have to make sure it has been loaded. You can check this by reading the menu options from the Database menu of Database Builder. If the Connectivity Kit has been loaded, you will see a menu item Convert to Pervasive.SQL….

Loading the Connectivity Kit

If the Connectivity Kit has not been loaded, you can load it now or you can modify the DFINI.CFG file and instruct it to load the Connectivity Kit every time we start up DataFlex. When you want to load it every time DataFlex is being started, add a line to your DFINI.CFG file that reads:

4096=DFBTRDRV

This will instruct DataFlex to load the Connectivity Kit whenever DataFlex is being started. Note that you can have more than one 4096 entry in your DFINI.CFG file.

If you want to load the Connectivity Kit now, you can select the Load database driver item from the same Database menu.

You will be prompted to select one of the drivers that have been installed in your Bin directory. Select the DFBTRDRV.DLL file. When this driver does not appear in your list, you’ll need to reinstall the driver.

Converting Tables

After the Connectivity Kit has been loaded, the menu option ‘Convert to Pervasive.SQL…” is available in your ‘Database’ menu.

After selecting this menu item, you’ll get a list of the tables available in your filelist. Select the tables you want to convert by checking the checkboxes. When you are done selecting tables, press the Convert button to go to the Convert to Pervasive.SQL options panel.

Depending if the Connectivity Kit is configured to operate in database mode or non-database mode (DATABASE_MODE setting in DFBTRDRV.INT), different information must be entered on the conversion panel.

If the Connectivity Kit is configured to operate in database mode, the following panel will appear:

If the Connectivity Kit is configured to operate in non-database mode, the following panel will appear:

URI

When running in database mode, an URI must be specified to determine in which database the converted tables must be created. The Server, Database, User and Password input forms are used to compose the URI. More information on URIs can be found in the chapter: Database Mode and Security.

Delete Original after Conversion

When this option has been checked, the original table will be deleted after a successful conversion. If there are errors during the conversion, the table will not be deleted. It is recommended to make a backup copy of all data before starting a conversion.

NOTE: When this option has been selected, the .FD file will be deleted as well. The Connectivity Kit will automatically create a new .FD file when this happens.

Recnum Support

This option controls whether the table will be converted with original recnum support. Please read the chapter Recnum Support about how this option may influence the conversion and the DataFlex programs.

Owner Names

This is the place where an owner can be set for all tables to be converted. When an owner has been set for a table, the table can be protected by either encrypting its data or making the table read-only for applications that do not pass the ID of the owner with the open attempt.

Note that the owner name should be treated like a password. It is independent from the logged-in user name. Refer to the Pervasive.SQL documentation for more information about owner names.

Read-Only Access

When this is checked, Pervasive.SQL will allow applications that do not pass the right owner to open the table for read-only access. When this option is unchecked, it will only allow applications that pass the right owner to open the table. An application that passes the right owner always has full access to the table.

This option is only available when an owner has been set.

Encrypt Data

When this is checked, the data in the table will be encrypted using the specified owner, so the data won’t be readable by applications that just read in the table’s raw data like a text editor.

This option is only available when an owner has been set.

Conversion Process Notes:

  • The flexerrs.dat table and dferrxxx.dat tables cannot be converted to Pervasive.SQL The DataFlex runtime accesses these tables directly without going through a driver.

  • When your DataFlex database tables are compressed, the Pervasive.SQL tables will also be compressed. Note that Pervasive.SQL, unlike DataFlex, only has one type of compression, which can be switched on or off.

  • Note that when you look at the indexes using the Pervasive.SQL tools, indexes may be numbered one less than the DataFlex index number. This will happen when the table has been converted without recnum support. When converted with Recnum support, the index numbers will match the DataFlex index numbers, because the new RECID field is using Index 0.

  • When alias tables are being used (two or more entries in the filelist have the same root name), Database Builder will only convert the first physical table it runs into. Any other entries using the same root name (the aliases) will only have the INT extension added to the root name.

See Also

Pervasive.SQL Conversion Schema


Pervasive.SQL Conversion Schema

This topic contains information about how the Pervasive.SQL Connectivity Kit converts existing data to Pervasive.SQL and which decisions it makes when creating or restructuring Pervasive.SQL tables through this Connectivity Kit.

DataFlex-to-Pervasive.SQL Conversion

When the Connectivity Kit converts a field, it selects the Pervasive.SQL field type that comes closest to the DataFlex field type. Pervasive.SQL only needs to know the field type of a piece of data when it is being used in an index so that it knows how to sort the index. Pervasive.SQL does not care about the type of the information being put into the field itself.

Other applications using the DDF tables maintained by the Connectivity Kit do care about a field’s format and contents.

The conversion function of the Connectivity Kit uses the following table to convert DataFlex field types to Pervasive.SQL field types.

DataFlex Field Type | Pervasive.SQL Field Type
ASCII | STRING
NUMERIC | DECIMAL
DATE | DATE
OVERLAP | STRING
TEXT | LONGVARCHAR
BINARY | LONGVARBINARY

ASCII Fields

A field of type ASCII in DataFlex will be converted to Pervasive.SQL’s STRING type. This type works exactly the way the DataFlex ASCII field type works.

NUMERIC or BCD Fields

A Numeric field in DataFlex will be converted to the Pervasive.SQL type DECIMAL. This is a COMP-3-compliant format. Fields in COMP-3 format take 1 nibble to store the sign. Therefore, the size of the field after it has been converted is somewhat different when compared to DataFlex. For example, when in DataFlex a field size has been set to 2, it will take 1 byte to store it. When this field is converted to Pervasive.SQL, it needs 1 nibble for the sign and 2 nibbles to store the digits. In Pervasive.SQL, this field will have a length of 2 bytes. Because 2-byte COMP-3 fields have room for 3 digits, it will report to the DataFlex API that the size is 3.

DATE fields

Date fields will be stored in Pervasive.SQL’s native DATE format, which takes 1 byte to store the day, 1 byte to store the month and 2 bytes to store the year.

Pervasive.SQL (applications) expects the dates to have 4-digit year values. When a field’s data is converted from DataFlex to Pervasive.SQL, it takes the value straight from the DataFlex field. If the value of the DataFlex date uses 2-digit years, it will also have 2-digit years in Pervasive.SQL. If it uses 4-digit years, it will have 4-digit years in Pervasive.SQL.

OVERLAP Fields

Overlap fields will be converted to the Pervasive.SQL STRING type. This means that in the DDF tables, where the fields are defined, there is more than one field occupying the same space in the record. There may be applications that cannot handle this kind of field. Currently we don’t know of such an application, but you should know that an Overlap field is not a commonly used field type in Pervasive.SQL.

When the Connectivity Kit encounters an Overlap field, it will try to detect at what position the overlap field starts and at what position it ends. Based on that information, it will try to create the right overlap for it.

Overlap fields that overlap a number of fields exactly, will also overlap those fields being converted to Pervasive.SQL. If the underlying fields acquired different sizes when converted to Pervasive.SQL, the Connectivity Kit will calculate the difference and modify the length of the overlap field automatically.

If an Overlap field does not start at the beginning of a field or end at the end of a field and the offending fields were ASCII fields in DataFlex, then the Connectivity Kit will automatically adjust the offset and/or offset of the overlap field.

If an Overlap field does not start at the beginning of a field or ends at the end of a field and the offending fields were not ASCII fields in DataFlex, then the Connectivity Kit will create the overlap to cover the complete field(s). You will get a warning that it has done this. After this, you can adjust the overlap yourself using the Visual DataFlex Database Builder.

TEXT Fields

Text fields will be converted to the Pervasive.SQL LONGVARCHAR type. LONGVARCHAR is a variable length field type. The amount of data stored is the actual length of the data. So if a text field with a maximum length of 1000 characters contains 10 characters, only 10 characters will be stored.

When a table has LONGVARCHAR type fields it will automatically have variable length records. The actual contents of the field will be stored in the variable part of every record. The fixed part will contain an 8 byte field that contains an offset (pointer) to the variable data and the length of the variable data.

There can be multiple text fields in a record/table.

NOTE

Earlier versions of the Connectivity Kit used different Pervasive.SQL types for text fields. Text fields that were the last field of the record would be converted to NOTE type, text fields that are not the last field of the record would be converted to ZSTRING type.

For backward compatibility reasons, these types can still be generated during conversion. Specify:

TEXT_TYPE NOTE

in DFBTRDRV.INT to use the NOTE/ZSTRING types.

Note that NOTE and ZSTRING types are no longer supported in Pervasive.SQL.

BINARY fields

Binary fields will be converted to the Pervasive.SQL LONGVARBINARY type. LONGVARBINARY is a variable length field type. The amount of data stored is the actual length of the data. So if a binary field with a maximum length of 1000 characters contains 10 characters, only 10 characters will be stored.

When a table has LONGVARBINARY type fields it will automatically have variable length records. The actual contents of the field will be stored in the variable part of every record. The fixed part will contain an 8 byte field that contains an offset (pointer) to the variable data and the length of the variable data.

There can be multiple binary fields in a record/table.

NOTE

Earlier versions of the Connectivity Kit used the Pervasive.SQL STRING type for binary fields.

For backward compatibility reasons, this types can still be generated during conversion. Specify:

TEXT_TYPE NOTE

in DFBTRDRV.INT to use the STRING type.

Pervasive.SQL-to-DataFlex Conversion

The Connectivity Kit supports reading, writing, and restructuring tables that have been created or came with other applications that use Pervasive.SQL. Pervasive.SQL supports more field types than DataFlex and therefore, we need to map the data from a certain Pervasive.SQL field type to a DataFlex field type.

The only field types currently not supported are BFLOAT and LVAR.

The following table lists the known Pervasive.SQL field types. For every Pervasive.SQL field type, the DataFlex field type is shown and the maximum physical length supported for that field. The length column shows the length as it will be reported back by the DF_FIELD_LENGTH attribute.

Pervasive.SQL type | DataFlex type | Physical Length | Length | Remark
STRING (1) | ASCII | X (1-255) | X |
INTEGER | NUMERIC | 1,2,4,8 | 3,5,10,14 | Error when too large
IEEE (float) | NUMERIC | 4,8 | 22 | Precision is 8
DATE | DATE | N/A | N/A |
TIME | NUMERIC | N/A | 8 |
DECIMAL | NUMERIC | x(1,10) | (x*2)-1 |
MONEY | NUMERIC | x(1,10) | (x*2)-1 |
LOGICAL | NUMERIC | 1 | 3 |
NUMERIC | NUMERIC | x (1-15) | X |
BFLOAT | NUMERIC | N/A | N/A |
LSTRING (1,2) | ASCII | x(1-256) | x-1 |
ZSTRING (1) | ASCII | x(1-256) | x-1 |
NOTE | TEXT | x(1- 32767) | X |
LVAR | N/A | N/A | N/A | Not supported
BINARY | NUMERIC | 1,2,4 | 3,5,10 |
AUTOINC | NUMERIC | 1,2,4 | 3,5,10 |
NUMERICSTS | NUMERIC | x(1-15) | X |
NUMERICSA | NUMERIC | x(2-15) | x-1 |
LONGVARCHAR | TEXT | 8 + x | X |
LONGVARBINARY | BINARY | 8 + x | X |
CURRENCY | NUMERIC | 8 | 14.8 |
TIMESTAMP | NUMERIC |  | 14.4 | Decimal contains milliseconds

(1) The size specified is the size officially supported by Pervasive.SQL. The Connectivity Kit, however, accepts larger sizes.

(2) Normally, the first byte of an LSTRING contains the length of the actual data. The Connectivity Kit also supports a format where the first two bytes contain the length of the actual format. It will do this when the physical length of the field is larger than 255.


Connecting to Existing Data

There are two ways to connect to existing data: using wizards and manually.

To connect to data using any of the SQL Connectivity Kits use Database Builder. You can connect to any SQL database by using a Connection Wizard. Connecting manually is optional.

You can only connect to a Pervasive.SQL table manually.


Using Data Connection Wizards

Database Builder uses wizards to setup the connect process to a CLI/SQL based back end. Most pages in the wizards are the same, except where the database information is entered. This section will describe the connect logic for every CLI/SQL based Connectivity Kit using the SQL Server Connect wizard as example.

Welcome

Every wizard starts with a welcome page.

Database Selection

The Database Selection page is Connectivity Kit specific. On this page you define the database to connect to.

For every Connectivity Kit the default connection settings will be used when the page is activated.

SQL Server Database Selection

On the SQL Server Database Selection page you define the server and database to connect to. You can enter login information on the page either as a user name and password or by checking the NT Authentication checkbox.

You can setup the connect granularity. Often you want to connect to all tables of a database but sometimes you will want to be able to select individual tables.

Check the “Data is in OEM format” checkbox if the data is stored in OEM format. Given the fact that most tools that are able to connect to SQL Server data use ANSI, most existing data will be in ANSI format.

DB2 Database Selection

On the DB2 Database Selection page you define the database to connect to. You can enter login information on the page as a user name and password.

ODBC Database Selection

On the ODBC Database Selection page you define the data source to connect to. You can select the type of data sources that will be displayed in the data source combo list by checking the “Show user data sources” and/or “Show system data sources” checkboxes. You can select a File Data Source by clicking the “File DSN” button.

If the database requires this you can enter login information on the page as a user name and password. If the database supports schemas you can specify a schema of the table that will be converted.

You can setup the connect granularity. Often you want to connect to all tables of a data source but sometimes you will want to be able to select individual tables.

Check the “Data is in OEM format” checkbox if the data is stored in OEM format. Given the fact that most Windows tools use ANSI, most existing data on the Windows platform will be in ANSI format.

Database Filter

If you selected the “Connect to an entire database” granularity on the Database Selection page, you will be presented with the Database Filter page. This page allows you to filter the tables to connect to, based on their type.

Table Selection

If you selected the “Select individual tables” granularity on the Database Selection page, you will be presented with the Table Selection page. This page allows you to select individual tables in a treeview. Tables are organized by their type.

Progress

On the progress page the progress of the connect process is displayed. The selected tables will be analyzed, filelist slots are claimed, an intermediate and fd file are generated and so forth.

Copy SQL Relationship

The copy SQL Relationship page shows the progress of copying relationships defined on the back end. Only tables selected for this connect process will be considered. If you already connected to a table in a previous run of the wizard and table you are currently connecting to have a relationship with this previously connected to table, that relationship will not be copied.

ODBC

Some back ends do not support getting relationship information. Obviously relationships for such back ends cannot be copied and need to be established manually after the connect wizard finishes.

Wizard Completion

The Wizard Completion page show a summary of the connect process.


Connecting Manually

The manual connection process for any Connectivity Kit consists of three steps:

  1. Creating an intermediate file.

  2. Adding a filelist entry.

  3. Generating a FD file.

Creating an Intermediate File

To manually connect to existing data, you first need to create an intermediate file.

For SQL Connectivity Kits this intermediate file should at least set the intermediate file keywords DRIVER_NAME and SERVER_NAME. Normally you would also set the DATABASE_NAME and possibly the SCHEMA_NAME keyword. The table to connect to must have at least one unique index defined.

For Pervasive.SQL an intermediate file is not required when running in non database mode. When running in database mode intermediate files are required to store the URI information of the database. If you want to connect to a table when using non database mode an intermediate file is required when you want to setup a relationship for the table.

The intermediate file for Pervasive.SQL should contain at least the DRIVER_NAME keyword. If using database mode it should also contain the URI keyword.

SQL Server

For example, if we want to connect to the table Department, owned by dbo in the database MyDB, on server MySrvr, using Windows NT authentication, we would create an intermediate file, called dept.int, with the following content:

DRIVER_NAME MSSQLDRV

SERVER_NAME SERVER=MySrvr;Trusted_Connection=yes;DATABASE=MyDB

DATABASE_NAME Department

SCHEMA_NAME dbo

ODBC

For example, if you want to connect to the table Department, in the data source Company, we would create an intermediate file, called dept.int, with the following content:

DRIVER_NAME ODBC_DRV

SERVER_NAME DSN=Company

DATABASE_NAME Department

DB2

For example, if we want to connect to the table Department in the schema CompSchema in the database Company, we would create an intermediate file, called dept.int, with the following content:

DRIVER_NAME DB2_DRV

SERVER_NAME DSN=Company

DATABASE_NAME Department

SCHEMA_NAME CompSchema

Pervasive.SQL

For example if we want to connect in database mode to the table Department in the database MyDB on server MyServer as user “ed” using password “secret”, we would create an intermediate file, called dept.int, with the following content:

DRIVER_NAME DFBTRDRV

URI btrv://ed@MyServer/MyDB?table=Department&pwd=secret

If you want to connect in non database mode to the table Department, we would create an intermediate file, called dept.int, with the following content:

DRIVER_NAME DFBTRDRV

DDF_NAME Department

Creating a Filelist Entry

The next step is to place a reference to the created intermediate file in the filelist.

  • Use Database Builder

  • Select the appropriate workspace

  • From the "Filelist" menu choose "New entry…"

For the new entry you should set the root name to the name of the intermediate file you just created (dept.int). The user and logical name can be set to your specifications. Typically, in the above example, they would be set to “Departments in the company” and “dept” respectively.

Generating an FD File

The last step is to generate a FD file for the new filelist entry. The DataFlex compiler uses FD files to import table definitions. Use Database Builder to generate the FD.


Understanding How Connectivity Works

All Connectivity Kits use the same basic principles. A Connectivity Kit is a dynamically loadable library (DLL) that can be loaded by the runtime. The DLL must implement functions the Visual DataFlex database API expects to be implemented by a Connectivity Kit. The functions implement basic database functionality like finding a single record; saving and deleting a single record; starting, committing or aborting a database transaction. Next to this a number of data definition manipulation functions must be implemented. Functions like create a new column, create a new index and so forth.

With the introduction of Visual DataFlex 11 the database API was updated to support an extended function list in a Connectivity Kit. The new functions add standard table support to the Connectivity Kit’s abilities. The update is created in such a manner that it is still possible to load an “old style” Connectivity Kit. When such a Connectivity Kit is loaded a compatibility layer handles the missing functions.

The new functions handle the new RowId database level functionality. Next to these new functions a provision has been made so that Connectivity Kit can support new levels of attributes. The current Connectivity Kits support attributes on table, column, index and index segment level. In the future it will be possible to add attributes on Connectivity Kit and database (connection) level. One Connectivity Kit level attribute has already been defined (DF_DRIVER_CONFORMANCE) that indicates if a driver supports the extended function list.

Version 4 of the SQL Connectivity Kits supports the extended function list. It is possible to use a version 4 Connectivity Kit with a pre-Visual DataFlex 11 runtime; the new functions will never be called. The Pervasive.SQL Connectivity Kit does not support the extended function list. The Btrieve API used by this Connectivity Kit always supports recnum natively it is not needed to create standard table support.

Next to the function list that is implemented all Data Access Connectivity Kits use shared functionality. All Connectivity Kits support structure caching, intermediate files, transactions and use a configuration file. All SQL Connectivity Kits support the use of ODBC Escape Sequences. There are a number of other Connectivity principles that should be discussed, principles like table types, error handling and programming techniques.


Structure Caching

When opening a table through the Connectivity Kit, information on the table definition will be assembled. The information will be obtained from the meta database. Since this involves a number of database find operations, it may take some time to get all this information. In general, table definitions are very static, especially in a deployed environment. For this reason, structure caching was implemented. Structure caching will dramatically speed up the opening of tables. It stores the table definition in a disk file (*.cch) and reads this disk file instead of getting the information from the meta database.

Storing information in two places is always dangerous. It is possible for the cache to get “out of sync” with the actual table definition. The structure cache mechanism was designed to prevent this from happening as much as possible.

Since environments and requirements vary between different installations, structure cache behavior can be setup through the Connectivity Kit configuration file.

What is Structure Caching

Structure caching will store all information (table, column and index) of a table in a cache file (*.cch) when the table is first opened through the Connectivity Kit. The next time the table is opened, this cache file will be used to get the structure information instead of using the meta database.

Location of Cache Files

By default, the structure cache files will be placed in the same directory as the intermediate file for the table. You can specify a cache path in the Connectivity Kit configuration file. If this path is defined, it must point to a valid directory. All cache files will be placed in that directory.

Cache paths can be used for easy maintenance or when using multiple Connectivity Kits. Other Connectivity Kits also support a structure cache mechanism. In a mixed environment it may be needed to give each Connectivity Kit its own cache directory.

Lifetime of Cache Files

Cache files can get “out of sync”. There are a number of reasons why this happens. Most of the time the Connectivity Kit will automatically detect the “out of syncness” and regenerate the cache file automatically. The reasons why a cache file will get “out of sync” are:

  • The intermediate file changes.

  • A restructure operation was done through the DataFlex API

  • The table definition changes not using the Connectivity Kit to make the definition change.

  • The Connectivity Kit uses a new cache format.

Most of the cases above will be handled automatically.

The cache mechanism will compare the timestamps of the cache file and the intermediate file. If the intermediate file is newer than the cache file, the cache file will be regenerated. You can switch off the timestamp check in the Connectivity Kit configuration file.

When a restructure operation is done, the cache file will be deleted. Upon the next open of the table, the cache file will be regenerated.

Every cache file contains a signature. This signature defines the format of the cache file. When a cache file is opened but the signature does not comply with the expected format, the cache file will be regenerated.

The only situation that is not automatically detected and handled is when table definition changes are made outside the Connectivity Kit. In that case the cache files of the changed tables should be deleted. When the tables are opened the next time, a new cache file will be generated.

It is always allowed to delete cache files, they will be regenerated automatically.


Intermediate Files

To be able to open tables and to access their data from a Visual DataFlex program, we need to know how the table is structured; which fields are defined and what their type and length are; what indexes are defined (consisting of which segments) and so forth.

We retrieve most of the structural information from the database (in the case of Pervasive.SQL, the metadatabase: the FILE.DDF, FIELD.DDF and INDEX.DDF tables) Not all of that information is available for all target database formats. For example, the concept of a Visual DataFlex system table (a table with 1 record that is automatically read when the table is opened) is unknown outside of the Embedded Database. So, the information that a certain table is a system table must be stored somewhere else.

The intermediate file is the location where this type of information is stored. The contents of an intermediate file can be divided into three sections.

  • A section that allows Visual DataFlex to determine which database driver to use

  • A section that contains information needed before a table can be opened

  • A section that contains information needed after a table has been opened

The general format of the intermediate file consists of lines of text separated by carriage return and line feed (CR/LF) characters. Each line may be up to 255 characters long and consists of a keyword and value pair or a comment.

Keywords may be upper, lower or mixed case. Comments are preceded by the semicolon (;) character. In line comments are not supported. White space, defined as blank spaces and tab characters, is not significant and may be used for legibility.

The specific meaning and usage of intermediate file keywords are entirely dependent upon the specific database driver with the exception of the DRIVER_NAME keyword.

In general, an intermediate file must be present for every table that is accessed through the Connectivity Kit. In some specific circumstances an intermediate file can be omitted.

Intermediate files are automatically created when converting data or when connecting to existing data using one of the connect wizards. When restructuring existing tables with Database Builder, intermediate files will be updated if necessary. It is also possible to create or edit intermediate files manually with a text editor.

See Also

Order of Keywords

Header

Column Keywords

Index Keywords

Table Keywords


Order of Keywords

Intermediate file keywords must be placed in the following order: header, columns and indexes. The upcoming paragraphs will discuss all supported intermediate file keywords, the value they can be set to and the associated attribute, if any.

The keywords will be presented in the following format:

<Keyword> (<Usage>)

Value <Possible values>

Associated attribute <Attribute_Name> (<Type>)

Where

  • <Keyword> The keyword to set in the intermediate file.

  • (<Usage>) “Required.” Since most keywords are optional, this is not mentioned in the keyword’s description. It is only mentioned if a keyword is required, all others are optional. Optional keywords can be omitted; required keywords must be set.

  • <Possible values> A list of values or a description of possible values for the keyword.

  • <Attribute_Name> The name of the attribute associated with the keyword.

  • (<Type>) The type of the associated attribute.

Associated Attributes

Some keywords have a so-called associated attribute. The behavior that is set up by such a keyword can also be obtained by using the attribute. Attributes can be set by the Set_Attribute command. Their value can be queried by the Get_Attribute command.

Setting up behavior through the intermediate file creates a global, persistent setting. Using the Set_Attribute command will result in a local setting, only valid until the next Set_Attribute command. It depends on your specific needs, which of the two ways should be used in a specific case.

The Get_RID_After_Create keyword, for example, has an associated attribute DF_FILE_GET_RID_AFTER_CREATE of type Boolean. There are two ways to switch the attribute on:

Get_RID_After_Create YES ; Intermediate file line

Set Attribute DF_FILE_GET_RID_AFTER_CREATE of ;

MyTable.File_number To True

Alternatively, you can use the following to switch the attribute off:

Get_RID_After_Create NO ; Intermediate file line

Set Attribute DF_FILE_GET_RID_AFTER_CREATE of ;

MyTable.File_number To False

See Also

Header

Column Keywords

Index Keywords

Table Keywords


Header Keywords

The keywords for the intermediate file header must be placed at the beginning of the intermediate file in the order they are discussed here. If an intermediate file does not have this information at the beginning of the file, the file and the associated table will fail to open.

The following keywords can be used in the header of the intermediate file:

  • Driver_Name (Required)

  • Server_Name (Required)

  • Database_Name

  • Schema_Name

  • URI

  • Recnum_Support

  • DDF_Name

  • Owner

  • DataFlex_For_Btrieve

See Also

Intermediate Files

Order of Keywords

Table Keywords

Column Keywords

Index Keywords


Driver_Name (Required)

The Driver_Name keyword is used by the Data Access API to determine the driver that must be used to open the table that is associated with the intermediate file.

Supported By

All Connectivity Kits

Value

Driver specific.

  • Microsoft SQL Server Connectivity Kit = MSSQLDRV

  • Pervasive.SQL Connectivity Kit = DFBTRDRV

  • IBM DB2 Connectivity Kit = DB2_DRV

  • ODBC Connectivity Kit = ODBC_DRV

Associated Attribute

DF_FILE_DRIVER (String)

Remarks

The driver will be loaded if necessary. Normally, this keyword has been parsed before the specific driver is called. The driver will then start parsing the rest of the intermediate file information. This keyword must be the first keyword in any intermediate file.

See Also

Header Keywords


Server_Name (Required)

The Server_Name keyword must be set to a connection string. The connection string identifies the database or DSN to connect to.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

Connection string

Associated Attribute

DF_FILE_LOGIN (String)

Remarks

The Server_Name keyword must be set to a connection string. The connection string identifies the database or DSN to connect to. The string can contain user information, including password, but that is not required. The string is made up of a number of Keyword=Value pairs separated by semicolons (;).

For information on keeping user information out of the intermediate file see Commands and Techniques.

SQL Server

Connection String Values

CONNECTION KEYWORD | DESCRIPTION OF THE VALUE
SERVER | Name of a server running SQL Server on the network. The value must be either the name of a server on the network, or the name of a SQL Server Client Network Utility advanced server entry. You can enter (local) as the server name on Windows NT to connect to SQL Server running on the same computer.
UID | A valid login account. UID need not be specified when using Windows NT authentication.
PWD | The password for the SQL Server login account specified in the UID parameter. PWD need not be specified if the login has a NULL password or when using Windows NT authentication.
Trusted_Connection | When YES , instructs the SQL Server driver to use Windows NT Authentication Mode for login validation. The UID and PWD keywords are optional. When NO, instructs the SQL Server driver to use Server user name and password for login validation. The UID and PWD keywords must be specified.
DATABASE | Name of the default SQL Server database for the connection. If Database is not specified, the default database defined for the login is used.
APP | The name of the application (optional). This name will be shown in SQL Server utilities like SQL Server Profiler. If you do not specify an application name it will be set to “DataFlex”.
<Configuration keyword> | Server specific defined keyword. For a list of configuration keywords and their description, see the manual for your database server.

SQL Server Example

If we want to connect to the table Department owned by dbo in the database Company on server TheCompanyServer using Windows NT authentication we would create an intermediate file, called dept.int, with the following content:

DRIVER_NAME MSSQLDRV

SERVER_NAME SERVER=TheCompanyServer;Trusted_Connection=yes;DATABASE=Company

DATABASE_NAME Department

SCHEMA_NAME dbo

DB2

Connection String Values

CONNECTION KEYWORD | DESCRIPTION OF THE VALUE
DSN | Name or alias name of a DB2 database.
UID | A valid DB2 authorization name.
PWD | The password corresponding to the authorization name.
<Configuration keyword> | DB2 CLI defined keyword. For a list of configuration keywords and their description see the DB2 manual.

DB2 Example

For example, if we want to connect to the table Department in the schema CompSchema in the database Company we would create an intermediate file, called dept.int, with the following content:

DRIVER_NAME DB2_DRV

SERVER_NAME DSN=Company

DATABASE_NAME Department

SCHEMA_NAME CompSchema

ODBC

Connection String Values

CONNECTION KEYWORD | DESCRIPTION OF THE VALUE
DSN | Name of the data source to connect to.
UID | A user id if needed by the data source.
PWD | The password corresponding to the user id name.
<Configuration keyword> | Back end specific defined keyword. For a list of configuration keywords and their description see your database’s manual.

ODBC Example

If we want to connect to the table Department, in the data source Company, we would create an intermediate file, called dept.int, with the following content:

DRIVER_NAME ODBC_DRV

SERVER_NAME DSN=Company

DATABASE_NAME Department

See Also

Header Keywords


Database_Name

The name of the table associated with the intermediate file.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

The name of the table associated with the intermediate file. If this keyword is not set, the intermediate file name (without the .int extension) will be used.

Associated Attribute

DF_FILE_TABLE_NAME (String)

Remarks

The Database_Name keyword was created and designed before actually connecting to SQL databases. This is why it has the “old” DataFlex meaning of table. In a future revision this may be adjusted to a more SQL oriented keyword.

See Also

Header Keywords


Schema_Name

The name of the schema the table belongs to.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

The name of the schema the table belongs to. A schema is a collection of names or objects. A schema can contain tables, views, and triggers. Schemas provide a logical classification of objects in the database.

If the keyword is not set, the user ID used to login to the data source is used as the schema name.

Associated Attribute

DF_FILE_OWNER (String)

Remarks

The Schema_Name keyword was created and designed with SQL92 in mind. SQL Server has a completely different approach to security and privileges and uses owners.

See Also

Header Keywords


URI

Table specification

Supported By

Pervasive.SQL Connectivity Kit

Value

An URI (Uniform Resource Indicator) is used to specify in what Pervasive.SQL server and database the table is located. It can also specify a username and password to login to the database.

The URI keyword can only be used if the Connectivity Kit is operating in database mode (The DATABASE_MODE keyword in DFBTRDRV.INT is on).

Database mode and URI’s can only be used on Pervasive.SQL V8.5 or later.

Associated Attribute

DF_FILE_LOGIN (String)

Remarks

Refer to the chapter on Database Mode and Security for more information about URI’s

See Also

Header Keywords


Recnum_Support

Is an extra record identity column added before the actual columns?

Supported By

Pervasive.SQL Connectivity Kit

Value

When set to a non-zero value, this indicates that the table is converted from DataFlex with recnum support. A table with recnum supports has the recnum values of the original DataFlex table preserved. Refer to the chapter on recnum support for further information.

Associated Attribute

None

Remarks

You will only need to convert with recnum support if the recnum values have some meaningful value. For example when the recnum value is used as the customer id number in a customer file. Also if you have defined relations from or to the recnum field, you must use recnum support. In general recnum support will only be necessary with applications that are derived from older DataFlex character mode applications.

See Also

Header Keywords


DDF_Name

The name of the table to open (when operating in non database mode).

Supported By

Pervasive.SQL Connectivity Kit

Value

DDF_NAME may be used to point to a record in FILE.DDF. The information in this record will be used to physically open the Pervasive.SQL table. If no name has been given, the root of the name of the INT file will be used.

Associated Attribute

None

Remarks

None

See Also

Header Keywords


Owner

The Pervasive.SQL owner name.

Supported By

Pervasive.SQL Connectivity Kit

Value

Use OWNER when the Pervasive.SQL table needs an owner name to be opened.

Associated Attribute

None

Remarks

Pervasive.SQL tables have a concept called the owner name of a table. The value of an owner name is not the name of the person who created the table or the person who owns it. You should think of owner names like passwords. People who know the password have unlimited access, while people who don’t, have not.

The owner name concept was originally intended to protect unauthorized access to Btrieve files. Pervasive.SQL also offers more advanced security features that can be combined with owner names. Refer to the Pervasive.SQL documentation and the chapter on Database Mode and Security for further information.

Instead of defining an attribute, the Pervasive.SQL Connectivity Kit defines commands that can be used to set or clear the owner name of a table. There is also a command top create an owner name list. See DFBTR_SET_OWNER, DFBTR_CLEAR_OWNER, DFBTR_ADD_OWNER and DFBTR_REMOVE_ALL_OWNERS.

See Also

Header Keywords


DataFlex_For_Btrieve

Indicates if the table was created using DataFlex for Btrieve.

Supported By

Pervasive.SQL Connectivity Kit

Value

When set to a non-zero value, this indicates that this table has been converted using “DataFlex for Btrieve”. Note that DataFlex for Btrieve is no longer a supported product.

Associated Attribute

None

Remarks

Refer to the chapter on Dataflex_For_Btrieve for more information.

See Also

Header Keywords


Table Keywords

The following keywords set attributes on table level. They must be set directly after the intermediate file header and before the column keywords (if any).

  • Dummy_Update_Column

  • Generate_Record_ID_Method

  • Get_RID_After_Create

  • Index_Tablespace

  • Long_Tablespace

  • Max_Rows_Fetched

  • Primary_Index

  • Recnum_Table

  • Refind_After_Save

  • System_File

  • Table_Character_Format

  • Table_Tablespace

  • Use_Dummy_Zero_Date

See Also

Intermediate Files

Order of Keywords

Header Keywords

Column Keywords

Index Keywords


Dummy_Update_Column

The column for which a "dummy update" is done when finding records inside a transaction for a back endthat supports SQLSetPos for locking.

Supported By

ODBC Connectivity Kit

Value

1 – number of columns in the table

Associated Attribute

DF_FILE_DUMMY_UPDATE_COLUMN

Remarks

Desktop databases usually do not support positioned updates. In these cases a different update mechanism, called SQLSetPos that allows for records to be locked, is used. If the back end does not support exclusive locks on records, the Connectivity Kit will perform a “dummy update” to lock the record. This mechanism will ensure that records are locked when they are found while in a transaction. Since most ODBC drivers do not support table locking, there is a difference between Visual DataFlex locking and ODBC locking.

The dummy update mechanism updates a record (without changing any field value) directly after it has been found. The record identity column is set to the value just got from the find. This happens in the find logic. If the record identity column is not "updatable" (it could be an auto-increment, for example), you can set up an alternative column by using the intermediate file keyword DUMMY_UPDATE_COLUMN. The Dummy_Update_Column keyword should be set to the number of the column you want to "dummy update". Column numbers start at 1.

At this moment there is no facility to determine how the back end in use supports locking. There are several ways this can be done depending on the back end in use. Possible behaviors are:

  • Positioned updates. If the back end supports positioned updates, locking records is supported, no dummy updates are required.

  • SQLSetPos + exclusive lock. Some back ends support the SQLSetPos logic with the possibility to lock a record exclusively. No dummy updates are required.

  • SQLSetPos + dummy update. If the back end does not support exclusive locks on records, a dummy update will be done directly after a record has been found while in a transaction. In this case, the DUMMY_UPDATE_COLUMN intermediate file setting is used to determine the column to use in the dummy update operation.

  • None. Some back ends are read-only and do not support locking at all.

See Transactions for more information on locking and transactions.

See Also

Table Keywords


Generate_Record_ID_Method

The Generate_Record_ID_Method setting indicates how the record identity column is filled.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

None, Identity_Column, External, Dispenser_Table

Associated Attribute

DF_FILE_GENERATE_RECORD_ID_METHOD (enum list)

Remarks

The Generate_Record_ID_Method setting indicates how the record identity column is filled. There are four possible values:

VALUE

MEANING

None

Record identifiers are not generated by the back-end. Record identity values must be filled by giving the columns an explicit value in the application

When a new record is created, the value in the record identifier column is passed to the back-end.

Identity_Column

The record identifier is filled by the back-end using the features the server provides for this (identity columns).

When a new record is created, the value in the record identifier column is not passed to the back-end.

This value is only applicable to the SQL Server and DB2 Connectivity Kits.

External

The record identifier is generated by the back-end but in some other way than using identity columns. For example: one could use triggers.

When a new record is created, the value in the record identifier column is not passed to the back-end.

Dispenser_Table

The record identifier value is dispensed from a table that keeps track of the next available record identity value. The dispenser logic is enforced using triggers when records are inserted.

When a new record is created, the value in the record identifier column is not passed to the back-end.

When a table is opened a check will be done to see if the triggers, the dispenser table and the record in the dispenser table for the table being opened exist. If one (or more) of these is missing, it will automatically be created.

This value is only applicable to the DB2 Connectivity Kit.

See Also

Table Keywords


Get_RID_After_Create

Should the value of the record identity column be fetched after creating a new record?

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

YES, NO

Associated Attribute

DF_FILE_GET_RID_AFTER_CREATE (Boolean)

Remarks

When this keyword is set to YES, after records are created in a table, the assigned record identity is moved to the record buffer used by DataFlex. Setting this keyword to NO will switch off moving the new identity to the record buffer. This eliminates a Client/Server communication round trip, thus speeding up performance when creating records.

For the SQL Server Connectivity Kit the way the record identity is moved to the buffer depends on the setting of the GENERATE_RECORD_ID_METHOD keyword. If that keyword is set to “Identity_Column” the Ident_Current function of SQL Server will be used (@@IDENTITY in pre SQL Server 2000 version).

For the DB2 Connectivity Kit the way the record identity is moved to the buffer depends on the setting of the GENERATE_RECORD_ID_METHOD keyword. If that keyword is set to “Identity_Column” the IDENTITY_VAL_LOCAL function of DB2 will be used. When the GENERATE_RECORD_ID_METHOD keyword is set to Dispenser_Table, the record identity value will be selected from the dispenser table.

For all SQL connectivity Kits the way the record identity is moved to the buffer when the GENERATE_RECORD_ID_METHOD keyword is set to “None” or “External” is the same, the maximum value of the record identity column is used.

Be aware that setting this keyword to NO can result in unwanted or erroneous behavior. Switching off the move behavior can speed up bulk creation of records. This keyword will rarely be used; normally you will only use this attribute from within the program logic where it will be used in massive record creations. In such cases, it will be switched off, and then the records are created after which the attribute is switched back ON.

See Also

Column Keywords

Index Keywords

Table Keywords


Index_Tablespace

The table space in which the indexes for the table are stored.

Supported By

DB2 Connectivity Kit

Value

The name of the tablespace to store index information.

Associated Attribute

DF_FILE_INDEX_TABLESPACE (String)

Remarks

Table spaces are used to distribute the storage of information associated with a table over multiple disks. See the DB2 documentation for more information on tablespaces. For a table one can store the index, long data and “normal” table data in different table spaces. The index tablespace will only be used if a table data tablespace has been defined.

See Also

Table Keywords


Long_Tablespace

The table space in which the long data for the table are stored.

Supported By

DB2 Connectivity Kit

Value

The name of the tablespace to store long data.

Associated Attribute

DF_FILE_LONG_TABLESPACE

Remarks

Table spaces are used to distribute the storage of information associated with a table over multiple disks. See the DB2 documentation for more information on tablespaces. For a table one can store the index, long data and “normal” table data in different table spaces. The long data tablespace will only be used if a table data tablespace has been defined.

See Also

Table Keywords


Primary_Index

The number of the index that defines the key or the record identity of the table.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

0.. Highest index number defined for the table

Associated Attributes

DF_FILE_PRIMARY_INDEX (Integer)

DF_FILE_RECORD_IDENTITY (Integer)

Remarks

The number of the primary index, for standard tables this will be the key of the table, for recnum tables the record identity.

Standard Table

In a standard table individual records are uniquely identified by one or more columns of any type. The Connectivity Kit is informed about these columns by specifying an index number with the primary_index intermediate file keyword. The index should contain the identifying columns.

Recnum Table

In a recnum table a record identity is required. This is a column in the table that uniquely identifies a row in the table. This column should be numeric and an index should be defined for it. For more information on record identity, see Record Identity.

Setting the keyword to 0 (zero) will make the first column the record identity column and it will be hidden – its column number will be 0 (zero). The index that contains the first column will also be hidden – its index number will be 0 (zero). Any non-zero value will not hide the record identity column.

If this keyword is not set, the Connectivity Kit will search for a column with the name DFRECNUM. If such a column exists, this column will be made the record identity and a logical index will be created, if necessary. This index will not be created on the server itself; it is merely a sort order to access the table by.

If no DFRECNUM column is present, the first index that contains one numeric segment will be made primary. Indexes are searched in order of their name, rather than by their DataFlex index number.

The DF_FILE_RECORD_IDENTITY attribute uses column numbers. The Primary_Index intermediate file keyword uses index numbers. When setting up the primary index in the intermediate file, the record identity field is indirectly set.

See Also

Table Keywords

Table Types


Max_Rows_Fetched

The number of rows to limit a result to.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

0 ..

Associated Attribute

DF_FILE_MAX_ROWS_FETCHED (Positive integer)

Remarks

The number of records result sets of find operations on this table should be limited to. The default value is 0 (zero), which means that result sets will not be limited. All other positive integer values will limit the result set to that value.

Database servers use the SQL language to manipulate data. SQL is a set oriented language. Every statement works on set(s) and results in a set. A Visual DataFlex find command will be translated into its SQL counterpart, which is sent to the database server. The SQL statement will result in a set of rows that satisfy the condition of the statement for the find command. This result set can have no, one or more rows. In some cases, a result set will contain all rows of a table.

Limiting the result set can improve performance. Unfortunately, there is no rule that can be followed when using this attribute. The best setting for the attribute depends on the program logic and may vary in different functional areas in one program. Normally, the best settings to use when experimenting with values for this attribute are 0, 1 and the number of records that are shown on the screen (in lists).

The Microsoft SQL Server Connectivity Kit uses dynamic cursors for its find logic – it is one of the server side cursors supported by Microsoft SQL Server. In general, a setting of zero (0) will provide the best performance. For more information about cursors, see the SQL Server documentation.

The IBM DB2 Connectivity Kit uses forward only cursors for its find logic. The database server handles a forward only cursor and is one of the cursors supported by DB2. In general, a setting of zero (0) will provide the best performance. For more information about cursors, see the DB2 documentation.

See Also

Table Keywords


Primary_Index_Trigger

Primary_Index_Trigger (Obsolete)

The Primary_Index_Trigger keyword has been replaced with the Generate_Record_ID_Method keyword.

The keyword is still supported for backward compatibility reasons. The value will be translated in the following way: “No” to “None” and “Yes” to “Identity_Column”.

See Generate_Record_ID_Method for more information.

See Also

Table Keywords


Recnum_Table

Indicates if the table is a recnum or standard table.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

YES, NO

Associated Attribute

DF_FILE_RECNUM_TABLE (Boolean)

Remarks

The keyword indicates if a table is a standard or a recnum table. See the chapter on table type for a discussion on standard and recnum tables.

See Also

Table Keywords


Refind_After_Save

Will the record be refound directly after a save operation.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

YES, NO

Associated Attribute

DF_FILE_REFIND_AFTER_SAVE (Boolean)

Remarks

If triggers are defined on a table that fill one (or more) columns in a row that is created or updated, you may use this setting if you want these new column values to be available directly after the save operation. Setting this keyword will ensure that the record buffer is up-to-date. Setting this keyword to NO, the default, will switch re-fetching the row off. This eliminates a Client/Server communication round trip, thus speeding up performance when creating records.

See Also

Table Keywords


System_File

Indicates if the table is a Visual DataFlex system table.

Supported By

All Connectivity Kits

Value

YES, NO

Associated Attribute

DF_FILE_IS_SYSTEM_FILE (Boolean)

Remarks

System tables are treated in a special way. They should contain one record and one record only. When a system table is opened, the first (and only) row in the table will be placed in the table’s record buffer.

The DataFlex Embedded Database determines this attribute by the maximum number of records. In the other supported back ends, we cannot set a maximum number of rows. Be aware that the number of records in the table does not need to be one. This is determined by program logic, not by the Connectivity Kit.

See Also

Table Keywords


Table_Character_Format

The format of the data in the table.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

ANSI, OEM

Associated Attribute

DF_FILE_TABLE_CHARACTER_FORMAT (String)

Remarks

This format can be set to ANSI or to OEM. DataFlex programs use data in OEM format. Most Windows applications expect data to be in ANSI format. If you want to access data from DataFlex and some other Windows tool, it may be required that you have the data stored in ANSI format.

Be aware that setting this value by editing the intermediate file will only change the way data is presented and new data is stored. Existing data will not be converted from OEM to ANSI or vice versa. You need to run a conversion utility to convert existing data.

If you are creating new tables (when converting, by using Database Builder or doing a structure operation) the setting of the driver configuration keyword DEFAULT_TABLE_CHARACTER_FORMAT will be used to determine the initial setting of the attribute.

For more information on character formats, see Character Formats (OEM or ANSI).

For more information on configuration files, see Driver Configuration.

See Also

Table Keywords


Table_Tablespace

The name of the tablespace to store data from the table.

Supported By

DB2 Connectivity Kit

Value

The name of the tablespace to store data from the table.

Associated Attribute

DF_FILE_TABLE_TABLESPACE (String)

Description

Table spaces are used to distribute the storage of information associated with a table over multiple disks. See the DB2 documentation for more information on tablespaces. For a table one can store the index, long data and “normal” table data in different table spaces. The index and long tablespace will only be used if a table data tablespace has been defined.

See Also

Table Keywords


Use_Dummy_Zero_Date

Must dummy zero dates be use for the data columns of the table?

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

YES, NO

Associated Attribute

DF_FILE_USE_DUMMY_ZERO_DATE (Boolean)

Remarks

This attribute indicates if dummy zero dates must be used for date columns that do not allow null values. The setting has no effect on date columns that allow null values. When set to YES, the Connectivity Kit will translate the DataFlex zero date to the dummy zero date value as follows:

  • SQL Server = "1753-01-01"

  • DB2 = "0001-01-01"

  • ODBC = "0001-01-01"

This avoids problems that can arise with sorting on indexes that use the date columns.

The ODBC Connectivity Kit allows the dummy zero data value to be setup in the configuration file.

For more information see NULL Values and Defaults.

See Also

Table Keywords


Column Keywords

The following keywords set attributes on column level. They must be set directly after the table keywords and before the index keywords (if any). Column keywords are grouped per column. If you want to set a column keyword, the column must be identified first (Field_Number), and then you can set one or more column keywords for that particular column. The keywords will apply to the last Field_Number that was specified.

Most of the keywords discussed will be automatically set by the Connectivity Kit and will never be added to the intermediate file.

The length of a column for example, is defined at the server and normally this is not changed on the Visual DataFlex side. In some situations, you may want to change the attribute on the Visual DataFlex side only. In those cases, you should use the keywords or associated attributes to setup the desired value.

The following intermediate file keywords set column attributes:

  • Field_Index

  • Field_Length

  • Field_Name

  • Field_Number

  • Field_Overlap_Start and Field_Overlap_End

  • Field_Overlap_Offset_Start and Field_Overlap_Offset_End

  • Field_Precision

  • Field_Read_Only

  • Field_Related_File

  • Field_Related_Field

  • Field_Store_Time

  • Field_Type

  • Field_Type_Aux

  • Field_Type_Btr

  • Next_Column_Hidden

See Also

Intermediate Files

Order of Keywords

Header Keywords

Table Keywords

Index Keywords


Field_Index

Main index for the column.

Supported By

All Connectivity Kits

Value

0 .. Highest index number defined for the table

Associated Attribute

DF_FIELD_INDEX (Integer)

Remarks

This keyword will set the main index attribute for a column. If this attribute is not set in the intermediate file, the DF_FIELD_INDEX attribute will be set to the first index the column appears in as a segment.

See the Visual DataFlex documentation for more information on main indexes.

See Also

Column Keywords


Field_Length

Length of the column.

Supported By

All Connectivity Kits

Value

1 .. Maximum length for the type of the column

Associated Attribute

DF_FIELD_LENGTH (Integer)

Remarks

The Connectivity Kit will get the lengths defined at the server. If you want to define a different length in Visual DataFlex from the length at the server, you should use this setting. It defines the length of the column (together with Field_Precision).

This keyword is normally used to make sure that two relating columns have the same length. This can be a problem when relating between tables on different back ends.

For example, Visual DataFlex will report the length of a numeric field as a multiple of 2. SQL servers support lengths for numeric data that are not a multiple of 2. If you want to relate between an SQL numeric column of length 3 and a Visual DataFlex field of length 4, you should set this property for that field to 4.

In the SQL Connectivity Kits this keyword can be used to enlarge the size of a text or binary column. SQL back ends often store text and binary information in large objects (CLOB or BLOB). For columns of such type you cannot specify a length, instead they can contain data up to a large value (typically 2 or 4 Gb). When connecting to a table that contains such a column the length of these columns will be reported as 16Kb by the SQL Connectivity Kit. It is obvious the column can hold much more data then that. You can increase the length you can use by setting the Field_Length keyword. This will result in a field buffer of the entered size being allocated in memory.

See Also

Column Keywords


Field_Name

The name of the column.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

The name of the column as reported by Visual DataFlex

Associated Attribute

DF_FIELD_NAME (String)

Remarks

This keyword is generally used to setup overlap column names. It can also be used to setup a different name for the Visual DataFlex environment from the name at the server.

There are column names that are legal at the SQL data source but not in Visual DataFlex. If you want to access a table with such a column, use the Field_Name keyword to set it to a legal Visual DataFlex name. An example of this type of name would be File_Number, which is a legal name in most SQL environments, but is not legal in Visual DataFlex.

See Also

Column Keywords


Field_Number

The number of the column.

Supported By

All Connectivity Kits

Value

0 .. Maximum number of columns in a table.

Associated Attribute

DF_FIELD_NUMBER (Integer)

Remarks

The Field_Number keyword defines a column keyword group. All subsequent column keyword settings will apply to the column with the number specified. The column number will change when another Field_Number keyword is used.

It is not possible to separate settings under multiple column groups. Every new column number will overwrite any preexisting settings.

See Also

Column Keywords


Field_Overlap_Start, Field_Overlap_End

Define begin- and end column of an overlap column.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

1 .. Number of columns in the table

Associated Attributes

DF_FIELD_LENGTH (Integer)

DF_FIELD_OFFSET (Integer)

Description

The Field_Overlap_Start and Field_Overlap_End keywords are used to define an overlap column. An overlap column is a logical column that “overlaps” multiple underlying real columns. The keywords are set to the numbers of the columns that are overlapped.

If we want to define a column at number 5 called My_Overlap starting at column 3 and ending at column 4 (inclusive), we need to place the following lines in the intermediate file:

Field_Number 5

Field_Name My_Overlap

Field_Overlap_Start 3

Field_Overlap_End 4

The lines above will insert a column in the table definition. Column number 5 is a logical column; the original column number 5 and higher will shift one position. Overlaps defined in this way always overlap complete columns.

Please note that the overlap column will be inserted when the column definition is finished at a new field group header, an index group header or the end of the intermediate file. Therefore, the following intermediate file definition will generate two subsequent overlap columns at position 5 and 6. The original column number 5 and higher will have shifted two positions.

Field_Number 5

Field_Name Eventually_Field_6

Field_Overlap_Start 2

Field_Overlap_End 3

Field_Number 5

Field_Name Eventually_Field_5

Field_Overlap_Start 1

Field_Overlap_End 3

Multi Segment Relationships

The biggest reason to use overlap columns in a Visual DataFlex environment was to define relationships. Up until Visual DataFlex 11 relationships had to be defined from one single column to one single column. Overlap column where used to create multi segment relationships and still comply with the 1 column relationship requirement. With the introduction of VDF11 multi segment relationships are supported. There is no need to define overlap fields for multi segment relationship anymore.

See Also

Column Keywords


Field_Overlap_Offset_Start, Field_Overlap_Offset_End

Define begin- and end column of an overlap column.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

1 .. Length of a row in the table

Associated Attributes

DF_FIELD_LENGTH (Integer)

DF_FIELD_OFFSET (Integer)

Remarks

The Field_Overlap_Offset_Start and Field_Overlap_Offset_End keywords are used to define an overlap column. An overlap column is a logical column that overlaps multiple underlying real columns. The keywords are set to the offset in the row of the columns that are overlapped. These keywords can be used to create so-called "underlaps".

The Field_Overlap_Offset keywords are not supported in Structure operations. If you perform a restructure operation on a table with underlaps, they will be forced to complete overlap by the Structure_End logic.

Please note that every back-end has its own rules for offsets and field lengths. Using the same settings in Visual DataFlex and SQL servers can result in different overlaps. Be sure to check if the overlap definition is correct.

See the discussion on the Field_Overlap_Start and Field_Overlap_End keywords for more information on inserting overlaps and the consequences for other column’s numbers.

See Also

Column Keywords


Field_Precision

Precision of the column.

Supported By

All Connectivity Kits

Value

1 .. Maximum precision for the type of the column

Associated Attribute

DF_FIELD_PRECISION (Integer)

Remarks

The Connectivity Kit will get the precision defined at the server. If you want to define a different precision in Visual DataFlex from the precision at the server, you should use this setting. It defines the length of the column (together with Field_Length).

This keyword is normally used to make sure that two relating columns have the same length. This can be a problem when relating between tables of different back ends.

For example, Visual DataFlex will report the length of a numeric field as a multiple of 2. SQL servers support lengths for numeric data that are not a multiple of 2. If you want to relate between an SQL numeric column of length 3 and a Visual DataFlex field of length 4, you should set this property for that field to 4.

See Also

Column Keywords


Field_Read_Only

Set a columns read only attribute.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

No, IgnoreChange, AcceptChange, ErrorOnChange

Associated Attribute

DF_FIELD_READ_ONLY (Enum list)

Remarks

In some cases it is not desirable that a certain column is changed through the Connectivity Kit. It is possible to handle certain column updates through triggers. If one goes that way, it would be needed to change every program that accesses that table so it no longer updates the column in question. Alternatively, one could use the Field_Read_Only keyword and the program logic does not have to change.

The keyword can be set to the following values:

VALUE | MEANING
No | Normal column. Data can be moved into the column in the normal way.
IgnoreChange | Any move of any value to the column will be ignored.
AcceptChange | Values can be moved into the column but these values will never be stored. This setting can be used when using an indexed column; values should be accepted in order to seed find operations.
ErrorOnChange | When the value in the column is changed, an error is generated (error 12315, CLIERR_FIELD_READONLY).

See Also

Column Keywords


Field_Related_File

Filelist number of the parent table.

Supported By

All Connectivity Kits

Value

1 .. Maximum number of tables supported by DataFlex

Associated Attribute

DF_FIELD_RELATED_FILE (Integer)

Remarks

Visual DataFlex relationships are setup through the filelist. In the filelist, all tables are assigned a number. This number is used within Visual DataFlex to identify the table; columns are also identified by their number.

By setting the Field_Related_File and Field_Related_Field keywords, a relationship can be defined. The Data Connection Wizards in Database Builder use the foreign and primary key definitions created at the server to copy relationships when connecting to existing data. See the chapter on Connecting to Existing Data for more information on the Data Connection Wizards.

Multi Segment Relationships

Up until Visual DataFlex 11 relationships had to be defined from one single column to one single column. Overlap column where used to create multi segment relationships and still comply with the 1 column relationship requirement. With the introduction of Visual DataFlex 11 multi segment relationships are supported. There is no need to define overlap fields for multi segment relationship anymore.

See Also

Column Keywords


Field_Related_Field

Column number in the parent table that this column relates to.

Supported By

All Connectivity Kits

Value

1.. Number of columns in the "relates to" table

Associated Attribute

DF_FIELD_RELATED_FIELD (Integer)

Remarks

Visual DataFlex relationships are setup through the filelist. In the filelist, all tables are assigned a number. This number is used within Visual DataFlex to identify the table; columns are also identified by their number.

By setting the Field_Related_File and Field_Related_Field keywords, a relationship can be defined. The Connect Wizards in Database Builder use the foreign and primary key definitions created at the server to copy relationships when connecting to existing data. See the chapter on Connecting to existing data for more information on Connect Wizards.

Multi Segment Relationships

Up until Visual DataFlex 11 relationships had to be defined from one single column to one single column. Overlap column where used to create multi segment relationships and still comply with the 1 column relationship requirement. With the introduction of Visual DataFlex 11 multi segment relationships are supported. There is no need to define overlap fields for multi segment relationship anymore.

See Also

Column Keywords


Field_Store_Time

Time portion of a datetime column.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

.. 86400

Associated Attribute

DF_FIELD_STORE_TIME (Integer)

Description

This keyword sets the time portion for a datetime type column. For more information on the datetime type, see the documentation for your server.

The integer represents the number of seconds in the day. A value of –1 indicates that the server time will be used. Any other negative value indicates that the client’s system time will be used.

The time portion will be stored upon save, every time the column is changed. Datetime columns contain a date and a time portion. The Connectivity Kit will report the column as being of the DF_DATE type.

In a Visual DataFlex program, the column can be manipulated using the date logic in Visual DataFlex. The time portion can be set using this attribute. The time portion of a datetime column cannot be read by Visual DataFlex; this can only be done Using Embedded SQL.

For a more flexible way to manipulate the time portion of a datetime column, see DF_FIELD_TIME.

See Also

Column Keywords


Field_Type

The type of the column.

Supported By

Pervasive.SQL Connectivity Kit

Value

ASCII, BCD, BINARY, DATE, OVERLAP, TEXT

Associated Attribute

DF_FIELD_TYPE (Enum list)

Remarks

Sets the data-type information for a field. This is used, for example, when we want to mark a field as a DataFlex Overlap field because, according to Pervasive.SQL, those fields are just string fields. This is because Pervasive.SQL doesn't support the Overlap field type.

See Also

Column Keywords


Field_Type_Aux

The Pervasive.SQL non standard type of the column.

Supported By

Pervasive.SQL Connectivity Kit

Value

LSTRING2, DFBCD

Associated Attribute

None

Remarks

This can be used to specify certain non-standard data types and is typically used for DataFlex for Btrieve converted data tables that use non-standard field types. Currently implemented are LSTRING2 and DFBCD.

The LSTRING2 type can be used for TEXT fields in tables that have been converted with the for Btrieve product. This field type stores the length of a text in the first two bytes followed by the actual text.

The DFBCD type is also being used by DataFlex for Btrieve converted data for numeric fields that exceeds the maximum number of digits of 21 for Pervasive.SQL numeric fields.

See Also

Column Keywords


Field_Type_Btr

The Pervasive.SQL type of the column.

Supported By

Pervasive.SQL Connectivity Kit

Value

STRING, INTEGER, IEEE, DATE, TIME, DECIMAL, MONEY, LOGICAL, NUMERIC, BFLOAT, LSTRING, ZSTRING, NOTE, UNKNOWN, UNSIGNED, AUTOINCREMENT, UNKNOWN, NUMERIC_STS, NUMERIC_SA, CURRENCY, TIMESTAMP, LONGVAR

Associated Attribute

None

Remarks

This can be used to overrule the Pervasive.SQL field type specified in the DDF tables and will be rarely used.

See Also

Column Keywords


Next_Column_Hidden

Indicates the column is used as a case insensitive index segment.

Value

Uppercased

Associated Attribute

DF_INDEX_SEGMENT_CASE (enum list)

Remarks

The Visual DataFlex Embedded Database supports case insensitive index segments. SQL back ends do not support this. The Connectivity Kit uses a work-around to implement case insensitive index segment support. The work-around is to create a hidden column, which is defined in the table on the server but not reported by the Connectivity Kit. The hidden column directly follows the original column. It will store the original column values uppercased.

To indicate a column is hidden, the Next_Column_Hidden keyword is used in the field definition of the original column. The keyword can only be set to Uppercased.

In SQL Server and DB2 the database server will automatically maintain the contents of the hidden column. This does not require any special settings in DB2 but for the SQL Server database the option ARITHABORT must be set to ON. Whenever a table that has at least one case insensitive segment is opened or created, the Connectivity Kit will check if the database option is set correctly. If it is not set correctly a warning will be generated. The user has the option to let the Connectivity Kit attempt to change the database option. The table cannot be opened or created until the database option ARITHABORT is set to ON.

See Also

Column Keywords


Index Keywords

The following keywords set attributes on index level. They must be set directly after the column keywords, if those are present in the INT file.

Index keywords are grouped per index. If you want to set an index keyword, the index must be identified first (Index_Number), then you can set one or more index keywords for that particular index. The keywords will apply to the last Index_Number that was specified.

Most of the keywords discussed here will be automatically set by the Connectivity Kit and will never be added to the intermediate file.

There are two types of indexes that can be defined in the intermediate file: Indexes that are defined at the server and those that are defined only in Visual DataFlex. You can use a mix of the two index types on a table. Defining an index in Visual DataFlex only is useful when using database views or an index that is only used sporadically.

The Structure_End logic favors server indexes. It will try to create as many indexes at the server as possible. If you have defined indexes only in Visual DataFlex because they are seldom used, a Structure_End on the table will create these indexes at the server.

Server Indexes

When the index exists at the server itself, only use the following intermediate file keywords:

  • Index_Number

  • Index_Name

Visual DataFlex Indexes

When defining indexes that exist on the Visual DataFlex side only, use the following intermediate file keywords:

  • Index_Number

  • Index_Name

  • Index_Number_Segments

  • Index_Unique

  • Index_Segment_Field

  • Index_Segment_Case

  • Index_Segment_Direction

Special Note

Please note that you can define indexes on the Visual DataFlex side only. This means that there is no physical index defined in the database. You can program in Visual DataFlex as if the index actually exists.

Be aware that since no actual physical index exists, the performance when accessing that table by the index will be greatly affected (i.e. it is not going to be fast).


Index_Number

The number of the index.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

1 ..

Associated Attribute

None

Remarks

The Index_Number keyword defines an index keyword group. All subsequent index keyword settings will apply to the index with the number specified. The index number will change when another Index_Number keyword is used.

It is not possible to separate settings under multiple index groups. Using the same index number twice (or more) will result in errors in the table definition.

Indexes for a table are numbered in the following order:

  1. All indexes defined for the table will be read in.

  2. All settings in the intermediate file are read and the indexes defined are assigned a number.

  3. Lastly, all indexes that have not been assigned a number yet will be assigned a number starting with the highest number used until now + 1. The remaining indexes are numbered in alphabetical order.

See Also

Index Keywords


Index_Name

The name of the index.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

The name of the index in SQL Server

Associated Attribute

DF_INDEX_NAME (String)

Remarks

Whenever a table is opened, the Connectivity Kit will automatically read the indexes defined for that table. The Index_Name keyword lets you set up a number for the index with the specified name.

Let's assume a table with indexes, MyTable001, MyTable002, MyTable003 and MyTable004 and the following intermediate file index section:

Index_Number 2

Index_Name MyTable003

Would result in:

INDEX NAME | DATAFLEX INDEX NUMBER
MyTable001 | 3
MyTable002 | 4
MyTable003 | 2
MyTable004 | 5

See Also

Index Keywords


Index_Number_Segments

The number of index segments.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

1 ..

Associated Attribute

DF_INDEX_NUMBER_SEGMENTS (Integer)

Remarks

The Index_Number_Segments keyword defines the number of segments in the index.

See Also

Index Keywords


Index_Unique

Indicates if an index is unique.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

YES, NO

Associated Attribute

DF_INDEX_UNIQUE (Boolean)

Remarks

SQL supports both unique and non-unique indexes. Setting the keyword to YES indicates the index is unique; setting it to NO indicates the index is non-unique. Using non-unique indexes may give unexpected results while finding records using that index.

See Also

Column Keywords

Index Keywords

Table Keywords


Index_Segment_Field

The field number of the index segment column.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

0 ..Number of columns in the table

Associated Attribute

DF_INDEX_SEGMENT_FIELD (Integer)

Remarks

The number of the column in the current segment. There must be an Index_Segment_Field line for every segment in the index.

For example, if we want to define index 4 as having three segments where segment 1 is column 5, segment 2 is column 3 and segment 3 is column 2 this would look like:

Index_Number 4

Index_Number_Segments 3

Index_Segment_Field 5

Index_Segment_Field 3

Index_Segment_Field 2

See Also

Index Keywords


Index_Segment_Case

The index segment casing.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

Used, Ignored

Associated Attribute

DF_INDEX_SEGMENT_CASE (enum list)

Remarks

The keyword indicates if the segment is case insensitive. Case insensitive segments treat every value as if it were stored in one casing (uppercase). Trying to add the values "Data Access" and "data access" to a column that is the single case insensitive segment in a one-segment index will result in a duplicate record error.

Setting the keyword to "Used" will make the segment case sensitive (no duplicate record error would be generated in the above example). Setting the keyword to "Ignored" will make the segment case insensitive and behave like the example above.

See Also

Column Keywords

Index Keywords

Table Keywords


Index_Segment_Direction

The sort direction of the segment.

Supported By

SQL Connectivity Kits (SQL Server, DB2 and ODBC)

Value

ASCENDING, DESCENDING

Associated Attribute

DF_INDEX_SEGMENT_DIRECTION (enum list)

Remarks

The direction of a certain segment. If you want to set the direction, this must be done directly after the Index_Segment keyword. The keyword can be set to either ASCENDING or DESCENDING. ASCENDING is the default value.

Therefore, if we wanted the above index to be descending on the last two segments the definition would look like:

Index_number 4

Index_Number_Segments 3

Index_Segment_Field 5

Index_Segment_Field 3

Index_Segment_Direction DESCENDING

Index_Segment_Field 2

Index_Segment_Direction DESCENDING

See Also

Index Keywords


Character Formats (OEM or ANSI)

When using the SQL Connectivity Kits (SQL Server, DB2 or ODBC), you can choose to store your data in either OEM or ANSI format. While tables using the embedded database store their data in OEM format this may not be an appropriate format for other databases. The Connectivity Kit can read or write data in either OEM or ANSI format and handle all the required translations automatically. The native character format of your data will be invisible to your application (i.e. no programming changes are required). However, you must identify the character format of each table so the Connectivity Kit can handle the translations as needed. This is accomplished with settings in your .INT files.

What format do I want for my tables?

Embedded database tables use OEM format. If you are moving your data to another database and you expect that DataFlex will be the only application using this data, then you could just store all of your data in OEM format. There are two reasons why you may not want to do this:

  1. You may be hooking into an existing table and you must use the character format that already exists, or

  2. You will want your data to be accessible by other tools and applications that expect the data to be in a specific character format.

To simplify the decision, just assume that you want to store your data in the format that is the standard for the selected database.

See Also

Setting Character Formats

Converting Table Formats


Setting Character Formats

Determining the Character Format of a Table

Each table's .INT file should contain information about how the data is stored. You will have a line in this file that looks like

TABLE_CHARACTER_FORMAT OEM

Or, if you set the character format to ANSI, the line will look like

TABLE_CHARACTER_FORMAT ANSI

If your .INT file does not contain this setting, it indicates that the file was created with an earlier version of the Connectivity Kit and has not yet been modified by the newer Connectivity Kit. When missing, the format is assumed to be OEM. TABLE_CHARACTER_FORMAT tells the driver (and you) what the current character format for a table is. You must be very careful if you change this value! Changing the value does not change the data. This can result in the driver making improper translations. If you need to change the character format of a table you should use a conversion utility to do this.

You can safely change this value if the table is empty. You might do this if you wish to set a table's character format before adding or converting data. Normally, you will never need to do this. Instead, you can set a default character format for all new tables as described below.

Defining the Default Character Format for New Tables

When creating new tables, Database Builder must know what character format to use when creating the table definition. It does this by looking at a setting in your driver configuration file called DEFAULT_TABLE_CHARACTER_FORMAT.

DEFAULT_TABLE_CHARACTER_FORMAT [OEM | ANSI]

This setting determines what format will be used when defining and creating a new table. It determines whether the table's TABLE_CHARACTER_FORMAT will be set to OEM or ANSI. This setting ensures that table conversions save the data in the proper character format.

If your configuration file does not contain the DEFAULT_TABLE_CHARACTER_FORMAT setting or the file is missing, the default will be OEM. We advise that you explicitly set this value in your configuration file. Note that when missing, the character format defaults to OEM. This is done for backwards compatibility reasons and does not represent a recommendation.

For more information on the driver configuration file see Driver Configuration.

Recommendations

  1. We recommend that all of the tables in any database should use the same character format.

  2. Existing tables created by pre 2.1 versions of the driver are most likely using OEM format. These will continue to work properly. If you are using ANSI as your default character format, we advise that you convert the format of these tables to ANSI using one of the available conversion utilities (see Converting Table Formats).

See Also

Character Formats (OEM or ANSI)


Converting Table Formats

Visual DataFlex provides a wizard to walk you through the process of converting data from OEM to ANSI format or vice versa. It will also adjust the table definition of the converted tables to the new format.

The VDFOEMAnsi wizard allows the user to select the method of conversion (Workspace, Filelist and/or Individual table) and to select a target format. To start the VDFOEMAnsi wizard you need to select the "OEM ANSI Wizard…" menu choice in the "Database" menu of Database Builder.

See Also

Character Formats (OEM or ANSI)


Table Types

Visual DataFlex applications can use data from most databases. The Visual DataFlex Embedded Database is ISAM-based and the Application Framework and language were built on the ISAM model of data access. In order for Visual DataFlex to function when connecting to other databases, it imposes some requirements on the structure of the data it can connect to. Every table that Visual DataFlex connects to must have the means to uniquely identify individual records (rows) in the table. If a table fails to meet this requirement it cannot be accessed using the Application framework. It can however be accessed using Embedded SQL.

Previous versions of Visual DataFlex and SQL based Connectivity Kits imposed an additional requirement on tables; a table needed "record identity". This requirement has been removed with the introduction of Visual DataFlex 11. A table that meets the record identity requirement is called a recnum table.

The SQL Connectivity Kits are able to access data in tables that do not meet the record identity requirement but do meet the less strict requirement of the ability to uniquely identify individual records. Such a table is called a standard table.

See Also

Standard Tables

Recnum Tables

Defining the Table Type and Primary Index


Standard Tables

In a standard table individual records are uniquely identified by one or more columns of any type. The Connectivity Kit is informed about these columns by specifying the (unique) index made up of the columns. The index that is used to define the identifying columns is called the primary index.

Most tables have one or more column combinations that uniquely identify records. Such a combination is called a key. In most databases you can assign one of the keys to be the primary key. If a primary key exists it is the most likely candidate to be setup as primary index.

There are two programming styles that can be used to handle tables in the Application framework: RowId and RECNUM style. When using standard tables, the RECNUM style cannot be used, RowId style is mandatory.

See Also

Table Types


Recnum Tables

In a recnum table individual records are uniquely identified by a record identity. A record identity is a single numeric column with no decimal places that uniquely identifies a record in a table. The Connectivity Kit is informed about the record identity by specifying the (unique) index made up of the record identity column.

There are two programming styles that can be used to handle tables in the Application framework: RowId and RECNUM style. When using recnum tables, Both RECNUM- and RowId style can be used.

What is a Record Identity?

A record identity used to be required for historic reasons. With the introduction of VDF11 and the CLI/SQL Connectivity Kits version 4, record identities are no longer required. A short introduction on record numbers explains that history.

Visual DataFlex Embedded Database Record Numbers

The Visual DataFlex embedded database stores its information in disk files. Every table is stored in several disk files. One of the files contains the actual data, the other files contain the indexes, a DataFlex compiler include file (so the table can be used in programs) and a column name file.

DataFlex embedded database data is accessed according to a defined sort order called an index. One order always exists and that is the “storage order.” This order can be used from within a DataFlex environment and is referred to as the record number (RECNUM) order. The record number is a consecutive positive number starting at 1 that indicates a record’s relative position in the table. It can be used to search the table for a specific record.

Since record numbers indicate a record’s relative position in the table, it can be used in conjunction with the record size to determine the records position in the disk file. This involves minimal disk access and results in a fast operation.

The record number can be used within the DataFlex environment as if it were a field in the table. In reality, it is a logical column; no disk space is allocated to store record numbers. Record numbers are assigned when creating records. DataFlex programmers cannot control the record number for a new record.

It has been strongly discouraged by Data Access to use record numbers as meaningful information. Older systems programmed in DataFlex sometimes misused the logical column as customer number or order number.

DataFlex record numbers have the following characteristics:

  • Uniquely identify a row

  • Automatically available

  • Automatically maintained

  • Unchangeable for a given row

  • Reusable

  • Offers faster access than other indexes

  • Sequential consecutive number ranging from 1 to 16 million

In Visual DataFlex 11 the runtime and packages have been adjusted so they no longer rely on the existence of records numbers. Older Visual DataFlex revisions do rely on record numbers in the runtime and packages. Using the CLI/SQL Connectivity Kits it is still possible to rely on the existence of record numbers by using RECNUM tables.

API Requirements

The API requires every recnum table it accesses to have a record number like column called the record identity. There is only a need to access recnum tables in a non embedded database if the program uses the RECNUM programming style. This column can be a logical column or actually exist in the table. It should have the following characteristics:

  • Uniquely identify a row

  • Numeric with no decimal places

  • Ranges from 1 to 2^31 (2147483647)

  • Is available as a unique index

The API does not require the record identity to

  • Be automatically available

  • Be automatically maintained

  • Be unchangeable for a given row

  • Be reusable

  • Offer faster access than other indexes

  • Be sequential consecutive numbers ranging from 1 to 16 million

All recnum tables accessed by the Data Access Database API must fulfill the four characteristics. Since the API does not require that the record identity is automatically maintained there may be drivers that require additional programming to maintain the identity. Also be aware that other non-DataFlex applications creating data in tables accessed by DataFlex need to make sure that the record identity meets the minimum requirements of the API.

Other Databases

Other database types do not have a record number column or use some other form of identifying the rows in a table. Some databases use record number like functionality, others use so-called ROWID’s, some use time stamps others do not use any type of logical identifier (at least not accessible by client programs).

SQL Server

Microsoft SQL Server does not have a record identity column that is automatically available for every table. It has a type attribute that we can use so the API for recnum tables requirements are met; it is called the IDENTITY type attribute. For more information on this type, see the SQL Server documentation.

When converting a table to a SQL Server recnum table, an extra column will be inserted before the original definition. This column will be called RECNUM. It is an integer column that has the IDENTITY attribute set. Since SQL Server automatically maintains identity columns, every application accessing the table will follow the API’s minimum requirements for recnum tables. The program that used the original table does not need to be adjusted in any way.

DB2

IBM’s DB2 Universal Database does not have a record identity column that is automatically available for every table. It has a type attribute that we can use so the API requirements for recnum tables are met; it is called the IDENTITY type attribute. For more information on this type, see the DB2 documentation.

When converting a table to a DB2recnum table, an extra column will be inserted before the original definition. This column will be called RECNUM. It is an integer column that has the IDENTITY attribute set. Since Db2 automatically maintains identity columns, every application accessing the table will follow the API’s minimum requirements. The program that used the original table does not need to be adjusted in any way.

ODBC

Since ODBC is an open specification it is unknown if the data source supports record identity columns, RowId's, time stamps or none of the mentioned identifiers.

When converting a table to an ODBC recnum table, an extra column can be pre-pended to the original definition. This column will be called RECNUM. It is a numeric column; the exact type depends on the types supported by the actual back-end used. The program that used the original data may need to be adjusted.

Some databases support an auto-increment feature for certain column types. If this feature is supported it can be used by altering the database configuration file.

See Also

See the Database Specific Configuration File for a discussion of pre-defined database configuration files.

See Driver Configuration for a more information on configuration files.


Pervasive.SQL Recnum Support

Recnum Support means that when a table is converted from DataFlex to Pervasive.SQL the Connectivity Kit will preserve the original recnum values of the DataFlex table.

You will only need to convert with recnum support if the recnum values have some meaningful value. For example when the recnum value is used as the customer id number in a customer file. Also if you have defined relations from or to the recnum field, you must use recnum support. In general recnum support will only be necessary with applications that are derived from older DataFlex character mode applications.

Tables without recnum support will still have a recnum field. Recnum values are calculated from the position of the record in the table. These recnum values cannot be used in indexes and also are not numbered started with 1 and incremented with 1.

Converting Tables

When a table is being converted with recnum support, an extra field will be inserted at the beginning of the record. This field is called RECID by default and is a 4-byte integer. The field will be the only segment of Index 0 (Pervasive.SQL) and is being defined as an AUTOINCREMENT field, which means that Pervasive.SQL will assign a number to it whenever a new record is being inserted which has no value (0) for the RECID field.

If you want to choose another name for this substitute for the DataFlex recnum fields, you can do so by adding a line into your DFBTRDRV.INT file like this:

RECID_NAME “MYRECID”

Note that this setting will only be used when converting tables. After tables have been converted, you can only change the name of the field by using a special tool for maintaining DDF files, or by temporarily commenting out the RECNUM_SUPPORT keyword in the generated .INT file.

Index Numbers

Normally, the indexes of a Pervasive.SQL tables are presented to the API with a number, higher by one than Pervasive.SQL’s actual index number. This is needed because Pervasive.SQL indexes start numbering at 0. When a table has been converted with recnum support, the first Pervasive.SQL index (0) is the one that we use for the recnum field index. In that case, all other Pervasive.SQL index numbers are passed without modification, because Index Number 1 in Pervasive.SQL is Index Number 1 to DataFlex.

Opening Tables

When the Connectivity Kit opens a Pervasive.SQL table, it needs to know if this table has been converted with or without recnum support. This information has been written to the .INT file generated for the table when it was being converted. The keyword RECNUM_SUPPORT should have a numeric value other then 0 in this case. If your INT file is missing this line, the field that represents RECNUM will be the first field of the record according to DataFlex and all other field numbers will be shifted 1 up. Numbering of the indexes will also be shifted by 1. Refer to Opening Tables, for more information.

Opening Tables Directly

The Connectivity Kit is also capable of opening Pervasive.SQL tables directly, bypassing the .INT file created for the table. In order to do that, the root name of the table needs to be set to MYFILE.BTR or DFBTRDRV:MYFILE. Note that the extension being used in the first example has nothing to do with the extension of the physical filename. It is just a sign for the API that the Pervasive.SQL Connectivity Kit should handle this file. When this method is being used for opening tables, the Connectivity Kit will open the INT file itself.

If you have no INT file but converted the table with Recnum support, you need to make this clear to the CK. The way to do this is to add a ‘+’ sign to the end of the base name of the table. Examples of root names that will open tables directly with recnum support are:

MyFile+.BTR

DFBTRDRV:MyFile+

No Recnum Support

When you elect not to use recnum support, there are some things you will have to be aware of.

Recnum Value

The value recnum returns will not start with 1 for the first record. It will also probably not be incremented by one for each next record. The ‘gap’ between the recnums of two records following each other may be larger than 1.

Finding by Recnum

When no recnum support has been selected, the table can still be accessed on the recnum index. This will also be the fastest way to scan through a table.

One thing that works differently is that you can’t expect Pervasive.SQL to find a record by clearing a table and just moving a random value into recnum, even if this value falls within the maximum number of records. This is because the maximum number of records just gives you the number of records in the Pervasive.SQL database and tells you nothing about their recnum values!

The next sample shows a piece of code that will not work. Here the program expects that moving a high value into the recnum field followed by a FIND LT will find the last record in the database. To find the last record, just clear the record buffer and do a find LT.

// Sample of things which might not work when

// recnum support has been switch off.

// Wrong code to find last record!

Open Customer

Move 999999 to Customer.Recnum

Find LT Customer by RECNUM

// Right code to find last record!

Open Customer

Find LT Customer by RECNUM


Defining the Table Type and Primary Index

The type of a table should be setup through the intermediate file keyword Recnum_Table. This keyword is set to “no” for standard tables and to “yes” for recnum tables. If the keyword is not set, the Connectivity Kit will automatically detect the table type. The automatic detection of table types also depends on the setting of the primary index, this is why they are discussed together.

The primary index of a table should be setup through the intermediate file by using the Primary_Index keyword. Note that the Primary_Index keyword is used to define the identifier of both RECNUM and standard tables. You should set the keyword to the number of the unique index. If the primary index is not set, the Connectivity Kit will automatically detect a primary index.

Automatically detecting table type and primary index

The automatic detection works in the order defined below.

If the primary index is set to 0 (zero) the table is assumed to be a recnum table. The record identity column is assumed to be the first column of the table, it is automatically hidden. This happens regardless of the table type setting in the intermediate file.

If table type is not set and the primary index is not set or set to a non-zero value the Connectivity Kit will look for a column names “recnum” or “dfrecnum”, if such a column exists the table is assumed to be a recnum table and the column is the record identifier. In case the column is named ”recnum” and the primary index keyword was not set, it will automatically be hidden. This behavior ensures the Connectivity Kit version 4 will be able to open tables created with previous versions of the Connectivity kit.

If both table type and primary index are not set, and the recnum columns described above are not present, the Connectivity Kit will query if a primary key has been defined on the table. If a primary key is defined, its associated index will be made the primary index. If there is no associated index one will be created on the DataFlex side.

If no primary key exists, the Connectivity Kit will search for a column with the identity attribute. If such a column exists and it is present as the single segment in an index, that index is made the primary index.

If none of the above applies the Connectivity kit will select the first index with the least number of segments as the primary index.

After detecting the primary index, the table type depends on the contents of the index. If the index contains a single numeric column with no decimal places, the table is assumed to be a recnum table. All other indexes will result in a standard table.

The logic described above can be influenced by setting Connectivity Kit configuration keywords Default_Record_Identity_Hiding and Default_Map_To_RECNUM. Setting the Default_Record_Identity_Hiding keyword to a non-zero value will ensure the record identifiers of all recnum tables are hidden. Setting the Default_Map_To_RECNUM keyword to zero will ensure that tables with a primary index that contains a single numeric column are not interpreted as recnum tables.

See Also

See the appendix on configuration files for a more information on configuration files.


Programming Styles

Visual DataFlex 11 introduces two programming styles that can be used to handle tables in a DataFlex program: RowId style and RECNUM style.

RowId style can be used with both table types, RECNUM style can only be used with recnum tables. Trying to use the RECNUM style with standard tables will result in errors.

RowId Style

If the RowId programming style is used, the RowId helper functions are used to manipulate tables. Please note that you can use the RowId programming style on both standard and recnum tables. The RowId programming style is the recommended style.

RECNUM Style

If the recnum programming style is used, the record number column can be accessed as if it exists. The DataFlex programmer can manipulate the RECNUM column like any other column except for its value when creating a record. A common technique is to store the record number, do some operations, re-find the record and manipulate the buffer. This is done by:

Move MyTable.Recnum To LocalVariable

…

Move LocalVariable To MyTable.Recnum

Find Eq MyTable By Recnum

…

The above piece of code will still work when using the Connectivity Kits with recnum tables. The Connectivity Kit will automatically translate every reference to RECNUM into a reference to the record identity column.

Visual DataFlex handles moving a value into the record number column in a special way. In addition to moving the value into the (logical) column, the record buffer’s status is set to INACTIVE. This feature is used to create copies of existing records.

Connectivity Kits fully supports this behavior. If for example we have a table called MyTable, with a record identity column called MyRID the following two commands will place 10 into the MyRID column:

Move 10 To MyTable.Recnum

Move 10 to MyTable.MyRID

The first command will also set the MyTable record buffer to inactive. The second command will not change the status of the record buffer.

Please note that if a table has a hidden record identity there is only one way to access that column: Table.Recnum. If a table has a visible record identity there are two ways to access the column: Table.Recnum and Table.RecId.

See Also

Table Types


NULL Values and Defaults

Null and default values are closely related. Usually one will define a default value for most columns that do not allow null values.

See Also

Null Values

Default Values

Configuring Null and Default Values for Conversion


Null Values

SQL represents the fact that some piece of information is missing by a special marker called a null. Columns that contain a null indicate it is not known what the real value is. Informally you can think of such columns as “containing a null” or “being null.” One could argue that the term “null value” is nonsense because the whole point about nulls is that they are not values. We are aware of this argument but the term is commonly used within the database community so we will use it in this discussion.

How nulls are actually represented in the system is implementation dependent. That implementation must (obviously) be so that the system can distinguish between null and non-null values.

Null values complicate internal database logic by creating a three-valued logic as opposed to the normal two-valued (binary) logic. In normal logic operations, the result is either true or false. Using null values will add a third outcome, unknown. This complicates logic considerably.

Null values complicate matters. It may be confusing to the end users if they see unexpected results. More importantly we have found that allowing null values in index columns has a negative impact on performance. Therefore we advise to avoid allowing null values in any column that appears in an index. If you do not allow null values in a column make sure you define an appropriate default for that column. Defaults can be setup per (DataFlex) type.

Whether a column allows null values or not depends on the table definition. This definition can be adjusted by using the DF_FIELD_NULL_ALLOWED attribute. When converting, a configuration file is used that sets up "nullability" per type to convert. These defaults can be adjusted in the driver configuration file.

Support for Null Values

All Connectivity Kits support null values and nullable columns. The SQL Connectivity kits support null values in the data manipulation and data definition logic. You can connect to, convert to or even adjust the table definition with support for null values and nullable columns.

The Pervasive.SQL Connectivity Kit supports null values when creating records. It does not support null values in data definition logic. The Connectivity Kit can not create or restructure tables with nullable columns. Null support in the Connectivity Kit is intended to be used when connecting to existing tables with nullable columns. Such tables must be created and maintained (restructured) with external tools, for example with SQL commands like CREATE TABLE and ALTER TABLE. Tables that are created through the Connectivity Kit (this includes tables that are converted from DataFlex) will not have nullable columns.

Using Null Values in a Program

DataFlex has no equivalent for the SQL concept of null values in a database. The Connectivity Kit adds a column attribute DF_FIELD_IS_NULL of type Boolean that can be used to check if a column is null or to set it to null.

If a row is found that contains a column with the null value, you can still get the value of the column. It will be set to empty or zero (0) depending on the columns type. The only way to know that the column contains the null value is by checking the DF_FIELD_IS_NULL attribute of the column.

If a program wants to save a null value in a record, it needs to set the DF_FIELD_IS_NULL attribute for the column before saving. When records are created, only the columns that have been assigned a value will be assigned an explicit value. All others will get the default value defined for the column in the table definition. If no default is defined null will be used.

Sort Order of Null Values

When a column contains null values, a problem arises when we sort based on that column. A comparison on a null value will return the unknown result. So there is no way to determine the collating sequence of null values. This has been solved by always collating nulls in a standard way.

  • SQL Server will place null values at the beginning of the sort when sorting in ascending order, at the end when sorting in descending order.

  • DB2 will place null values at the end of the sort when sorting in ascending order and at the beginning when sorting in descending order.

  • For ODBC look at your database documentation to find out how null values collate.

  • Pervasive.SQL will place null values at the end of the sort when sorting in ascending order and at the beginning when sorting in descending order.

Dates and Null Values

Almost all possible values of the DataFlex database types can be mapped to legal back end values. The only exception is the zero date value in DataFlex. There is no sensible date value in a SQL back end to map this value to other than null. Pre 2.1 revisions of the SQL Connectivity Kits would therefore convert date column to allow null values with a default value of null. This however introduced performance issue when a date column was part of an index segment, finding on that index would be slow.

Dummy Zero Date

When dummy zero date is used, the Connectivity Kit will use the lowest possible date value as the value to map the DataFlex zero date to. This value is 1753-01-01 for SQL Server, 0001-01-01 for DB2 and 0001-01-01 for ODBC (by default). The Connectivity Kit will handle this internally. The DataFlex program still uses the zero date value. The Connectivity Kit handles automatic conversion of the dummy zero date value whenever needed.

The dummy zero date logic can be configured by the DF_FILE_USE_DUMMY_ZERO_DATE table attribute. If the attribute is set to true for a table, all date columns that do not allow null values will apply the dummy zero date logic.

If there is a need to access the data from outside the Connectivity Kit one should handle the dummy zero date value in a special way.

The dummy zero date logic speeds up indexed find operations. In pre- 2.1 Connectivity Kit versions, date columns allowed null values. Finding on an index containing segments that allow null values is slow. Since the dummy zero date logic does not create columns that allow null values. Finding is as fast as finding using other indexes.

The introduction of the dummy zero date concept changed a number of default settings used at conversion. In pre 2.1 versions the date columns would be converted to allow null values and have a default value of null. In 2.1 and higher date columns will be converted not to allow null values and have a default value equal to the dummy zero date value. These defaults can be adjusted in the driver configuration file.

Connectivity Kit Independent Code for Dummy Zero Dates

The dummy zero date concept is supported in SQL Connectivity Kits. The dummy zero date value is not the same for all Connectivity Kits. When writing embedded SQL code, the programmer will need to filter the dummy zero date values from result sets. In order to do this the value should be known. For this reason the driver level attribute DRVR_DUMMY_ZERO_DATE_VALUE was created.

A back-end independent way to handle this would be:

Function CreateZeroDateQuery String sCKID Returns String

String sZeroDateValue

String sQuery

CLI_Get_Attribute sCKID DRVR_DUMMY_ZERO_DATE_VALUE ;

To sZeroDateValue

Function_return (“Select * From MyTable Where MyDate = ‘” ;

+ sZeroDateValue + “’”)

End_procedure // SelectAllZerodates

For a detailed discussion on the CLI_Get_Driver_Attribute command see Techniques.

Converting from Nullable Columns to Dummy Zero Date

Data created with a pre 2.1 Connectivity Kit would allow null values for date columns. There may be a need to convert such data to use the dummy zero date logic in order to avoid the sort order or performance problems. The conversion can be done in Database Builder or through a DataFlex program.

In Database Builder the parameter tab page allows you to switch the DF_FILE_USE_DUMMY_ZERO_DATE setting for a table. The field tab page allows you to switch the “nullability” of a column. To convert pre 2.1 data to use dummy zero dates check the “Use dummy zero date” checkbox on the parameter tab. For every data column in the table uncheck the “Nullable” column in the field tab.

In Console Mode a program must be written that converts tables. The essence of the conversion logic would be:

Procedure ConvertTable Integer iTable

Integer iNumFields

Integer iField

Integer iType

Structure_Start iTable

Set_Attribute DF_FILE_USE_DUMMY_ZERO_DATE Of iTable ;

To True

Get_Attribute DF_FILE_NUMBER_FIELDS Of iTable To iNumFields

For iField From 1 To iNumFields

Get_Attribute DF_FIELD_TYPE Of iTable iField To iType

If (iType = DF_DATE) ;

Set_Attribute DF_FIELD_NULL_ALLOWED Of ;

iTable iField To False

Loop

Structure_End iTable

End_Procedure // ConvertTable

See Also

NULL Values and Defaults


Default Values

SQL servers allow column definitions to include a default value. This default is used when records are created and no value for the column has been defined. SQL defaults are different from DataFlex data dictionary default values. The DataFlex default values as implemented in the data dictionary class will be used at data entry time. While the user is entering data, the default is displayed on screen. SQL defaults are used at save time. Data entry has been completed; the user will not see the default value until the record in question is reselected. Both approaches have their merits. The data entry time approach has the advantage of direct feedback, the save time approach has the advantage of data integrity guaranties. You can setup SQL defaults on a column in three different formats: literal, ODBC escape sequence or back-end string.

Since defaults are used when creating records and no value for the column has been specified, they are usually set to a value that indicates the data is unknown. Or they are set to a function that generates the desired information. Defaults are also used to make sure that columns that do not allow null values always have a valid value.

A literal default is set by using a string in single quotes. It should be a valid literal value for the SQL type of the column. An ODBC escape sequence is enclosed in curly brackets {} finally a back-end string is enclosed in square brackets [].

Literal values must be enclosed in single quotes. You can use any literal value that is legal in SQL Server for the type and length of the column.

ODBC escape sequences must be enclosed in curly brackets. The main reason to use ODBC escape sequences rather than back-end strings is that ODBC escape sequences are supported by other drivers. ODBC defines escape sequences for a number of language elements. Two escape sequence types can be used when setting up default values: the Date, time, timestamp and datetime interval literals and the scalar functions. For a detailed discussion of ODBC escape sequences see ODBC Escape Sequences.

Back-end strings are used for any value that is not a literal in quotes and not an ODBC escape sequence. Usually they are used to setup a default scalar function.

The default value of a column depends on the table definition. This definition can be adjusted by using the DF_FIELD_DEFAULT_VALUE attribute. When converting, a configuration file is used that sets up defaults per type to convert. These defaults can be adjusted in the driver configuration file.

Typical examples of setting default values are:

Set_Attribute DF_FIELD_DEFAULT_VALUE iMyFile iMyCharField To "'Unknown'"

Set_Attribute DF_FIELD_DEFAULT_VALUE iMyFile iMyDateField To "{fn current_date()}"

Set_Attribute DF_FIELD_DEFAULT_VALUE iMyFile iMyCharField To "[convert(char(30), CURRENT_USER)]"

The default will be used when creating records. So if we were to have a table MyTable with columns A, B, C and use the code below, we would end up with a new row in MyTable having default values (if any) for columns B and C.

Clear MyTable

Lock

Move “Not a default value” To MyTable.A

SaveRecord MyTable

Unlock

See Also

NULL Values and Defaults


Configuring Null and Default Values for Conversion

When data accessible by DataFlex is converted to a SQL Connectivity Kit a problem arises. DataFlex does not support null and defaults at database level. It is important to setup the null and default behavior correctly when converting. Since allowing nulls and default values are part of a table definition, it can be expensive to adjust these settings after conversion. For that reason the SQL Connectivity Kits allow the user to setup conversion defaults per type. These defaults are setup in an ASCII configuration file.

It is not needed to use the configuration file. In case no configuration is present the Connectivity Kit will use the following scheme:

DATAFLEX TYPE | NULL ALLOWED | DEFAULT
Ascii | No | ""
Numeric | No | 0
Date | No | 1753-01-01
Text | No | ""
Binary | No | 0x0

Next to the default per type, the default table setting to use dummy zero dates can be setup through the configuration file. This can be done by setting DEFAULT_USE_DUMMY_ZERO_DATE. The default set for this configuration file setting will be used when creating a new table through a structure operation (when converting for example).

For a detailed discussion of the Connectivity Kit Configuration file see Driver Configuration.

Recommendations

It is strongly recommended never to allow null values in any type of column. Sometimes it is required to use null values for a certain column. If this is needed, make sure that column is never used as an index segment. The use of null values as index segments is supported, it may give unexpected results.

When converting existing DataFlex data a SQL Connectivity Kit we strongly advise to use the defaults for conversion. That is not to allow null values in any column and to use dummy zero dates for every date column.

See Also

NULL Values and Defaults


Attributes

The DataFlex API defines a number of attributes that give information about a table and its definition. In addition to those attributes, connectivity specific attributes have been added. Attributes that concern the Connectivity Kit can be defined on table, column and index level.

Attributes are documented in the Language Reference. The table below lists the Connectivity Kit specific attributes and the corresponding intermediate file keyword (if any). If you want to use any of these attributes I a program you must include the package of the Connectivity Kit being used. Every Connectivity Kit comes with a package that defines the Connectivity Kits constants, commands and classes.

ATTRIBUTE | INTERMEDIATE FILE KEYWORD
DF_DATABASE_ID |
DF_DATABASE_NUMBER_TYPES |
DF_DATABASE_TYPE_AUTOINC |
DF_DATABASE_TYPE_ID |
DF_DATABASE_TYPE_NAME |
DF_FILE_DATABASE_ID |
DF_FILE_FETCH_ALL_COLUMNS |
DF_FILE_GENERATE_RECORD_ID_METHOD | Generate_Record_ID_Method
DF_FILE_GET_RID_AFTER_CREATE | Get_RID_After_Create
DF_FILE_MAX_ROWS FETCHED | Max_Rows_Fetched
DF_FILE_PRIMARY_INDEX_TRIGGER | Primary_Index_Trigger
DF_FILE_REFIND_AFTER_SAVE | Refind_After_Save
DF_FILE_SQL_FILTER |
DF_FILE_SQL_FILTER_ACTIVE |
DF_FILE_TABLE_CHARACTER_FORMAT | Table_Character_Format
DF_FILE_TABLE_NAME | Database_Name
DF_FILE_USE_DUMMY_ZERO_DATE | Use_Dummy_Zero_Date
DF_FIELD_DEFAULT_VALUE |
DF_FIELD_FETCH_STATE |
DF_FIELD_IS_NULL |
DF_FIELD_NATIVE_TYPE |
DF_FIELD_NATIVE_TYPE_NAME |
DF_FIELD_NULL_ALLOWED |
DF_FIELD_READ_ONLY | Field_Read_Only
DF_FIELD_STORE_TIME | Field_Store_Time
DF_FIELD_TIME |
DF_INDEX_NAME | Index_Name
DF_INDEX_UNIQUE | Index_Unique

Attribute Usage

The attributes that are set for the Connectivity Kit are attributes on database-, table-, column- and index level. The attributes by category are:

Category | Attributes
Database | DF_DATABASE_ID, DF_DATABASE_NUMBER_TYPES, DF_DATABASE_TYPE_AUTOINC, DF_DATABASE_TYPE_ID, DF_DATABASE_TYPE_NAME
Table | DF_FILE_DATABASE_ID, DF_FILE_FETCH_ALL_COLUMNS, DF_FILE_GENERATE_RECORD_ID_METHOD, DF_FILE_GET_RID_AFTER_CREATE, DF_FILE_MAX_ROWS_FETCHED, DF_FILE_REFIND_AFTER_SAVE, DF_FILE_SQL_FILTER, DF_FILE_SQL_FILTER_ACTIVE, DF_FILE_TABLE_CHARACTER_FORMAT, DF_FILE_TABLE_NAME, DF_FILE_USE_DUMMY_ZERO_DATE
Column | DF_FIELD_DEFAULT_VALUE, DF_FIELD_FETCH_STATE, DF_FIELD_IS_NULL, DF_FIELD_NATIVE_TYPE, DF_FIELD_NATIVE_TYPE_NAME, DF_FIELD_NULL_ALLOWED, DF_FIELD_READ_ONLY, DF_FIELD_STORE_TIME, DF_FIELD_TIME
Index | DF_INDEX-NAME, DF_INDEX_UNIQUE

Attributes are used with the Get_Attribute and Set_Attribute command. The parameters for the commands depend on the attribute’s level. See the samples for the attributes for more information on parameter usage.

All attributes in the database category and the DF_FILE_DATABASE_ID attribute from the table category are read only (i.e. they cannot be set).

Structure Versus Non-Structure

The Structure_Start and Structure_End commands are used to mark a table structure update. The Structure_Start command will return a so-called structure handle. This handle must be used in the Set_Attribute and Get_Attribute commands. Next to that there are commands to add and remove columns and indexes (Create_Field, Create_Index, Delete_Field, Delete_Index). Manipulating a table definition inside a structure operation is done in memory. The Structure_End command will execute the adjustments on the physical table in the database. After the Structure_End command completes, the table definition has been permanently adjusted.

Most of the extra attributes can be set within or outside of a structure operation. If set within a structure operation (within a Structure_Start .. Structure_End command block), the setting is permanent after the Structure_End command completes. If set outside of a structure operation, the setting will exist for the duration of the program or until it is re-set.

The way attributes can be set is listed below. This list also contains the attributes that are not SQL Server specific but can be used in a different way than for the embedded database.

The attributes that can only be set inside a structure operation are:

DF_FILE_TABLE_NAME, DF_FILE_USE_DUMMY_ZERO_DATE, DF_FIELD_DEFAULT_VALUE, DF_FIELD_NATIVE_TYPE, DF_FIELD_NATIVE_TYPE_NAME, DF_FIELD_NULL_ALLOWED, DF_INDEX_NAME, DF_INDEX_UNIQUE

The attributes that can only be set outside a structure operation are:

DF_FILE_FETCH_ALL_COLUMNS, DF_FILE_SQL_FILTER, DF_FILE_SQL_FILTER_ACTIVE, DF_FIELD_FETCH_STATE, DF_FIELD_IS_NULL, DF_FIELD_TIME

The attributes that can be set both inside and outside structure operations are:

DF_FILE_RECORD_IDENTITY, DF_FILE_MAX_ROWS_FETCHED, DF_FILE_GENERATE_RECORD_ID_METHOD, DF_FILE_GET_RID_AFTER_CREATE, DF_FILE_OWNER_NAME, DF_FILE_REFIND_AFTER_SAVE, DF_FILE_TABLE_CHARACATER_FORMAT, DF_FIELD_STORE_TIME, DF_FIELD_READ_ONLY


Techniques

Every Connectivity Kit contains a package that contains back end specific definitions and commands. You can use these in DataFlex source code to make your application more back end specific. This might make the program unusable for other database types.

Next to the commands defined in the Connectivity Kit package, you can use Embedded SQL. How to use Embedded SQL is described in the Embedded SQL User’s Guide.

The packages that are part of the Connectivity kit are:

  • MSSQLdrv.pkg for SQL Server

  • DB2_drv.pkg for Db2

  • ODBC_drv.pkg for ODBC

  • DFBTRdrv.pkg for Pervasive.SQL

See Also

User Information Outside .INT File

Opening a Table without Using an Intermediate File

Selective Column Fetching

Using SQL Filters (Constraints)

Using Application Roles

Showing the Employee Photo from the Northwind Sample

Using Alternate Collating Sequences in Pervasive.SQL


User Information Outside .INT File

The SQL Connectivity Kits determine the database server of a table by using the SERVER_NAME setting of the intermediate file of the table. Usually this setting contains database server identification and user login information.

Intermediate files are plain ASCII files that can be viewed by anybody having access to the intermediate file. For this reason, it is preferred not to store the user information in the intermediate file.

Next to security reasons, there may be a need to open tables under different user accounts. If the user information is not stored in the intermediate file, the user account can change without the need for a different intermediate file.

SQL Server NT Authentication

The SERVER_NAME setting for a table using NT Authentication will be something like:

SERVER_NAME SERVER=MySQLServer;Trusted_Connection=yes;DATABASE=MyDb

When using NT authentication you trust that if the user is able to login to NT there are sufficient rights to access the data. In this mode there is no need to change the intermediate file since no user information is stored in the file.

"Normal" Authentication

When using "normal" authentication for the SQL Connectivity Kits, the SERVER_NAME setting for a table will contain user and password information as in the examples below:

SQL Server

SERVER_NAME SERVER=MySQLServer;UID=MyName;PWD=MyPassword;DATABASE=MyDb

DB2

SERVER_NAME DSN=MyDB2Database;UID=MyName;PWD=MyPassword

ODBC

SERVER_NAME DSN=MyDataSource;UID=MyName;PWD=MyPassword

In this case, there is sensitive information in the intermediate file. It would be desirable to remove the user information from the intermediate file for security reasons. The result would be an intermediate file containing a SERVER_NAME setting like:

SQL Server

SERVER_NAME SERVER=MySQLServer;DATABASE=MyDb

DB2

SERVER_NAME DSN=MyDB2Database

ODBC

SERVER_NAME DSN=MyDataSource

In order to open a table that does not contain any user information in the intermediate file a connection should be established before the table is opened.

Establishing a connection is possible by using the Login command. In order to login to the database MyDb on server MySQLServer as user MyName using password MyPassword one would issue the following login command:

SQL Server

Login "SERVER=MySQLServer;DATABASE=MyDb" "MyName" "MyPassword" "MSSQLDRV"

DB2

Login "DSN=MyDB2Database" "MyName" "MyPassword" "DB2_DRV"

ODBC

Login "DSN=MyDataSource" "MyName" "MyPassword" "DB2_DRV"

After this command has been issued, tables containing the server name setting as described above can be opened without having to enter any additional information.

Using Visual DataFlex Tools with "No User Info" Tables

Tables that do not contain any user information in the intermediate file can be used from the Visual DataFlex tools Database Builder, Database Explorer and Studio.

In order to open a "no user info" table in any of the tools, you need to establish a connection before opening the table. To establish a connection, select Database | Login. Choose the appropriate driver. In the server form, enter the same information as is stored in the intermediate file for the SERVER_NAME setting. In case of the SQL Server example above that would be "SERVER=MySQLServer;DATABASE=MyDb". In the user name form enter the user name and in the password form enter the password.

In order to convert tables in a way that results in intermediate files without user information, you need to establish a connection before converting your tables. To establish a connection select Database | Login. See above for further details.

Then, in the conversion wizard enter the server name in the Server form (without the SERVER= or DSN=) and the database name in the Database form (without the DATABASE=). Do not enter information in the User ID or Password forms. Also do not check the use NT Authentication checkbox. Mark the other options as needed for the conversion and press OK.

SQL Server, Leaving out the Database Information

In some environments, an application needs to access data from different databases. The definition of the data (columns, indexes and such) is the same in multiple databases but the information in the tables is different. A set-up like this is quite common in environments where one company runs an administration service for other companies.

It is possible to create a SERVER_NAME setting without the database reference. In that case the database reference needs to be specified when logging in. If we want to be able to open data on database server MySQLServer that has two different databases – MyDb and TheirDB – we would need to create an intermediate file with SERVER_NAME setting only:

SERVER_NAME SERVER=MySQLServer

When we want to open tables in database TheirDb, we need to establish the connection using the login command:

Login "SERVER=MySQLServer" "MyName;DATABASE=TheirDb" "MyPassword" "MSSQLDRV"

The database name is passed as part of the user name to the login command. After this login command has been issued all tables that use the “SERVER_NAME SERVER=MySQLServer” as server name setting in their intermediate file will automatically be opened in database TheirDb.

If we want to connect to database MyDb we would need to issue the login command in the following way:

Login "SERVER=MySQLServer" "MyName;DATABASE=MyDb" "MyPassword" "MSSQLDRV"

After this login command has been issued, all tables that use the "SERVER_NAME SERVER=MySQLServer" as server name setting in their intermediate file will automatically be opened in database MyDb.

Tables that do not have any database information in the intermediate file can also be opened in the Visual DataFlex tools. Like the code sample above you need to enter ";DATABASE=…" after the user ID in the login screen when establishing a connection.

See Also

Techniques


Opening a Table without Using an Intermediate File

SQL Connectivity Kits

It is possible to open a table without using an intermediate file. The general way to do this for a SQL Connectivity Kit is by using the format:

Open "<CKId>:<Schema>#<Table>@<ConnectString>" As hTable

Where:

  • <CKId> is the Connectivity kit identifier (MSSQLDRV, DB2_DRV or ODBC_DRV).

  • <Schema> is the name of the table's schema or owner (optional).

  • <Table> is the name of the table.

  • <ConnectString> is the connect string needed to connect to the database.

Pervasive.SQL

When using the Pervasive.SQL Connectivity Kit in database mode, open a table without using an intermediate file by using the format:

Open “DFBTRDRV:btrv://psqluser@MyPervasiveServer/Order?table=salesp&pwd=secret” as hTable

When using the Pervasive.SQL Connectivity Kit in non database mode, open a table without using an intermediate file by using the format:

Open “DFBTRDRV:<LogName>|<PhysName>.btr” As hTable

Where:

  • <LogName> is table’s logical name as defined in the file.ddf meta database table.

  • <PhysName> is the table’s physical name on disk.

If you have no INT file but converted the table with Recnum support, you need to make this clear to the CK. The way to do this is to add a ‘+’ sign to the end of the base name of the table. Examples of root names that will open tables directly with recnum support are:

MyFile+.BTR

DFBTRDRV:MyFile+

See Also

Techniques


Selective Column Fetching

Selective Column Fetching (SCF) offers a way to programmatically influence the number of columns that are fetched from the back-end. This feature is especially useful when looping through records. It is supported by the SQL Connectivity Kits. Limiting the number of columns that are fetched reduces the amount of data that is sent from the database server to the client, thus improving performance.

There are two levels in which SCF can be controlled. It can be switched ON or OFF at the table level using the DF_FILE_FETCH_ALL_COLUMNS attribute. It can be switched ON or OFF for individual columns using the DF_FIELD_FETCH_STATE attribute.

DF_FILE_FETCH_ALL_COLUMNS

The DF_FILE_FETCH_ALL_COLUMNS table attribute indicates if Selective Column Fetching is ON or OFF for a table. When a table is opened, it will automatically be set to true (all columns are fetched after opening).

When DF_FILE_FETCH_ALL_COLUMNS is set to false, all columns having the fetch state set to false will be cleared. The value in the buffer for the columns that have the fetch state set to true will not be changed.

Setting DF_FILE_FETCH_ALL_COLUMNS to true does not alter any column values.

DF_FIELD_FETCH_STATE

The DF_FIELD_FETCH_STATE column attribute indicates if individual columns are selected or not. There is a special field number keyword to set this attribute for all columns in a table at once: DF_ALL_COLUMNS. When a table is opened, the attribute will automatically be set to true for all columns (all columns are fetched after opening).

Setting the DF_FIELD_FETCH_STATE of a column to false will also clear the column value in the buffer. Setting the attribute to true will not alter the column value in the buffer.

If we would want to fetch column "MySampleColumn" of MyTable only, we would write:

Move MyTable.File_Number To hTable

Field_Map hTable "MySampleColumn" To hColumn

Set_Attribute DF_FILE_FETCH_ALL_COLUMNS Of hTable To False

Set_Attribute DF_FIELD_FETCH_STATE Of hTable DF_ALL_COLUMNS To False

Set_Attribute DF_FIELD_FETCH_STATE Of hTable hColumn To True

Setting DF_FILE_FETCH_ALL_COLUMNS will not alter the individual column settings for the DF_FIELD_FETCH_STATE attribute. This enables the programmer to create maximum efficiency in update loops. Let’s assume we want to update the table MyTable looping through it by MyIndexColumn starting at a given value and updating it when MyTriggerColumn has a certain value. One would program a loop like:

Procedure RunLoop Handle hTable String sSeed String sTrigger

Handle hColumn1

Handle hColumn2

Handle hSomeOtherColumn

Boolean bMyTableFound

String sValue

String sSomeValue

//*** Switch to SCF for two columns

Set_Attribute DF_FILE_FETCH_ALL_COLUMNS Of hTable To False

Set_Attribute DF_FIELD_FETCH_STATE Of hTable DF_ALL_COLUMNS To False

Field_Map hTable “MyIndexColumn” To hColumn1

Set_Attribute DF_FIELD_FETCH_STATE Of hTable hColumn1 To True

Field_Map hTable “MyTriggerColumn” To hColumn2

Set_Attribute DF_FIELD_FETCH_STATE Of hTable hColumn2 To True

//*** Determine number of other column to update

Field_Map hTable “MyOtherColumn” To hSomeOtherColumn

//*** Seed the buffer and loop

Clear hTable

Set_Field_Value Of hTable hColumn2 To sSeed

VFind hTable 1 GE

Move (Found) To bMyTableFound

While (bMyTableFound)

Get_Field_Value Of hTable hColumn2 To sValue

If (sValue = sTrigger) Begin

//*** Switch to normal fetching

Set_Attribute DF_FILE_FETCH_ALL_COLUMNS Of hTable To True

//*** Update the record

Begin_Transaction

//*** Update record

Reread hTable

Set_Field_Value Of hTable hColumn2 To sNewValue

Get CalculateSomeValue hTable To sSomeValue

Set_Field_Value Of hTable hSomeOtherColumn To sSomeValue

SaveRecord hTable

Unlock

End_Transaction

//*** Switch to SCF

Set_Attribute DF_FILE_FETCH_ALL_COLUMNS Of hTable To False

End

VFind hTable 1 GT

Move (Found) To bMyTableFound

End

//*** Switch to normal fetching

Set_Attribute DF_FILE_FETCH_ALL_COLUMNS Of hTable To True

End_procedure // RunLoop

SCF ERROR HANDLING

Trying to set the value of a column that has its fetch state set to false, in a table for which the DF_FILE_FETCH_ALL_COLUMNS state is false, will result in error 12318 (CLIERR_ CANTCHANGEINACTIVECOLUMN). This error cannot be switched off.

Trying to set the fetch state of the RECNUM column to false can result in error 12317 (CLIERR _CANTSETRECNUMINACTIVE). This error will only be generated when the REPORT_ACTIVE_COLUMN_ERRORS global driver attribute is switched ON.

Trying to get value of a column that has its fetch state set to false can result in error 12319 (CLIERR _ FIELDISINACTIVE). This error will only be generated when the REPORT_ACTIVE_COLUMN_ERRORS global driver attribute is switched ON. If the global driver attribute is switched off, the column value that is currently in the buffer is returned.

The global driver attribute REPORT_ACTIVE_COLUMN_ERRORS can be set in the driver configuration file “mssqldrv.int” by using the keyword REPORT_ACTIVE_COLUMN_ERRORS. It can be set to ON by giving it a non-zero value or to OFF by giving it the zero value. By default the attribute is switched off.

It is also possible to set the attribute from within a program by using the DRVR_REPORTACTIVECOLUMNERRORS attribute with the CLI_Set_Driver_Attribute and CLI_Get_Driver_Attribute commands.

PERFORMANCE

Selective column fetching will reduce the amount of data that travels over the network and will increase the speed of a program accessing this data. In lab testing SQL Server we found that the impact on text columns is the largest. The default SQL Server type to map a DataFlex text column to is now SQL Server text, it used to be SQL Server varchar. The table below shows the results of our lab test on two tables. One table converted the “old way” using varchar, one table converted the “new” way using text. On both tables we ran a loop that fetched all columns and one that fetched all but the DataFlex text columns:

Varchar Text Difference

Loop fetch all columns 214 270 56 – 26%

Loop fetch selected columns 209 120 89 – 43%

Difference 5 – 2% 150 – 56%

Be aware that the actual numbers in the table above do not have a big meaning. Changing the environment will change the numbers. The differences between the numbers are important. The differences show that using text column is slower when fetching all columns but much faster when not fetching all columns.

Since in a lot of situations the text columns are never used, we provide a helper class to easily switch fetching all text columns of all open tables OFF and back ON again. The class is called cTableColumnFetchHelper and can be found in cTableColumnFetchHelper.pkg.

See Also

Techniques


Using SQL Filters (Constraints)

SQL Filters can be used in the SQL Connectivity Kits. If you want to filter the records processed by a function, you can check for the record contents in the DataFlex code. If we want to show all order detail records with a quantity ordered greater than or equal to 4, we would do something like:

Procedure ShowDetails

Open OrderDtl

Clear OrderDtl

Repeat

Find Gt OrderDtl By Index.1

If (Found And OrderDtl.Qty_Ordered >= 4) ;

Showln OrderDtl.Order_number ", " ;

OrderDtl.Detail_number ", " ;

OrderDtl.Qty_ordered

Until (Not(Found))

Close OrderDtl

End_Procedure // ShowDetails

The loop above will work but may be a bit slow. The loop will process all records in the Order Detail table. Using filters, you can limit the number of records that need to be processed. If we rewrite the code above to use SQL filters, we would get something like:

Procedure ShowDetailsFilter

Handle hTable

String sFilter

Open OrderDtl

Move OrderDTl.File_number To hTable

Set_Attribute DF_FILE_SQL_FILTER Of hTable ;

To "OrderDtl.Qty_ordered >= 4"

Set_Attribute DF_FILE_SQL_FILTER_ACTIVE Of hTable To True

Clear OrderDtl

Repeat

Find Gt OrderDtl By Index.1

If (Found) ;

Showln OrderDtl.Order_number ", " ;

OrderDtl.Detail_number ", " ;

OrderDtl.Qty_ordered

Until (Not(Found))

Set_Attribute DF_FILE_SQL_FILTER_ACTIVE Of hTable To False

End_Procedure // ShowDetailFilter

The SQL filter settings are set at table level. We recommend using SQL filters under controlled finding conditions only. When such conditions apply, one will switch ON filtering, process records and switch off filtering again.

When using SQL filters in data dictionary constraints, be aware that navigating between application-views requires the SQL filter to be reset.

See Also

Techniques


Using Application Roles in SQL Server

SQL Server accommodates two types of roles in its security system: database roles and application roles. Application roles are used to setup security at application level rather than at database level. Usually the application has more rights on the database since actions on the database are controlled. The user only has restricted rights on the database. This prevents users from making unwanted changes to the database using tools such as SQL Server Query Analyzer.

An application switches to an application role after a connection has been established. The way to do this from a DataFlex application is to call the stored procedure sp_SetAppRole. To call a stored procedure you must use Embedded SQL. The SetAppRole procedure below will switch the connection’s security role to an application role:

//***

//*** Procedure: SetAppRole

//*** Purpose : Set the application to use the application role

//*** Arguments:

//*** - sAppRole The application role name

//*** - sPassword The password for the application role

//*** - hFile The handle of the SQL Server table already open

//***

Procedure SetAppRole String sAppRole String sPassword Handle hFile

Handle hoSQL

Handle hdbc

Handle hstmt

//*** Create the handle manager, we want to call a stored

//*** procedure using ESQL

Get Create U_cSQLHandleManager To hoSQL

If (hoSQL <> 0) Begin

//*** Connect

Get SQLFileConnect Of hoSQL hFile To hdbc

If (hdbc <> 0) Begin

Get SQLOpen Of hdbc To hstmt

If (hstmt <> 0) Begin

Send SQLSetProcedureName Of hstmt "sp_SetAppRole"

Send SQLSetArgument Of hstmt 1 sAppRole

Send SQLSetArgument Of hstmt 2 sPassword

Send SQLSetArgument Of hstmt 3 "None"

Send SQLCall Of hstmt

Send SQLClose Of hstmt

End

Else ;

Error 775 "Unable to open a statement handle."

Send SQLDisconnect Of hdbc

End

Else ;

Error 776 "Unable to connect."

Send Destroy Of hoSQL

End

Else ;

Error 777 "Unable to create Embedded SQL handle manager."

End_procedure // SetAppRole

For more information on application roles, see the SQL Server documentation. For more information on Embedded SQL, see Using Embedded SQL.

See Also

Techniques


Showing the Employee Photo from the Northwind Sample

The sample database Northwind that is installed with SQL Server contains a table called Employees that stores a photograph of the employees in an image column. We will extract the information from that column and store it as a bitmap in a disk file. We use the bitmap format because that is the format used to store the photograph in the table.

The data stored in the Employees.Photo column contains 79 bytes of extra information after which the bitmap is stored. These 79 bytes are ignored, the rest of the column is written to a disk file. This “bitmap header” probably is information from the COM object used to create and manipulate the bitmap. The purpose of this sample is showing how to get information from large columns. This is why we ignore the header and concentrate on the essentials. We extract the information from the Photo column by using the Embedded SQL SQLGetData function.

We can use the described technique in a Visual DataFlex view to show the photo next to columns from a record. The photo is displayed by using a BimtapContainer object. The other columns of the table are shown through normal dbForm objects.

In order to be able to use the column in dbForm objects we need to create an intermediate file for the Employees tables. We use the Connect Wizard in Database Builder for this. After connecting to the table a view was created in Visual DataFlex Studio. In this view the procedure Entry_Display of the EmployeedID dbForm was augmented in the following way:

DRIVER_NAME MSSQLDRV

SERVER_NAME SERVER=(local);Trusted_Connection=yes;DATABASE=NorthWind

DATABASE_NAME Employees

SCHEMA_NAME dbo

PRIMARY_INDEX 1

GENERATE_RECORD_ID_METHOD NONE

TABLE_CHARACTER_FORMAT ANSI

USE_DUMMY_ZERO_DATE YES

INDEX_NUMBER 1

INDEX_NAME PK_Employees

INDEX_NUMBER 2

INDEX_NAME LastName

INDEX_NUMBER 3

INDEX_NAME PostalCode

After creating the intermediate file, an fd file was generated when adding the table to the DataFlex filelist in Database Builder (Filelist | New Entry). A Data Dictionary was generated, and a view created in Visual DataFlex Studio. In this view the procedure Entry_Display of the EmployeedID dbForm was augmented in the following way:

Procedure Entry_Display Integer iFile Boolean bDoAll

Forward Send Entry_Display iFile bDoAll

Send ShowEmployeeBitmap

End_procedure // Entry_Display

The ShowEmployeeBitmap procedure extracts the bitmap from the Employees table on SQL Server using Embedded SQL. It does this by getting 1KB chunks from the column and processing those chunks.

Procedure ShowEmployeeBitmap

Integer iEmployeeID

Handle hoESQLManager

Handle hdbc

Handle hstmt

Integer iFetchResult

String sChunk

Boolean bTruncate

Get Field_Current_Value Of Employee_DD FIELD Employee.EmployeeID ;

To iEmployeeID

If (iEmployeeID <> 0) Begin

Get Create U_cSQLHandleManager To hoESQLManager

If (hoESQLManager > 0) Begin

//*** Create a connection to the SQL datasource

Get SQLFileConnect Of hoESQLManager Employee.File_number ;

To hdbc

If (hdbc <> 0) Begin

Get SQLOpen Of hdbc To hstmt

If (hstmt <> 0) Begin

Send SQLExecDirect Of hstmt ("SELECT photo FROM Employees Where EmployeeID =" * String(iEmployeeID))

Move True To bTruncate

Repeat

Get SQLFetch Of hstmt To iFetchResult

If (iFetchResult <> 0) Begin

Send ClearBitmapFile

Repeat

Get SQLGetData Of hstmt 1 1024 To sChunk

Send AddChunkToBitmapFile ;

sChunk bTruncate

Move False To bTruncate

Until (SQLResult = 0)

Send ShowPhotoFromBitmapFile

End

Until (iFetchResult = 0)

Send SQLCLose Of hstmt

End

Else ;

Error 997 "Unable to create a statement handle."

Send SQLDisconnect Of hdbc

End

Else ;

Error 998 "Unable to create a handle to a connection."

Send Destroy Of hoESQLManager

End

Else ;

Error 999 "Cannot create an Embedded SQL Manager object."

End

Else ;

Set Bitmap Of oEmployeeBitmap To ""

End_Procedure // ShowEmployeeBitmap

Procedure ClearBitmapFile

Direct_Output Channel 1 "c:\project\empphoto.bmp"

End_procedure // ClearBitmapFile

Procedure AddChunkToBitmapFile String sChunkInHex Boolean bTruncate

Char cBinChar

String sBinChar

Integer iBinChar

Integer iChunkLen

Integer iCount

Integer iStart

Move (Length(sChunkInHex)) To iChunkLen

If (bTruncate) ;

Move 79 To iStart

Else ;

Move 1 To iStart

For iCount From iStart To (iChunklen / 2)

Move ("$" + Mid(sChunkInHex, 2, ((iCount - 1) * 2) + 1)) ;

To sBinChar

If (sBinChar <> "$") ;

Write Channel 1 (Character(Integer(sBinChar)))

Else ;

Move iChunkLen To iCount

Loop

End_procedure // AddChunkToBitmapFile

Procedure ShowPhotoFromBitmapFile

Close_Output Channel 1

Set Bitmap Of oEmployeeBitmap To "c:\project\empphoto.bmp"

End_procedure // ShowPhotoFromBitmapFile

Embedded SQL return binary columns as hexadecimal values. The procedure AddChunkToBitmap converts the hexadecimal value of the column to the “real” value.

The resulting view looks like this:

The purpose of this section was to demonstrate how to get at large data (blob’s, clob’s and the like). It does not use the best or most efficient way to show the picture in the view.

See Also

Techniques


Using Alternate Collating Sequences in Pervasive.SQL

Pervasive.SQL sorts indexes. ACSes make it possible for characters with accents and other inflections to be sorted like there is no accent. You can make up your own collating sequence.

By default, Pervasive.SQL uses the ASCII table to sort string segments in an index and binary values for sorting numeric data. Using an ACS, you can change the collating sequence for string fields only. Fields that are known as Overlap fields to DataFlex are sorted as strings.

Creating a table, converting an existing table to Pervasive.SQL, or restructuring a table causes the Connectivity Kit to create indexes. When an ACS is active at that moment, it will use the ACS for each created index. An ACS cannot be dropped by itself. To drop an ACS, you will have to drop the complete index and recreate it when no ACS is active for the Connectivity Kit.

Creating an ACS File

Before you can use an ACS, you need to define what the sorting should be for an ACS. In order to do that, you need to create an ACS file, which contains all information about a collation sequence.

An ACS file has a static length of 265 characters. The first byte identifies the file as an ACS and should contain the value 0xAC (hexadecimal) or 172 (decimal). The next 8 bytes should be used to give the ACS a name. If you create an ACS for German, you might call it GERMAN. Unused space should be set to spaces. This leaves 256 bytes. This area we call the collating table. In the bytes of the collating table, you put the sort weight for each character. The weight (a value between 0 and 255) determines where a character appears when a value is being sorted.

If for example you want to have the character ë (ASCII 137) to sort the same as the character e (ASCII 101) you put the value 101 in Position 146 (137 plus the 9-byte header) of our file. This way, you can build a completely new collating sequence for our indexes.

You can also define that control characters (ASCII 0 to 31) in a string should be sorted at the end. To do this, you put the values 0xE0 through 0xFF into the first 32 bytes of your collating table.

Format of an Alternate Collating Sequence File

Byte Range | Description
0 | Signature byte, always 0xAC (172)
1-8 (8 bytes) | 8-byte name that identifies the table.
9-264 | (256 bytes) Collating table

Making an ACS Active

Once an ACS file has been created, you can make it active. To make it active, put a line in your DFBTRDRV.INT file stating:

ACS “MYACS.ACS”

The Connectivity Kit will read the DFBTRDRV.INT file when it is loaded. Any index created by the Connectivity Kit when an ACS is active will be sorted by the collating table specified in the ACS file. If the table is used later without the ACS being active, it will still be sorted using the ACS that was active when the table was being created.

Using an ACS with Case-Insensitive Index Segments

An ACS is only used on index segments that are case-sensitive. When the flag for a case-insensitive segment is been used, the segment will sort following the ACSII collating sequence. If you want case-insensitive index segments to be sorted by an ACS too, you need to specify an extra ACS for this. You can do this by putting a line into your DFBTRDRV.INT file stating:

ACS_UPPER “MYUPACS.ACS”

It will use this ACS for every string-based index segment.

Restructuring a File

When a table is being restructured, the Connectivity Kit will try to reuse the ACS an index was using before. This means that restructuring an existing Pervasive.SQL table will keep its original ACS no matter whether you have an active ACS or not.

Switching the ACS of an Index

To switch the ACS an index is using, you will have to drop every index that is using the ACS, reopen the table with the new ACS active, and recreate the indexes.

If you are adding an index and the name of the active ACS is the same as the name of an ACS already in use by the table, then the ACS already in use will be used. It does not check whether the contents of the ACS are different; it only checks the name of the ACS.

Removing the ACS of an Index

To delete the ACS an index is using, you will have to drop every index that is using the ACS, reopen the table with no ACS active, and recreate the indexes.


Transactions

This chapter discusses the way transactions and locking are handled by Connectivity Kits. The chapter starts with a small introduction to concurrency issues, discuss the DataFlex programming language aspect then it will go into details of the supported database formats.

See Also

Concurrency

Transactions and Locking in Visual DataFlex

Transactions and the SQL Server Connectivity Kit

Transactions and the ODBC Connectivity Kit


Concurrency

Concurrency is the ability of multiple users to access and modify data simultaneously and is of vital importance in any database environment. The database should handle multiple users accessing the database simultaneously in a correct way. The means to achieve this are transactions and locking.

Transactions

A transaction is a unit of work that is done as a single atomic operation. Transactions either succeed or fail as a whole. For example consider a transaction that transfers money from one bank account to another. This involves withdrawing money from one account and depositing the money in the other account. It is important that both actions occur, it is unacceptable for one action to succeed and the other to fail. A database that supports transactions is able to guarantee that either both steps succeed or both steps fail.

The transaction support of a database system must have the ACID (Atomicity, Consistency, Isolation and Durability) properties.

  • Atomicity. A transaction must be an atomic unit of work.

  • Consistency. When completed a transaction should leave the database in a consistent state. Internal data structures such as indexes must be correct at the end of the transaction.

  • Isolation. Modifications made by the current transaction must be isolated from modifications made by other concurrent transactions. A transaction should not be able to “see” intermediate results of another transaction.

  • Durability. After a transaction has completed its effects are permanent.

Transactions are started by a program, the program then manipulates data in the database. Eventually the transaction is committed, or rolled back. A commit will make all changes made by the transaction permanent. A rollback will remove all changes made by the transaction just like the transaction was never started.

Most databases support all of the transaction properties. The Isolation property usually can be set up to be less restrictive. So-called Isolation Levels have been defined. The lowest level will make intermediate results available to other transactions, the highest level will not. There is an inverse relation between Isolation Level and concurrency. The higher the Isolation Level, the lower the concurrency.

Locking

A lock guarantees exclusive access to the object on which it is applied. All databases that support multi user access use some form of locking. Locking is used to enforce the Isolation transaction property. Although there are a number of variants at implementation level basically databases support the following lock granularities: row locking, page locking and table locking.

Usually a database supports one or more of the lock granularities or uses a mechanism that will automatically select the best locking granularity for the task at hand. There is an inverse relation between lock granularity and concurrency. The smaller the granularity, the bigger the concurrency. If for example we have a table with 10 rows made up of 5 pages, each page having 2 rows, 10 users can simultaneously lock a row, 5 users can simultaneously lock a page and only one user can lock the table.

The use of locks can introduce a side effect known as a deadlock. A deadlock is a situation where two, or more, transactions are waiting on each other’s locks to be released. Transaction A waits for B and B waits for A. In a deadlock situation transactions wait indefinitely, this is an unacceptable situation. The database system must either prevent deadlocks from happening or detect deadlocks when they happened and resolve that situation.

The scenario below gives a sample of a deadlock situation with two transactions. The sample uses record locking. In this case, the lock must be part of the find operation. One can only lock a record after it has been found. To indicate this special type of find we use XFind.

TRANSACTION A | TIME | TRANSACTION B
- |  | -
XFind R1 | T1 | -
- |  | -
- | T2 | XFind R2
- |  | -
XFind R2 | T3 | -
Wait |  | -
Wait | T4 | XFind R1
Wait |  | Wait
Wait |  | Wait

If the above situation occurs, the two transactions are waiting for each other indefinitely. This is an unacceptable situation so the DBMS either needs to prevent deadlocks from happening or detect when they happen and resolve that situation.

There are deadlock avoidance strategies. The native DataFlex database uses one of these strategies. Most database systems however use a deadlock detection and resolving strategy. Deadlock can be resolved by choosing a victim transaction in the list of deadlocked transactions. The victim is then stopped by issuing a rollback. This will free the locks claimed by the victim transaction thus allowing other transactions to obtain those locks and continue.

It is important to understand that deadlocks are not a programming error. It is a situation that can occur in certain environments. It is the application programmer’s responsibility to handle deadlocks in a proper way. Application programmers typically handle deadlock errors in two ways, one is to report an error to the user and let the user re-enter the information. The other is to automatically retry the transaction a designated number of times.

Again, deadlock is not a programming error. It is a condition that can occur in a certain environment. It depends on the application and database back-end what the chance is for deadlock to occur. Usually this chance is very small. Nevertheless, application programmers should handle deadlock no matter how small the chances are for it ever occurring.

See Also

Transactions


Transactions and Locking in Visual DataFlex

Visual DataFlex programs will alter data in tables using one of two methods. Either they will:

  • use data-dictionaries (DDOs); or,

  • manually code transactions in their applications using commands. This method is usually referred to "procedural".

All table changes in DDOs are handled through two messages, Request_Save and Request_Delete. Using DDOs greatly simplifies transaction handling. When you use DDOs, transaction support is built in (in fact it is required).

Manual methods include using the traditional commands Save, Saverecord, Delete, Lock, Reread, Unlock, Begin_Transaction, End_Transaction, and Abort_Transaction. Depending on the applications coding logic, changes may be required to make an application work properly with transactions. Even if a legacy application works properly with transactions you may want to make changes in your code to take full advantage of the transaction handling.

If you have an application that uses DDOs or DSO, you will want to refer the section titled Transaction and Data-Dictionaries.

If you have applications that do not use DDOs or DSO, you should review Transactions and Locking using the Command Language.

See Also

Transactions


Transactions and Locking Using the Command Language

The DataFlex programming language supports a number of commands to define transactions and use locking. These commands are:

  • Begin_Transaction to define the beginning of a transaction

  • End_Transaction to commit a transaction

  • Abort_Transaction to rollback a transaction

  • Lock to lock the database

  • Reread to lock the database and refresh all active buffers

  • Unlock to unlock the database

Transactions support the ACID properties; this makes programming a system that supports transactions more simple. For example, suppose we have a restriction in our application that we can only order items that are in stock. In a non-transaction system this condition would have to be checked before trying to save the order. In a transaction system however one can start the transaction, then start saving the rows that make up the order. If somewhere along the way the condition is not met, issue an error, which will return the database in the state it had before starting the transaction. If the condition is met for every row, issue an End_Transaction thus committing the transaction. Using the transaction commands to define transactions is referred to as doing explicit transactions.

Errors in a Transaction

Because transactions must support Atomicity, errors that occur during a transaction will force a rollback of the transaction. When the error occurred during an explicit transaction, control will jump to the next line of the End_Transaction command. This behavior of transactions results in a minimal use of the Abort_Transaction command. Transactions are usually rolled back because some error occurred, since the occurrence of an error results in a rollback, there is no need to explicitly use the Abort_Transaction command in such a case.

The only error that is an exception to this rule is the DFERR_LOCK_TIMEOUT (4106) error. If this error occurs, the program will check the retry setting and if a retry must be done jump to the beginning of the (implicit or explicit) transaction. The number of retries can be set by using the Set_Transaction_Retry command. If the object oriented programming style is used the message Verify_Retry will be send to the object where the transaction is defined. This function can return zero in which case the transaction will be retried, a non-zero return value will stop the retry. If the logic loops through all its retries and it still gets a time out error, the timeout error will be treated as any other error would.

Implicit transactions will not be aborted when an error occurs. Instead the flow of the program will continue on the next line. Since implicit transactions were designed for compatibility reasons, the behavior is the same as it was before transactions were introduced to DataFlex. Some database drivers may not be able to support implicit transactions.

Please note that explicit transactions will always be aborted when an error occurs no matter how the DF_TRANABORT_ONERROR attribute is set. Data sets and Data dictionaries automatically use explicit transactions. Setting the DF_TRANABORT_ONERROR attribute has no effect on Data Set / Data Dictionary based applications. They always use explicit transactions.

Lock Granularity

The Embedded Database uses a Visual DataFlex specific method for locking. This method is not supported by other database systems. Issuing a lock can therefore result in different behavior depending on the database system in use.

The Embedded Database supports table level locking only. This means that one and only one transaction can have a table locked at any given time. Most other database systems support row level locking only. In those systems there can be multiple concurrent transactions that have rows in one table locked at a given time. A further difference in table and row locking is the moment the actual lock is done. When using table locking, the table is locked the moment the lock is issued by the program. With row or page locking however, the row or page can only be locked after it, or a row on it, has been found. So row or page locking systems lock while rows are being found in a transaction. This is a conceptual difference.

Some legacy DataFlex programs misuse the lock behavior of DataFlex to guarantee exclusive access to certain resources. Let’s assume we want to write to an ASCII disk file from a DataFlex program and (mis)use the DataFlex lock mechanism to ensure only one DataFlex program writes to the file at any given time. If the underlying database changes to a row-locking database, this logic will no longer work.

See Also

Transactions and Locking in Visual DataFlex

Transactions


Transactions and Data-Dictionaries

This discussion applies to the Data-Dictionaries and their predecessor, Data sets. The term Data-Dictionary or DDO will be used to refer to both technologies.

DDOs alter tables using two methods, Request_Save and Request_Delete. Both methods use transactions (in fact they require than your tables support transactions) and fully support all of the ACID property requirements. These methods both operate as follows:

  1. Method starts (Request_Save or Request_Delete)

  2. A Begin_Transaction is executed (unless a transaction is already started)

  3. Table data is reread and locked as needed. If table locking is used, all tables that participate in the save or delete are locked. If row (record) locking is used, rows are locked as they are reread.

  4. Data is validated, processed and table columns are updated

  5. If any error occurs, at any time, the error is handled as follows:

  • Execution of the current method is stopped

  • The transaction is rolled back and aborted

  • All tables and rows are unlocked and the transaction is ended

  • The error is reported (after the unlock)

  • The Err indicator is set to True

  • Control is returned to the method that called the request method or if a transaction was already started, to the line following the End_Transaction.

Note that this applies to all errors. If the runtime encounters any unexpected error, this process is triggered. If the developer generates an explicit error with the Error command (typically done within the events Validate_Save or Validate_Delete), the process is triggered.

  6. If no errors occur

  • The save or delete is completed,

  • The transaction is committed (unless the request was already within a transaction).

  • All tables and rows are unlocked and the transaction is successfully ended (unless the request was already within a transaction).

  • Control is returned to the method that called the request method

Errors in a DDO Transaction

The error rollback is a very simple process. If an error occurs, execution stops, the transaction is rolled back, and the request method is completed. While this is simple, it is powerful and has the following implications.

  • A Request_Save or a Request_Delete may change many rows from many tables. For example a delete cascades and deletes rows in descendant tables causing hundreds of rows to be deleted and hundreds of parent rows to be altered. If an error occurs, all of these changes are rolled back.

  • If you wish to stop a transaction inside of a DDO, use the error command. It is not expected that you will ever use the Abort_Transaction command within a DDO.

  • The event methods Validate_Save and Validate_Delete, were created to provide a place for a developer to check for any errors and to generate errors as needed. There is nothing stopping you from declaring an error in any DDO event (e.g. Update, Backout, Save_Main_File). Any error generated at any time within the transaction will properly abort the transaction.

  • Once an error is encountered within a method, none of the other commands within that method (or the methods that called this method) are executed. The rollback occurs, the error is generated and control is returned to the method that made the request. For example, in the sample below, the code in the function that occurs after the error command can never be executed.

Function Validate_save Returns Integer

Error 300 “Sorry, no save”

// If an error occurred, this code never is executed

Showln “You will never see me”

// We don’t need to return a value, the error triggers the stop

End_Function // Validate_save

  • Error reporting is always deferred until the transaction is rolled back and all locks are removed. You can, therefore, execute an error within a DDO transaction without worrying that the error will be reported when tables are locked.

Grouping Multiple DDO Saves or Deletes

If you wish to group several DDO Request_Save or Request_Delete operations within a single transaction you can group them using Begin_Transaction and End_Transaction as follows:

Begin_transaction

Send Request_save Of hMyDDO1

Send Request_save Of hMyDDO2

End_transaction

If an error occurs in either DDO transaction both transactions are rolled back and execution resumes at the line following the End_Transaction.

Note that you should never use a Lock, Reread or Unlock command to group DDO transactions.

See Also

Transactions and Locking in Visual DataFlex

Transactions


Transactions and the SQL Server Connectivity Kit

The SQL Server Connectivity Kit allows DataFlex programs to access data in Microsoft SQL Server databases. SQL Server is a high performance, Client/Server relational database management system (RDBMS). SQL Server runs on Microsoft Windows Server-based networks and can be installed as a desktop database system on a Window Workstation. SQL is used to access data in a SQL Server database.

Transactions and Locking

SQL Server fully supports the ACID transaction properties. Next to the normal rollback facilities SQL Server also supports so called roll forward functionality. SQL Server supports all Isolation Levels. The Connectivity Kit will always use the Read Uncommitted isolation level. Transactions in SQL Server are logged. The SQL Server database system can recover from system failures.

The lock granularity used by SQL Server is row (or record) locking. It is possible that the database manager replaces multiple row locks with a single page or table lock, this is called lock escalation. Lock escalation is implemented in several database platforms. If a lot of records on a page or table are locked the overhead of administrating the locks gets so big that it is cheaper and/or faster, to escalate the lock to lock an entire page or table. In SQL Server three different types of lock are possible:

  • Share – Other transactions are limited to read-only access

  • Update – Other transactions are limited to read-only access provided they do not declare an intention to update the row. This type of locking is known as intent locking, the transaction tells the database manager to lock a row because it intents to update the data in the row.

  • Exclusive – Other transactions cannot access the data at all except those transactions that use an Isolation Level of Read Uncommitted.

SQL Server will place exclusive locks on rows that are inserted, updated or deleted. The SQL Server Connectivity Kit uses the Update lock provided by SQL Server. This type of lock is applied by using a special form of the SQL Select statement. The statement uses a so-called update clause. Update locks are placed while finding rows in a table. Once the row is actually updated, the lock will transform into an exclusive lock.

The moment at which a lock is applied is different from the moment the native DataFlex database acquires a lock. In native DataFlex a lock is acquired when the lock command is issued. In SQL Server locks are acquired as data is read in a locked state.

Deadlock

Since SQL Server uses row locking, deadlock can occur. SQL server will periodically scan sessions waiting on a lock. If in such a scan a session is detected that was waiting in the previous periodic scan, a deadlock detection search is started. If deadlock is detected the least expensive transaction to undo is chosen as deadlock victim. This victim transaction is rolled back. When the rollback occurs, the locks are released thus offering other transactions the possibility to proceed. The rolled back transaction (application) will get notified of the event by receiving the deadlock notification error. It is possible for a transaction to “volunteer” as victim by setting the deadlock priority. The SQL Server Connectivity Kit does not use this attribute. Next to deadlock detection, SQL Server also supports a configurable lock timeout. If a lock timeout occurs the transaction trying to acquire the lock will be rolled back and is notified by receiving the timeout notification error. The SQL Server Connectivity Kit will report both these errors in the same way, since they result in the same behavior for the transaction involved. The error is passed to DataFlex as DFMSSQLERR_DEADLOCK_OR_TIMEOUT (12303).

The SQL Server Connectivity Kit does not pass the DFERR_LOCK_TIMEOUT (4106) error to DataFlex. When a lock timeout occurs, the transaction will not be automatically retried. Since SQL Server uses record locking, a lock timeout error can occur at any time during a transaction. If the DFERR_LOCK_TIMEOUT error would be passed, the runtime would retry the transaction, jumping to the Begin_Transaction command. If the transaction was “well underway” at the moment the lock timeout occurs, variables and properties used in the transaction will have changed. An automatic retry would not give the desired result; a transaction rollback does not restore variables and properties to their original value. This situation cannot occur when using DataFlex data; Begin_Transaction will do all locking that will ever be done in a transaction so it is safe to automatically retry transactions when using DataFlex data.

It is the programmer’s responsibility to handle deadlock or lock timeouts. The DataFlex programmer can check for the error condition and act upon it. The code below shows a sample of retrying the transaction 9 times.

Procedure Retry9TimesWhenDeadlockOrTimeout

Integer bAborted

Integer bRetry

Integer iRetryCount

Repeat

Send InitializeForTransaction

Begin_Transaction

Send DoSomeSQLServerUpdates

End_Transaction

Get_attribute DF_TRANSACTION_ABORT To bAborted

If (bAborted And ;

(LastErr = DFMSSQL2ERR_DEADLOCK_OR_TIMEOUT)) ;

Move (True) To bRetry

Else ;

Move (False) To bRetry

Increment iRetryCount

Until ((Not(bRetry) Or (iRetryCount > 10))

If (bAborted) ;

SendInformUser LastErr

End_procedure // Retry9TimesWhenDeadlockOrTimeout

See Also

Transactions


Transactions and the Pervasive.SQL Connectivity Kit

Pervasive’s MicroKernel Database Engine (MKDE) is a record management system that offers client server facilities to applications.

Transactions and Locking

Pervasive.SQL supports two types of transactions, exclusive and concurrent. Exclusive transactions use table level locking, concurrent transactions use row level locking. Pervasive.SQL fully supports the ACID transaction properties.

The moment at which a lock is applied is different from the moment the native DataFlex database acquires a lock. In native DataFlex a lock is acquired when the lock command is issued. In Pervasive.SQL locks are acquired as data is read. In order to simulate the DataFlex behavior, the Connectivity Kit supports the EXPLICIT_LOCKING setting. If set to true the Connectivity Kit will lock active records immediately when the lock command is issued.

Explicit locking involves extra find operations on the open tables. Pervasive.SQL acquires a lock when a find operation is done. In order to force the lock, a find must be done. In case of concurrent transactions the Connectivity Kit will re-find all active records. In case of explicit transactions, it will re-find all active records and for the tables that do not have an active record, it will find the first (physical) record in the table.

Combining the two settings the Connectivity Kit supports four different modes:

EL / TT Combination Mode | Behavior
I (off / exclusive) | Tables are locked on the first find in the table after lock command is issued.
II (off / concurrent) | Records are locked as they are found in the table.
III (on / exclusive) | Tables are locked the moment the lock command is issued. This is compatible with the native DataFlex database.
IV (on / concurrent) | Active records are locked the moment the lock command is issued. Consecutive find operations will lock records as they are found.

Which of the four modes should be used depends on the application and the number of users. Tables locks (exclusive transactions) should be used in processes that involve a lot of rows of the table. Row locking (concurrent transactions) should be used in most other cases. If the application needs explicit locking depends o the assumptions made in the transactions. The most likely modes to be used are mode II and III.

The Pervasive.SQL API offers a number two possible ways to lock, wait locking and nowait locking. When wait locking is used, the lock attempt will only return after success or if it has been timed out or chosen as deadlock victim. When nowait locking is used, the lock attempt will immediately return, no matter if it succeeds or not. The DataFlex Connectivity Kit for Pervasive.SQL uses nowait locking. A timeout / delay mechanism is implemented in the Connectivity Kit itself. The mechanism can be set up through the attributes DF_LOCK_TIMEOUT and DF_LOCK_DELAY.

If the Connectivity Kit detects a timeout when trying to lock, it will generate the DFERR_LOCK_TIMEOUT (4106) error. Whenever this error is generated in a transaction the automatic retry mechanism will be started. In case mode III is used, this is no problem. In all other cases it is possible that the transaction is already “well underway” when the error occurs. Variables, properties used in the transaction may have changed. Make sure you reset the variables and properties to the value they had at transaction begin. A good place to trap the retry and reset variables and properties is the Verify_Retry message send in an object oriented environment.

Deadlock

The DataFlex Connectivity Kit for Pervasive.SQL uses nowait locking. Deadlocks will never occur because transactions never wait for locks to succeed. This is handled at Connectivity Kit level, the Pervasive.SQL mechanism for timeout and deadlock does not apply to transactions using nowait locking.

See Also

Transactions


Transactions and the DB2 Connectivity Kit

The DB2 Connectivity Kit allows DataFlex programs to access data in IBM DB2 Universal Databases. DB2 is a client server relational database management system (RDBMS) that runs on a variety of operating systems. SQL is used to access data in a DB2 database.

Transactions and Locking

DB2 fully supports the ACID transaction properties. Next to the normal rollback facilities DB2 also supports so called roll forward functionality. DB2 supports all Isolation Levels. The Connectivity Kit will always use the Read Uncommitted isolation level. Transactions in DB2 are logged. The DB2 database system can recover from system failures.

The lock granularity used by DB2 is row (or record) locking. It is possible that the database manager replaces multiple row locks with a single table lock. This is called lock escalation. Lock escalation is implemented in several database platforms. If a lot of records on a page or table are locked, the overhead of administrating the locks gets so big that it is cheaper and/or faster to escalate the lock to lock an entire page or table. In DB2 three different types of locks are possible:

  • Share – Other transactions are limited to read-only access

  • Update – Other transactions are limited to read-only access provided they do not declare an intention to update the row. This type of locking is known as intent locking. The transaction tells the database manager to lock a row because it intends to update the data in the row.

  • Exclusive – Other transactions cannot access the data at all except those transactions that use an Isolation Level of Read Uncommitted.

DB2 will place exclusive locks on rows that are inserted, updated or deleted. The DB2 Connectivity Kit uses the Update lock provided by DB2. This type of lock is applied by using a special form of the SQL Select statement. The statement uses a so-called update clause. Update locks are placed while finding rows in a table. Once the row is actually updated, the lock will transform into an exclusive lock.

The update clause is only supported when used in a select statement that does not have a so-called order by clause. The only statement generated by the DB2 Connectivity Kit that does not use an order by clause is the one generated for a Find Eq by Recnum operation. The Connectivity Kit will therefore only place Update locks on rows that are found through a Find Eq by Recnum operation after the database has been locked. A Reread generates a Find Eq by Recnum after a lock so rows found by a Reread will also be locked. All rows that are found in some other way will be locked when they are updated or deleted.

The moment at which a lock is applied is different from the moment the native DataFlex database acquires a lock. In native DataFlex a lock is acquired when the lock command is issued. In DB2 locks are acquired as data is read in a locked state or as it gets updated or deleted.

When accessing DB2 make sure rows are locked, and always use either Reread or a Find Eq by Recnum in a locked state. Data Sets and Data Dictionaries will use Reread when updating data. Programs using the DDO/DSO objects will therefore correctly lock all data that is updated. Procedural programs may require code changes for all locks to be applied.

A further difference between DataFlex and DB2 is the amount of data that is updated in an update operation. DataFlex will read and write entire records. DB2 on the other hand is capable of updating one or more columns in a row. If for example one wants to update the name of a customer. DataFlex will read the entire record, modify the name and write the entire record back to the data file. DB2 will only write the modified customer name to the database.

The ability to update specified columns will reduce the amount of procedural code that needs adjusting. If the program overwrites columns with values not based on previous values of columns in the row, there is no need to make sure the row is locked. If the program uses previous values of columns in the row to calculate new values of columns in the row, you must make sure the row is locked. In those cases a Reread or Find Eq by Recnum must be added to the code if this is not already present. Below is an example of a procedure that does not need to be adjusted and one that must be adjusted.

Procedure NoNeedToAdjust

Clear SomeTable

Begin_Transaction

Repeat

Find Gt SomeTable By SomeIndex

If (Found) Begin

Move “SomeValue” To SomeTable.SomeColumn

Saverecord SomeTable

End

Until (Not(Found))

End_Transaction

End_Procedure // NoNeedToAdjust

Procedure MustBeAdjusted

Clear SomeTable

Begin_Transaction

Repeat

Find Gt SomeTable By SomeIndex

If (Found) Begin

Move (SomeTable.SomeColumn * 1.16) To ;

SomeTable.SomeColumn

Saverecord SomeTable

End

Until (Not(Found))

End_Transaction

End_Procedure // MustBeAdjusted

The procedure that must be adjusted can be adjusted the following way:

Procedure MustBeAdjusted

Clear SomeTable

Begin_Transaction

Repeat

Find Gt SomeTable By SomeIndex

If (Found) Begin

Reread

Move (SomeTable.SomeColumn * 1.16) To ;

SomeTable.SomeColumn

Saverecord SomeTable

Unlock

End

Until (Not(Found))

End_Transaction

End_Procedure // MustBeAdjusted

Data Access has been recommending the use of Reread when updating records for quite some time. It is expected that the number of programs that need adjusting in this area is limited. If you want both procedures to apply update locks on the records involved, you should adjust both procedures.

Deadlock

DB2 uses row locking, deadlock can occur. Deadlock is detected by the DB2 Deadlock Detector. When deadlock is detected, the deadlock detector arbitrarily selects one transaction that is rolled back. When the rollback occurs, the locks are released thus offering other transactions the possibility to proceed. The rolled back transaction (application) will get notified of the event by receiving the deadlock notification error. It is possible to set up the interval between two deadlock detection events. Next to deadlock detection, DB2 also supports a configurable lock timeout. If a lock timeout occurs the transaction trying to acquire the lock is rolled back and is notified by receiving the timeout notification error. The DB2 Connectivity Kit will report both these errors in the same way since they result in the same behavior for the transaction involved. The error is passed to DataFlex as DB2ERR_DEADLOCK_OR_TIMEOUT (12303).

The DB2 Connectivity Kit does not pass the DFERR_LOCK_TIMEOUT (4106) error to DataFlex. When a lock timeout occurs, the transaction is not automatically retried. Since DB2 uses record locking, a lock timeout error can occur at any time during a transaction. If the DFERR_LOCK_TIMEOUT error would be passed, the runtime would retry the transaction, jumping to the Begin_Transaction command. If the transaction was “well underway” at the moment the lock timeout occurs, variables and properties used in the transaction would have changed. An automatic retry would not give the desired result; a transaction rollback does not restore variables and properties to their original value. This situation cannot occur when using DataFlex data; Begin_Transaction will do all locking that will ever be done in a transaction so it is safe to automatically retry transactions when using DataFlex data.

It is the programmer’s responsibility to handle deadlock or lock timeouts. The DataFlex programmer can check for the error condition and act upon it. The code below shows a sample of retrying the transaction 9 times.

Procedure Retry9TimesWhenDeadlockOrTimeout

Integer bAborted

Integer bRetry

Integer iRetryCount

Repeat

Send InitializeForTransaction

Begin_Transaction

Send DoSomeDB2Updates

End_Transaction

Get_attribute DF_TRANSACTION_ABORT To bAborted

If (bAborted And (LastErr = DB2ERR_DEADLOCK_OR_TIMEOUT)) ;

Move (True) To bRetry

Else ;

Move (False) To bRetry

Increment iRetryCount

Until ((Not(bRetry) Or (iRetryCount > 10))

If (bAborted) ;

SendInformUser LastErr

End_procedure // Retry9TimesWhenDeadlockOrTimeout

See Also

Transactions


Transactions and the ODBC Connectivity Kit

The ODBC Connectivity Kit allows DataFlex programs to access data through ODBC. Open Database Connectivity (ODBC) is a widely accepted application programming interface (API) for database access. ODBC is designed to enable an application to access different database management systems (DBMS’s) with the same source code. An application calls ODBC functions which are implemented in database specific modules called drivers. ODBC uses SQL to access data.

ODBC is an API specification. The API is independent from any DBMS or operating system. It is important to understand that ODBC is designed to expose database capabilities, not supplement them. Thus, application writers should not expect that using ODBC will suddenly transform a simple database into a fully featured relational database engine. Nor are driver writers expected to implement functionality not found in the underlying database.

A variety of database management systems can be accessed through ODBC. These include enterprise database systems such as Oracle, Sybase, DB2, SQL Server, flat file systems as dBase, Paradox and even non-database systems as Excel, XML and ASCII.

ODBC supports transactions if the database connected to supports transactions. The same can be said about locking. How a DataFlex application behaves with transactions and locking when using the ODBC Connectivity Kit depends on the database used and the ODBC driver used to connect to that database.

Transactions and Locking

There are ODBC drivers for non-database environments. These generally do not support transactions and locking at all. The discussion below is limited to databases only.

If the database supports the Read Uncommitted Isolation Level, the ODBC Connectivity Kit will use that Isolation Level. If Read Uncommitted is not supported the Connectivity Kit does not set up an Isolation Level and will use the default level for the data source.

If transactions are supported they will be used automatically by the ODBC Connectivity Kit. In order to determine if a database supports transactions see its documentation. In general enterprise databases support transactions with rollback and roll forward features. Flat file databases provide the full range from no support to full rollback / forward support. If there is no support for transactions, the ODBC Connectivity Kit cannot use it.

Most databases support row locking. The ODBC Connectivity Kit assumes the environment to be a row-locking environment. If the granularity happens to be greater, page or table, this will also work. Assuming the smallest lock granularity assures that locking (if supported) works in all cases. In general databases use two approaches to locking: Optimistic and pessimistic locking.

When optimistic locking is used records are not really locked. All transactions have access to the record at all times. When the transaction requests a lock, a copy of the contents of the record is made. When at a later time in the transaction the record is updated, the current record in the table will be compared to the copy made at the time of the lock. If the two versions do not match, an error is declared and the update is not executed. The idea is that the change of two transactions trying to modify the same row simultaneously is very small. Applications connecting to a database that uses optimistic locking should handle the optimistic lock error condition. When using pessimistic locking Records are actually locked when the transaction requests a lock. Other transactions that try to lock the record will have to wait for the lock to be released.

The way the ODBC Connectivity Kit handles locks depends on the database that is used. At login time a number of attributes of the database are queried that determine the locking method. The method used will eventually select a so-called cursor to be used when accessing the database the cursor choice logic essentially is the following:

If DBMS supports a dynamic cursor use it

Else If DBMS supports positioned updates in a forward only cursor use it

Else If DBMS supports positioned updates in a keyset driven cursor use it

Else If DBMS supports SQLSetPos updates in a forward only cursor use it

Else If DBMS supports SQLSetPos updates in a keyset driven cursor use it

Else use forward only cursor

SQL is a set oriented language. A find (select) operation will return a set of records instead of just one like in record oriented environments. To traverse these sets a mechanism known as database cursors is used. A cursor allows a non set-oriented environment to obtain information from a set one row at a time.

Dynamic Cursors

Dynamic cursors are the most advanced type of cursor. Unfortunately very few databases support dynamic cursors. If a database supports dynamic cursors, the Connectivity Kit will use that type of cursor. Dynamic cursors support record locking in all find modes.

The moment at which a lock is applied is different from the moment the native DataFlex database acquires a lock. In native DataFlex a lock is acquired when the lock command is issued. In ODBC using dynamic cursors locks are acquired as data is read in a locked state.

Positioned Updates

A positioned update is an update at the current position of an active cursor. In order to be able to use this form of updating a special form of the select statement must be used. The select statement must contain a so-called update clause. The update clause will instruct the database to lock the record in question. Most enterprise databases support positioned updates through one or more cursor types.

The update clause will only be generated when a Find Eq by Recnum operation is done. The Connectivity Kit will therefore only place Update locks on rows that are found through a Find Eq by Recnum operation after the database has been locked. A Reread generates a Find Eq by Recnum after a lock so rows found by a Reread will also be locked. All rows that are found in some other way will be locked when they are updated or deleted.

The moment at which a lock is applied is different from the moment the native DataFlex database acquires a lock. In native DataFlex a lock is acquired when the lock command is issued. In ODBC locks are acquired as data is read in a locked state or as it gets updated or deleted.

When accessing ODBC make sure rows are locked, always use either Reread or a Find Eq by Recnum in a locked state. Data Sets and Data Dictionaries will use Reread when updating data. Programs using the DDO/DSO objects will therefore correctly lock all data that is updated. Procedural programs may require code changes for all locks to be applied.

A further difference between DataFlex and ODBC is the amount of data that is updated in an update operation. DataFlex will read and write entire records. ODBC (actually SQL) on the other hand is capable of updating one or more columns in a row. If for example one wants to update the name of a customer. DataFlex will read the entire record, modify the name and write the entire record back to the data file. ODBC should only write the modified customer name to the database.

The ability to update specified columns will reduce the amount of procedural code that needs adjusting. If the program overwrites columns with values not based on previous values of columns in the row, there is no need to make sure the row is locked. If the program uses previous values of columns in the row to calculate new values of columns in the row, you must make sure the row is locked. In that case a Reread or Find Eq by Recnum must be added to the code if t is not already present. Below an example of a procedure that does not need to be adjusted and one that must be adjusted.

Procedure NoNeedToAdjust

Clear SomeTable

Begin_Transaction

Repeat

Find Gt SomeTable By SomeIndex

If (Found) Begin

Move “SomeValue” To SomeTable.SomeColumn

Saverecord SomeTable

End

Until (Not(Found))

End_Transaction

End_Procedure // NoNeedToAdjust

Procedure MustBeAdjusted

Clear SomeTable

Begin_Transaction

Repeat

Find Gt SomeTable By SomeIndex

If (Found) Begin

Move (SomeTable.SomeColumn * 1.16) To ;

SomeTable.SomeColumn

Saverecord SomeTable

End

Until (Not(Found))

End_Transaction

End_Procedure // MustBeAdjusted

The procedure that must be adjusted can be adjusted the following way:

Procedure MustBeAdjusted

Clear SomeTable

Begin_Transaction

Repeat

Find Gt SomeTable By SomeIndex

If (Found) Begin

Reread

Move (SomeTable.SomeColumn * 1.16) To ;

SomeTable.SomeColumn

Saverecord SomeTable

Unlock

End

Until (Not(Found))

End_Transaction

End_Procedure // MustBeAdjusted

Data Access has been recommending the use of Reread when updating records for quite some time. It is expected that the number of programs that need adjusting in this area is limited. If you want both procedures to apply update locks on the records involved, you should adjust both procedures.

SQLSetPos Updates

ODBC provides an alternative way to update records from SQL through an API know as SQLSetPos. This API can be used to update and delete rows in a table. Even if SQLSetPos is supported, there are a variety of details in support for the API. SQLSetPos can be used to lock a row exclusive, update a row, delete a row or refresh a row. Not all of the possibilities have to be supported by a database. If the database supports updating rows through SQLSetPos, the Connectivity Kit will use SQLSetPos.

When SQLSetPos is supported with support for exclusive locks this will be called directly after each find in a locked state. This way records that are found in a locked state will be locked as they are found.

If the exclusive lock is not supported the Connectivity Kit will perform a so-called “dummy update” to ensure that the row is locked. Directly after a row has been found, the row will be updated. The dummy update column will be set to the value that has just been found. By default the dummy update column is the record identity column. This column is least likely to change. If however a different column should be used for the dummy update logic, this can be set up through the intermediate file keyword Dummy_Update_Column. Another reason to use an alternative dummy update column is when the record identity column cannot be updated. Some database support system assigned columns like auto-increment columns. In general it is considered an error to try to update such a column. After the dummy update has been done, a re-find is done to ensure the latest version is in the record buffer.

If SQLSetPos is supported all records that are read in a locked state will be locked as they are read. Depending on the support this may as simple as placing a lock or as complicated as doing a dummy update and re-finding the record.

No Update Support

If the database reports no support for dynamic cursors, positioned updates and SQLSetPos, the Connectivity Kit will use a forward only cursor. It is not defined how locking works in this case. In general these type of environments will lock rows as they are updated, deleted or inserted. Locks are applied at the moment of the DataFlex Save, SaveRecord or Delete command. No locks are applied when finding in a locked state.

Summary on Locking

There are a lot of options and unknown factors for ODBC in general. A database might support a particular feature or it may not. It would be quite confusing to keep track of all the different possibilities and implementations. Luckily most programmers only use one or two databases to connect to through ODBC.

Data Access has tested a number of environments to see how they support locking and transactions. In general we can distinguish the following types of support:

  • DC - Dynamic cursors

  • PU - Positioned updates

  • SPL - SQLSetPos + Exclusive lock

  • SPDU - SQLSetPos + Dummy update

The following table lists the tested environments with it locking type support

Environment Lock Type Comments

DB2 UDB 7.1 PU

MS SQL 7.0 DC

Sybase ASA 7.0 PU

Oracle 8.0 PU

Oracle 8.i PU

MS Access 2000 SPDU Make sure Access is set up to use pessimistic locking. The way to set this up can be found at http://support.microsoft.com/support/kb/articles/Q225/9/26.ASP.

Deadlock

In most databases that can be accessed through ODBC deadlock can occur. If the database detects deadlock depends on the database in use. See the database documentation if deadlocks can occur and if so if detection is supported. If deadlock is detected, the transaction will be aborted and the deadlock detection error is sent to the victim transaction. If the database supports a lock timeout, the same happens when lock timeout occurs. There is no way ODBC Connectivity Kit can know upfront what the error numbers of the database for the two events are. Errors generated by databases will be reported under number 12289. There is no way to know if an error was a deadlock, timeout or some other error that can be generated by the database in use.

Since the ODBC Connectivity Kit does not know if the database generated a timeout error it will also not pass the DFERR_LOCK_TIMEOUT (4106) error to DataFlex. Even if it would be able to determine if the lock timeout error occurs the DFERR_LOCK_TIMEOUT error would not be generated. Since most databases use record locking, a lock timeout error can occur at any time during a transaction. If the DFERR_LOCK_TIMEOUT error would be passed, the runtime would retry the transaction, jumping to the Begin_Transaction command. If the transaction was “well underway” at the moment the lock timeout occurs, variables and properties used in the transaction will have changed. An automatic retry would not give the desired result; a transaction rollback does not restore variables and properties to their original value. This situation cannot occur when using DataFlex data, Begin_Transaction will do all locking that will ever be done in a transaction so it is safe to automatically retry transactions when using DataFlex data.

The only way to detect if Deadlock occurred is by parsing the error text of the latest error. The ODBC Connectivity Kit formats it errors in a special way: <SQLState> (<Native error number>)-<Error text>. If the SQLState that is set when deadlock or timeout occurs is known a DataFlex program could test for this state. SQLState is a five-character string. Not all databases pass native error numbers through ODBC, if it does the DataFlex programmer could also check the native error number.

See Also

Transactions


Pervasive.SQL Database Mode and Security

The DataFlex Connectivity Kit for Pervasive.SQL can be configured to operate in database mode or in non database mode. When running in database mode Pervasive.SQL tables are located by specifying a Pervasive.SQL database name. In non-database mode tables are located by specifying paths to the physical data files.

Database mode can only be used when running on Pervasive.SQL V8.5 or later.

When running in database mode it is possible to access Pervasive.SQL secured databases. One of the main advantages of secured databases is that users no longer need operating system access rights to access Pervasive.SQL data files. Instead all authentication and authorization is handled by the Pervasive transactional database engine.

When using secured databases, access rights can be defined for individual users and tables. Users and access rights are defined in the Pervasive.SQL metadatabase and are independent of operating system access rights.

When operating in database mode the Connectivity Kit can also concurrently access tables in more then one database, possibly on different servers.


Pervasive.SQL Database Concepts

A database in Pervasive.SQL consist of:

  • Data tables (BTR files)

  • Meta data with structural information (FILE.DDF, FIELD.DDF, INDEX.DDF)

  • Meta data with authentication information (USERS.DDF and RIGHTS.DDF).

Databases must be setup using Pervasive Control Center. During setup the folder on the server where the data files will reside must be specified.

Databases can be secured or unsecured. Security of a database can be switched on and off in Pervasive Control Center. When security is on, users and user rights can be defined for the database.

Note: Pervasive.SQL supplies different security models to choose from. (Classic/Mixed/Database security) Depending on the chosen model, security setup (users and rights) will be different. Refer to the Pervasive documentation for further information.

Once a database is setup, the database can be accessed by specifying the name of the database in an URI (Uniform Resource Indicator).

An URI looks like this:

btrv://user@host/database?table=tablename&pwd=passwd

Where:

  • user/passwd: The user name and password as defined for the PSQL database

  • host: The server name of the PSQL server

  • Database The name of the database that needs to be accessed

  • Table The table in the database to open

Example

btrv://psquser@MyPervasiveServer/ORDER?table=SALESP&pwd=secret

This URI shows how to open the table SALESP in database ORDER on server MyPervasiveServer. The table can only be accessed if user psqluser has been assigned sufficient access rights to the database and/or table.

Refer to the Pervasive Documentation for further info about URI’s.


Using Database Access with the Connectivity Kit

The Connectivity Kit can be configured to operate in database mode or in non-database mode. This is specified by the DATABASE_MODE setting in the Connectivity Kit configuration file DFBTRDRV.INT.

When running in database mode (DATABASE_MODE is on), the Connectivity Kit accesses tables by specifying a database name in an URI.

When running in non-database mode (DATABASE_MODE is off), the Connectivity Kit functions the same as earlier versions of the Connectivity Kit. Tables are located by searching the data path (DFPATH) or using the BTR_PATH setting.

The DATABASE_MODE setting can only be on when Pervasive.SQL V8.5 or later is used. If the setting is on, all tables must be accessed in database mode using URI’s. It is not possible to use both database access and non-database access.

When using the Connectivity Kit with Pervasive.SQL versions before V8.5 the DATABASE_MODE setting must be off.

Although URI’s are mainly intended to access secured databases, they can also be used to access unsecured databases (but only on Pervasive.SQL 8.5 or later). When accessing unsecured databases, os-level (Windows) user names can be specified in the URI.

If DATABASE_MODE is on, the Connectivity Kit does not (need to) know where the BTR and DDF files are located, since this is specified by the database name in the URI. For this reason the data path (DFPATH) will not be searched and the BTR_PATH and DDF_PATH settings will not be used.

Note that the Connectivity Kit still must be able to access the intermediate (INT) files and structure cache (CCH) files when using databases. These files must be somewhere in a central accessible place, where the Connectivity Kit can access them.

The CCH and INT files can be (and preferably are) in a different location than the BTR and DDF files.

Opening Tables in Database Mode

Opening a table in database mode requires specification of an URI. URI’s for individual tables must be specified in the intermediate (.INT) file for the table with the URI keyword.

The following is an example of intermediate file SALESP.INT that can be used to access table SALESP in database "Order" on server "MyPervasiveServer".

DRIVER_NAME DFBTRDRV

URI btrv://psqluser@MyPervasiveServer/Order?table=salesp&pwd=secret

; Data after this point is read after the DDF's have been read

; ID

FIELD_NUMBER 1

FIELD_INDEX 1

; NAME

FIELD_NUMBER 2

FIELD_INDEX 2

Open As with an URI

In a normal open the Connectivity Kit expects the name of the intermediate file in the rootname of the table in filelist.cfg. The rootname can be specified as the name of the intermediate file (“SALESP.INT”) or with a driver prefix (“DFBTRDRV:SALESP”).

Alternatively, when using an "Open As" command the rootname can be specified in the command itself.

Example

Open “SALESP.INT” as hFile

Open “DFBTRDRV:SALESP” as hFile

All of the above open methods require an INT file with an URI specified.

In addition, the Connectivity Kit allows specification of an URI in the Open As command as follows:

Open "DFBTRDRV: btrv://psqluser@MyPervasiveServer/Order?table=salesp&pwd=secret" as hFile

This "URI Open As" command will open the table as specified by the URI. The "URI Open As" can use an intermediate file, but does not necessarily have to.

An intermediate file will be used if:

  • USE_INT in DFBTRDRV.INT is on, and

  • An <table>.INT file can be found

If an INT file is found and it contains an URI that URI will not be used, but instead the URI of the "Open as" command will be used. All other information from the INT file (like relations) will be used.

The "URI Open As" will not use an intermediate file if:

  • USE_INT in DFBTRDRV.INT is off, or

  • An <table>.INT file can not be found

An "URI Open As" will use the table name from the URI as the base name for the intermediate file (<table>.INT) and the structure cache file (<table>.CCH>).

Note

The special Connectivity Kit Open As method:

Open “LOGIFILE|PHYSFILE.BTR” As hFile

is not supported when DATABASE_MODE is on.


Conversion in Database Mode

To convert DataFlex tables to Pervasive.SQL in database mode, Database Builder version 10.1 or later is needed.

This Database Builder will detect if the DATABASE_MODE setting in the Connectivity Kit is on. If the DATABASE_MODE setting is on, the information to compose the URI can be entered on the Convert to Pervasive.SQL dialog.

The conversion logic will create an URI to access the converted table in the intermediate (INT) file.


Migrating to Secured Databases

If you have an existing application using Pervasive.SQL and you want to start using secured databases follow the following procedure.

  • Make sure you are using Pervasive.SQL V8.5 or later and Connectivity Kit 3.0 or later.

  • Determine how to set up your database(s) and where the various files should be located.

When using traditional (non-databasemode) access, the various file types the Connectivity Kit needs to access (BTR, DDF, INT and CCH) must all be accessible through the data path (DFPATH).

When using database mode, the BTR and DDF files no longer have to be in the data path. It is recommended to move the BTR and DDF files to a different folder outside the data path. This will make it easier to change access right and hide the Pervasive.SQL tables from users at the Operating System level.

The INT and CCH files must still be in the data path. They can be anywhere where they are accessible for the Connectivity Kit. They don’t have to be on the same server as the BTR and DDF files.

When you have a setup with more than one folder with BTR and/or DDF files, you should define multiple Pervasive.SQL databases.

  • In Pervasive Control Center create a database and let it point to the folder where your data files (BTR files) and dictionary files (DDF files) are located.

  • Turn on security for the database. You also need to setup the security model you want to use (Classic, Mixed and Database).

  • Define users, user groups and access rights for the database. Depending on the chosen security model, the security setup (users and user rights) will be different. Refer to the Pervasive.SQL documentation for further information.

  • Set DATABASE_MODE 1 (on) in the Connectivity Kit Configuration file DFBTRDRV.INT.

  • Migrate the tables to use URI’s. There is a special option available in Database Builder (version 10.1 or later) that can migrate the tables for you:

  • Choose “Migrate Pervasive.SQL tables to use URI’s” from the Database menu in Database Builder.

  • Select the tables you want to migrate.

  • Enter the information to compose the URI’s:

  • The migration process will open all selected tables with an “Open As Uri”, composed from the entered URI. A restructure will be made that will cause the INT file to be rewritten with an URI that can access the table. The restructure will also cause the structure information to be rewritten to the DDF files.


Security in Pervasive.SQL Prior to V8.5

Versions of Pervasive.SQL prior to V8.5, also provide limited database security facilities. The Connectivity Kit supports this limited security only when operating in non-database mode. (Database mode can only be used on Pervasive.SQL V8.5 or later)

Security in pre-v8.5 versions can be turned on in Pervasive Control Center. When you turn on security, you must provide a password for the ‘Master’ user. This password is also put as an owner name on the DDF files.

The Connectivity Kit needs to know this DDF owner name to be able to access the DDFs.

You can pass the DDF owner name by specifying it with the DDF_OWNER keyword in DFBTRDRV.INT.

DDF_OWNER Secret

Note: Owner names are case sensitive.

This implies a security risk, because you need to put the password in the DFBTRDRV.INT in plain ASCII.

You can also pass the owner name at runtime with the DFBTR_DDF_OWNER command.

Example

Use DFBTRDRV.pkg

String sDdfOwnerName

Move “Secret” To sDdfOwnerName

DFBTR_DDF_OWNER sDDFOwnerName


Owner Names

Pervasive.SQL tables have a concept called the owner name of a table. The value of an owner name is not the name of the person who created the table or the person who owns it. You should think of owner names like passwords. People who know the password have unlimited access, while people who don't, have either restricted access or no access at all.

The owner name concept was originally intended to protect unauthorized access to Btrieve files. Pervasive.SQL also offers more advanced security features that can be combined with owner names. Refer to the Pervasive.SQL documentation and the chapter on Database Mode and Security for further information.

This chapter describes how the Connectivity Kit supports owner names.

Conversion Options

When you convert a table from DataFlex to Pervasive.SQL, you have the option to enter an owner name. When you enter an owner name, you can select whether you want to allow read-only access or to encrypt the data.

Read-only Access

When a table allows read-only access, it means that any application which does not know the owner name of a table can open the table, but only has read-only access to it. This means that those applications cannot make changes to the data in the table like making changes to existing records, adding records, or deleting records.

Encrypt Data

When this option has been selected when entering an owner name, Pervasive.SQL will encrypt the data when it is being stored to disk. This way, it is not readable by anyone opening the table with an application that does not know how to handle Pervasive.SQL tables. This option can be used in combination with read-only access.

How to Set or Clear an Owner Name

There are two ways to put an owner name to a table. The first is when a table is being converted to the Pervasive.SQL format using one of the conversion tools. The other way is to use a special command DFBTR_SET_Owner Name.

Conversion

When you are converting tables, you can enter an owner name for the table(s) you want to convert. When you do, you can also specify whether you allow read-only access or if you want to encrypt the table’s data.

DFBTR_SET_OWNER

This command can be used in a program to change or set the owner name of an opened table. Note that when the table has been opened, you need to have full access to the table. This means that if the table already has an owner name, you need to have it opened using that name.

When setting the owner, you can specify that you allow read-only access and/or if you want the table’s data to be encrypted.

DFBTR_SET_OWNER SALESP.File_Number To “MYOWNER” READONLY

See Appendix B for complete syntax details.

DFBTR_CLEAR_OWNER

This command can be used to clear the owner of a table. After the owner has been cleared, any application and/or user can access the data and make changes to the data.

The table of which the owner has to be clear need to be open and needs full access to the table.

DFBTR_CLEAR_OWNER SALESP.File_Number

See Appendix B for complete syntax details.

Opening Tables with Owner Names

Once an owner name has been put on a table, you need to pass this owner name to the DataFlex Connectivity Kit for Pervasive.SQL before you can open it and make changes to the data in the table. There are several ways to do this:

  • Set the owner name in the INT file

  • Add the owner name to the DFBTRDRV.INT file

  • Add the owner name at run time

The first option uses the owner name specified for that table only. The other options add the owner names to an internal list of owner names.

Owner Name List

The Connectivity Kit keeps an internal list of owner names to use when opening Pervasive.SQL tables. Whenever a Pervasive.SQL table needs to be opened which has not been assigned an individual owner name, the Connectivity Kit will try the first owner name of the list to open the table. If it doesn't succeed, it will try the next owner name in the list, until it has reached the end and it still could not open the table. When it reaches the end without opening the table, it will try to open the table without owner name. When the owner name list is empty, it will immediately try to open the table without owner name. If it still could not open the table, it will generate an error BTR:51.

Setting the Owner Name in the INT File

When you are using an INT file to open a Pervasive.SQL table through the Connectivity Kit, you can set a line in the INT file specifying the owner name of the table. This owner name will be used to open the table. If it can’t open the table using the specified owner name, it will try the other owner names of your list of owner names and if it still can’t open it, it will try it without owner name.

Put a line like this in the INT file for your Pervasive.SQL table:

OWNER “SECRET”

NOTE: Using this method is not very secure. Anyone who has access to the INT file can read the owner name of the table.

Add the Owner Name to the DFBTRDRV.INT File

If all or a number of tables share the same owner name, you can choose to put this owner name in your DFBTRDRV.INT configuration file. Every owner listed will be added to the internal list of owner names of the Connectivity Kit. The names in this list will be used to open tables.

Put a line(s) like this in the DFBTRDRV.INT:

OWNER “SECRET1”

OWNER “SECRET2”

OWNER “SECRET3”

NOTE: Using this method is not very secure. Anyone that has access to the DFBTRDRV.INT file can read the owner name(s) of the table.

Pass the Owner Name at Run Time

This is the safest method to add owner names to the internal list of owner names. You can use the command DFBTR_ADD_OWNER to add an owner name to the list. The best way to do this is to start your program with a login screen in which the user can type in the owner name(s).

The syntax for adding an owner name to the list is:

DFBTR_ADD_OWNER Owner

Owner The owner name to add to the internal list. It may be a constant or a string variable.


Error Handling

The Connectivity Kits handles several types of errors. We distinguish between driver level and database level errors.

Driver level errors are detected at Connectivity Kit level. Trying to set an attribute for a non-existing column, for example, will trigger a driver level error.

Database level errors are raised by the server and passed on by the Connectivity Kit to Visual DataFlex. Not having sufficient rights to perform a certain operation will trigger a database level error.

See Also

Driver Level Errors

SQL Server Error Class

DB2 Error Class

Database Level Errors

SQL State Table


Driver Level Errors

A Connectivity Kit raises a driver level error when it detects an illegal operation.

SQL Connectivity Kits Verbosity Term

In general a Connectivity Kit is as verbose as possible to identify the cause of the error. If a program tries to set a field attribute in table MyTable of a non-existing column with number 12 the kit will report the following message: “Field number out of range [MyTable, 12]”. The text between square brackets is intended as extra information to help identify the cause of the error and is referred to as verbosity term.

Most of the time the verbosity term will identify a table name or number. Sometimes however the term may not be clear at first sight; those terms are listed in the following table. In the following table we use abbreviations TN table name, CN column name, AN attribute number, IN index number, ISN index segment number.

ERROR | VERBOSITY TERM
Setting a non supported attribute | [<TN>,<AN >] [<TN>,<CN >,<AN>] [<TN>,index.<IN >,<AN >] [<TN>,index.<IN>,segment.<ISN>,<AN>]
Field number out of range | [<TN>, <IllegalFieldNumber>]
Index number out of range | [<TN>, index.<IN>]
Index segment out of range | [<TN>,index.<IN>,<ISN>]
String too long | [TheString]
Bad attribute value | [<TN>,<AN >,<BadValue>] [<TN>,<CN >,<AN >,<BadValue>] [<TN>,index.<IN>,<AN >,<BadValue>] [<TN>,index.<IN>,segment.<ISN>,<AN>,<BadValue.]
Index is not available | [<TN>,index.<IN>]
Invalid intermediate file value | [<TN>,<Keyword>,<IllegalValue>]
Invalid intermediate file keyword | [<IllegalKeyword>]
Number to large for field | [<TN>,<CN>]


SQL Error Class (12289 – 12331)

The DataFlex error system defines several classes of errors: user, system and utility errors. The SQL Connectivity Kits (SQL Server, DB2 and ODBC) add an error class to the DataFlex error classes. The SQL Connectivity Kits add the following errors:

NUMBER | TEXT | DESCRIPTION
12289 | General error | Database level error entry point; see the paragraph on database level errors.
12290 | Can't initialize | The Connectivity Kit is unable to initialize. Check the database client setup.
12291 | Can't de-initialize | The Connectivity Kit is unable to de-initialize and free up the CK environment. Check the database client setup.
12192 | Bad or no primary index specified. | The primary index is bad. This can be caused by several reasons. Either the index does not exist or it contains more than one segment.
12293 | Login unsuccessful | Unable to login to the specified server. Either the database client is not properly setup or the user does not have sufficient privileges to login to the server.
12294 | Logout unsuccessful | Unable to logout from the server. Check the database client setup.
12295 | Table not in connection | An attempt is made to open a table that cannot be found on the specified server for the specified owner.
12296 | Null value not allowed | An attempt has been made to put a NULL value into a column does not allow NULL values.
12297 | Segment number out of range | An attempt has been made to set or get an attribute of a non-existing index segment.
12298 | Index number out of range | An attempt has been made to set or get an attribute of a non-existing index.
12299 | Login attribute must be set | Structure changes have been made to the table. The Structure_End operation is missing login information for the table and is unable to save the changes. Make sure to set the DF_FILE_LOGIN attribute of the table.
12300 | Physical name must be set | Trying to create a new table. The Structure_End operation is missing the physical name of the table. This is the name the table will get in the back end. Make sure to set the DF_FILE_PHYSICAL_NAME attribute.
12301 | Invalid registration file | The registration file is invalid.
12302 | License expired | A temporary license is expired.
12303 | Deadlock or timeout | The current transaction was interrupted and rolled back because of a deadlock or timeout. For more information about handling deadlocks and/or timeouts, see the Transaction chapter.
12304 | Embedded SQL error | General Embedded SQL error.
12305 | Invalid SQL statement handle | A statement using the handle cannot be found for the specified connection.
12306 | Invalid SQL connection handle | A connection using the handle cannot be found.
12307 | Invalid SQL Connectivity Kit Identifier | The Connectivity Kit identifier is illegal.
12308 | Invalid SQL bind file | The specified bind file is not open, it is not an table connected to by the Connectivity Kit used for the Embedded SQL statement or the piBindFile property has not been set.
12309 | Invalid SQL column | A column with the specified number does not exist in the result set.
12310 | Invalid attribute | The attribute identifier is illegal.
12311 | Invalid buffer | The file passed to FetchActivatesBuffer is not open.
12312 | Invalid configuration keyword | A keyword in the global configuration file is invalid.
12313 | Unique index required for restructure | When restructuring an existing table at least one unique index is required.
12315 | Attempt to change a read only field | An attempt was made to change a column for which the DF_FIELD_READ_ONLY attribute was set to RO_ERRORONCHANGE.
12316 | Database property not set correctly | When using uppercase segments, the database property ARITHABORT was not set ON. (SQL Server only.)
12317 | Cannot set RECNUM inactive | An attempt was made to set the RECNUM column to non-active (DF_FIELD_FETCH_STATE = FALSE) and the ReportActiveColumnErrors global attribute is set ON.
12318 | Cannot change an inactive column | An attempt was made to change the value of a non-active column.
12319 | The field is not active can't get value | An attempt was made to get the value of a non-active column (DF_FIELD_FETCH_STATE = FALSE) and the ReportActiveColumnErrors global attribute is set ON.
12320 | Connectivity Kit not properly registered | The Connectivity Kit is not properly registered. Run the registration program.
12321 | Can't find registration file | The registration file cannot be found. Run the registration program. Registration files are: SQL Server: mssqldrv.cfg DB2: db2_drv.cfg ODBC: odbc_drv.cfg
12322 | Can't read registration file | The registration file cannot be read. Run the registration program. Registration files are: SQL Server: mssqldrv.cfg DB2: db2_drv.cfg ODBC: odbc_drv.cfg
12323 | Maximum number of users exceeded | The maximum number of users for the Connectivity Kit has been exceeded.
12324 | User count file error | An error in the user count file has been detected. Run the registration program.
12325 | Can't initialize user counting | An error occurred while initializing the user count system.
12326 | User count file not found | The user count file was not found. Run the registration program. User count files are: SQL Server: ms<serial number>.dfr DB2: db<serial number>.dfr ODBC: od<serial number>.dfr
12327 | Can't read user count file | The user count file cannot be read. User count files are: SQL Server: ms<serial number>.dfr DB2: db<serial number>.dfr ODBC: od<serial number>.dfr
12328 | Can't decrypt user count file | The user count file cannot be decrypted. Run the registration program. User count files are: SQL Server: ms<serial number>.dfr DB2: db<serial number>.dfr ODBC: od<serial number>.dfr
12329 | Bad version of user count file | The user count file has a bad version. Run the registration program. User count files are: SQL Server: ms<serial number>.dfr DB2: db<serial number>.dfr ODBC: od<serial number>.dfr
12330 | Can't create record with recnum zero | An attempt was made to create a record with a record number that is 0 (zero) and it is not automatically filled. This is a programming error.
12331 | Can't get column information | When a table is opened the Connectivity Kit will get information on all the columns in the table. When getting this information fails, this error is raised.


Pervasive.SQL Error Class (20482 - 20575)

The DataFlex error system defines several classes of errors: user, system and utility errors. The Pervasive.SQL Connectivity Kit adds an error class to the DataFlex error classes. The Pervasive.SQL Connectivity Kits adds the following errors:

20482 Invalid Integer Length Integer fields are only supported to have a size of 1, 2, or 4 bytes. Any other length will trigger this error.

20483 Can’t Get Stat Information Whenever the Connectivity Kit is opening a Pervasive.SQL table, it tries to get information about that table from the Pervasive.SQL engine it is connected to. This error indicates an error during that process.

20484 Index Structure Mismatch One of the following conditions is true:

  • The Pervasive.SQL table has indexes that are not present in the DDF table.

  • The index definitions described in the DDF table do not match the index definition of the Pervasive.SQL table.

20485 Index Segment Field Structure Mismatch An index segment described in the DDF table does not match the offset and/or the length of the actual segment in the Pervasive.SQL table.

20486 No Index for Record Identity A table that is using recnum support has no index for the recnum field.

20487 Invalid Character in Path The Connectivity Kit detects an invalid character being used in the path for a table. Pervasive.SQL does not support the use of spaces in a path, for example.

20488 Field Invalid Type An internal routine has been called with a field type that is invalid for DataFlex.

20489 Unsupported Date Type A date field is being accessed from within a DataFlex program, but that the Pervasive.SQL field type is not date.

20490 Cant Find Segment Field A record from INDEX.DDF is pointing to a non-existent field in FIELD.DDF or that the field it is pointing to is not a part of the table it is pointing to.

20491 Invalid Driver Function Call The Call_Driver command is being executed with an illegal function number.

20492 File Exists The Connectivity Kit is trying to create a Pervasive.SQL table that already exists somewhere in a directory that can be reached through the DFPATH environment setting.

20493 Cant Delete File An error occurred when a Pervasive.SQL table was being created and the Connectivity Kit can’t delete the created table for cleanup.

20494 Pervasive.SQL Path Too Long The maximum length of a path for a Pervasive.SQL table accessed through this Connectivity Kit is 255 characters. This error indicates that there are more than 255 characters being used.

20495 DDF File Entry Not Found The Connectivity Kit can’t find the table specified in FILE.DDF. Check if the right table is being accessed and check if the Connectivity Kit is using the right DDF tables.

20496 Can’t Get Temp Handle The Connectivity Kit can’t find a free file number to temporarily open a new table under when converting a table to Pervasive.SQL from another format.

20497 Root Name Too Long This error can be generated when the new rootname of a converted table has become too large to fit into the rootname slot of a file-list entry. The maximum length of a rootname is 40 characters. If your current rootname is including a path, you might want to remove the path and set the DFPATH setting so that the table can be reached through the DFPATH.

20498 Can’t Convert Inside Transaction Table conversions can only take place outside the scope of a database transaction.

20499 Recnum Has To Be Last In Index This error can be seen if a table is being converted without recnum support and the recnum field is being used as a segment in an index while that segment is not the last segment of that index. The Connectivity Kit will actually not instruct Pervasive.SQL to include the recnum field but instead it will mark the index to allow duplicates, which is the usual reason the recnum field is included in indexes.

20500 Invalid Overlap The conversion function can’t find the field that the start or endpoint of an overlap field is pointing to.

20501 Invalid INT Fieldtype This error will be generated when the type defined in an INT file for a field does not match one of the standard DataFlex field types. Supported field types are ASCII, BCD, DATE, OVERLAP, TEXT and BINARY.

20502 License Expired This error indicates that the expiration date of your DataFlex for Pervasive.SQL license has passed. Contact your distributor or Data Access Corporation.

20503 Logical Value Out Of Range Pervasive.SQL logical fields only have values between 0 and 255. In DataFlex, this field is being treated like a BCD field.

20504 Invalid Field Name An invalid fieldname has been used. The Connectivity Kit will correct the illegal characters automatically.

20505 Invalid Record Identity The record-identity property of a table is being set to a value outside the range of valid field numbers or to a field that cannot be the record-identity field.

20506 Invalid Field Type Combination This error indicates that the internal field type conversion table could not convert the DataFlex field type into a valid Pervasive.SQL field type. This should never happen.

20507 Can’t Change Length Static Data Type This error will be generated whenever the length is going to be changed of a field connected to a Pervasive.SQL field type that has a static length like the date or time field types.

20508 Unsupported Pervasive.SQL Field Type This error will be generated whenever the Connectivity Kit has to deal with a field type it does not support.

20509 Duplicate Field Name A field already exists with the name of a new field.

20510 Invalid Type for Offset Set Whenever the offset of a field that is not an overlap field is set, this error will be generated.

20511 Invalid Offset Value This error is generated when setting the offset will cause the overlap to lie past the end of the record.

20512 Invalid Indexnumber An invalid index number was passed to the Connectivity Kit.

20513 Invalid Segmentnumber An invalid segment number was passed to the Connectivity Kit.

20515 Ownername Too Long The maximum length of the ownername of a table is 8 characters. Whenever a larger string is being passed, the Connectivity Kit will generate this error.

20516 Owner Set Within Restructure An ownername can only be set outside a restructure operation. This error indicates it is done within a restructure operation.

20517 Err Invalid Owner Flags An invalid flag was passed when setting the ownername of a table.

20518 Cant Delete File Read-only The Connectivity Kit tried to delete a table and received an error that the table is marked as read-only.

20519 Cant Delete File Invalid Path The Connectivity Kit tried to delete a file and is using an invalid path. This should never happen.

20520 Fieldname Adjusted The name of a field has been truncated because its length exceeded the maximum number of characters allowed for a Pervasive.SQL field name, which is 20 characters.

20522 Cant Create Temp File Whenever the Connectivity Kit is finishing a restructure operation, it will first create the file under a new temporary filename. When it is done, it will rename the original file to another temporary filename and then rename the first temporary filename to the name of the original file. It uses a random-number generator to get a temporary filename. When it can’t get a temporary filename, it will declare this error.

20523 Cant Find Acs The Connectivity Kit is trying to load the ACS specified using the Connectivity Kit configuration file or the ACS keyword, but it can’t find the ACS.

20524 Cant Find Upper Acs The Connectivity Kit is trying to load the ACS specified using the Connectivity Kit configuration file or one of the ACS keywords, but it can’t find the ACS.

20525 Cant Open Acs The Connectivity Kit is trying to open the ACS specified using the Connectivity Kit configuration file or the ACS_UPPER keyword, but it can’t open the ACS.

20526 Invalid Acs The format of the ACS does not comply with the format expected. Read the chapter on how to define an ACS or refer to the documentation that came with your Pervasive.SQL Engine.

20527 Maximum Number of Segments Exceeded The Pervasive.SQL table you are working with has no more index segments available. Every Pervasive.SQL table can have a maximum number of segments defined. This number of segments is independent on the number of indexes. The number of segments that can be used depends on the page size of a Pervasive.SQL table. The following table gives the maximum number of segments available per page size:

Page Size | Segments
512 | 8
1024 | 23
1536 | 24
2048-3584 | 54
4096 | 119

20528 DDF Indexes Not Complete A Pervasive.SQL index contains more segments than are defined in the DDF table for that index.

20529 DDF Index Segments Not Complete An index in a Pervasive.SQL table is found which is not present in the DDF tables.

20530 Stat Acs Structure Mismatch The result of a Pervasive.SQL Stat operation does not match the number of ACSes expected.

20531 Invalid Transaction Type An invalid transaction type is being set. Valid types are NONE, EXCLUSIVE and CONCURRENT.

20532 Cannot Change Transaction Type While Active The Connectivity Kit was requested to change the transaction type while a transaction is active.

20533 Invalid Registration File This error indicates that the information in your registration file is invalid. Please re-enter the registration code for the product.

20534 File Has No Fields This error will be triggered when a table with no fields defined will be opened. This may be caused when no record can be found in FIELD.DDF that refers to the table being opened.

20535 Invalid Configuration Keyword This error indicates that an invalid keyword has been used in the DFBTRDRV.INT configuration file.

20536 Length of Date Field Cant Be Changed This error will be generated when an application is trying to change the length of a field which type has been set to date. Date fields have a fixed format.

20537 Cant Find Df4btr Recnum Field When the DATAFLEX_FOR_BTRIEVE flag has been set to TRUE for a table the Connectivity Kit will search for a field called “DATAFLEX_RECNUM_ONE” in the table, which will represent the recnum. This error indicates that this field cannot be found in the field list.

20538 Cannot Open Cachefile For Write This error will be generated when the use of structure caching has been switched on (USE_CACHE 1) and the reporting of cache error has been switched on (REPORT_CACHE_ERRORS 1) and an error occurs while trying to create the cache file.

20539 Cannot Write To Cachefile This error will be generated when the use of structure caching has been switched on (USE_CACHE 1) and the reporting of cache error has been switched on (REPORT_CACHE_ERRORS 1) and an error occurs while trying to create the cache file.

20540 Cannot Read From Cachefile This error will be generated when the use of structure caching has been switched on (USE_CACHE 1) and the reporting of cache error has been switched on (REPORT_CACHE_ERRORS 1) and an error occurs while reading the cache file.

20541 Cannot Read Signature From Cachefile This error will be generated when the use of structure caching has been switched on (USE_CACHE 1) and the reporting of cache error has been switched on (REPORT_CACHE_ERRORS 1) and an error occurs while reading the cache file.

20542 Cannot Open Cachefile For Read This error will be generated when the use of structure caching has been switched on (USE_CACHE 1) and the reporting of cache error has been switched on (REPORT_CACHE_ERRORS 1) and an error occurs while reading the cache file.

20543 Cannot Close Cachefile This error will be generated when the use of structure caching has been switched on (USE_CACHE 1) and the reporting of cache error has been switched on (REPORT_CACHE_ERRORS 1) and an error occurs while reading the cache file.

20544 Invalid Int Fieldtype Btr Valid values for FIELDTYPE_BTR are STRING, INTEGER, IEEE, DATE, TIME, DECIMAL, MONEY, LOGICAL, NUMERIC, BFLOAT, LSTRING, ZSTRING, NOTE, UNSIGNED, AUTOINCREMENT, NUMERIC_STS and NUMERIC_SA.

20545 Invalid Int Fieldtype Aux Valid values for FIELDTYPE_AUX are LSTRING2 and DFBCD.

20546 Cannot Find Unique Fieldname The Connectivity Kit could not create a unique fieldname when creating a field.

20547 Invalid Fieldtype For Getstring The fieldtype of field for which the string value is being requested is not supported for getting a string value.

20548 Invalid Recnum Method An invalid value has been specified for the RECNUM_METHOD setting of DFBTRDRV.INT. Value values are GET_POSITION, POSITION_BLOCK, DOUBLE_CHECK and AUTO_CONFIG.

20549 Recnum Mismatch This error will be generated when the RECNUM_METHOD has been set to DOUBLE_CHECK and the values get from the GET_POSITON and POSITION_BLOCK method do not match.

20552 Invalid Cachefile Version This error will be generated when the use of structure caching has been switched on (USE_CACHE 1) and the reporting of cache error has been switched on (REPORT_CACHE_ERRORS 1) and an error occurs while reading the cache file.

20554 Cannot Rename File This error will be generated when the Connectivity Kit failed to rename a file while restructuring a file.

20555 Invalid Zerofile Method An invalid value for the ZEROFILE_METHOD of DFBTRDRV.INT has been specified. Valid values are CREATE, FALLBACK and DELETE.

20556 Cachefile Expired This error will be generated when the use of structure caching has been switched on (USE_CACHE 1) and the reporting of cache error has been switched on (REPORT_CACHE_ERRORS 1) and an error occurs while reading the cache file.

20557 Cannot Find Cachefile This error will be generated when the use of structure caching has been switched on (USE_CACHE 1) and the reporting of cache error has been switched on (REPORT_CACHE_ERRORS 1) and an error occurs while trying to locate the cache file.

20558 Invalid Character Set This error will be generated when an invalid character set is specified in DFBTRDRV.INT.

20559 Cannot Open Logfile This error will be generated when a LOGFILE_PATH has been specified and the specified file cannot be opened.

20560 Length Of Timestamp Field Cant Be Changed This error will be generated when an application is trying to change the length of a BTR_TIMESTAMP_TYPE (type 20) field.

20561 Single Recnum Index Not Allowed This error will be generated when an application tries to define an index with RECNUM as the only field segment in the index.

20562 Incompatible Pos Sign Detected This error will be generated when the Connectivity Kit reads a numeric value from the Pervasive.SQL table, which has a different value for the positive sign, than the value specified by COMP3_SIGN_POS in the DFBTRDRV.INT file. (If no COMP3_SIGN_POS is specified the default value of 15 (Hex 0x0F) will be taken.)

This error message can be turned off, by specifying:

DETECT_INCOMPATIBLE_SIGN_POS 0

In the DFBTRDRV.INT file.

20653 File Ddf Full This error will be generated if no new XF$ID value in FILE.DDF can be generated. New XF$ID values are generated by scanning the FILE.DDF and taking the first available free XF$ID value.

20564 Field Ddf Full This error will be generated if no new XE$ID value in FIELD.DDF can be generated. New XE$ID values are generated by scanning the FIELD.DDF and taking the first available block of consecutive free XE$ID values, where the fields to add will fit in.

20565 Number Cannot Be Negative This error will be generated if the application tries to store a negative value to a numeric field type that does not allow negative values.

20566 Owner Name Not Valid The table cannot be opened while the ownername in not a valid one to get access to the table. This means that he table is protected against both reading and writing

20567 Restructure Not Allowed This error indicates that the table on which a restructure operation is requested does not allow that. Reasons for this might be:

  • The DDF tables are readonly

  • The table contains incompatible fieldtypes

The extra error text will indicate the source of the problem.

20568 Invalid Nullable Column This error will be given when a field is marked as nullable, but the structure for storing the nullable information is not found or incorrect.

20569 One Or More Indexes Not Created This error indicates that one or more indexes could not be created during a restructure operation. There can be various reasons why the index cannot be created. For example, because the index contains duplicate entries for an index that is supposed to be unique. Check the table after the restructure operation has completed to see what indexes have not been created.

20570 Mixed Note And Longvar Type In Record This error indicates that within one table, fields of both the NOTE and LONGVAR fieldtype have been found. This is an illegal structure.

20571 Longvar Data Too Large For Record The data that is currently put in the recordbuffer cannot be save because the total length of the record is too large for the record or the communication buffer size. By default, a record cannot be larger than 64Kb.

20572 Incompatible Database Engine Version This error indicates that the Pervasive.SQL Database Engine this Connectivity Kit is used on, is not compatible with this Connectivity Kit. You need to upgrade your Pervasive.SQL Database Engine to a later version in order to be able to work with this Connectivity Kit.

20573 Invalid Texttype The TEXT_TYPE setting in DFBTRDRV.INT has an invalid value.

20574 Invalid URI An URI with an illegal format has been specified. Allowed syntax for URI’s can be found in the Pervasive.SQL documentation.

20575 Cannot open DDfs The DDFs are opened when the first table is opened. This error will be raised if the DDFs can not be opened in DATABASE_MODE. The extra error information will specify the PSQL status code and the URI used in the open.


SQL Database Level Errors (12289)

The CLI/SQL error handling mechanism is quite different from the DataFlex mechanism. Ideally, we would be able to project the error system on to the DataFlex system. Unfortunately, this is not possible. The identification mechanism in both systems is incompatible. DataFlex uses error number where CLI/SQL uses SQL State, a 5-byte character string.

DataFlex needs an error number when reporting an error to a program. We have chosen to use one number for every CLI/SQL error that is reported to the Connectivity Kit. This number is 12289. Database level errors will always be formatted:

12289 -- <SQL State> (<Native Error>)--<Component identifier> <Error text>

SQL State

SQL States are used in SQL environments to identify a certain exception condition that has occurred. SQL states are 5 character strings using only uppercase letters A – Z and the digits 0 – 9. The string is divided into two components. The first two characters are the class code; the last three are the subclass code. For more information on SQL States, see the SQL Server documentation.

NativeErr

The native error number of the SQL Server error.

Component Identifier

The component identifier is supposed to help you identify the component that causes the error. The communication to SQL Server uses a number of components, each of which can raise an error. For errors and messages that occur outside of the SQL Server data source the component identifier format is:

[Vendor identifier][Component identifier]

For errors that occur inside the SQL Server data source the component identifier format is:

[Vendor identifier][Component identifier][Data source identifier]

Error Text

Contains the text of the error or message.

Truncated Error Text

The error messages generated by SQL back ends tend to be a bit larger than is common in a traditional DataFlex environment. The object oriented error handlers within a DataFlex environment can handle these long texts without problems. Procedural programs however tend to reserve one line of 80 positions that is used for error reporting. If the error text is larger than 80 positions, it will be truncated. If the error text is truncated, use the database documentation to find the SQL State.

You can get the complete error text by calling the LastDriverError function.

Alternatively you can set the Error_Debug_Mode configuration keyword.

See Also

SQL State Table


SQL State Table

The table below lists SQL Sates and their general description.

SQLSTATE | ERROR
01000 | General warning
01001 | Cursor operation conflict
01002 | Disconnect error
01003 | NULL value eliminated in set function
01004 | String data, right truncated
01006 | Privilege not revoked
01007 | Privilege not granted
01S00 | Invalid connection string attribute
01S01 | Error in row
01S02 | Option value changed
01S06 | Attempt to fetch before the result set returned the first rowset
01S07 | Fractional truncation
01S08 | Error saving File DSN
01S09 | Invalid keyword
07002 | COUNT field incorrect
07005 | Prepared statement not a cursor-specification
07006 | Restricted data type attribute violation
07009 | Invalid descriptor index
07S01 | Invalid use of default parameter
08001 | Client unable to establish connection
08002 | Connection name in use
08003 | Connection does not exist
08004 | Server rejected the connection
08007 | Connection failure during transaction
08S01 | Communication link failure
21S01 | Insert value list does not match column list
21S02 | Degree of derived table does not match column list
22001 | String data, right truncated
22002 | Indicator variable required but not supplied
22003 | Numeric value out of range
22007 | Invalid datetime format
22008 | Datetime field overflow
22012 | Division by zero
22015 | Interval field overflow
22018 | Invalid character value for cast specification
22019 | Invalid escape character
22025 | Invalid escape sequence
22026 | String data, length mismatch
23000 | Integrity constraint violation
24000 | Invalid cursor state
25000 | Invalid transaction state
25S01 | Transaction state
25S02 | Transaction is still active
25S03 | Transaction is rolled back
28000 | Invalid authorization specification
34000 | Invalid cursor name
3C000 | Duplicate cursor name
3D000 | Invalid catalog name
3F000 | Invalid schema name
40001 | Serialization failure
40002 | Integrity constraint violation
40003 | Statement completion unknown
42000 | Syntax error or access violation
42S01 | Base table or view already exists
42S02 | Base table or view not found
42S11 | Index already exists
42S12 | Index not found
42S21 | Column already exists
42S22 | Column not found
44000 | WITH CHECK OPTION violation
HY000 | General error
HY001 | Memory allocation error
HY003 | Invalid application buffer type
HY004 | Invalid SQL data type
HY007 | Associated statement is not prepared
HY008 | Operation canceled
HY009 | Invalid use of null pointer
HY010 | Function sequence error
HY011 | Attribute cannot be set now
HY012 | Invalid transaction operation code
HY013 | Memory management error
HY014 | Limit on the number of handles exceeded
HY015 | No cursor name available
HY016 | Cannot modify an implementation row descriptor
HY017 | Invalid use of an automatically allocated descriptor handle
HY018 | Server declined cancel request
HY019 | Non-character and non-binary data sent in pieces
HY020 | Attempt to concatenate a null value
HY021 | Inconsistent descriptor information
HY024 | Invalid attribute value
HY090 | Invalid string or buffer length
HY091 | Invalid descriptor field identifier
HY092 | Invalid attribute/option identifier
HY095 | Function type out of range
HY096 | Invalid information type
HY097 | Column type out of range
HY098 | Scope type out of range
HY099 | Nullable type out of range
HY100 | Uniqueness option type out of range
HY101 | Accuracy option type out of range
HY103 | Invalid retrieval code
HY104 | Invalid precision or scale value
HY105 | Invalid parameter type
HY106 | Fetch type out of range
HY107 | Row value out of range
HY109 | Invalid cursor position
HY110 | Invalid driver completion
HY111 | Invalid bookmark value
HYC00 | Optional feature not implemented
HYT00 | Timeout expired
HYT01 | Connection timeout expired
IM001 | Driver does not support this function
IM002 | Data source name not found and no default driver specified
IM003 | Specified driver could not be loaded
IM004 | Driver’s SQLAllocHandle on SQL_HANDLE_ENV failed
IM005 | Driver’s SQLAllocHandle on SQL_HANDLE_DBC failed
IM006 | Driver’s SQLSetConnectAttr failed
IM007 | No data source or driver specified; dialog prohibited
IM008 | Dialog failed
IM009 | Unable to load translation DLL
IM010 | Data source name too long
IM011 | Driver name too long
IM012 | DRIVER keyword syntax error
IM013 | Trace file error
IM014 | Invalid name of File DSN
IM015 | Corrupt file data source


Pervasive.SQL Database Level Errors (21000 ..)

The Pervasive error handling mechanism uses error number just like the Visual DataFlex error handling mechanism. In order to avoid error number conflicts, the Pervasive.SQL Connectivity Kit will add 21000 to the Pervasive.SQL error number. If you get an error with a number above 21000, subtract 21000 to get the original Pervasive.SQL error number. See the Pervasive.SQL documentation for a description of the error.

If for example you get error 21020: “The MicroKernel or Btrieve Requester is inactive”, subtract 21000 to get the Pervasive.SQL error number (20). In the Pervasive.SQL documentation you will find the text below (text from the Pervasive.SQL 8.5 documentation).

20: The MicroKernel or Btrieve Requester is Inactive

________________________________________

Note

For an expanded list of possible recovery solutions, consult the Pervasive.SQL Knowledge Base at http://support.pervasive.com/eSupport.

________________________________________

If you are running an application in a client/server environment:

  • Make sure the Btrieve requester is loaded.

  • Verify that the IPX/SPX or TCP/IP protocol is properly installed at the client machine and that no two machines on the network have the same Internal Network Number.

  • Make sure at least one of the client configuration options, AccessUse Local MicroKernel Engine or AccessUse Remote MicroKernel Engine is enabled. If your environment includes both a server engine and Workgroup engines, you should have both settings enabled.

  • If you are running an application in a workstation/workgroup environment, make sure the MicroKernel is loaded.

  • If you are running an application in a client/server environment and also need to access files located on a local drive:

  • Make sure the Btrieve Requester is loaded.

  • Make sure both of the client configuration options, AccessUse Local MicroKernel Engine or AccessUse Remote MicroKernel Engine are enabled.

  • Make sure a local MicroKernel is available and loaded.

  • If you are operating in a NetWare environment:

    • Make sure the MicroKernel and (if applicable) the Btrieve Requester are loaded before generating any requests.

    • Make sure the appropriate communication modules are loaded at the server.

  • If you are operating in a Windows Server environment:

    • Make sure the MicroKernel is started before generating any requests.

    • Make sure the Windows DLLs are in your path.

    • Make sure the appropriate communications modules are loaded at the server.


ODBC Data Sources

When using the ODBC Connectivity Kit you will have to setup an ODBC data source to connect to. This section introduces ODBC data sources.

There are two types of Data Sources, machine- and file Data Sources. Both types contain similar information, they differ in the way the information is stored. Because of these differences, they are used in a somewhat different manner.

Machine Data Sources are stored on the client system. Associated with the Data Source is all the information the ODBC Manager and database driver need to connect to the specified database. There are two Data Source subtypes, User- and System Data Sources. One specific user of the machine can use a User Data Sources; all users that use the machine where the Data Source is defined can use a System Data Source.

File Data Sources are stored in a file with extension .dsn (in ASCII format). The file Data Source stores all the information the ODBC Manager and database driver need to connect to the specified database. The file can be manipulated like any other text file.

Creating a Data Source

Data Sources are created with a program called the ODBC Administrator. The ODBC Administrator can be started from the Control Panel or from Database Builder. Some database environments add a shortcut to the ODBC Administrator to the start menu options.

When adding a Data Source the ODBC Administrator presents a list of all available drivers. The user chooses one driver and the Administrator passes control to the driver set up logic so it can obtain all required information. The information required to set up a Data Source for a driver is driver (and backend) specific. See below for a sample of a driver set up panel. Depending on the Data Source type the information is stored in the machines registry or a disk file.

Information of a particular Data Source is stored in the following way:

DSN Type

Information Location

User

User data sources are stored in the registry at HKEY_CURRENT_USER\SOFTWARE\ODBC\ODBC.INI under this key a subkey for every User Data Source can be found.

User Data Sources are typically used in an environment where there is only one user or as a test for ODBC connectivity.

System

System Data Sources are stored in the registry at HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI under this key a subkey for every System Data Source can be found.

System Data Sources are typically used when there is a need to access data from one machine. This usually is a server type process like the Visual DataFlex Web Application Server.

File

File Data Sources are stored in disk files. For specifics on the contents of the file data source, see your ODBC driver’s documentation.

File Data Sources can be shared among all users that have access to the disk file.

When an application needs to access the data defined in a Data Source, it calls the ODBC Manager and passes the name of the data source. The ODBC Manager identifies the driver to use, loads it and passes the Data Source name. The driver uses the Data Source name to connect to the Data Source. Connecting to a Data Source may involve prompting the user for login information.


ODBC Escape Sequences

To setup default values ODBC Escape Sequences can be used. ODBC defines a number of escape sequences of which we can use the literal and scalar function escape sequence.

An ODBC escape sequence is enclosed in curly brackets {}. The escape sequence is recognized by SQL Server and translated into the SQL Server equivalent.

Literals

The ODBC literal escape sequence is used to define date, time and datetime literals. These are defined by using {literaltype ‘literal’}. The following literal types are defined:

Type | Meaning | Format of Value
d | Date | yyyy-mm-dd
t | Time | hh:mm.ss
ts | Timestamp | yyyy-mm-dd hh:mm:ss

Scalar Functions

The ODBC scalar function escape sequence is used to define a function call to a scalar function. A scalar function returns a value for every row. Function calls are defined by using {fn scalar-function}. Several different types of functions have been defined: string functions, numeric functions, date time functions, system functions and data type conversion functions.

See Also

String Functions

Numeric Functions

Time, Date and Interval Functions

System Functions

Data Type Conversion Functions


String Functions

Function | Description
ASCII (string_exp) | Returns the ASCII code value of the leftmost character of string _exp as an integer.
BIT_LENGTH (string_exp) | Returns the length in bits of the string expression.
CHAR (code) | Returns the character that has the ASCII code value specified by code. The value of code should be between 0 and 255.
CHAR_LENGTH (string_exp) CHARACTER_LENGTH (string_exp) | Returns the length in characters of the string expression, if the string expression is of a character data type; otherwise returns the length in bytes of the string expression.
CONCAT (string_exp1, string_exp2) | Returns a character string that is the result of concatenating string_exp2 to string_exp1.
DIFFERENCE (string_exp1, string_exp2) | Returns an integer value that indicates the difference between the values returned by the SOUNDEX function for string_exp1 and string_exp2.
INSERT (string_exp1, start, length, string_exp2) | Returns a character string where length characters have been deleted from string_exp1 at start and where string_exp2 has been inserted into string_exp1 at start.
LCASE (string_exp) | Returns a string where all uppercase characters in string_exp have been converted to lowercase.
LEFT (string_exp, count) | Returns the count leftmost characters of string_exp.
LENGTH (string_exp) | Returns the number of characters in string_exp, excluding trailing blanks.
LOCATE (string_exp1, string_exp2 [,start]) | Returns the starting position of the first occurrence of string_exp1 within string_exp2. The search begins on the first character position in string_exp2 unless the optional argument start is specified. If start is specified the search begins on character position indicated by the value of start. Character positions start at 1. The function returns 0 if string_exp1 is not found in string_exp2.
LTRIM (string_exp) | Returns string_exp with leading blanks removed.
OCTET_LENGTH (string_exp) | Returns the length in bytes of the string_exp.
POSITION (string_exp1 IN string_exp2) | Returns the position of string_exp1 in string_exp2.
REPEAT (string_exp, count) | Returns a string composed of string_exp repeated count times.
REPLACE (stirng_exp1, string_exp2, string_exp3) | Replace occurences of string_exp2 in string_exp1 with string_exp3.
RIGHT (string_exp, count) | Returns the count rightmost characters of string_exp.
RTRIM (string_exp) | Returns string_exp with trailing blanks removed.
SOUNDEX (string_exp) | Returns a character string representing the sound of the words in string_exp.
SPACE (count) | Returns a string consisting of count spaces.
SUBSTRING (string_exp, start, length) | SUBSTRING (string_exp, start, length) Returns the substring from string_exp beginning at start that is length characters long.
UCASE (string_exp) | Returns a string where all lowercase characters in string_exp have been converted to uppercase.

See Also

ODBC Escape Sequences

Numeric Functions

Time, Date and Interval Functions

System Functions

Data Type Conversion Functions


Numeric Functions

Function | Description
ABS (numeric_exp) | Absolute value.
ACOS (float_exp) | Arc cosine as an angle expressed in radians
ASIN (float_exp) | Arc sine as an angle expressed in radians
ATAN (float_exp) | Arc tangent as an angle expressed in radians
ATAN2 (float_exp1, float_exp2) | Arc tangent of the x- and y-coordinates specified by float_exp1 and float_exp2 as an angle expressed in radians
CEILING (numeric_exp) | Smallest integer greater than or equal to numeric_exp.
COS (float_exp) | The cosine of float_exp where float_exp is an angle expressed in radians.
COT (float_exp) | The cotangent of float_exp where float_exp is an angle expressed in radians.
DEGREES (numeric_exp) | Converts to the number of degrees where numeric_exp is an angle expressed in radians.
EXP (float_exp) | Exponential value of float_exp
FLOOR (numeric_exp) | Largest integer less than or equal to numeric_exp.
LOG (float_exp) | Natural logarithm of float_exp.
LOG10 (float_exp) | Base 10 logarithm of float_exp.
MOD (integer_exp1, integer_exp2) | Remainder (modulus) of integer_exp1 divided by integer_exp2.
PI () | Constant value of pi.
POWER (numeric_exp, integer_exp) | Numeric_exp to the power of integer_exp.
RADIANS (numeric_exp) | Converts to the number of radians where numeric_exp is an angle expressed in degrees.
RAND ([integer_exp]) | Random number using the optional integer_exp as seed value.
ROUND (numeric_exp, integer_exp) | Numeric_exp rounded to integer_exp positions right of the decimal separator.
SIGN (numeric_exp) | Returns an indicator of the sign of numeric_exp. If numeric_exp is less than zero, -1 is returned. If numeric_exp is zero, 0 is returned. If numeric_exp is greater than zero, 1 is returned.
SIN (float_exp) | The sine of float_exp where float_exp is an angle expressed in radians.
SQRT (float_exp) | Square root of float_exp.
TAN (float-exp) | The tangent of float_exp where float_exp is an angle expressed in radians.
TRUNCATE (numeric_exp, integer_exp) | Numeric_exp truncated to integer_exp positions right of the decimal separator.

See Also

ODBC Escape Sequences

String Functions

Time, Date and Interval Functions

System Functions

Data Type Conversion Functions


Time, Date and Interval Functions

Function | Description
CURRENT_DATE () | Current date.
CURRENT_TIME ([time_precision]) | Current local time, the time_precision optional argument determines the seconds precision of the returned value.
CURRENT_TIMESTAMP ([timestamp_precision]) | Current local data and local time as a timestamp value, the timestamp_precision optional argument determines the seconds precision of the returned value.
CUR_DATE () | Current date.
CURTIME () | Current local time.
DAYNAME (date_exp) | The name of the day of the passed date.
DAYOFMONTH (date_exp) | The number of the day in the month in date_exp in the range of 1 – 31.
DAYOFWEEK (date_exp) | The number of the day of the week in date_exp in the range 1-7 where 1 is Sunday.
DAYOFYEAR (date_exp) | The number of the day of the year in date_exp in the range 1- 366.
EXTRACT (extract_field FROM extract_source) | Extracts the extract_field portion of the extract_source. Extract_source is a datetime or interval expression. Extract_field can be one of the following keywords: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND.
HOUR (time_exp) | The hour of the time_exp in the range 0 – 23.
MINUTE (time_exp) | The minute in time_exp in the range 0 – 59.
MONTH (date_exp) | The month in date_exp in the range 1 – 12.
MONTHNAME (date_exp) | The name of the month in date_exp.
NOW () | Current date and time as a timestamp value.
QUARTER (date-exp) | The quarter in date_exp in the range 1 – 4. Where quarter 1represent January 1 through March 31.
SECOND (time_exp) | The seconds in time_exp in the range 0 – 59.
TIMESTAMPDIFF (interval, timestamp_exp1, timestamp_exp2) | The integer number of intervals that timestamp_exp2 is gretaer than timestamp_exp1. Interval can be one of the following keywords: SQL_TSI_FRAC_SECOND, SQL_TSI_SECOND, SQL_TSI_MINUTE, SQL_TSI_HOUR, SQL_TSI_DAY, SQL_TSI_WEEK, SQL_TSI_MONTH, SQL_TSI_QUARTER, SQL_TSI_YEAR.
WEEK (date_exp) | The weeknumber of the year in date_exp in the range 1 – 53.
YEAR (date_exp) | The year of date_exp.

See Also

ODBC Escape Sequences

String Functions

Numeric Functions

System Functions

Data Type Conversion Functions


System Functions

Function | Description
DATABASE () | The name of the database.
IFNULL (exp, value) | If exp is null, value is returned. If exp is not null, exp is returned.
USER () | The user name. This may be different from the login name

See Also

ODBC Escape Sequences

String Functions

Numeric Functions

Time, Date and Interval Functions

Data Type Conversion Functions


Data Type Conversion Functions

ODBC defines one explicit data type conversion function, convert. Its syntax is CONVERT (value_exp, data_type). The function returns value_exp converted to data_type where data_type is one of the folowing keywords:

  • SQL_BIGINT

  • SQL_BINARY

  • SQL_BIT

  • SQL_CHAR

  • SQL_DECIMAL

  • SQL_DOUBLE

  • SQL_FLOAT

  • SQL_INTEGER

  • SQL_INTERVAL_MONTH

  • SQL_INTERVAL_YEAR

  • SQL_INTERVAL_YEAR_TO_MONTH

  • SQL_INTERVAL_DAY

  • SQL_INTERVAL_HOUR

  • SQL_INTERVAL_MINUTE

  • SQL_INTERVAL_SECOND

  • SQL_INTERVAL_DAY_TO_HOUR

  • SQL_INTERVAL_DAY_TO_MINUTE

  • SQL_INTERVAL_DAY_TO_SECOND

  • SQL_INTERVAL_HOUR_TO_MINUTE

  • SQL_INTERVAL_HOUR_TO_SECOND

  • SQL_INTERVAL_MINUTE_TO_SECOND

  • SQL_LONGVARBINARY

  • SQL_LONGVARCHAR

  • SQL_NUMERIC

  • SQL_REAL

  • SQL_SMALLINT

  • SQL_TYPE_DATE

  • SQL_TYPE_TIME

  • SQL_TYPE_TIMESTAMP

  • SQL_TINYINT

  • SQL_VARBINARY

  • SQL_VARCHAR

  • SQL_WCHAR

  • SQL_WLONGVARCHAR

  • SQL_WVARCHAR

See Also

ODBC Escape Sequences

String Functions

Numeric Functions

Time, Date and Interval Functions

System Functions


Create a DB2 Database

CreaDB

The creadb command line program is used to create a DB2 database (on default table spaces) that uses a given DataFlex Collating Sequence. The collating sequence of a database defines the sort order. DB2 uses a number of predefined collating sequences. If you want to create a database that uses exactly the same collating sequence as the DataFlex environment, use creadb.

For more information on databases and the options available when creating a database, refer to the DB2 documentation.

Usage

Creadb is a command line utility. It uses flags to setup flags can be passed both using the traditional Unix syntax “-flag” or DOS/Windows syntax “/flag”. The order the flags are specified is not important.

Required Flags:

Flag | Required Parameter
-d | Name of the database to create.
-c | Path and file name of the DataFlex collating sequence.

Optional Flags:

Flag | Required Parameter
-a | Alias name of the database to create, the database name (see -d) will be used if not supplied.
-u | User identification to use when attaching to the node.
-p | Password of the user.
-n | Name of the node on which to crate the database. Use "list node directory" in the CLP for a list of node names.
-s | The codeset to use for the database (ISO8859-1 by default).
-t | The country identifier for the database (En_US by default).
-| | The location (path) on which to create the database.
-x<subflag> | Extended options
-xc | Comment for the database. If the comment contains spaces, surround it with double quotes.
-xs | Number of file segments to be created in the database.
-xx | Default extent size of table spaces.
-h | Show usage.

For more information on databases and the options available when creating a database, refer to the DB2 documentation.

Special Note

  • Do not add a space between the flag and the required parameter

  • Parameters should not be specified within quotes – only if they have spaces in them, like paths or comments

Examples

To create database MyDB using a collating sequence located in C:\Program Files\Visual DataFlex 10\Usr, use:

creadb –dMyDB –c”C:\Program Files\Visual DataFlex 10\Usr\df_collate.cfg”

To have user Auser with password userPwd create database MyDB using alias SW and a collating sequence located in C:\Program Files\Collate, use:

creadb –dMyDB –aSW –cc:\Collate\df_collate.cfg –uAuser –puserPwd


Driver Configuration

It is possible to configure the behavior of a Connectivity Kit through configuration files. Configuration files can be located anywhere in DFPATH. In general one configuration file per install is enough. There are situations where there is a need to have different configurations for different deploy environments on one machine/network. In that case the configuration file should be placed in the deploy environment rather than in the overall Visual DataFlex environment.

Connectivity Kit Configuration files are named:

SQL Server Mssqldrv.int

DB2 DB2_drv.int

ODBC ODBC_drv.int

Pervasive.SQL Dfbtrdrv.int

These Connectivity Kit configuration files setup "global" Connectivity Kit behavior. Since the ODBC Connectivity Kit allows a Visual DataFlex program to connect to any database for which there is an ODBC driver available, it requires a more flexible way to configure, this is why the ODBC Connectivity Kit supports database specific configuration files in addition to the global configuration file. A database configuration file is called: <database>.INT.

In this section we describe the configuration options for specific database servers. The most popular database systems are discussed. If the database you are connecting to is not discussed in this document, there is a section on setting up a new configuration file.

The general format of the configuration file consists of lines of text separated by carriage return and line feed (CR/LF) characters. Each line may be up to 255 characters long and consists of a keyword and value pair or a comment.

Keywords may be upper, lower or mixed case. Comments are preceded by the semicolon (;) character. In-line comments are not supported. White space, defined as blank spaces and tab characters, is not significant and may be used for legibility.


MSSQLDRV.INT

The general behavior of the SQL Server Connectivity Kit can be configured through the configuration file, mssqldrv.int. The configuration file is read when the Connectivity Kit initializes.

Configuration files can be located anywhere in DFPATH. In general one configuration file per installation is enough. There are situations where there is a need to have different configurations for different deploy environments on one machine/network. In that case the configuration file should be placed in the deploy environment rather than in the overall DataFlex environment.

A sample configuration file MSSQLDRVSample.INT is installed in the Visual DataFlex bin directory. The sample configuration file can be used as the basis of an environment configuration file.

The keywords will be presented in the following format:

<Keyword>

Value <Possible values>

Associated attribute <Attribute_Name> (<Type>)

Where

  • <Keyword> The keyword to set in the intermediate file.

  • <Possible values> A list of values or a description of possible values for the keyword.

  • <Attribute_Name> The name of the attribute associated with the keyword.

  • (<Type>) The type of the associated keyword.

Keywords

The supported keywords for the global intermediate file are:

Cache_Path

Value Path to a valid directory

Associated attribute None

Sets up a directory to store cache files. By default, cache files will be stored in the same directory as the corresponding intermediate file.

Default_Default_ASCII

Value Default specification

Associated attribute None

Sets up the default value that will be used when an ASCII field is created. Fields can be created during conversion or within a restructure operation.

Default_Default_Binary

Value Default specification

Associated attribute None

Sets up the default value that will be used when a Binary field is created. Fields can be created during conversion or within a restructure operation.

Default_Default_Date

Value Default specification

Associated attribute None

Sets up the default value that will be used when a Date field is created. Fields can be created during conversion or within a restructure operation.

Default_Default_Numeric

Value Default specification

Associated attribute None

Sets up the default value that will be used when a Numeric field is created. Fields can be created during conversion or within a restructure operation.

Default_Default_Text

Value Default specification

Associated attribute None

Sets up the default value that will be used when a Text field is created. Fields can be created during conversion or within a restructure operation.

Default_Nullable_ASCII

Value Integer value

Associated attribute None

Sets up if ASCII fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero), all other integer values will allow null values.

Default_Nullable_Binary

Value Integer value

Associated attribute None

Sets up if Binary fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero), all other integer values will allow null values.

Default_Nullable_Date

Value Integer value

Associated attribute None

Sets up if Date fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero), all other integer values will allow null values.

Default_Nullable_Numeric

Value Integer value

Associated attribute None

Sets up if Numeric fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero), all other integer values will allow null values.

Default_Nullable_Text

Value Integer value

Associated attribute None

Sets up if Text fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero), all other integer values will allow null values.

Default_Record_Identity_Hiding

Value Integer value

Associated attribute None

When old definition tables are opened - with a record identity column called DFRECNUM that is placed at he end of the record – this attributes determines if the record identity is visible or not. Setting the attribute to a non-zero value will hide every record identity column in every table.

Default_Table_Character_Format

Value ANSI, OEM

Associated attribute None

The default table character format to use when creating new tables.

Default_Use_Dummy_Zero_Date

Value Integer value

Associated attribute None

Sets up the default value of the DF_FILE_USE_DUMMY_ZERO_DATE attribute for new tables created in a structure operation. Dummy zero dates will not be used if set to 0, all other integer values will use dummy zero dates.

Error_Debug_Mode

Value Integer value

Associated attribute None

Sets the error debug mode OFF if attribute is set to 0 (zero), all other integer values will switch the error debug mode ON. When the error debug mode is ON all errors generated by the database back-end will be displayed in a message box. This mode can be used in procedural environments where the screen space reserved to show error messages is often too small to show the complete text of the error message.

Report_Active_Column_Errors

Value Integer value

Associated attribute None

Switches error reporting on active columns ON or OFF. The reporting is OFF if the attribute is set to 0 (zero), all other integer values will switch reporting ON. By default, active column errors are not reported.

Report_Cache_Errors

Value Integer value

Associated attribute None

Switches reporting on cache read errors ON or OFF. The reporting is OFF if the attribute is set to 0 (zero), all other integer values will switch reporting ON. By default, cache read errors are not reported.

Use_Cache

Value Integer value

Associated attribute None

Switches the use of structure caching ON or OFF. Structure cache is OFF if the attribute is set to 0 (zero), all other integer values will switch structure caching ON. By default, structure cache is ON.

Use_Cache_Expiration

Value Integer value

Associated attribute None

Switches the structure caching intermediate file expiration checking ON or OFF. Expiration check is OFF if the attribute is set to 0 (zero), all other integer values will switch reporting ON. By default, expiration checking is ON.

Sample Configuration File

A configuration file that sets up date columns not to allow null values and to use the system date as default value looks like:

DEFAULT_NULLABLE_DATE 0

DEFAULT_DEFAULT_DATE {fn current_date()}


DB2_DRV.INT

The general behavior of the DataFlex Connectivity Kit for DB2 can be configured through the configuration file, db2_drv.int. The configuration file is read when the Connectivity Kit initializes.

Configuration files can be located anywhere in DFPATH. In general one configuration file per installation is enough. There are situations where there is a need to have different configurations for different deploy environments on one machine/network. In that case the configuration file should be placed in the deploy environment rather than in the overall DataFlex environment.

A sample configuration file DB2_DRVSample.INT is installed in the DataFlex bin directory. The sample configuration file can be used as the basis of an environment configuration file.

The keywords will be presented in the following format:

<Keyword>

Value <Possible values>

Associated attribute <Attribute_Name> (<Type>)

Where

  • <Keyword> The keyword to set in the intermediate file.

  • <Possible values> A list of values or a description of possible values for the keyword.

  • <Attribute_Name> The name of the attribute associated with the keyword.

  • (<Type>) The type of the associated keyword.

Keywords

The supported keywords for the global intermediate file are:

Cache_Path

Value Path to a valid directory

Associated attribute None

Sets up a directory to store cache files. By default, cache files will be stored in the same directory as the corresponding intermediate file.

Default_Default_ASCII

Value Default specification

Associated attribute None

Sets up the default value that will be used when an ASCII field is created. Fields can be created during conversion or within a restructure operation.

Default_Default_Binary

Value Default specification

Associated attribute None

Sets up the default value that will be used when a Binary field is created. Fields can be created during conversion or within a restructure operation.

Default_Default_Date

Value Default specification

Associated attribute None

Sets up the default value that will be used when a Date field is created. Fields can be created during conversion or within a restructure operation.

Default_Default_Numeric

Value Default specification

Associated attribute None

Sets up the default value that will be used when a Numeric field is created. Fields can be created during conversion or within a restructure operation.

Default_Default_Text

Value Default specification

Associated attribute None

Sets up the default value that will be used when a Text field is created. Fields can be created during conversion or within a restructure operation.

Default_Nullable_ASCII

Value Integer value

Associated attribute None

Sets up if ASCII fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero). All other integer values will allow null values.

Default_Nullable_Binary

Value Integer value

Associated attribute None

Sets up if Binary fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero). All other integer values will allow null values.

Default_Nullable_Date

Value Integer value

Associated attribute None

Sets up if Date fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero). All other integer values will allow null values.

Default_Nullable_Numeric

Value Integer value

Associated attribute None

Sets up if Numeric fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero). All other integer values will allow null values.

Default_Nullable_Text

Value Integer value

Associated attribute None

Sets up if Text fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero). All other integer values will allow null values.

Default_Record_Identity_Hiding

Value Integer value

Associated attribute None

When old definition tables are opened - with a record identity column called DFRECNUM that is placed at he end of the record – this attributes determines if the record identity is visible or not. Setting the attribute to a non-zero value will hide every record identity column in every table.

Default_Table_Character_Format

Value ANSI, OEM

Associated attribute None

The default table character format to use when creating new tables.

Default_Use_Dummy_Zero_Date

Value Integer value

Associated attribute None

Sets up the default value of the DF_FILE_USE_DUMMY_ZERO_DATE attribute for new tables created in a structure operation. Dummy zero dates will not be used if set to 0, all other integer values will use dummy zero dates.

Error_Debug_Mode

Value Integer value

Associated attribute None

Sets the error debug mode OFF if attribute is set to 0 (zero), all other integer values will switch the error debug mode ON. When the error debug mode is ON all errors generated by the database back-end will be displayed in a message box. This mode can be used in procedural environments where the screen space reserved to show error messages is often too small to show the complete text of the error message.

This seting will have no effect in a Linux environment.

Report_Active_Column_Errors

Value Integer value

Associated attribute None

Switches error reporting on active columns ON or OFF. The reporting is OFF if the attribute is set to 0 (zero), all other integer values will switch reporting ON. By default, active column errors are not reported.

Report_Cache_Errors

Value Integer value

Associated attribute None

Switches reporting on cache read errors ON or OFF. The reporting is OFF if the attribute is set to 0 (zero), all other integer values will switch reporting ON. By default, cache read errors are not reported.

Use_Cache

Value Integer value

Associated attribute None

Switches the use of structure caching ON or OFF. Structure cache is OFF if the attribute is set to 0 (zero), all other integer values will switch structure caching ON. By default, structure cache is ON.

Use_Cache_Expiration

Value Integer value

Associated attribute None

Switches the structure caching intermediate file expiration checking ON or OFF. Expiration check is OFF if the attribute is set to 0 (zero), all other integer values will switch reporting ON. By default, expiration checking is ON.

Sample Configuration File

A sample configuration file is installed in the DataFlex bin directory. The file is called db2_drvsample.int. It contains all possible settings and comments that describe the settings.

A configuration file that sets up date columns not to allow null values and to use the system date as default value looks like:

DEFAULT_NULLABLE_DATE 0

DEFAULT_DEFAULT_DATE {fn current_date()}


ODBC_DRV.INT

The general behavior of the ODBC Connectivity Kit can be configured through the configuration file, odbc_drv.int. The configuration file is read when the Connectivity Kit initializes.

A sample configuration file ODBC_DRVSample.INT is installed in the DataFlex bin directory. The sample configuration file can be used to base an environment’s configuration file on.

The keywords will be presented in the following format:

<Keyword>

Value <Possible values>

Associated Attribute <Attribute_Name> (<Type>)

Where

  • <Keyword> The keyword to set in the intermediate file.

  • <Possible values> A list of values or a description of possible values for the keyword.

  • <Attribute_Name> The name of the attribute associated with the keyword.

  • (<Type>) The type of the associated keyword.

Keywords

The supported keywords for the global intermediate file are:

Cache_Path

Value Path to a valid directory

Associated Attribute None

Sets up a directory to store cache files. By default, cache files will be stored in the same directory as the corresponding intermediate file.

Default_Default_ASCII

Value Default specification

Associated Attribute None

Sets up the default value that will be used when an ASCII field is created. Fields can be created during conversion or within a restructure operation.

This keyword can also be specified in the database specific configuration file.

Default_Default_Binary

Value Default specification

Associated Attribute None

Sets up the default value that will be used when a Binary field is created. Fields can be created during conversion or within a restructure operation.

This keyword can also be specified in the database specific configuration file.

Default_Default_Date

Value Default specification

Associated Attribute None

Sets up the default value that will be used when a Date field is created. Fields can be created during conversion or within a restructure operation.

This keyword can also be specified in the database specific configuration file.

Default_Default_Numeric

Value Default specification

Associated Attribute None

Sets up the default value that will be used when a Numeric field is created. Fields can be created during conversion or within a restructure operation.

This keyword can also be specified in the database specific configuration file.

Default_Default_Text

Value Default specification

Associated Attribute None

Sets up the default value that will be used when a Text field is created. Fields can be created during conversion or within a restructure operation.

This keyword can also be specified in the database specific configuration file.

Default_Nullable_ASCII

Value Integer value

Associated Attribute None

Sets up if ASCII fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero), all other integer values will allow null values.

This keyword can also be specified in the database specific configuration file.

Default_Nullable_Binary

Value Integer value

Associated Attribute None

Sets up if Binary fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero), all other integer values will allow null values.

This keyword can also be specified in the database specific configuration file.

Default_Nullable_Date

Value Integer value

Associated Attribute None

Sets up if Date fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero), all other integer values will allow null values.

This keyword can also be specified in the database specific configuration file.

Default_Nullable_Numeric

Value Integer value

Associated Attribute None

Sets up if Numeric fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero), all other integer values will allow null values.

This keyword can also be specified in the database specific configuration file.

Default_Nullable_Text

Value Integer value

Associated Attribute None

Sets up if Text fields allow null values by default. Null values are not allowed if the attribute is set to 0 (zero), all other integer values will allow null values.

This keyword can also be specified in the database specific configuration file.

Default_Record_Identity_Hiding

Value Integer value

Associated Attribute None

When old definition tables are opened - with a record identity column called DFRECNUM that is placed at he end of the record – this attributes determines if the record identity is visible or not. Setting the attribute to a non-zero value will hide every record identity column in every table.

Default_Table_Character_Format

Value ANSI, OEM

Associated Attribute None

The default table character format to use when creating new tables.

Default_Use_Dummy_Zero_Date

Value Integer value

Associated Attribute None

Sets up the default value of the DF_FILE_USE_DUMMY_ZERO_DATE attribute for new tables created in a structure operation. Dummy zero dates will not be used if set to 0, all other integer values will use dummy zero dates.

Driver_Date_Format

Value EUROPEAN, MILITARY, USA

Associated Attribute None

ODBC demands that drivers use the military format (yyy-mm-dd) in the supported SQL. Nevertheless there are drivers that do not use this format but rather a format that depends on the country settings of the machine or the database client software. For those environments the driver date separators can be set

A configuration file that sets the date format to European would look like:

DRIVER_DATE_FORMAT EUROPEAN

DRIVER_DATE_SEPARATOR /

This keyword can also be specified in the database specific configuration file.

Driver_Date_Separator

Value Character

Associated Attribute None

ODBC demands that drivers use the military format (yyy-mm-dd) in the supported SQL. Nevertheless there are drivers that do not use this format but rather a format that depends on the country settings of the machine or the database client software. For those environments the driver date separators can be set

A configuration file that sets the date format to European would look like:

DRIVER_DATE_FORMAT EUROPEAN

DRIVER_DATE_SEPARATOR /

This keyword can also be specified in the database specific configuration file.

Driver_Decimal_Separator

Value Character

Associated Attribute None

ODBC demands that drivers use the US decimal separator in the supported SQL. Nevertheless there are drivers that do not use this separator but rather a separator that depends on the country settings of the machine or the database client software. For those environments the driver separators can be set.

A configuration file that sets the numeric format to European would look like:

DRIVER_DECIMAL_SEPARATOR ,

DRIVER_THOUSANDS_SEPARATOR .

This keyword can also be specified in the database specific configuration file.

Driver_Thousands_Separator

Value Character

Associated Attribute None

ODBC demands that drivers use the US thousands separator in the supported SQL. Nevertheless there are drivers that do not use this separator but rather a separator that depends on the country settings of the machine or the database client software. For those environments the driver separators can be set.

A configuration file (ODBC_DRV.INT) that sets the numeric format to European would look like:

DRIVER_DECIMAL_SEPARATOR ,

DRIVER_THOUSANDS_SEPARATOR .

This keyword can also be specified in the database specific configuration file.

Dummy_Zero_Date_Value

Value String value with dummy date value

Associated Attribute None

Sets up the value of the dummy zero date. This should be set to the lowest possible date value that the database supports. IN most databases the default 0001-01-01 can be used. Some databases however support a different lowest possible date value.

This keyword can also be specified in the database specific configuration file.

Error_Debug_Mode

Value Integer value

Associated Attribute None

Sets the error debug mode off if attribute is set to 0 (zero), all other integer values will switch the error debug mode on. When the error debug mode is on all errors generated by the database backend will be displayed in a message box. This mode can be used in procedural environments where the screen space reserved to show error messages is often too small to show the complete text of the error message.

Ignore_UCASE_Support

Value Integer value

Associated Attribute None

Turns on the check for an uppercase scalar function when case insensitive index segments are used when set to 0 (zero), all other integer values will switch this check off. When switched off, case insensitive index segments will be ignored. By default the check for an uppercase scalar function is on.

This keyword can also be specified in the database specific configuration file.

Max_Active_Statements

Value Integer value

Associated Attribute None

The maximum number of concurrently active statements allowed per connection, 0 (zero) means there is no limit.

This attribute can be queried through ODBC but we have found that some drivers do not return a reliable value. The value of the attribute is used by the Connectivity Kit to determine the size of the statement pool. The Connectivity Kit keeps track of the statements that are used per connection in a Most Recently Used sorted list. If the maximum number of statements is in use, the least recently used statement will be freed whenever an additional statement is required.

Some ODBC drivers return a value of 1 for this attribute. This will make the Connectivity Kit free and re-allocate statements all the time. For some drivers the value is accurate (MS Jet Engine ODBC Driver e.g.) but for others it is not (Oracle ODBC driver e.g.). In case the attribute value is not accurate you can overwrite it by setting the Max_Active_Statements keyword.

This keyword can also be specified in the database specific configuration file.

Report_Active_Column_Errors

Value Integer value

Associated Attribute None

Switches error reporting on active columns on or off. The reporting is off if the attribute is set to 0 (zero), all other integer values will switch reporting on. By default, active column errors are not reported.

Report_Cache_Errors

Value Integer value

Associated Attribute None

Switches reporting on cache read errors on or off. The reporting is off if the attribute is set to 0 (zero), all other integer values will switch reporting on. By default, cache read errors are not reported.

Use_Cache

Value Integer value

Associated Attribute None

Switches the use of structure caching on or off. Structure cache is off if the attribute is set to 0 (zero), all other integer values will switch structure caching on. By default, structure cache is on.

Use_Cache_Expiration

Value Integer value

Associated Attribute None

Switches the structure caching intermediate file expiration checking on or off. Expiration check is off if the attribute is set to 0 (zero), all other integer values will switch reporting on. By default, expiration checking is on.


DFBTRDRV.INT

The general behavior of the Connectivity Kit can be configured through the Connectivity Kit configuration file: DFBTRDRV.INT. The configuration file contains setting that change the behavior of the Connectivity Kit in various situations.

A sample configuration file DFBTRDRV_DEFAULT.INT is installed in the DataFlex bin directory. The sample configuration file can be used as the basis of an environment configuration file.

Keywords

The following sections list all possible settings for the configuration file DFBTRDRV.INT.

ACS

Possible values Name of an ACS file

Default value <none>

This keyword needs to be followed by a path to a file containing an Alternate Collating Sequence table to be used on String fields. In Pervasive.SQL, this might be a STRING, LSTRING or ZSTRING type. This collating sequence will be used for every String field in an index that does not specify case-insensitive. The ACS to be used for fields using the case-insensitive switch must be named after the ACS_UPPER keyword.

The filename needs to be passed within quotes. When a path is specified, the Connectivity Kit will read the table using that path. If no path is specified, the DFPath will be used to search for the file.

ACS_UPPER

Possible values Name of an ACS file

Default value <none>

This keyword needs to be followed by a path to a file containing an Alternate Collating Sequence table to be used on String fields that use the case-insensitive switch. In Pervasive.SQL, this might be a STRING, LSTRING or ZSTRING type. This collating sequence will be used for every String field in an index that has been defined using the case-insensitive switch. The ACS to be used for fields not using the case-insensitive switch must be given using the ACS keyword.

The filename needs to be passed within quotes. When a path is specified, the Connectivity Kit will read the table using that path. If no path is specified, the DFPath will be used to search for the file.

ALLOW_UNLOCKED_UPDATES

Possible values 0 (False) or 1 (True)

Default value 0

By default the Connectivity Kit requires a program to lock a record before it can make a change to it. When record has not been locked it will generate an error. To suppress this error, this setting can be set to 1 (TRUE).

AUTO_LOGOUT

Possible values 0 (False) or 1 (True)

Default value 1

This setting controls whether the DDF tables will be closed automatically once the last Pervasive.SQL table has been closed. By default, it will close the tables because this opens the way to switch DDF tables by changing the DFPATH at runtime. If you do not want to close the DDF tables after the last Pervasive.SQL table has been closed, you have to set the value of this setting to 0.

AUTO_MARK_SYSFILE

Possible values 0 (False) or 1 (True)

Default value 1

This setting controls how a table containing one record and no indexes will be treated when opened. If this setting is true (not equal to 0) then the table will be marked as being a system table. If this value has been set to 0, it will be treated like a normal table.

BTR_PATH

Possible values A valid path. UNC path is possible

Default value none

NOTE: This setting applies only when DATABASE_MODE setting is false. This setting will not be used when DATABASE_MODE setting is true.

This setting controls the location of the Pervasive.SQL tables. By default is has not been set which means it will use the datapath/ DFPath to find a Pervasive.SQL table. When this setting has been used it needs to point to a directory. The Connectivity Kit will try to locate all Pervasive.SQL tables in this location and no longer use the path. Note that this setting can only have one path!

CACHE_PATH

Possible values A valid path. UNC path is possible

Default value None

This setting controls the location of structure cache (.CCH) files. By default structure cache files are searched for along datapath/DFPATH. New structure cache files are created in the first directory of datapath/DFPATH if no CACHE_PATH is specified.

COMP3_SIGN_NEG

Possible values 13

Default value 13

The value the Connectivity Kit uses for the negative sign in numeric values. Numeric values are stored as COMP3-type fields in Pervasive.SQL tables. In COMP3 type fields the sign is determined by a 1-byte value. Pervasive.SQL allows one value for the negative sign: Hexadecimal 0x0d (decimal 13). Specify the decimal value in the DFBTRDRV.INT file.

NOTE: It is hardly ever necessary to change this value. Changing this is considered advanced usage. Do not change this setting from its default.

COMP3_SIGN_POS

Possible values 12 or 15

Default value 15

The value the Connectivity Kit uses for the positive sign in numeric values. Numeric values are stored as COMP3 type fields in Pervasive.SQL tables. In COMP3-type fields the sign is determined by a 1-byte value. Pervasive.SQL allows two values for the positive sign: Hexadecimal 0x0c (decimal 12) and hexadecimal 0x0F (decimal 15). Specify the decimal value in the DFBTRDRV.INT file.

NOTE: It is hardly ever necessary to change this value. Changing this is considered advanced usage. Do not change this setting from its default, unless absolutely necessary.

CONVERT_LONG_FILENAMES

Possible values 0 (False) or 1 (True)

Default value 1

The Connectivity Kit automatically converts a long filename to a short one before it tries to open a table. This conversion causes a Novell client to try to login to a Novell server instead of just perform an authentication. This is typically used when using a Novell Runtime server that only allows one concurrent user. This setting switches on or off the conversion of long filenames.

DATABASE_MODE

Possible values 0 (Off) or 1 (On)

Default value 0

The database_mode determines how the Connectivity Kit locates Pervasive.SQL metadata tables and data tables. In non-database mode, data tables are found by searching the datapath or DFPATH or by specifying a BTR_PATH and DDF_PATH setting.

In database_mode data tables are found by specifying a Pervasive.SQL database name in an URI. Refer to the chapter: Database Mode and Security for further information.

DATABASE_MODE can only be set to on when running on Pervasive.SQL V8.5 or later.

If DATABASE_MODE is on, the following settings will not be used: BTR_PATH, DDF_PATH and DDF_OWNER.

DETECT_INCOMPATIBLE_SIGN_POS

Possible values 0 (False) or 1 (True)

Default value 1

This setting controls whether the Connectivity Kit should detect an incompatible positive sign in numeric (COMP3) fields. Numeric values are stored as COMP3 type fields in Pervasive.SQL tables. In COMP3-type fields the sign is determined by a 1-byte value. Pervasive.SQL allows two values for the positive sign: Hexadecimal 0x0c (decimal 12) and hexadecimal 0x0F (decimal 15).

If this setting is set to true (1), the Connectivity Kit will perform a check when reading numeric values.

If the positive sign of the numeric value in the Pervasive.SQL table is different from the positive sign specified by COMP3_SIGN_POS the following error will be occur:

Error 20562, DFBTRERR_INCOMPATIBLE_POSITIVE_SIGN_DETECTED

NOTE: This error will only occur in very specific circumstances. It will be hardly ever necessary to change the DETECT_INCOMPATIBLE_SIGN_POS setting. Changing this is considered advanced usage. Do not change this setting from its default, unless you get the above mentioned error.

DDF_OWNER

Possible values A valid Pervasive.SQL ownername

Default value None

This setting supports database security in Pervasive.SQL versions before version V8.5. Security in Pervasive.SQL version V8.5 or later is supported by the DATABASE_MODE setting. If DATABASE_MODE is on, the DDF_OWNER setting will not be used.

When database security is switched on in pre-V8.5, you can use this keyword to make the password for Database Security known to the Pervasive.SQL Engine. Note that you can accomplish the same by using the DFBTR_DDF_OWNER command that is used defined in the DFBTRDRV.PKG.

DDF_PATH

Possible values A valid path. UNC path is possible

Default value none

NOTE: This setting applies only when DATABASE_MODE setting is false. This setting will not be used when DATABASE_MODE setting is true.

This setting controls the location of the Pervasive.SQL metadata tables (DDF tables). By default it has not been set which means it will use the datapath/ DFPath to find a Pervasive.SQL table. When this setting has been used it needs to point to a directory. The Connectivity Kit will try to locate the DDF tables in this location and no longer use the path. Note that this setting can only have one path!

EXPLICIT_LOCKING

Possible values 0 (False) or 1 (True)

Default value 1

This setting controls the state of EXPLICIT_LOCKING. Its default value is 1 (True). When set to 0 (false), EXPLICIT_LOCKING will be switched off. Refer to the chapter: Transactions and Locking for more information.

INT_PATH

Possible values A valid path. UNC path is possible

Default value None

This setting controls the location of the intermediate (.INT) files. By default .INT files are searched for along datapath/DFPATH. New .INT are created in the first directory of datapath/DFPATH. The Connectivity Kit will no longer use datapath/DFPath to look for the INT files when this setting has been used.

LOCK_DELAY

Possible values 0-2147483647

Default value 0

This setting controls the number of milliseconds the Connectivity Kit will wait between two lock tries when a lock has failed. The default value for this is being controlled by the DataFlex API and is 0. This setting overrules the value of the DataFlex API when set.

LOCK_READONLY

Possible values 0 (False) or 1 (True)

Default value 0

This setting controls whether or not tables that are opened for read-only access are being locked or not when being accessed within a transaction. Note that this only affects the locking process of concurrent transactions since exclusive transactions always lock every open table independent of the file mode.

This setting is 0 (FALSE) by default.

LOCK_TIMEOUT

Possible values 0-2147483647

Default value 60000

This setting controls the number of milliseconds after which a lock attempt is considered to have failed. By default the setting from the DataFlex API is being used which is 60000 (60 seconds). When set it will overrule the setting of the DataFlex API.

LOGFILE_PATH

Possible values Pathname to log file.

Default value None

This setting controls the location of the error log file. When this is set to a valid filename, it will write extra error information to this file.

The information is formatted as a;b;c;d where

a = Error number

b = Extra error context information

c = User who got the error

d = Table the error was triggered on (when available)

OWNER

Possible values A valid Pervasive.SQL ownername

Default value None

Note: Owner names are case sensitive.

This keyword must be followed by an ownername. It can be used to fill the Connectivity Kit’s list of owners upon initialization. The keyword may be used more than once to fill the list.

Whenever the Connectivity Kit opens a table, it will try to use one of the owner names from the list starting with the first one. If the table doesn’t open using the first one, it will try the second one, and so on. When it reaches the end of the list and still has not opened the table, it will try to open the table without an ownername.

PAD_STRING

Possible values 0 (False) or 1 (True)

Default value 0

With this keyword, you can control how the Connectivity Kit stores string values. Normally they will be stored as the DataFlex API presents them to the Connectivity Kit. In some cases, it is desirable that strings are stored padded with spaces if the actual value does not fill the complete length of the field. Setting the PAD_STRING keyword to non-zero will turn on the padding of spaces for the string values.

NOTE: Padding applies only to fields of the DataFlex ASCII type. Text fields are not affected.

RECID_NAME

Possible values A valid Pervasive.SQL field name

Default value RECID

This keyword is used when converting from DataFlex to Pervasive.SQL with recnum support. It determines the name to use for the record id field.

RECNUM_METHOD

Possible values GET_POSITION, POSITION_BLOCK, DOUBLE_CHECK and AUTO_CONFIG

Default value AUTO_CONFIG

This setting controls the way the Connectivity Kit will determine the record number for a record when the table does not have recnum support. The default setting is AUTO_CONFIG.

The possible values are:

GET_POSITION This is the conventional way of getting a record id for a record. It will make a call to the Pervasive.SQL client asking for an ID for the current record. Executing this call takes as much time as finding a record.

POSITION_BLOCK This setting will take the value of the ID for the recnum from the so-called position block that belongs to the table. This method is much faster because it doesn’t need to access the Pervasive.SQL client.

DOUBLE_CHECK This is a special debug setting that can be used to validate the use of the POSITION_BLOCK value. This value will use both the GET_POSITION and POSITION_BLOCK method. The values of both methods are compared each time and an error will be generated when the values do not match.

AUTO_CONFIG This method will use the DOUBLE_CHECK method the first time it is being asked for a recnum and when this first call succeeds it will assume that it’s save to use the POSITION_BLOCK method.

RENAME_RETRY_COUNT

Possible values 0-1000

Default value 10

The number of times a rename will be retried when it does not succeed.

During the restructure process of a table, the Connectivity Kit might need to rename the original Pervasive.SQL table and replace it with a new Pervasive.SQL table. Just before it renames the table, the Connectivity Kit will close the table. The Pervasive.SQL engine now needs to close the table before the operating system can rename the table. When the Pervasive.SQL engine does not release the table right away, the Connectivity Kit needs to retry the renaming process a few times. This setting specifies the number of times the rename will be retried.

There will be a 1-second delay between two retries.

REPORT_CACHE_ERRORS

Possible values 0 (False) or 1 (True)

Default value 1

This setting controls whether or not an error should be generated whenever the Connectivity Kit could not write to a structure cache file.

RUNTIME_SERVER_SUPPORT

Possible values 0 (False) or 1 (True)

Default value 0

This should be set when using a Novell runtime server. When this keyword is set to true (1), the following settings will be set to false: CONVERT_LONG_FILENAMES and USE_CACHE_EXPIRATION.

TEXT_TYPE

Possible values LONGVAR and NOTE

Default value LONGVAR

This setting determines which Pervasive.SQL type will be used for DataFlex text and binary type fields. When TEXT_TYPE is set to LONGVAR, DF_TEXT fields will be set to LONGVARCHAR and DF_BINARY fields will be set to LONGVARBINARY types. This will happen both during conversion and during restructuring.

When TEXT_TYPE is set to NOTE, DF_TEXT fields will be set to type ZSTRING if the text fields is not the last field of the table, and to type NOTE when the text field is the last field of the table. DF_BINARY fields will be set to type char. This will happen both during conversion and during restructuring.

Earlier versions of the Connectivity Kit used ZSTRING/NOTE type fields. These types are no longer supported in Pervasive.SQL. It is recommended to use the LONGVAR types.

TRANSACTION_TYPE

Possible values EXCLUSIVE, CONCURRENT and NONE

Default value EXCLUSIVE

This keyword needs to be followed by the preferred transaction type to use.

Refer to Transactions and Locking, for more information.

USE_CACHE

Possible values 0 (False) or 1 (True)

Default value 1

This setting controls whether or not structure caching should be used when opening tables. Structure caching will read all structural information about a table from structure cache (.CCH) files. This speeds up the opening of files. Refer to the chapter Opening Tables for more information.

USE_CACHE_EXPIRATION

Possible values 0 (False) or 1 (True)

Default value 1

When this setting is set to true (1), before opening the structure cache (.CCH) file, the Connectivity Kit will check whether the cache file might be invalid. The Connectivity Kit will compare the date and time of the cache file (.CCH) with the date and time of the DDF files and with the date and time of the .INT file. If the date and time of the DDFs is later than the date and time of the .CCH, the .CCH file will be regenerated.

This value should be set to false (0) when using a Novell runtime server.

USE_INT_FILE

Possible values 0 (False) or 1 (True)

Default value 1

When a table is being opened using either the prefix method (“DFBTRDRV:mytable”) or the extension method (“mytable.BTR”), this setting controls whether or not an INT file will be read during the open.

WARNING: Setting USE_INT_FILE 0 means that all information from the INT file is NOT available after opening the tables. This includes all relationship information. Tables will be opened without relations. Your application has to set relations at runtime (soft relates).

NOTE: If DATABASE_MODE is on, an INT file must be present with ‘normal’ opens, since an URI must be specified in the INT file. The only way to open tables without an INT file in DATABASE_MODE is by using an “Open As with Uri”

ZEROFILE_METHOD

Possible values CREATE, FALLBACK and DELETE

Default value FALLBACK

This setting controls how a ZEROFILE command is being executed. Valid values are CREATE, FALLBACK and DELETE.

Delete When set to this value the Connectivity Kit will delete each record from the table by finding and deleting each record. This is the safest but also slowest method to remove all records from a table.

Fallback When set to this value the Connectivity Kit will first try to create an exact copy of the table without copying the data and replacing the original table with the new created table. If this method fails the Connectivity Kit will delete all records from the original table using the ‘delete’ method.

Create When set to this value the Connectivity Kit will always try to create a new table. When the Connectivity Kit fails it will generate an error message.


Database Specific Configuration File

The ODBC Connectivity Kit can be used to connect to any ODBC back end. These back ends will require specific configuration settings to perform in an optimal way. Managing Connectivity Kit configuration files to handle different back ends would be troublesome if not impossible. This is why you can create a database specific configuration file.

File Name

The name of the database specific configuration file is <database name>.int, where <database name> is the database name returned by the back end. You can find out the database name by looking at the table revision, DF_FILE_REVISION, of a table. The table revision of a table is made up of two components, the database name and the version number

You can see the database name in Database Builder. Open a table from a certain back end, move to the parameter tab page of the open table, look at the Table Revision setting, the database name is the fist part of the revision.

A Microsoft Access table, for example, shows:

The database specific configuration file for an Access database is ”Access.int”

Shared Keywords

A number of database specific settings can also be set up in the Connectivity Kit configuration file. If a setting is defined in both files, the global setting will be overwritten by the database specific one.

Keywords

Column_Create_Defaultclause

Value Integer value

Associated Attribute None

Indicates if there is support for a default clause when creating tables. A non-zero value means the default clause is supported, a zero value means it is not supported.

This attribute can be queried through ODBC but we have found that some drivers do not return a reliable value. The value of the attribute is used by the Connectivity Kit to set up default values.

By default the value that is returned by the database will be used.

Default_Default_ASCII

This keyword can also be specified in the Connectivity Kit configuration file. See Default_Default_ASCII for a description.

Default_Default_Binary

This keyword can also be specified in the Connectivity Kit configuration file. See Default_Default_Binary for a description.

Default_Default_Date

This keyword can also be specified in the Connectivity Kit configuration file. See Default_Default_Date for a description.

Default_Default_Numeric

This keyword can also be specified in the Connectivity Kit configuration file. See Default_Default_Numeric for a description.

Default_Default_Text

This keyword can also be specified in the Connectivity Kit configuration file. See Default_Default_Text for a description.

Default_Nullable_ASCII

This keyword can also be specified in the Connectivity Kit configuration file. See Default_Nullable_ASCII for a description.

Default_Nullable_Binary

This keyword can also be specified in the Connectivity Kit configuration file. See Default_Nullable_Binary for a description.

Default_Nullable_Date

This keyword can also be specified in the Connectivity Kit configuration file. See Default_Nullable_Date for a description.

Default_Nullable_Numeric

This keyword can also be specified in the Connectivity Kit configuration file. See Default_Nullable_Numeric for a description.

Default_Nullable_Text

This keyword can also be specified in the Connectivity Kit configuration file. See Default_Nullable_Text for a description.

Driver_Date_Format

This keyword can also be specified in the Connectivity Kit configuration file. See Driver_Date_Format for a description.

Driver_Date_Separator

This keyword can also be specified in the Connectivity Kit configuration file. See Driver_Date_Separator for a description.

Driver_Decimal_Separator

This keyword can also be specified in the Connectivity Kit configuration file. See Driver_Decimal_Separator for a description.

Driver_Thousands_Separator

This keyword can also be specified in the Connectivity Kit configuration file. See Driver_Thousands_Separator for a description.

Duprec_ErrorNumber

Value

Integer value

Associated Attribute

None

Description

The native error number of the database duplicate records error. This keyword, in combination with the Duprec_State keyword, is be used to specify how the duplicate records error of the database can be translated to the DataFlex duplicate records error.

Duprec_State

Value

String value

Associated Attribute

None

Description

The SQLState of the database duplicate records error. This keyword, in combination with the Duprec_ErrorNumber keyword, is be used to specify how the duplicate records error of the database can be translated to the DataFlex duplicate records error.

Dummy_Zero_Date_Value

This keyword can also be specified in the Connectivity Kit configuration file. See Dummy_Zero_Date_Value for a description.

Index_Asc

Value

Integer value

Associated Attribute

None

Description

Indicates if there is support for the ascending (“asc”) keyword in the create index statement. A non-zero value means the ascending keyword is supported, a zero value means it is not supported.

This attribute can be queried through ODBC but we have found that some drivers do not return a reliable value. The value of the attribute is used by the Connectivity Kit to handle creating indices.

By default the value that is returned by the database will be used.

Index_Create

Value

Integer value

Associated Attribute

None

Description

Indicates if there is support for the create index statement. A non-zero value means the creating of indices is supported, a zero value means it is not supported.

This attribute can be queried through ODBC but we have found that some drivers do not return a reliable value. The value of the attribute is used by the Connectivity Kit to handle creating indices. If the backend does not support creating indices every index will be defined on the DataFlex side only. This means there will be no physical index, it is very likely a connection to such a backend will be slow.

By default the value that is returned by the database will be used.

Index_Desc

Value

Integer value

Associated Attribute

None

Description

Indicates if there is support for the descending (“desc”) keyword in the create index statement. A non-zero value means the descending keyword is supported, a zero value means it is not supported.

This attribute can be queried through ODBC but we have found that some drivers do not return a reliable value. The value of the attribute is used by the Connectivity Kit to handle creating indices.

By default the value that is returned by the database will be used.

Index_Drop

Value

Integer value

Associated Attribute

None

Description

Indicates if there is support for the drop index statement. A non-zero value means the dropping of indices is supported, a zero value means it is not supported.

This attribute can be queried through ODBC but we have found that some drivers do not return a reliable value. The value of the attribute is used by the Connectivity Kit to handle dropping indices. If the backend does not support dropping indices you will have to manually drop indices if need be. It is not recommended to use Database Builder for index definition on such backends.

By default the value that is returned by the database will be used.

Ignore_UCASE_Support

This keyword can also be specified in the Connectivity Kit configuration file. See Ignore_UCASE_Support for a description.

Max_Active_Statements

This keyword can also be specified in the Connectivity Kit configuration file. See Max_Active_Statements for a description.

Type_Createparams_L

Value

String value

Associated Attribute

None

Description

Indicates if the specified type must use a length paramater when creating columns of this type. The keyword is set to the name of the type that the length parameter must be used for.

This attribute can be queried through ODBC but we have found that some drivers do not return a reliable value. The value of the attribute is used by the Connectivity Kit to handle creating columns.

By default the value that is returned by the database will be used.

Type_Createparams_LP

Value

String value

Associated Attribute

None

Description

Indicates if the specified type must use a length and a precision parameter when creating columns of this type. The keyword is set to the name of the type that the length and precision parameter must be used for.

This attribute can be queried through ODBC but we have found that some drivers do not return a reliable value. The value of the attribute is used by the Connectivity Kit to handle creating columns.

By default the value that is returned by the database will be used.

Type_Createparams_None

Value

String value

Associated Attribute

None

Description

Indicates if the specified type must use no parameter when creating columns of this type. The keyword is set to the name of the type that no parameter must be used for.

This attribute can be queried through ODBC but we have found that some drivers do not return a reliable value. The value of the attribute is used by the Connectivity Kit to handle creating columns.

By default the value that is returned by the database will be used.

Use_Identity_Type

Value

Integer value

Associated Attribute

None

Description

Indicates if the database supports an identity- or autoincrement type that should be used to base the record identifier column on. A non-zero value means the type must be used, a zero value means it must not be used.

There are database in which the auto increment is a separate type. In other databases auto increment behavior is an attribute of a database types rather than a type by itself. The way to set up the attribute in these databases is by using special SQL syntax for the column in question. Some ODBC drivers will return the special syntax as a separate type. Yet other databases do not support auto increment behavior at all.

The ODBC Connectivity Kit will get al the supported types from the database. This list of types is used when creating a table to select the database types to use from.

You can use the identity behavior of a database when:

  • The database supports it

  • The ODBC driver returns it as a separate type

  • The ODBC driver returns the full syntax. In some databases an auto increment column must have other attributes set (e.g. it must be the primary key). You cannot use the auto increment behavior for such databases.

By default identity types are not used.


Microsoft Access

Microsoft Access, being part of the Office suite, is a widely used storage format. It uses the Microsoft Jet Database Engine as the storage format for its native tables. Access databases are stored in disk files with an “.mdb” extension. The disk file stores the entire database (tables, indexes, metadata and so forth).

In our final testing of the connection to Microsoft Access we used Office 2003 (thus Access 2003). Earlier tests used Office 2000 (thus Access 2000). The ODBC driver used was version 4.00.6019.00. Both Access 2003 and 2000 use the same Jet Database Engine.

Access Behaviour

Column Default Values

Although Microsoft Access itself supports column defaults values this is not supported through the Microsoft Access ODBC driver. When getting column attributes it will always report the column as having no default value.

Note that defaults are not supported at all through the Access ODBC (not supported in the DDL SQL syntax) driver. Even though the ODBC Connectivity Kit allows you to specify a default value for a column (DF_FIELD_DEFAULT_VALUE) this will have no effect.

Column Null-ability

Although Microsoft Access itself supports columns that do not allow null values this is not supported through the Microsoft Access ODBC driver. When getting column attributes it will always report the column as allowing null values. If the column attribute required is set in Access, the Access ODBC driver will still report the column as allowing null values.

The SQL syntax supported by the Access ODBC driver does support creating columns that disallow null values. So you are able to create tables that do not allow null values. When these tables are opened, in Database Builder e.g., they will report all columns as allowing null values.

When using Database Builder to edit an Access table definition, make sure to set the Nullable column for every field to the correct value. You cannot trust the values that are reported and must set them to the desired values. Alternatively you can use Access to edit the table definition. In that case make sure to delete the table’s cache file.

Database Configuration File

The name of the database configuration file for Microsoft Access is: Access.int.

A configuration file with recommended settings is part of the installation. Most settings reported by Access are accurate. In this file the following settings are made:

Default Value Keywords

As explained in Column default values default values are not supported through ODBC. Setting the default value database configuration keywords has no effect, they are ignored. In the installed Access.int configuration file these keywords are not set.

Duplicate Record Keywords

The duplicate record keywords are set to the Access duplicate record error state and number as follows:

Duprec_Errornumber -1605

Duprec_State 23000

Max_Active_Statements

The Max_Active_Statements keyword is set to 0.

Use_Identity_Type

The Use_Identity_Type keyword is set to 1. This will ensure the ODBC Connectivity Kit uses the Access AutoNumber type for record identity columns. If you convert a database of an existing DataFlex application to Access, the DataFlex application does not need to be adjusted.

You can only use this setting if the column’s NewValues attribute is set to increment. In Access you can assign AutoNumbers in two different ways, increment and random. See the Access documentation for more information.

If you set this keyword to 0 (the default value) the AutoNumber type will not be used. This means you will have to adjust existing DataFlex code to assign record identifiers.


IBM DB2

DB2

Data Access provides a dedicated DB2 Connectivity Kit, we recommend using it to connect to DB2 data.


MySQL

MySQL is a popular open source database that is distributed under a dual license policy. If you want to use MySQL in a DataFlex environment you should obtain a MySQL Commercial License from MySQL AB.

MySQL supports different table types that have different physical characteristics. How a MySQL database is stored depends on the table type used.

In our final testing of the connection to MySQL we used MySQL 4.0.20 The ODBC driver used was version 3.51.09.00.

Table Types

MySQL supports different ways to store tables known as table types. Different table types are available. Some support transactions, others do not. We recommend using a table type that supports transactions. The default table type that will be used is InnoDB. For more information on table types see the MySQL documentation.

If you use InnoDB, make sure you setup the InnoDB buffer size () to a reasonable value. A small InnoDB buffer will impact performance in a negative way. The default values after installing MySQL are very conservative. See the MySQL documentation on setting the InnoDB buffer size, look for Innodb_Buffer_Pool_Size.

Database Configuration File

The name of the database configuration file for MySQL is: MySQL.int.

A configuration file with recommended settings is part of the installation. Most settings reported by MySQL are accurate. In this file the following settings are made:

Duplicate Record Keywords

The duplicate record keywords are set to the MySQL duplicate record error state and number as follows:

Duprec_Errornumber 1062

Duprec_State 23000

Use_Identity_Type

The Use_Identity_Type keyword is set to 1. This will ensure the ODBC Connectivity Kit uses the MySQL Auto Increment type for record identity columns. If you convert a database of an existing DataFlex application to MySQL, the DataFlex application does not need to be adjusted.

If you set this keyword to 0 (the default value) the Auto Increment type will not be used. This means you will have to adjust existing DataFlex code to assign record identifiers.

MySQLTableType

The MySQLTableType keyword can be used to setup the type of the MySQL tables created by the Connectivity Kit. MySQL supports several different table types each having its advantages and disadvantages. See the MySQL documentation for more information on table types. It is recommended to use a table type that supports transactions.

In the MySQL database configuration file the keyword is not set, so the default is used. The default table type is InnoDB. The entry is in the configuration file to document the possibility to set the keyword and its possible values.

Default_Max_Rows

In most ODBC connections the default result set size of 0 works reasonably well. While testing the connection to MySQL we found that the result set size must be limited to get decent performance.

The Default_Max_Rows keyword can be used to setup a default for the Max_Rows_Fetched setting of new tables. The recommended setting for this keyword is 10.


Oracle

Oracle is a widely used relational database management system.

In our final testing of the connection to Oracle we used Oracle 9.02.0010 The ODBC driver used was version 9.02.00.00.

Automatically Assigning Record Numbers

Oracle does not support an auto increment type attribute. The only way to let Oracle automatically assign record numbers is by using triggers. A trigger is a database event that fires when a certain operation is executed on a table. One can define triggers on insert (creating records), update (modifying existing records) or delete operations.

Oracle supports so called sequences. The best way to automatically assign record numbers for every table accessed though the ODBC Connectivity Kit is to take following steps for each individual table:

  • Define a sequence starting at the (highest record number + 1) incrementing by 1.

  • Define a trigger before insert that uses the next value of the table’s sequence and assigns it to the record number.

  • Change the table level attributes DF_FILE_GENERATE_RECORD_ID_METHOD to RIM_EXTERNAL, and DF_FILE_GET_RID_AFTER_CREATE to True.

Sample Conversion Source Code

It is not a difficult task to write a Visual DataFlex program that automates this process. Sample code that automates this using Embedded SQL is listed below.

//***

//*** Procedure: ConvertOrclToSequenceAndTrigger

//*** Purpose : Convert all Oracle tables in the current filelist to use a sequence

//*** and a trigger to fill the record identity.

//***

Procedure ConvertOrclToSequenceAndTrigger

Handle hTable

String sRootName

String sDriver

String sRevision

Boolean bIsOpen

String sDisplayName

Handle hoDone

//*** Create a set to keep track of the tables that are already done, this

//*** takes care of alias tables

Get Create U_Set To hoDone

//*** Make sure failure to open does not abort the program

Send Ignore_Error of Error_Object_Id DFERR_CANT_OPEN_DATA_FILE

//*** Show that we are starting this

Showln

Showln "Changing Oracle tables so record numbers are filled automatically"

Showln "Scanning Filelist"

Showln

//*** Traverse filelist

Move 0 to hTable

Repeat

Get_Attribute DF_FILE_NEXT_USED of hTable to hTable

If (hTable > 0) Begin

//*** Get the rootname to use in error reporting

Get_Attribute DF_FILE_ROOT_NAME of hTable to sRootName

//*** If name is in set, it’s already done so skip it.

If (Find_Element(hoDone, Uppercase(sRootName)) = -1) Begin

//*** Open the table

Open hTable

Move (Found) to bIsOpen

If (bIsOpen) Begin

//*** Make sure it is an Oracle table

Get_Attribute DF_FILE_DRIVER of hTable to sDriver

If (sDriver = "ODBC_DRV") Begin

Get_Attribute DF_FILE_REVISION of hTable to sRevision

If (Uppercase(Left(sRevision, 6)) = "ORACLE") Begin

//*** Register as done

Send Add_Element of hoDone (Uppercase(sRootName))

//*** Show progress

Get_Attribute DF_FILE_DISPLAY_NAME of hTable to sDisplayName

Showln "Handling table " hTable ", " sRootName ", " sDisplayName

Send ChangeGenerateRecordIdMethod hTable

//*** Open the table

Open hTable

Move (Found) to bIsOpen

If (bIsOpen) ;

Send CreateSequenceAndTriggerForTable hTable

End

Else ;

Showln "Table: " hTable ", " sRootName " is not an Oracle table."

End

Else ;

Showln "Table: " hTable ", " sRootName " is not an ODBC table."

//*** If still open, close table

Get_Attribute DF_FILE_OPENED of hTable To bIsOpen

If (bIsOpen) ;

Close hTable

End

Else ;

Showln "Unable to open table: " hTable ", " sRootName "."

End

Else ;

Showln "Table already handled (alias): " hTable ", " sRootName "."

End

Until (hTable = 0)

//*** Make sure failure to open works as it did before this procedure

Send Trap_Error of Error_Object_Id DFERR_CANT_OPEN_DATA_FILE

//*** Destroy set

Send Destroy of hoDone

End_procedure // ConvertOrclToSequenceAndTrigger

//***

//*** Procedure: CreateSequenceForTable

//*** Purpose : Create a sequence and a trigger for the passed table.

//*** Sequence will be names <TableName>_DFSQNC, trigger will be

//*** named <TableName>_DFTRG.

//***

Procedure CreateSequenceAndTriggerForTable Handle hTable

Handle hoSQL

Handle hdbc

Handle hstmt

String sTableName

String sSchema

String sRecnumName

String sSQLStatement

String sSequenceName

String sTriggerName

Integer iMaxRecnum

Get Create U_cSQLHandleManager to hoSQL

If (hoSQL <> 0) Begin

Get SQLFIleConnect of hoSQL hTable to hdbc

If (hdbc <> 0) Begin

//*** Get table info

Get_Attribute DF_FILE_TABLE_NAME of hTable to sTableName

Get_Attribute DF_FILE_OWNER of hTable to sSchema

//*** Assemble names

Move "" To sSequenceName

If (sSchema <> "") ;

Move (Append(sSequenceName, '"' + sSchema + '".')) To sSequenceName

Move (Append(sSequenceName, '"' + sTableName + '_DFSQNC"')) to sSequenceName

Move "" To sTriggerName

If (sSchema <> "") ;

Move (Append(sTriggerName, '"' + sSchema + '".')) To sTriggerName

Move (Append(sTriggerName, '"' + sTableName + '_DFTRG"')) to sTriggerName

//*** Get name of recnum

Get_Attribute DF_FIELD_NAME of hTable 0 to sRecnumName

//*** Create the sequence

Get SQLOpen of hdbc to hstmt

If (hstmt <> 0) Begin

//*** Get last used recnum

Clear hTable

vFind hTable 0 Lt

If (Found) ;

Get_Field_Value hTable 0 to iMaxRecnum

Else ;

Move 0 to iMaxRecnum

//*** Build the statement

Showln " Creating sequence: " sSequenceName

Move 'CREATE SEQUENCE ' to sSQLStatement

Move (Append(sSQLStatement, sSequenceName)) to sSQLStatement

Move (Append(sSQLStatement, ' INCREMENT BY 1 START WITH ')) to sSQLStatement

Move (Append(sSQLStatement, String(iMaxRecnum + 1))) to sSQLStatement

Move (Append(sSQLStatement, ' NOMAXVALUE MINVALUE 1')) to sSQLStatement

Move (Append(sSQLStatement, ' NOCYCLE NOCACHE NOORDER')) to sSQLStatement

Send SQLExecDirect of hstmt sSQLStatement

Send SQLClose of hstmt

End

//*** Create the trigger

Get SQLOpen of hdbc to hstmt

If (hstmt <> 0) Begin

//*** Build the statement

Showln " Creating trigger: " sTriggerName

Move 'CREATE OR REPLACE TRIGGER ' to sSQLStatement

Move (Append(sSQLStatement, sTriggerName)) to sSQLStatement

Move (Append(sSQLStatement, ' BEFORE INSERT ON ')) to sSQLStatement

If (sSchema <> "") ;

Move (Append(sSQLStatement, '"' + sSchema + '".')) To sSQLStatement

Move (Append(sSQLStatement, '"' + sTableName + '"')) to sSQLStatement

Move (Append(sSQLStatement, ' REFERENCING OLD AS OLD NEW AS NEW')) ;

To sSQLStatement

Move (Append(sSQLStatement, ' FOR EACH ROW Begin Select ')) to sSQLStatement

Move (Append(sSQLStatement, sSequenceName)) to sSQLStatement

Move (Append(sSQLStatement, '.NEXTVAL INTO :new.')) To sSQLStatement

Move (Append(sSQLStatement, '"' + sRecnumName + '"')) to sSQLStatement

Move (Append(sSQLStatement, ' FROM DUAL; End;')) to sSQLStatement

Send SQLExecDirect of hstmt sSQLStatement

Send SQLClose of hstmt

End

Send SQLDisconnect of hdbc

End

Send Destroy of hoSQL

End

End_procedure // CreateSequenceForTable

//***

//*** Procedure: ChangeGenerateRecordIdMethod

//*** Purpose : Set the DF_FILE_GENERATE_RECORD_ID_METHOD attribute of

//*** the table to RIM_EXTERNAL.

//***

Procedure ChangeGenerateRecordIdMethod Handle hTable

Showln " Changing DF_FILE_GENERATE_RECORD_ID_METHOD"

Structure_Start hTable

Set_Attribute DF_FILE_GENERATE_RECORD_ID_METHOD of hTable To RIM_EXTERNAL

Set_Attribute DF_FILE_GET_RID_AFTER_CREATE of hTable To True

Structure_End hTable DF_STRUCTEND_OPT_NONE "." Self

End_procedure // ChangeGenerateRecordIdMethod

//***

//*** Function: Callback

//*** Purpose : Handle progress information for the Structure_end operation

//***

Function Callback String CallbackMsg Integer CallbackType Returns Integer

If CallbackType NE DF_MESSAGE_PROGRESS_VALUE ;

Showln " - " CallbackMsg

Function_return False

End_function // Callback

Database Configuration File

The name of the database configuration file for Oracle is: Oracle.int.

A configuration file with recommended settings is part of the installation. Most settings reported by Oracle are accurate. In this file the following settings are made:

Default_Default_Date

The default value for date columns is ‘0001-01-01’. Oracle does not accept that format so we overwrite it in the database configuration file with a format it does understand, {d '0001-01-01'}.

Index_Desc

The Oracle ODBC driver reports that descending index segments are not supported. In version 9.2 they are supported.

Duplicate Record Keywords

The duplicate record keywords are set to the Oracle duplicate record error state and number as follows:

Duprec_Errornumber 1

Duprec_State 23000

Max_Active_Statements

The Max_Active_Statements keyword is set to 0.


PSQL

Data Access provides a dedicated Pervasive.SQL Connectivity Kit, we recommend using it to connect to Pervasive.SQL data.

Embedded SQL

The dedicated Pervasive.SQL CK uses the Btrieve API to access the tables. This API uses the Pervasive.SQL transactional engine that does not support the SQL language. This also means the dedicated Pervasive.SQL CK does not support Embedded SQL. For this reason the ODBC CK is bundled with the Pervasive CK so Embedded SQL can be used for Pervasive.SQL tables.


SQL Server

Data Access provides a dedicated SQL Server Connectivity Kit, we recommend using it to connect to SQL Server data.


Other Databases

When connecting to other, non-discussed, databases a database configuration file may have to be created.

Database Configuration File

The first step in creating a database configuration file is determining its name. The name of the database specific configuration file is <databasename>.int. Where <databasename> is the database name returned by the backend. You can find out the database name by looking at the table revision, DF_FILE_REVISION, of a table. The table revision of a table is made up of two components, the database name and the version number

You can see the database name in Database Builder. Open a table from a certain backend, move to the parameter tab page of the open table, look at the Table Revision setting, the database name is the fist part of the revision.

A Microsoft Access table, for example, shows:

The database specific configuration file for an Access database is ”Access.int”

The settings you should make in the database configuration file depend on the back-end in use. Sometimes the capabilities of the back-end differ from what the ODBC driver returns. You can see the capabilities returned by the ODBC driver by creating a status dump file. Next to that you need to know what the capabilities of the back-end are. Usually you should be able to get this information from the back-end’s documentation.

Sample code to dump the status:

//***

//*** Procedure: DumpStatus

//*** Purpose : Dump the status for the connection of the specified table

//***

Procedure DumpStatus Handle hTable

Handle hoODBC

Boolean bIsOpen

String sDriver

String sDir

String sSep

String sDumpFile

//*** Make sure failure to open does not abort the program

Send Ignore_Error of Error_Object_Id DFERR_CANT_OPEN_DATA_FILE

//*** Open the table defined in the table number form

If (hTable <> 0) Begin

Open hTable

Move (Found) to bIsOPen

If (bIsOpen) Begin

//*** Make sure this is an ODBC table

Get_Attribute DF_FILE_DRIVER of hTable to sDriver

If (Uppercase(sDriver) = "ODBC_DRV") Begin

//*** Get data path and use first directory

Get psDataPath of (phoWorkspace(ghoApplication)) to sDir

If (Pos(";", sDir) > 0) ;

Move (Left(sDir, Pos(";",sDir) - 1)) to sDir

Move (Sysconf(Sysconf_Dir_Separator)) to sSep

If (Right(sDir, 1) <> sSep) ;

Move (sDir + sSep + "ODBCsts.log") to sDumpFile

Else ;

Move (sDir + "ODBCsts.log") to sDumpFile

Set Value of oDumpFileTB to sDumpFile

//*** Create the dump file

Get Create U_cODBCHandler to hoODBC

Send DumpStatus of hoODBC sDumpFile

Send Destroy of hoODBC

End

Else ;

Error 987 "Table is not accessed by the ODBC CK."

Close hTable

End

End

//*** Make sure failure to open works as it did before this procedure

Send Trap_Error of Error_Object_Id DFERR_CANT_OPEN_DATA_FILE

End_procedure // DumpStatus


Using Embedded SQL

The Structured Query Language, SQL is the de facto standard to manipulate and define data in most relational database systems. It was originally defined by IBM research in 1974, since then numerous database vendors have implemented it.

SQL is a set oriented language based on relational algebra. Every SQL statement uses one or more sets and produces one or more result sets. The set oriented approach is quite different from the traditional record-oriented programming approach. In SQL, you define what you want rather than how you want it done.

The Embedded SQL implementation in Visual DataFlex allows you to issue SQL statements from within a Visual DataFlex program. The SQL statements can be specified by sending messages to SQL broker objects.

Embedded SQL is supported by the following Connectivity Kits:

  • DB2 Connectivity Kit.

  • SQL Server Connectivity Kit

  • ODBC Connectivity Kit

The Embedded SQL interface for all three environments is the same. This enables an easy switch from one environment to another. A Visual DataFlex program using Embedded SQL on DB2 can also be used on SQL Server provided the underlying tables are present in both environments and no server specific syntax has been used. We will indicate server specific issues where appropriate.

This guide starts with a short Introduction to SQL. This introduction is not exhaustive. There are many good books on SQL programming available from beginner to expert level. If you want to know more about SQL, we suggest you to look for such books.

The classes that define the SQL broker objects will be discussed. These are the base SQL handling objects. They handle all SQL activity in a Visual DataFlex program.

In the original Embedded SQL implementation (version 2.0) two programming interfaces were present: the message and the command interface. It has been decided not to support the command interface any longer. The documentation of the command interface is still present in this reference guide.


Introduction to SQL

SQL was first defined in 1974 at the IBM Research Laboratory in San Jose, California. A prototype implementation was built there under the name “System R.” Successful testing results led to IBM’s decision to build products based on the System R technology. A number of other vendors also produced systems that support SQL.

Currently SQL has become the de facto standard for manipulating databases. It is used by most relational database systems. An official ISO/ANSI standard has been defined.

SQL is a standard language. Some vendors have created syntax that is not supported in any other environment to enable access to vendor specific features. For the larger part however, SQL is portable across database systems.

The SQL language defines statements to define and manipulate data. Using SQL, you can create a database, populate it and run reports on the data. We will take a quick look at the data manipulation statements. These allow you to select data, create new data, update existing data or delete data. The SQL statements for these actions are: select, insert, update and delete.

In our discussion of the SQL language, we will not go into detail. The purpose of this introduction is to show basic SQL constructs. It is not meant to be a complete discussion of the SQL language. Details are discussed in your database’s documentation; please refer to it for more information.

In our discussion of SQL statements, we will use the Visual DataFlex Order Entry sample application sample data. For a discussion of this database, refer to Appendix A – The Order Entry Sample Application.

The discussion of SQL statements is in no way complete. We merely “scratch the surface” of the data manipulation statements. The data definition statements are not discussed at all. The purpose of this introduction is not to explain SQL to its fullest detail. It is intended to be a minimal overview of the SQL language.

See Also

The Select Statement

The Insert Statement

The Update Statement

The Delete Statement


The Select Statement

The general form of the select statement is:

select column(s)

from table(s)

[where predicate]

[order by column(s)];

We start with a simple example – Get Name, Address and City for customers in California.

select name, address, city

from customer

where state = ’CA’;

Result

Name | Address | City
America West Hospital | P.O. Drawer 3333 | San Diego
Stunning Software Corp. | 9876 N. Dakota St. | Fresno
3A Software | 1600 Technology Circle | La Mesa
Zorro Cutlery | 12121 SE 12th Street | San Diego
All Canada Brewing Company | 1111 Main Ave | Montreal

The above example demonstrates the most common form of the select statement. It is important to stress that the result of the query on table customer is another table that is derived from existing tables. Because of this fact the retrieval part SQL is called a closed system. The result of a SQL select statement is always a table.

Select Column List

The column list specified in a select statement is made up of column names separated by commas. You can use just the name of the column or a qualified name. The above statement using qualified names would look like:

select customer.name, customer.address, customer.city

from customer

where state = ’CA’;

Using qualified names is optional if the name is unique in the set of columns. However, if there are multiple columns with the same name, you should use qualified names to avoid confusion. If, for example, we would have an account manager table that contains columns ID and Name and we would relate to that table from Customer we could create the query:

select customer.name, address, city, accntmngr.name

from customer, accntmngr

where customer.accntmngr_id = accntmngr.id and

customer.state = ‘CA’;

In this case, we must use qualified column names, otherwise it would not be clear what name we are referring too. This statement joins two tables. More on joins will follow.

If you want to select all columns in a table, the shortcut ‘*’ has been defined. To select all columns of all rows of the customer table we would create the following query:

select *

from customer;

From Table List

The table list that is specified in a select statement is made up of table names separated by commas. You should specify all tables involved in the query here.

Where Predicate

The predicate following the optional where clause, filters the data selected by the select statement. It is made up of a number of conditions combined by logical operators. It is possible to use a subselect statement in the predicate. If, for example, we want to select all orders with an amount above the average order amount, we could create the query:

select *

from orderhea

where order_total > (select avg(order_total)

from orderhea);

Order by Column List

The column list that is specified in the order by clause of a select statement is made up of column names separated by commas. You can use just the name of the column or a qualified name.

We adjust our original sample to – Get Name, Address and City for customers in California ordering the result by customer name.

select name, address, city

from customer

where state = ’CA’

order by name;

Result

Name | Address | City
3A Software | 1600 Technology Circle | La Mesa
All Canada Brewing Company | 1111 Main Ave | Montreal
America West Hospital | P.O. Drawer 3333 | San Diego
Stunning Software Corp. | 9876 N. Dakota St. | Fresno
Zorro Cutlery | 12121 SE 12th Street | San Diego

The columns in the order by list may or may not appear in an index. This is a major difference from the way DataFlex and other record-oriented systems work. SQL can order by any column that is included in the statement, some columns may be excluded because of restrictions in size and type of columns allowed in the order by list.

Even if the columns appear in an index, there is no guarantee that the index will actually be used to retrieve the desired information. SQL systems have a component called the “optimizer”. This component will analyze the SQL query and decide if and how indexes are used. Sometimes it may be more efficient to scan the entire table instead of using an index. The optimizer uses database statistics gathered by the database system to base its decisions on. Some servers allow you to influence the optimizer’s decision by adding so called ‘hints’ to a select statement.

Joining Tables

The item that should not be left undiscussed is joining tables. A join is a relational operator; it defines how two tables need to be “glued together” to retrieve information from them. There are a number of different join types. The most common type is the equi-join.

In an equi-join, we glue two tables together based on equivalence of one or more columns in those tables. An example was already given above in the statement:

select customer.name, address, city, accntmngr.name

from customer, accntmngr

where customer.accntmngr_id = accntmngr.id and

customer.state = ‘CA’;

The “where customer.accntmngr_id = accntmngr.id” is the “join part” of the statement. Joins can be specified as part of the predicates following a where clause. They can also be specified in the join section of a from clause.

select customer.name, address, city, accntmngr.name

from customer join accntmngr

on customer.accntmngr_id = accntmngr.id

where customer.state = ‘CA’;

This form has the advantage that relational operators are clearly separated from filter predicates.

There are other join operators that will not be discussed here these include cross-join, natural join and outer joins. Not all SQL dialects support the join operator. Refer to your database’s documentation for more information.

See Also

Introduction to SQL

The Insert Statement

The Update Statement

The Delete Statement


The Insert Statement

The general form of the insert statement is:

insert into table [( columns )]

values (valuelist);

To insert a new sales person row we would use:

insert into salesp (id, name)

value (‘NEW’, ‘New salesp’);

Column List

The optional column list defines the columns that will be assigned a value. The columns do not need to be in any specific order as long as the column and value lists match.

The column list can be omitted; in that case, the value list must be in the order in which the columns are defined in the table. In general, it is good practice to always specify a column list. If the table is restructured and the order of the columns changes, the insert statement will still work.

Value List

The value list specifies all values that must be inserted in the row.

See Also

Introduction to SQL

The Select Statement

The Update Statement

The Delete Statement


The Update Statement

The general form of the update statement is:

update table

set colum-expression list

[where predicate];

To update the salesperson for all orders sold by Don Marino to Liza Collins we would issue the following update statement:

update orderhea

set salesperson_id = ‘LC’

where salesperson_id = ‘DM’;

Column-Expression List

The column expression list is made up of column expressions separated by commas. A column expression is of the form column = expression. You can use mathematical operators in the expression.

Where Predicate

If vendor 7, Software Publishing, would increase all prices by 10 percent, we could update our inventory in the following way:

update invt

set unit_price = unit_price * 1.1

where vendor_id = 7;

If no where clause is specified, the update is done on all rows. So to increase all prices by 10 percent, we would use the following statement:

update invt

set unit_price = unit_price * 1.1;

See Also

Introduction to SQL

The Select Statement

The Insert Statement

The Delete Statement


The Delete Statement

The general form of the delete statement is:

delete from table

[where predicate];

To delete salesperson Don Marino we would use the following statement:

delete from salesp

where id = ‘DM’;

The predicate can specify more than one row if needed. If, for example, you want to delete all orders placed before January 1, 1999, you would use:

delete from orderhea

where order_date < ‘1999-01-01’;

If no where clause is specified, the delete is done on the complete table. So to remove all rows from the salesperson table, we would use:

delete from salesp;

See Also

Introduction to SQL

The Select Statement

The Insert Statement

The Update Statement


Embedded SQL in Visual DataFlex

The Visual DataFlex programming language does not allow you to type in SQL statements as part of a program source code. Embedded SQL in Visual DataFlex is implemented through SQL broker objects. You will send messages to the SQL broker objects that define statements and process the results.

Package

Embedded SQL is defined in a package called sql.pkg. It can be included in a DataFlex program by the command “use SQL”.

Connection

If you want to use Embedded SQL in a Visual DataFlex program, you will have to setup a proper environment for the SQL statements to be executed.

Before you can execute SQL statements, you will need to create a connection to the database. Even if the database is located on the same machine, a connection must be established. Connections are identified by connection handles.

Once a connection exists, statements can be created in that connection. Statements are identified by statement handles. Once you are done with the statement, you will need to dispose of the statement.

If all processing for a connection is finished, you should dispose of the connection handle.

Every Embedded SQL program will be of the form:

Connect

Repeat

Open a statement handle

Manipulate the statement

Close a statement handle

Until done

Disconnect

It is possible to have multiple statement handles active at the same time. It is also possible to have multiple connections active at the same time. To limit the resources needed by the program we advise to free statement and connection handles as soon as they are no longer needed.

For connection allocation and de-allocation the Embedded SQL interface defines SQLConnect, SQLFileConnect and SQLDisconnect. Once a connection is established all the tables located in the connected database can be accessed.

To allocate and de-allocate statement handles SQLOpen and SQLClose have been defined. You need to close a statement handle whenever the statement changes.

Statements

Embedded SQL will perform all of its database access through SQL statements. Statements can be executed once the proper environment is created. There are several ways to execute statements in an Embedded SQL module.

In general, execution of an SQL statement is a two, or more, step process. The Database Server will compile the SQL statement into a so-called access plan. This plan describes in detail how the statement must be executed. It contains the indexes to use (if any), the order to create temporary results (if any) and much more. The second step is to actually execute the statement using the created access plan. The Embedded SQL interface offers various ways to execute statements:

  • Prepared Execution

  • Direct Execution

  • Procedures

See Also

Result Sets

Informational Messages

ESQL Example


Prepared Execution

Prepared Execution is intended for statements that must be executed more than once. The execution of the statement is separated into two steps: SQLPrepare and SQLExecute. The SQLPrepare logic will create the access plan for the statement. The SQLExecute logic will execute the statement.

Prepared execution has the advantage that the access plan will only be created once while the statement can be executed more than one time. Creating an access plan usually is an expensive operation.

For Prepared Execution, the Embedded SQL interface defines SQLPrepare and SQLExecute.

See Also

Embedded SQL in Visual DataFlex

Direct Execution

Procedures

Result Sets

Informational Messages

ESQL Example


Direct Execution

Direct Execution is the simplest way to execute a statement. A statement’s access plan is created and it is executed directly afterwards. The use of Direct Execution is intended for statements that will be executed only one time. The statement is parsed and an access plan is created every time Direct Execution is invoked.

For Direct Execution, the Embedded SQL interface defines SQLExecDirect.

See Also

Embedded SQL in Visual DataFlex

Prepared Execution

Procedures

Result Sets

Informational Messages

ESQL Example


Procedures

A Procedure is an executable object in the database server. In general, it consists of one or more SQL statements that have been precompiled. They are usually referred to as stored procedures or stored functions. A first attempt has been made to standardize procedure handling in RDBMS systems. The standard refers to procedures as persistent stored modules.

The main advantage of a procedure is that SQL statements are moved from the application to the database server. The application only needs to call the procedure to execute the SQL statements. Procedures are usually fast because the statements are precompiled and no time is needed to create access plans. They are commonly used to store business rules. Furthermore, procedures can make an application portable. The specific SQL code may vary on different database servers as long as the procedure definition (its arguments and return values) does not change, the application still works.

The main disadvantage of a procedure is that SQL statements are moved from the application to the database server. A procedure must be written and compiled for every DBMS on which the calling application runs. Many DBMS’s do not support procedures. The grammar to create a procedure is not standardized. Even though you can call procedures in a standard way, there is no standard creation mechanism.

The decision to use procedures must be made with the application environment in mind. If, for example, we are creating a vertical application that must run on any DBMS flavor, procedures should not be used. If, on the other hand, we are creating an in-house application on a DBMS that supports procedures the use of procedures is more likely.

Procedures can have arguments that can be input, output or input/output parameters. Input parameters are used to pass information to a procedure. Output parameters are used to pass information back to the calling application. Input/Output parameters are used to pass information to the procedure and after the procedure has been called pass information back to the calling application. It is also possible for a procedure to have a return value.

The Embedded SQL interface defines a complete set of messages to handle procedures. This set consists of SQLSetProcedurename, SQLSetArgument, SQLCall, SQLGetArgument and SQLReturnValue.

See Also

Embedded SQL in Visual DataFlex

Prepared Execution

Direct Execution

Result Sets

Informational Messages

ESQL Example


Result Sets

A statement that is executed can have no, one or multiple result sets. As was discussed in Introduction to SQL, SQL is a set oriented language.

The Update, Insert and Delete statements have no result set. A single select statement has one result set. A batch is a group of two or more SQL statements or a single SQL statement that has the same effect (calling a procedure, for example).

Result sets can be traversed in forward direction only, one row at a time. This is done by “fetching” the current row. After the row has been fetched, the data of that row can be retrieved. The Embedded SQL interface offers several different ways to retrieve the data. It can be retrieved into variables or file buffers. For bigger data types, Blob’s, Clob’s and the like, an interface has been defined that allows retrieval of the data in smaller sized chunks.

For fetching rows, the Embedded SQL interface defines SQLFetch. For getting data SQLBindFile, SQLColumnValue and SQLGetData have been defined. To switch to the next result set in a batch SQLNextResultSet has been defined.

A result set is made up out of one or more columns. The number of columns and some attributes per column can be retrieved by using SQLStmtAttribute and SQLColAttribute.

See Also

Embedded SQL in Visual DataFlex

Informational Messages

ESQL Example


Informational Messages

Some SQL Statements generate so-called informational messages. These messages are stored in the ESQL layer when a statement is executed. Informational messages are different from error messages. Errors are passed to DataFlex through the standard DataFlex error handling mechanism. Informational messages sometimes contain warnings and sometimes additional information on the status of a statement.

In SQL Server, for example, the T-SQL statement “RESTORE VERIFYONLY“ returns an informational message rather than a result set.

To handle informational messages, the Embedded SQL interface defines a statement attribute, SQLSTMTATTRIB_NUMMESSAGES and a function SQLGetMessage.

See Also

Embedded SQL in Visual DataFlex

Result Sets

ESQL Example


ESQL Example

Example

We have created a Visual DataFlex program that executes the sample select statement used in Introduction to SQL. The program contains two procedures MessageSample and CommandSample that use the Message and Command interface respectively.

We will not go into detail on the methods and commands used in the sample program. For a detailed description see Message interface.

The statement is:

select name, address, city

from customer

where state = ’CA’

order by name;

In order not to confuse the reader, we have chosen to use the showln command to output the query result. The program connects to a local SQL Server database server. If we would change the program to DB2 on database MyDatabase, we would need to change the following line:

#REPLACE CS_CONNECT "DSN=MyDatabase "

and we would need to pass DB2_DRV_ID to the SQLConnect method and command.

//*****************************************************************************

//*** Chapter3.src ***

//*** ***

//*** Author: Ben Weijers ***

//*** Data Access Nederland ***

//*** September 2000 ***

//*** ***

//*** Purpose: ***

//*** Embedded SQL user's guide chapter 3 sample program. Uses the ***

//*** message interface and the command interface. Shows the query: ***

//*** select name, address, city ***

//*** from customer ***

//*** where state = 'CA' ***

//*** order by name; ***

//*****************************************************************************

Use Windows

Use MSSQLDRV

Use SQL

Global_variable Integer AKey

#REPLACE CS_CONNECT "SERVER=(local);Trusted_Connection=yes;Database=Order"

#REPLACE CS_QUERY "select name, address, city from customer where state = 'CA' order by name;"

//***

//*** Procedure: MessageInterface

//*** Purpose : Execute the query and show its result using the message interface

//***

Procedure MessageInterface

String sName

String sAddress

String sCity

Integer hoSQL

Integer hdbc

Integer hstmt

Integer iFetchResult

//*** The SQL handle manager object

Object oSQLHandler Is A cSQLHandleManager

Move Self To hoSQL

End_Object // oSQLHandler

//*** Connect to the database server

Send SQLSetConnect Of hoSQL MSSQLDRV_ID CS_CONNECT

Get SQLConnect Of hoSQL "" "" To hdbc

If (hdbc <> 0) Begin

//*** Open a statement

Get SQLOpen Of hdbc To hstmt

If (hstmt <> 0) Begin

//*** Execute the statement, we do it only once so use direct

//*** execution

Send SQLExecDirect Of hstmt CS_QUERY

//*** Traverse the result set

Repeat

Get SQLFetch Of hstmt To iFetchResult

If (iFetchResult <> 0) Begin

Get SQLColumnValue Of hstmt 1 To sName

Get SQLColumnValue Of hstmt 2 To sAddress

Get SQLColumnValue Of hstmt 3 To sCity

Showln sName ", " sAddress ", " sCity

End

Until (iFetchResult = 0)

Send SQLClose Of hstmt

End

Send SQLDisconnect Of hdbc

End

//*** Destroy the SQL handle manager object

Send Destroy_Object Of hoSQL

End_procedure // MessageInterface

Send MessageInterface

A second sample program shows calling the procedure sp_help in a SQL server database. The sp_help procedure is a predefined SQL Server stored procedure. It gets one argument, the name of an object. It returns zero if it was successful, one if it fails. Depending on the type of the object passed as argument,it will generate a number of result sets. For more information on the sp_help procedure, see the SQL Server documentation.

//*****************************************************************************

//*** sp_help.src ***

//*** ***

//*** Author: Ben Weijers ***

//*** Data Access Nederland ***

//*** September 2000 ***

//*** ***

//*** Purpose: ***

//*** Call the sp_help procedure for the vendor table in the order ***

//*** database. ***

//*****************************************************************************

Use Windows

Use MSSQLDRV

Use SQL

Global_variable Integer AKey

#REPLACE CS_CONNECT "SERVER=(local);Trusted_Connection=yes;Database=Order"

Procedure CallSp_Help

String sLabel

String sColumn

Integer hoSQL

Integer hdbc

Integer hstmt

Integer iFetchResult

Integer iNumCols

Integer iCol

Integer iResult

Integer iNextSetResult

//*** The SQL handle manager object

Object oSQLHandler Is A cSQLHandleManager

Move Self To hoSQL

End_Object // oSQLHandler

//*** Connect to the database server

Send SQLSetConnect Of hoSQL MSSQLDRV_ID CS_CONNECT

Get SQLConnect Of hoSQL "" "" To hdbc

If (hdbc <> 0) Begin

//*** Open a statement

Get SQLOpen Of hdbc To hstmt

If (hstmt <> 0) Begin

//*** Setup the procedure

Send SQLSetProcedurename Of hstmt "SP_HELP"

Send SQLSetArgument Of hstmt 1 "VENDOR"

//*** Call the procedure

Send SqlCall Of hstmt

//** Check the return value

Get SQLReturnValue Of hstmt To iResult

If (iResult = 0) Begin

Repeat

Get SQLStmtAttribute Of hstmt SQLSTMTATTRIB_COLUMNCOUNT To iNumCols

If (iNumCols > 0) Begin

For iCol From 1 To iNumCols

Get SQLColAttribute Of hstmt iCol SQLCOLATTRIB_LABEL To sLabel

Show sLabel

If (iCol < iNumCols) ;

Show ", "

Loop

Showln

Repeat

Get SQLFetch of hstmt To iFetchResult

If (iFetchResult <> 0) Begin

For iCol From 1 To iNumCols

Get SQLColumnValue Of hstmt iCol To sColumn

Show sColumn

If (iCol < iNumCols) ;

Show ", "

Loop

Showln

End

Until (iFetchResult = 0)

End

Get SQLNextResultSet Of hstmt To iNextSetResult

If ((iNextSetResult <> 0) And (iNumCols > 0)) ;

Showln "*******************************************************"

Until (iNextSetResult = 0)

End

Send SQLClose Of hstmt

End

Send SQLDisconnect Of hdbc

End

//*** Destroy the SQL handle manager object

Send Destroy_Object Of hoSQL

End_Procedure // CallSp_Help

Send CallSp_Help

Inkey Akey

See Also

Embedded SQL in Visual DataFlex

Result Sets

Informational Messages


Embedded SQL Class Reference

The message interface is used to send messages to the SQL broker objects. SQL broker objects can be of the following classes:

Class | Short description
cSQLStatement | A cSQLStatement object is created for every statement handle that is allocated.
cSQLConnection | A cSQLConnection object is created for every connection handle that is allocated. An object of this class creates cSQLStatement objects as child objects.
cSQLHandleManager | The main entry point for embedded SQL messages. An object of this class creates cSQLConnection objects as child objects.

The Visual DataFlex class definition is synchronized with the SQL definitions. API’s for SQL environments use the same hierarchical structure for connections and statements. The Visual DataFlex classes add an extra layer of abstraction to this setup. They allow one program to create a connection through the DB2 Connectivity Kit and the SQL Server Connectivity Kit at the same time.

The only object that the programmer needs to define is the outer, cSQLHandleManager object. Once that object is created, messages can be send to it that will automatically create cSQLConnection objects. A code sample that executes an update statement follows:

Handle hoSQLMngr

Handle hdbc hstmt

Object oSQLManager Is A cSQLHandleManager

Move Self To hoSQLMngr

End_object // oSQLManager

Open Customer

Get SQLFileConnect Of hoSQLMngr Customer.File_number To hdbc

Get SQLOpen Of hdbc To hstmt

Send SQLExecDirect To hstmt “UPDATE Customer SET AccountMngr = ‘John’ WHERE AccountMngr = ‘Mary’”

Send SQLClose To hstmt

Send SQLDisconnect To hdbc

As is evident from the sample, the connection handle and statement handle used in DataFlex are actually object handles. Internally the underlying logic will use the handles, as is custom in the Connectivity Kits environment. Possible differences between Connectivity Kits are hidden from the Visual DataFlex programmer. This allows one consistent programmer’s interface that is independent from the underlying Connectivity Kit. A program using Embedded SQL can switch to another Connectivity Kit without having to adjust the code.

We will discuss the classes in the order they are normally used, cSQLHandleManager, cSQLConnection and cSQLStatement. All classes are defined in one package: sql.pkg.

You will notice that we do not discuss class inheritance in the discussion of the three classes. The inheritance is not important. The classes are based on the array class not because they use array features, but because it is the smallest possible non-visible class in a Character Mode environment. Embedded SQL can be used in Visual DataFlex and Character Mode environments.

Private messages will be discussed but in a limited way. Direct usage of private message is not recommended. Data Access reserves the right to completely redefine the private interface of a class. If a programmer uses the messages marked as private, there is no guarantee these will work, or work the same way, in a later revision.


Embedded SQL Command Interface (Obsolete)

Appendix B – Command Interface (Obsolete)

In the original Embedded SQL implementation (version 2.0) two programming interfaces were present: the message and the command interface. It has been decided not to support the command interface any longer. The documentation of the command interface is still present in this reference guide as an appendix.

The command interface that has been defined consists of the following commands:

Command | Short Description
SQLSetConnect | Set a default driver to be used in statements.
SQLConnect | Open a new connection
SQLFileConnect | Use the same connection as the already open table/file does
SQLOpen | Open a statement handle
SQLPrepare | Prepare a statement for execution
SQLExecute | Execute a prepared statement
SQLExecDirect | Prepare and execute a statement
SQLFileFetch | Fetch the next row of the result set into file buffer(s)
SQLBindFetchFile | Bind a default file for fetching to the statement
SQLFetch | Fetch the next row of the result set into variable(s)
SQLGetData | Get column data after a fetch
SQLColumnMap | Get a column number for a given column name
SQLColAttribute | Get a column attribute
SQLStmtAtrtribute | Get a statement attribute
SQLCall | Call a stored procedure
SQLGetArguments | Get procedure arguments and return value
SQLNextResultSet | Switch to the next result set of a procedure or batch
SQLFetchActivatesBuffer | Setup a buffer so its status is set to activate after a successful fetch on the result set.
SQLClose | Close a statement
SQLDisconnect | Close a connection

Command Reference

We will describe every command in more detail in the next paragraphs. For every command we will give a small example. Error handling is not done in any of the examples below. Commands are presented in a logical order the examples grow accordingly.

In the following command descriptions we use:

  • [] To indicate that a command keyword or argument is optional.

  • … To indicate that the keyword or argument can be repeated.

  • | To indicate a one of a list choice


Connectivity

Data Connectivity

  • Connectivity Kits

  • Converting Data

  • Connecting to Existing Data

  • Structure Caching

  • Intermediate Files

  • Character Formats (OEM or ANSI)

  • Table Types

  • NULL Values and Defaults

  • Transactions

  • Error Handling

  • ODBC Escape Sequences

  • Driver Configuration

  • Using Embedded SQL