DatabaseDrivers
DatabaseDrivers
This publication is protected by copyright and all rights are reserved by SoftVelocity Incorporated.
It may not, in whole or part, be copied, photocopied, reproduced, translated, or reduced to any
electronic medium or machine-readable form without prior consent, in writing, from SoftVelocity
Incorporated.
This publication supports Clarion. It is possible that it may contain technical or typographical
errors. SoftVelocity Incorporated provides this publication “as is,” without warranty of any kind,
either expressed or implied.
SoftVelocity Inc.
P.O. Box 510190
Melbourne Beach, Florida 32951
(866) 783-4320
www.softvelocity.com
Trademark Acknowledgements:
i
Table of Contents
ii
Table of Contents
iii
Table of Contents
iv
Table of Contents
v
Database Drivers and Interfaces
Data Independence
Clarion achieves database independence with its built-in driver technology, which lets you access
data from virtually any file system using the same set of Clarion language commands. Many file
drivers are available and more are being added.
Before you can use a database driver, it must be registered. The database drivers
in this package are pre-registered. See the IDE User's Guide and online help for
more information on registering add-on database drivers.
The Clarion language commands for accessing data are the same regardless of the file system
you use; simply choose the appropriate file driver from the drop-down list in your Data Dictionary,
then don't worry about it. The file driver translates the Clarion commands to the chosen file
system's native format. The drivers read and write in the file system's native format without
temporary files or import/export routines.
1
Database Drivers
2
Database Drivers and Interfaces
Trace=[1|0]
TraceFile=[Pathname]
where filedriver is the database driver name (for example [MS-SQL]). Neither the INI section
name [filedriver] nor the INI entry names are case sensitive.
Profile=1 tells the driver to include the Clarion I/O statements in the log file; Profile=0 tells the
driver to omit Clarion I/O statements. The Profile switch must be turned on for the Details switch
to have any effect.
Details=1 tells the driver to include record buffer contents in the log file; however, if the file is
encrypted, you must turn on both the Details switch and the ALLOWDETAILS switch to log record
buffer contents (see ALLOWDETAILS). Details=0 tells the driver to omit record buffer contents.
The Profile switch must be turned on for the Details switch to have any effect.
Trace=1 tells the driver to include all calls to the back-end DBMS, including the generated SQL
statements and their return codes, in the log file. Trace=0 omits these calls. The Trace switch
generally generates log information that helps to debug the SQL drivers, but is normally not
particularly useful to the developer.
TraceFile names the log file to write to. If TraceFile is omitted the driver writes the log to driver.log
in the current directory. Pathname is the full pathname or the filename of the log file to write. If no
path is specified, the driver writes the specified file to the current directory.
To view the trace details in your system debugger, name the target trace file DEBUG:.
Logging opens the named log file for exclusive access. If the file exists, the new log data is
appended to the file.
On Demand Logging
For on-demand logging you can use property syntax within your program to conditionally turn
various levels of logging on and off. The logging is effective for the target table and any view for
which the target table is the primary table.
file{PROP:Profile}=Pathname !Turns Clarion I/O logging on
file{PROP:Profile}='' !Turns Clarion I/O logging off
PathName = file{PROP:Profile} !Queries the name of the log file
file{PROP:Log}=string !Writes the string to the log file
file{PROP:Details}=1 !Turns Record Buffer logging on
fFile{PROP:Details}=0 !Turns Record Buffer logging off
Pathname is the full pathname or the filename of the log file to create. If you do not specify a
path, the driver writes the log file to the current directory.
You can also accomplish on demand logging with a SEND() command and the LOGFILE driver
string.
3
Database Drivers
4
Database Drivers and Interfaces
Driver Strings
There are switches or "driver strings" you can set to control the way your application creates,
reads, and writes files with a specific driver. Driver strings are simply messages or parameters
that are sent to the file driver at run-time to control its behavior. The various driver specific driver
strings are described in the Driver Strings section for each driver.
Driver strings are sent in three ways: with the OPEN or CREATE statement, with the SEND
procedure, and with property syntax.
All File Drivers support the following Driver Strings:
ALLOWDETAILS
LOGFILE
SEND(file, 'DriverString')
The SEND function sends a driver string to the file driver at any time, including before the file is
opened. SEND functions take two forms--with an equal sign to change the value of the switch,
and without an equal sign to return the value of the switch. With SEND, the ISAM drivers do not
require the preceeding forward slash, but the SQL drivers do require it. For example:
SEND(MyFile,'LOGFILE='&MyLogFile) !Set the logfile
MyLogFile=SEND(MyFile,'/LOGFILE') !Query the logfile
OldLogFile=SEND(MyFile,'LOGFILE='&NewLogFile) !Set & Query the logfile
file{PROP:DriverString}
Property syntax is an alternative to the SEND function. With property syntax you can send a
driver string to the file driver any time after the file is opened. With property syntax, the driver
string does not require the preceeding forward slash. For example:
MyLogFile = 'MyFile.Log'
MyFile{PROP:Profile}=MyLogFile !Set the logfile
MyLogFile = MyFile{PROP:Profile} !Query the logfile
5
Database Drivers
ALLOWDETAILS
DRIVER('Driver', '/ALLOWDETAILS = TRUE | FALSE' )
The ALLOWDETAILS driver string allows the file driver to include record buffer contents in the log
file for encrypted files.
The ALLOWDETAILS driver string works with the Details switch described in the Database Driver
System-wide Logging section.
LOGFILE
DRIVER( 'Driver', '/LOGFILE [= Pathname] [[message]]' )
[ LogFile" = ] SEND(file, '/LOGFILE [= Pathname] [[message]]' )
The LOGFILE driver string turns logging on and off, and optionally writes a message to the log
file. Turning the LOGFILE switch on writes Clarion I/O statements processed by the driver to the
specified log file. The LOGFILE driver string is equivalent to the Profile switch described in the
Database Driver System-wide Logging section.
Pathname is the full pathname or the filename of the log file to write. If you do not specify a path,
the driver writes the log file to the current directory. If Pathname is omitted, the driver writes the
log to Driver.log in the current directory.
If the log file already exists, the driver appends to it; otherwise, the driver creates the log file.
The message is optional, however, if included, it must be surrounded by square brackets ([]) and
a space must preceed the opening square bracket.
/LOGFILE must be the last driver string specified by the DRIVER attribute.
6
Database Drivers and Interfaces
Due to its lack of relational features and security (anyone can view and change an ASCII
file using Notepad), it's unlikely you'll use the ASCII driver to store large data files. But it
can help you create a text file viewer--use it to open a file, and read it in to a multi-line edit
or list box control!
ASCII:Supported Data Types
STRING
GROUP
USTRING
ASCII:File Specifications/Maximums
File Size: 4 GB
Records per File: 4,294,967,295 bytes
Record Size: 65,520 bytes
Field Size: 65,520 bytes
Fields per Record: 65,520
Keys/Indexes per File: n/a
Key Size: n/a
Memo fields per File: n/a
Memo Field Size: n/a
Open Data Files: Operating system dependent
7
Database Drivers
ASCII:Driver Strings
There are switches or "driver strings" you can set to control the way your application creates,
reads, and writes files with a specific driver. Driver strings are simply messages or parameters
that are sent to the file driver at run-time to control its behavior. See Common Driver Features--
Driver Strings for an overview of these runtime Database Driver switches and parameters.
Some driver strings have no effect after the file is open, so no SEND function syntax is
listed for those strings. However, the SEND function syntax to return the value of the
switch is listed for all driver strings.
The ASCII Driver supports the following Driver Strings:
CLIP
CTRLZISEOF
ENDOFRECORD
Mainframes and MACs frequently use just a carriage return to delimit records.
You can use ENDOFRECORD=1,13 to read these files. UNIX/Linux files frequently
terminate with just a line feed and can be read using ENDOFRECORD=1,10
8
Database Drivers and Interfaces
FILEBUFFERS
The default buffer size for files opened denying write access to other users is the larger of
1024 or (2 * record size), and the larger of 512 or record size for all other open modes.
TAB
QUICKSCAN
9
Database Drivers
UTF
UTFBOM
10
Database Drivers and Interfaces
CREATE Y
NAME Y
ENCRYPT N
OWNER(password) N
RECLAIM N
PRE(prefix) Y
BINDABLE Y
THREAD Y4
EXTERNAL(member) Y
DLL([flag]) Y
OEM Y
LOCALE N
INDEX N
KEY N
MEMO N
BLOB N
RECORD Y
BINARY N
DUP N
NOCASE N
OPT N
PRIMARY N
11
Database Drivers
NAME N
Ascending Components N
Descending Components N
Mixed Components N
DIM Y
OVER Y
NAME Y
BOF(file) N
BUFFER(file) N
BUILD(file) N
BUILD(key) N
BUILD(index) N
BUILD(index, components) N
BYTES(file) Y5
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) N
DUPLICATE(key) N
EMPTY(file) Y
EOF(file) Y
FLUSH(file) N
LOCK(file) Y
NAME(label) Y
12
Database Drivers and Interfaces
PACK(file) N
POINTER(file) Y2
POINTER(key) N
POSITION(file) Y3
POSITION(key) N
RECORDS(file) N
RECORDS(key) N
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) N
UNLOCK(file) Y
ADD(file) Y
ADD(file, length) N
APPEND(file) Y
APPEND(file, length) N
DELETE(file) N
GET(file,key) N
GET(file, filepointer) Y
GET(key, keypointer) N
HOLD(file) N
NEXT(file) Y
NOMEMO(file) N
13
Database Drivers
PREVIOUS(file) N
PUT(file) Y1
PUT(file, filepointer) Y1
RELEASE(file) N
REGET(file,string) Y
REGET(key,string) N
RESET(file,string) Y
RESET(key,string) N
SET(file) Y
SET(file, key) N
SET(file, filepointer) Y
SET(key) N
SET(key, key) N
SET(key, keypointer) N
SKIP(file, count) N
WATCH(file) N
COMMIT N
ROLLBACK N
NULL(field) N
SETNULL(field) N
SETNULL(file, field) N
SETNONNULL(field) N
14
Database Drivers and Interfaces
Notes
1 When using PUT() with this driver you should take care to PUT back the same number of
characters that were read. If you PUT back more characters than were read, then the
"extra" characters will overwrite the first part of the subsequent record. If you PUT back
fewer characters than were read, then only the first part of the retrieved record is
overwritten, while the last part of the retrieved record remains as it was prior to the PUT().
2 POINTER() returns the relative byte position within the file.
3 POSITION(file) returns a STRING(4).
4 THREADed files consume additional file handles for each thread that accesses the file.
5 BYTES() returns the actual bytes read from the file. The size of the clipped RECORD
may be different depending on the file driver and it's DRIVER() strings. With the ASCII or
BASIC file drivers BYTES will include the ENDOFRECORD (typically 13,10) byte count,
but these bytes are not in the RECORD. With the ASCII driver the /TAB driver string can
affect (expand, change or remove) the tab (9) characters in the record buffer resulting in
a different length.
15
Database Drivers
Basic:Specifications
The BASIC file driver reads and writes comma-delimited ASCII files. By default, quotes ( " " )
surround strings, commas delimit fields, and a carriage-return/line-feed delimits records. The
original BASIC programming language defined this file format. The Basic driver does not support
keys or backward file processing (thus Basic files are not a good choice for random access
processing).
The Basic file format provides a good choice for a common file format for sharing data
with spreadsheet programs. A common file extension used for these files is *.CSV, which
stands for "comma separated values."
Basic:File Specifications/Maximums
File Size: 4 GB
Records per File: 4,294,967,295 bytes
Record Size: 65,520 bytes
Field Size: 65,520 bytes
Fields per Record: 65,520
Keys/Indexes per File: n/a
Key Size: n/a
Memo fields per File: 0
Memo Field Size: n/a
Open Data Files: Operating system dependent
16
Database Drivers and Interfaces
Basic:Driver Strings
There are switches or "driver strings" you can set to control the way your application creates,
reads, and writes files with a specific driver. Driver strings are simply messages or parameters
that are sent to the file driver at run-time to control its behavior. See Common Driver Features--
Driver Strings for an overview of these runtime Database Driver switches and parameters.
Some driver strings have no effect after the file is open, so no SEND function syntax is
listed for those strings. However, the SEND function syntax to return the value of the
switch is listed for all driver strings.
The Basic Driver supports the following Driver Strings:
ALWAYSQUOTE
COMMA
CTRLZISEOF
17
Database Drivers
ENDOFRECORD
Mainframes frequently use just a carriage return to delimit records. You can use
ENDOFRECORD to read these files.
ENDOFRECORDINQUOTE
FIELDDELIMITER
If both FIELDDELIMITER and COMMA are specified, the last specification prevails.
18
Database Drivers and Interfaces
FILEBUFFERS
The default buffer size for files opened denying write access to other users is the larger of
1024 or (2 * record size), and the larger of 512 or record size for all other open modes.
FIRSTROWHEADER
DRIVER('BASIC', '/FIRSTROWHEADER=[ON|OFF]' )
[ Buffers" = ] SEND(file, '/FIRSTROWHEADER [ = ON|OFF]' )
This indicates if the first row of the file contains the labels of the columns.
By default this switch is off. If turned on, then CREATE(file) will add a line containing the labels of
the fields separated by the comma character (as specified by the COMMA switch or ','), further
the first line will always be skipped when reading from the file.
QUICKSCAN
TAB-delimited values are a common format compatible with the Windows clipboard. Using
the BASIC file driver string
/COMMA=9 lets you read Windows clipboard files
19
Database Drivers
QUOTE
20
Database Drivers and Interfaces
CREATE Y
NAME Y
ENCRYPT N
OWNER(password) N
RECLAIM N
PRE(prefix) Y
BINDABLE Y
THREAD Y4
EXTERNAL(member) Y
DLL([flag]) Y
OEM Y
LOCALE N
INDEX N
KEY N
MEMO N
BLOB N
RECORD Y
BINARY N
DUP N
NOCASE N
OPT N
PRIMARY N
21
Database Drivers
NAME N
Ascending Components N
Descending Components N
Mixed Components N
DIM Y
OVER Y
NAME Y
BOF(file) N
BUFFER(file) N
BUILD(file) N
BUILD(key) N
BUILD(index) N
BUILD(index, components) N
BYTES(file) Y5
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) N
DUPLICATE(key) N
EMPTY(file) Y
EOF(file) Y
FLUSH(file) N
LOCK(file) Y
NAME(label) Y
22
Database Drivers and Interfaces
PACK(file) N
POINTER(file) Y2
POINTER(key) N
POSITION(file) Y3
POSITION(key) N
RECORDS(file) N
RECORDS(key) N
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) N
UNLOCK(file) Y
ADD(file) Y
ADD(file, length) N
APPEND(file) Y
APPEND(file, length) N
DELETE(file) N
GET(file,key) N
GET(file, filepointer) Y
GET(key, keypointer) N
HOLD(file) N
NEXT(file) Y
NOMEMO(file) N
23
Database Drivers
PREVIOUS(file) N
PUT(file) Y1
PUT(file, filepointer) Y1
RELEASE(file) N
REGET(file,string) Y
REGET(key,string) N
RESET(file,string) Y
RESET(key,string) N
SET(file) Y
SET(file, key) N
SET(file, filepointer) Y
SET(key) N
SET(key, key) N
SET(key, keypointer) N
SKIP(file, count) N
WATCH(file) N
COMMIT N
ROLLBACK N
NULL(field) N
SETNULL(field) N
SETNULL(file, field) N
SETNONNULL(field) N
24
Database Drivers and Interfaces
Notes
1 When using PUT() with this driver you should take care to PUT back the same number of
characters that were read. If you PUT back more characters than were read, then the
"extra" characters will overwrite the first part of the subsequent record. If you PUT back
fewer characters than were read, then only the first part of the retrieved record is
overwritten, while the last part of the retrieved record remains as it was prior to the PUT().
2 POINTER() returns the relative byte position within the file.
3 POSITION(file) returns a STRING(4).
4 THREADed files consume additional file handles for each thread that accesses the file.
5 BYTES() returns the actual bytes read from the file. The size of the clipped RECORD
may be different depending on the file driver and it's DRIVER() strings. With the ASCII or
BASIC file drivers BYTES will include the ENDOFRECORD (typically 13,10) byte count,
but these bytes are not in the RECORD. With the ASCII driver the /TAB driver string can
affect (expand, change or remove) the tab (9) characters in the record buffer resulting in
a different length.
25
Database Drivers
Btrieve:Specifications
This file driver reads and writes Btrieve files using low-level direct access.
Under Clarion, the Btrieve file driver is implemented by using .DLLs and an .EXE supplied by
Pervasive Software (formerly Btrieve Technologies, Inc.). For an application to use a Btrieve file
driver, the following files must accompany the executable:
You must purchase a 32-bit Btrieve engine from Pervasive Software.
LICENSE WARNING: A registered Clarion owner cannot redistribute the above files
outside of his/her organization without a license from Pervasive Software.
Btrieve:Data Types
Clarion data type Btrieve data type
BYTE STRING (1 byte)
SHORT INTEGER (2 bytes)
LONG INTEGER (4 bytes)
SREAL FLOAT (4 bytes)
REAL FLOAT (8 bytes)
BFLOAT4 BFLOAT (4 bytes)
BFLOAT8 BFLOAT (8 bytes)
PDECIMAL DECIMAL
STRING STRING
CSTRING ZSTRING
PSTRING LSTRING
DATE DATE
TIME TIME
USHORT UNSIGNED BINARY (2 bytes)
ULONG UNSIGNED BINARY (4 bytes)
MEMO STRING,LVAR or NOTE
(see /MEMO below)
BYTE,NAME('LOGICAL') LOGICAL*
USHORT,NAME('LOGICAL') LOGICAL*
PDECIMAL,NAME('MONEY') MONEY*
STRING(@N0n-),NAME('STS') SIGNED TRAILING SEPARATE*
DECIMAL*
Notes:
*You can store Clarion DECIMAL types in a Btrieve file. However, you cannot build a key or
index using the field. This is provided for backward compatibility with older Clarion programs
which used the Btrieve LEM. If you need standard Btrieve decimal data that is compatible with
any other Btrieve compliant program, you should use the PDECIMAL data type and not the
DECIMAL data type.
26
Database Drivers and Interfaces
*If you want to create a file with LOGICAL or MONEY field types, you must specify LOGICAL
or MONEY in the field's NAME attribute. If you are accessing an existing file, the NAME
attribute is not required.
*LOGICAL may be declared as a BYTE or USHORT, depending on whether it is a one or two
byte LOGICAL:
LogicalField1 BYTE !One byte LOGICAL
LogicalField2 USHORT !Two byte LOGICAL
*MONEY may be declared as a PDECIMAL(x,2), where x is the total number of digits to be
stored:
MoneyField PDECIMAL(7,2),NAME('MONEY') !Store up to 99999.99
*Btrieve NUMERIC fields are not fully supported by the driver. Btrieve NUMERIC is stored as a
string with the last character holding a digit and an implied sign. The possible values for this
last character are:
1 2 3 4 5 6 7 8 9 0
Positive: A B C D E F G H I {
Negative: J K L M N O P Q R }
*To access a NUMERIC field you must define a STRING(@N0x), where x is one less than the
digits in the NUMERIC, and a STRING(1) to hold the sign indicator. The Btrieve driver does not
maintain this sign field, the application must be written to directly handle it.
*For example to access a NUMERIC(7) you would have:
NumericGroup GROUP !Store -999999 to 999999
Number STRING(@N06) !Numbers
Sign STRING(1) !Sign indicator
END
27
Database Drivers
Btrieve:File Specifications/Maximums
The specifications below document Version 6.15. Your specific limits are dependant on what
version of Btrieve you are using, and are not dependant on the Btrieve driver. Refer to your
Btrieve documentation for your specific limitations.
The Btrieve driver supports data only and key only files.
28
Database Drivers and Interfaces
Btrieve:Driver Strings
There are switches or "driver strings" you can set to control the way your application creates,
reads, and writes files with a specific driver. Driver strings are simply messages or parameters
that are sent to the file driver at run-time to control its behavior. See Common Driver Features--
Driver Strings for an overview of these runtime Database Driver switches and parameters.
The Btrieve Driver supports the following Driver Strings:
ACS
ALLOWREAD
APPENDBUFFER
BALANCEKEYS
29
Database Drivers
COMPRESS
Btrieve allows you to specify the Client ID used in the Btrieve APIs to uniquely identify a client
application. This can be used to help monitor Btrieve activity as well as avoid a deadlock
situation inside the MicroKernel if multiple threads access the MicroKernel simultaneously.
To set the Client ID, add /CLIENTID=xx to the driver string for the first Btrieve file that you use.
xx is the ID you want to set. This is limited to 2 characters. The following character pairs should
not be used:
You can also use SEND before any file I/O to set this value. You can also use SEND to read the
value.
FREESPACE
30
Database Drivers and Interfaces
LACS
LACS=country_ID,code_page {obsolete}
You can also specify a User-Defined Alternate Collating Sequence. This allows your string key to
sort based on the DOS country code and code page for a particular country. To use this feature
you put '/LACS=country_id,codepage' in your driver string. Note that there must be no spaces
surrounding the comma.
SEND returns country_id,codepage or the string ',' if using the Local Alternate Collating
Sequences feature.
MEMO
/MEMO=SINGLE
To access existing Btrieve files created with the Btrieve LEM from Clarion Professional Developer
2.1(DOS), or files with variable length records set MEMO to SINGLE.
To access a file with variable length records, use a SINGLE style MEMO whose size equals the maximum size
of the variable length component of the record. To add/put records to this style file with binary data stored in the
variable length section, use the ADD(file,length), APPEND(file,length) and PUT(file,pos,length) functions. The
driver ignores the pos parameter in the PUT function, but initialize it to 0 (zero) for future compatibility. The ADD,
APPEND or PUT functions will remove all trailing spaces for text memos and NULL characters for binary memos
before storing the record.
/MEMO=LVAR
/MEMO=NOTE,<delimiter>
To access Xtrieve data files that have data type of Note or LVar, set the driver string to NOTE
and LVAR respectively. With the NOTE data type, specify the end-of-field delimiter. Specify the
ASCII value for the delimiter. NOTE and LVAR memos do not require the use of the size variants
of ADD, APPEND and PUT, when storing records. The end of record marker is not necessary for
a NOTE style memo. The driver automatically adds the end of record marker before storing the
record and removes it before putting the memo data into the memo buffer.
As an example, "/MEMO=NOTE,141" indicates a file with an Xtrieve Notes field using CR/LF as
the delimiter. For more information on the Xtrieve data types refer to the documentation supplied
by Novell.
SEND(file,'MEMO')
31
Database Drivers
NULLPDECIMALS
DRIVER('BTRIEVE', '/NULLPDECIMALS = ON|OFF' )
[ PSize" = ] SEND(file, NULLPDECIMALS = ON|OFF')
A PDECIMAL field has two different values for 0, the sign nibble can be either 0FH or 0. Clarion
normally uses a sign nibble of 0FH. However, if you define a key in Btrieve with the OPT attribute
and this key has a PDECIMAL component, then Btrieve requires that the sign nibble be 0. The
Btrieve file driver detects these situations and automatically converts the sign nibble to and from
0FH as required. The driver does this conversion only for PDECIMAL fields that are components
of a key with the OPT attribute. If you want to force the driver to do this conversion work for all
PDECIMAL fields you can set NULLPDECIMAL=ON. Your program will run fractionally slower,
but you will not have problems in the future if you decide to add an OPT key on that field. If you
do not set this switch to on you later decide to add an OPT key, then you will need to add this
driver string to your file, read every record in the file and write it out again to make sure the 0
nibble is set.
PAGESIZE
PREALLOCATE
TRUNCATE
PROP:PageLevelLocking
PROP:PageLevelLocking sets the type of locking the driver uses with LOGOUT. The driver uses
either page or file level locking schemes. Set to PageLevelLocking by setting the property to '1'.
This is the default. To set the driver to file level locking, set the property to ''.
32
Database Drivers and Interfaces
33
Database Drivers
PROP:PositionBlock
PROP:PositionBlock returns the Btrieve pointer to the Btrieve position block used by the Btrieve
driver for the named file. This allows you to call Btrieve operations directly. For example:
MAP
MODULE('Btrieve')
BTRV(USHORT,LONG,<*STRING>,*UNSIGNED,<*STRING>,BYTE,BYTE),|
NAME('BTRV'),PASCAL,RAW
END
END
StatData STRING(33455)
KeyData STRING(64)
DataLen UNSIGNED(33455)
CODE
PosBlock = file{PROP:PositionBlock}
BTRV(15,PosBlock,StatData,DataLen,KeyData,64,0) !Get file statistics
34
Database Drivers and Interfaces
CREATE Y
NAME Y
ENCRYPT Y
OWNER(password) Y1
RECLAIM Y
PRE(prefix) Y
BINDABLE Y
THREAD Y15
EXTERNAL(member) Y
DLL([flag]) Y
OEM Y
LOCALE Y17
INDEX Y
KEY Y
MEMO Y2
BLOB N
RECORD Y
BINARY Y16
DUP Y
NOCASE Y
OPT Y
PRIMARY Y
NAME Y2
Ascending Components Y
35
Database Drivers
Descending Components Y
Mixed Components Y
DIM Y
OVER Y
NAME Y
BOF(file) Y10
BUFFER(file) N
BUILD(file) Y3
BUILD(key) Y3
BUILD(index) Y3
BUILD(index, components) Y3
BYTES(file) N
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) Y
DUPLICATE(key) Y
EMPTY(file) Y
EOF(file) Y10
FLUSH(file) N
LOCK(file) N4
NAME(label) Y
PACK(file) Y
POINTER(file) Y11
POINTER(key) Y11
36
Database Drivers and Interfaces
POSITION(file) Y12
POSITION(key) Y12
RECORDS(file) Y
RECORDS(key) Y
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) Y
UNLOCK(file) N
ADD(file) Y5
ADD(file, length) Y5
APPEND(file) Y6
DELETE(file) Y7
GET(file,key) Y
GET(file, filepointer) Y
GET(key, keypointer) Y
HOLD(file) Y
NEXT(file) Y
NOMEMO(file) Y
PREVIOUS(file) Y
PUT(file) Y5
PUT(file, filepointer) N
37
Database Drivers
RELEASE(file) Y
REGET(file,string) Y
REGET(key,string) Y
RESET(file,string) Y
RESET(key,string) Y
SET(file) Y
SET(file, key) Y
SET(file, filepointer) Y8
SET(key) Y
SET(key, key) Y
SET(key, keypointer) Y8
SKIP(file, count) Y
WATCH(file) Y
COMMIT Y14
ROLLBACK Y
NULL(field) N
SETNULL(field) N
SETNULL(file,field) N
SETNONNULL(field) N
Notes
1 We recommend using a variable password that is lengthy and contains special characters
because this more effectively hides the password value from anyone looking for it. For
example, a password like "dd....#$...*&" is much more difficult to "find" than a password
like "SALARY."
To specify a variable instead of the actual password in the Owner Name field of the
38
Database Drivers and Interfaces
File Properties dialog, type an exclamation point (!) followed by the variable name.
For example: !MyPassword.
2 The driver ignores any NAME attribute on a MEMO field. MEMO fields can reside either in
a separate file, or in the data file if the driver string /MEMO is set to SINGLE, LVAR or
NOTE. If the driver string /MEMO is not set, the separate MEMO file name is "MEM,"
preceded by the first five characters of the file's label, plus the file extension ".DAT."
Setting the driver string /MEMO restricts you to one memo field per file.
3 If used after an APPEND(), but before a file is closed, this adds the keys dropped by
APPEND(). In all other cases BUILD() rebuilds the file and keys. If you only want to
rebuild keys, doing a BUILD(key) for each key is faster than BUILD(file).
4 Btrieve does not directly support file locking. If you require file locking, use LOGOUT.
5 When using the LVAR and NOTE memo type, make certain that the memo has the
appropriate structure. If the structure is incorrect and the driver calculates a length
greater than the maximum memo size defined for that file, these functions fail and set
errorcode to 57 - Invalid Memo File.
6 Btrieve does not support non-key updates. To emulate APPEND() behavior, the driver
drops all indexes possible when APPEND() is first called. Calling BUILD() immediately
after appending records rebuilds the dropped key fields.
7 Btrieve's DELETE destroys positioning information when processing in file order. The
driver attempts to reposition to the appropriate record. This is not always possible and
may require the driver to read from the start of the file. Using key order processing avoids
this possible slow down.
8 If a file pointer or key pointer has a value of zero, the driver ignores the pointer parameter.
Processing is set to either file or key order, and the record pointer is set to the first
element.
9 If the file pointer has a value of zero, processing starts at the first key value whose
position is greater than (or less than for PREVIOUS) the file pointer. Not passing a valid
pointer, other than maximum LONG or maximum ULONG, is inefficient.
10 These functions are supported, but not recommended. They cause more disk I/O than
ERRORCODE(). Btrieve returns eof when reading past the last record. Therefore, the
driver must read the next record, then the next to see if it's at the end of file, then return
to the record you want.
11 POINTER() returns a relative position within the file, not a record number.
12 POSITION(file) returns a STRING(4). POSITION(key) returns a STRING the size of the
key fields + 4 bytes.
13 If a system crashes during a transaction (LOGOUT--COMMIT), the recovery is
automatically handled by the Btrieve driver the next time the affected file is accessed.
When you issue a LOGOUT, all Btrieve files accessed during the transaction are logged
out. The following code is illegal because you cannot close a logged-out file:
LOGOUT(1,file1)
OPEN(file1)
CLOSE(file1)
14 See also PROP:Logout in the Language Reference.
15 THREADed files do not consume additional file handles for each thread that accesses
the file.
16 OEM conversion is not applied to BINARY MEMOs. The driver assumes BINARY
MEMOs are zero padded; otherwise, space padded.
39
Database Drivers
17 LOCALE only effects the CREATE statement. Below is a list of locale/code page pairs
supported by Btrieve. If one of these pairs is set, then the CREATE statement will create
a Btrieve ISR ACS. See Pervasive SQL’s documentation on ISR for more information.
Any English Locale 437 MS-DOS Latin-US
850 MS-DOS-Latin-1
437 MS-DOS Latin-US
Any French Locale 850 MS-DOS-Latin-1
437 MS-DOS Latin-US
Any German Locale 850 MS-DOS-Latin-1
437 MS-DOS Latin-US
Any Spanish Locale 850 MS-DOS-Latin-1
Btrieve:Other
Client/Server
For Client/Server-based Btrieve, Netware Btrieve is a server-based version of Btrieve that runs on
a Novell server.
Collating Sequence
NOCASE Key Attribute
NLM 5 does not support case insensitive indexing. When necessary, you must supply an
alternate collating sequence which implements case insensitive sorting.
Btrieve supports an alternate collating sequence. However, NLM 6 does not support both
NOCASE and an alternate collating sequence. If you specify both, the NOCASE attribute takes
precedence. No error is returned fromThe SEND function.
Changing the Collating Sequence
Btrieve stores the collating sequence inside the file. So to change the collating sequence you
have to change the .ENV file, then create a new Btrieve file based on the modified .ENV file,
then copy the data from the old file to the new file.
Error Codes
All Btrieve error codes up to 2007 are now mapped to appropriate error messages.
File Sharing
Btrieve lets you open a file in five different formats: NORMAL, ACCELERATED, READ-ONLY,
VERIFY, or EXCLUSIVE. The equivalent Clarion OPEN() states are:
Btrieve State Clarion OPEN/SHARE access mode
ACCELERATED Read/Write with FCB compatibility mode (2H)
READ-ONLY Read Only (0H,10H,20H,30H,40H)
VERIFY Write Only with FCB compatibility mode (1H)
EXCLUSIVE Write Only with any Deny flag (11H,21H,31H,41H);
Read/Write with Deny All, Read or Write (12H,22H,32H)
NORMAL Read/Write with Deny None (42H)
Btrieve allows a file to have a specified owner. See the /READONLY driver string for details on
setting this flag. The file may also be encrypted with the ENCRYPT attribute. A file can only be
encrypted when an owner name is supplied.
40
Database Drivers and Interfaces
File Structure
A single file normally holds the data and all keys. Data filenames default to a *.DAT file extension.
By default, the driver stores memos in a separate file, or optionally in the data file itself, given the
appropriate driver string.
Because Btrieve is a data-model independent, indexed record manager, it does not store field
definitions within the data itself. The application accessing the data determines how to interpret
the Btrieve record. Absent .DDF files describing the Btrieve file, it is very difficult for an application
that does not create or maintain the file to meaningfully interpret its data.
The Btrieve file format stores minimal file structure information in the file. As far as possible, the
driver validates your description against the information in the file. However, it is possible to
successfully open a Btrieve file that has key definitions that do not exactly match your definition.
You must make certain that your file and key definitions accurately match the Btrieve file.
41
Database Drivers
KEY Definitions
When defining a file, the key definition does not need to exactly match the underlying file. For
example, you can have a physical file with a single component STRING(20). You can define
this as a key with two string components with a total length of 20. The rule is that the data
types must match and the total size must match. However, if your Clarion definition does not
exactly match the underlying file, the driver cannot optimize APPEND() or BUILD() statements.
A Key's NAME attribute can add additional functionality.
KEY,NAME('MODIFIABLE=true|false')
Btrieve lets you create a key that cannot be changed once created. To use this feature you can
use the name attribute on the key to set MODIFIABLE to FALSE. It defaults to TRUE.
KEY,NAME('ANYNULL')
Btrieve lets you create a key that will not include a record if any key components are null. To
create such a key you specify ANYNULL in the key name.
For example, to create a key that is non-modifiable and excludes keys if any component is null:
Key1 KEY(+pre:field1,-pre:field2),NAME('ANYNULL MODIFIABLE=FALSE')
KEY,NAME('AUTOINCREMENT')
The Clarion CREATE statement creates a Btrieve autoincrement key. The key must have 1
key component of type LONG.
KEY,NAME('REPEATINGDUPLICATE')
By default Btrieve version 6 stores a reference to only the first record in a series of duplicate
records in a key. The other occurrences of the duplicate key value are obtained by following a
link list stored at the record. To create an index where all duplicate records are stored in the
key you use the NAME('REPEATINGDUPLICATE'). This produces larger keys, but random
access to duplicate records is faster (this feature is only available for version 6 files).
Page Size
To determine the physical record length, add 8 bytes for each KEY that allows duplicates. Add 4
bytes if the file allows variable record lengths. Finally, allow 6 bytes for overhead per page.
For example: If the record size is 300 bytes and the file has three KEYs that allow Duplicates, the
total record size is:
A page size of 512 would only hold one such record, and 182 bytes per page would go unused
(512 - 6 - 324). If the page size were 1024, three records could be stored per page and only 46
bytes would go unused (1024 - 6 - (324 * 3)).
42
Database Drivers and Interfaces
You must load BTRIEVE.EXE with a page size equal to or greater than the largest page size of
any file that you will be accessing.
Record Lengths
The driver stores records less than 4K as fixed length. It stores records greater than 4K as
variable length. The minimum record length is 4 bytes. One record can be held in each open file
by each user.
Record Pointers
Btrieve uses an unsigned long for its internal record pointer; negative values are stripped of their
sign. We recommend the ULONG data type for your record pointer.
Transaction Framing
You cannot create files inside a transaction frame with Btrieve. This means that if you have
"Defer opening files until accessed" template option checked in your applications, you must make
sure that all files exist before entering transaction frames (initiated with LOGOUT). The easiest
way to ensure this is that on startup of an application, it should detect if a file exists, and if it does
not, then create a routine that creates the files as needed (by simply calling FileManager.Open for
all the files).
43
Database Drivers
By avoiding the ASCII-only file formats of many other popular PC database application
development systems, the Clarion file format provides a more secure means of storing
data.
Clarion:Data Types
BYTE DECIMAL
LONG MEMO
REAL GROUP
Clarion:File Specifications/Maximums
File Size: 4,294,967,295
Records per File : 4,294,967,295
Record Size: 65,520 bytes
Field Size : 65,520 bytes
Field Name: 12 characters
Fields per Record: 65,520
Keys/Indexes per File: 251
Key Size: 245 bytes
Memo fields per File : 1
Memo Field Size: 65,520 bytes
Open Data Files: Operating system dependent
44
Database Drivers and Interfaces
Clarion:Driver Strings
There are switches or "driver strings" you can set to control the way your application creates,
reads, and writes files with a specific driver. Driver strings are simply messages or parameters
that are sent to the file driver at run-time to control its behavior. See Common Driver Features--
Driver Strings for an overview of these runtime Database Driver switches.
Some driver strings have no effect after the file is open, so no SEND function
syntax is listed for those strings. However, the SEND function syntax to return the
value of the switch is listed for all driver strings.
The Clarion Driver supports the following Driver Strings:
DELETED
SEND(file, 'DELETED')
For use only with the SEND command when IGNORESTATUS is on. Reports the status of the
loaded record. If deleted, the return string is "ON" and if not "OFF."
HELD
SEND(file, 'HELD')
For use only with the SEND command when IGNORESTATUS is on. Reports the status of the
loaded record. If held, the return string is "ON" and if not "OFF."
IGNORESTATUS
MAINTAINHEADERTIME
RECOVER
45
Database Drivers
The RECOVER string, when n is greater than 0, UNLOCKs data files, RELEASEs held records,
and rolls back incomplete transactions in order to recover from a system crash. See also
Transaction Processing for Clarion Files.
n represents the number of seconds to wait before invoking the recovery process. When n is
equal to 1, the recovery process is invoked immediately. When n is equal to 0, the recovery
process is disarmed.
There are two ways of using RECOVER:
SEND(file, 'RECOVER=n')
OPEN(file)
This releases a LOCK on a file that was locked when a machine crashed. It also rolls back a
transaction that was in process when a system crashed.
SEND(file, 'RECOVER=n')
GET or NEXT or PREVIOUS
This removes a hold flag from records that where held when a machine crashed. Here is a piece
of code that removes all hold flags from a file:
OPEN(file) !make sure no one else is using the file
SEND(file,'IGNORESTATUS=ON')
SET(file)
LOOP
NEXT(file)
IF ERRORCODE()
BREAK
END
IF SEND(file,'HELD') = 'ON' THEN
SEND(file,'RECOVER=1')
REGET(file,POSITION(file))
END
END
RECOVER may not be used as a DRIVER string--you may only use it with the SEND function.
The SEND function returns a blank string.
46
Database Drivers and Interfaces
CREATE Y
NAME Y
ENCRYPT Y
OWNER(password) Y1
RECLAIM Y
PRE(prefix) Y
BINDABLE Y
THREAD Y8
EXTERNAL(member) Y
DLL([flag]) Y
OEM Y
LOCALE Y
INDEX Y
KEY Y
MEMO Y
BLOB N
RECORD Y
BINARY Y9
DUP Y
NOCASE Y
OPT Y
PRIMARY Y
NAME Y
47
Database Drivers
Ascending Components Y
Descending Components N
Mixed Components N
DIM Y
OVER Y
NAME Y
BOF(file) Y2
BUFFER(file) N
BUILD(file) Y
BUILD(key) Y
BUILD(index) Y
BUILD(index, components) Y
BYTES(file) Y
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) Y
DUPLICATE(key) Y
EMPTY(file) Y
EOF(file) Y2
FLUSH(file) Y
LOCK(file) Y
NAME(label) Y
PACK(file) Y
POINTER(file) Y3
48
Database Drivers and Interfaces
POINTER(key) Y3
POSITION(file) Y4
POSITION(key) Y4
RECORDS(file) Y
RECORDS(key) Y
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) Y
UNLOCK(file) Y
ADD(file) Y10
ADD(file, length) N
APPEND(file) Y
APPEND(file, length) N
DELETE(file) Y
GET(file,key) Y
GET(file, filepointer) Y
GET(key, keypointer) Y
HOLD(file) Y
NEXT(file) Y
NOMEMO(file) Y
PREVIOUS(file) Y
PUT(file) Y10
PUT(file, filepointer) Y
49
Database Drivers
RELEASE(file) Y
REGET(file,string) Y
REGET(key,string) Y
RESET(file,string) Y
RESET(key,string) Y
SET(file) Y
SET(file, key) Y
SET(file, filepointer) Y
SET(key) Y
SET(key, key) Y
SET(key, keypointer) Y
SKIP(file, count) Y
WATCH(file) Y
COMMIT Y
ROLLBACK Y
NULL(field) N
SETNULL(field) N
SETNULL(file,field) N
SETNONNULL(field) N
50
Database Drivers and Interfaces
Notes
1 We recommend using a variable password that is lengthy and contains special characters
because this more effectively hides the password value from anyone looking for it. For
example, a password like "dd....#$...*&" is much more difficult to "find" than a password
like "SALARY."
To specify a variable instead of the actual password in the Owner Name field of the
File Properties dialog, type an exclamation point (!) followed by the variable name.
For example: !MyPassword.
2 These functions are supported but not recommended due to the lack of support in other
file systems. NEXT and PREVIOUS post Error 33 if you attempt to read beyond the end
of the file.
3 POINTER() returns a record number.
4 POSITION(file) returns a STRING(4). POSITION(key) returns a STRING the size of the
key fields + 4 bytes.
5 The RECOVER switch must be "armed" at the beginning of your program in order to
support transaction processing. See Driver Strings for more information on the
RECOVER function.
6 LOGOUT has the effect of LOCKing the file. See also PROP:Logout in the Language
Reference.
7 You cannot LOGOUT an aliased file and its primary file at the same time.
8 THREADed files consume additional file handles for each thread that accesses the file.
9 OEM conversion is not applied to BINARY MEMOs. The driver assumes BINARY MEMOs
are zero padded; otherwise, space padded.
10 Prior to Clarion 2.003 in 16-bit programs under Microsoft operating systems, writes (ADD,
PUT) did not correctly flush operating system buffers. This problem is corrected with
Clarion 2.003 and higher, so that writes are slower but safer. To implement the pre 2.003
behavior, use STREAM and FLUSH.
Clarion:Other
Transaction Processing for Clarion Files
When you issue a LOGOUT statement the Clarion file driver creates a transaction file called
programname.TR$. By default this file is created in the same directory as the program. To create
the transaction file elsewhere, add a CWC21 section to the WIN.INI file as follows:
[CWC21]
CLATMP=path
where path is a directory visible to all users. This statement
PUTINI('CWC21','CLATMP',path)
creates the correct .INI file section.
During a transaction datafile.LOG files are created for each data file edited during the transaction.
These LOG files always reside in the same directory as the data file.
If a system crashes while a transaction is active, no user will be able to access the files until a
recovery is run on the files. See the RECOVER send command on how to do this.
LOGOUT has the effect of LOCKing the file.
51
Database Drivers
Field Labels
The Clarion driver only supports fully qualified field names (prefix + label) of 16 characters or
less. That is, within the Clarion file (*.DAT) header, the driver truncates prefix + label to the first
16 characters. If the first 16 characters are not unique, the truncation results in duplicate field
names.
Duplicate field names within the file header can cause problems with Clarion for DOS 2.1 and
earlier. In addition, it can cause problems if you import the file definition from the Clarion file
(*.DAT), then compile a Clarion application based on the imported file definition containing the
duplicate field names.
You can avoid duplicate field name problems by using the NAME attribute (the External Name
field in the Data Dictionary's Field Properties dialog) to provide unique names for fields whose
first 16 characters are duplicated. By providing unique names in the NAME attribute, your
application can refer to the field by its (long) label, and the Clarion driver uses the unique NAME
attribute to resolve conflicts.
52
Database Drivers and Interfaces
53
Database Drivers
Clipper:Specifications
The Clipper file driver is compatible with Clipper Summer '87 and Clipper 5.0. The default data file
extension is *.DBF.
Keys and Indexes exist as separate files from the data file. Keys are dynamic--they automatically
update as the data file changes. Indexes are static--they do not automatically update, but instead
require the BUILD statement for updating. The default file extension for the index file is *.NTX.
The driver stores records as fixed length. It stores memo fields in a separate file. The memo file
name takes the first eight characters of the File Label plus an extension of .DBT.
If your application reads and writes to existing files, a pictured STRING will suffice. However, if
your application creates a Clipper file, you may require additional information for these Clipper
types:
* To create a Numeric field in the Data Dictionary, choose the REAL data type. In the
External Name field on the Attributes tab, specify
'NumericFieldName=N(Precision,DecimalPlaces)' where NumericFieldName is the name
of the field, Precision is the precision of the field and DecimalPlaces is the number of
decimal places. With a REAL data type, you cannot access the Character or Places fields
in the Field definition, you must specify those attributes with an expression in the External
Name Field on the Attributes tab.
For example, if you want to create a field called Number with nine significant digits and
two decimal places, enter 'Number=N(9,2) in the External Name field on the Attributes
tab of the Field properties in the Data Dictionary.
If you're hand coding a native Clarion data type, add the NAME attribute using the same
syntax.
54
Database Drivers and Interfaces
* To create a logical field, using the data dictionary, choose the BYTE data type. There are
no special steps; however, see the miscellaneous section for tips on reading the data
from the field.
If you're hand coding a STRING with picture, add the NAME attribute: STRING(1),
NAME('LogFld = L').
* To create a date field, using the data dictionary, choose the DATE data type, rather than
LONG, which you usually use for the TopSpeed or Clarion file formats.
* MEMO field declarations require the a pointer field in the file's record structure. Declare
the pointer field as a STRING(10) or a LONG. This field will be stored in the .DBF file
containing the offset of the memo in the .DBT file. The MEMO declaration must have a
NAME() attribute naming the pointer field. An example file declaration follows:
File FILE, DRIVER('Clipper')
Memo1 MEMO(200),NAME('Notes')
Memo2 MEMO(200),NAME('Text')
Rec RECORD
Mem1Ptr LONG,NAME('Notes')
Mem2Ptr STRING(10),NAME('Text')
END
END
Whenever possible, use the File Import Utility in the Dictionary Editor to define
your files.
Clipper:File Specifications/Maximums
File Size: 2,000,000,000 bytes
Records per File: 1,000,000,000
Record Size: 4,000 bytes (Clipper '87)
8,192 bytes (Clipper 5.0)
Field Size
Character: 254 bytes (Clipper '87)
2048 bytes (Clipper 5.0)
Date: 8 bytes
Logical: 1 byte
Numeric: 20 bytes including decimal point
Memo: 65,520 bytes (see note)
Field Name: 10 characters
Fields per Record: 1024
Keys/Indexes per File: No Limit
Key Sizes
Character: 100 bytes
Numeric, Date: 8 bytes
Memo fields per File: Dependent on available memory
Open Files: Operating system dependent
55
Database Drivers
Clipper:Driver Strings
There are switches or "driver strings" you can set to control the way your application creates,
reads, and writes files with a specific driver. Driver strings are simply messages or parameters
that are sent to the file driver at run-time to control its behavior. See Common Driver Features--
Driver Strings for an overview of these runtime Database Driver switches and parameters.
Some driver strings have no effect after the file is open, so no SEND function syntax is
listed for those strings. However, the SEND function syntax to return the value of the
switch is listed for all driver strings.
The Clipper Driver supports the following Driver Strings:
BUFFERS
The default is three buffers of 1024 bytes each. Increasing the number of buffers will not
increase performance when a file is shared by multiple users.
RECOVER
DRIVER('CLIPPER', '/RECOVER' )
[ Status" = ] SEND(file, 'RECOVER' )
Equivalent to the Xbase RECALL command, which recovers records marked for deletion. When
using the Clipper driver, the DELETE statement flags a record as "inactive." The driver does not
remove the record until the PACK command is executed.
RECOVER is evaluated each time you open the file if you add the driver string to the data
dictionary. When the driver recovers the records previously marked for deletion, you must
manually rebuild keys and indexes with the BUILD statement.
IGNORESTATUS
56
Database Drivers and Interfaces
DELETED
ZEROY2K
DRIVER('CLIPPER', '/ZEROY2K = on | off' )
[ Status" = ] SEND(file, 'ZEROY2K [ on | off ]' )
In the header of Clipper files there is a field that stores the year that the file was last edited. Some
applications store this as the number of years since 1900. Others store it as a 2-digit year. So for
dates in the year 2000 some applications store 0 in this field and others 100. Clarion will read files
with either. However it will write 100. Writing 100 may make the files unreadable by products that
only support 0. To change this behavior you can with use a driver string of ZEROY2K, a SEND
command or a setting in the WIN.INI file.
The driver will store 0 in the DBF file header when the WINI.INI setting is set to 1 or 'on' in a
SEND command or driver string, otherwise a 100 will be stored in the DBF file header.
The SEND command causes the setting to be set for all files that use that driver, not just
for that file.
Example:
WIN.INI
;Sets all Clipper files to store a 0 in the DBF file header
[CWCLIPPER]
ZEROY2K=1
SEND command
SEND('Orders', ZEROY2K='on' !sets Orders file to store 0 in the DBF file header
SEND('Orders', ZEROY2K='off' !sets Orders file to store 100 in the DBF file header
Driver String
Orders FILE, DRIVER('clipper', '/ZEROY2K=on'),PRE(ORD) !SETS Orders file to store 0
57
Database Drivers
CREATE Y1
NAME Y
ENCRYPT N
OWNER(password) N
RECLAIM N2
PRE(prefix) Y
BINDABLE Y
THREAD Y16
EXTERNAL(member) Y
DLL([flag]) Y
OEM Y
LOCALE Y
INDEX Y
KEY Y
MEMO Y3
BLOB N
RECORD Y
BINARY N
DUP Y4
NOCASE Y
OPT N
PRIMARY Y
58
Database Drivers and Interfaces
NAME Y3
Ascending Components Y
Descending Components Y
Mixed Components Y
DIM N
OVER Y
NAME Y1
BOF(file) Y11
BUFFER(file) N
BUILD(file) Y
BUILD(key) Y
BUILD(index) Y
BUILD(index, components) Y5
BYTES(file) N
CLOSE(file) Y
CREATE(file) Y1
DUPLICATE(file) Y
DUPLICATE(key) Y
EMPTY(file) Y
EOF(file) Y11
FLUSH(file) Y
LOCK(file) Y
NAME(label) Y
59
Database Drivers
PACK(file) Y
POINTER(file) Y12
POINTER(key) Y12
POSITION(file) Y13
POSITION(key) Y13
RECORDS(file) Y14
RECORDS(key) Y14
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) Y
UNLOCK(file) Y
ADD(file) Y9
ADD(file, length) N
APPEND(file) Y9
APPEND(file, length) N
DELETE(file) Y6
GET(file,key) Y
GET(file, filepointer) Y
GET(key, keypointer) Y
HOLD(file) Y10
NEXT(file) Y
NOMEMO(file) Y
60
Database Drivers and Interfaces
PREVIOUS(file) Y
PUT(file) Y
PUT(file, filepointer) Y
RELEASE(file) Y
REGET(file,string) Y
REGET(key,string) Y
RESET(file,string) Y
RESET(key,string) Y
SET(file) Y
SET(file, key) Y
SET(file, filepointer) Y
SET(key) Y
SET(key, key) Y
SET(key, keypointer) Y
SKIP(file, count) Y
WATCH(file) Y
COMMIT N
ROLLBACK N
NULL(field) N
SETNULL(field) N
SETNULL(file,field) N
SETNONNULL(field) N
61
Database Drivers
Notes
1 If your application creates a Clipper file, you may require additional NAME information for
these Clipper data types:
For a Clipper numeric field, use the Clarion REAL data type. Then in the NAME attribute
(the External Name field on the Attributes tab in the Field Properties dialog), specify
'NumericFieldName=N(Precision,DecimalPlaces)' where NumericFieldName is the name
of the field, Precision is the precision of the field and DecimalPlaces is the number of
decimal places. See Data Types above for more information.
For a Clipper logical field, use the Clarion BYTE data type. See Data Types above for
more information. See the Miscellaneous section for tips on reading the data from the
field.
For a Clipper date field, use the Clarion DATE data type. See Data Types above for more
information.
2 When the driver deletes a record from a Clipper database, the record is not physically
removed, instead the driver marks it inactive. Memo fields are not physically removed
from the memo file, however they cannot be retrieved if they refer to an inactive record.
To remove records and memo fields permanently, execute a PACK(file).
To those programmers familiar with Clipper, this driver processes deleted records
consistent with the way Clipper processes them after the SET DELETED ON
command is issued. Records marked for deletion are ignored from processing by
executable code statements, but remain in the data file.
3 MEMO field declarations require a pointer field in the file's record structure. Declare the
pointer field as a STRING(10) or a LONG. This field will be stored in the .DBF file
containing the offset of the memo in the .DBT file. The MEMO declaration must have a
NAME() attribute naming the pointer field. See Data Types above for more information.
4 In Clipper it is legal to enter multiple records with duplicates of the unique key
components. However, only the first of these records is indexed. So processing in key
order only shows this first record. If you delete a record, then enter a new record with the
same key value, the key file continues to point at the deleted record rather than the new
record. In this situation, the Clipper file driver driver changes the key file to point at the
active record rather than the deleted record. This means that if you use a Clipper
program to delete a unique record, then insert a duplicate of this record, the new record
is invisible when processing in key order until a pack is done. If you do the same process
in a Clarion program, the new record is visible when processing in key order.
5 When building dynamic indexes, the components may take one of two forms:
BUILD(DynNdx, '+Pre:FLD1, -Pre:FLD2')
This form specifies the names of the fields on which to build the index. The field names
must appear as specified in the fields' NAME() attribute if supplied, or must be the label
name. A prefix may be used for compatibility with Clarion conventions but is ignored.
BUILD(DynNdx, 'T[Expression]')
This form specifies the type and Expression used to build an index--see Miscellaneous--
Key Definition below.
6 The COPY() command copies data and memo files using newfile, which may specify a
new file name or directory. Key or index files are copied if the newfile is a subdirectory
specification. To copy an index file to a new file, use a special form of the copy
command:
COPY(file,'<index>|<newfile>')
62
Database Drivers and Interfaces
This returns File Not Found if an invalid index is passed. The COPY command assumes
a default extension of .NTX for both the source and the target file names if none is
specified. If you require a file name without an extension, terminate the name with a
period. Given the file structure:
Clar2 FILE,CREATE,DRIVER('Clipper'),PRE(CL2)
NumKey KEY(+CL2:Num),DUP
StrKey KEY(+CL2:Str1)
StrKey2 KEY(+CL2:Str2)
AMemo MEMO(100), NAME('mem')
Record RECORD
Num STRING(@n-_9.2)
STR1 STRING(2)
STR2 STRING(2)
Mem STRING(10)
END
END
The following commands copy this file definition to A:
COPY(Clar2,'A:\CLAR2')
COPY(Clar2,'StrKey|A:\STRKEY')
COPY(Clar2,'StrKey2|A:\STRKEY2')
COPY(Clar2,'NumKey|A:\NUMKEY')
After these calls, the following files would exist on drive A: CLAR2.DBF, CLAR2.DBT,
STRKEY.NTX, STRKEY2.NTX, and NUMKEY.NTX.
7 You do not need SHARE (or VSHARE) in any environment (for example, Novell) that
supplies file locking as part of the operating system.
8 The RENAME command copies the data and memo files using newfile, which may specify
a new file name or directory path. Key and index files must be renamed using the same
syntax as the COPY command, above.
9 The ADD statement tests for duplicate keys before modifying the data file or its
associated KEY files. Consequently it is slower than APPEND which performs no checks
and does not update KEYs. When adding large amounts of data to a database use
APPEND...BUILD in preference to ADD.
10 Clipper performs record locking by locking the entire record within the data file. This
prevents read access to other processes. Therefore we recommend minimizing the
amount of time for which a record is held.
11 Although the driver supports these functions, we do not recommend their use. They must
physically access the files and add overhead. Instead, test the value returned by
ERRORCODE() after each sequential access. NEXT or PREVIOUS post Error 33
(Record Not Available) if an attempt is made to access a record beyond the end or
beginning of the file.
12 There is no distinction between file pointers and key pointers; they both return the record
number for any given record.
13 POSITION(file) returns a STRING(12). POSITION(key) returns a STRING the size of the
key fields + 4 bytes.
14 Under Clipper, the RECORDS() function reports the same number of records for the data
file and its keys and indexes. Usually there will be no difference in the number of records
unless the INDEX is out of date. Because the DELETE statement does not physically
remove records, the number of records reported by the RECORDS() function includes
inactive records. Exercise care when using this function.
15 See also PROP:Logout in the Language Reference.
16 THREADed files consume additional file handles for each thread that accesses the file.
63
Database Drivers
Clipper:Other
Boolean Evaluation
Clipper allows a logical field to accept one of nine possible values (y,Y,n,N,t,T,f,F or a space
character). The space character is neither true nor false. When using a logical field from a
preexisting database in a logical expression, account for all these possibilities. Remember that
when a STRING field is used as an expression, it is true if it contains any data and false if it is
equal to zero or blank. Therefore, to evaluate a Logical field's truth, the expression should be true
if the field contains any of the "true" characters (T,t,Y, or y). For example, if a Logical field were
used to specify a product as taxable or nontaxable, the expression to evaluate its truth would be:
(If Condition):
Taxable='T' OR Taxable='t' OR Taxable='Y' OR Taxable='y'
Large MEMOs
Clipper supports MEMO fields up to a maximum of 64K. If you have an existing file which
includes a memo greater than 64K, you can use the file but not modify the large MEMOs.
You can determine when your application encounters a large MEMO by detecting when the
memo pointer variable is non-blank, but the memo appears to be blank. Error 47 (Bad Record
Declaration) is posted. If you attempt to update such a record, any modification to the MEMO field
is ignored.
Sort Sequence
The Clipper driver supports international sort orders, however, to maintain compatibility with
Clipper's international sort order, remove the CLADIGRAPH= line from ..\(CLA
root)\BIN\Clarion7.ENV file.
Key Definition
Clipper supports the use of expressions to define keys. Within the Dictionary Editor, you can
place the expression in the external name field in the Key Properties dialog. The format of the
external name is:
'FileName=T[Expression]'
Where FileName represents the name of the index file (which can contain a path and file
extension), and T represents the type of the index. Valid types are: C = character, D = date, and
N = numeric. If the type is D or N then Expression can name only one field.
String expressions may use the '+' operator to concatenate multiple string arguments. Numeric
expressions use the '+' or '-' operators with their conventional meanings. The maximum length of
a Clipper expression is 250 characters.
The expression may refer to multiple fields in the record, and may contain xBase functions.
Square brackets must enclose the expression. The currently supported functions appear below. If
the driver encounters an unsupported Xbase function in a preexisting file, it posts error 76 'Invalid
Index String' when the file is opened for keys and static indexes.
Supported xBase Key Definition Functions
64
Database Drivers and Interfaces
65
Database Drivers
dBaseIII:Data Types
The xBase file format stores all data as ASCII strings. You may either specify STRING types with
declared pictures for each field, or specify native Clarion types, which the driver converts
automatically.
dBase data type Clarion data type STRING w/ picture
Date DATE STRING(@D12)
*Numeric REAL STRING(@N-_p.d)
*Logical BYTE STRING(1)
Character STRING STRING
*Memo MEMO MEMO
If your application reads and writes to existing files, a pictured STRING will suffice. However, if
your application creates a dBase III file, you may require additional information for these dBase III
types:
* To create a Numeric field in the Data Dictionary, choose the REAL data type. In the
External Name field on the Attributes tab, specify
'NumericFieldName=N(Precision,DecimalPlaces)' where NumericFieldName is the name
of the field, Precision is the precision of the field and DecimalPlaces is the number of
decimal places. With a REAL data type, you cannot access the Character or Places fields
in the Field definition, you must specify those attributes with an expression in the External
Name Field on the Attributes tab.
For example, if you want to create a field called Number with nine significant digits and
two decimal places, enter 'Number=N(9,2) in the External Name field on the Attributes
tab of the Field properties in the Data Dictionary.
If you're hand coding a native Clarion data type, add the NAME attribute using the same
syntax.
If you're hand coding a STRING with picture, STRING(@N-_9.2), NAME('Number'),
where Number is the field name.
66
Database Drivers and Interfaces
* To create a logical field, using the data dictionary, choose the BYTE data type. There are
no special steps; however, see the miscellaneous section for tips on reading the data
from the field.
If you're hand coding a STRING with picture, add the NAME attribute: STRING(1),
NAME('LogFld = L').
To create a date field, using the data dictionary, choose the DATE data type, rather than
LONG, which you usually use for the TopSpeed or Clarion file formats.
* MEMO field declarations require the a pointer field in the file's record structure. Declare
the pointer field as a STRING(10) or a LONG. This field will be stored in the .DBF file
containing the offset of the memo in the .DBT file. The MEMO declaration must have a
NAME() attribute naming the pointer field. An example file declaration follows:
File FILE, DRIVER('dBase3')
Memo1 MEMO(200),NAME('Notes')
Memo2 MEMO(200),NAME('Text')
Rec RECORD
Mem1Ptr LONG,NAME('Notes')
Mem2Ptr STRING(10),NAME('Text')
END
END
Use the File Import Utility in the Clarion Dictionary Editor to define your files.
dBaseIII:File Specifications/Maximums
File Size: 2,000,000,000 bytes
Records per File: 1,000,000,000
Record Size: 4,000 bytes
Field Size
Character: 254 bytes
Date: 8 bytes
Logical: 1 byte
Numeric: 20 bytes including decimal point
Memo: 64K (see note)
Fields per Record: 128
Field Name: 10 characters
Keys/Indexes per File: No Limit
Key Sizes
Character: 100 bytes
Numeric, Date: 8 bytes
Memo fields per File: Dependent on available memory
Open Files: Operating system dependent
67
Database Drivers
dBaseIII:Driver Strings
There are switches or "driver strings" you can set to control the way your application creates,
reads, and writes files with a specific driver. Driver strings are simply messages or parameters
that are sent to the file driver at run-time to control its behavior. See Common Driver Features--
Driver Strings for an overview of these runtime Database Driver switches and parameters.
Some driver strings have no effect after the file is open, so no SEND function syntax is
listed for those strings. However, the SEND function syntax to return the value of the
switch is listed for all driver strings.
The dBaseIII Driver supports the following Driver Strings:
BUFFERS
The default is three buffers of 1024 bytes each. Increasing the number of buffers will not
increase performance when a file is shared by multiple users.
RECOVER
DRIVER('DBASE3', '/RECOVER' )
[ Status" = ] SEND(file, 'RECOVER' )
Equivalent to the Xbase RECALL command, which recovers records marked for deletion. When
using the dBaseIV driver, the DELETE statement flags a record as "inactive." The driver does not
remove the record until the PACK command is executed.
RECOVER is evaluated each time you open the file if you add the driver string to the data
dictionary. When the driver recovers the records previously marked for deletion, you must
manually rebuild keys and indexes with the BUILD statement.
IGNORESTATUS
68
Database Drivers and Interfaces
DELETED
OMNIS
DRIVER('DBASE3', '/OMNIS' )
SEND(file, 'OMNIS' )
Specifies OMNIS file header and file delimiter compatibility. SEND is only valid when the file is
closed; it returns nothing.
ZEROY2K
The driver will store 0 in the DBF file header when the WINI.INI setting is set to 1 or 'on' in a
SEND command or driver string, otherwise a 100 will be stored in the DBF file header.
The SEND command causes the setting to be set for all files that use that driver, not just
for that file.
Examples:
WIN.INI:
;Sets all dBase3 files to store a 0 in the DBF file header
[CWDBASE3]
ZEROY2K=1
SEND command:
SEND('Orders', ZEROY2K='on' !sets Orders file to store 0 in the DBF file header
SEND('Orders', ZEROY2K='off' !sets Orders file to store 100 in the DBF file header
69
Database Drivers
CREATE Y
NAME Y
ENCRYPT N
OWNER(password) N
RECLAIM N1
PRE(prefix) Y
BINDABLE Y
THREAD Y12
EXTERNAL(member) Y
DLL([flag]) Y
OEM Y
LOCALE Y
INDEX Y
KEY Y
MEMO Y
BLOB N
RECORD Y
BINARY N
DUP Y2
NOCASE Y
OPT N
PRIMARY Y
70
Database Drivers and Interfaces
NAME Y
Ascending Components Y
Descending Components Y
Mixed Components N
DIM N
OVER Y
NAME Y
BOF(file) Y8
BUFFER(file) N
BUILD(file) Y
BUILD(key) Y
BUILD(index) Y
BUILD(index, components) Y3
BYTES(file) N
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) Y
DUPLICATE(key) Y
EMPTY(file) Y
EOF(file) Y8
FLUSH(file) Y
LOCK(file) N
NAME(label) Y
71
Database Drivers
PACK(file) Y
POINTER(file) Y9
POINTER(key) Y9
POSITION(file) Y10
POSITION(key) Y10
RECORDS(file) Y11
RECORDS(key) Y11
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) Y
UNLOCK(file) N
ADD(file) Y6
ADD(file, length) N
APPEND(file) Y6
APPEND(file, length) N
DELETE(file) Y1
GET(file,key) Y
GET(file, filepointer) Y
GET(key, keypointer) Y
HOLD(file) Y7
NEXT(file) Y
NOMEMO(file) Y
72
Database Drivers and Interfaces
PREVIOUS(file) Y
PUT(file) Y
PUT(file, filepointer) Y
RELEASE(file) Y
REGET(file,string) Y
REGET(key,string) Y
RESET(file,string) Y
RESET(key,string) Y
SET(file) Y
SET(file, key) Y
SET(file, filepointer) Y
SET(key) Y
SET(key, key) Y
SET(key, keypointer) Y
SKIP(file, count) Y
WATCH(file) Y
COMMIT N
ROLLBACK N
NULL(field) N
SETNULL(field) N
SETNULL(file,field) N
SETNONNULL(field) N
73
Database Drivers
Notes
1 When the driver deletes a record from a dBase III database, the record is not physically
removed, instead the driver marks it inactive. Memo fields are not physically removed
from the memo file, however they cannot be retrieved if they refer to an inactive record.
Key values are removed from the index files. To remove records and memo fields
permanently, execute a PACK(file).
To those programmers familiar with dBase III, this driver processes deleted
records consistent with the way dBase III processes them after the SET DELETED
ON command is issued. Records marked for deletion are ignored from processing
by executable code statements, but remain in the data file.
2 dBase III does not support any form of unique index. So the DUP attribute must be on all
keys.
3 When building dynamic indexes, the components may take one of two forms:
BUILD(DynNdx, '+Pre:FLD1, -Pre:FLD2')
This form specifies the names of the fields on which to build the index. The field names
must appear as specified in the fields' NAME() attribute if supplied, or must be the label
name. A prefix may be used for compatibility with Clarion conventions but is ignored.
BUILD(DynNdx, 'T[Expression]')
This form specifies the type and Expression used to build an index--see Miscellaneous--
Key Definition below.
4 These commands copy data and memo files using newfile, which may specify a new file
name or directory. Key or index files are copied if the newfile is a subdirectory
specification. To copy an index file to a new file, use a special form of the copy or rename
command:
COPY(file,'<index>|<newfile>')
This returns File Not Found if an invalid index is passed. The COPY command assumes
a default extension of ".NDX" for both the source and the target file names if none is
specified. If you require a file name without an extension, terminate the name with a
period. Given the file structure:
Clar2 FILE,CREATE,DRIVER('dBase3'),PRE(CL2)
NumKey KEY(+CL2:Num),DUP
StrKey KEY(+CL2:Str1)
StrKey2 KEY(+CL2:Str2)
AMemo MEMO(100), NAME('mem')
Record RECORD
Num STRING(@n-_9.2)
STR1 STRING(2)
STR2 STRING(2)
Mem STRING(10)
END
END
The following commands copy this file definition to A:
COPY(Clar2,'A:\CLAR2')
COPY(Clar2,'StrKey|A:\STRKEY')
COPY(Clar2,'StrKey2|A:\STRKEY2')
COPY(Clar2,'NumKey|A:\NUMKEY')
After these calls, the following files would exist on drive A: CLAR2.DBF, CLAR2.DBT,
STRKEY.NDX, STRKEY2.NDX, and NUMKEY.NDX.
74
Database Drivers and Interfaces
5 You do not need SHARE (or VSHARE) in any environment (for example, Novell) that
supplies file locking as part of the operating system.
6 The ADD statement tests for duplicate keys before modifying the data file or its
associated KEY files. Consequently it is slower than APPEND which performs no checks
and does not update KEYs. When adding large amounts of data to a database use
APPEND...BUILD in preference to ADD.
7 dBase III performs record locking by locking the entire record within the data file. This
prevents read access to other processes. Therefore we recommend minimizing the
amount of time for which a record is held.
8 Although the driver supports these functions, we do not recommend their use. They must
physically access the files and add overhead. Instead, test the value returned by
ERRORCODE() after each sequential access. NEXT or PREVIOUS post Error 33
(Record Not Available) if an attempt is made to access a record beyond the end or
beginning of the file.
9 There is no distinction between file pointers and key pointers; they both return the record
number for any given record.
10 POSITION(file) returns a STRING(12). POSITION(key) returns a STRING the size of the
key fields + 4 bytes.
11 Under dBase III, the RECORDS() function reports the same number of records for the
data file and its keys and indexes. Usually there will be no difference in the number of
records unless the INDEX is out of date. Because the DELETE statement does not
physically remove records, the number of records reported by the RECORDS() function
includes inactive records. Exercise care when using this function.
12 THREADed files consume additional file handles for each thread that accesses the file.
75
Database Drivers
dBaseIII:Other
Boolean Evaluation
dBase III allows a logical field to accept one of nine possible values (y,Y,n,N,t,T,f,F or a space
character). The space character is neither true nor false. When using a logical field from a
preexisting database in a logical expression, account for all these possibilities. Remember that
when a STRING field is used as an expression, it is true if it contains any data and false if it is
equal to zero or blank. Therefore, to evaluate a Logical field's truth, the expression should be true
if the field contains any of the "true" characters (T,t,Y, or y). For example, if a Logical field were
used to specify a product as taxable or nontaxable, the expression to evaluate its truth would be:
(If Condition):
Taxable='T' OR Taxable='t' OR Taxable='Y' OR Taxable='y'
Large MEMOs
dBase III supports MEMO fields up to a maximum of 64K. If you have an existing file which
includes a memo greater than 64K, you can use the file but not modify the large MEMOs.
You can determine when your application encounters a large MEMO by detecting when the
memo pointer variable is non-blank, but the memo appears to be blank. Error 47 (Bad Record
Declaration) is posted, and any modification to the MEMO field is ignored.
KEY Definitions
dBase III supports the use of expressions to define keys. Within the Dictionary Editor, you can
place the expression in the external name field in the Key Properties dialog. The general format
of the external name is :
'FileName=T[Expression]'
Where FileName represents the name of the index file (which can contain a path and file
extension), and T represents the type of the index. Valid types are: C = character, D = date, and
N = numeric. If the type is D or N then Expression can name only one field.
String expressions may use the '+' operator to concatenate multiple string arguments. Numeric
expressions use the '+' or '-' operators with their conventional meanings. The maximum length of
a dBase III expression is 250 characters.
The expression may refer to multiple fields in the record, and contain xBase functions. Square
brackets must enclose the expression. The currently supported functions appear below. If the
driver encounters an unsupported Xbase function in a preexisting file, it posts error 76 'Invalid
Index String' when the file is opened for keys and static indexes.
76
Database Drivers and Interfaces
77
Database Drivers
dBaseIV:Specifications
The dBase4 file driver is compatible with dBase IV. The default data file extension is *.DBF.
Keys and Indexes exist as separate files from the data file. Keys are dynamic--they automatically
update as the data file changes. Indexes are static--they do not automatically update, but instead
require the BUILD statement for updating. The default file extension for the index file is *.NDX.
dBase IV supports multiple index files, whose extension is *.MDX. The miscellaneous section
describes procedures for using .MDX files.
The driver stores records as fixed length. It stores memo fields in a separate file. The memo file
name takes the first eight characters of the File Label plus an extension of .DBT.
dBase IV was never as widely adopted as dBase III. Choose this driver only when you must
share data with an end-user using dBase IV.
dBaseIV:Data Types
The xBase file format stores all data as ASCII strings. You may either specify STRING types with
declared pictures for each field, or specify native Clarion types, which the driver converts
automatically.
dBase data type Clarion data type STRING w/ picture
Date DATE STRING(@D12)
*Numeric REAL STRING(@N-_p.d)
*Logical BYTE STRING(1)
Character STRING STRING
*Memo MEMO MEMO
If your application reads and writes to existing files, a pictured STRING will suffice. However, if
your application creates a dBase IV file, you may require additional information for these dBase
IV types:
* To create a Numeric field in the Data Dictionary, choose the REAL data type. In the
External Name field on the Attributes tab, specify
'NumericFieldName=N(Precision,DecimalPlaces)' where NumericFieldName is the name
of the field, Precision is the precision of the field and DecimalPlaces is the number of
decimal places. With a REAL data type, you cannot access the Character or Places fields
in the Field definition, you must specify those attributes with an expression in the External
Name Field on the Attributes tab.
For example, if you want to create a field called Number with nine significant digits and
two decimal places, enter 'Number=N(9,2) in the External Name field on the Attributes
tab of the Field properties in the Data Dictionary.
If you're hand coding a native Clarion data type, add the NAME attribute using the same
syntax.
If you're hand coding a STRING with picture, STRING(@N-_9.2), NAME('Number'),
where Number is the field name.
78
Database Drivers and Interfaces
* To create a Logical field, using the data dictionary, choose the BYTE data type. There are
no special steps; however, see the miscellaneous section for tips on reading the data
from the field.
If you're hand coding a STRING with picture, add the NAME attribute: STRING(1),
NAME('LogFld = L').
* To create a Date field, using the data dictionary, choose the DATE data type, rather than
LONG, which you usually use for the TopSpeed or Clarion file formats.
* MEMO field declarations require the a pointer field in the file's record structure. Declare
the pointer field as a STRING(10) or a LONG. This field will be stored in the .DBF file
containing the offset of the memo in the .DBT file. The MEMO declaration must have a
NAME() attribute naming the pointer field. An example file declaration follows:
Use the File Import Utility in the Clarion Dictionary Editor to define your files.
dBaseIV:File Specifications/Maximums
File Size: 2,000,000,000 bytes
Records per File: 1,000,000,000
Record Size: 4,000 bytes
Field Size
Character: 254 bytes
Date: 8 bytes
Logical: 1 byte
Numeric: 20 bytes including decimal point
Float: 20 bytes including decimal point
Memo: 64K (see note)
Fields per Record: 512
Field Name: 12 characters
Keys/Indexes per File:
.NDX: No Limit
.MDX 47 tags per .MDX files
Key Sizes
Character: 100 bytes
Numeric, Date: 8 bytes
Memo fields per File: Dependent on available memory
Open Files: Operating system dependent
79
Database Drivers
dBaseIV:Driver Strings
There are switches or "driver strings" you can set to control the way your application creates,
reads, and writes files with a specific driver. Driver strings are simply messages or parameters
that are sent to the file driver at run-time to control its behavior. See Common Driver Features--
Driver Strings for an overview of these runtime Database Driver switches and parameters.
Some driver strings have no effect after the file is open, so no SEND function syntax is
listed for those strings. However, the SEND function syntax to return the value of the
switch is listed for all driver strings.
The dBaseIV Driver supports the following Driver Strings:
BUFFERS
The default is three buffers of 1024 bytes each. Increasing the number of buffers will not
increase performance when a file is shared by multiple users.
RECOVER
DRIVER('DBASE4', '/RECOVER' )
[ Status" = ] SEND(file, 'RECOVER' )
Equivalent to the Xbase RECALL command, which recovers records marked for deletion. When
using the dBaseIV driver, the DELETE statement flags a record as "inactive." The driver does not
remove the record until the PACK command is executed.
RECOVER is evaluated each time you open the file if you add the driver string to the data
dictionary. When the driver recovers the records previously marked for deletion, you must
manually rebuild keys and indexes with the BUILD statement.
IGNORESTATUS
80
Database Drivers and Interfaces
DELETED
ZEROY2K
The driver will store 0 in the DBF file header when the WINI.INI setting is set to 1 or 'on' in a
SEND command or driver string, otherwise a 100 will be stored in the DBF file header.
The SEND command causes the setting to be set for all files that use that driver, not just
for that file.
Examples:
WIN.INI:
;Sets all dBase4 files to store a 0 in the DBF file header
[CWDBASE4]
ZEROY2K=1
SEND command:
SEND('Orders', ZEROY2K='on' !sets Orders file to store 0 in the DBF file header
SEND('Orders', ZEROY2K='off' !sets Orders file to store 100 in the DBF file header
Driver String:
Orders FILE, DRIVER('dbase4', '/ZEROY2K=on'),PRE(ORD) !SETS Orders file to store 0
81
Database Drivers
CREATE Y
NAME Y
ENCRYPT N
OWNER(password) N
RECLAIM N1
PRE(prefix) Y
BINDABLE Y
THREAD Y12
EXTERNAL(member) Y
DLL([flag]) Y
OEM Y
LOCALE Y
INDEX Y
KEY Y
MEMO Y
BLOB N
RECORD Y
BINARY N
DUP Y2
NOCASE Y
OPT N
PRIMARY Y
82
Database Drivers and Interfaces
NAME Y
Ascending Components Y
Descending Components Y
Mixed Components N
DIM N
OVER Y
NAME Y
BOF(file) Y8
BUFFER(file) N
BUILD(file) Y
BUILD(key) Y
BUILD(index) Y
BUILD(index, components) Y3
BYTES(file) N
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) Y
DUPLICATE(key) Y
EMPTY(file) Y
EOF(file) Y8
FLUSH(file) Y
LOCK(file) N
NAME(label) Y
83
Database Drivers
PACK(file) Y
POINTER(file) Y9
POINTER(key) Y9
POSITION(file) Y10
POSITION(key) Y10
RECORDS(file) Y11
RECORDS(key) Y11
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) Y
UNLOCK(file) N
ADD(file) Y6
ADD(file, length) N
APPEND(file) Y6
APPEND(file, length) N
DELETE(file) Y1
GET(file,key) Y
GET(file, filepointer) Y
GET(key, keypointer) Y
HOLD(file) Y7
NEXT(file) Y
NOMEMO(file) Y
84
Database Drivers and Interfaces
PREVIOUS(file) Y
PUT(file) Y
PUT(file, filepointer) Y
RELEASE(file) Y
REGET(file,string) Y
REGET(key,string) Y
RESET(file,string) Y
RESET(key,string) Y
SET(file) Y
SET(file, key) Y
SET(file, filepointer) Y
SET(key) Y
SET(key, key) Y
SET(key, keypointer) Y
SKIP(file, count) Y
WATCH(file) Y
COMMIT N
ROLLBACK N
NULL(field) N
SETNULL(field) N
SETNULL(file,field) N
SETNONNULL(field) N
85
Database Drivers
Notes
1 When the driver deletes a record from a dBase IV database, the record is not physically
removed, instead the driver marks it inactive. Memo fields are not physically removed
from the memo file, however they cannot be retrieved if they refer to an inactive record.
Key values are removed from the index files. To remove records and memo fields
permanently, execute a PACK(file).
To those programmers familiar with dBase IV, this driver processes deleted
records consistent with the way dBase IV processes them after the SET DELETED
ON command is issued. Records marked for deletion are ignored from processing
by executable code statements, but remain in the data file.
2 In dBase IV it is legal to enter multiple records with duplicates of the unique key
components. However, only the first of these records is indexed. So processing in key
order only shows this first record. If you delete a record, then enter a new record with the
same key value, the key file continues to point at the deleted record rather than the new
record. In this situation, the dBase IV file driver driver changes the key file to point at the
active record rather than the deleted record. This means that if you use a dBase IV
program to delete a unique record, then insert a duplicate of this record, the new record
is invisible when processing in key order until a pack is done. If you do the same process
in a Clarion program, the new record is visible when processing in key order.
3 When building dynamic indexes, the components may take one of two forms:
BUILD(DynNdx, '+Pre:FLD1, -Pre:FLD2')
This form specifies the names of the fields on which to build the index. The field names
must appear as specified in the fields' NAME() attribute if supplied, or must be the label
name. A prefix may be used for compatibility with Clarion conventions but is ignored.
BUILD(DynNdx, 'T[Expression]')
This form specifies the type and Expression used to build an index--see Miscellaneous--
Key Definition below.
4 These commands copy data and memo files using newfile, which may specify a new file
name or directory. Key or index files are copied if the newfile is a subdirectory
specification. To copy an index file to a new file, use a special form of the copy
command:
COPY(file,'<index>|<newfile>')
This returns File Not Found if an invalid index is passed. The COPY command assumes
a default extension of .NDX for both the source and the target file names if none is
specified. If you require a file name without an extension, terminate the name with a
period. Given the file structure:
Clar2 FILE,CREATE,DRIVER('dBase4'),PRE(CL2)
NumKey KEY(+CL2:Num),DUP
StrKey KEY(+CL2:Str1)
StrKey2 KEY(+CL2:Str2)
AMemo MEMO(100), NAME('mem')
Record RECORD
Num STRING(@n-_9.2)
STR1 STRING(2)
STR2 STRING(2)
Mem STRING(10)
END
END
The following commands copy this file definition to A:
86
Database Drivers and Interfaces
COPY(Clar2,'A:\CLAR2')
COPY(Clar2,'StrKey|A:\STRKEY')
COPY(Clar2,'StrKey2|A:\STRKEY2')
COPY(Clar2,'NumKey|A:\NUMKEY')
After these calls, the following files would exist on drive A: CLAR2.DBF, CLAR2.DBT,
STRKEY.NDX, STRKEY2.NDX, and NUMKEY.NDX.
5 You do not need SHARE (or VSHARE) in any environment (for example, Novell) that
supplies file locking as part of the operating system.
6 The ADD statement tests for duplicate keys before modifying the data file or its
associated KEY files. Consequently it is slower than APPEND which performs no checks
and does not update KEYs. When adding large amounts of data to a database use
APPEND...BUILD in preference to ADD.
7 dBase IV performs record locking by locking the entire record within the data file. This
prevents read access to other processes. Therefore we recommend minimizing the
amount of time for which a record is held.
8 Although the driver supports these functions, we do not recommend their use. They must
physically access the files and add overhead. Instead, test the value returned by
ERRORCODE() after each sequential access. NEXT or PREVIOUS post Error 33
(Record Not Available) if an attempt is made to access a record beyond the end or
beginning of the file.
9 There is no distinction between file pointers and key pointers; they both return the record
number for any given record.
10 POSITION(file) returns a STRING(12). POSITION(key) returns a STRING containing the
size of the key fields + 4 bytes.
11 Under dBase IV, the RECORDS() function reports the same number of records for the
data file and its keys and indexes. Usually there will be no difference in the number of
records unless the INDEX is out of date. Because the DELETE statement does not
physically remove records, the number of records reported by the RECORDS() function
includes inactive records. Exercise care when using this function.The field names must
appear as specified in the fields' NAME() attribute if supplied, or must be the label name.
A prefix may be used for compatibility with the Clarion conventions but is ignored.
12 THREADed files consume additional file handles for each thread that accesses the file.
87
Database Drivers
dBaseIV:Other
International Sort Sequence
dBase IV sorts as if there were no diacritics in a field, thus A is sorted the same as Ä. If two words
are identical except for diacritic characters, then the words are sorted as though the diacritic
character was greater than the normal character. For example Äa < Ab < Äb whereas a
CLADIGRAPH of ÄAE will sort as Ab < Äa < Äb. Solution- if the same file is used in Clarion and
dBase IV, issue a BUILD statement rebuild the keys before updating the file (reading the file
causes no problems).
Boolean Evaluation
dBase IV allows a logical field to accept one of 11 possible values (1,0,y,Y,n,N,t,T,f,F or a space
character). The space character is neither true nor false. When using a logical field from a
preexisting database in a logical expression, account for all these possibilities. Remember that
when a STRING field is used as an expression, it is true if it contains any data and false if it is
equal to zero or blank. Therefore, to evaluate a Logical field's truth, the expression should be true
if the field contains any of the "true" characters (T,t,Y, or y). For example, if a Logical field were
used to specify a product as taxable or nontaxable, the expression to evaluate its truth would be:
(If Condition):
Taxable='1' OR Taxable='T' OR Taxable='t' OR Taxable='Y' OR Taxable='y'
Large MEMOs
Clarion supports MEMO fields up to a maximum of 64K. If you have an existing file which
includes a memo greater than 64K, you can use the file but not modify the large MEMOs.
You can determine when your application encounters a large MEMO by detecting when the
memo pointer variable is non-blank, but the memo appears to be blank. Error 47 (Bad Record
Declaration) is posted, and any modification to the MEMO field is ignored.
Key Definition
dBase IV supports the use of expressions to define keys. Within the Dictionary Editor, you can
place the expression in the external name field in the Key Properties dialog. The general format
of the external name is :
'FileName=T[Expression]'
Where FileName represents the name of the index file (which can contain a path and file
extension), and T represents the type of the index. Valid types are: C = character, D = date, and
N = numeric. If the type is D or N then Expression can name only one field.
Multiple-index (.MDX) files require the NAME() attribute on a KEY or INDEX to specify the
storage type of the key and any expression used to generate the key values. The general format
of the NAME() attribute on a KEY or INDEX is:
NAME('TagName|FileName[PageSize]=T[Expression],FOR[Expression]')
88
Database Drivers and Interfaces
TagName Specifies the name of an index tag within a multiple index file. If omitted
the driver creates a dBase IV style .NDX file using the name specified in
FileName.
FileName Specifies the name of the index file, which may contain a path and
extension.
PageSize Specifies that when creating a .MDX file, (if a TagName is specified), a
number in the range 2-32 specifying the number of 512-byte blocks in
each index page. This value is only used when creating the file. If you
specify multiple values with declarations for different tags in the same
.MDX file, the largest value will be selected. The default value is 2.
Elements of the NAME() attribute may be omitted from the right. When specifying an
Expression, you must also specify the type and name. If the Expression is omitted, the
driver determines the Expression from the key fields when the file is created, or from the
index file when opened.
If the type is omitted, the driver determines the index type from the first key component
when the file is created, or from the index file when opened.
If the NAME() attribute is omitted altogether, the index file name is determined from the
key label. The path defaults to the same location as the .DBF.
Tag names are limited to 9 characters in length. If the supplied name is too long it is
automatically truncated.
Specify all field names in the NAME() attribute without a prefix.
dBase IV additionally supports the use of the Xbase FOR statement in expressions to define
keys. The expressions supported in the FOR condition must be a simple condition of the form:
expression comparison_op expression
comparison_op may be <, <=, =<, <>, =, =>, >= or >.
The expression may refer to multiple fields in the record and contain xBase functions.
Square brackets must enclose the expression. The currently supported functions appear
below. If the driver encounters an unsupported Xbase function in a preexisting file, it
posts error 76 'Invalid Index String' when the file is opened for keys and static indexes.
String expressions may use the '+' operator to concatenate multiple string arguments.
Numeric expressions use the '+' or '-' operators with their conventional meanings. The
maximum length of a dBase IV expression is 250 characters.
89
Database Drivers
90
Database Drivers and Interfaces
91
Database Drivers
DOS:Specifications
The DOS file driver reads and writes any binary, byte-addressable files. Neither fields nor records
are delimited. When reading a record, the driver reads the number of bytes defined in the file's
RECORD structure, unless a length parameter is specified in the GET statement.
The DOS driver supports the length parameter for the ADD, APPEND, GET, and PUT
statements; this allows for variable length records in a DOS file.
The POINTER function returns the relative byte position within the file of the beginning of the last
record accessed by an ADD, APPEND, GET, or NEXT statement.
This file driver performs forward sequential processing only. No key or transaction processing
functions are supported, and the PREVIOUS statement is not supported.
Due to its limitations, the main function of this driver is as a disk editor for binary files.
DOS:Data Types
BYTE DECIMAL
SHORT PDECIMAL
USHORT STRING
LONG CSTRING
ULONG PSTRING
SREAL DATE
REAL TIME
BFLOAT4 GROUP
BFLOAT8
DOS:File Specifications/Maximums
File Size: 4,294,967,295
Records per File: 4,294,967,295
Record Size: 64K
Field Size: 64K
Fields per Record: 64K
Keys/Indexes per File:n/a
Key Size: n/a
Memo fields per File: n/a
Memo Field Size: n/a
Open Data Files: Operating system dependent
92
Database Drivers and Interfaces
DOS:Driver Strings
There are switches or "driver strings" you can set to control the way your application creates,
reads, and writes files with a specific driver. Driver strings are simply messages or parameters
that are sent to the file driver at run-time to control its behavior. See Common Driver Features--
Driver Strings for an overview of these runtime Database Driver switches and parameters.
Some driver strings have no effect after the file is open, so no SEND function syntax is
listed for those strings. However, the SEND function syntax to return the value of the
switch is listed for all driver strings.
The DOS Driver supports the following Driver Strings:
FILEBUFFERS
The default buffer size for files opened denying write access to other users is the larger of
1024 or (2 * record size), and the larger of 512 or record size for all other open modes.
QUICKSCAN
93
Database Drivers
CREATE Y
NAME Y
ENCRYPT N
OWNER(password) N
RECLAIM N
PRE(prefix) Y
BINDABLE Y
THREAD Y4
EXTERNAL(member) Y
DLL([flag]) Y
OEM Y
LOCALE Y
INDEX N
KEY N
MEMO N
BLOB N
RECORD Y
BINARY N
DUP N
NOCASE N
OPT N
PRIMARY N
94
Database Drivers and Interfaces
NAME N
Ascending Components N
Descending Components N
Mixed Components N
DIM Y
OVER Y
NAME Y
BOF(file) N
BUFFER(file) N
BUILD(file) N
BUILD(key) N
BUILD(index) N
BUILD(index, components) N
BYTES(file) Y
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) N
DUPLICATE(key) N
EMPTY(file) Y
EOF(file) Y
FLUSH(file) Y
LOCK(file) Y
NAME(label) Y
95
Database Drivers
PACK(file) N
POINTER(file) Y2
POINTER(key) N
POSITION(file) Y3
POSITION(key) N
RECORDS(file) Y
RECORDS(key) N
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) N
UNLOCK(file) Y
ADD(file) Y
ADD(file, length) Y
APPEND(file) Y
APPEND(file, length) Y
DELETE(file) N
GET(file,key) N
GET(file, filepointer) Y
GET(key, keypointer) N
HOLD(file) N
NEXT(file) Y
NOMEMO(file) N
96
Database Drivers and Interfaces
PREVIOUS(file) Y
PUT(file) Y
PUT(file, filepointer) Y1
RELEASE(file) N
REGET(file,string) Y
REGET(key,string) N
RESET(file,string) Y
RESET(key,string) N
SET(file) Y
SET(file, key) N
SET(file, filepointer) Y
SET(key) N
SET(key, key) N
SET(key, keypointer) N
SKIP(file, count) N
WATCH(file) N
COMMIT N
ROLLBACK N
NULL(field) N
SETNULL(field) N
SETNULL(file,field) N
SETNONNULL(field) N
97
Database Drivers
Notes
1 When using PUT() with this driver you should take care to PUT back the same number of
characters that were read. If you PUT back more characters than were read, then the
"extra" characters will overwrite the first part of the subsequent record. If you PUT back
fewer characters than were read, then only the first part of the retrieved record is
overwritten, while the last part of the retrieved record remains as it was prior to the PUT().
2 POINTER() returns the relative byte position within the file.
3 POSITION(file) returns a STRING(4).
4 THREADed files consume additional file handles for each thread that accesses the file.
98
Database Drivers and Interfaces
99
Database Drivers
FoxPro:Specifications
The FoxPro file driver is compatible with FoxPro and FoxBase. The default data file extension is *.DBF.
The default index file extension is *.IDX. The default Memo file extension is .FBT. FoxPro also
supports multiple index files, whose default extension is *.CDX. The miscellaneous section
describes the procedures for using the .CDX files.
The FoxPro index file format is the backbone of its vaunted "Rushmore" technology. The
old saying "There's no free lunch," however, applies. Adding and appending records to a
large database is a slower process than in other xBase formats, due to the time required to
update the index file.
FoxPro:Data Types
The xBase file format stores all data as ASCII strings. You may either specify STRING types with
declared pictures for each field, or specify native Clarion types, which the driver converts
automatically.
FoxPro data type Clarion data type STRING w/ picture
*Date DATE STRING(@D12)
*Numeric REAL STRING(@N-_p.d)
*Logical BYTE STRING(1)
Character STRING STRING
*Memo MEMO MEMO
If your application reads and writes to existing files, a pictured STRING will suffice. However, if
your application creates a FoxPro or FoxBase file, you may require additional information for
these FoxPro and FoxBase types:
* To create a numeric field in the Data Dictionary, choose the REAL data type. In the
External Name field on the Attributes tab, specify
'NumericFieldName=N(Precision,DecimalPlaces)' where NumericFieldName is the name
of the field, Precision is the precision of the field and DecimalPlaces is the number of
decimal places. With a REAL data type, you cannot access the Character or Places fields
in the Field definition, you must specify those attributes with an expression in the External
Name Field on the Attributes tab.
For example, if you want to create a field called Number with nine significant digits and
two decimal places, enter 'Number=N(9,2) in the External Name field on the Attributes
tab of the Field properties in the Data Dictionary.
If you're hand coding a native Clarion data type, add the NAME attribute using the same
syntax.
If you're hand coding a STRING with picture, STRING(@N-_9.2), NAME('Number'),
where Number is the field name.
100
Database Drivers and Interfaces
* To create a logical field, using the data dictionary, choose the BYTE data type. There are
no special steps; however, see the miscellaneous section for tips on reading the data
from the field.
If you're hand coding a STRING with picture, add the NAME attribute: STRING(1),
NAME('LogFld = L').
* To create a date field, using the data dictionary, choose the DATE data type, rather than
LONG, which you usually use for the TopSpeed or Clarion file formats.
* MEMO field declarations require the a pointer field in the file's record structure. Declare
the pointer field as a STRING(10) or a LONG. This field will be stored in the .DBF file
containing the offset of the memo in the .DBT file. The MEMO declaration must have a
NAME() attribute naming the pointer field. An example file declaration follows:
File FILE, DRIVER('FoxPro')
Memo1 MEMO(200),NAME('Notes')
Memo2 MEMO(200),NAME('Text')
Rec RECORD
Mem1Ptr LONG,NAME('Notes')
Mem2Ptr STRING(10),NAME('Text')
END
END
FoxPro:File Specifications/Maximums
File Size: 2,000,000,000 bytes
Records per File: 1,000,000,000 bytes
Record Size: 4,000 bytes
Field Size
Character: 254 bytes
Date: 8 bytes
Logical: 1 byte
Numeric: 20 bytes including decimal point
Float: 20 bytes including decimal point
Memo: 65,520 bytes (see note)
Fields per Record: 512
Field Name: 10 characters
Keys/Indexes per File: No Limit
Key Sizes
Character: 100 bytes (.IDX)
254 bytes (.CDX)
Numeric, Date: 8 bytes
Memo fields per File: Dependent on available memory
Open Files: Operating system dependent
101
Database Drivers
FoxPro:Driver Strings
There are switches or "driver strings" you can set to control the way your application creates,
reads, and writes files with a specific driver. Driver strings are simply messages or parameters
that are sent to the file driver at run-time to control its behavior. See Common Driver Features--
Driver Strings for an overview of these runtime Database Driver switches and parameters.
Some driver strings have no effect after the file is open, so no SEND function syntax is
listed for those strings. However, the SEND function syntax to return the value of the
switch is listed for all driver strings.
The FoxPro Driver supports the following Driver Strings:
BUFFERS
The default is three buffers of 1024 bytes each. Increasing the number of buffers will not
increase performance when a file is shared by multiple users.
RECOVER
DRIVER('FOXPRO', '/RECOVER' )
[ Status" = ] SEND(file, 'RECOVER' )
Equivalent to the Xbase RECALL command, which recovers records marked for deletion. When
using the FoxPro driver, the DELETE statement flags a record as "inactive." The driver does not
remove the record until the PACK command is executed.
RECOVER is evaluated each time you open the file if you add the driver string to the data
dictionary. When the driver recovers the records previously marked for deletion, you must
manually rebuild keys and indexes with the BUILD statement.
IGNORESTATUS
102
Database Drivers and Interfaces
DELETED
ZEROY2K
The driver will store 0 in the DBF file header when the WINI.INI setting is set to 1 or 'on' in a
SEND command or driver string, otherwise a 100 will be stored in the DBF file header.
The SEND command causes the setting to be set for all files that use that driver, not just
for that file.
Example:
WIN.INI:
;Sets all FoxPro files to store a 0 in the DBF file header
[CWFOXPRO]
ZEROY2K=1
SEND command:
!sets Orders file to store 0 in the DBF file header:
SEND('Orders', ZEROY2K='on' )
!sets Orders file to store 100 in the DBF file header:
SEND('Orders', ZEROY2K='off')
Driver String:
!SETS Orders file to store 0
Orders FILE, DRIVER('FOXPRO', '/ZEROY2K=on'),PRE(ORD)
103
Database Drivers
CREATE Y
NAME Y
ENCRYPT N
OWNER(password) N
RECLAIM N1
PRE(prefix) Y
BINDABLE Y
THREAD Y13
EXTERNAL(member) Y
DLL([flag]) Y
OEM N2
LOCALE Y
INDEX Y
KEY Y
MEMO Y
BLOB N
RECORD Y
BINARY N14
DUP Y3
NOCASE Y
OPT N
PRIMARY Y
104
Database Drivers and Interfaces
NAME Y
Ascending Components Y
Descending Components Y
Mixed Components N
DIM N
OVER Y
NAME Y
BOF(file) Y9
BUFFER(file) N
BUILD(file) Y
BUILD(key) Y
BUILD(index) Y
BUILD(index, components) Y4
BYTES(file) N
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) Y
DUPLICATE(key) Y
EMPTY(file) Y
EOF(file) Y9
FLUSH(file) Y
LOCK(file) N
NAME(label) Y
105
Database Drivers
PACK(file) Y
POINTER(file) Y10
POINTER(key) Y10
POSITION(file) Y11
POSITION(key) Y11
RECORDS(file) Y12
RECORDS(key) Y12
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) Y
UNLOCK(file) Y
ADD(file) Y7
ADD(file, length) N
APPEND(file) Y7
APPEND(file, length) N
DELETE(file) Y1
GET(file,key) Y
GET(file, filepointer) Y
GET(key, keypointer) Y
HOLD(file) Y8
NEXT(file) Y
NOMEMO(file) Y
106
Database Drivers and Interfaces
PREVIOUS(file) Y
PUT(file) Y
PUT(file, filepointer) Y
RELEASE(file) Y
REGET(file,string) Y
REGET(key,string) Y
RESET(file,string) Y
RESET(key,string) Y
SET(file) Y
SET(file, key) Y
SET(file, filepointer) Y
SET(key) Y
SET(key, key) Y
SET(key, keypointer) Y
SKIP(file, count) Y
WATCH(file) Y
COMMIT N
ROLLBACK N
NULL(field) N
SETNULL(field) N
SETNULL(file,field) N
SETNONNULL(field) N
107
Database Drivers
Notes:
1 When the driver deletes a record from a FoxPro database, the record is not physically
removed, instead the driver marks it inactive. Memo fields are not physically removed
from the memo file, however they cannot be retrieved if they refer to an inactive record.
Key values are removed from the index files. To remove records and memo fields
permanently, execute a PACK(file).
To those programmers familiar with FoxPro, this driver processes deleted records
consistent with the way FoxPro processes them after the SET DELETED ON
command is issued. Records marked for deletion are ignored from processing by
executable code statements, but remain in the data file.
2 If you need to access FoxPro data with alternate characters stored using a non-English
version of FoxPro, then you should use ODBC. However, if you do not have any string
based kesys, you can use the FoxPro driver and call the ConvertOEMToANSI and
ConvertANSIToOEM after retrieving and before updating a record.
3 In FoxPro it is legal to enter multiple records with duplicates of the unique key
components. However, only the first of these records is indexed. So processing in key
order only shows this first record. If you delete a record, then enter a new record with the
same key value, the key file continues to point at the deleted record rather than the new
record. In this situation, the FoxPro file driver changes the key file to point at the active
record rather than the deleted record. This means that if you use a FoxPro program to
delete a unique record, then insert a duplicate of this record, the new record is invisible
when processing in key order until a pack is done. If you do the same process in a
Clarion program, the new record is visible when processing in key order.
4 When building dynamic indexes, the components may take one of two forms:
BUILD(DynNdx, '+Pre:FLD1, -Pre:FLD2')
This form specifies the names of the fields on which to build the index. The field names
must appear as specified in the fields' NAME() attribute if supplied, or must be the label
name. A prefix may be used for compatibility with Clarion conventions but is ignored.
BUILD(DynNdx, 'T[Expression]')
This form specifies the type and Expression used to build an index--see Miscellaneous--
Key Definition for more information.
5 These commands copy data and memo files using newfile, which may specify a new file
name or directory. Key or index files are copied if the newfile is a subdirectory
specification. To copy an index file to a new file, use a special form of the copy
command:
COPY(file,'<index>|<newfile>')
This returns File Not Found if an invalid index is passed. The COPY command assumes
a default extension of .IDX for both the source and the target file names if none is
specified. If you require a file name without an extension, terminate the name with a
period. Given the file structure:
Clar2 FILE,CREATE,DRIVER('FoxPro'),PRE(CL2)
NumKey KEY(+CL2:Num),DUP
StrKey KEY(+CL2:Str1)
StrKey2 KEY(+CL2:Str2)
AMemo MEMO(100), NAME('mem')
Record RECORD
Num STRING(@n-_9.2)
STR1 STRING(2)
108
Database Drivers and Interfaces
STR2 STRING(2)
Mem STRING(10)
END
END
The following commands copy this file definition to A:
COPY(Clar2,'A:\CLAR2')
COPY(Clar2,'StrKey|A:\STRKEY')
COPY(Clar2,'StrKey2|A:\STRKEY2')
COPY(Clar2,'NumKey|A:\NUMKEY')
After these calls, the following files would exist on drive A: CLAR2.DBF, CLAR2.FPT,
STRKEY.IDX, STRKEY2.IDX, and NUMKEY.IDX.
6 You do not need SHARE (or VSHARE) in any environment (for example, Novell) that
supplies file locking as part of the operating system.
7 The ADD statement tests for duplicate keys before modifying the data file or its
associated KEY files. Consequently it is slower than APPEND which performs no checks
and does not update KEYs. When adding large amounts of data to a database use
APPEND...BUILD in preference to ADD.
8 FoxPro performs record locking by locking the entire record within the data file. This
prevents read access to other processes. Therefore we recommend minimizing the
amount of time for which a record is held.
9 Although the driver supports these functions, we do not recommend their use. They must
physically access the files and they are slow. Instead, test the value returned by
ERRORCODE() after each sequential access. NEXT or PREVIOUS post Error 33
(Record Not Available) if an attempt is made to access a record beyond the end or
beginning of the file.
10 There is no distinction between file pointers and key pointers; they both return the record
number for the given record.
11 POSITION(file) returns a STRING(12). POSITION(key) returns a STRING the size of the
key fields + 4 bytes.
12 Under FoxPro, the RECORDS() function reports the same number of records for the data
file and its keys and indexes. Usually there will be no difference in the number of records
unless the INDEX is out of date. Because the DELETE statement does not physically
remove records, the number of records reported by the RECORDS() function includes
inactive records. Exercise care when using this function.The field names must appear as
specified in the fields' NAME() attribute if supplied, or must be the label name. A prefix
may be used for compatibility with the Clarion conventions but is ignored.
13 THREADed files consume additional file handles for each thread that accesses the file.
14 OEM conversion is not applied to BINARY MEMOs. The driver assumes BINARY MEMOs
are zero padded; otherwise, space padded.
109
Database Drivers
FoxPro:Other
Boolean Evaluation
FoxPro and FoxBase allow a logical field to accept one of 11 possible values (0,1,y,Y,n,N,t,T,f,F
or a space character). The space character is neither true nor false. When using a logical field
from a preexisting database in a logical expression, account for all these possibilities. Remember
that when a STRING field is used as an expression, it is true if it contains any data and false if it
is equal to zero or blank. Therefore, to evaluate a Logical field's truth, the expression should be
true if the field contains any of the "true" characters (1,T,t,Y, or y). For example, if a Logical field
were used to specify a product as taxable or nontaxable, the expression to evaluate its truth
would be:
(If Condition):
Taxable='1' OR Taxable='T' OR Taxable='t' OR Taxable='Y' OR Taxable='y'
Large MEMOs
FoxPro supports MEMO fields up to a maximum of 64K. If you have an existing file which
includes a memo greater than 64K, you can use the file but not modify the large MEMOs.
You can determine when your application encounters a large MEMO by detecting when the
memo pointer variable is non-blank, but the memo appears to be blank. Error 47 (Bad Record
Declaration) is posted, and any modification to the MEMO field is ignored.
Key Definition
FoxPro and FoxBase support the use of expressions to define keys. Within the Dictionary
Editor, you can place the expression in the external name field in the Key Properties
dialog. The general format of the external name is :
'FileName=T[Expression]'
Where FileName represents the name of the index file (which can contain a path and file
extension), and T represents the type of the index. Valid types are: C = character, D =
date, and N = numeric. If the type is D or N then Expression can name only one field.
Multiple-index (.CDX) files require the NAME() attribute on a KEY or INDEX to specify the
storage type of the key and any expression used to generate the key values. The general
format of the NAME() attribute on a KEY or INDEX is:
NAME('TagName|FileName=T[Expression],COMPRESSED')
The following are the parameters for the NAME() attribute:
TagName Names an index tag within a multiple index file. If the TagName is
omitted the driver creates an .IDX file with the name specified in
FileName.
110
Database Drivers and Interfaces
FileName Names the index file, and optionally contains a path and
extension.
Elements of the NAME() attribute may be omitted from the right. When specifying an
Expression, the type and name must also be specified. If the Expression is omitted, the
driver determines the Expression from the key fields when the file is created, or from the
index file when opened.
If the type is omitted, the driver determines the index type from the first key component
when the file is created, or from the index file when opened.
If the NAME() attribute is omitted altogether, the index file name is determined from the
key label. The path defaults to the same location as the .DBF.
Tag names are limited to 10 characters in length; if the supplied name is too long it is
automatically truncated.
All field names in the NAME() attribute must be specified without a prefix.
FoxPro additionally supports the use of the Xbase FOR statement in expressions to
define keys. The expressions supported in the FOR condition must be a simple condition
of the form:
expression comparison_op expression
comparison_op may be one of the following: <, <=, =<, <>, =, =>, >= or >.
The expression may refer to multiple fields in the record, and contain xBase functions.
Square brackets must enclose the expression. The currently supported functions appear
below. If the driver encounters an unsupported Xbase function in a preexisting file, it
posts error 76 'Invalid Index String' when the file is opened for keys and static indexes.
String expressions may use the '+' operator to concatenate multiple string arguments.
Numeric expressions use the '+' or '-' operators with their conventional meanings. The
maximum length of a FoxPro or FoxBase expression is 250 characters.
111
Database Drivers
112
Database Drivers and Interfaces
113
Database Drivers
The TopSpeed Database file system is a high-performance, high-security, proprietary file driver
for Clarion development tools. It is not file compatible with the Clarion file driver's data.
Data tables, keys, indexes and memos can all be stored together in a single DOS file. The default
file extension is *.TPS. A separate "Transaction Control File" uses the *.TCF extension by default.
The TopSpeed driver can optionally store multiple tables in a single file. This lets you open as
many data tables, keys, and indexes as necessary using a single DOS file handle. This feature
may be especially useful when there are a large number of small tables, or when a group of
related files are normally accessed together. All keys, indexes, and memos are stored internally.
When multiple tables share a single DOS handle, the first OPEN mode applies to all the
tables within the file.
In addition, the TopSpeed file system supports the BLOB data type (Binary Large OBject), a field
which is completely variable-length and may be greater than 64K in size. A BLOB must be
declared before the RECORD structure. Memory for a BLOB is dynamically allocated and de-
allocated as necessary. For more information, see BLOB in the Language Reference.
This driver offers speed, security, and takes up fewer resources on the end user's system.
114
Database Drivers and Interfaces
TopSpeed:Specifications
Data Types
BYTE SHORT USHORT LONG ULONG SREAL DECIMAL REAL
STRING CSTRING PSTRING MEMO GROUP BLOB DATE TIME
File Maximums/Specifications
File Size : 2 GB
Records per File : Unsigned Long (4,294,967,295)
Record Size : 15,000 bytes
Field Size : 15,000 bytes
Fields per Record : 15,000
Keys/Indexes per File: 240
Key Size : 15,000 bytes
Memo fields per File: 255
Memo Field Size : 64,000 bytes
BLOB fields per File: 255
BLOB Size : Hardware dependent (Max size 640 MB)
Open Data Files : Operating system dependent
Table Name : 1,000 bytes
Tables per DOS File : Limited only by the maximum DOS f
ile size--
approximately 2^32 bytes (4,294,9
67,296).
Concurrent Users per File: 1024
115
Database Drivers
The TopSpeed driver has a built-in encryption system. However, the encryption algorithm is
proprietary and this makes the TopSpeed file format unavailable to some developers who have to
guarantee the encryption algorithm. Available starting with Clarion 7.0, you have the option to
use any encryption algorithm supported by any encryption provider that plugs into the Windows
encryption subsystem. This will enable developers to create, store and exchange data in a very
secure environment.
There are two providers that are installed on all Windows Operating Systems: Microsoft Base
Cryptographic Provider and Microsoft Enhanced Cryptographic Provider.
The Microsoft Enhanced Cryptographic Provider supports the same capabilities as the Microsoft
Base Cryptographic Provider, but provides for stronger security through longer keys and
additional algorithms. The Enhanced provider is installed on your machine when you apply the
Internet Explorer 128-bit security patch.
In addition, you now have the ability to use any encryption algorithm supported by any
encryption provider that plugs into the Windows encryption subsystem. So you can now
even use new encryption providers as they become available!
To enable use of an alternative encryption algorithm you just supply at least one of the following
encryption settings to the driver via the driver string:
Example Format:
(DriverString = Default Value)
/PROVIDER= PROV_RSA_FULL 1
116
Database Drivers and Interfaces
Additional Notes:
(1) You can use any of the driver string switches in a SEND command before the file is open to
set the encryption algorithm. You can also retrieve the current value of any of the encryption
options as the return result of the SEND command.
(2) /CONTAINER is the key container name. This is a string that identifies the key container to
the CSP (cryptographic service provider). This name is independent of the method used to store
the keys. Some CSPs store their key containers internally (in hardware), some use the system
registry, and others use the file system.
When /CONTAINER is not specified, a default key container name is used. For example, the
Microsoft Base Cryptographic Provider uses the logon name of the currently logged on user as
the key container name. Other CSPs can also have default key containers that can be acquired in
this way.
(3) This is the value associated with the different provider types. See the Microsoft Cryptographic
Provider Types page for full details on provider types. The values of the different provider types
supplied by the Microsoft Enhanced Cryptographic Provider (MECP) are:
PROV_RSA_FULL 1
PROV_RSA_SIG 2
PROV_DSS 3
PROV_FORTEZZA 4
PROV_MS_EXCHANGE 5
PROV_SSL 6
PROV_RSA_SCHANNEL 12
PROV_DSS_DH 13
PROV_EC_ECDSA_SIG 14
PROV_EC_ECNRA_SIG 15
PROV_EC_ECDSA_FULL 16
PROV_EC_ECNRA_FULL 17
PROV_DH_SCHANNEL 18
PROV_SPYRUS_LYNKS 20
PROV_RNG 21
PROV_INTEL_SEC 22
PROV_REPLACE_OWF 23
PROV_RSA_AES 24
117
Database Drivers
TopSpeed:Driver Strings
There are switches or "driver strings" you can set to control the way your application creates,
reads, and writes files with a specific driver. Driver strings are simply messages or parameters
that are sent to the file driver at run-time to control its behavior. See Common Driver Features--
Driver Strings for an overview of these runtime Database Driver switches and parameters.
Some driver strings have no effect after the file is open, so no SEND function syntax is
listed for those strings. However, the SEND function syntax to return the value of the
switch is listed for all driver strings.
The TopSpeed Driver supports the following Driver Strings:
DECIMALCheck
This switch should be used as a driver string, or, in a SEND command before the file is opened.
FLAGS
TPSREADONLY EQUATE(1)
For example, the following code makes the file read-only for ODBC access while preserving any
other flags:
TpsFlags = SEND(MyFile, 'FLAGS')
SEND(MyFile, 'FLAGS ='&BOR(TpsFlags,TPSREADONLY)
FULLBUILD
118
Database Drivers and Interfaces
PNM=
TCF
We recommend using one transaction control file for a system. Using multiple files with
different access rights can result in partially committed transactions-- some of the files
within a transaction might be updated and others left unchanged.
See Also: Transaction Control Files
119
Database Drivers
CREATE Y
NAME Y
ENCRYPT Y
OWNER(password) Y1
RECLAIM N2
PRE(prefix) Y
BINDABLE Y
THREAD Y12
EXTERNAL(member) Y
DLL([flag]) Y
OEM Y
LOCALE Y
INDEX Y
KEY Y
MEMO Y3
BLOB Y15
RECORD Y
BINARY Y13
DUP Y
NOCASE Y
OPT Y
PRIMARY Y
120
Database Drivers and Interfaces
NAME Y4
Ascending Components Y
Descending Components Y
Mixed Components Y
DIM Y
OVER Y
NAME Y
BOF(file) Y
BUFFER(file) N
BUILD(file) Y
BUILD(key) Y
BUILD(index) Y
BUILD(index, components) Y
BYTES(file) Y
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) Y
DUPLICATE(key) Y
EMPTY(file) Y
EOF(file) Y
FLUSH(file) Y
LOCK(file) Y5
NAME(label) Y
121
Database Drivers
PACK(file) Y6
POINTER(file) Y8
POINTER(key) Y8
POSITION(file) Y9
POSITION(key) Y9
RECORDS(file) Y
RECORDS(key) Y
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) Y7
UNLOCK(file) Y
ADD(file) Y
ADD(file, length) N
APPEND(file) Y
APPEND(file, length) N
DELETE(file) Y2
GET(file,key) Y
GET(file, filepointer) Y8
GET(key, keypointer) Y
HOLD(file) Y
NEXT(file) Y
NOMEMO(file) Y
122
Database Drivers and Interfaces
PREVIOUS(file) Y
PUT(file) Y
PUT(file, filepointer) Y
RELEASE(file) Y
REGET(file,string) Y
REGET(key,string) Y
RESET(file,string) Y
RESET(key,string) Y
SET(file) Y
SET(file, key) Y
SET(file, filepointer) Y
SET(key) Y
SET(key, key) Y
SET(key, keypointer) Y
SKIP(file, count) Y
WATCH(file) Y
COMMIT Y
ROLLBACK Y
NULL(field) N
SETNULL(field) N
SETNULL(file,field) N
SETNONNULL(field) N
123
Database Drivers
Notes
1 We recommend using a variable password that is lengthy and contains special characters
because this more effectively hides the password value from anyone looking for it. For
example, a password like "dd....#$...*&" is much more difficult to "find" than a password
like "SALARY."
To specify a variable instead of the actual password in the Owner Name field of the
File Properties dialog, type an exclamation point (!) followed by the variable name.
For example: !MyPassword.
2 The TopSpeed driver automatically reclaims space freed by deleted records and keys.
3 The TopSpeed file system uses the same compression algorithm for RECORDs and
MEMOs. For data of 255 bytes or less, MEMOs have no disk space advantage over
STRINGs. However, STRINGs are always allocated space (RAM) within the record
buffer, whereas MEMOs are only allocated space when the file is OPENed. MEMOs do
carry the advantage of BINARY versus NONBINARY, plus MEMOs may be omitted from
all processing with the NOMEMO statement.
4 The TopSpeed driver does not support external names for keys, because all keys are
stored internally.
5 LOCK() only affects other LOCK() calls. The only effect of a successful call to LOCK() is
that other processes will get an error (‘File is Already Locked’) when they call LOCK().
6 PACK performs a BUILD and truncates the file to it's minimum size.
7 STREAM has the effect of LOCKing the file.
8 GET(file,filepointer) requires a pointer value returned from the POINTER() function.
POINTER() returns a physical record address (not a record number). Therefore you
cannot use
GET(file,1)
to retrieve the first record in a TopSpeed file because 1 is not a valid pointer in a
TopSpeed file.
9 POSITION(file) returns a STRING(4). POSITION(key) returns a STRING the size of the
key fields + 4 bytes.
10 TopSpeed file logging is very fast (about 100 times faster than the Clarion driver). With
LOGOUT, the TopSpeed engine posts all transactions to memory. ROLLBACK simply
frees the memory, while COMMIT writes out the database changes in a stream.
If a system crashes during a transaction (LOGOUT--COMMIT), the recovery is
automatically handled by the TopSpeed driver the next time the affected file is accessed.
11 LOGOUT has the effect of LOCKing the file. See also PROP:Logout in the Language
Reference.
12 THREADed files do not consume additional file handles for each thread that accesses the
file.
13 OEM conversion is not applied to BINARY MEMOs and BLOBs.
14 The TopSpeed driver accomplishes case insensitivity by converting strings to lowercase.
This can cause unexpected behavior for characters that fall between the upper and lower
case alphabet (that is, ^(94) and _(95) for both ANSI and ASCII sequences).
15 The driver can store BLOBs up to 640 MB. If you attempt to store a BLOB bigger than
this, an ERRORCODE 80 - Function not supported, is returned. This error is returned
after the BLOB handle assignment:
(e.g., blobname{PROP:Handle} = image{PROP:Handle}).
124
Database Drivers and Interfaces
TopSpeed:Other
ERRORCODE 90
The TopSpeed driver posts an ERRORCODE of 90 for unexpected runtime errors. At the same
time, the driver posts a FILEERRORCODE (the former TPSBT error code) that helps us diagnose
the problem. This error handling gives you more control over runtime errors and provides us with
more information. That is, your program can trap for ERRORCODE=90 and react accordingly.
Should you receive an ERRORCODE of 90 from the TopSpeed driver, we want to know about it.
Please send us a copy of the file and the corresponding FILEERRORCODE value.
125
Database Drivers
In a more realistic case (data and keys are compressible), the file size may be estimated as:
((size of all string fields)/(compressibility factor) +
size of all binary fields +
size of all binary key components +
(4 * number of string key components)) * Records + Fixed Overhead
Note that Fixed Overhead varies depending on your file definition. Fixed overhead includes about
800 bytes for the driver, plus the header information describing the fields and keys for the file.
The more fields and keys, and the longer the names, the higher the fixed overhead. A rough rule
of thumb for calculating fixed overhead is 800 bytes + 40 bytes for each field and key. For
Example:
126
Database Drivers and Interfaces
127
Database Drivers
For example:
FileA FILE,DRIVER('TopSpeed'),NAME('TPSFile\!SubTable')
...
END
FileB FILE,DRIVER('TopSpeed'),NAME('TPSFile\!SubTable')
...
END
FileC FILE,DRIVER('TopSpeed'),NAME('TPSFile\!SubTable2')
...
END
FileD FILE,DRIVER('TopSpeed'),NAME('TPSFile\!SubTable2')
...
END
CODE
OPEN(FileA, 10H) ! Read Only - Deny None
OPEN(FileB), 12H) ! Read/Write - Deny None
! Due to access promotion FileA now has Read/Write access
CLOSE(File) does not reset access modes, so given the above example doing:
CLOSE(fileD)
CLOSE(fileC)
CLOSE(fileB)
128
Database Drivers and Interfaces
Similarly, if one of the tables in the file is logged out, then all the tables are effectively logged out.
If one table in the file is flushed, then all the tables are flushed.
This feature is especially useful when there are a large number of small tables, or when the
application must normally access several related tables at once.
When using a variable to hold the name of the multi-table element, you can browse the file in the
Dictionary Editor by selecting the Browse tablename option, selecting the core file name, and
appending the specific table name to the mutil-file name before loading. Example:
invoice.tps\!customer where invoice.tps is the file name stored on disk.
You can retrive the names of tables within the .TPS files with the SEND() command. To retrieve
the first name, issue:
SEND(file,'PNM=')
This returns the name of the first table. To retrieve the second name, issue:
SEND(file,'PNM=FirstTableName')
If you use the OWNER attribute on multiple tables in a single .TPS file, all the tables must have
the same OWNER attribute.
If you don't specify a table name, the table is called 'unnamed', so that the following are all
equivalent:
myname FILE,DRIVER('TopSpeed')
myname FILE,DRIVER('TopSpeed'),NAME('myname')
myname FILE,DRIVER('TopSpeed'),NAME('myname\!unnamed')
Collating Sequences
The collating sequence for a TopSpeed file is established when the table is created or a full build
is performed. Therefore the OEM flag and LOCALE attribute are only significant at the creation of
the file or on a full build.
Any application that uses an incorrect sequence (due to an incompatible .ENV file) to access a
file may get unpredictable results, but will not corrupt the data.
129
Database Drivers
130
Database Drivers and Interfaces
522 invalid data size found while unpacking record (from disk)
530 invalid repeat count found while unpacking record (from disk)
1163 trying to create new record ID when the btree is marked read-only
1164 cannot get btree header (while allocating new record ID)
1477 btree page size (from header) does not match size stored on disk
1602 btree unpacked page size (from header) does not match size loaded from disk
1735 btree header corrupt (discovered when trying to calculate disk file size)
1781 btree structure corrupt (discovered while shifting btree pages up)
131
Database Drivers
1894 btree structure corrupt invalid page parent level (discovered while moving btree
pages)
2272 encryption block invalid size (discovered when reading page from disk)
2277 ReadFile Win32 API function failed (when reading page from disk)
2286 encryption block invalid size (discovered when writing a page to disk)
2341 SetFilePointer Win32 API function failed (when reading page from disk)
132
Database Drivers and Interfaces
The TopSpeed Database Recovery Utility is an emergency repair tool and should not be
used on a regular basis. Use it only when a file has been damaged.
The TopSpeed Database Recovery Utility reads the damaged file and writes the recovered
records to a new file. It uses the information stored in the file's header and scans the file
recovering undamaged portions.
Optionally, you can provide an example file containing the header information in the event the
original header information is damaged. An example file is any file with a FILE declaration
identical to the damaged file. You can create an example file by issuing a CREATE(file)
command, then saving the resulting empty file to a new name.
The TopSpeed Database Recovery Utility is a distributable utility designed to help your end users
recover damaged files.
The following DLLs, found in the Clarion BIN folder, also need to be distributed with TPSFIX.EXE:
CLARUN
CLATPS
The Clarion license agreement applies to TPSFIX.EXE and its associated DLLs. You may
distribute to your users, but they may not redistribute it.
The recovery utility is designed to work either interactively or noninteractively with command line
parameters. Interactively, you provide the parameters through two wizard dialogs. You can run
TPSFIX noninteractively by supplying the command line parameters with the Clarion RUN()
statement, Windows API calls, Windows 95 shortcuts, or Program Manager Icons.
133
Database Drivers
1. Start the utility by DOUBLE-CLICKING on the TopSpeed Database Recovery Utility Icon
In the Clarion Program Group.
The TopSpeed Database Recovery Utility dialog appears. The utility consists of two wizard
dialogs.
2. In the Source (file to recover) section, specify the file name or press the Browse button to
select it from a standard file open dialog.
3. If the file has a password, type it in the Password entry box.
If the database file contains multiple tables (data files), each table must have the same
password.
4. Optionally, in the Destination (result file) section, specify the file name for the target file or
press the Browse button to select it from a standard file open dialog.
By default the .TPR extension is added to the source file name. This parameter is
optional. If omitted, the original (source file) is overwritten and a backup file is created.
The source file is renamed to filename.TPx, where x is automatically incremented from 1
to 9 each time a new file is created. If all nine numbers are used, any subsequent files
created are given the extension .TP$ and are overwritten.
5. If the result file is to have a different password, type it in the Password entry box. If
omitted, the password is removed.
6. Press the Next button.
The second wizard dialog for the TopSpeed Database Recovery Utility appears.
7. Optionally, specify the Example File file name or press the Browse button to select it from
a standard file open dialog.
The utility uses the Example File to determine table layouts and key definitions in the
event those areas of the source file are damaged. The default extension is .TPE, but if
you choose, you may use any valid DOS extension
We recommend shipping an example file when you deploy your application. This
improves data recovery from a damaged file.
8. If the example file has a password, type it in the Password entry box.
9. If you want the utility to rebuild Keys, check the Build Keys box.
If omitted, the keys are rebuilt by the original application when it attempts to open it.
10. If you want to use the Header Information in the source file, check the Use Header box.
Using Header Information optimizes the utility's performance, but should not be used if
the file header is corrupt. If omitted, the utility searches the entire data file and restores all
undamaged pages.
11. If the application uses a Locale (.ENV) File for an alternate collating sequence, specify
the .ENV file or press the Browse button to select it from a standard file open dialog.
12. If the file is using the OEM attribute to control the collating sequence, Check the Use OEM
box.
This enables the OEMTOANSI and ANSITOOEM conversion.
13. Press the Start button to begin the recovery process.
If the utility does not find any errors, a message appears informing you that "No Errors
Detected in <fliename.ext>" and asks if you want to continue with recovery.
134
Database Drivers and Interfaces
sourcepath The file name and path of the source (damaged) database file.
destpath The file name and path of the recovered database file. If omitted, the destpath
is the same as the sourcepath and an example file is required.
/A If specified, the user is not offered a backup prompt. The prompt suppressed,
however a backup of the file is made.
/C:codepage If specified, the code page will be used when rebuilding keys. See also /LO
parameter
/E:examplepath The file name and path of the example database file. This parameter is
required for any fix-in-place operation (that is, when sourcepath = destpath).
/H- If specified, the utility uses the header information in the source file.
/L:localepath The file name and path of the Locale (.ENV) file used to specify an alternate
collating sequence.
/LO:locale If specified, the locale will be used when rebuilding keys. See also /LO
parameter
/N If specified, the file will be checked for errors. No errors will be corrected.
/P If specified, the user is prompted for each parameter even if they are supplied
on the command line.
/T:filename If there are file errors, a log file with the supplied filename will be created.
135
Database Drivers
This recovers the "datafile.TPS" file using the "Example.TPE" file as an example for the table and
key layouts, does not rebuild the keys, and uses the header information in the original file.
TPSFIX automatically saves the original file to a backup with a file extension of TP1 through TP9.
Each time the utility is executed, the numeric portion of the extension is incremented.
This copies the datafilelabel file to DATAFILE.OLD, recovers the file and writes it to
DATAFILE.TPS using the header information in the original file.
136
Database Drivers and Interfaces
137
Database Drivers
138
Database Drivers and Interfaces
Ord FILE,PRE(Ord),DRIVER('SQLDriver'),NAME('ord')
NameDate KEY(+Ord:Name,+Ord:Date),NAME('DateKey')
Record RECORD
Name STRING(12),NAME('NameId')
Date DATE,NAME('OrderDate')
Type STRING(1),NAME('OrderType')
Details STRING(20),NAME('OrderDetails')
END
END
CODE
Ord:Name = 'SMITH'
SET(Ord:NameDate,Ord:NameDate)
LOOP
NEXT(Ord)
!... some processing
END
The SET(file) statement (to process in file order, not keyed order) only supports the NEXT
statement. Any attempt to execute a PREVIOUS statement when processing in file order
causes ERRORCODE 80 (Function Not Supported).
139
Database Drivers
NULL Fields
When you read a row with NULL values from an SQL table, the Clarion record buffer contains an
empty string for string fields, or a 0 for numeric fields, and NULL(field) returns TRUE for the field.
If the field's contents are later changed to a non-empty or non-zero value then NULL(field) returns
FALSE.
If you want to change a NULL field to non-null, but still blank or zero, then you must call
SETNONULL(field) to reset the null flag.
If you wish to clear a field to NULL that was previously non-null then call SETNULL(field) or
SETNULL(record). SETNULL() clears the contents of the field or record and resets the null flag.
When adding a new record to a file, by default all blank fields are added as blank or zero fields,
not as NULL. If you want to force a field to be added with a NULL value, then you must call
SETNULL(field) or SETNULL(record) to null all the fields.
140
Database Drivers and Interfaces
Driver-specific import information is described in the chapter or manual for each driver.
Before you can connect to the SQL database and import table definitions, the database
must be started and must be accessible from your computer.
Fill in the fields in the Login/Connection dialog.
Next >
Press this button to open the Import Wizard's Import List dialog.
141
Database Drivers
Driver Options
Typically, the Import Wizard places nothing in the Driver Options field. However, you can add
driver strings to this field to control how the driver accesses your SQL data. For example, you can
generate a log of driver activity or specify how the driver handles dates with a value of zero (0).
See SQL Driver Strings for more information.
Owner Name
Typically, the Import Wizard places the SQL database connection information (Host, Username,
Password, etc.) in the Owner Name field.
For security and portability reasons, you may want to specify this connection information with
variables rather than hard coded strings in your dictionary. To use a variable specification, type
the variable name, preceeded by an exclamation point in the Owner Name field; for example
!LoginString. Then use whatever method you choose to prime the variable before accessing the
SQL table.
Some SQL Accelerator drivers allow additional information in the Owner Name field. This
information is described in the documentation for each driver.
The SQL drivers now parse out double quotes within the owner attribute to allow commas to be
passed in a section. For example, you can now do
"server,port",database,uid,pwd
142
Database Drivers and Interfaces
All SQL drivers support the ability to automatically retrieve values set by the server when an
INSERT is issued or to set values via server calls before an INSERT is issued. Normally, this
usage is designed for auto incrementing columns that are not set up as auto number key columns
on the client side.
These techniques are designed so that the value in columns that are auto incremented by actions
that are performed by the Database Server (as opposed to auto incrementing on the client side)
are available to the client application right after the insert without having to perform a requery of
the database.
This feature is achieved by using the file property (PROP:ServerAutoInc) and two driver strings
(/AUTOINC and /PREAUTOINC).
Language Support
Here is the "behind the scenes" language support provided for Server Side Auto Incrementing. In
most cases, if you were using the application/dictionary approach to development, you would not
need to hand code these properties (they are built-in to the template support via dictionary driver
string and field option settings – see below)
PROP:ServerAutoInc
This property is READ/WRITE. To make the driver automatically update fields after an ADD or
APPEND call (or before in some cases) you need to issue the following statement
file{PROP:ServerAutoInc}
before issuing the ADD(file) or APPEND(file).
This property is a flag that is reset by ADD and APPEND. So it must be reissued each time an
ADD or APPEND is done. If you always want this flag set, you should attach a file driver
callback interface to the file and set the property before the ADD or APPEND statements are
executed.
To specify which field is actually set on the server, you need to issue the following statement:
file{PROP:ServerAutoInc, n} = m
where n is the field number and m is the column number of the returning SQL code. This is
almost always 1. However, in the following SELECT statement:
SELECT MAX(Col1),MAX(Col2)….FROM ACCOUNTS
and your file structure had Col1 as the first field and Col2 as the second field then you would
issue:, you would issue:
Accounts{PROP:ServerAutoInc, 1} = 1
Accounts{PROP:ServerAutoInc, 2} = 2
You only need to set the value of {PROP:ServerAutoInc, n} once for non-threaded files and once
per thread for threaded files.
If no valid fields are specified to receive the results for the auto incrementing method and
file{PROP:ServerAutoInc} has been issued, ADD() will return error code 80 (Function not
supported).
143
Database Drivers
You can query PROP:ServerAutoInc to see if the next ADD or APPEND will do a server side
auto increment or to verify that a field is set to receive the results of the auto increment.
with the necessary SQL statement you want executed for retrieving the auto-incrementing fields
and
/PREAUTOINC=[TRUE|FALSE]
to indicate that the auto-incrementing code should be executed before or after the INSERT
statement. For all the drivers (except Oracle), if PREAUTOINC is not specified, then the SQL
code is issued after the SELECT. For Oracle, it is issued before the SELECT.
These properties can easily be set through the Dictionary Driver String Options.
Example:
!ORACLE Example
OracleFile FILE,DRIVER('Oracle', '/AUTOINC=SELECT Myseq.nextVal')
RECORD
SomeData STRING
autoIncFld PDECIMAL(31)
END
END
CODE
OPEN(OracleFile)
OracleFile{PROP:ServerAutoInc}
ADD(OracleFile) !will return error code 80 as no field has been set to
receive the result of the SELECT statement
OracleFile{PROP:ServerAutoInc, 2} = 2
ADD(OracleFile) !will return error code 80 as no first field has been set
OracleFile{PROP:ServerAutoInc, 2} = 1
OracleFile{PROP:ServerAutoInc}
ADD(OracleFile)
! This will first put the nextval sequence value into
! OracleFile.autoIncFld and then do a normal ADD call.
!********************************************************
!MySQL Example
Pet FILE,DRIVER('ODBC','/AUTOINC=SELECT LAST_INSERT_ID()'),|
OWNER('menagerie,root'),NAME('pet'),PRE(pet),BINDABLE,THREAD
Primary KEY(pet:PetID),PRIMARY
Record RECORD,PRE()
144
Database Drivers and Interfaces
Name CSTRING(21)
Owner CSTRING(21)
Species CSTRING(21)
Sex STRING(1)
Birth DATE
Death DATE
PetID LONG !Server side auto inc
END
END
CODE
OPEN(Pet)
Pet{PROP:ServerAutoInc, 7} = 1 ! indicate which field receives which value
Pet:Name = 'test autoinc'
Pet:Owner = 'Pierre'
Pet:Species = 'Dog'
Pet:Sex = 'M'
Pet:Birth = DEFORMAT('2005-12-12', @d10)
Pet{PROP:ServerAutoInc} ! arms automatic updating
ADD(Pet) ! PetID now has the Auto incremented value
Pet:PetID = 0
Pet:Name = 'test no autoinc'
Pet:Owner = 'Pierre'
Pet:Species = 'Dog'
Pet:Sex = 'M'
Pet:Birth = DEFORMAT('2005-12-12', @d10)
ADD(Pet) ! PetID will not have the auto incremented value.
Application/Dictionary Implementation
There are essentially two steps involved to activate the retrieval of a server side auto-
incrementing value.
145
Database Drivers
1. In the Dictionary, identify the column in the Column Properties User Options, with one of two
option types:
To identify a column in the dictionary as a server side Identity column, add the following user
option:
IsIdentity = TRUE
FileLabel{PROP:ServerAutoInc, FieldNumber} = 1
The supported values for IsIdentity are TRUE,True or 1 (it is not case sensitive).
Remember, the column you identify must exist on the server as one that possesses the "Identity"
characteristic.
If you are returning more than one column in your own SQL code, use the ServerAutoIncColumn
user option as follows:
ServerAutoIncColumn=m
FileLabel{PROP:ServerAutoInc, FieldNumber} = m
146
Database Drivers and Interfaces
This essentially associates a column in the dictionary with a Server Side Auto-Incrementing
Column. You may also need to add the needed SQL SELECT statement in the /AUTOINC driver
string. For example:
/AUTOINC=SELECT LAST_INSERT_ID()
An Identity or ServerAutoIncColumn column cannot be used in a key with the auto number
feature active. The template will display an error message, if you do this.
In addition, server side auto incrementing columns are NOT supported for BLOB, MEMO, or
GROUP data types, and any data element using the OVER attribute.
Template Considerations
When using this new feature with Clarion template chain applications, the trigger support needs
to be enabled in order to use the IsIdentity and ServerAutoIncColumn field options. This option is
found in the Global Properties File Options.
This is necessary because all of the above template support is generated in the FileManager’s
PreInsert method.
147
Database Drivers
The SQL view engine supports PROP:GroupBy and PROP:Having. These properties allow you
to add respectively GROUP BY and HAVING SQL clauses to your SELECT statement.
See Also: Runtime SQL Properties for Views using SQL Drivers
Example:
PROGRAM
MAP
END
EMP FILE,DRIVER('ORACLE'),NAME('EMP'),PRE(EMP)
P_EKY_EMP KEY(EMP:EMPNO),NOCASE,OPT,PRIMARY
KEY_DEP KEY(EMP:DEPTNO),DUP,NOCASE,OPT
Record RECORD
EMPNO SHORT !Emp-no
ENAME CSTRING(11) !Employee name
JOB CSTRING(10) !Job
HIREDATE DATE !Hiredate
MGR SHORT !Manager
SAL PDECIMAL(7,2) !Salary
COMM PDECIMAL(7,2) !Commisison
DEPTNO BYTE
END
END
MyView VIEW(EMP)
PROJECT(EMP:Mgr)
PROJECT(EMP:Sal)
END
CODE
148
Database Drivers and Interfaces
OPEN(EMP)
OPEN(MyView)
MyView{'EMP:Sal',PROP:Name} = 'sum(sal)'
MyView{PROP:GroupBy} = 'Mgr'
MyView{PROP:Having} = 'sum(sal) > 100000'
SET(MyView)
NEXT(MyView)
The example code above is the equivalent to "SELECT mgr, sum(sal) FROM EMP GROUP BY
mgr HAVING sum(sal) > 100000"
In other words, this code will return a list of all Manager IDs and the total salary of their
subordinates if their subordinates make a total of more than 100000.
149
Database Drivers
No matter what type of SQL/ADO/ODBC driver you are using, Clarion will detect and convert
these composite DateTime columns for you automatically.
MSSQL TIMESTAMP fields are now flagged as READONLY by the Dictionary Synchronizer.
Know your back end! For example, the SMALLDATETIME and DATETIME data types of MS-
SQL are treated equally, with both only being able to store the minimum of either the precision of
the Clarion TIME field or the backend data type. So, in the case of the SMALLDATETIME data
type, the seconds and hundredths of a second are discarded, using the SMALLDATETIME rule
that > 29.99 is rounded up to the next minute.
Another note; If you don't need the time portion, you can just use a "Date" type field (as long as
no one else is writing to the "Time" portion from another application). Otherwise, you
will need to be aware that the time portion is not zero when filtering, sorting, etc.
If you do not use the time part of a timestamp field then you can safely change the Clarion coumn
definition from:
TSField STRING(8)
TSFieldGroup GROUP,OVER(TSField)
DateFld DATE
TimeFld TIME
END
to
TSField DATE
150
Database Drivers and Interfaces
Synchronizer Considerations
When using the dictionary synchronizer, the READONLY attribute will be set by the MSSQL
synchroniser for UNIQUEID and TIMESTAMP fields only. The SQL Anywhere synchronizer sets
it for fields that have a default value of TIMESTAMP.
If your backend stores more information than this in the time field (i.e., fractions of a second), you
must use a timestamp structure to access the field for accurate indexing. When a timestamp
structure is used, then the driver uses an ODBC TIMESTAMP_STRUCT to communicate with the
backend.
Example:
151
Database Drivers
With the new PROP:ServerCaseInsensitive set to 0 in version 6.3, the SQL behavior is
equivalent to Clarion 6.2
152
Database Drivers and Interfaces
153
Database Drivers
154
Database Drivers and Interfaces
155
Database Drivers
CHECKFORNULL
The CHECKFORNULL field switch applies to all SQL drivers
Usage:
When browsing through a table, it is sometimes necessary for the driver to request all rows
that are at, or before, the current row. It does this by generating a WHERE clause. For
example:
WHERE (field1 <= value) AND (field1 < value OR field2 <= value2)
The above example is for a two component key. For more components, the WHERE clause
gets longer, and this will work well in most cases. However, in SQL, if a field has a NULL
value, then field < value is false, field = value is false, and field > value is also false. So, if you
are sorting on field components that contain NULL values, you need to set the external field
name of the field to
So, in this example, the WHERE clause will also return rows that contain NULL values, instead of
rejecting them.
156
Database Drivers and Interfaces
Regarding SQL databases, standard SET(key,key) processing is not always the most efficient
approach. This is because the SET(key,key) statement sets the starting part of the search, but
not the ending part of the search.
CLEAR(PHO:Record)
PHO:CategoryID = 1
SET(PHO:FK_CategoryKey,PHO:FK_CategoryKey)
LOOP
IF Access:Photos.Next() <> LEVEL:Benign
BREAK
END
IF PHO:CategoryID <> 1
BREAK
END
END
CLEAR(PHO:Record)
PHO:CategoryID = 1
SET(PHO:FK_CategoryKey,PHO:FK_CategoryKey)
SEND(Photos, '/WHERE CategoryId = ''' & PHO:CategoryID & '''')
!Eliminates PHO:CategoryID checking
LOOP
IF Access:Photos.Next() <> LEVEL:Benign
BREAK
END
END
CLEAR(PHO:Record)
PHO:CategoryID = 1
SET(PHO:FK_CategoryKey) !SET(KEY,KEY) not needed
157
Database Drivers
All of the filtering you need is defined and optimized in the /WHERE driver string via the SEND
command.
If you notice that the backend is doing a full table scan, this would indicate that a design problem
is possible on the backend database. Clarion simply sends a SELECT statement to the server. It
does NOT tell the server how to fulfill that SELECT. That decision is left up to the server. For
example, if you send to the server:
If there is no corresponding index on the server, then the server has no choice but to do a full
table scan. In that case, instead of rewriting all of the Clarion code to use a Prop:SQL statement,
the time would be better spent on optimizing the database design.
Using PROP:Where (or SEND(FILE, '/WHERE.....')) can limit the result set you get, and even
eliminate using a key in the SET statement. Clarion does this by setting or adding to the WHERE
clause containing your condition, greatly reducing the load on the server.
Note: Do not use the standard clarion field name syntax (e.g., pre:columnname).
For example:
SET(MyFile)
MyFile{PROP:WHERE} = 'CUSTOMERID = ' & LOC:CUSTOMERID
LOOP
NEXT(MYFILE)
IF ERRORCODE() THEN BREAK.
! process record here
END
SET(MYF:K_DATE)
MYFILE{PROP:WHERE} = 'CUSTOMERID = ' & LOC:CUSTOMERID
will do the same, but order them by the date (whatever is in MYF:K_DATE).
158
Database Drivers and Interfaces
Using PROP:Where also eliminates the hassle of handling "field alignment" when using
PROP:SQL to retrieve records. It accomplishes what you would get if you intend to do the
equivalent of a "SELECT *".
You can also improve performance by using a BUFFER statement, like this:
BUFFER(MyFile, 20)
SET(MYF:K_DATE)
MYFILE{PROP:WHERE} = 'CUSTOMERID = ' & LOC:CUSTOMERID
159
Database Drivers
Performance Considerations
Generally, Clarion's development environment (Data Dictionary Import Wizard, Database Drivers,
and templates) produces optimized, high performance, SQL applications.
This section describes some of the issues involved in producing these optimized applications.
You should be aware of these issues so you can maintain a high level of performance as you
take more control of the development process.
Most, but not all, SQL servers sort case insensitively. So, for example, when you issue the
following SELECT statement:
Alan
arthur
Brian
chris
James
And not:
160
Database Drivers and Interfaces
arthur
chris
Alan
Brian
James
If a key does not have the Case Sensitive option checked in the dictionary editor, then the SQL
Accelerator is forced to issue a SELECT statement with ORDER BY UPPER(key component) and
WHERE clauses including calls to the UPPER function. In most cases this is not necessary and
may impact on performance, depending on the sophistication of your server. A more advanced
server will notice the unnecessary calls to UPPER and ignore them. A less advanced server will
not notice them and probably do a full table scan to process the SELECT statement.
161
Database Drivers
You may want to issue intermittent calls to COMMIT and LOGOUT to save data at regular
intervals. See the Language Reference for more information.
162
Database Drivers and Interfaces
When you issue a SELECT or CALL statement using PROP:SQL or any statement using
PROP:SQLRowSet, the returned columns must match the fields declared in the named file or
view. In addition, if you use VIEW{Prop:SQL} to issue a SELECT statement, the fields in the
SELECT must be ordered based on the field order in the file definition, not the PROJECT
sequence.
PROP:SQL
You can use Clarion's property syntax (PROP:SQL) to send SQL statements to the backend SQL
server, within the normal execution of your program. You can send any SQL statements
supported by the SQL server.
This capability lets your program do backend operations independent of the SQL Accelerator
driver's generated SQL. For example, multi-record updates can often be accomplished more
efficiently with a single SQL statement than with a template generated Process procedure which
updates one record at a time. In cases like these it makes sense for you to take control and send
custom SQL statements to the backend, and PROP:SQL lets you do this.
If you issue an SELECT or CALL statement, you use NEXT(file) to retrieve the result set one row
at a time, into the file's record buffer. The FILEERRORCODE() and FILEERROR() functions
return any error code and error message set by the back-end SQL server.
You may also query the contents of PROP:SQL to get the last SQL statement issued by the file
driver.
Examples:
SQLFile{PROP:SQL}='SELECT field1,field2 FROM table1' |
& 'WHERE field1 > (SELECT max(field1)' |
& 'FROM table2' !Returns a result set you
163
Database Drivers
PROP:SQLRowSet
If you want to execute an SQL statement that returns a result set, you have two options. If you
need to execute a SELECT or CALL statement you can use PROP:SQL. However, if you want to
issue an other SQL statement that returns a result set, you must use PROP:SQLRowSet. You
must use NEXT(file|view) to retrieve the rows returned by the SQL statement.
CODE
SqlFile{PROP:SQL} = 'UPDATE SalaryFile SET '&|
'SALARY=SALARY * 1.1 WHERE JOB=''S'''
The names used in the SQL statement are the SQL table names, not the Clarion field names.
PROP:SQLFilter
You can use PROP:SQLFilter to filter your VIEWs using native SQL code rather than Clarion
code.
When you use PROP:SQLFilter, the SQL filter is passed directly to the server. As such it cannot
contain the name of variables or functions that the server is not aware of; that is the filter
expression must be valid SQL syntax with valid SQL column names. For example:
VIEW{PROP:SQLFilter} = 'Date = TO_DATE(''01-MAY-1996'',''DD-MON-YYYY'')'
or
164
Database Drivers and Interfaces
When you append the SQL filter by using the plus sign, the logical end result of the filtering
process is (View Filter) AND (SQL Filter).
Omit the plus sign (+) to replace the Clarion filter with the SQL filter. When you replace the
Clarion filter with the SQL filter by omitting the plus sign, the logical end result of the filtering
process is simply (SQL Filter).
CALL
To call a stored procedure you use property syntax to issue the SQL syntax 'CALL
storedprocedure.'
Example:
MyFile{PROP:SQL} = 'CALL SelectRecordsProcedure (&MyVar[INOUT])'
NORESULTCALL
165
Database Drivers
The SQL Accelerator drivers also allow the syntax 'NORESULTCALL storedprocedure' for stored
procedures that do not return a result set.
Example:
MyFile{PROP:SQL} = 'NORESULTCALL SelectRecordsProcedure (&MyVar[INOUT])'
When you issue a {PROP:SQL} = '&return = call storedProcedure' against MSSQL, the field
bound to return will not hold the result of the procedure call until all records have been retrieved
via calls to NEXT(file)
The BINARY switch is used to signal the driver to pass the data in the bound field as binary data
rather than character data. See the example below.
Example:
MyFile FILE,DRIVER('ODBC')
Record RECORD
ErrorCode LONG
ErrorMsg STRING(100)
END
END
CODE
OPEN(MyFile)
MyFile{PROP:SQL} = 'CALL ProcWithResultSet'
NEXT(MyFile)
IF ~ERRORCODE()
IF MyFile.ErrorCode THEN STOP(MyFileErrorMsg).
END
The above example shows how to return a result set. The result set must match the fields
declared in the named file or view. The storedprocedure ProcWithResultSet includes a
final select statement that results with the set of requested data.
Example:
PROGRAM
MAP
CallProc(STRING)
END
MyFile FILE,DRIVER('MSSQL')
Record RECORD
c LONG
END
END
Ret LONG
166
Database Drivers and Interfaces
Out STRING(10)
CODE
BIND('RetCode', Ret)
BIND('Out', Out)
CallProc('&RetCode = CALL StoredProcTest(''1'',&Out)')
MESSAGE(Return value of StoredProcTest =' & Ret)
MESSAGE(Output parameter of StoredProcTest =' & Out)
CallProc PROCEDURE(Str)
CODE
MyFile{PROP:SQL} = Str
Example:
PROGRAM
MAP
END
PRAGMA('link(C%V%MSS%X%%L%.LIB)')
SQLFile FILE,DRIVER('MSSQL'),NAME('SYSFILES')
REC RECORD
ID LONG
NAME CSTRING(100)
END
END
TS STRING(8)
CODE
OPEN(SQLFile)
SQLFile{PROP:SQL} = 'DROP PROCEDURE tstest'
SQLFile{PROP:SQL} = 'CREATE PROCEDURE tstest @ts as timestamp AS '& |
' return'
BIND('TS',TS)
TS='<0><0><0><0><0><0><5H><0DDH>'
SQLFile{PROP:SQL}='NORESULTCALL TSTEST(&TS[IN][BINARY])'
167
Database Drivers
The above example shows how to use the IN and BINARY switches.
For a more specific example tailored to MSSQL, refer to the MSSQL Accelerator topic.
168
Database Drivers and Interfaces
Explanation:
What you are asking for (in pseudo SQL) is
Without the DESC you will get the fields in the same order as going forward.
Rule Two:
You not only have to have a key defined, but the sort order has to be
unique.
Explanation:
Let us use a simple table example with two fields F1 and F2 with contents of
169
Database Drivers
F1 F2
1 1
1 2
1 3
2 1
2 2
2 3
3 1
Now if you have a browse on this table ordered on F1 only, the above sequence would produce
the following results.
F1 F2
1 1
1 2
1 3
2 1
2 2
2 3
3 1
With the record selected, we fill from the current record forward:
SELECT F1, F2 FROM table WHERE F1>=2 ORDER BY F1
F1 F2
2 1
2 2
2 3
3 1
170
Database Drivers and Interfaces
But the driver knows that we are starting on F1=2 and F2=2, so it only returns a result set of:
F1 F2
2 2
2 3
3 1
Next, the browse needs to fill from the current record backwards. This generates:
SELECT F1, F2 FROM table WHERE F1 <= 2 ORDER BY F1 DESC
F1 F2
2 1
2 2
2 3
1 1
1 2
1 3
Notice that this sort is not the same as reversing the original sort:
F1 F2
2 3
2 2
2 1
1 3
1 2
1 1
Again, since the driver knows that you are actually starting from F1=2, F2=2 so you get a result
set of:
F1 F2
2 2
2 3
1 1
1 2
171
Database Drivers
1 3
Notice that F1=2, F2=3 is retrieved when asking for either forward or backwards results. This
means you may end up with a browse screen looking like this:
F1 F2
1 3
1 2
1 1
2 3 <<<<<<< result returned by backward retrieve
2 2
2 3 <<<<<<< result returned by forward retrieve
3 1
The only way to stop this ghosting effect is to make sure that all your browses always use
a unique sort sequence. In addition any other optional sort sequences should also include
a unique component.
For example, if you had a unique EmployeeID component, and another Name key based on
LastName and FirstName, add the unique EmployeeID as the third component of the name key.
172
Database Drivers and Interfaces
EMP FILE,DRIVER('ORACLE'),NAME('EMP'),PRE(EMP)
P_EKY_EMP KEY(EMP:EMPNO),NOCASE,OPT,PRIMARY
KEY_DEP KEY(EMP:DEPTNO),DUP,NOCASE,OPT
Record RECORD
EMPNO SHORT !Emp-no
ENAME CSTRING(11) !Employee name
JOB CSTRING(10) !Job
HIREDATE DATE !Hiredate
MGR SHORT !Manager
SAL PDECIMAL(7,2) !Salary
COMM PDECIMAL(7,2) !Commisison
DEPTNO BYTE
END
END
MyView VIEW(EMP)
PROJECT(EMP:EmpNo)
END
CODE
OPEN(EMP)
OPEN(MyView)
MyView{'EMP:EmpNo',PROP:NAME} = 'count(*)'
SET(MyView)
NEXT(MyView)
This example will produce the equivalent of "SELECT count(*) FROM EMP".
173
Database Drivers
System-wide Logging
There is an utility/example application --Trace.EXE. You can run this from the Clarion Start Menu
option. A compiled version is installed in the .\BIN directory and the source .APP is installed in the
\Examples\DriverTrace directory. This utility allows you to easily set tracing options for each file
driver and for the VIEW engine.
These tracing options are stored in DRIVERS.INI in the
CSIDL_APPDATA\SoftVelocity\Clarion\<clarion_version> folder.
For system-wide logging, you can add the following to your DRIVERS.INI file:
[CWdriver]
Profile=[1|0]
Details=[1|0]
Trace=[1|0]
TraceFile=[Pathname]
where driver is the database driver name (for example [CWTopSpeed]). Neither the INI section
name [CWdriver] nor the INI entry names are case sensitive.
Profile=1 (PROP:Profile) tells the driver to include the Clarion I/O statements in the log file;
Profile=0 tells the driver to omit Clarion I/O statements. The Profile switch must be turned on for
the Details switch to have any effect.
Details=1 (PROP:Details) tells the driver to include record buffer contents in the log file;
however, if the file is encrypted, you must turn on both the Details switch and the
ALLOWDETAILS switch to log record buffer contents (see ALLOWDETAILS). Details=0 tells the
driver to omit record buffer contents. The Profile switch must be turned on for the Details switch to
have any effect.
Trace=1 tells the driver to include all calls to the back-end file system, including the generated
SQL statements and their return codes, in the log file. Trace=0 omits these calls. The Trace
switch generally generates log information that helps to debug the SQL drivers, but is normally
not particularly useful to the developer.
TraceFile names the log file to write to. If TraceFile is omitted the driver writes the log to
driver.log in the current directory. Pathname is the full pathname or the filename of the log file to
write. If no path is specified, the driver writes the specified file to the current directory.
To view the trace details in your system debugger, name the target trace file DEBUG:.
Logging opens the named logfile for exclusive access. If the file exists, the new log data is
appended to the file.
On Demand Logging
For on-demand logging you can use property syntax within your program to conditionally turn
various levels of logging on and off. The logging is effective for the target table and any view for
which the target table is the primary table.
174
Database Drivers and Interfaces
175
Database Drivers
176
Database Drivers and Interfaces
A forward slash precedes all SQL driver strings. The slash allows the driver to distinguish
between driver strings and SQL statements sent with the SEND function.
The SQL Accelerator Drivers support the following Driver Strings:
ALLOWDETAILS
APPENDBUFFER
AUTOINC
BINDCOLORDER
BINDCONSTANTS
BUSYHANDLING
BUSYMESSAGE
BUSYRETRIES
CLIPSTRINGS
FASTCOLUMNFETCH
FORCEUPPERCASE
GATHERATOPEN
GETINFO
IGNORETRUNCATION
ISOLATIONLEVEL
JOINTYPE
LOGFILE
NESTING
ODBCCALL
ORDERINSELECT
PREAUTOINC
TURBOSQL
USEINNERJOIN
VERIFYVIASELECT
WHERE
ZERODATE
ZEROISNULL
177
Database Drivers
APPENDBUFFER
DRIVER('SQLDriver', '/APPENDBUFFER = size ' )
[ Buffer" = ] SEND(file, 'APPENDBUFFER [ = size ]' )
By default, APPEND adds records to the file one at a time. To get better performance over a
network you can tell the driver to build up a buffer of records then send all of them to the SQL
back end at once. Size is the number of records you want to allocate for the buffer. SEND returns
the number of records that will fit in the buffer.
AUTOINC
The AUTOINC driver string is used to specify an SQL statement that you want executed for
retrieving a server side auto-incrementing field.
The Dictionary Editor contains a Driver String Options dialog in the Table Properties to allow
easy entry of this string.
See Also: Server side auto-incrementing values
178
Database Drivers and Interfaces
BINDCOLORDER
The order that these are executed is not completely fixed. The compile (Step 1) must be done
first and the fetch (Step 5) last. However, the other three steps can be executed in any order.
If BINDCOLORDER is set to 0, the order is 1, 2, 3, 4, 5.
If BINDCOLORDER is set to 1, the order is 1, 3, 2, 4, 5.
If BINDCOLORDER is set to 2, the order is 1, 3, 4, 2, 5.
The default is 0 for all supported driver except MySQL, which has a default setting of 2.
BINDCONSTANTS
DRIVER('SQLDriver', '/BINDCONSTANTS = TRUE | FALSE ' )
[ Bind" = ] SEND(file, '/BINDCONSTANTS [ = TRUE | FALSE ]' )
179
Database Drivers
BUSYHANDLING
Valid for all SQL drivers and ODBC except for Oracle.
BUSYHANDLING is used to set the strategy for handling busy connections with MSSQL and
ODBC drivers. This setting is system wide, so once you set it (regardless of which table) it is set
for all tables on all threads.
180
Database Drivers and Interfaces
1 indicates that the driver should do nothing about the error. This would be used
when an application is only single threaded.
3 indicates to use the retry on busy strategy. This is the default driver behavior.
BUSYMESSAGE
Valid for MSSQL and ODBC drivers only. The str parameter indicates the message to use when a
busy connection is detected.
Use this driver string to set the string the driver should look for to detect a busy connection. The
default message the driver looks for is "[Microsoft][ODBC SQL Server Driver]Connection is busy
with results for another hstmt".
MSSQL and ODBC do not return a unique error code for the busy connection error. Therefore,
the driver is forced to use default error text to detect the busy error. This text changes depending
on the language your user's MSSQL is set up to use. BUSYMESSAGE allows the programmer to
detect a consistent busy message, regardless of language version of MS SQL or ODBC that is
used.
181
Database Drivers
BUSYRETRIES
Valid for MSSQL and ODBC drivers only. The n parameter indicates the number of retries
(default = 20).
BUSYRETRIES is used to set the number of times to retry a connection that is busy. This is the
default busy strategy (attempt a retry) that is used for MSSQL/ODBC.
CLIPSTRINGS
DRIVER('SQLDriver', '/CLIPSTRINGS = TRUE | FALSE ' )
[ Clipped" = ] SEND(file, '/CLIPSTRINGS [ = TRUE | FALSE ]' )
FASTCOLUMNFETCH
DRIVER('SQLDriver', '/FASTCOLUMNFETCH = TRUE | FALSE ' )
[ Fetch" = ] SEND(file, '/FASTCOLUMNFETCH [ = TRUE | FALSE ]' )
182
Database Drivers and Interfaces
FORCEUPPERCASE
DRIVER('SQLDriver', '/FORCEUPPERCASE = TRUE | FALSE ' )
[ Uppered" = ] SEND(file, '/FORCEUPPERCASE [ = TRUE | FALSE ]' )
GATHERATOPEN
DRIVER('SQLDriver', '/GATHERATOPEN = TRUE | FALSE ' )
183
Database Drivers
GETINFO
Result = filelabel{PROP:GETINFO, property}
SQL_ACTIVE_CONNECTIONS EQUATE(0)
SQL_ACTIVE_STATEMENTS EQUATE(1)
SQL_DATA_SOURCE_NAME EQUATE(2)
SQL_DRIVER_HDBC EQUATE(3)
SQL_DRIVER_HENV EQUATE(4)
SQL_DRIVER_HSTMT EQUATE(5)
SQL_DRIVER_NAME EQUATE(6)
SQL_DRIVER_VER EQUATE(7)
SQL_FETCH_DIRECTION EQUATE(8)
SQL_ODBC_API_CONFORMANCE EQUATE(9)
SQL_ODBC_VER EQUATE(10)
SQL_ROW_UPDATES EQUATE(11)
SQL_ODBC_SAG_CLI_CONFORMANCE EQUATE(12)
SQL_SERVER_NAME EQUATE(13)
SQL_SEARCH_PATTERN_ESCAPE EQUATE(14)
SQL_ODBC_SQL_CONFORMANCE EQUATE(15)
SQL_DBMS_NAME EQUATE(17)
SQL_DBMS_VER EQUATE(18)
SQL_ACCESSIBLE_TABLES EQUATE(19)
SQL_ACCESSIBLE_PROCEDURES EQUATE(20)
SQL_PROCEDURES EQUATE(21)
SQL_CONCAT_NULL_BEHAVIOR EQUATE(22)
SQL_CURSOR_COMMIT_BEHAVIOR EQUATE(23)
SQL_CURSOR_ROLLBACK_BEHAVIOR EQUATE(24)
SQL_DATA_SOURCE_READ_ONLY EQUATE(25)
SQL_DEFAULT_TXN_ISOLATION EQUATE(26)
SQL_EXPRESSIONS_IN_ORDERBY EQUATE(27)
184
Database Drivers and Interfaces
SQL_IDENTIFIER_CASE EQUATE(28)
SQL_IDENTIFIER_QUOTE_CHAR EQUATE(29)
SQL_MAX_COLUMN_NAME_LEN EQUATE(30)
SQL_MAX_CURSOR_NAME_LEN EQUATE(31)
SQL_MAX_OWNER_NAME_LEN EQUATE(32)
SQL_MAX_PROCEDURE_NAME_LEN EQUATE(33)
SQL_MAX_QUALIFIER_NAME_LEN EQUATE(34)
SQL_MAX_TABLE_NAME_LEN EQUATE(35)
SQL_MULT_RESULT_SETS EQUATE(36)
SQL_MULTIPLE_ACTIVE_TXN EQUATE(37)
SQL_OUTER_JOINS EQUATE(38)
SQL_OWNER_TERM EQUATE(39)
SQL_PROCEDURE_TERM EQUATE(40)
SQL_QUALIFIER_NAME_SEPARATOR EQUATE(41)
SQL_QUALIFIER_TERM EQUATE(42)
SQL_SCROLL_CONCURRENCY EQUATE(43)
SQL_SCROLL_OPTIONS EQUATE(44)
SQL_TABLE_TERM EQUATE(45)
SQL_TXN_CAPABLE EQUATE(46)
SQL_USER_NAME EQUATE(47)
SQL_CONVERT_FUNCTIONS EQUATE(48)
SQL_NUMERIC_FUNCTIONS EQUATE(49)
SQL_STRING_FUNCTIONS EQUATE(50)
SQL_SYSTEM_FUNCTIONS EQUATE(51)
SQL_TIMEDATE_FUNCTIONS EQUATE(52)
SQL_CONVERT_BIGINT EQUATE(53)
SQL_CONVERT_BINARY EQUATE(54)
SQL_CONVERT_BIT EQUATE(55)
SQL_CONVERT_CHAR EQUATE(56)
SQL_CONVERT_DATE EQUATE(57)
SQL_CONVERT_DECIMAL EQUATE(58)
SQL_CONVERT_DOUBLE EQUATE(59)
SQL_CONVERT_FLOAT EQUATE(60)
SQL_CONVERT_INTEGER EQUATE(61)
SQL_CONVERT_LONGVARCHAR EQUATE(62)
SQL_CONVERT_NUMERIC EQUATE(63)
SQL_CONVERT_REAL EQUATE(64)
SQL_CONVERT_SMALLINT EQUATE(65)
SQL_CONVERT_TIME EQUATE(66)
SQL_CONVERT_TIMESTAMP EQUATE(67)
185
Database Drivers
SQL_CONVERT_TINYINT EQUATE(68)
SQL_CONVERT_VARBINARY EQUATE(69)
SQL_CONVERT_VARCHAR EQUATE(70)
SQL_CONVERT_LONGVARBINARY EQUATE(71)
SQL_TXN_ISOLATION_OPTION EQUATE(72)
SQL_ODBC_SQL_OPT_IEF EQUATE(73)
186
Database Drivers and Interfaces
SQL_MAX_ROW_SIZE EQUATE(104)
SQL_MAX_STATEMENT_LEN EQUATE(105)
SQL_MAX_TABLES_IN_SELECT EQUATE(106)
SQL_MAX_USER_NAME_LEN EQUATE(107)
SQL_MAX_CHAR_LITERAL_LEN EQUATE(108)
SQL_TIMEDATE_ADD_INTERVALS EQUATE(109)
SQL_TIMEDATE_DIFF_INTERVALS EQUATE(110)
SQL_NEED_LONG_DATA_LEN EQUATE(111)
SQL_MAX_BINARY_LITERAL_LEN EQUATE(112)
SQL_LIKE_ESCAPE_CLAUSE EQUATE(113)
SQL_QUALIFIER_LOCATION EQUATE(114)
IGNORETRUNCATION
187
Database Drivers
ISOLATIONLEVEL
DRIVER('SQLDriver', '/ISOLATIONLEVEL = number' )
number = SEND(file,'/ISOLATIONLEVEL = number')
file{PROP:IsolationLevel} = number
number = file{PROP:IsolationLevel}
Dirty Read Transaction 1 changes a row. Transaction 2 reads the changed row
before transaction 1 commits the change. If transaction 1 rolls back the
change, transaction 2 will have read a row that is considered to have
never existed.
Nonrepeatable Read Transaction 1 reads a row. Transaction 2 updates or deletes that row
and commits this change. If transaction 1 attempts to reread the row, it
will receive different row values or discover that the row has been
deleted.
Phantom Transaction 1 reads a set of rows that satisfy some search criteria.
Transaction 2 inserts a row that matches the search criteria. If
transaction 1 reexecutes the statement that read the rows, it receives a
different set of rows.
188
Database Drivers and Interfaces
FAQs:
Does PROP:LOGOUTISOLATION work only on the FILE LEVEL or is it on the Database level?
How does PROP:LOGOUTISOLATION deal with multiple tables on a transaction frame, when
one isolation level is different from another?
Isolation levels work at a connection level. So they apply to all files opened using the same
OWNER attribute.
How can you remove the ODBC cursor after a LOGOUT no matter what isolation level you
choose (i.e., GET(file,0)) - does this remove a cursor?
The ODBC cursor is maintained throughout the life of the file (e.g., until PROP:Disconnect or the
end of a thread for threaded files.)
189
Database Drivers
JOINTYPE
DRIVER('SQLDriver', '/JOINTYPE = Watcom | DB2 | Microsoft | FirstSQL | Inner | Partial |
None' )
[ Join" = ] SEND(file, '/JOINTYPE [ = Watcom | DB2 | Microsoft | FirstSQL | Inner | Partial |
None ]' )
table-ref::=
<single-table> |
<joined-table>
single-table ::=
table-name AS correlation-name
joined-table ::=
<table-ref> LEFT OUTER JOIN <single-table> ON join-condition
JOINTYPE=MICROSOFT
This is the join syntax specified by the ODBC 2.0 spec. The Base Normal Form for the relevant
ODBC spec is:
from-clause ::=
FROM <table-ref> |
FROM <odbc-joined-table>
table-ref ::=
<single-table> |
<joined-table>
single-table ::=
table-name AS correlation-name
odbc-joined-table ::=
{oj <joined-table> }
joined-table ::=
190
Database Drivers and Interfaces
JOINTYPE=WATCOM
This is the join syntax used by SQL Anywhere and is a merger of the ODBC and ANSI
specifications. The Base Normal Form for this syntax is:
from-clause ::=
FROM <table-ref> |
FROM <odbc-joined-table>
table-ref ::=
<single-table> |
<joined-table>
single-table ::=
table-name AS correlation-name
odbc-joined-table ::=
{oj <joined-table> }
joined-table ::=
<table-ref> LEFT OUTER JOIN <single-table> ON join-condition
JOINTYPE=FIRSTSQL
This is the join syntax used by FirstSQL and is not recommended to be used with any other file
format.
JOINTYPE=PARTIAL
This format supports nested outer joins with the limitation that the column names in the ON
clause of the outer join must be in the same order as their respective table names in the OUTER
JOIN clause.
The Base Normal Form for this format is:
from-clause ::=
FROM <single-table> |
FROM <odbc-joined-table>
single-table ::=
table-name AS correlation-name
odbc-joined-table ::=
{oj <joined-table> }
joined-table ::=
<single-table> LEFT OUTER JOIN <table-ref> ON join-condition |
(<joined-table>) LEFT OUTER JOIN <table-ref> ON join-condition |
table-ref ::=
<single-table> |
<joined-table>
JOINTYPE=INNER
This is a format that should work with any database, but is likely to be very slow.
JOINTYPE=NONE
191
Database Drivers
192
Database Drivers and Interfaces
MULTIPLEACTIVERESULTSETS
The ODBC and MSSQL drivers default to FALSE (using MARS (Multiple Active Result Sets))
whenever MS-SQL Server 2005 is detected. MARS is defined as the ability to have more than
one pending request under a given SQL Server connection. For most cases this will directly
translate to the ability to have more than one default result set outstanding while other operations
can execute within the same session.
If you need to enable the MARS support, set this driver string to TRUE. It can be turned on by
accessing the driver string dialog, or by using a SEND statement prior to the table being opened.
This is a connection-wide switch, which means that all files with the same OWNER will have the
same MARS support based on the first file that is opened on that connection.
If all tables are closed and a PROP:Disconnect is issued successfully, you will need to SEND the
/MULTIPLEACTIVERESULTSETS = TRUE again before the first table is opened.
When MARS is set to ON, the BusyHandling switch is still active, but should not be needed.
The driver's default behavior is to retry whenever the busy message is encountered, but a busy
message should never happen with MULTIPLEACTIVERESULTSETS on (or active).
Setting this switch ON to backends that do not support MARS have no adverse effect. The driver
will detect if the backend does not support MARS and ignore the switch in this case.
NESTING
DRIVER('SQLDriver', '/NESTING = TRUE | FALSE ' )
[ Nest" = ] SEND(file, '/NESTING [ = TRUE | FALSE ]' )
193
Database Drivers
ODBCCALL
DRIVER('SQL Driver', '/ODBCCALL = TRUE | FALSE ' )
[ Call" = ] SEND(file, '/ODBCCALL [ = TRUE | FALSE ]' )
By default (ODBCCALL = True) the SQL Accelerator reformats your CALL statements to match
the ODBC standard call syntax. To disable this automatic reformatting, set ODBCCALL=FALSE.
ORDERINSELECT
DRIVER('SQLDriver', '/ORDERINSELECT= TRUE | FALSE' )
[ OIS" = ] SEND(file, '/ORDERINSELECT [ = TRUE | FALSE ]' )
PREAUTOINC
The /PREAUTOINC driver string is used to inform the target table as to when a server side auto-
incrementing field is incremented in regards to the SQL SELECT statement when an Insert action
is active. When the string is set to TRUE, (except Oracle), the SQL code is issued after the
SELECT,. For Oracle, it is issued before the SELECT (when set to TRUE). TRUE is the driver’s
strings default setting (e.g., if it omitted, it is implicitly TRUE).
The Dictionary Editor contains a Driver String Options dialog in the Table Properties to allow easy
entry of this string.
See Also: Server side auto-incrementing values
194
Database Drivers and Interfaces
TURBOSQL
You can use this switch to simply define a buffer on the application side that will receive a
prop:sql resultset without the need to define a view with valid column name and data type.
Example:
CODE
OPEN(MyResult)
MyResult{prop:SQL} = |
'SELECT products.ProductID,products.ProductName,products.Qty from PRODUCTS'
The driver will match the resultset with the application buffer (MyResult) using the ordinal order
for the matching field.
Using the above code, the driver will assume that the resultant columns are text fields. If you
want to return binary data in the fields you will need to define your column like this:
195
Database Drivers
The TURBOSQL switch disables data collection done by the driver the first time a table is
opened. This is fine if the table is ONLY used for receiving the results of PROP:SQL calls.
However, if ANY normal Clarion I/O is done (via either views or standard Clarion File I/O calls),
this switch should not be used. If the switch is used in combination with standard Clarion I/O calls,
then the driver will have insufficient information to return properly converted data (i.e., CAST
specifications) resulting in scrambled (corrupted) data and possible GPFs.
USEINNERJOIN
DRIVER('SQLDriver', '/USEINNERJOIN= TRUE | FALSE' )
[ Join" = ] SEND(file, '/USEINNERJOIN [ = TRUE | FALSE ]' )
By default (USEINNERJOIN = True) the SQL Accelerator generates the following ANSI SQL for
inner joins:
SELECT ... FROM table1 INNER JOIN table2 ON table1.field=table2.field
However, not all backends support ANSI SQL. The driver provides an alternative syntax for inner
joins. To generate the following alternative syntax, set USEINNERJOIN=FALSE:
SELECT ... FROM table1, table2 WHERE table1.field=table2.field
UNICODE
DRIVER('SQLDriver', '/UNICODE= TRUE | FALSE' )
[ Join" = ] SEND(file, '/UNICODE[ = TRUE | FALSE ]' )
By default (UNICODE = False) all STRING fields are considered to contain ANSI characters. The
CREATE statement will attempt to create char fields, or the equivalent for the SQL backend. All
data retrieval and storage functions will inform the database server that the data being passed
contains standard ANSI characters.
If UNICODE=TRUE, then all STRING fields are considered to contain UTF-16 characters. The
CREATE statement will create an nchar (or equivalent) row with size equal to the field’s size
divided by 2. Eg STRING(20) will create an nchar(10). All data retrieveal and storage functions
will inform the database server that the data being passed contains UTF-16 characters.
To enable UNICODE support for a single field, use the “| UNICODE” NAME modifier for the field.
Clarion pads all STRING fields with spaces. It is the responsibility of the programmer to make
sure that any STRING field that the driver treats as UNICODE is padded with UNICODE spaces
(U+0020). Due to Windows use of little-endian, a UNICODE space is <020H><00H>. If you do
not pad your string with UNICODE spaces, the server will interpret the end of your string as being
padded with the UNICODE character U+2020(†).
196
Database Drivers and Interfaces
VERIFYVIASELECT
DRIVER('SQL Driver', '/VERIFYVIASELECT = TRUE | FALSE' )
[ Verify" = ] SEND(file, '/VERIFYVIASELECT [ = TRUE | FALSE ]' )
VERIFYVIASELECT lets the SQL Driver use an alternative, sometimes faster, method to validate
fields when opening a table. By default (VERIFYVIASELECT=FALSE), the SQL Driver uses the
SQLColumns function to validate fields. However, some backends (particularly SQL Anywhere)
can validate fields faster using a SELECT statement. To verify fields using the SELECT
statement, set VERIFYVIASELECT to TRUE.
VERIFYVIASELECT defaults to TRUE for SQL Anywhere backends.
197
Database Drivers
The SQL Accelerator drivers automatically build SQL WHERE clauses when your Clarion code
contains a SET followed by a NEXT or PREVIOUS. You can customize the driver generated
WHERE clause by using the WHERE driver string. You can also set the WHERE driver string at
runtime with the use of PROP:WHERE. PROP:WHERE is a write-only property.
The SEND must be executed after the SET statement and before the NEXT or PREVIOUS
statement.
The SET statement clears any WHERE clause set by the SEND statement.
Because the SQL driver's generated SELECT statement is not compiled until the NEXT or
PREVIOUS statement, the SEND function posts no error code and returns no result. For
example:
Orders FILE,PRE(Ord),DRIVER('ODBC'),NAME('Ord')
NameDate KEY(+Ord:NameId,-Ord:Date)
Record RECORD
Name STRING(12),NAME('NameId')
Date DATE,NAME('OrderDate')
Type STRING(1),NAME('OrderType')
Details STRING(20),NAME('OrderDetails')
END
END
CODE
Ord:Name = 'SMITH'
SET(Ord:NameDate,Ord:NameDate)
SEND(Orders, '/WHERE OrderType = "M"')
LOOP
NEXT(Orders)
!...some processing
END
198
Database Drivers and Interfaces
ZERODATE
ZERODATE defines how the target driver should generate a WHERE clause for cleared DATE
and TIME fields and replaces the /ZEROISNULL driver string.
ZERODATE=NULL is equivalent to ZEROISNULL=TRUE and is the default behavior.
ZERODATE=0 is equivalent to ZEROISNULL=FALSE.
ZERODATE=1 indicates that a cleared date will be generated as 01/01/0001 and a cleared time
is generated as 0.
ZERODATE=yyyymmdd indicates that a cleared date will be generated as mm/dd/yyyy and a
cleared time is generated as 0.
If both ZERODATE and ZEROISNULL are specified in the driver string, the last one will be used.
If you use the driver string editor in the dictionary editor, it will automatically convert
ZEROISNULL to the equivalent ZERODATE.
This driver string is meant for how the field is updated and how it is retrieved. When you do a
SET(key,key) on a key with a date component that has been cleared, the driver uses this setting
to generate the SELECT .. WHERE clause.
For example:
199
Database Drivers
ZEROISNULL
DRIVER(''SQLDriver'', '/ZEROISNULL = TRUE | FALSE' )
[ Nulls" = ] SEND(file, '/ZEROISNULL [ = TRUE | FALSE ]' )
200
Database Drivers and Interfaces
201
Database Drivers
202
Database Drivers and Interfaces
PROP:Alias
PROP:Alias is a read/write file property that sets or returns the alias the SQL Accelerator driver
uses when generating SELECT statements for a view. It will return an empty string if PROP:Alias
has not previously been called to set the alias. PROP:Alias only returns a value previously set
using PROP:Alias. For example:
Customer{PROP:Alias} = 'C' !set new table alias
OldAlias" = Customer{PROP:Alias} = '' !use default alias
If you have not used PROP:Alias to set the alias of a file, the SQL driver generates an SQL
statement which uses an Alias of "A" for the first file in the View, "B" for the second etc. If you
wish to use the SQL() directive in Prop:Filter, your filter has to be compatible with the previously
generated SQL statement – e.g., you need use A/B/etc. as the file prefixes.
Setting a file's property will set it for as long as that file is in scope. For non-threaded files this
means for the duration of the program. For threaded files it means for the duration of the thread.
You can use file{PROP:Alias} to specify what alias the driver should use when constructing
SELECT statements for views.
If the file has the THREAD attribute, then it refers to the current thread. If it does not, then it is
global.
See Also: PROP:SQL
PROP:AlwaysRebind
PROP:AlwaysRebind sets or returns the toggle that controls whether the SQL Accelerator
rebinds memory locations when a NULL state changes.
For all backends except MSSQL, PROP:AlwaysRebind defaults to 0 or False, so the SQL driver
does not rebind memory locations when a NULL state changes. However, some SQL backends
(including MSSQL) do not recheck the null state, so they must have the memory location rebound
to force the change of null state. Setting PROP:AlwaysRebind to 1 or True tells the SQL
Accelerator to do this extra binding.
PROP:ConnectString
PROP:ConnectString returns an SQL database's connection information. For example:
AFileOwner STRING(256)
AFile FILE,DRIVER('ODBC'),OWNER(AFileOwner)
CODE
AFileOwner='DataSource'
OPEN(Afile)
IF NOT ERRORCODE()
AFileOwner=AFile{PROP:ConnectString}
END
203
Database Drivers
PROP:DBMSver
Good for all SQL Drivers except Oracle.
File{PROP:DBMSver} returns a character string indicating the version of the DBMS accessed by
the driver. The version is of the form ##.##.####, where the first two digits are the major version,
the next two digits are the minor version, and the last four digits are the release version.
PROP:Details
See the Details switch described in the Debugging Your SQL Application section.
Details=1 tells the driver to include record buffer contents in the log file; however, if the file is
encrypted, you must turn on both the Details switch and the ALLOWDETAILS switch to log record
buffer contents (see ALLOWDETAILS). Details=0 tells the driver to omit record buffer contents.
The Profile switch must be turned on for the Details switch to have any effect.
PROP:Disconnect
PROP:Disconnect CLOSEs any open files in the target file's database, then disconnects the
application from the database.
Example:
PROP:DriverTracing
If this property is set to '', then all driver tracing for all file drivers is disabled. No INI file or
registry entry will be read. However file specific settings set via SEND commands or file
property settings will still take effect.
Example:
SYSTEM{PROP:DriverTracing} = '' !disable all driver tracing
SYSTEM{PROP:DriverTracing} = '1' !enable all driver tracing
204
Database Drivers and Interfaces
PROP:GroupBy, PROP:Having
The SQL view engine supports PROP:GroupBy and PROP:Having. These properties allow you
to add respectively GROUP BY and HAVING clauses to your SELECT statement. Note that
PROP:GroupBy must be set first to allow PROP:Having to be generated.
Example:
PROGRAM
MAP
END
EMP FILE,DRIVER('ORACLE'),NAME('EMP'),PRE(EMP)
P_EKY_EMP KEY(EMP:EMPNO),NOCASE,OPT,PRIMARY
KEY_DEP KEY(EMP:DEPTNO),DUP,NOCASE,OPT
Record RECORD
EMPNO SHORT !Emp-no
ENAME CSTRING(11) !Employee name
JOB CSTRING(10) !Job
HIREDATE DATE !Hiredate
MGR SHORT !Manager
SAL PDECIMAL(7,2) !Salary
COMM PDECIMAL(7,2) !Commisison
DEPTNO BYTE
END
END
MyView VIEW(EMP)
PROJECT(EMP:Mgr)
PROJECT(EMP:Sal)
END
CODE
OPEN(EMP)
OPEN(MyView)
MyView{'EMP:Sal',PROP:Name} = 'sum(sal)'
MyView{PROP:GroupBy} = 'Mgr'
MyView{PROP:Having} = 'sum(sal) > 100000'
SET(MyView)
NEXT(MyView)
The example code above is the equivalent to "SELECT mgr, sum(sal) FROM EMP GROUP BY
mgr HAVING sum(sal) > 100000"
In other words, this code will return a list of all Manager IDs and the total salary of their
subordinates if their subordinates make a total of more than 100000.
205
Database Drivers
PROP:hdbc
PROP:henv
PROP:Hint
The HINT driver string is valid for Oracle and MS-SQL drivers..
PROP:hstmt
PROP:Inner
PROP:Inner is a writable property for SQL Accelerator drivers. This is useful for testing the ODBC
USEINNERJOIN driver string. See PROP:Inner in the Language Reference for more information.
PROP:INNER is read-only for non-SQL views and read/write for SQL based views.
PROP:IsolationLevel
206
Database Drivers and Interfaces
PROP:LogonScreen
PROP:LogonScreen sets or returns the value that determines whether the driver automatically
prompts for logon information. By default, PROP:LogonScreen=TRUE, and the driver displays a
logon window if no connect string is supplied. If set to FALSE, and there is no connect string, the
OPEN(file) fails and FILEERRORCODE() returns a driver specific error code. For example:
AFile FILE,DRIVER('SQLAnywhere')
!file declaration with no userid and password
END
CODE
AFile{PROP:LogonScreen}=True !enable auto login screen
OPEN(Afile)
In the above example, the logon screen uses the SQLAnywhere Connect dialog. Consult your
specific database documentation for more information on this dialog. The end-user's ability to use
the connect dialog will depend on the security surrounding the specific database. For example,
the end-users may have access rights to a named database that they can access with the
database’s client software, but they may not have access rights to other files that comprise the
database.
PROP:Log
PROP:Log writes a designated string value to the log file. For example:
AFile FILE,DRIVER('ODBC'),OWNER('DataSource')
CODE
OPEN(Afile)
IF NOT ERRORCODE()
AFile{PROP:Log}='AFile opened:'&CLOCK()
END
PROP:LogFile
207
Database Drivers
PROP:LoginTimeout
PROP:LogSQL
A FILE property specifically used for SQL based tables, and turns on or off logging of calls to the
backend for SQL drivers. A value of 1 turns on logging, a value of 0 turns off logging.
Example:
filelabel{PROP:LogSQL} = 1 !turn on logging
filelabel{PROP:LogSQL} = 0 !turn off logging
PROP:MaxStatements
PROP:MaxStatements sets or returns the maximum amount of SQL statements that can be
generated (open) on a single connection. A connection must be active before implementing this
property.
number = file{PROP:MaxStatements} !return allowable
file{PROP:MaxStatements} = 32767 !set allowable
208
Database Drivers and Interfaces
to change the field's name in the generated SQL. This is normally a name that will be used for a
field in a SELECT statement.
Example:
PROGRAM
MAP
END
EMP FILE,DRIVER('ORACLE'),NAME('EMP'),PRE(EMP)
P_EKY_EMP KEY(EMP:EMPNO),NOCASE,OPT,PRIMARY
KEY_DEP KEY(EMP:DEPTNO),DUP,NOCASE,OPT
Record RECORD
EMPNO SHORT !Emp-no
ENAME CSTRING(11) !Employee name
JOB CSTRING(10) !Job
HIREDATE DATE !Hiredate
MGR SHORT !Manager
SAL PDECIMAL(7,2) !Salary
COMM PDECIMAL(7,2) !Commisison
DEPTNO BYTE
END
END
v VIEW(EMP)
PROJECT(EMP:EmpNo)
END
CODE
OPEN(EMP)
OPEN(v)
CODE
OPEN(EMP)
OPEN(v)
v{PROP:Order}=SQL(1)
v{'EMP:EmpNo',PROP:NAME} = 'count(*)'
SET(v)
NEXT(v)
MESSAGE(EMP:EmpNo)
This example will produce the equivalent of "SELECT count(*) FROM EMP".
209
Database Drivers
PROP:OrderAllTables
Setting PROP:OrderAllTables to True forces the SQL Accelerator driver to use linking fields and
secondary files' key component fields, as well as the primary file's key component fields, in the
ORDER BY clause it sends to the server. You may need this switch if you are using a Clarion
VIEW that joins multiple tables. By default (View{PROP:OrderAllTables}=FALSE), the SQL
Accelerator driver includes only the primary file's key components in the ORDER BY clause it
sends to the SQL server. For example:
BRW1::View:Browse VIEW(Customer)
PROJECT(CUST:CustNo)
PROJECT(CUST:Name)
PROJECT(CUST:Zip)
PROJECT(CUST:CustNo)
JOIN(ORD:ByCustomer,CUST:CustNo)
PROJECT(ORD:OrderNo)
PROJECT(ORD:OrderDate)
END
END
CODE
?BRW1::View:Browse{PROP:OrderAllTables} = TRUE
PROP:OrderInSelect
(NOTE: Not valid for ORACLE Accelerator)
Some SQL backends require that any fields used in the ORDER BY clause also appear in the
SELECT statement. By setting this property to TRUE (1) the driver will make sure that this rule is
applied for all views regardless of the fields that you project.
PROP:Profile
When you are tracing file driver activity and writing actions to an external log file, setting
PROP:Profile to a valid logfile name alerts the driver to include Clarion I/O statements in the log
file. Also, see the Profile switch described in the Debugging Your SQL Application section.
In the DRIVERS.INI file in the CSIDL_APPDATA\SoftVelocity\Clarion\<clarion_version> folder,
Profile=1 tells the driver to include the Clarion I/O statements in the log file; Profile=0 tells the
driver to omit Clarion I/O statements. The Profile switch must be turned on for the Details switch
(described below) to have any effect.
Details=1 tells the driver to include record buffer contents in the log file; however, if the file is
encrypted, you must turn on both the Details switch and the /ALLOWDETAILS switch to log
record buffer contents (see ALLOWDETAILS). Details=0 tells the driver to omit record buffer
contents. The Profile switch must be turned on for the Details switch to have any effect.
/ALLOWDETAILS is only valid as a parameter of the DRIVER attribute (Driver Options field
in the File Properties dialog). It is not valid with the SEND command.
See Also: PROP:Details , PROP:LOG , PROP:LOGSQL
210
Database Drivers and Interfaces
PROP:QuoteString
(NOTE: Not valid with Oracle Accelerator.)
PROP:QuoteString sets or returns the column name delimiter (typically a quote) that the SQL
Accelerator Driver uses to surround column names within its generated SQL statements. Different
backends require different delimiter characters.
You can use PROP:QuoteString to build your own dynamic SQL statements. Note that you must
enclose any column names that are also SQL reserved words in the correct delimiter character.
See Using Embedded SQL.
Some backends do not correctly return the delimiter character. For those backends you should
set the value of PROP:QuoteString before using it.
PROP:ServerCaseInsensitive
In previous versions of Clarion, the SQL file drivers assumed that your SQL server was set up to
support case sensitive searches. This required a modification of all case insensitive keys defined
in the data dictionary to achieve optimum performance.
The SQL drivers now assume that the server is set up with case insensitive searches, and no
longer generate UPPER calls in the SQL code when requested by the Clarion code. To turn off
this behavior (force generation of UPPER calls), use PROP:ServerCaseInsensitive. When this
file property is active (1), you will make the file driver behave as in previous versions (prior to 6.3).
This property only needs to be set once per connection and can only be done after a connection
to the database has been established
Example:
Customer{PROP:ServerCaseInsensitive} = 1
!server searches are now case insensitive.
211
Database Drivers
PROP:SQL
You can use Clarion's property syntax (PROP:SQL) to execute SQL statements in your program
code by using PROP:SQL and naming the FILE or imported SQL VIEW in the data dictionary as
the target within the normal execution of your program. This is only valid when using an SQL file
driver (such as the ODBC, Scalable SQL, or Oracle drivers). You can send any SQL statements
supported by the SQL server.
This capability lets your program do backend operations independent of the SQL Accelerator
driver's generated SQL. For example, multi-record updates can often be accomplished more
efficiently with a single SQL statement than with a template generated Process procedure that
updates one record at a time. In cases like these it makes sense for you to take control and send
custom SQL statements to the backend, and PROP:SQL lets you do this.
If you issue an SQL statement that returns a result set (such as an SQL SELECT statement), you
use NEXT(file) to retrieve the result set one row at a time, into the file's record buffer. The FILE
declaration receiving the result set must have at least the same number of fields as the SQL
SELECT statement returns. If the Clarion ERRORCODE procedure returns 90, the
FILEERRORCODE() and FILEERROR() functions return any error code and error message set
by the back-end SQL server. In order to return a valid result set, you must also begin your
statement with either SELECT or CALL. If you need to return a result set and your statement
does not begin with either SELECT or CALL, then use PROP:SQLRowSet
You may also query the contents of PROP:SQL to get the last SQL statement issued by the file
driver.
Example:
SQLFile{PROP:SQL}='SELECT field1,field2 FROM table1' |
& 'WHERE field1 > (SELECT max(field1)' |
& 'FROM table2' !Returns a result set you
! get one row at a time
! using NEXT(SQLFile)
212
Database Drivers and Interfaces
SEND
You can also use the Clarion SEND procedure to send an SQL command to the backend
database. This is provided for backward compatibility with early versions of Clarion. We
recommend using the property syntax to send SQL statements to the backend database.
Example:
SEND(SQLFile,'SELECT field1,field2 FROM table1' |
& 'WHERE field1 > (SELECT max(field1)' |
& 'FROM table2') ! Returns a result set you
! get one row at a time
! using NEXT(SQLFile)
SQL does a good job of handling batch processing procedures such as: printing reports,
displaying a screen full of table rows, or updating a group of table rows.
The SQL Accelerator drivers take full advantage of this when browsing a table or printing.
However, they do not always use it to its best advantage with the Process template or in code
which loops through a table to update multiple records. Therefore, when doing batch updates to a
table, it can be much more efficient to execute an embedded SQL statement than to rely on the
code generated by the Process template.
For example, to use PROP:SQL to increase all Salesman salaries by 10% you could:
SQLFile FILE,DRIVER('Oracle'),NAME(SalaryFile)
Record RECORD
SalaryAmount PDECIMAL(5,2),NAME('JOB')
END
END
CODE
SqlFile{PROP:SQL} = 'UPDATE SalaryFile SET '&|
'SALARY=SALARY * 1.1 WHERE JOB=''S'''
The names used in the SQL statement are the SQL table names, not the Clarion field names.
See Also: Using Embedded SQL, PROP:SQLRowSet.
213
Database Drivers
PROP:SQLFilter
Although still valid in this release, this statement should be replaced by the more versatile SQL()
statement.
You can use PROP:SQLFilter to filter your VIEWs using native SQL code rather than Clarion
code. This is only appropriate when using an SQL file driver (such as the ODBC, Scalable SQL,
or Oracle drivers). If the first character of the PROP:SQLFilter expression is a plus sign (+), the
PROP:SQLFilter expression is appended to any existing PROP:Filter expression and both are
used. Omitting the plus sign replaces the existing PROP:Filter expression with the
PROP:SQLFilter.
When you use PROP:SQLFilter, the SQL filter is passed directly to the server. As such it cannot
contain the names of tables, variables, or functions that the server is not aware of; that is the filter
expression must be valid SQL syntax with valid SQL table and column names. For example:
View{PROP:SQLFilter} = 'Date = TO_DATE(''01-MAY-1996'',''DD-MON-YYYY'')'
or
View{PROP:SQLFilter} = 'StrField LIKE ''AD%'''
Note that the SQL Accelerator incorporates the PROP:SQLFilter expression into the WHERE
clause of a generated SELECT statement. The generated SELECT statement may reference one
or more tables by aliases. If your filter also references tables (e.g., Customer.Name < 'T'), you
must use the same alias names generated by the SQL Accelerator. By default, the SQL
Accelerator uses the next letter of the alphabet as the alias name. For example, the Accelerator
uses 'A' as the alias for the first table in the generated SELECT statement, then 'B' for the next
table, and so on. You can use PROP:Alias to control the alias names generated by the SQL
Accelerator. See PROP:Alias for more information.
When you append the SQL filter by using the plus sign, the logical end result of the filtering
process is (View Filter) AND (SQL Filter).
Omit the plus sign (+) to replace the Clarion filter with the SQL filter. When you replace the
Clarion filter with the SQL filter by omitting the plus sign, the logical end result of the filtering
process is simply (SQL Filter).
See Also: PROP:Filter for additional information.
214
Database Drivers and Interfaces
PROP:SQLJoinExpression
You can use PROP:SQLJoinExpression to structure your VIEWs using native SQL code rather
than Clarion code.
When you concatenate the SQL join by using the plus sign, the result set contains first the Clarion
joined values, then the SQL joined values.
Omit the plus sign (+) to replace the Clarion join expression with the SQL join expression.
PROP:SQLJoinExpression only affects the JOIN portions of the VIEW declaration; it does
not affect the PROJECT portions.
215
Database Drivers
PROP:SQLOrder
You can use PROP:SQLOrder to sort your VIEWs using native SQL code rather than Clarion
code.
Note that the SQL Accelerator incorporates the PROP:SQLOrder expression into the ORDERBY
clause of a generated SELECT statement. The generated SELECT statement may reference one
or more tables by aliases. If your order expression also references tables (e.g., Customer.Name <
'T'), you must use the same aliase names generated by the SQL Accelerator. By default, the
SQL Accelerator uses the next letter of the alphabet as the alias name. For example, the
Accelerator uses 'A' as the alias for the first table in the generated SELECT statement, then 'B' for
the next table, and so on. You can use PROP:Alias to control the alias names generated by the
SQL Accelerator. See PROP:Alias for more information.
When you append the SQL order by using the plus sign, the result set is ordered first by the
Clarion order expression, then by the SQL order expression.
Omit the plus sign (+) to replace the Clarion order with the SQL order.
See Also: PROP:Order
216
Database Drivers and Interfaces
PROP:SQLRowSet
You can use Clarion's property syntax (PROP:SQLRowSet) to execute SQL statements that
return result sets in your program code by using PROP:SQLRowSet and naming the FILE or
imported SQL VIEW in the data dictionary as the target within the normal execution of your
program. This is only valid when using an SQL file driver (such as the ODBC, Scalable SQL, or
Oracle drivers). You can send any SQL statements that return results supported by the SQL
server.
After issuing the SQL statement, you use NEXT(file) to retrieve the result set one row at a time,
into the file's record buffer. The FILE declaration receiving the result set must have at least as
many fields as the SQL SELECT statement returns. If the Clarion ERRORCODE procedure
returns 90, the FILEERRORCODE() and FILEERROR() functions return any error code and error
message set by the back-end SQL server.
Example:
SQLiteFile{PROP:SQLRowSet}='PRAGMA table_list' ! get the list of tables in file
LOOP
NEXT(SQLiteFile)
…
END
f{PROP:SQLRowSet} = 'WITH q AS (SELECT COUNT(*) FROM f) SELECT * FROM q'
NEXT(f)
The names used in the SQL statement are the SQL table names, not the Clarion field names.
See Also: Using Embedded SQL, PROP:SQLRowSet.
217
Database Drivers
PROP:TraceFile
SYSTEM{PROP:TraceFile} = INIFilename
A SYSTEM property that specifies the INI file that file drivers will read to get driver tracing settings
from. The drivers will look in the [CW<drivername>] section for specific settings.
These properties must be set before ANY file I/O calls are done.
PROP:TraceKey
SYSTEM{PROP:TraceKey} = keyName
A SYSTEM property that specifies the Registry key that the file drivers will read to get driver
tracing settings from. The drivers will look at entries in the keyName\<driverName> key for
driver tracing settings.
These properties must be set before ANY file I/O calls are done.
218
Database Drivers and Interfaces
MSSQL Accelerator
Overview
MSSQL Server
For complete information on the MSSQL database system, please review Microsoft's SQL Server
documentation.
MSSQL Accelerator
The MSSQL Accelerator is one of several SoftVelocity SQL Accelerator drivers. These SQL
Drivers share a common code base and many common features such as SoftVelocity's unique,
high speed buffering technology, common driver strings, and SQL logging capability. See SQL
Accelerators for information on these common features.
The MSSQL Accelerator converts standard Clarion file I/O statements and function calls into
optimized SQL statements, which it sends to the backend MSSQL server for processing. This
means you can use the same Clarion code to access both MSSQL tables and other file systems
such as TopSpeed files. It also means you can use Clarion template generated code with your
SQL databases.
All the common behavior of all the SQL Accelerators is documented in the SQL Accelerators
section. The MSSQL Accelerator is based on the ODBC Accelerator and inherits all features of
the ODBC Accelerator. All the common behavior of the SQL Accelerators that are derived from
the ODBC Accelerator is documented in the ODBC Accelerator section. All behavior specific to
this driver is noted here.
219
Database Drivers
If you are using a Trusted Connection (Integrated NT Security), you must establish a
connection to the NT workstation running the MSSQL Server before you can connect to
the MSSQL database and import table definitions. You can verify your connection by
running the MSSQL ISQL_w Server utility installed with your MSSQL Client software.
Fill in the following fields in the Login/Connection dialog:
Servername Select the workstation running the MSSQL database to import from. If the
Servername list is empty, you may type in the name. See your DBA or
network administrator for information on how the server is specified.
Username For Standard Security, type your MSSQL Username. For Trusted Security
(Integrated NT Security) no Username is required. See your server
documentation or your DBA for information on applicable Usernames and
security methods.
Password For Standard Security, type your MSSQL Password. For Trusted Security
(Integrated NT Security) no Password is required. See your server
documentation or your DBA for information on applicable Passwords and
security methods.
Database Select the MSSQL database that contains the tables or views to import. If
the Database list is empty, you may type in the name. See your server
documentation or your DBA for information on database names.
Filter Optionally, provide a filter expression to limit the list of tables and views to
import. The filter expression queries the dbo.sysobjects table. The filter
expression is limited to 1024 characters in length.Tip: The filter is case
sensitive, so type your filter value accordingly.
220
Database Drivers and Interfaces
Following is a list of the column names (and their Clarion datatypes) you can reference in your
filter expression. Generally, filtering on MSSQL system tables requires not only an intimate
knowledge of the MSSQL system tables, but also of the MSSQL stored procedures. For example,
to filter on table owner:
uid = user_id('DBO')
See your SQL server documentation for information on the MSSQL system tables and stored
procedures.
name CSTRING(31)
id LONG
uid SHORT
type STRING(2)
userstat SHORT
sysstat SHORT
indexdel SHORT
schema_ver SHORT
refdate STRING(8)
crdate STRING(8)
version LONG
deltrig LONG
Instrig LONG
updtrig LONG
Seltrig LONG
category LONG
Cache SHORT
Next > Press this button to open the Import Wizard's Import List dialog.
221
Database Drivers
You can use the Clarion Enterprise Edition Dictionary Synchronizer to import an entire
database, including table relationships, in a single pass.
222
Database Drivers and Interfaces
Type an exclamation point (!) followed by a variable name in the Owner Name field to
specify a variable rather than hard coding the OWNER attribute . For example:
!GLO:SQLOwner.
223
Database Drivers
This error happens when using SQL managed client tries to connect to a server using TCP/IP
and the default port used by the managed client is wrong. Set up the correct port name using the
MSSQL configuration utility.
224
Database Drivers and Interfaces
225
Database Drivers
MyFile FILE,DRIVER('MSSQL')
Record RECORD
c LONG
END
END
Ret LONG
In SHORT(10)
Out STRING(10)
CreateReq BYTE(FALSE)
CODE
BIND('Ret',Ret)
CheckError('BIND Ret')
BIND('Out',Out)
CheckError('BIND Out')
BIND('In',In)
CheckError('BIND In')
226
Database Drivers and Interfaces
NEXT(MyFile)
CheckError('Next SProc2')
!Call Stored Procedure passing input values, return output parameter
CallProc('&Ret = CALL SFunc2(7, '')'')')
LOOP WHILE ~ERRORCODE()
NEXT(MyFile)
END
IF Ret ~= VAL(')')+7
MESSAGE('out of SFunc2 =' & out)
END
MESSAGE('Done')
227
Database Drivers
MESSAGE(Msg & ' ' & ERRORCODE() & ':' & ERROR())
END
END
228
Database Drivers and Interfaces
PROGRAM
MAP
CheckError(STRING) !Check for errorcodes
CallProc(STRING) !Call Stored Procedure
END
MyFile FILE,DRIVER('MSSQL'),NAME('SProctable')
Record RECORD
c LONG
END
END
Ret LONG
In SHORT(10)
Out STRING(10)
CreateReq BYTE(FALSE)
CODE
BIND('Ret',Ret)
CheckError('BIND Ret')
BIND('Out',Out)
CheckError('BIND Out')
BIND('In',In)
CheckError('BIND In')
229
Database Drivers
CallProc('CALL SProc2(&in[IN])')
NEXT(MyFile)
CheckError('Next SProc2')
ret = 0
!Call Stored Procedure passing input values, return output parameter
CallProc('&Ret = CALL SFunc2(7, '')'')')
IF Ret ~= 0
MESSAGE('out of SFunc2 before fetches =' & Ret)
END
LOOP WHILE ~ERRORCODE()
NEXT(MyFile)
END
230
Database Drivers and Interfaces
IF Ret ~= VAL(')')+7
MESSAGE('out of SFunc2 =' & Ret)
END
MESSAGE('Done')
!Check for errorcodes
CheckError PROCEDURE(Msg)
CODE
IF ERRORCODE()
IF ERRORCODE() = 90
HALT(1, Msg & ' ' & FILEERRORCODE() & ':' & FILEERROR())
ELSE
HALT(1, Msg & ' ' & ERRORCODE() & ':' & ERROR())
END
END
231
Database Drivers
A forward slash preceeds all SQL Accelerator driver strings. The slash allows the driver to
distinguish between driver strings and SQL statements sent with SEND.
In addition to the standard SQL Driver Strings, the MSSQL Accelerator supports the following
Driver Strings:
AUTOINCUSESSCOPEIDENTITY
HINT
LOGONSCREEN
GATHERATOPEN
SAVESTOREDPROC
TRUSTEDCONNECTION
232
Database Drivers and Interfaces
AUTOINCUSESSCOPEIDENTITY
MSSQL has three ways of returning the auto-incremented field: @@IDENTITY,
SCOPE_IDENTITY() and IDENT_CURRENT( 'table_name' ). All have problems.
IDENT_CURRENT( 'table_name' ) is pretty useless as it returns the current identity regardless of
which user last updated the table. So as soon as another user does an ADD between the calls to
ADD and getting IDENT_CURRENT you get the wrong value.
@@IDENTITY gives you the last identity value set by this connection. This works fine unless you
have an insert trigger that inserts other records that have identity fields. Then you end up getting
the identity field for the wrong table. The default server side auto increment system uses this
variable.
SCOPE_IDENTITY() returns the identity set by the statement executed on this statement handle.
Before Clarion 10, the file driver could not use this because the INSERT statement executed by
the driver and the SELECT used to retrieve the incremented value where executed on different
statement handles. So SCOPE_IDENTITY() always returned 0.
As of Clarion 10, If you add the driver string /AUTOINCUSESSCOPEIDENTITY=TRUE to the
driver string of a file, the driver will use SCOPE_IDENTITY() using the same statement handle as
the INSERT to retrieve the auto-incremented value.
Example:
tzi FILE,DRIVER('MSSQL','/AUTOINC=''SELECT @@identity''
/TRUSTEDCONNECTION=TRUE'),PRE(tzi),OWNER(ownerVariable),NAME('tz')
pk KEY(tzi:id)
RECORD
Id LONG
Name STRING(20)
END
END
tzs FILE,DRIVER('MSSQL','/ AUTOINCUSESSCOPEIDENTITY=TRUE
/TRUSTEDCONNECTION=TRUE'),PRE(tzs),OWNER(ownerVariable),NAME('tz')
pk KEY(tzs:id)
RECORD
Id LONG
Name STRING(20)
END
END
CODE
tzi{PROP:SQL} = 'DROP TABLE TZ'
tzi{PROP:SQL} = 'DROP TABLE TY'
tzi{PROP:SQL} = 'CREATE TABLE TZ (id int IDENTITY(1,1) PRIMARY KEY, name
varchar(20) NOT NULL)'
tzi{PROP:SQL} = 'CREATE TABLE TY (id int IDENTITY(100,5) PRIMARY KEY, name
varchar(20) NOT NULL)'
tzi{PROP:SQL} = 'CREATE TRIGGER Ztrig ON TZ FOR INSERT AS BEGIN INSERT TY
VALUES ('''') END'
OPEN(tzi)
tzi{PROP:ServerAutoInc, 1} = 1
OPEN(tzs)
tzs{PROP:ServerAutoInc, 1} = 1
tzi:name = 'Lisa'
ADD(tzi)
tzi:name = 'Mike'
ADD(tzi)
tzi:name = 'Carla'
ADD(tzi)
tzi{PROP:ServerAutoInc} = 1
tzi:name = 'Rosalie'
ADD(tzi)
233
Database Drivers
HINT
You can tell MSSQL Accelerator to generate MSSQL hints by using the HINT driver string,
DRIVER ('MSSQL','/HINT=hint')
with SEND,
SendReturn = SEND (file,' /HINT=[&]hint')
The square brackets [] above are used to show that the ampersand (&) is optional.
You can either override the base hint or concatenate a hint. If the first character after the = in the
KEY hint is an ampersand (&), MSSQL Accelerator concatenates the hint onto the FILE hint,
otherwise it overrides the FILE hint.
If the first character after the = in the SEND hint is an ampersand (&) or the first character of a
hint property is an ampersand, MSSQL Accelerator concatenates the hint onto the current hint
(the FILE hint and the KEY hint), otherwise it overrides the FILE and KEY hint.
You can also use PROP:Hint to return the hint that is in use (or will be in use if called after a SET,
but before the first NEXT or PREVIOUS statement.)
Example:
AFile DRIVER('MSSQL','/hint=COST')
AKey KEY(field),NAME('KeyName /HINT=&FIRST_ROWS')
SEND(AFile,'/HINT=FIRST_ROWS')
AFile{PROP:Hint} = 'FIRST ROWS'
234
Database Drivers and Interfaces
TRUE forces the driver to gather most of the field information when the file is opened, which
avoids a slowdown during program execution.
235
Database Drivers
To set the connection type, you must issue the TRUSTEDCONNECTION switch before the
connection is made to the server.
236
Database Drivers and Interfaces
The automatic logon screen lets prompts for the following connection information. Consult your
MSSQL documentation for more information on these prompts:
237
Database Drivers
CREATE Y
NAME Y
ENCRYPT N
OWNER(password) Y1
RECLAIM N
PRE(prefix) Y
BINDABLE Y
THREAD Y
EXTERNAL(member) Y
DLL([flag]) Y
OEM N
LOCALE N
INDEX Y
KEY Y
MEMO N
BLOB Y
RECORD Y
BINARY N
DUP Y
NOCASE Y
OPT N
238
Database Drivers and Interfaces
PRIMARY Y
NAME Y
Ascending Components Y
Descending Components Y
Mixed Components Y
DIM N
OVER Y
NAME Y
BOF(file) N
BUFFER(file) Y
BUILD(file) Y
BUILD(key) Y
BUILD(index) Y3
BUILD(index, components) Y3
BYTES(file) Y
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) Y
DUPLICATE(key) Y
EMPTY(file) Y
EOF(file) N
FLUSH(file) N
LOCK(file) N
239
Database Drivers
NAME(label) Y
PACK(file) N
POINTER(file) N
POINTER(key) N
POSITION(file) N
POSITION(key) Y
RECORDS(file) Y
RECORDS(key) Y
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) N
UNLOCK(file) N
ADD(file) Y
ADD(file, length) N
APPEND(file) Y
APPEND(file, length) N
DELETE(file) Y
GET(file,key) Y
GET(file, filepointer) N
GET(key, keypointer) N
HOLD(file) N
NEXT(file) Y
240
Database Drivers and Interfaces
NOMEMO(file) N
PREVIOUS(file) Y
PUT(file) Y
PUT(file, filepointer) N
RELEASE(file) N
REGET(file,string) N
REGET(key,string) Y
RESET(file,string) N
RESET(key,string) Y
SET(file) Y
SET(file, key) N
SET(file, filepointer) N
SET(key) Y
SET(key, key) Y
SET(key, keypointer) N
SKIP(file, count) Y
WATCH(file) Y
COMMIT Y
ROLLBACK Y
NULL(field) Y
SETNULL(field) Y
SETNULL(file,field) Y
241
Database Drivers
SETNONNULL(field) Y
Notes
1 We recommend using a variable password that is lengthy and contains special characters
because this more effectively hides the password value from anyone looking for it. For
example, a password like "dd....#$...*&" is much more difficult to "find" than a password
like "SALARY."
{bmc TipBox.BMP}
To specify a variable instead of the actual password in the Owner Name field of the
File Properties dialog, type an exclamation point (!) followed by the variable name.
For example: !MyPassword.
2 See also PROP:LOGOUT in the Language Reference.
3 BUILD(index) sets internal driver flags to guarantee the driver generates the correct
ORDER BY clause. The driver does not call the backend server.
4 Whether LOGOUT also LOCKs the table depends on the server's configuration for
transaction processing. See your server documentation.
242
Database Drivers and Interfaces
If you are using a Trusted Connection (Integrated NT Security), you must establish a
connection to the NT workstation running the MSSQL Server before you can connect to
the MSSQL database and import table definitions. You can verify your connection by
running the MSSQL ISQL_w Server utility installed with your MSSQL Client software.
Fill in the following fields in the login dialog:
Host Select the workstation running the MSSQL database to import from. If
the Host list is empty, you may type in the name. See your DBA or
network administrator for information on how the host is specified.
Database Select the MSSQL database that contains the tables or views to
import. If the Database list is empty, you may type in the name. See
your server documentation or your DBA for information on database
names.
Username For Standard Security, type your MSSQL Username. For Trusted
Security (Integrated NT Security) no Username is required. See your
server documentation or your DBA for information on applicable
Usernames and security methods.
Password For Standard Security, type your MSSQL Password. For Trusted
Security (Integrated NT Security) no Password is required. See your
server documentation or your DBA for information on applicable
Passwords and security methods.
Include Select this option to include system tables in the list of importable
System Files objects.
Exclude Select this option to exclude system tables from the list of importable
System Files objects.
Other Filter Select this option to provide a filter expression to limit the list of tables
and views to import. The filter expression queries the dbo.sysobjects
table. The filter expression is limited to 1024 characters in length.
243
Database Drivers
Following is a list of the column names (and their Clarion datatypes) you can reference in your
filter expression. Generally, filtering on MSSQL system tables requires not only an intimate
knowledge of the MSSQL system tables, but also of the MSSQL stored procedures. For example,
to filter on table owner:
uid = user_id('DBO')
See your SQL server documentation for information on the MSSQL system tables and stored
procedures.
name CSTRING(31)
id LONG
uid SHORT
type STRING(2)
userstat SHORT
sysstat SHORT
indexdel SHORT
schema_ver SHORT
refdate STRING(8)
crdate STRING(8)
version LONG
deltrig LONG
instrig LONG
updtrig LONG
seltrig LONG
category LONG
cache SHORT
244
Database Drivers and Interfaces
ODBC:Overview
The ODBC Acclerator Driver is one of several SoftVelocity SQL Accelerator drivers. These SQL
Drivers share a common code base and many common features such as SoftVelocity's unique,
high speed buffering technology, common driver strings, and SQL logging capability. See SQL
Accelerator Drivers for information on these common features.
The ODBC Accelerator Driver converts standard Clarion file I/O statements and function calls into
optimized SQL statements, which it sends to the backend SQL server for processing. This means
you can use the same Clarion code to access both SQL tables and other file systems such as
TopSpeed files. It also means you can use Clarion template generated code with your SQL
databases.
The ODBC Accelerator Driver is slightly different from the other SQL drivers in that it is a generic
SQL driver. It is not specific to a particular SQL server, but, in fact, works with any database or
file system that supports the ODBC standard. This includes SQL systems such as AS400,
Informix, MSSQL, Oracle, Scalable SQL, SQL Anywhere, Sybase, and many non-SQL systems
as well (dBase, Excel, FoxPro, etc.). This chapter describes special issues and considerations
that arise when using the ODBC Accelerator Driver to access data.
All the common behavior of all the SQL Accelerator drivers is documented in the SQL Accelerator
Drivers chapter. All behavior specific to the ODBC driver is noted in this chapter.
Make sure you have the latest ODBC drivers from your database server provider, as well
as the end users of your applications.
What is ODBC?
ODBC (Open DataBase Connectivity) is a Windows "strategic interface" for accessing data from
a variety of Relational Database Management Systems (RDBMS) across a variety of networks
and platforms.
The ODBC standard was developed and is maintained by Microsoft, which publishes an ODBC
Software Development Kit (SDK), geared for use with its Visual C++ product. ODBC support is
another way in which Clarion provides an extensible platform for you to create applications.
Over the years Microsoft has modified what they call ODBC. It used to be that you would first
download their ODBC manager. Next, you would download and install any database specific
ODBC drivers that you need.
Recently, many different layers of database software have surfaced. You can find ADO, RDO,
OLE DB, and many more. Microsoft has merged all of these technologies into one complete
installation package called MDAC (Microsoft Data Access Components). Basically it consists of
several components that provide various database technologies; including ODBC. MDAC is a
royalty-free redistributable package that you can install on any Windows machine without cost.
245
Database Drivers
246
Database Drivers and Interfaces
When you use ODBC to access data, four components must cooperate to make it work:
1. Your application calls the ODBC driver manager, and sends it the appropriate requests
for data, with the ODBC API.
Clarion does this for you transparently, using the CLAODBX.DLL (32-bit) application
extension. When hand-coding, be sure to include this library in the project. When
distributing your application, be sure to deploy this file with your .EXE file (unless you
produce a one-piece .EXE).
2. The ODBC driver manager receives the API calls, check the Windows Registry for
information on the data source, then loads the ODBC "back-end" driver.
The actual "interface" to the driver manager is a file called ODBC32.DLL, which the
Microsoft setup program places in the \Windows\System directory. This is the ODBC
Administrator, which then loads other libraries to do its work.
3. The ODBC "backend" driver is another library (.DLL) which contains the executable code
for accessing the data.
Various third-parties supply "backend" drivers. For example, Lotus Development Corp.
supplies the ODBC driver for Lotus Notes. Microsoft Office distributes an ODBC SDK
containing drivers for most of their database products.
4. The data source is either a data file (usually when ODBC is used for local data access),
or a remote DBMS, such as an Oracle database.
The data source has a descriptive name; for example, "Microsoft Access Databases."
The name serves as the section name in the ODBC.INI file.
The ODBC driver manager must know the exact data source name so that it can load the
right driver to access the data. Therefore, it's vitally important that you know the precise
data source name.
247
Database Drivers
Notes:
C The Clarion data type can be used to manipulate the ODBC data type. CREATE does create
the ODBC data type.
The Clarion type can be used to manipulate the ODBC data type, however, CREATE does
NOT create the ODBC data type.
1 Clarion LONG, SHORT, and BYTE can be used with ODBC DECIMAL and NUMERIC data
types if the ODBC field does not have any decimal places.
Example:
TimeStampField STRING(8),NAME('TimeStampField')
TimeStampGroup GROUP,OVER(TimeStampField)
TimeStampDate DATE
TimeStampTime TIME
END
CREATE creates a TIMESTAMP field if you use a similar structure.
248
Database Drivers and Interfaces
5 CREATE attempts to create a TINYINT for a BYTE. If the backend does not support
TINYINT, CREATE treats BYTE as a SHORT. CREATE attempts to create a SMALLINT for a
SHORT. If the backend does not support SMALLINT, CREATE treats SHORT as a LONG.
CREATE attempts to create an INTEGER for a LONG. If the backend does not support
INTEGER, CREATE creates a decimal field.
Your backend database may contain data types that are not listed here. These data types
are converted to ODBC data types by the backend database. Consult your backend
database documentation to determine which ODBC data type is used.
249
Database Drivers
250
Database Drivers and Interfaces
Typically, you add SQL support to your application by importing the SQL or ODBC table, view,
and synonym definitions into your Clarion Data Dictionary. The Import Wizard automatically fills in
the Table Properties dialog with default values based on the imported item. However, there are
several prompts in the Table Properties dialog you can use to further configure the way the
ODBC Accelerator Driver accesses the data. These Table Properties prompts, and their uses, are
described below.
Owner Name
Typically, the Import Wizard places the SQL database connection information (Host, Username,
Password, etc.) in the Owner Name field.
Some backend databases may require additional connection information which you can supply in
the Owner Name field. This information follows the password and is separated by semicolons,
using the syntax: keyword=value;keyword=value.
For example, when accessing a Sybase database with the ODBC driver, this would appear as:
DataSource,UserID,PassWord,DATABASE=DataBaseName;APP=APPName
Consult your appropriate SQL Server's documentation for information on these keywords, their
uses and effects.
251
Database Drivers
When adding attributes to the External Name feature, make sure to separate the column
name from the appropriate switch (i.e., columnname | switch). The spaces separating each
value are required. These switches are also case sensitive.
External Name
| BINARY
Adding the BINARY switch to the External Name tells the ODBC driver to store the data
in binary format. This is useful when storing images or non-printable characters. Valid
only with STRING data types.
| NOWHERE
Adding the NOWHERE switch to the External Name tells the ODBC driver to exclude the
field from any WHERE clauses it sends to the backend server. This is necessary for
certain backends when WATCH is in effect. Some backends do not allow certain data
types in a where clause, but they fail to advise the ODBC Accelerator Driver of this
restriction. The NOWHERE switch lets you manually advise of the restriction when
WATCH causes the ODBC driver to generate.
| READONLY
Adding the READONLY switch to the External Name tells the ODBC driver not to insert
the field when the record is added OR updated. This is necessary for certain back ends
that do not allow auto incrementing key fields to be set to null. Some back ends do not
allow auto incrementing key fields to be set to null, but they fail to advise the ODBC
Accelerator Driver of this restriction. The READONLY switch lets you manually advise of
the restriction.
| UNICODE
Adding the UNICODE switch to the External Name tells the ODBC driver to treat the
data in the field as Unicode. The CREATE statement will attempt to create the row as a
Unicode row. All data retrieval and storage commands will treat the contents of the field
as Unicode data. See the UNICODE driver string for more details. This switch is only
valid for STRING fields and is ignored for fields with other data types.
| WRITABLE
Adding the WRITABLE switch to the External Name tells the ODBC driver to insert the
field when the record is added OR updated. This allows you to force the driver to write
data even when the backend advises the ODBC Accelerator Driver that data cannot be
written to this field.
| ZERONOTNULL
Adding the ZERONOTNULL switch to the External Name tells the ODBC driver to not
set the field to NULL when the value is zero. the data in binary format. This is useful
when you need to store midnight for time or a zero date. Valid only with DATE, TIME and
TimeStamp data types.
252
Database Drivers and Interfaces
253
Database Drivers
When you use the ODBC Accelerator Driver, the ODBC Administrator can create a log file
documenting all calls made by the ODBC Accelerator Driver. It includes the actual SQL
statements made by the ODBC driver to the data source, and includes any errors posted. This
administrator logging slows down your program considerably, so it should only be activated
during testing. Additionally, the log file can grow to large proportions very quickly, so you should
turn logging off and delete the log file after using it.
Besides "snooping" on the actual SQL statements generated by the driver, you can zero in on
any errors. For example, if the application is unable to connect, you can open the log file, scroll to
the bottom of the file, then work up until you find the word "SQLError."
See Microsoft's ODBC documentation (ODBCINST.HLP--ODBC Options Dialog Box) for
instructions on using the ODBC Administrator logs.
ODBC:Driver Strings
There are switches or "driver strings" you can set to control the way your application creates,
reads, and writes files with a specific driver. Driver strings are simply messages or parameters
that are sent to the file driver at run-time to control its behavior. See Common Driver Features--
Driver Strings for an overview of these runtime Database Driver switches and parameters.
A forward slash preceeds all SQL driver strings. The slash allows the driver to distinguish
between driver strings and SQL statements sent with the SEND function.
There are no Driver Strings specific to ODBC, the ODBC Accelerator Driver supports all the SQL
Accelerator Driver Strings.
See Also: SQL Accelerator Driver Strings .
ODBC:Driver Properties
There are no driver properties specific to ODBC, the ODBC Accelerator Driver supports all the
SQL Accelerator Driver properties.
See Also: SQL Accelerator Driver Properties
254
Database Drivers and Interfaces
CREATE Y
NAME Y
ENCRYPT N
OWNER(password) Y2
RECLAIM N
PRE(prefix) Y
BINDABLE Y
THREAD Y6
EXTERNAL(member) Y
DLL([flag]) Y
OEM N3
LOCALE N
INDEX Y3
KEY Y3
MEMO N
BLOB Y
RECORD Y
BINARY N7
DUP Y
NOCASE Y
OPT N
PRIMARY Y
255
Database Drivers
NAME Y
Ascending Components Y
Descending Components Y
Mixed Components Y
DIM N
OVER Y
NAME Y
BOF(file) N
BUFFER(file) Y
BUILD(file) Y
BUILD(key) Y
BUILD(index) Y8
BUILD(index, components) Y8
BYTES(file) Y
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) Y
DUPLICATE(key) Y
EMPTY(file) Y
EOF(file) N
FLUSH(file) N
LOCK(file) N
NAME(label) Y
256
Database Drivers and Interfaces
PACK(file) N
POINTER(file) N
POINTER(key) N
POSITION(file) N
POSITION(key) Y
RECORDS(file) Y
RECORDS(key) Y
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) N
UNLOCK(file) N
ADD(file) Y
ADD(file, length) N
APPEND(file) Y
APPEND(file, length) N
DELETE(file) Y
GET(file,key) Y
GET(file, filepointer) N
GET(key, keypointer) N
HOLD(file) N
NEXT(file) Y
NOMEMO(file) N
257
Database Drivers
PREVIOUS(file) Y4
PUT(file) Y
PUT(file, filepointer) N
RELEASE(file) N
REGET(file,string) N
REGET(key,string) Y
RESET(file,string) N
RESET(key,string) Y
SET(file) Y4
SET(file, key) N
SET(file, filepointer) N
SET(key) Y
SET(key, key) Y
SET(key, keypointer) N
SKIP(file, count) Y
WATCH(file) Y
COMMIT Y
ROLLBACK Y
NULL(field) Y
SETNULL(field) Y
SETNULL(file,field) Y
SETNONNULL(field) Y
258
Database Drivers and Interfaces
Notes
1 The Clarion ODBC file driver supports the listed items, however, the underlying file
system may not support all of these items.
2 We recommend using a variable password that is lengthy and contains special characters
because this more effectively hides the password value from anyone looking for it. For
example, a password like "dd....#$...*&" is much more difficult to "find" than a password
like "SALARY."
To specify a variable instead of the actual password in the Owner Name field of the
File Properties dialog, type an exclamation point (!) followed by the variable name.
For example: !MyPassword.
3 International sorting is assumed to be done by the underlying file system. As such the
OEM attribute and the .ENV file are ignored.
4 PREVIOUS is not supported in file order.
5 See also PROP:Logout in the Language Reference.
6 THREADed files do not consume additional file handles for each thread that accesses the
file.
7 BUILD(index) sets internal driver flags to guarantee the driver generates the correct
ORDER BY clause. The driver does not call the backend server.
8 Whether LOGOUT also LOCKs the table depends on the server's configuration for
transaction processing. See your server documentation..
ODBC Caveats
Attempting to access some ODBC commands during a DLL unload phase may cause ODBC to
crash. Any destructor of a global object is called during the DLL unload phase.
Therefore you cannot perform any commands that will cause the file drivers to access the ODBC
API inside destructors of global objects.
259
Database Drivers
Oracle Accelerator
Oracle Accelerator
Oracle Accelerator is one of several SoftVelocity SQL Accelerators. These SQL drivers share a
common code base and many common features such as SoftVelocity's unique, high speed
buffering technology, common driver strings, and SQL logging capability. See SQL Accelerators
for information on these common features.
The Oracle Accelerator converts standard Clarion file I/O statements and function calls into
optimized SQL statements, which it sends to the backend Oracle server for processing. This
means you can use the same Clarion code to access both Oracle tables and other file systems
such as TopSpeed files. It also means you can use Clarion template generated code with your
SQL databases.
All the common behavior of all the SQL Accelerators is documented in the SQL Accelerators
section. All behavior specific to this driver is noted here.
SoftVelocity's Oracle Accelerator automatically works with Oracle versions 7.0 and higher. At
runtime, the driver initially tries to load the latest Oracle Client DLLs. If they are not available, it
tries to load earlier versions.
Personal Oracle 8.0 and higher only works with 32-bit programs.
260
Database Drivers and Interfaces
Software
To develop Windows programs with Oracle Accelerator, you must have Oracle version 7.0 or
higher.
The minimum configuration is to install the Oracle Instant client, which would contain the following
DLLs:
OCI.DLL
oracnnzsbb11.dll
oraociicus11.dll
These files reference version 11. One other file is required if you are using non-Western
languages.
These .DLLs must be in a directory that is in your system PATH.
You will not be able to define or import Oracle files in your Clarion data dictionary until the
Oracle DLLs are installed in a directory that is in your system PATH.
The Oracle driver requires that you have a valid Oracle client installed on both the development
and user machines. Oracle clients come in two versions: a regular client and an "Instant" client.
The regular client supports TNSNAMES (see Oracle documentation). The Instant client requires
you to specify full connection parameters to the Oracle server (IP address, Port, SID (Server ID)),
but is much smaller and easier to deploy.
261
Database Drivers
262
Database Drivers and Interfaces
2. Only those indexes directly associated with the table as CONSTRAINTs are
imported by the Oracle Accelerator driver. If you need more indexes, simply define
them manually.
3. If the Oracle database INDEX flag is set to OFF, the Oracle Accelerator Import
Wizard does not import CONSTRAINTS.
Fill in the following fields in the Login/Connection dialog:
Host Select the Oracle host that contains the tables or views to import. If the
Host list is empty, you may type in the host (a blank host specifies the
Oracle 8 Personal database). See your DBA or network administrator for
information on how the host is specified. For example, type 2: to connect to
the local Personal Oracle (7.2 and earlier) database. X: prefixes an IPX
host and TNS: prefixes a TCP/IP host. For Personal Oracle 8, leave the
Host field blank.
Username Type your Oracle Username. See your server documentation or your DBA
for information on applicable Usernames.
Password Type your Oracle Password. See your server documentation or your DBA
for information on applicable Passwords.
Optionally, you type a complete connect string in the Username field using either of the following
syntaxes:
username/password@Protocol:dbname
or
username@Protocol:dbname,password
For example, type:
scott/tiger@2:production1
in the Username field. Or, you may type just your username and the database name in the
Username field, and type your password in the Password field.
For example, type:
scott@2:production1
in the Username field, then type
tiger
in the Password field. The Import Wizard displays the password as a series of asterisks. See
your Oracle documentation for more information on Oracle connect string syntax.
263
Database Drivers
Filter Optionally, provide a filter expression to limit the list of tables and views to
import. The filter expression queries the ALL_CATALOG view. For
example the filter: OWNER='SCOTT' returns only the tables which have
SCOTT as the OWNER. . The filter expression is limited to 1024
characters in length.
Next > Press this button to open the Import Wizard's Import List dialog.
You can use the Enterprise Edition Dictionary Synchronizer to import an entire database,
including relationships, in a single pass.
264
Database Drivers and Interfaces
or
username@Protocol:dbname,password
See your Oracle documentation for more information on Oracle connect string syntax.
If the Username field is not long enough, you may continue the entry in the Password field,
because the Oracle Accelerator driver simply concatenates these fields and forwards their
contents to the Oracle server.
265
Database Drivers
2. Declare your Clarion file to use the Oracle Sequence like this:
OracleFile FILE,DRIVER('Oracle', '/AUTOINC=SELECT Myseq.nextVal')
RECORD
SomeData STRING
autoIncFld PDECIMAL(31)
END
END
3. Use PROP:ServerAutoInc before adding your data to the file using normal Clarion or
ABC syntax. The file driver will automatically get the sequence number and store it in the
appropriate field.:
OPEN(OracleFile)
OracleFile{PROP:ServerAutoInc, 2} = 1 !Set the 2nd field as the receiving
field
OracleFile{PROP:ServerAutoInc} ! tell the driver that the next ADD needs
auto-inc
ADD(OracleFile)
! This will first put the nextval sequence value into
! OracleFile.autoIncFld and then do a normal ADD call.
266
Database Drivers and Interfaces
HINT
You can tell Oracle Accelerator to generate Oracle hints by using the HINT driver string,
DRIVER('Oracle','/HINT=hint')
The square brackets [] above are used to show that the ampersand (&) is optional.
You can either override the base hint or concatenate a hint. If the first character after the = in the
KEY hint is an ampersand (&), Oracle Accelerator concatenates the hint onto the FILE hint,
otherwise it overrides the FILE hint.
If the first character after the = in the SEND hint is an ampersand (&) or the first character of a
hint property is an ampersand, Oracle Accelerator concatenates the hint onto the current hint (the
FILE hint and the KEY hint), otherwise it overrides the FILE and KEY hint.
You can also use PROP:Hint to return the hint that is in use (or will be in use if called after a SET,
but before the first NEXT or PREVIOUS statement.)
Example:
AFile DRIVER('Oracle','/hint=COST')
AKey KEY(field),NAME('KeyName /HINT=&FIRST_ROWS')
SEND(AFile,'/HINT=FIRST_ROWS')
AFile{PROP:Hint} = 'FIRST ROWS'
267
Database Drivers
LOGON SCREEN
LOGONSCREEN sets the toggle that determines whether the driver automatically prompts for
logon information. By default, the driver displays a logon window if no connect string is supplied.
If set to FALSE and there is no connect string, an ERRORCODE of 90 is returned.
The logon screen elements are contained within the file driver logic.
The end-user's ability to use the connect dialog will depend on the security surrounding the
Oracle database.
PERSONAL
The Personal Oracle 7.1 Server behaves differently than other Oracle servers. When using
Personal Oracle 7.1 you should inform Oracle Accelerator so it can tailor the generated SQL
especially for Personal Oracle 7.1. For example:
DRIVER ('Oracle','/PERSONAL')
or
SEND (Myfile,'/PERSONAL')
Notes:
The /PERSONAL switch is not required for Personal Oracle 7.2 (Personal Oracle for
Windows 95).
Personal Oracle 8.0 only works with 32-bit programs.
USEASYNCHRONOUSCALLS
The Oracle driver supports reading ahead asynchronously using the BUFFER statement. This
may give performance gains when using this variation of the BUFFER statement. For example,
you may have a large report where you need to read a lot of records and do some client side
processing. It would improve performance to use the BUFFER's read ahead facility to get data
in at the same time you are processing it. However, to enable this feature, all other commands
will run slower (become asynchronous).
By default the asynchronous read ahead feature of the BUFFER statement is disabled. To
enable this feature set /USEASYNCHRONOUSCALLS=TRUE
268
Database Drivers and Interfaces
WHERE
In addition to WHERE driver string supported by all the SQL Accelerator drivers, Oracle
Accelerator supports the following special WHERE driver string.
/Where in the FILE Definition
When a FILE declaration references more than one Oracle table, you must tell the Oracle server
which columns link the tables together. A /WHERE in the FILE definition specifies the connecting
fields between two or more Oracle tables. For example:
OrdBrowse FILE,DRIVER('ORACLE','/WHERE Orders.AccNum=Customer.AccNum'),|
NAME('Orders,Customer'),PRE(Orb),BINDABLE,THREAD
OrdbKey KEY(-Orb:OrderNumber),NAME('OrdbKey'),PRIMARY
Record RECORD,PRE()
OrderNumber LONG,NAME('OrderNum')
AccountNumber LONG,NAME('Orders.AccNum')
ShipTo STRING(32),NAME('ShipTo')
Name STRING(31),NAME('Name')
END
END
If you use the templates to generate your application, you will not need this technique. The
templates automatically generate VIEWs when more than one table is referenced.
269
Database Drivers
PL/SQL
PL/SQL is Oracle's procedural language extension to Oracle's SQL language. Because PL/SQL
statements are managed by the same engine that manages SQL statements, PL/SQL statements
may be incorporated into your Clarion programs in the same manner as SQL statements. For
example:
SQLFile FILE,DRIVER('Oracle'),NAME(SalaryFile)
Record RECORD
SalaryAmount PDECIMAL(5,2),NAME('JOB')
END
END
CODE
SqlFile{PROP:SQL} = |
'DECLARE ' &|
'TempPhoneArea clarionclient.PhoneArea%type; '&|
'CURSOR AreaCursor IS ' &|
'SELECT PhoneArea ' &|
'FROM ClarionClient ' &|
'WHERE PhoneArea = 305; ' &|
'BEGIN ' &|
'OPEN AreaCursor; ' &|
'LOOP ' &|
'FETCH AreaCursor INTO TempPhoneArea; ' &|
'EXIT WHEN AreaCursor%NOTFOUND; ' &|
'UPDATE ClarionClient ' &|
'SET PhoneArea = 954; ' &|
'END LOOP; ' &|
'CLOSE AreaCursor; ' &|
'COMMIT WORK; ' &|
'END;'
270
Database Drivers and Interfaces
The Oracle driver can now call stored procedures and stored functions that return result sets.
This feature is supported for Oracle 8 or later client versions. In addition, although you can use
these clients to access older versions of the Oracle server, this feature is only supported with
Server Version 7 or later.
Example:
file{PROP:SQL} = 'CALL GrantAccessProcedure'
271
Database Drivers
272
Database Drivers and Interfaces
273
Database Drivers
CREATE Y1
NAME Y
ENCRYPT N
OWNER(password) Y
RECLAIM N
PRE(prefix) Y
BINDABLE Y
THREAD Y
EXTERNAL(member) Y
DLL([flag]) Y
OEM Y2
LOCALE N
INDEX Y
KEY Y
MEMO N
BLOB Y
RECORD Y
BINARY N
DUP Y
NOCASE Y
OPT Y
PRIMARY Y
NAME Y
274
Database Drivers and Interfaces
Ascending Components Y
Descending Components Y
Mixed Components Y
DIM N
OVER Y
NAME Y
BOF(file) N
BUFFER(file) Y
BUILD(file) Y
BUILD(key) Y
BUILD(index) Y3
BUILD(index, components) Y3
BYTES(file) Y10
CLOSE(file) Y
CREATE(file) Y1
DUPLICATE(file) Y
DUPLICATE(key) Y
EMPTY(file) Y
EOF(file) N
FLUSH(file) N
LOCK(file) N
NAME(label) Y
275
Database Drivers
PACK(file) N
POINTER(file) N
POINTER(key) N
POSITION(file) Y14
POSITION(key) Y11
RECORDS(file) Y
RECORDS(key) Y12
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) N
UNLOCK(file) N
ADD(file) Y
ADD(file, length) N
APPEND(file) Y4
APPEND(file, length) N
DELETE(file) Y
GET(file,key) Y
GET(file, filepointer) Y5
GET(key, keypointer) N
HOLD(file) Y6
NEXT(file) Y
NOMEMO(file) N
PREVIOUS(file) Y7
276
Database Drivers and Interfaces
PUT(file) Y
PUT(file, filepointer) N
RELEASE(file) N
REGET(file,string) Y8
REGET(key,string) Y8
RESET(file,string) N
RESET(key,string) Y9
SET(file) Y
SET(file, key) N
SET(file, filepointer) N
SET(key) Y
SET(key, key) Y
SET(key, keypointer) N
SKIP(file, count) Y
WATCH(file) Y
COMMIT Y
ROLLBACK Y
NULL(field) Y
SETNULL(field) Y13
SETNULL(file,field) Y
SETNONNULL(field) Y
Notes
277
Database Drivers
1 CREATE(file) does not work for every data type. See Supported Data Types for more
information.
2 Adding the OEM attribute causes the driver to generate calls to NLSSORT for string fields
in a sort sequence (either key components or PROP:Order components).
3 The BUILD(dynamic index) and BUILD(index) statements do not perform any disk action.
They only initialize internal Oracle driver structures to track key order access and allow
SELECT statements to be built when you issue SET(key) or SET(key,key) statements
referencing the index.
4 The APPEND statement behaves identically to the ADD statement, that is, keys are
updated by the APPEND statement.
5 The GET(file, filepointer) statement is unsupported for all values of filepointer except
filepointer = 0. In this case, the record position is cleared and ERRORCODE 35 is
returned.
6 Apart from the holding records, the HOLD statement has another use. Normally, the driver
will not reread the record when you execute a RESET/NEXT to the current record.
Executing a HOLD statement before the RESET/NEXT forces the driver to reread the
record from disk.
7 You can't execute a PREVIOUS after a SET(file) statement. You can only examine the file
in a forward order.
8 The REGET statement only works if you have a unique key defined for the file
9 The RESET(key,position)/NEXT(file) statement sequence is optimized to retrieve the
record from the driver's internal buffer if the code is resetting to the current record. To
force the driver to reread the record from disk, execute a HOLD statement before the
RESET/NEXT sequence. This optimization is not in effect within a transaction frame.
10 The BYTES(file) function returns the number of records in the file or the number of bytes
in the last record accessed. Following an OPEN statement, the BYTES function returns
the number of records in the file. After the file has been accessed by GET, NEXT, ADD,
or PUT, the BYTES function returns the size of the last record accessed.
11 The POSITION(key) function returns (1 + size of the key components + the size of the
components of the file's primary key). This formula is true even if the first unique key is
the same key you are positioning on. If no primary key is defined, then the first unique
key is considered the primary key.
If there is no unique key, POSITION(key) returns 1 + size of the key components. In this
case RESET(key) will reposition to the first occurrence of the key value, since there is no
way of uniquely identifying a record. Therefore, the RESET may position on a different
record.
12 The RECORDS(key) function returns the number of UNIQUE occurrences of the first
element of the key. This is the same as doing an SQL statement of:
SELECT COUNT ( DISTINCT key_field1) FROM table
13 SETNULL(field) clears the contents of the field.
14 The returned POSITION can only be used with REGET(file,position) and only for unique
keys.
278
Database Drivers and Interfaces
Generally, you should not have to do any manual matching of data types. Rather, you
simply import file definitions from your Oracle database into your Clarion data dictionary.
The Oracle Accelerator driver automatically selects the proper data types (see Importing
Oracle Files to a Data Dictionary).
You cannot use the CREATE statement to create rows of type LONG or LONG RAW.
6 Clarion can access Oracle DATE data types by using either a DATE or a STRING with a
GROUP overlaying the STRING.
If you use a Clarion DATE field, the TIME component of the field is not readable and is
set to 0 when writing the field. You may use a CREATE statement to create the table. For
example:
279
Database Drivers
If you use a Clarion STRING with an overlaid GROUP, the GROUP consists of a DATE
and a TIME field. You may not use a CREATE statement to create the table. For
example:
Your Clarion application should generally reference the DATE field (StartDate), and should
not reference the STRING field (OraDate) or the GROUP field (StartDate_Group).
However, if the Oracle date stamp is part of the key, you must include the STRING field
(not the DATE field) as a key component in your Clarion data dictionary.
7 Oracle ROWID data types are read and written as a STRING(18) of format
BBBBBBBB.RRRR.FFFF. Where B, R, and F are hexadecimal numbers representing
block, row, and file number respectively. See your Oracle documentation for more
information.
CREATE will not create a ROWID row.
280
Database Drivers and Interfaces
281
Database Drivers
When you press the Next > button, the Import Wizard opens the Import List dialog. The Import
List dialog lists the importable items.
Highlight the table whose definition to import, then press the Finish button to import. The Import
Wizard adds the definition to your Clarion Data Dictionary, then opens the File Properties dialog
to let you modify the default definition.
Import additional tables by repeating these steps. After all the items are imported, return to the
Dictionary Editor where you can define relationships and delete any columns not used in your
Clarion application. See SQL Accelerator Drivers--Define Only the Fields You Use.
282
Database Drivers and Interfaces
Clarion's Dictionary Editor Import Wizard lets you import Pervasive SQL table definitions into your
Clarion Data Dictionary. When you select the Pervasive SQL Accelerator Driver from the driver
drop-down list, the Import Wizard opens the Login/Connection dialog. The Login/Connection
dialog collects the connection information for the Pervasive SQL database.
Before you can connect to the SQL database and import table definitions, the database
must be started and must be accessible from your computer.
Fill in the following fields in the Login/Connection dialog:
Database Name Select the Pervasive SQL database that contains the tables to
import. If the Database Name list is empty, you may type in the
name. See your server documentation for information on how the
database is specified. The specification may depend on where the
database server is located (remote or local), and on the network
protocol (TCP/IP, IPX, etc.) used to access it.
DDF Directory Press the Browse button to select the pathname or directory
containing the database DDF files.
Database Directory Press the Browse button to select the pathname or directory
containing the database.
Specify either the Database Name or the DDF directory, but not both.
Owner Names Optionally, type a comma separated list of names the Pervasive
SQL driver tries when opening encrypted Btrieve files. If a
name contains a comma or space, it must be surrounded by
single quotes.
Refresh table list Check this box to refresh the list of tables to import when you
press the Next > button. Clear the box to improve performance
when the database is likely to be unchanged between imports.
Disconnect after Check this box to disconnect from the server after importing the
Import or Cancel (last) definition. Generally, you should clear this box when
importing multiple definitions in order to maintain your
connection to the server between imports.
Next > Press this button to open the Import Wizard's Import List
dialog.
283
Database Drivers
Typically, you add Pervasive SQL support to your application by importing the table definitions
into your Clarion Data Dictionary. The Import Wizard automatically fills in the File Properties
dialog with default values based on the imported item. However, you can use the Owner Name
field in the File Properties dialog to further configure the way the Pervasive SQL Driver accesses
the data.
Pervasive SQL allows some information in addition to the database identification in the Owner
Name field. This information appears alternatively as:
Database[,Owners;Switches]
or
DDF=DDFPath[|Datapath][,Owners;Switches]
Where Database is the name of a Pervasive SQL database. DDFPath is a path to a set of DDF
(Btrieve data dictionary) files. Datapath is the path to the corresponding data files. If omitted,
Datapath defaults to DDFPath. Owners is a comma separated list of names to try when opening
encrypted Btrieve files. If a name contains a comma or space, it must be surrounded by single
quotes. Switches is a semicolon separated list of assignments. Valid switches are:
CREATEDDF=[0|1|2]
Where 0 creates a new DDF file, 1 replaces the existing DDF file, and 2 removes the existing
DDF File.
NOTE:
The CREATEDDF switch is provided primarily for use during initial installation to allow you to
build new DDF files. You should never use this switch for existing databases.
284
Database Drivers and Interfaces
CREATE Y
NAME Y
ENCRYPT N
OWNER(password) Y1
RECLAIM N
PRE(prefix) Y
BINDABLE Y
THREAD Y
EXTERNAL(member) Y
DLL([flag]) Y
OEM N
INDEX Y
KEY Y
MEMO N
BLOB Y
RECORD Y
BINARY N3
DUP Y
NOCASE Y
OPT N
PRIMARY Y
285
Database Drivers
NAME Y
Ascending Components Y
Descending Components Y
Mixed Components Y
DIM N
OVER Y
NAME Y
BOF(file) N
BUFFER(file) Y
BUILD(file) Y
BUILD(key) Y
BUILD(index) Y3
BUILD(index, components) Y3
BYTES(file) Y
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) Y
DUPLICATE(key) Y
EMPTY(file) Y
EOF(file) N
FLUSH(file) N
LOCK(file) N
NAME(label) Y
286
Database Drivers and Interfaces
PACK(file) N
POINTER(file) N
POINTER(key) N
POSITION(file) N
POSITION(key) Y
RECORDS(file) Y
RECORDS(key) Y
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) N
UNLOCK(file) N
ADD(file) Y
ADD(file, length) N
APPEND(file) Y
APPEND(file, length) N
DELETE(file) Y
GET(file,key) Y
GET(file, filepointer) N
GET(key, keypointer) N
HOLD(file) N
NEXT(file) Y
NOMEMO(file) N
287
Database Drivers
PREVIOUS(file) Y
PUT(file) Y
PUT(file, filepointer) N
RELEASE(file) N
REGET(file,string) N
REGET(key,string) Y
RESET(file,string) N
RESET(key,string) Y
SET(file) Y
SET(file, key) N
SET(file, filepointer) N
SET(key) Y
SET(key, key) Y
SET(key, keypointer) N
SKIP(file, count) Y
WATCH(file) Y
COMMIT Y
ROLLBACK Y
NULL(field) Y
SETNULL(field) Y
SETNULL(file,field) Y
SETNONNULL(field) Y
288
Database Drivers and Interfaces
Notes
1 We recommend using a variable password that is lengthy and contains special characters
because this more effectively hides the password value from anyone looking for it. For
example, a password like "dd....#$...*&" is much more difficult to "find" than a password
like "SALARY."
To specify a variable instead of the actual password in the Owner Name field of the
File Properties dialog, type an exclamation point (!) followed by the variable name.
For example: !MyPassword.
2 See also PROP:Logout in the Language Reference.
3 BUILD(index) sets internal driver flags to guarantee the driver generates the correct
ORDER BY clause. The driver does not call the backend server.
4 Whether LOGOUT also LOCKs the table depends on the server's configuration for
transaction processing. See your server documentation.
289
Database Drivers
SQLAnywhere Accelerator
Overview
SQLAnywhere Server
For complete information on the SQLAnywhere database system, please review Sybase's
SQLAnywhere documentation.
SQLAnywhere Accelerator
The SQLAnywhere Accelerator is one of several SoftVelocity SQL Accelerators. These SQL
Accelerators share a common code base and many common features such as SoftVelocity's
unique, high speed buffering technology, common driver strings, and SQL logging capability. See
SQL Accelerators for information on these common features.
The SQLAnywhere Accelerator converts standard Clarion file I/O statements and function calls
into optimized SQL statements, which it sends to the backend SQLAnywhere server for
processing. This means you can use the same Clarion code to access both SQLAnywhere tables
and other file systems such as TopSpeed files. It also means you can use Clarion template
generated code with your SQL databases.
All the common behavior of all the SQL Accelerators is documented in the SQL Accelerators
section. The SQLAnywhere Accelerator is based on the ODBC Accelerator and inherits all
features of the ODBC Accelerator. All the common behavior of the SQL Accelerators that are
derived from the ODBC Accelerator is documented in the ODBC Accelerator section. All
behavior specific to this driver is noted here.
Before you can connect to the SQLAnywhere database and import table definitions, you
must start the database client software.
If you have not started the client software, Clarion issues the unable to start database engine
message.
290
Database Drivers and Interfaces
Database Select the SQLAnywhere engine that contains the tables to import. If the
Database list is empty, you may type in the name. See your server
documentation or your DBA for information on database engines.
Username For Standard Security, type your Username. For Trusted Security
(Integrated NT Security) no Username is required. See your server
documentation or your DBA for information on applicable Usernames and
security methods.
Password For Standard Security, type your Password. For Trusted Security
(Integrated NT Security) no Password is required. See your server
documentation or your DBA for information on applicable Passwords and
security methods.
Filter Optionally, provide a filter expression to limit the list of tables and views to
import. The filter expression queries the SYSCATALOG view. The filter
expression is limited to 1024 characters in length. The filter is case
sensitive, so type your filter value accordingly.
Following is a list of the column names (and their Clarion datatypes) you can reference in
your filter expression. See your SQLAnywhere documentation for information on these fields.
CREATOR STRING(128)
TNAME STRING(128)
DBSPACENAME STRING(128)
TABLETYPE STRING(10)
NCOLS LONG
PRIMARY_KEY STRING(1)
CHECK STRING(32767)
REMARKS STRING(32767)
Disconnect from Server Check this box to disconnect from the server after
when Import is finished importing (or canceling). Generally, you should clear this
box when importing multiple definitions in order to
maintain your connection to the server between imports.
Next > Press this button to open the Import Wizard's Import
List dialog.
291
Database Drivers
When you press the Next > button, the Import Wizard opens the Import List dialog. The Import
List dialog lists the importable items.
Highlight the table whose definition to import, then press the Finish button to import. The Import
Wizard adds the definition to your Clarion Data Dictionary, then opens the File Properties dialog
to let you modify the default definition.
Import additional tables by repeating these steps. After all the items are imported, return to the
Dictionary Editor where you can define relationships and delete any columns not used in your
Clarion application. See SQL Accelerators--Define Only the Fields You Use.
The SQLAnywhere driver uses ODBC to communicate with the SQLAnywhere engine. When
more than one ODBC Driver for SQLAnywhere is installed on a machine the driver will choose to
use the “Sybase SQL Anywhere” driver first. To force the driver to use a specific ODBC Driver
you add to the Windows Registry the String Value “Dll” to the key
HKEY_LOCAL_MACHINE\Software\SoftVelocity\SQLAnywhere. You set this value to the name
of the ODBC Driver. For Example, set the value to “SQL Server Native Client 10.0” to force the
MSQL driver to use the 10.0 Driver even when the 11.0 driver is available.
Type an exclamation point (!) followed by a variable name in the Owner Name field of the
File Properties dialog to specify a variable connect string rather than hard coding the
connect string (OWNER attribute) . For example: !GLO:ConnectString.
292
Database Drivers and Interfaces
A forward slash preceeds all SQL Accelerator driver strings. The slash allows the driver to
distinguish between driver strings and SQL statements sent with SEND.
In addition to the standard SQL Driver Strings, the SQLAnywhere Accelerator supports the
following Driver Strings:
LOGONSCREEN
GATHERATOPEN
293
Database Drivers
The logon screen is the SQLAnywhere Connect dialog. Consult your SQLAnywhere
documentation for more information on this dialog. The end-user's ability to use the connect
dialog will depend on the security surrounding the SQLAnywhere database. For example, the
end-users may have access rights to a named database (sademo) that they can access with the
SQLAnywhere client software, but they may not have access rights to the *.db files that comprise
the database. The SQLAnywhere connect dialog requires *.db files rather than database name.
294
Database Drivers and Interfaces
295
Database Drivers
CREATE Y
NAME Y
ENCRYPT N
OWNER(password) Y1
RECLAIM N
PRE(prefix) Y
BINDABLE Y
THREAD Y
EXTERNAL(member) Y
DLL([flag]) Y
OEM N
LOCALE N
INDEX Y
KEY Y
MEMO N
BLOB Y
RECORD Y
BINARY N3
DUP Y
NOCASE Y
OPT N
296
Database Drivers and Interfaces
PRIMARY Y
NAME Y
Ascending Components Y
Descending Components Y
Mixed Components Y
DIM N
OVER Y
NAME Y
BOF(file) N
BUFFER(file) Y
BUILD(file) Y
BUILD(key) Y
BUILD(index) Y3
BUILD(index, components) Y3
BYTES(file) Y
CLOSE(file) Y
CREATE(file) Y
DUPLICATE(file) Y
DUPLICATE(key) Y
EMPTY(file) Y
EOF(file) N
FLUSH(file) N
LOCK(file) N
297
Database Drivers
NAME(label) Y
PACK(file) N
POINTER(file) N
POINTER(key) N
POSITION(file) N
POSITION(key) Y
RECORDS(file) Y
RECORDS(key) Y
REMOVE(file) Y
SEND(file, message) Y
STATUS(file) Y
STREAM(file) N
UNLOCK(file) N
ADD(file) Y
ADD(file, length) N
APPEND(file) Y
APPEND(file, length) N
DELETE(file) Y
GET(file,key) Y
GET(file, filepointer) N
GET(key, keypointer) N
HOLD(file) N
NEXT(file) Y
298
Database Drivers and Interfaces
NOMEMO(file) N
PREVIOUS(file) Y
PUT(file) Y
PUT(file, filepointer) N
RELEASE(file) N
REGET(file,string) N
REGET(key,string) Y
RESET(file,string) N
RESET(key,string) Y
SET(file) Y
SET(file, key) N
SET(file, filepointer) N
SET(key) Y
SET(key, key) Y
SET(key, keypointer) N
SKIP(file, count) Y
WATCH(file) Y
COMMIT Y
ROLLBACK Y
299
Database Drivers
NULL(field) Y
SETNULL(field) Y
SETNULL(file,field) Y
SETNONNULL(field) Y
Notes:
1 We recommend using a variable password that is lengthy and contains special characters
because this more effectively hides the password value from anyone looking for it. For
example, a password like "dd....#$...*&" is much more difficult to "find" than a password
like "SALARY." To specify a variable instead of the actual password in the Owner
Name field of the File Properties dialog, type an exclamation point (!) followed by
the variable name. For example: !MyPassword.
2 See also PROP:Logout in the Language Reference.
3 BUILD(index) sets internal driver flags to guarantee the driver generates the correct
ORDER BY clause. The driver does not call the backend server.
4 Whether LOGOUT also LOCKs the table depends on the server's configuration for
transaction processing. See your server documentation.
300
Database Drivers and Interfaces
301
Database Drivers
Overview
SQLite is a very portable file format particularly useful for data that needs to be accessible locally
from various devices include PCs running various operating systems or smart phones.
SQLite is not designed for multi-user access. It is not a client/server system like most SQL
systems. There is no engine that needs to be installed. It is much more like the TopSpeed Driver
than MSSQL.
To run a Clarion program that uses the SQLite driver all that you need are the Clarion libraries
that you use, plus sqlite3.dll. This can be downloaded from www.sqlite.org. The driver requires
version 3.3.1 or later of sqlite3.dll.
SQLite stores all tables and keys in a single data file.
SQLite does not support stored procedures.
Warning:
Although the SQLite driver supports DECIMAL and PDECIMAL data types, the SQLite data
format does not properly support these. It stores the values as binary numbers. Normally this will
not cause any problems. You may encounter problems if you use SQL code to retrieve data and
in this SQL code use rounding functions. For example, ROUND(9.95,1) evaluates to 10, not 9.9
as expected. This only affects any SQL code. It does not affect standard Clarion code.
Tip:
ADD() is very fast with SQLite when you use it within a transaction. If you need to add a lot of
data it is recommended to issue a LOGOUT statement followed by the ADD calls and when
completed issue a COMMIT.
Note:
When building a project that uses the SQLite driver the project system will copy sqlite3.dll to the
destination folder. If the dll cannot be found a warning is generated. To avoid this warning either
place this dll in a folder listed in the [Copy] section of your redirection file, or turn off “Copy
Referenced Dlls” in the properties for the project; or edit <Application
Data>\SoftVelocity\Clarion\<Clarion Version>\LibCopyList.xml file and remove the dll entry
named C%V%LIT.DLL.
302
Database Drivers and Interfaces
EXTERNAL(member) Y
DLL([flag]) Y
OEM N
LOCALE N
303
Database Drivers
Notes
1 The OWNER is the name of the SQLite database file that the table is stored in.
2 See also PROP:Logout in the Language Reference.
3 BUILD(index) sets internal driver flags to guarantee the driver generates the correct
ORDER BY clause. The driver does not call the backend server.
304
Database Drivers and Interfaces
4 You cannot logout threaded and non-threaded files at the same time. All files in the
LOGOUT statement must be in the same database table.
5 Doing SET;NEXT;LOGOUT;NEXT is not supported.
6 If OPEN fails with ERRORCODE 47 (InvalidFileErr), and you have file logging turned on
(See the “Database Driver System-wide Logging”), the log file will have the name of the
field that could not be found in the table on disk and a list of names of columns in the
table on disk.
7 CREATE converts Clarion data types to SQLite Data types using the following table
8 A PRIMARY KEY AUTOINCREMENT constraint will be added to a field definition if
/AUTOINC=TRUE is specified in the driver string and the field is the key component of
the primary key and there is only one key component for the primary key and the field
type is LONG.
STRING CHAR
CSTRING VARCHAR
STRING(8);GROUP DATETIME
OVER(STRING);DATE;TIME
DATE DATE
PDECIMAL NUMBER
DECIMAL NUMBER
BYTE TINYINT
SHORT SMALLINT
LONG INTEGER
SREAL FLOAT
REAL REAL
BLOB CLOB
BLOB,BINARY BLOB
305
Database Drivers
WHERE
Note 1: The AUTOINC driver string for SQLite is in the form ‘AUTOINC = TRUE | FALSE’. If
AUTOINC is set to TRUE and there is a primary key on the table that has only one component
and that component is of type LONG, then the CREATE statement will create an
AUTOINCREMENT PRIMARY KEY constraint on that component and ADD will retrieve the value
for that field set by SQLite.
PROP:CreateDB is a command property. This command property tells the SQL Accelerator to
create the SQLite Database file that is specified in the OWNER attribute of the file.
If the database file already exists, this command does nothing. The existing database file will not
be destroyed.
You can also create a database by issuing a CREATE statement for any table in that database. If
the database does not exist, it will be created and the table will also be created in the database.
You would use this property if you are using SQL statements to create the database rather than
the Clarion CREATE statement.
Example:
sqlTable FILE,DRIVER(‘SQLite’),OWNER(‘MyDatabase.sqlite’)
RECORD
END
END
CODE
sqlTable{PROP:CreateDB} ! Will create the file MyDatabase.sqlite
IF ERRORCODE() ! test to see if the create worked
306
Database Drivers and Interfaces
Below is a table with all the error codes that FILEERRORCODE() will return after a call to an
SQLite file. For programs designed to target non-English speaking users or ones that wish to
change the error messages, the table also includes the CLAMSGerrornumber values that must
be used in the env file.
307
Database Drivers
Notes:
1: ERRORCODE() will return 8, NoMemErr
2: ERRORCODE() will return 5, NoAccessErr
3: %1 will be substituted with the error code returned from the operating system. %2 will be
substituted with the matching error message. If you set a replacement string, you do not
need to have %1 or %2 in your string.
4: %1 will be substituted with the name of the missing procedure
308
Database Drivers and Interfaces
ADO Interface
What is ADO?
ADO is a Microsoft technology, and stands for ActiveX Data Objects. It is a high-level
programming interface used to access data in a database. ADO is designed as an easy-to-use
application level interface to Microsoft's low-level data access interface, OLE DB.
The Clarion ADO classes and templates were created to provide access to the MS ADO
database connectivity layer. While not specifically a database driver, it is accessed in a similar
manner. As such, intrinsic data file operations will not function and require that the provided class
methods and templates be used.
ADO is automatically installed with Microsoft IIS as an Active X component. ADO is a common
way to access a database from inside a web page (like an ASP page). For example, to connect to
a database inside an ASP page:
The important thing to note here is the specific opening and closing of the database
connection. Failure to specifically close an ADO connection can result in memory leakage.
309
Database Drivers
ADO Requirements
The use of Clarion with ADO requires that you have installed the Microsoft Data Access
Components (MDAC) interface, which is a free download from the Microsoft web site. You must
have Version 2.62 or later installed.
ADO Logging
The ADO Synchronizer supports trace logging. Logging can only be turned on via the
DRIVERS.INI file in the CSIDL_APPDATA\SoftVelocity\Clarion\<clarion_version> folder.
Trace=0|1
TraceFile=filename
TraceFile specifies the file you want to log to. If not supplied then the log is
ADOSYNCHRONISER.LOG
The DrvTrace example application has been updated to support logging of the ADO
Synchronizer.
This logging is active during the synchronization process with the Dictionary Editor. It is not to be
confused with the normal trace logging that can be active in your application at runtime.
310
Database Drivers and Interfaces
Index
32-bit applications .................................... 251 Error Codes ............................................... 33
6.3 Features............................................. 144 File Sharing ............................................... 33
ACS ........................................................... 25 File Structure............................................. 33
ADO ......................................................... 300 KEY Definitions ......................................... 33
ADO - Date and Time Columns ............... 145 Keys and Indexes ..................................... 33
ADO Logging ........................................... 301 Page Size .................................................. 33
ADO Requirements ................................. 301 Record Lengths......................................... 33
ALIAS ....................................................... 197 Record Pointers ........................................ 33
ALL_CATALOG ....................................... 253 Supported Commands and Attributes....... 28
ALLOWDETAILS ..................................... 173 Transaction Framing ................................. 33
ALLOWREAD ............................................ 25 Btrieve Database Driver ............................ 20
ALWAYSQUOTE ....................................... 15 Btrieve Driver Strings ................................ 25
AlwaysRebind .......................................... 198 BUFFERS ............................... 51, 65, 75, 97
APPENDBUFFER..............................25, 174 BUSYHANDLING.................................... 175
ASCII ...................................................5, 7, 8 BUSYMESSAGE .................................... 176
Database Driver ........................................... 5 BUSYRETRIES....................................... 177
Driver Strings ............................................... 7 C60ORA.DLL .......................................... 253
Supported Commands and Attributes ......... 8 CALL ....................................................... 165
auto numbered keys ................................ 256 Calling a stored procedure ...................... 165
AUTOINC................................................. 174 Calling a Stored Procedure ............. 261, 286
BALANCEKEYS ........................................ 25 Oracle ..................................................... 261
Basic ....................................................15, 16 SQLAnywhere ......................................... 286
Driver Strings ............................................. 15 Calling a Stored Procedure (SQLAnywhere
Accelerator ) ............................................ 286
Supported Commands and Attributes ....... 16
CHECKFORNULL................................... 145
Basic Database Driver ............................... 10
Choosing the Right Database Driver .......... 1
BINARY driver switch .............................. 242
Clarion Database Driver ........................... 38
BINARY switch on bound parameters ..... 165
Clarion Driver Strings ................................ 41
BINDCOLORDER .................................... 174
Clarion Functions used in SQL Filter
BINDCONSTANTS .................................. 175
Statements .............................................. 149
Browsing SQL Tables .............................. 149
Clarion Other ............................................. 44
Btrieve ..................................................28, 33
Clarion Supported Commands and
Client/Server .............................................. 33 Attributes ................................................... 42
Collating Sequence ................................... 33 CLIP ............................................................ 7
Driver Properties ........................................ 20 Clipper ........................................... 51, 53, 55
311
Database Drivers
312
Index
313
Database Drivers
314
Index
315
Database Drivers
316
Index
317