You are on page 1of 230

Connecting Centura

Objects to Databases
20-6204-0004

Trademarks
Centura, the Centura logo, Centura net.db, Centura Web Developer, Gupta, the Gupta
logo, Gupta Powered, the Gupta Powered logo, Fast Facts, Object Nationalizer,
Quest, QuickObjects, SQL/API, SQLBase, SQLBase Exchange, SQLConsole,
SQLGateway, SQLHost, SQLNetwork, SQLRouter, SQLTalk, Team Object
Manager, RDM, and Velocis are trademarks of Centura Software Corporation and
may be registered in the United States of America and/or other countries. The
trademarks TeamWindows, ReportWindows and EditWindows, and the registered
trademark SQL Windows, are all exclusively used and licensed by Centura Software
Corporation.
Adobe is a trademark of Adobe Systems, Incorporated.
IBM, OS/2, NetBIOS, and AIX are registered trademarks of International Business
Machines Corporation.
Java and Solaris are trademarks of Sun Microsystems, Incorporated.
Microsoft, Internet Explorer, Internet Information Server, DOS, Win 32, Windows,
Windows NT, Windows 95 and Visual Basic are either registered trademarks or
trademarks of Microsoft Corporation in the United States of America and/or other
countries.
Netscape FastTrack and Navigator are trademarks of Netscape Communications
Corporation.
Novell is a registered trademark, and NetWare is a trademark of Novell, Incorporated.
RoboHELP is a trademark of Blue Sky Software Corporation.
All other product or service names mentioned herein are trademarks or registered
trademarks of their respective owners.

Copyright
Copyright 2000 by Centura Software Corporation. All rights reserved.
Connecting Centura Objects to Databases
20-6204-0003
March 2000

Contents
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix
1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-1
Client/server architecture . . . . . . . . . . . . . . . . . . . . . . 1-2
Autocommit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-3
Bind variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5
Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-5
Connectivity parameters . . . . . . . . . . . . . . . . . . . . . . . 1-6
Connect search order . . . . . . . . . . . . . . . . . . . . . . . . . 1-6
Cursor context preservation . . . . . . . . . . . . . . . . . . . . 1-7
Front end result sets . . . . . . . . . . . . . . . . . . . . . . . . . . 1-8
Handles, contexts, and connections . . . . . . . . . . . . . . 1-9
IMAGE column types . . . . . . . . . . . . . . . . . . . . . . . . 1-11
Isolation levels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-12
Lock time-out. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-15
Nulls, empty strings, and spaces . . . . . . . . . . . . . . . 1-15
Positioned updates . . . . . . . . . . . . . . . . . . . . . . . . . . 1-17
Result set mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-19
SQL.INI keywords . . . . . . . . . . . . . . . . . . . . . . . . . . 1-21
Stored procedures. . . . . . . . . . . . . . . . . . . . . . . . . . . 1-21
Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-22

2 Initializing and Testing


Your Connection . . . . . . . . . . . . . . . . . . . . . . . . 2-1
Synopsis of what to do . . . . . . . . . . . . . . . . . . . . . . . . 2-2
Before connecting . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-2
Configuring an ODBC data source . . . . . . . . . . . . . . . 2-3

iii

Initializing Centura SQLWindows applications . . . . . . 2-4


Testing the connection . . . . . . . . . . . . . . . . . . . . . . . . 2-6
Connecting to Sybase . . . . . . . . . . . . . . . . . . . . . . . . . 2-7
Connecting to Oracle . . . . . . . . . . . . . . . . . . . . . . . . . 2-8
Specifying the database in your application . . . . . . . 2-10
Troubleshooting problems. . . . . . . . . . . . . . . . . . . . . 2-10
Sample applications . . . . . . . . . . . . . . . . . . . . . . . . . 2-14

3 Connecting to Informix . . . . . . . . . . . . . . . . . 3-1


Before you begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2
Arithmetic functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2
Autocommit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-2
Cursor context preservation . . . . . . . . . . . . . . . . . . . . 3-2
Cursors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-3
Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-3
DDL statement support . . . . . . . . . . . . . . . . . . . . . . . . 3-4
Empty strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-4
GET DIAGNOSTICS statement . . . . . . . . . . . . . . . . . 3-4
Isolation levels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-5
Lock time-out. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-5
Miscellaneous features . . . . . . . . . . . . . . . . . . . . . . . . 3-5
NLS data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-5
Positioned updates . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-6
SET statement support . . . . . . . . . . . . . . . . . . . . . . . . 3-6
SQL.INI keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-7
Stored procedures. . . . . . . . . . . . . . . . . . . . . . . . . . . 3-12
Storing TEXT and BYTE data . . . . . . . . . . . . . . . . . . 3-13

4 Connecting to
Microsoft SQL Server

. . . . . . . . . . . . . . . . . . 4-1

Before you begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2


Autocommit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2
Cursor context preservation . . . . . . . . . . . . . . . . . . . . 4-2
Data types supported . . . . . . . . . . . . . . . . . . . . . . . . . 4-2
iv

Empty strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-4


Isolation levels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-4
Keywords as table and column names . . . . . . . . . . . . 4-5
Lock time-out. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-5
Native connectivity . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-5
Positioned updates . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-6
Result set mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-6
SET statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-6
SqlDirectoryByName semantics . . . . . . . . . . . . . . . . . 4-7
SQL.INI keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-7

5 Connecting to Oracle . . . . . . . . . . . . . . . . . . . 5-1


Before you begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-2
Autocommit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-2
Cursor context preservation . . . . . . . . . . . . . . . . . . . . 5-2
Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-3
Dynamic PL/SQL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-3
Empty strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-4
Isolation levels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-4
Lock time-out. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-5
Optimizing message traffic . . . . . . . . . . . . . . . . . . . . . 5-5
Positioned updates . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-5
Result set mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-5
SQL.INI keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-5
Stored procedures. . . . . . . . . . . . . . . . . . . . . . . . . . . 5-11
Transactions, disconnects, and exits . . . . . . . . . . . . 5-15
Writing RAW data . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-16

6 Connecting to Sybase . . . . . . . . . . . . . . . . . . 6-1


Before you begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-2
Autocommit and chained transactions . . . . . . . . . . . . 6-2
Bind variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-3
COMPUTE clause . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-4
Cursor context preservation . . . . . . . . . . . . . . . . . . . . 6-4
v

Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-5


Empty strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6
Error processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6
Getting multiple connections . . . . . . . . . . . . . . . . . . . 6-12
Handles and connections . . . . . . . . . . . . . . . . . . . . . 6-13
Isolation levels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-13
Positioned updates . . . . . . . . . . . . . . . . . . . . . . . . . . 6-14
Releasing locks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-16
Reserved strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-16
SQL.INI keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-16
Stored procedures. . . . . . . . . . . . . . . . . . . . . . . . . . . 6-27
Transactions, disconnects, and exits . . . . . . . . . . . . 6-36
Writing and retrieving IMAGE and TEXT data . . . . . 6-37

7 Connecting to Ingres . . . . . . . . . . . . . . . . . .

7- 1

Before you begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 2


Autocommit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 2
Cursor context preservation . . . . . . . . . . . . . . . . . . . 7- 2
Cursors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 2
Database events . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 2
Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 3
Empty strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 4
Isolation levels. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 4
Lock time-out. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 4
Positioned updates . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 4
Result set mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 5
SQL.INI keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 5
Stored procedures. . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 9
User prefix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7- 11

8 Connecting to Databases
using ODBC . . . . . . . . . . . . . . . . . . . . . . . . . . .

8- 1

Before you begin . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8- 2


Connecting to specific data sources . . . . . . . . . . . . . 8- 2
vi

Brand information . . . . . . . . . . . . . . . . . . . . . . . . . . . 8- 3
Cursor context preservation . . . . . . . . . . . . . . . . . . . 8- 4
Data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8- 5
Error processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8- 5
Error code mapping. . . . . . . . . . . . . . . . . . . . . . . . . . 8- 6
Lock time-out. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8- 10
SQL.INI keywords . . . . . . . . . . . . . . . . . . . . . . . . . . 8- 10
Stored procedures. . . . . . . . . . . . . . . . . . . . . . . . . . 8- 14
Transactions, disconnects, and exits . . . . . . . . . . . 8- 15

9 Connecting to Multiple
Databases Concurrently

. . . . . . . . . . . . . . 9- 1

Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9- 2
Two approaches . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9- 2
About the application. . . . . . . . . . . . . . . . . . . . . . . . . 9- 3
Running the application. . . . . . . . . . . . . . . . . . . . . . . 9- 4
Design issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9- 9
Implementation details . . . . . . . . . . . . . . . . . . . . . . 9- 25
Getting more information. . . . . . . . . . . . . . . . . . . . . 9- 29

10 Certifying ODBC Drivers . . . . . . . . . . . . . . 10-1


About DCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2
Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2
Before certifying an ODBC driver . . . . . . . . . . . . . . . 10-4
Certifying an ODBC driver. . . . . . . . . . . . . . . . . . . . . 10-8
Deploying an ODBC driver . . . . . . . . . . . . . . . . . . . . 10-9
Mapping the column types . . . . . . . . . . . . . . . . . . . . 10-9
DCC.INI file for Paradox 3.x . . . . . . . . . . . . . . . . . . 10-10

Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Glossary-1
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Index-1

vii

Connecting Centura Objects to Databases

Preface
This book tells you how to connect a Centura SQLWindows application to any one of
a variety of databases:

Oracle

Microsoft SQL Server

Informix OL and SE-

Sybase System 11.x

CA-OpenIngres

Any database for which an ODBC driver certified to work with Centura
SQLWindows applications is available. This includes:

IBM DB2/400StarQuest Software, Inc. driver

dBASEINTERSOLV, Inc. driver

Microsoft AccessMicrosoft, Inc. driver

OracleVisigenic Software, Inc. driver

This book also describes how you can certify your own ODBC driver to work with
Centura SQLWindows applications using the Database Connectivity Configuration
(DCC) feature.
For information on how to use SQLBase OLE DB Data Provider to connect SQLBase
and applications built with software such as Visual Basic or Delphi, please read the
SQLBase OLE DB Data Provider Users Guide in the online book collection.
For information on how to use Centura Team Developer as an OLE DB Consumer to
connect SQLWindows applications to a variety of data sources, please read Chapter
13 of the Developing with SQLWindows manual in the online book collection.

Connecting Centura Objects to Databases

ix

Preface

This book does not describe how to connect a Centura SQLWindows application to
Centura Softwares SQLBase database. For information, read the SQLBase
documentation set.
Also, this book does not describe how to connect a Centura SQLWindows
application to DB2 databases using SQLHost, SQLGateway, and other components
of the SQLNetwork for DB2 or the SQLHost for Visual Basic productsread the
documentation that accompanies those products for more information.
This preface provides the following information:

Who should read this manual

The organization of this manual

The documentation format

The notation conventions used in this manual

Other helpful resources

How to contact Centura

Who should read this book


Anyone who wants to connect a Centura SQLWindows application to one of the
databases listed at the beginning of this Preface should read this book. To
successfully connect the application to your target database, you may also need the
help of your network administrator and database administrator.

What is in this book


Chapter 1 gives an overview of how Centura SQLWindows applications connect to
database servers.
Chapter 2 tells you how to initialize and test your connection to the database.
Chapters 3 through 7 give you additional information about connecting a Centura
SQLWindows application to specific databases.
Chapter 8 describes how to connect to an ODBC data source. It also talks specifically
about connecting to DB2/400 and dBASE.
Chapter 9 discusses some issues that are important when you connect a single
Centura SQLWindows application to more than one database at the same time.
Chapter 10 walks you through an example of how to certify your own ODBC driver.

Connecting Centura Objects to Databases

Notation conventions
Before you start using this manual, it is important to understand the typographical
conventions we use in this manual:
Formatting Convention

Type of Information

You

A developer who reads this manual

User

The end-user of applications that you write

bold type

Menu items, push buttons, and field names. Things that


you select. Keyboard keys that you press.

Courier 9

Builder or C language code example

SQL.INI

Program names and file names

MAPDLL.EXE
Precaution

Warning:

Vital
information

Important:

Supplemental
information

Note:

Alt+1

A plus sign between key names means to press and hold


down the first key while you press the second key

Other helpful resources


Centura Books Online. The Centura document suite is available online. This
document collection lets you perform full-text indexed searches across the entire
document suite, navigate the table of contents using the expandable/collapsible
browser, or print any chapter. Open the collection by selecting the Centura Books
Online icon from the Start menu or by double-clicking on the launcher icon in the
program group.
World Wide Web. Centura Softwares world wide Web site contains information
about Centura Software Corporations partners, products, sales, support, training, and
users. The URL is http://www.centurasoft.com.
The technical services section of our Web site is a valuable resource for customers
with technical support issues, and addresses a variety of topics and services, including
technical support case status, commonly asked questions, access to Centuras online
newsgroups, links to shareware tools, product bulletins, white papers, and
downloadable product updates.

Connecting Centura Objects to Databases

xi

Preface

Our Web site also includes information on training, including course descriptions,
class schedules, and certified training partners.

xii

Connecting Centura Objects to Databases

Send comments to...


Anyone reading this manual can contribute to it. If you have any comments or
suggestions, please send them to:
Technical Publications Department
Centura Software Corporation
975 Island Drive
Redwood Shores, CA 94065
or send email, with comments or suggestions to:
techpubs@centurasoft.com

Connecting Centura Objects to Databases

xiii

Preface

xiv

Connecting Centura Objects to Databases

Connecting Centura Objects to Databases

Chapter 1

Overview
This chapter describes how to connect Centura SQLWindows applications to
database servers. It describes some of the features supported by one or more of the
databases to which you can connect a Centura SQLWindows application.
Read this chapter to get a general description of each feature, then read the chapter
that covers the database to which you are connecting to find out if (and how) those
features are supported by that database.
Note: If the chapter that discusses a particular database does not mention a particular feature,
that feature is not supported (either because the database does not support it, or because Centura
SQLWindows does not support it for that database).

Connecting Centura Objects to Databases

1-1

Chapter

Overview

Client/server architecture
A Centura SQLWindows client/server application consists at runtime of the
following components:

Centura SQLWindows applicationthis is a program that performs services


for the user, and that communicates with a database using a SQLRouter. The
application can be written using QuickObjects, the object-oriented Scalable
Application Language (SAL), or a combination of both.

SQLRoutera software library supplied with Centura that takes as input data
and actions specified by a Centura SQLWindows application; SQLRouter
maps the input into appropriate function calls and data types from a database
vendors API (such as Oracles OCI or Microsofts ODBC) to implement the
specified actions on the given data.

SQLRouter also accepts data and actions from a database, and converts them into
actions and data that a Centura SQLWindows application can understand.
This table lists the different SQLRouters available and the databases you use the
SQLRouter to connect to:
SQLRouter

Target Databases

SQLRouter/Informix

Informix 7.2 and 7.3

SQLRouter/ODBC

DB2/400, Microsoft SQL Server 6.x,


Microsoft Access, dBase, Oracle (using the
ODBC API)

SQLRouter/Oracle

Oracle 7.2, 7.3, and 8.0.x (using the native


API)

SQLRouter/Sybase

System 11.x

SQLRouter/Ingres

CA-OpenIngres 2.0

Note: You can also use SQLRouter/ODBC to connect to any database for which you can obtain
an ODBC driver that is certified to work with Centura SQLWindowsfor more information
about certifying ODBC drivers, read Chapter 10, Certifying ODBC Drivers.

1-2

Database vendor API the call-level interface supplied by a database


vendor to communicate with that vendors database. Examples include
Oracle OCI, Informix SQLI, Sybase CT-LIB, CA-OpenIngres Embedded
SQL, and Microsoft ODBC.

Connecting Centura Objects to Databases

Autocommit

Network access layerthe software library supplied by a database vendor to


accept the actions and data specified by the database vendor API and send
them out over the network. This library also accepts actions and data provided
by the database over the network and passes them up to the database vendor
API layer.

Network softwaresoftware that sends and receives messages over network


hardware. Examples include TCP/IP, IPX/SPX, NetBEUI, NetBIOS, and
Named Pipes.

Autocommit
Commit relates to the grouping of server actions (typically changes to a database) so
all of the actions are made permanent in the database if and only if they are all
successful. The set of such actions constitutes a transactionsee also Transactions
on page 1-22.
The default setting for autocommit is:

OracleOFF

InformixOFF

Microsoft SQL ServerON

System 11OFF

CA-OpenIngresOFF

ODBCIn general, it depends on the driver and data source.

For dBASE and Microsoft Access 95, the default setting is ON.If autocommit is on,
each SQL statement executed becomes its own transaction. Unless an error occurs,
the result of the SQL statement is committed to the database. Also, you release locks
and other transaction resources as soon as possible, without needing to execute an
explicit COMMIT statement.
If autocommit is off and you have a pending transaction, what happens if you try to
execute a DDL statement depends on the database server:

Microsoft SQL Server and SybaseDDL statements are not allowed while
a transaction is pending.

OracleIf you try to execute a DDL statement, the database server first
commits the pending transaction before executing the DDL statement.

InformixIf you are using the ANSI or Transaction database server mode,
DDL statements are considered part of the current transaction. Once you
commit (or roll back) the transaction, the DDL is committed (or rolled back)
along with all the other statements that make up the transaction.

Connecting Centura Objects to Databases

1-3

Chapter

Overview

CA-OpenIngresDDL statements are considered part of the current


transaction. Once you commit (or roll back) the transaction, the DDL is
committed (or rolled back) along with all the other statements that make up
the transaction.

If autocommit is off, you start a transaction, then you try to turn autocommit on, what
happens next depends on the database server:

Microsoft SQL Server, CA-OpenIngres, and SybaseYou get an error.


You must first commit or roll back the pending transaction before you can
turn autocommit on.

Oracle and InformixYou can execute the statement to turn autocommit on


while a transaction is pending, but the new setting for autocommit does not
immediately take effect; you must first finish the transaction by explicitly
committing it or rolling it back. Once you finish the pending transaction,
autocommit takes effect.If autocommit is on and cursor context preservation
(CCP) is off, performing an SQL statement that modifies a row in a result set
(such as UPDATE or DELETE) not only commits the change to the database,
it also destroys the result set and its associated cursor. To perform multiple
operations on the same result set, either disable autocommit or enable CCP
(or both).

If autocommit is off, you are responsible for:

Executing the COMMIT statement (or calling SqlCommit) often enough to


reduce unnecessary locking that could restrict access to data for other users
(because of either read or update locks).

Grouping your changes to the database in such a way that only the
appropriate changes are cancelled if you need to execute a ROLLBACK.

An explicit commit (either manual or automatic) affects all SQL handles associated
with the same connection to the database.
To find out if the database you are connecting to supports autocommit, how it
supports it, and whether autocommit is on or off by default, read the chapter in this
book devoted to that database.
To turn autocommit off for all Centura SQLWindows applications that connect to a
given database, set the appropriate SQL.INI keyword (if one is defined for that
database) to off.
Note: You can turn off autocommit only for some of the databases you can connect to. Read
the Autocommit section of the chapters that discuss the databases your application connects to
for more information.

1-4

Connecting Centura Objects to Databases

Bind variables

You turn autocommit on or off by calling SqlSetParameter. Even though you specify
a specific handle (hSql) as one of the arguments, the change in the setting for
autocommit affects all handles associated with the same connection as hSql.
To turn autocommit off for a given application, include the following line in your
Centura SQLWindows application:
Call SqlSetParameter(hSql, DBP_AUTOCOMMIT, FALSE, strNull)

If autocommit is off, changes you make to a database do not become permanent until
you execute a COMMIT statement (or call SqlCommit). Further, if you disconnect
from the database or exit the application (either normally or abnormally) without
executing COMMIT, the pending transaction may or may not be committed for you.
To find out what does happen, read the chapter that covers the database you are
connecting to.
For additional information, read the documentation on SqlSetParameter and
DBP_AUTOCOMMIT in the Centura SQLWindows Function Reference.

Bind variables
Bind variables, also called program variables, host variables, or parameter markers,
refer to data values associated with an SQL statement. Bind variables associate (bind)
a syntactic location in an SQL statement with a data value in that statement; the
binding actually occurs at runtime.
A bind variable in an SQL statement indicates that data from a variable in the
application is bound to it each time the statement executes. This feature allows an
SQL statement to be compiled once and executed repeatedly with a new set of values
in the bind variables each time.
Read the chapter that covers the database to which you are connecting to find out if
(and how) bind variables are supported by that database.

Concurrency
A single Centura SQLWindows application can access multiple tables on a given
database, as well as connect to multiple databases simultaneously. However,
execution of all Scalable Application Language (SAL) functions is single-threaded
the function must complete (and the value of bOk returned to the application) before
the next statement or function in the application can be executed.
Concurrency can also be affected by how different applications obtain and release
locksfor related information, read Isolation levels on page 1-12 and Lock time-out
on page 1-15.

Connecting Centura Objects to Databases

1-5

Chapter

Overview

To learn how to write applications that connect to multiple databases concurrently,


read Chapter 9, Connecting to Multiple Databases Concurrently.

Connectivity parameters
In your Centura SQLWindows application you can get and set a number of
parameters that affect transaction processing and other activities or attributes related
to connectivity.
The following parameters can be retrieved with SqlGetParameter and set with
SqlSetParameter:

DBP_AUTOCOMMITWhether autocommit is on or off.

DBP_BRANDThe vendor of the database you are connected to.

DBP_LOCKWAITTIMEOUTTime limit on waiting for a lock to be


released.

DBP_PRESERVEWhether cursor context preservation is on or off.

DBP_VERSIONThe version of the database to which you are connected.

DBP_ROLLBACKONTIMEOUTWhether the most recent transaction is


rolled back if a time-out expires.

The library file SQLNWKCN.APL (in the Centura installation directory) contains a
large number of user constants that you can retrieve with SqlGetParameterAll and set
with SqlSetParameterAll. To use these constants, include this file in your Centura
SQLWindows application. Open this file with File, Open from the Centura
SQLWindows menu bar and expand the user constants section of the outline to see
the constants defined.
For example, to set the size of the buffer used to hold LONG data to 2000 bytes,
include this line in your application:
SqlSetParameterAll(hSql,DBP_LONGBUFFER,2000,,TRUE)

Connect search order


The name of the database your Centura SQLWindows application tries to connect to
(the target database) must be assigned to the global variable SqlDatabase before the
application calls SqlConnect. Before the application actually tries to connect to the
database, it searches each router-specific section of the SQL.INI file for a
remotedbname statement that lists the target database name.
The order in which you list the different SQLRouters (using the comdll keyword)
in the SQL.INI file determines the order in which the router-specific sections are
searched. For example, if the DLL for SQLRouter/Oracle is listed first in the

1-6

Connecting Centura Objects to Databases

Cursor context preservation

comdll statements, the Oracle-specific section of the file, namely [oragtwy], is


searched first.
If a remotedbname statement is found that lists a name matching the name of the
target database, the application tries to connectif the attempt to connect fails, the
application gets an error.
If no remotedbname statement is found that lists a name matching the name of the
target database, the router-specific section for the next SQLRouter in the sequence of
comdll statements is searched. This continues until a matching database name is
found, or until the sequence of comdll statements is exhausted.
A slight variation applies to SQLRouter/ODBC and SQLRouter/Microsoft SQL
Server. Instead of searching the [odbcrtr] section of SQL.INI for a
remotedbname statement, the application tries to find an ODBC data source name
in the ODBC.INI file that matches the target database name. Otherwise, the
processing is the same as for all the other SQLRouters.
For more information about the SQL.INI file, read Initializing Centura SQLWindows
applications on page 2-4. For more information about the remotedbname
statement, read the SQL.INI keywords section for each of the database servers
(Oracle, Informix, and so forth) you will connect to.

Cursor context preservation


Cursor context preservation (CCP) preserves any result sets (including FERSsee
Front end result sets on page 1-8) that you retrieved during a transaction, as well as
the cursors associated with those result sets, even after you do a COMMIT. You also
maintain the locks you obtained during the transaction.
Not all databases support CCP. CA-OpenIngres does not. If the database you are
connecting to does not support CCP, or it supports it but you have turned it off, you
lose all result sets and their associated cursors when you do a COMMIT; you also
release all locks obtained during the transaction.
Note: Centura SQLWindows turns CCP off by default.
If CCP is off and you commit the current transaction (either explicitly or because
autocommit is on), you lose all open result sets and all prepared statements are
invalidated. If CCP is on, however, the result sets remain open even after the commit.
Important: If you roll back the transaction, you lose all open result sets even if CCP is on.

Connecting Centura Objects to Databases

1-7

Chapter

Overview

If autocommit is off and you change the setting of CCP during the course of a
transaction, the new setting for CCP does not take effect until you commit or roll
back the current transaction.
To turn CCP on, include the statement:
Call SqlSetParameter(hSql, DBP_PRESERVE, TRUE, strNull)

in your Centura SQLWindows application. Call this function for each SQL handle
associated with the result sets you want to maintain context forsee Handles,
contexts, and connections on page 1-9 for related information.
Important: If your application performs a ROLLBACK, all result sets (whether backend
result sets or FERS) and their cursors are discarded even if CCP is enabled.

If you are using front end result sets (FERS) and you have enabled CCP, the rows in
the result set remain available to your application even after you execute a COMMIT.
However, the data in the FERS file is not updated to keep it in sync with any changes
made to the corresponding rows on the database server. If other clients make changes
to the table on the server, the FERS data will be out of date. To learn more about
FERS, read the section Front end result sets on page 1-8.
To find out if the database you are connecting to supports CCP, read the chapter in
this book that covers that database.

Front end result sets


If you turn on result set mode (read Result set mode on page 1-19) in your Centura
SQLWindows application, the user of your application can scroll both backwards and
forwards through a result set returned from the database; the user then has a
scrollable cursor. If you turn off result set mode, the user of your application can
scroll only forwards through the result setnot backwards.
Note: In Centura SQLWindows, result set mode is off by default.
If you turn on result set mode, and your application is connected to a database that
has native support for scrollable cursors (sometimes called backend result sets or
backend cursors), Centura SQLWindows uses that support to allow the user to scroll
in both directions through a result set. If the database does not have native support for
scrollable cursors, Centura SQLWindows implements this capability using front end
result sets (FERS).

1-8

Connecting Centura Objects to Databases

Handles, contexts, and connections

Note: Even if the target database supports (backend) scrollable cursors, this feature must first
be enabled on the database for your application to use it.

To implement FERS, the SQLRouter software takes a snapshot of the result set
returned by a SELECT statement and stores it in a temporary file on the client. Each
file is named FRSn (with no extension), where n is a positive integerthe first file is
named FRS1; the second, FRS2; and so on.
SQLRouter needs two file handles for every FERS file it creates. If SQLRouter
cannot obtain the file handles, it returns an error to the application.
These FERS files are deleted when your Centura SQLWindows application attempts
to prepare another SQL statement or disconnects from the database server. If the
application ends abnormally and leaves these files, you must delete them manually
look for them in the standard directory where temporary files are stored.
Note: If your application is using FERS, you can release all shared locks on the result set
returned by your SELECT statementcall SqlGetResultSetCount. To learn more about this
function, read the Centura SQLWindows Function Reference.
You cannot SELECT...FOR UPDATE (use positioned cursors) if the named cursor is
associated with a front end result set. In other words, you cannot lock on the server
the rows that are being displayed on the client. The data the user sees on the client
may not match the data on the server if another application makes changes to those
same rows.
For information on result set mode and how to enable it, read Result set mode on page
1-19. For information on FERS and cursor context preservation (CCP), read Cursor
context preservation on page 1-7.

Handles, contexts, and connections


For a SQLRouter, a Centura SQLWindows SQL handle identifies a context for the
separate preparation (compilation) and execution of SQL statements, and (for
SELECT statements) the accessing of rows from a result set. The handle also
identifies a separate context for communication between the application and the
server. If allowed by the target database server, a Centura SQLWindows application
can have multiple connections to a database, and multiple open handles on any given
connection.
A Centura SQLWindows application opens a connection to a database when it makes
its first call to SqlConnect; at the same time, the application obtains its first handle
this allows the application to prepare and execute SQL statements. Associated with
this connection are a database name, user ID, and password. When the application
Connecting Centura Objects to Databases

1-9

Chapter

Overview

makes additional calls to SqlConnect, SQLRouter uses the same connection to the
database, but establishes a new context. If you pass a new SQL handle variable as the
argument to SqlConnect (the normal case), you continue to have access to all the
other contexts you created with earlier calls to SqlConnect.
This architecture allows you, for example, to obtain a result set, position the result set
cursor to the desired row, then update the row without losing the result set or the
execution plan for the SELECT statement that obtained the result setfor more
information, see Positioned updates on page 1-17.
Note: Some Centura documentation refers to the SQL handle as a cursor. This is very
different from the ANSI use of the term cursor, which is a pointer to a given row in a result set.

In general, a Centura SQLWindows application that uses multiple handles does one
of the following:

Connects to the same table for two different activitiesthe first handle is
used to prepare and execute a SELECT statement to obtain a result set, then
fetch the desired row from that result set; the second handle is used to prepare
and execute the SQL statement that modifies the result set (UPDATE,
INSERT, or DELETE).

Connects to two different tablesthe handle is used to prepare and execute


the SQL statement that updates a column in one table based on a value from
another table obtained by preparing and executing a different SQL statement.

Connects to two different databaseseach handle identifies a separate


context for preparing and executing SQL statements.

In general, different SQL handles, while they identify separate contexts for preparing
and executing SQL statements, are all part of the same transaction scope. Therefore,
if you execute a COMMIT or ROLLBACK statement on any handle, the database
server commits (or rolls back) the results of all of the uncommitted SQL statements
executed on all of the open handles connected to a given database.
Note: When it comes to committing statements, some databases distinguish between Data
Manipulation Language (DML) statements and Data Definition Langauge (DDL) statements.
With these databases, DDL statements are always committed, whereas DML statements are
committed only if the COMMIT statement (or the SqlCommit function) is executed. In other
databases, neither DML nor DDL statements are committed until COMMIT is executed (or
SqlCommit is called). This whole discussion assumes, of course, that autocommit is off.
The maximum number of handles and connections your application can have depends
on your client operating system resources and any limits imposed by the target
database serverCentura SQLWindows itself imposes no limitations.

1-10 Connecting Centura Objects to Databases

IMAGE column types

For related information, read Transactions on page 1-22.

IMAGE column types


A Centura SQLWindows application can read, write, and update LONG BINARY
data (IMAGE data) using regular SQL statements (SELECT and UPDATE). This is
true even though Centura SQLWindows does not have a native LONG BINARY data
type. Instead, Centura SQLWindows converts LONG BINARY data to LONG
STRING data when reading, and LONG STRING data to LONG BINARY data when
writing.
When writing LONG STRING data to IMAGE columns, the bind variable that
contains the data must be bound to the appropriate data type by calling
SqlSetLongBindDatatype.

Writing data to an IMAGE column


1.

Assign the data to a Centura SQLWindows LONG STRING variable. The data
must use the correct syntax for the column where it will be stored.

2.

Prepare the SQL statement that will update the appropriate value in the table.

3.

Set the binding of the LONG STRING variable to type LONG BINARY (numeric
value of 23) by calling SqlSetLongBindDatatype with the correct parameters.

4.

Execute the prepared SQL statement.

The syntax of SqlSetLongBindDatatype is:


bOk = SqlSetLongBindDatatype(nBindVarNumber,
nDatatype)
where both arguments are of type Number.
The first parameter identifies the bind variable to be set by its ordinal position in the
prepared SQL statementuse 1 to denote the first bind variable in the SQL
statement, 2 to denote the second bind variable, and so forth; the second parameter
indicates the data type to which the bind variable should be set (LONG BINARY).
Note: The numeric value to use as the second parameter is 23 (for LONG BINARY). To make
your code self-documenting, you should create a symbolic constant with that value, then use the
constant as the parameter.

For example:
Constants
System
User

Connecting Centura Objects to Databases

1-11

Chapter

Overview

Number: LONGBINARY = 23
Local Variables
String: strName
Long String: strPhoto
...
Actions
...
SqlConnect(hSql)
...
! Assume we have read a name into strName and a .BMP file
! into strPhoto. We want to update a particular employees
! photo in the database.
Call SqlPrepare(hSql, UPDATE emp ||
SET emp_name = :strName,image_col = :strPhoto )
! Because the bind variable :strPhoto is the second bind
! variable in the SQL statement we just prepared, we set
! the nBindVarNumber parameter of SqlSetLongBindDatatype to 2.
Call SqlSetLongBindDatatype(2, LONGBINARY)
Call SqlExecute(hSql)

SqlSetLongBindDatatype should be called immediately after the call to SqlPrepare.


The binding established with SqlSetLongBindDatatype lasts until the next call to
SqlPrepare on the same SQL handle.
Note: Centura SQLWindows automatically converts between LONG STRING and TEXT
data; you do not need to call SqlSetLongBindDatatype when reading and writing TEXT data.

Isolation levels
Isolation levels control how access to the tables in a database by one user affects
other users accessing the same tables in that database. These isolation levels are
implemented by locks and apply to all SQL statements executed as part of a single
transaction.
The isolation level you choose depends on the applications requirement for
consistency and concurrency.
Consistency means that during a transaction, the data read remains stable. This
implies that the data being read by one transaction does not change because of
updates, deletes, and inserts performed by other transactions.
Concurrency is a function of the number of users that can access data at the same
time. High concurrency allows multiple users to execute database transactions

1-12 Connecting Centura Objects to Databases

Isolation levels

simultaneously without interfering with each other, but at the possible expense of
consistency.

Isloation level terms


Isolation levels are often defined in terms of the following phenomena:

dirty read Transaction A changes one or more column values in a row.


Transaction B reads the same row, after which transaction A rolls back its
changes. Transaction B has now read values that (from a transaction-oriented
point of view) never existed.

nonrepeatable read Transaction A reads a row. Transaction B either


updates or deletes the row. Transaction A cannot now repeat the read of that
row and get the same results; either the values are different or the row no
longer exists.

phantom row Transaction A performs a SELECT on a table. Based on


the selection criteria in the SELECT statement, a set of rows is returned to A.
Transaction B inserts one or more new rows into the same table with values
that happen to match the selection criteria of the SELECT statement used by
A. If transaction A re-executes the same SELECT statement, it obtains a
different set of rows than it did the first time.

Note: This discussion applies to Centura applications. If using SQLTalk, the default isolation
level, irrespective of the database to which you connect, is always RR (repeatable reads).

Choose the appropriate isolation level for your applications depending on the balance
you need to achieve between data access concurrency and data consistency.

Isolation reads by server


Centura SQLWindows provides four different two-letter codes you can specify when
you set an isolation level. The table below shows you the isolation level you get
depending on the code you specify and the database server you are connected to.
Microsoft SQL
Server/ODBC

Sybase
System
11

CAOpenIngres

Code

Oracle

Informix

Default*

not applicable

committed reads

read_committed

Level 1

repeatable
reads

RO

not supported

dirty reads

read uncommitted

Level 0

not applicable

RL

not supported

committed reads

read committed

not
supported

not applicable

Connecting Centura Objects to Databases

1-13

Chapter

Code

Overview

Oracle

Informix

Microsoft SQL
Server/ODBC

Sybase
System
11

CAOpenIngres

CS

not supported

cursor stability

repeatable reads

Level 1

not applicable

RR

not supported

repeatable reads

serializable

Level 3

not applicable

Isolation level setting.


* Default is not an actual code. This row indicates the isolation level you get when
you first connect to the given database server.
Note: Microsoft SQL Server supports the isolation levels listed in the column Microsoft SQL
Server/ODBC. For ODBC data sources on other than Microsoft SQL Server, the Centura
SQLWindows ODBC router attempts to set the very same mapping of two-letter codes to
isolation levels; however, which isolation level (if any) is actually implemented for a given code
depends on the ODBC driver and the database server you are using to access your data source.
Your ODBC driver and database server documentation should provide the information you
need.

Note: CA-OpenIngres servers do not support isolation levels. Use the SET LOCKMODE
statement to set different types and levels of locks. The default lock is Shared for read and
Exclusive for write.
If you try to change isolation levels while a transaction is pending, what happens
depends on the database server:

OracleThe attempt to change isolation levels is ignored.

Informix and Microsoft SQL ServerThe pending transaction is first


committed, then the isolation level is changed as requested.

Sybase System 11The request is rejected and an error is raised.

To set the isolation level in your application, call SqlSetIsolationLevel. For example,
to set the isolation level to SQL_TXN_SERIALIZABLE on Microsoft SQL Server
6.0, put the statement:
Call SqlSetIsolationLevel(hSql,RR)

in your Centura SQLWindows application. See the Centura SQLWindows Function


Reference for more information about this function.

1-14 Connecting Centura Objects to Databases

Lock time-out

Important: Read the chapters that covers the databases to which you are connecting to find
out the kinds of isolation levels that are supported on those databases, and the appropriate
arguments to use when calling SqlSetIsolationLevel.

Lock time-out
Lock time-out is the amount of time spent waiting for a resource to become available.
If an action cannot be completed within the set limit, the transaction is aborted and
any changes are rolled back.
To enable lock time-out, call SqlSetLockTimeout, or call SqlSetParameter with the
DBP_LOCKWAITTIMEOUT parameter. (For more information about these
functions, refer to the Centura SQLWindows Function Reference and the on-line
help.)
Read the chapter that covers the database to which you are connecting to find what
kind of lock time-outs (if any) are supported on that database.

Nulls, empty strings, and spaces


Given a column that is of some character string data type, you can in general insert (or
update) the data in that column using any one of three different values that you may
think are similar to each other, but are actually quite distinct:

NULLThis value denotes undefined value. Use NULL to indicate that


there is no information available for that column. You can put NULL into a
column only if you defined the column to allow NULLs when you created the
table that has that column.

Empty stringThis is a string of length zero. It is an actual string value. If


a character string column has the empty string, the value of the column is
defined. (This is unlike NULL, which means that the value of the column is
undefined.)
To actually store the empty string in a column, you must be able to define the
column to be a varying-length character type, where the length varies from
zero to some positive number. If you define the column to be a fixed-length
character type, the value you insert (or update) is padded with spaces if it is
shorter than the fixed length defined for that column. The empty string has a
length of zero, so it is always padded with spaces (it is always shorter than the
fixed length defined for the column). Thus, in the case of a column of a fixedlength string data type, the database always stores a string of spaces in place
of the empty string. (If you concatenate the empty string with any string X,
the result is the same string X.)

Connecting Centura Objects to Databases

1-15

Chapter

Overview

SpaceThis is a string of length one. It is no different from any other string


of length one as far as the database is concerned. The only thing special about
a space is that it is harder for you to see a space than most other strings of
length one.

All databases will store a space in a character string column. If you allow NULLs in a
character string column when you create the table with that column, the database will
also store a NULL. However, different databases store different values in a (varyinglength) character string column when you try to store the empty stringsome do
store the empty string, some store NULL, and others store a space.
When inserting or updating a string column in a database table in such a way as to
indicate that there is no data in the column, you typically enter a NULL (if the table
allows this), the empty string (also called the zero-length string), or a space. Which of
these you values you use depends on whether the table allows NULLs in the column
and how your application is written.
The table below shows what value is actually stored in the database, depending on the
database server and the value supplied by the client.
Note: To use STRING_Null, you must assign it to a String variable, then use that variable as
a bind variable in your SQL INSERT or UPDATE statement.

Client Entry

Oracle

Informix

Microsoft
SQL Server

Sybase System
11

CA-OpenIngres

empty string
()

NULL

space

space

space (constant)
NULL (bind
variable)

space (constant)
NULL (bind
variable)

NULL

NULL

NULL

NULL

NULL

NULL

space

space

space

space

space

space

STRING_Null

NULL

NULL

NULL

NULL

NULL

Actual value stored.


Note: The behavior of an ODBC data source depends on the driver and the database
server you connect to.

Using NULL
To insert NULL into any of the string columns of your database tables, or to update
such columns with NULL (assuming the columns allow NULLs), you must:
1.

Set a String variable to the predefined constant STRING_Null.

1-16 Connecting Centura Objects to Databases

Positioned updates

2.

Prepare and execute a SQL INSERT or UPDATE statement using the variable in
step 1 as a bind variable.

For example:
Set strVar = STRING_Null
. . .
SqlPrepareAndExecute(hSql, `UPDATE my_table SET this_column = :strVar`)

Important: You must explicitly set the String variable to STRING_Null because Centura
SQLWindows initializes all String variables to the empty (zero-length) string. Only by using a
bind variable set to STRING_Null (rather than the empty string) can you store NULL in the
string columns of your database tables.

To test whether a string column value you fetch from one of the tables in your
database is NULL, you must compare the variable into which you fetched the value to
the constant STRING_Null.
For example:
SqlPrepareAndExecute(hSql, `SELECT string_col FROM my_table INTO
:strColValue`)
IF strColValue = STRING_Null
. . .

Note: You can also hard-code the NULL in a SQL statement, if appropriate.

Positioned updates
Centura SQLWindows applications can perform positioned updates (WHERE
CURRENT OF cursor updates) when connected to certain databases. For positioned
updates to be possible:

You must create a unique index on one of the table columns (Microsoft SQL
Server version 6.x only).

You must turn on result set mode (scrollable cursors).

Coding a positioned update


1.

Create a unique index on one of the table columns (Microsoft SQL Server version
6.x only).

2.

Connect twice to obtain two distinct SQL handles.

3.

Enable result set mode (scrollable cursors), specifying one of the SQL handles
obtained in the previous step.

Connecting Centura Objects to Databases

1-17

Chapter

Overview

4.

Using the same SQL handle as in the previous step, execute the SELECT... FOR
UPDATE statement to retrieve the key column value, and any other columns of
interest from the table.

5.

Using the same SQL handle as in the previous step, create a named cursor by
calling SqlOpen.

6.

Position the cursor to the appropriate row (using, for example, the SqlFetchNext,
SqlFetchPrevious, or SqlFetchRow functions).

7.

Using the other SQL handle, prepare and execute an UPDATE statement with the
WHERE CURRENT OF cursor clause. Specify the cursor that was named with
SqlOpen.

The following code fragment illustrates the highlights. In addition to providing an


example of the steps listed above, this fragment shows the creation of the table to be
accessed and the creation of the unique index. Replace numeric_data_type with an
appropriate numeric data type for your database.
Important: You need to execute the CREATE UNIQUE INDEX statement (included in the
code below) only when connected to Microsoft SQL Server version 6.x. For other databases,
omit this statement.
Call SqlConnect(hSqlA)
Call SqlConnect(hSqlB)
Set strCreateTable = CREATE TABLE REALTY
Set strCreateTable = strCreateTable || (PROPNUM INT,
Set strCreateTable = strCreateTable || CITY VARCHAR(30),
Set strCreateTable = strCreateTable || PRICE numeric_data_type)
Call SqlPrepareAndExecute(hSqlA, strCreateTable)
Set strCreateIndex = CREATE UNIQUE INDEX REALTY_IDX
Set strCreateIndex = strCreateIndex || ON REALTY(PROPNUM)
Call SqlPrepareAndExecute(hSqlA, strCreateIndex)
Call SqlSetResultSet(hSqlA, TRUE)
Call SqlPrepareAndExecute(hSqlA, SELECT PROPNUM, CITY, PRICE
FROM REALTY
FOR UPDATE
INTO :COL1,:COL2,:COL3)
If NOT SqlOpen(hSqlA, CUR1)

If NOT SqlFetchNext(hSqlA, nRetVal)

If NOT SqlPrepare(hSqlB, UPDATE REALTY


SET PRICE =:COL3
WHERE CURRENT OF CUR1)

1-18 Connecting Centura Objects to Databases

Result set mode

! If no problem preparing the UPDATE statement, do it.


Else Call SqlExecute (hSqlB)

Read the chapter that covers the database to which you are connecting to find out if
that database supports positioned updates.

Result set mode


You turn on result set mode in your Centura SQLWindows application to allow a user
of your application to scroll both forwards and backwards through a result set
returned by the database.
Result set mode is off by default when you connect to any of the databases covered in
this book. When result set mode is off, there are several consequences for your
application:

You can retrieve only one result set at a time.

The cursor can move forward only.

You must fetch all rows from the result set before retrieving another result set
or executing another SQL statement (for example, CREATE TABLE), even
on another handle. This means that, as long as a result set retrieved on a given
SQL handle is pending (you have not yet fetched all the rows), your
application cannot perform any operations on any other SQL handle in the
application.

Important: None of these restrictions applies if you turn on result set mode.

Turning the mode on and off


To turn on result set mode, include the statement:
Set SqlResultSet=TRUE

in your Centura SQLWindows application (before calling SqlConnect). You can also
include the statement:
Call SqlSetResultSet(hSql,TRUE)

in your application. Make this call before you prepare and execute the SELECT
statement that retrieves the result set for which you want the cursor to be scrollable.
To turn off result set mode, specify FALSE (instead of TRUE) in the Set and Call
statements.
If you turn on result set mode for a database server that does not support scrollable
cursors (sometimes called backend cursors), the SQLRouter software makes use of
front end result sets (FERS) to get the same effectfor more information, read Front
end result sets on page 1-8.

Connecting Centura Objects to Databases

1-19

Chapter

Overview

To find out if the database you are connecting to supports scrollable (backend)
cursors, read the chapter in this book that covers that database.

Initial setting
When a Centura SQLWindows application first starts up, the value of the global
system variable SqlResultSet is undefined (null). As long as the variable's value
remains undefined, result set mode is initially on for all your connections to SQLBase
and initially off for all your connections to all other database servers.
If you set SqlResultSet to TRUE, result set mode is initially on for any subsequent
connection you make to any database server, including SQLBase. If you set
SqlResultSet to FALSE, result set mode is initially off for any subsequent connection
you make to any database server, including SQLBase. In either case, if you then set
SqlResultSet to NUMBER_Null, result set mode is initially on for all your
subsequent connections to SQLBase and initially off for all subsequent connections
to all other database servers.
Important: Changing the value of the global variable SqlResultSet does not affect the setting
of result set mode for any existing connection. To change the setting of an existing connection,
you must call the function SqlSetResultSet.

With Microsoft SQL Server 6.x or any ODBC data source, even though you specify a
specific SQL handle as an argument to SqlSetResultSet, the new setting for result set
mode affects all SQL handles on the same connection, not just the SQL handle you
pass as an argument. If you connect natively to Oracle, Informix, or Sybase System
11, however, the new setting for result set mode affects only the handle you specify as
an argument to SqlSetResultSet.

Affects of setting the mode


The setting of result set mode may affect whether or not you can have multiple open
result sets (concurrent cursors). With CA-OpenIngres, using multiple concurrent
result sets, you should set SqlResultSet prior to any SqlConnects. Otherwise, you
have to use the function call after each connect.
Also, the setting of result set mode may affect stored procedures that return result
sets:

Microsoft SQL Server 6.xYou must always turn off result set mode
before calling a stored procedure if it returns one or more result sets. Once
you return from the stored procedure, you can turn result set mode back on if
you wish.

ODBC data sourceAny special requirements, restrictions, or side effects


depend on which ODBC driver you are using and the data source you are

1-20 Connecting Centura Objects to Databases

SQL.INI keywords

accessing. Read your driver and database server documentation for more
information.

OracleWhen you call SqlPLSQLCommand, Centura SQLWindows


automatically turns off result set mode for the SQL handle you supply as an
argument. Once you return from the call to SqlPLSQLCommand, you can
turn result set mode back on if you wish.

See the table below for more information.


Attribute

Oracle/Informix

Microsoft SQL Server/


Sybase System 11

CA-OpenIngres

default*

OFF

OFF

OFF

scrollable cursors

must be ON

must be ON

must be ON

concurrent result sets

can be ON/OFF

must be ON

must be ON (make sure


autocommit is OFF)

positioned updates or
deletes using a cursor
on a stored procedure

can be ON/OFF

not supported**

not supported

Status of Result Set mode.


* This row is correct if the global variable SqlResultSet is either null or FALSE.
** When connected to Sybase System 11, you can declare a cursor on a stored
procedure and fetch rows from a result set returned by that stored procedure;
however, you cannot do positioned updates or deletes on the result set using that
cursor.

SQL.INI keywords
All Centura SQLWindows applications initialize themselves by reading the SQL.INI
file. To find out more about this file, read Initializing Centura SQLWindows
applications on page 2-4.

Stored procedures
Most databases allow procedures containing SQL statements and procedure logic to
be compiled and executed on the database server. These procedures can return result
sets, and some can accept input bind variables (host variables) as arguments. If the
target database supports stored procedures, you can call them from a Centura
SQLWindows application.

Connecting Centura Objects to Databases

1-21

Chapter

Overview

Using stored procedures can improve application performance by reducing network


traffic and executing compiled SQL operations on the server. Because stored
procedures are compiled, the execution plans are stored in a system table; this allows
the stored procedure to execute very quickly. Stored procedures can enhance security
by acting as a controlled access point to sensitive data. They can also increase the
robustness and reliability of distributed processing by centralizing critical or core
application logic in one location (the server).
Depending on the database server you are connecting to, you may be able to pass
input arguments, retrieve values in output arguments, retrieve a result status from the
stored procedure, and retrieve result sets. In some cases you may be able to specify
input arguments and retrieve output arguments using bind variables. Read the chapter
that covers the database to which you are connecting to find out if that database
supports stored procedures, how to call them, and any other information specific to
that databases support for stored procedures.

Transactions
A transaction is a set of actions on a database that are treated atomicallyall of the
actions are made permanent in the database or none of them are. Normally, you make
all the actions permanent by preparing and executing the COMMIT statement (or
calling SqlCommit); if you want to abandon all the actions (undo them), you prepare
and execute the ROLLBACK statement.
There is no SAL function that corresponds to SqlCommit. To roll back a transaction,
you prepare and execute the ROLLBACK statement. For example:
SqlPrepareAndExecute(hSql,ROLLBACK)

Each COMMIT or ROLLBACK statement defines a new transaction boundary; all


the statements whose actions are made permanent with COMMIT (or undone with
ROLLBACK) are part of the transaction scope.
For additional information, read Autocommit on page 1-3 and Handles, contexts, and
connections on page 1-9.

1-22 Connecting Centura Objects to Databases

Connecting Centura Objects to Databases

Chapter 2

Initializing and Testing


Your Connection
This chapter describes how to connect a Centura SQLWindows application to a
database, how to test the connection, and how to configure the initialization of the
client.

Connecting Centura Objects to Databases

2-1

Chapter

Initializing and Testing Your Connection

Synopsis of what to do
1.

Install your network protocol software (such as TCP/IP, NetBIOS, NetBEUI,


Named Pipes, or IPX/SPX) and the client-side software supplied by your database
vendor (network access layer software, API library, and client tools and utilities).
Follow the instructions in the documentation provided with those products.

2.

Verify that you can connect to your target database using a suitable tool provided
by your database or other vendor. If you need help, talk to your network or
database administrator.
Some of the tools available are:

InformixILogin.exe

OracleSQL*Plus (if you have a sufficiently recent version of the


database), Sample Pro C application

CA-OpenIngresTerminal Monitor

Microsoft SqlServerISQL/w

SybaseSQL Advantage

3.

Install Centura SQLWindows and choose the appropriate SQLRouters for the
databases you will be connecting to.

4.

Configure the target data source. (This applies only if you are connecting using
ODBC.)

5.

Configure the initialization of Centura SQLWindows by editing the SQL.INI file


appropriately.

6.

Verify that you can connect to the target database using Centura software by
running SQLTalk for Windows.

Additional information on steps 4 through 6 is provided after the next section.

Before connecting
Here are some things to check out before trying to connect a Centura SQLWindows
application to a database:

On the client machine:


Be sure all the software components listed in the Release Notes are installed
on the client computer.
Verify that you can connect to the target database using the appropriate
tools provided by the database vendor. Read the documentation supplied

2-2

Connecting Centura Objects to Databases

Configuring an ODBC data source

by the vendor to learn about such tools and how to use them to verify the
connection between your client and the database.
Check that the SQL.INI file contains the appropriate statements, and that the
keyword values are specified correctly. To learn more about this, read the rest
of this chapter, then read the chapters that cover the databases you are
connecting to.

On the server machine:


Check that the appropriate network software is running.
Be sure the database server is running and that the target database has been
created.
Verify that you have a user account with the correct privileges on the
database.

Note: Consult with your database administrator and network administrator for any additional
help you might need.

Configuring an ODBC data source


This section applies only if you are connecting to a database using ODBC (such as to
Microsoft SQL Server 6.x, DB2/400, Microsoft Access, dBASE, and so on).
The following procedure describes how to use the ODBC Administrator to add and
set up a data source.

Adding and setting up an ODBC data source


1.

Select Control Panel from the Start menu, then click the 32bit ODBC icon.

2.

In the ODBC Data Source Administrator window, click Add.

3.

The Create New Data Source dialog box is displayed with the list of ODBC
drivers installed on your machine. Select the appropriate driver from this list, then
click Finish.

4.

Fill in the necessary information in the displayed dialog box, then click OK. You
normally get the information you need to complete this dialog box from your
database administrator. You can also read the on-line help (click Help) or the
documentation supplied by your ODBC driver vendor.

5.

The data source you specified is added to the list of Data Sources in the ODBC
Data Source Administrator window and to the ODBC.INI file. Click OK to
finish.

Connecting Centura Objects to Databases

2-3

Chapter

Initializing and Testing Your Connection

Important: Do not edit the ODBC.INI file directlyuse the ODBC Administrator to make
any changes to your list of ODBC data sources. Also, check the documentation that comes with
your ODBC driver to see if your ODBC driver vendor also supports other ways of modifying
the ODBC.INI file.

Initializing Centura SQLWindows applications


All Centura SQLWindows applications (including Centura SQLWindows itself and
all its components) read the file SQL.INI before running. To configure the
initialization of your application, add, delete, or modify the statements in this file.
If you have installed other Centura Software products on your machine, a SQL.INI
file already exists. If you install Centura SQLWindows in the same directory as the
other Centura Software products, the installation program adds new statements or
modifies existing statements in the file.
Note: All statements from the old SQL.INI file are carried over into the new one.
You should have only one SQL.INI file on a computer. If you install Centura
Software products into different directories, you may find that you have multiple
copies of this file. Consolidate the information into one copy of the file and delete the
others.

Search path for

SQL.INI
Before running a Centura SQLWindows application, be sure SQL.INI is located in
one of the directories listed below. A Centura SQLWindows applications searches for
a file called SQL.INI as follows:
IF an environment variable called SQLBASE is defined
IF the SQLBASE variable defines a valid directory path AND a file called
SQL.INI is located there
Use that SQL.INI file
ELSE
Assume SQL.INI does not exist
ELSE
Search the following locations in order. Use the first file called SQL.INI that you
find:
1.

2-4

Current directory

Connecting Centura Objects to Databases

Initializing Centura SQLWindows applications

2.

\CENTURA directory of current drive

3.

Root directory of the current drive

4.

Every directory defined in the PATH environment variable

Note: Normally, you should have a single SQL.INI file on your computer so that you are sure
you know the configuration values that will be used when running Centura SQLWindows and
other Centura applications. If you have more than one SQL.INI file, the configuration values
used will depend on which file is found first according to the above algorithm.

How

SQL.INI

is structured
SQL.INI is a simple text file that you modify using any ASCII text editor.
The file is subdivided into sections. Each section starts with a section name, a
character string enclosed in square brackets. Each section contains zero or more
statements. Each statement starts with a keyword, followed by the equals sign and a
sequence of comma-separated values:
[section_identifier]
keyword1=parameter1(,parameter2 ... )
keyword2=parameter1(,parameter2 ... )

keywordn=parameter1(,parameter2 ... )
When this book describes a default value for a SQL.INI keyword, this is either the
value as defined in the SQL.INI file before a user has edited it, or the value assumed
when the statement containing the keyword is absent or commented out.
The order in which the sections appear is not significant. For most sections, the order
of keywords within a section is also not significant. The only exception is the order of
the comdll keywords in the [win32client.dll] section, and the order of the
remotedbname keywords in the sections assigned to each individual database.
When a Centura SQLWindows application initializes, it tries to make a connection to
a database following the order of the routers listed using the comdll keywords; for
each router, the application tries to connect to a database in the order specified by the
appropriate remotedbname keywords.
If you connect natively to Oracle, Informix, CA-OpenIngres, or Sybase System 10
and System 11, the longbuffer keyword in the SQL.INI file specifies the maximum
number of bytes of long data type columns to retrieve, and truncates excess bytes.
However, this keyword does not control how much long data can be inserted or
updated.
If you connect to Microsoft SQL Server 6.x or any data source using ODBC, this
keyword controls how much long data can be fetched, inserted or updated.

Connecting Centura Objects to Databases

2-5

Chapter

How to edit

Initializing and Testing Your Connection

SQL.INI
List parameters for a keyword in the order indicated in the Syntax section of
the reference page for that keyword. Parameters may be ASCII alphanumeric
characters onlyno underscores, hyphens, or periods.

Carefully check the syntax of a keyword statement; in most cases, you use
commas (not spaces) to separate parameters.

Put each statement on one line. Inserting carriage returns or any end-of-line
markers in the statement can cause errors.

Put comments on their own lines rather than placing comments on the same
lines as keyword statements. Use a semi-colon (;) as the first character of the
comment line.

A Centura SQLWindows application reads the SQL.INI only when it initializes. To


force an application to see any changes you make to the file, you must stop or exit
from all Centura software running on the client (including Centura SQLWindows and
all running applications created with Centura SQLWindows), then restart the
application.
Important: If you use a word processor instead of a text editor to modify the SQL.INI file,
save the file as text only. Otherwise, the word processor inserts control codes that corrupt the
file.
SQL.INI

keywords to use
To learn how to set up the SQL.INI file, read the appropriate chapter for the database
to which you are connecting.
Important: The SQL.INI file must always have at least one comdll statement identifying
the SQLRouter to be used when connecting to a database.

Testing the connection


To test the connection between the Centura software running on your client machine
and the database, run SQLTalk for Windows and try to view a table you know is in
the database and that you have permission to look at.
Important: Be sure to verify that you can connect to the target database using the tools
provided by your database (or other) vendor before using SQLTalk.

2-6

Connecting Centura Objects to Databases

Connecting to Sybase

Testing the connection with SQLTalk


1.

Start SQLTalk for Windows by running the executable file sqltalk.exe in the
Centura installation directory.

2.

Select Session,Connect from the SQLTalk for Windows menu bar to display the
Connect dialog box. Fill in the database name, your user name, and your
password.

3.

Verify that the connection information appears in the Current Connections box of
the Connect dialog boxthis confirms that you have successfully connected to
the database. Click Close in the Connect dialog box.

4.

Select File, Exit from the SQLTalk for Windows menu bar.

If you see the connection information in the Current Connections box of the Connect
dialog box, you have correctly configured your client machine to communicate with
the target database from a Centura SQLWindows application.
Note: For more information on how to use SQLTalk, read the Centura on-line help topics for
SQLTalk.

Connecting to Sybase
You do not need to run catalog view scripts before running your Centura
SQLWindows applications against Sybase System 11.x, because SQLRouter/Sybase
can access the system catalog directly whenever necessary.
However, you need to obtain suitable privileges for each System 11.x database you
will connect to before you can run Centura SQLWindows or an application you create
with Centura SQLWindows.
For each such database:
1.

Log in as a user who has System Administrator privileges.

2.

Run the program SYBPRIVS.EXE (located in the Centura installation directory).

Connecting Centura Objects to Databases

2-7

Chapter

Initializing and Testing Your Connection

Connecting to Oracle
To connect to Oracle, you may have to make certain changes to your Windows NT or
Windows 95 Registry. You must also create certain views to access tables and (in the
case of Oracle8) to run stored procedures.

Modifying the Registry


To allow your Oracle client-side software (OCI libraries and SQL*Net) to work
together properly, you need to modify the Oracle section of your Windows NT or
Windows 95 Registry. If you are using version 7.0.x, version 7.1.x, or version 7.2.x,
8.0.x of the Oracle client-side software, add one of the following entries to the
Registry:
Client-side version

Entry to Add to Registry

Version 7.0.x

ORAOCI=ORA7NT.DLL

Version 7.1.x

ORAOCI=ORA71.DLL

Version 7.2.x

ORAOCI=ORA72.DLL

Version 7.3.x

ORAOCI=ORA73.DLL

Version 8.0.x

ORAOCI=ORA83.DLL and
ORAOCI=ORA84.DLL

Creating views
Before you can access tables on Oracle V6, Oracle7 and Oracle8 you must run the
appropriate views script. You must also run a specific views script to be able to
execute stored procedures on Oracle 7 and Oracle8.

Accessing tables on Oracle V6


To access tables on Oracle V6, you must execute one of two scripts:
VIEWFAST.ORA or VIEWSLOW.ORA. Both of these scripts are located in the
Centura installation directory.
Before you run either of these scripts, the database administrator (or someone with
suitable authorization) must create on the database a user name called SYSSQL that
has DBA authority. When you run the script, sign on as SYSSQL.
The script VIEWFAST.ORA uses various undocumented system tables to gain faster
access to the system catalog. If this script does not run successfully, or if you wish to
avoid accessing undocumented catalogs, run the script VIEWSLOW.ORAthis script
accesses only the documented system tables.

2-8

Connecting Centura Objects to Databases

Connecting to Oracle

Accessing tables and stored procedures on Oracle7 and Oracle8


To access tables on Oracle7, you must execute the script VIEW7.ORA. To execute
stored procedures, you must execute the script PLSVIEW7.ORA. To access tables on
Oracle8, you must execute the script VIEW8.ORA. To execute stored procedures,
you must execute the script PLSVIEW8.ORA. These scripts are located in the
Centura installation directory.
When you run the script, sign on as SYS (or another user with the same authority as
SYS).
Also, if you need to access the SYS account, add a line with the substitute
keyword in the [oragtwy] section of file SQL.INI as follows:
substitute=SYSSQL.,

Note: Put a period after SYSSQL, then a comma, then press the RETURN key.
For more information about using the substitute keyword with Oracle, read
substitute on page 5-10.

Running a view script


1.

Start SQLTalk by running the executable file sqltalk.exe in the Centura


installation directory.

2.

Select Session,Connect from the menu bar. Fill in the dialog box with the
appropriate information.

3.

Once you are connected, click Close.

4.

Select File, Open from the menu bar.

5.

In the File of Type selection box, select All Files (*.*).

6.

Select the file VIEW8.ORA (or PLSVIEW8.ORA) in the Centura installation


directory if using Oracle8. Select the file VIEW7.ORA (or PLSVIEW7.ORA) if
using Oracle7.

7.

Select Session, Execute Script from the menu bar. Let the script run to
completion. (Ignore any error messages about tables being dropped.)

8.

Select File, Exit from the menu.

Note: For more information on how to use SQLTalk, read the Centura on-line help topics for
SQLTalk.

Connecting Centura Objects to Databases

2-9

Chapter

Initializing and Testing Your Connection

Specifying the database in your application


In your Centura SQLWindows application, you can identify the name of the database
to connect to with the SqlDatabase system variable. For example, if the name of
the database is ORDERS, include the statement:
Set SqlDatabase=ORDERS

in your application before calling SqlConnect.


Make sure the name of the database you assign is exactly the same as the name you
assign to the keyword remotedbname in the SQL.INI filesee the section
SQL.INI keywords in the chapter that discusses your target database. (If you are using
ODBC, make sure the name you assign to SqlDatabase is the name you used
when setting up the data sourcesee Configuring an ODBC data source on page 23.)

Troubleshooting problems
This section discusses some of the problems that can arise when connecting Centura
SQLWindows applications to your database and possible ways to resolve them. It
also has a table of some of the errors you may encounter when running Centura
SQLWindows applications along with suggestions for fixing them.

Problems connecting
When a Centura SQLWindows application initializes, it reads the SQL.INI file.
When the application reads the [win32client.dll] section of that file, it loads
all the DLLs specified in the comdll statements.
The application tries to connect to the database by calling the appropriate function in
each DLL loaded. If the DLL finds the requested database, it issues a database
connect request. If the DLL gets no response, it returns the failure to connect error
to the application, which then calls the appropriate function in the next DLL that was
loaded. This continues until either a connection is established or all the DLLs have
been tried.
If you have trouble connecting your Centura SQLWindows application to your target
database:
1.

Check with your database administrator that the target database is running.

2.

Verify that you can connect to the database from your client machine, first with
native client database tools (or equivalent), then with SQLTalk for Windows.

3.

Make sure you have just one SQL.INI file on the client machine.

2-10 Connecting Centura Objects to Databases

Troubleshooting problems

Important: If you have multiple SQL.INI files on your machine (which is possible if you
install different Centura Software products into different directories), the file that you modify
might not be the one being used at initialization time. Check the order in which directories are
searched for the SQL.INI filerefer to Search path for SQL.INI on page 2-4.
4.

Check that the appropriate comdll statements appear in the


[win32client.dll] section of the SQL.INI file. (Read the SQL.INI
keywords section in each chapter that discusses a database to which you are
connecting for more information about the comdll keyword.)

5.

Check that you have configured your remotedbname statements correctly.


(This step does not apply if you are connecting to your database using ODBC.)

Truncation of LONG data


If you find that data from LONG data columns is being truncated, you may not have
set the value for the longbuffer keyword high enough in the SQL.INI file. For
more information, read the longbuffer reference page in the appropriate chapter
for the database you are connecting to.

Logging ODBC API calls


If you connect to your database using ODBC, you can trace the sequence of API calls
made on behalf of your Centura SQLWindows application by including the statement
odbctrace=on and the statement odbctracefile=filename in the SQL.INI
file. Read the odbctrace and odbctracefile reference pages in the
appropriate chapter for the database you are connecting to for more information.

Checking the Release Notes


The Release Notes that accompany this product contain useful information about:

ProblemsAll known bugs fixed in a particular release, as well as those still


outstanding are listed. If the bug has been reported, you can ask Centura
Software for status on it.

Certified environmentsCertified environments and software are those that


have actually been tested by Centura Software, or that have been configured
and tested by other vendors using the Centura DCC (Database Connectivity
Configuration) facility. (For more information about DCC, read Chapter 10,
Certifying ODBC Drivers.)

Connecting Centura Objects to Databases

2-11

Chapter

Initializing and Testing Your Connection

Contacting technical support


Before contacting technical support with a problem, please record the following
information:
1.

Version numbers of:

Microsoft Windows NT or Windows 95

Centura SQLWindows

Centura SQLRouters

The communication software

The database server

2.

Version and date of the SQLWNTM.DLL dynamic link library.

3.

Amount of available memory and operating system resources.

4.

Name of the component with the problem (name of executables running, or GPF,
or error message).

5.

The exact text of any error messages.

6.

Contents of the following files:

SQL.INI

Client-side initialization files for your database

Any log files

Determine if you can reproduce the problem consistently. Write down the steps so
you can help your technical support engineer reproduce the problem. A sample
application that simply and reliably recreates the problem is the quickest and most
efficient way to get your problem resolved.
If you are reporting a documentation problem, note the page number in the printed
book, or the file name and topic title in on-line help.

2-12 Connecting Centura Objects to Databases

Troubleshooting problems

Selected errors and ways to fix them


The table below lists some of the errors that can be generated when running a Centura
SQLWindows application, and suggests possible remedies.
Problem

Reason

Remedy

111 SQL
application interface
recursively entered.

Application has re-entered the library


SQLWNTM.DLL while waiting for a
server request. SQLWNTM.DLL is reentrant only from different
applications.

Check for any re-entrancy (for


example, SAM_Timer messages
during asynchronous operations)
and disable them during server
requests.

135 Invalid
cursor handle.

A SQL handle was passed to a function


before a valid connection was
established.

Establish a valid connection


before passing a SQL handle to a
function.

201 No compiled
command.

The application is attempting to


perform an operation, and either it has
not compiled an SQL statement, or no
statement exists any longer (for
example, because a ROLLBACK was
executed).

Compile SQL statements before


executing them.

203 Invalid SQL


statement.

You constructed an SQL statement


with illegal syntax, or spaced the
statement over several lines without
concatenating the parts of the statement
correctly.

Check the syntax of your SQL


statement. Check the
concatenation of multi-line SQL
statements.

321 Insert or
update value too
long.

The converted binary value exceeds


either the capacity of the
communications API or the current
longbuffer setting.

Make sure the longbuffer


setting is not lower than the
communications API value.

9279 Cannot find


specified protocol
entry.

Usually this message means that the


specified protocol cannot find the entry
it is looking for in the
[win32client.dll] section of
the SQL.INI file.

Check that the comdll


statements are correctly specified
in the SQL.INI file. Check that
you have supplied all the needed
keywords in the SQL.INI file
that apply to the SQLRouters you
are using.

30002 Invalid
function call
sequence

The SAL functions used to invoke


stored procedures were called in an
invalid sequence.

Make the calls in the correct


sequence. (Read the Stored
procedures section of the chapter
for your database for more
information.)

Connecting Centura Objects to Databases

2-13

Chapter

Initializing and Testing Your Connection

Problem

30003 Invalid
attempt to obtain a
subsequent result
set.

Reason

Remedy

An attempt was made to get the next


result set from a stored procedure even
though there were no more result sets.

The end of result sets can be


detected by checking the
bEndOfResult flag in the
parameter list for the SAL
function that gets the next result
set. Error code 30003 is returned
if SqlExecute is called even
though bEndOfResult was TRUE.

Sample applications
Several sample Centura SQLWindows applications are installed in the SAMPLES
subdirectory of the installation directory for Centura SQLWindows.

About the sample applications


The sample applications listed in this section illustrate various aspects of coding a
Centura SQLWindows application in conjunction with a particular router and
database. The list of sample applications in this section are organized by target
database.

Microsoft SQL Server


The following two sample applications illustrate the calling of stored procedures on
Microsoft SQL Server that return result sets.

ODBSAL1.APP gives an example of calling the SAL functions


OdrExecuteProc and OdrGetNextResults.

ODBSAL2.APP gives an example of using the SAL functions


OdrPrepareProc and OdrPrepareNextResults.

For more information about these functions, read the section Stored Procedures in
chapter 4.
Note: Before running these applications, be sure to install (on the server) the sample PUBS
database supplied with Microsoft SQL Server.

Oracle
The sample application ORADEMO.APP shows how to use the SAL function
SqlPLSQLCommand to call an Oracle stored procedure. For more information about
this function, read the section Stored procedures on page 5-11.

2-14 Connecting Centura Objects to Databases

Sample applications

Sybase System 11.x


The following sample applications illustrate features you might use when running a
Centura SQLWindows application against Sybase System 11.x:

SQLSYBS1.APP shows how to use the SAL extensions supported by


SQLRouter/Sybase.

SQLSYBS2.APP shows how to use the SAL extensions supported by


SQLRouter/Sybase.

SQLSYBS3.APP shows how to use the specific SAL extensions


SybPrepareProc and SybPrepareNextResults.

SQLSYBS4.APP shows how to SELECT and INSERT binary data (for


example, IMAGE data) using the function SqlSetLongBindDatatype.

SQLSYBS5.APP shows how to insert or update long binary data (for


example, IMAGE data) using the function SybWriteText.

For more information about the extended SAL functions for Sybase System 11.x and
related information, read the sections Stored Procedures and, Writing and Retrieving
IMAGE and TEXT Data in chapter 6, and IMAGE Column Types in chapter 1.

Connecting Centura Objects to Databases

2-15

Connecting Centura Objects to Databases

Chapter 3

Connecting to Informix
This chapter describes how to connect Centura SQLWindows applications to
Informix databases. It describes (in alphabetical order) various features of Informix
that can affect the way you write your Centura SQLWindows application or the way
it behaves when you connect to it with SQLRouter/Informix.

Connecting Centura Objects to Databases

3-1

Chapter

Connecting to Informix

Before you begin


Please read all of Chapter 1, Overview and Chapter 2, Initializing and Testing Your
Connection before reading this chapter.
You connect Centura SQLWindows applications to Informix databases using the
Centura native router, SQLRouter/Informix.

Arithmetic functions
You can use the following arithmetic functions in your Centura SQLWindows
applications:
ABS, ACOS, ASIN, ATAN, ATAN2, COS, EXP, LOGN, LOG10, MOD, POW,
ROOT, SIN, SQRT, TAN.

Autocommit
Informix databases support autocommit. Autocommit is off by default.
Informix has three database modes: default, ANSI, and Transaction. The default
mode can be further configured into two submodes: log on and log off. These modes
(and submodes) are configured by the database administratoryou cannot configure
these from your application.
With the default mode in the log off submode, all the SQL statements you execute in
your application are committed automatically, regardless of whether you have turned
autocommit on or off in your application.
With the default mode in the log on submode, or the ANSI or Transaction modes, if
you turn autocommit on, all the SQL statements you execute in your application are
committed automatically; if you turn autocommit off, your application must
explicitly commit or roll back any SQL statements you have executed.
For more background information, read Autocommit on page 1-3.

Cursor context preservation


Informix supports cursor context preservation (CCP). In Centura SQLWindows
applications that connect to Informix, CCP is off by default.
When CCP is on, cursors are declared using the WITH HOLD option, ensuring that
the cursor remains open even after a COMMIT. The cursor is not closed until the
CLOSE cursor command is issued.
If CCP is on (and autocommit is off), you can continue to execute prepared SQL
statements (without preparing them again) even after you commit the transaction that

3-2

Connecting Centura Objects to Databases

Cursors

those statements are a part of. If CCP is off, however, you cannot re-execute those
SQL statements once you commit the transaction without preparing them again.
Further, if you roll back the statements, you cannot re-execute them even if CCP is
onyou must prepare those statements all over again before you can re-execute
them.
For background information, read Cursor context preservation on page 1-7.

Cursors
A Centura SQLWindows application that connects to Informix has no limit on the
number of cursors it can create and use. You can connect to more than one database
and more than one database server in the same application.
Note: You cannot open a cursor WITH OPTIMIZATION or READ ONLY.
For related information, read Handles, contexts, and connections on page 1-9.

Data types
The table that follows shows the mapping between the data types supported by an
Centura SQLWindows application and the data types supported by an Informix
database server.
Centura SQLWindows
Data Type
STRING

LONG STRING

NUMBER

Informix Data Type


CHAR (default is 1)
VARCHAR (online only)
INTERVAL
TEXT (255 or more bytes; online only)
BYTE (255 or more bytes; online only)
CHAR (255 bytes to 32,767 bytes; online only)
CHAR (255 bytes to 32,511 bytes; SE only)
VARCHAR (255 bytes; online only)
SMALLINT (-215 to 215-1)
SERIAL (1 to 231-1)
INTEGER (-232 to 231-1)
SMALLFLOAT
FLOAT
DOUBLE PRECISION
REAL

Connecting Centura Objects to Databases

3-3

Chapter

Connecting to Informix

Centura SQLWindows
Data Type

DATE/TIME

Informix Data Type


DATETIME YEAR TO DAY
DATETIME HOUR TO FRACTION (5)
DATETIME YEAR TO FRACTION(5)

Note: If you are using the SE database, you cannot CREATE or ALTER a table that has a
VARCHAR column.

DDL statement support


You can use the following DDL (Data Definition Language) statements in your
Centura SQLWindows application:

Enhanced CREATE INDEX statement.

Cascading deletes.

FRAGMENT BY clause in CREATE TABLE statement.

FRAGMENT BY EXPRESSION in CREATE INDEX statement.

ALTER FRAGMENT statement.

ADD ROWIDS and DROP ROWIDS clauses in ALTER TABLE statement.

Optional specification of RESTRICT/CASCADE on the DROP TABLE,


DROP NEW, REVOKE statements.

Empty strings
On Informix, if you try to insert the empty string into a varying-length character
string column (or try to update such a column with the empty string), the database
stores a space instead.
For background information, read the section Nulls, empty strings, and spaces on
page 1-15.

GET DIAGNOSTICS statement


You cannot execute the GET DIAGNOSTICS statement against an Informix database
server from an Centura SQLWindows application.

3-4

Connecting Centura Objects to Databases

Isolation levels

Isolation levels
Informix supports the isolation levels shown in the following table:
Centura SQLWindows Parameter

Informix Isolation Level

RR

Repeatable Read

CS

Cursor Stability

RO

Dirty Read

RL

Committed Read

To set the isolation level in your application, call SqlSetIsolationLevel. For example,
to set the isolation level to Cursor Stability, put the statement:
Call SqlSetIsolationLevel(hSql,CS)

in your Centura SQLWindows application. See the Centura Function Reference for
more information about this function.
For general information on isolation levels, read Isolation levels on page 1-12.

Lock time-out
Informix supports lock time-outs. To specify no wait, specify a time-out value of
zero. To specify wait forever, specify a time-out value of 1.
For general information on lock time-outs, read Lock time-out on page 1-15.

Miscellaneous features
You can use the following Informix database features in your Centura SQLWindows
applications:

New data distribution features.

DBINFO utility function.

TRIM string function.

NLS data types


You cannot use NLS (National Language Support) data types in your Centura
SQLWindows applications. However, you can connect to an NLS-enabled database
from your Centura SQLWindows applications.

Connecting Centura Objects to Databases

3-5

Chapter

Connecting to Informix

Positioned updates
A Centura SQLWindows application can do positioned updates against an Informix
database.
For more information, read Positioned updates on page 1-17.

SET statement support


You can use the following SET statements in your Centura SQLWindows application
when connecting to an Informix database:

3-6

Connecting Centura Objects to Databases

SQL.INI keywords

SET DATASKIP statement.

SET PDQPRIORITY statement.

SET TRANSACTION statement.

SQL.INI keywords
This section describes the keywords you need or may want to use in the SQL.INI file
when you connect a Centura SQLWindows application to an Informix database.
For general information about SQL.INI, read Initializing Centura SQLWindows
applications on page 2-4.

buffrow
Use this keyword to control the buffering of data between your Centura
SQLWindows application and SQLRouter/Informix.
Section

[infogtwy]

Default

Syntax

buffrow=number_of_rows

Description

This keyword controls the buffering of data between your Centura SQLWindows
application and SQLRouter/Informix. By decreasing the buffrow value, response
time can be improved significantly. In contrast, larger values increase data
throughput, but lengthen the response time.
The values for buffrow can range from 0 through 32767. Assigning a value does not
guarantee that the current INMESSAGE is of sufficient size to fulfill the request. In
these cases, the number of buffered rows may be considerably less.
The default value of zero causes SQLRouter/Informix to revert to buffering data
based on the number of rows which will fit within the current INMESSAGE buffer
size.

Example

This statement instructs SQLRouter/Informix to perform single row fetches into the
INMESSAGE buffer:
buffrow=1

Notes

The buffrow keyword has no effect on the manner in which data is buffered and
transported across the network by Informix-Net.
You can also configure the buffering of data for individual SQL handles using the
SqlSetParameterAll function. Assuming nBuffrow has already been assigned the
value desired for SQL handle hSql, you can make the following call:
SqlSetParameterAll(hSql, DBP_BUFFROW, nBuffRow, FALSE, TRUE)

Connecting Centura Objects to Databases

3-7

Chapter

Connecting to Informix

comdll
Identify the SQLRouters available between Centura SQLWindows (or a client
application created with Centura SQLWindows) and the database.
Section

[win32client.dll]

Syntax

comdll=communication_dll_name

Description

This keyword identifies the filename of a SQLRouter DLL. You can put one comdll
statement in the SQL.INI file. If you use InformixNet 7.x, the value of
communication_dll_name to use for SQLRouter/Informix is sqlifx32.

Notes

For related information, read Connect search order on page 1-6.

defconnect
Use this keyword to connect using information in the INFORMIX.INI file.
Section

[infogtwy]

Default

off

Syntax

defconnect={on |off}

Description

This keyword lets you connect to an Informix database using the user name,
password, service, and host listed in the INFORMIX.INI file. You specify this
information with the Informix SETNET32 utility.

Example

This statement instructs SQLRouter/Informix to connect using the information in


INFORMIX.INI.
defconnect=on

log
Use this keyword to define the database router activity log and enable logging.
Section

[win32client.ifx32]

Syntax

log=fully_qualified_path_name

Description

Specify any valid file pathname after the keyword. If the file does not exist, it is
created. If the file already exists, it is overwritten (unless the /Fa option is specified
see below). Once the log statement has been added to the SQL.INI file, logging
is performed automatically.
You can specify one or more of the options listed below after the fully qualified
pathname to customize the output:

3-8

Connecting Centura Objects to Databases

SQL.INI keywords

/Bxexclude bind variable values

/Faappend to existing file

/FDdisplay fetch data

/Lddisplay LONG data read or written

/Txexclude timestamps

Enter the options exactly as shown, keeping upper-case letters upper-case and lowercase letters lower-case.
Example

This example calls for a log file that does not include timestamps on entries (to
conserve disk space), and displays the input and output of all LONG data (including
TEXT and IMAGE data items).
[win32client.ifx32]
log=c:\centura\informix.log /Tx /Ld

longbuffer
Use this keyword to specify the maximum number of bytes of long data type columns
to retrieve or send, and truncates excess bytes.
Section

[infogtwy]

Default

32767

Syntax

longbuffer=number_of_bytes

Description

Reduce the value of this keyword to conserve memory or reduce network traffic. If
you use longbuffer to limit the number of bytes to retrieve, the retrieved data is
truncated. To avoid truncating long data, set the value equal to the largest data type
size that your client applications need to read.
If specified in a section, longbuffer applies to all databases defined in that
section. You cannot specify a longbuffer larger than the maximum size for the
data type to be retrieved.
SQLRouter installs with a default value of 4095 bytes for each database. If the
keyword is not specified, or if it is commented out, the default is 32,767 bytes.
Note: BYTE and TEXT have no maximum size. The theoretical limit is 231 bytes.

Connecting Centura Objects to Databases

3-9

Chapter

Example

Connecting to Informix

This statement sets 2000 as the maximum number of bytes of long data type data to
retrieve or send.
longbuffer=2000
You can set this environment variable in your Centura SQLWindows application
using SqlSetParameterAll with the DBP_LONGBUFFER parameter. (This parameter
is defined in the SQLNWKCN.APL file.)

remotedbname
Use this keyword to specify the name of the database your Centura SQLWindows
application connects to, the connect string it uses, and (optionally) the host where the
database is located and the service through which you access it.
Section

[infogtwy]

Syntax

remotedbname=dbname,DATABASE databasename, -vservername -hhostname


-sservicename

Description

dbname- a one to eight character name for all the databases to be assigned to
SQLDatabase prior to issuing the SqlConnect ()call.
databasename- the EXACT name of the Informix database you wish to use for this
connection. This value is case sensitive. Do not include quotation marks. Everything
following the string DATABASE up to, but not including, the trailing comma, is
interpreted to be the Informix database name as known by the Informix server.
The next three parameters (-h, -v, -s) correspond to the Informix SETNET32 utility,
and the values shown in italics must be changed to correspond to the values you used
in the SETNET32 utility for the corresponding parameter:
SQL.INI Parameter

Informix SETNET32 Parameter

-hhostname

Hostname

-vonline_servername

Informix Server

-sservicename

Service Name

The following information does NOT pertain to SQL.INI but is provided as a service
to the user who is attempting to configure Informix for use with Centura products:
The only two protocols which can be selected for use with Centura and Informix are:
olsoctcp - for TCP/IP connection to Informix/OnLine
sesoctcp - for TCP/IP connection to Informix/SE

3-10 Connecting Centura Objects to Databases

SQL.INI keywords

There is an Informix requirement to close any entry in the operating systems


SERVICES file.
On windows NT it is found in: C:\WINNT\SYSTEM32\drivers\etc.
On Windows 95, it is found in C:\WINDOWS
This is the text file. It must be edited to contain an entry for the Service Name
parameter with the correct service name and part number value for your Informix
system. An example of the entry is:
turbo 1526\tcp
Refer to the Informix documentation for more details on the above information.
If you do not specify hostname, servername, and servicename, SQLRouter/Informix
uses the default Server as configured with the SETNET32 utility. You can specify
only one default server.
To connect to multiple Informix servers concurrently you must specify the hostname,
servername, and servicenameserver name on each remotedbname entry in the
SQL.INI.
Example

This example identifies a database that Centura SQL Windows/32 applications know
as STORES7. It resides on a computer named jupiter and is controlled by an
Informix server named ol_ jupiter with a service name of turbo.
remotedbname=STORES,DATABASESTORES7, -vol_jupiter
-hjupiter -sturbo
Warning: Enter all SQL.INI statement on a single line. Do not attempt to continue a line in
SQL.INI. If you attempt to do so, a syntax error will result, and your program will fail to
initialize.

yieldonservercall
Use this keyword to turn asynchronous processing in Informix I-Net on or off.
Section

[infogtwy]

Default

off

Syntax

yieldonservercall={on|off}

Description

This statement instructs SQLRouter/Informix to share the CPU with other


applications or other modules of your application. By setting this keyword to off
(the default), I-Net lets other applications use the CPU while it waits for the server to
complete the operation it sent.

Connecting Centura Objects to Databases

3-11

Chapter

Connecting to Informix

If your Centura SQLWindows application does asynchronous processing (for


example, by calling SalPostMsg to handle SQL statements) and you set
yieldonservercall to off (or took the default), you may get the message:
Error#111SQL Application Programming Interface(API)
recursively entered.

To prevent this, set yieldonservercall to on.


Example

This example allows Informix I-Net to do asynchronous processing.


yieldonservercall=on

Stored procedures
Informix stored procedures are programs written in Informix Stored Procedure
Language (SPL). Once you create a procedure, it is stored in an executable format on
the database server.
Procedures and triggers are database objects, just like tables; therefore, anyone with
appropriate privileges on a procedure may execute it.
If the stored procedure returns a result set, call SqlFetchNext to get rows from that
result set.

Creating stored procedures


You can create a stored procedures as follows:
Call SqlPrepare(hSql,create procedure p (custnum int)
returning char(20);
define company_name char(20);
select company into company_name
from customer where customer_num=custnum;
return company_name;
end procedure;)
Call SqlExecute(hSql)

Executing stored procedures


You can execute stored procedures in two ways:
Call SqlRetrieve(hSql,p,:nCustNum,:strLBItem)
Call SqlExecute(hSql)
! Need next line if stored procedure gets a result set.
SqlFetchNext(hSql, nRetVal)

Or:
Call SqlPrepare(hSql,execute procedure p(101))
Call SqlExecute(hSql)

3-12 Connecting Centura Objects to Databases

Storing TEXT and BYTE data

! Need next line if stored procedure gets a result set.


SqlFetchNext(hSql, nRetVal)

If another user owns the procedure, you must fully qualify the procedure name using
the syntax user_name.procedure_name. For example, refer to procedure p owned by
user informix with informix.p, as in:
Call SqlRetrieve(hSql,informix.p,:nCustNum,:strLBItem)

Important: Do not use SqlImmediate if the stored procedure returns result sets. SqlImmediate
creates a hidden handle, which disappears after the function completes; you need an explicit
handle to call SqlFetchNext and retrieve rows from a result set.

Dropping stored procedures


You can drop stored procedures in two ways:
Call SqlImmediate(drop procedure p)

Or:
Call SqlPrepare(hSql,drop procedure p)
Call SqlExecute(hSql)

More information on stored procedures


For general information about stored procedures, read Stored procedures on page 121.

Storing TEXT and BYTE data


When you update or insert TEXT and BYTE columns, you must use LONG STRING
variables in your Centura SQLWindows application to hold the data you will use to
do the UPDATE or the INSERT. Once you have prepared the UPDATE or INSERT
statement, call the function SqlSetLongBindDatatype to bind the data in the LONG
STRING bind variable to TEXT or BYTE data, then execute the prepared UPDATE
or INSERT statement. For the second argument to the function
SqlSetLongBindDatatype you must specify the integer constant 22 for TEXT columns
and the integer constant 23 for BYTE columns.
Note: The integer constant 24 is the correct second argument to the function
SqlSetLongBindDatatype when updating CHAR and VARCHAR data longer than 254 bytes.
However, Centura SQLWindows does the appropriate binding for this kind of data by default
when connected to an Informix database; you do not have to call the function
SqlSetLongBindDatatype when inserting and updating CHAR and VARCHAR data longer than
254 bytes.

Connecting Centura Objects to Databases

3-13

Chapter

Connecting to Informix

For example:
Constants
System
User
! Make the code self-documenting with symbolic constants.
Number:BINDTEXT=22
Number:BINDBYTE=23
...
Local variables
SqlHandle:hSql
Number:nNumber
Long String:sLong
Actions
Call SqlConnect(hSql)
If not PrepareAndExecute(hSql,
'CREATE TABLE longt(n FLOAT, s TEXT)')
...
If not SqlPrepare(hSql,
'INSERT INTO longt VALUES(:nNumber,:sLong)')
...
If not SqlSetLongBindDatatype(2, BINDTEXT)
...
If not SqlExecute(hSql)
...

Important: You must first prepare the INSERT or UPDATE statement, then call
SqlSetLongBindDatatype before you execute the statement. The binding from the function
SqlSetLongBindDatatype lasts only until your application prepares the next SQL statement.

For more information on SqlSetLongBindDatatype, refer to the Centura


SQLWindows Function Reference and the on-line help.

3-14 Connecting Centura Objects to Databases

Connecting Centura Objects to Databases

Chapter 4

Connecting to
Microsoft SQL Server
This chapter describes how to connect Centura SQLWindows applications to
Microsoft SQL Server version 6.5 and 7.0.

Connecting Centura Objects to Databases

4-1

Chapter

Connecting to Microsoft SQL Server

Before you begin


Please read all of Chapter 1, Overview and Chapter 2, Initializing and Testing Your
Connection before reading this chapter.
You connect Centura SQLWindows applications to ODBC data sources with the
Centura ODBC router, SQLRouter/ODBC. This router conforms to the ODBC 3.0
specification up to core levels 1 and 2 (i.e., to the ODBC 2.0 level within the 3.0
specification). See Chapter 8 for more on the ODBC driver.

Autocommit
When you connect to Microsoft SQL Server 6.5 and 7.0, autocommit is on by default.
Data Definition Language (DDL) statements, such as CREATE TABLE, are always
committed immediately, even if autocommit is off.
If autocommit is off, and you either disconnect from the database or exit the
application (whether normally or abnormally) before committing or rolling back a
pending transaction, the ODBC driver sends a ROLLBACK request to the database
server.
For background information on autocommit, read Autocommit on page 1-3.
For information on autocommit and cursor context preservation, read Cursor context
preservation on page 4-2.

Cursor context preservation


Microsoft SQL Server supports cursor context preservation (CCP). In Centura
SQLWindows applications that connect to Microsoft SQL Server, CCP is off by
default.
If CCP is on (and autocommit is off), you can continue to execute prepared SQL
statements (without preparing them again) even after you commit the transaction that
those statements are a part of. If CCP is off, however, you cannot re-execute those
SQL statements once you commit the transaction without preparing them again.
For background information, read Cursor context preservation on page 1-7.

Data types supported


A Centura SQLWindows application supports all Microsoft SQL Server data types,
including:

4-2

decimalThe server can be configured to provide a maximum precision of


38 decimal digits (the default maximum is 28 decimal digits). However, 22

Connecting Centura Objects to Databases

Data types supported

decimal digits is the maximum precision that Centura SQLWindows supports


for this data type.

numericThe server can be configured to provide a maximum precision of


38 decimal digits (the default maximum is 28 decimal digits). However, 22
decimal digits is the maximum precision that Centura SQLWindows supports
for this data type

double precisionBoth the server and Centura SQLWindows support a


maximum precision of 17 decimal digits for this data type.

Note: The decimal and numeric data typeswhich are identicalallow the exact
representation of a fractional value. This is unlike double precision or float (to which double
precision is mapped), which typically allow only approximate values.

The table below shows the data type mappings between Centura SQLWindows and
Microsoft SQL Server:
Centura
SQLWindows

Microsoft SQL Server


Version 6.5

Version 7.0

STRING

BINARY (254 or fewer bytes)


CHAR (254 or fewer bytes)
TIMESTAMP
VARBINARY (254 or fewer bytes)
VARCHAR (254 or fewer bytes)

BINARY (254 or fewer bytes)


CHAR (254 or fewer bytes)
TIMESTAMP
VARBINARY (254 or fewer bytes)
VARCHAR (254 or fewer bytes)

LONG STRING

BINARY (255 or more bytes)


CHAR (255 or more bytes)
IMAGE
TEXT
VARBINARY (255 or more bytes)
VARCHAR (255 or more bytes)

BINARY (8000 or fewer bytes)


CHAR (8000 or fewer bytes)
IMAGE
TEXT
VARBINARY (8000 or fewer
bytes)
VARCHAR (8000 or fewer bytes)

BIT
DECIMAL
DOUBLE PRECISION
FLOAT
INT
MONEY
NUMERIC
REAL
SMALLINT
SMALLMONEY
TINYINT

BIT
DECIMAL
DOUBLE PRECISION
FLOAT
INT
MONEY
NUMERIC
REAL
SMALLINT
SMALLMONEY
TINYINT

NUMBER

Connecting Centura Objects to Databases

4-3

Chapter

Connecting to Microsoft SQL Server

DATE/TIME

DATETIME
SMALLDATETIME

DATETIME
SMALLDATETIME

Identity column type


SQL Server tables can also include an IDENTITY column. If a column of this type is
defined when a table is created, the values in this column (which you cannot update)
are automatically incremented or decremented (by an amount you can set) every time
you create a new row. This makes this data type useful for automatically generating
such values as serial numbers, order numbers, and the like.

Empty strings
On Microsoft SQL Server 6.5 and 7.0, if you try to insert the empty string into a
varying-length character string column (or try to update such a column with the
empty string), the database stores a space instead.
For background information, read the section Nulls, empty strings, and spaces on
page 1-15.

Isolation levels
Microsoft SQL Server defines four isolation levels in terms of dirty reads,
nonrepeatable reads and phantom rows. (See Isolation levels on page 1-12 for the
definitions of these terms.)
SQL_TXN_READ_UNCOMMITTED Dirty reads, nonrepeatable reads, and
phantom rows are all possible.
SQL_TXN_READ_COMMITTED Dirty reads are prevented; nonrepeatable
reads and phantom rows are possible.
SQL_TXN_REPEATABLE_READ Dirty reads and nonrepeatable reads are
prevented; phantom rows are possible.
SQL_TXN_SERIALIZABLE Dirty reads, nonrepeatable reads, and phantom
rows are all prevented (transactions are serializable).
Centura SQLWindows supports the four isolation levels RO, RL, CS, and RR. When
a Centura SQLWindows application connects to Microsoft SQL Server, these
isolation levels are mapped to the SQL Server isolation levels as follows:

4-4

Connecting Centura Objects to Databases

Keywords as table and column names

Isolation Level Mapping


Centura
SQLWindows

Microsoft SQL Server

RO

SQL_TXN_READ_UNCOMMITTED

RL

SQL_TXN_READ_COMMITTED

CS

SQL_TXN_REPEATABLE_READ

RR

SQL_TXN_SERIALIZABLE

Note: Microsoft SQL Server maps SQL_TXN_REPEATABLE_READ to


SQL_TXN_SERIALIZABLE; thus, CS is actually equivalent to RR.

By default, a Centura SQLWindows application runs against Microsoft SQL Server


6.5 and 7.0 with an isolation level of RL.
For more background information, read Isolation levels on page 1-12.

Keywords as table and column names


To name a table or column in Microsoft SQL Server with a reserved keyword (such as
SELECT or WHERE) in a Centura SQLWindows application, you must use lowercase or mixed-case letters; if you use all upper-case letters, you get an error.

Lock time-out
The default value for lock time-out with Microsoft SQL Server is zero. This means
there is no lock time-out.
For more background information, read Lock time-out on page 1-15.

Native connectivity
Microsoft SQL Server 6.5 and 7.0 uses ODBC as its native call-level interface.
Microsoft SQL Server automatically maps SAL statements to the appropriate ODBC
functionsno ODBC calls appear in your Centura SQLWindows applications.
Note: The level of SQL syntax and semantics supported is Core; the ODBC API conformance
is Level II.

Connecting Centura Objects to Databases

4-5

Chapter

Connecting to Microsoft SQL Server

Positioned updates
Centura SQLWindows applications can perform positioned updates (WHERE
CURRENT OF cursor updates) when connected to Microsoft SQL Server. To learn
how to code a positioned update, see Positioned updates on page 1-17.
Important: You cannot do positioned updates on a result set returned by a stored procedure.
You should always disable result set mode before calling a stored procedure.

For additional information on stored procedures, see Stored procedures on page 4-11.
For background information on result set mode, see Result set mode on page 1-19.

Result set mode


Microsoft SQL Server 6.5 and 7.0 provides backend support for scrollable cursors
(result set cursors that scroll both backwards and forwards). Consequently, you
cannot create front end result sets (FERS) if you turn on result set mode.
You must turn on result set mode to have more than one result set open at the same
time. If result set mode is off, you must fetch all of the rows from one result set
before you can SELECT another result set. If you try to SELECT a result set before
fetching all the rows of a previously retrieved result set, you get the error:
[Microsoft][ODBC SQL Server Driver]Connection is busy with
result for another hstmt

Important: By default, result set mode is off for better performance. Also, you must always
turn off result set mode before calling a stored procedure.

For background information on result set mode and scrollable cursors, read Result set
mode on page 1-19. For more information on FERS, read Front end result sets on
page 1-8.

SET statement
Microsoft SQL Server supports the SET statement. You use this statement to set
various query-processing options for the duration of your work session (that is, until
you disconnect), or for the duration of a stored procedure.
When you execute the SET statement from a Centura SQLWindows application, you
do so by specifying a specific SQL handle. Nonetheless, the option you set applies to
all statements executed on your current connection to the database, regardless of the
SQL handle you specify when you execute those statements.

4-6

Connecting Centura Objects to Databases

SqlDirectoryByName semantics

For example, you can use SET to limit the number of rows returned in a result set,
such as:
SqlPrepareAndExecute(hSql1,SET ROWCOUNT 10)

If you then retrieve a result set, the database returns no more than 10 rows, even if you
specify a handle other than hSql1 when you execute the SELECT statement, for
example:
SqlPrepareAndExecute(hSql2,SELECT * FROM MYTABLE)

Read the Microsoft SQL Server 6.5 and 7.0 online documentation for further
information about the SET statement.

SqlDirectoryByName semantics
When a Centura SQLWindows application has connected to Microsoft SQL Server,
calling the function SqlDirectoryByName returns all of the databases listed in the
ODBC.INI file. This list is not necessarily the same as the list of all databases
accessible to Microsoft SQL Server.

SQL.INI keywords
This section contains the keywords you need or might want to use in the SQL.INI file
when connecting a Centura SQLWindows application to Microsoft SQL Server 6.5
and 7.0.

buffrow
Use this keyword to control the buffering of data between your Centura
SQLWindows application and Microsoft SQL Server.
Section

[odbcrtr]

Default

Syntax

buffrow=number_of_rows

Description

This keyword controls the buffering of data between your Centura SQLWindows
application and Microsoft SQL Server. By decreasing the buffrow value, response
time can be improved significantly. In contrast, larger values increase data
throughput, but lengthen the response time.
The values for buffrow can range from 0 through 32767. Assigning a value does not
guarantee that the current INMESSAGE is of sufficient size to fulfill the request. In
these cases, the number of buffered rows may be considerably less.

Connecting Centura Objects to Databases

4-7

Chapter

Connecting to Microsoft SQL Server

The default value of zero causes Microsoft SQL Server to revert to buffering data
based on the number of rows which will fit within the current INMESSAGE buffer
size.
Example

This statement instructs Microsoft SQL Server to perform single row fetches into the
INMESSAGE buffer:
buffrow=1

Notes

The buffrow keyword has no effect on the manner in which data is buffered and
transported across the network.
You can also configure the buffering of data for individual SQL handles using the
SqlSetParameterAll function. Assuming nBuffrow has already been assigned the
value desired for SQL handle hSql, you can make the following call:
SqlSetParameterAll(hSql,DBP_BUFFROW,nBuffRow,FALSE,TRUE)

comdll
Identify the SQLRouters available between Centura SQLWindows (or a client
application created with Centura SQLWindows) and the database.
Section

[win32client.dll]

Syntax

comdll=communication_dll_name

Description

This keyword identifies the filename of a SQLRouter DLL. You can put more than
one comdll statement in the SQL.INI file. The value of communication_dll_name
to use for SQLRouter/ODBC is sqlodb32.

Example

comdll=sqlodb32

Notes

For related information, read Connect search order on page 1-6.

log
Define the database router activity log and enable logging.
Section

[win32client.odb32]

Syntax

log=fully_qualified_path_name

Description

Specify any valid file pathname after the keyword. If the file does not exist, it is
created. If the file already exists, it is overwritten (unless the /Fa option is specified
see below). Once the log statement has been added to the SQL.INI file, logging
is performed automatically.
You can specify one or more of the options listed below after the fully qualified
pathname to customize the output:

4-8

Connecting Centura Objects to Databases

SQL.INI keywords

/Bx exclude bind variable values

/Fa append to existing file

/FD display fetch data

/Ld display LONG data read or written

/Tx exclude timestamps

Enter the options exactly as shown, keeping upper-case letters upper-case and lowercase letters lower-case.
Example

This example calls for a log file that does not include timestamps on entries (to
conserve disk space), and displays the input and output of all LONG data (including
TEXT and IMAGE data items).
[win32client.odb32]
log=c:\centura\mssqlsrv.log /Tx /Ld

longbuffer
Specify the maximum number of bytes of LONG column data to retrieve or send.
Sections

[odbcrtr]

Default

32 Kbytes

Syntax

longbuffer=number_of_bytes

Description

This keyword sets the size of the buffer that holds LONG data. Normally, the optimal
size that avoids data loss is the largest column of LONG data to be sent or retrieved
by the Centura SQLWindows application. A larger buffer uses more memory but
reduces network traffic; a smaller buffer uses less memory but increases network
traffic. If the buffer is too small to hold all of the data, the excess is truncated.
If specified, the longbuffer statement applies to all databases connected to using
ODBC. It is recommended that you not specify a value for longbuffer larger than
the maximum LONG column size in any of the tables stored in any of those
databases.

Example

This statement sets to 2000 the maximum number of bytes of LONG column data to
retrieve from or send to any database connected to using ODBC.
longbuffer=2000

Notes

You can also set this variable in a Centura SQLWindows program by calling
SqlSetParameterAll with the DBP_LONGBUFFER parameter (defined in
SQLNWKCN.APL). This allows you to tailor the size of the buffer to the application.

Connecting Centura Objects to Databases

4-9

Chapter

Connecting to Microsoft SQL Server

odbctrace
Trace all calls to the ODBC API.
Section

[odbcrtr]

Default

off

Syntax

odbctrace={on|off}

Description

The Microsoft ODBC Driver Manager can trace all calls made to the ODBC API.
The trace information is saved in the log file whose pathname is given in the
odbtracefile statement.

Example

This statement enables ODBC API call tracing.


odbctrace=on

odbctracefile
Specify the pathname of the trace file for ODBC API calls.
Section

[odbcrtr]

Default

root_directory\sql.log

Syntax

odbctracefile=fully_qualified_filename

Description

This keyword specifies the pathname of the trace file for ODBC API calls. This
keyword has no effect unless the odbtrace keyword is set to on see odbctrace
on page 4-10.

Example

This statement specifies that the trace file is called odbc.log, and that it is located
in the \logs directory on the clients c: drive.
odbctracefile=c:\logs\odbc.log

remotedbname
Use this keyword to specify database names and their associated connect strings.
Section

[odbcrtr]

Syntax

remotedbname=db_name,connect_string

Description

db_name specifies the database name; it cannot exceed eight characters.


connect_string is the exact connect string you will use to connect to the ODBC data
source. Typically, this entry begins with the string "DSN=" to specify the data source
name specified in the ODBC Administrator tool.

4-10 Connecting Centura Objects to Databases

SQL.INI keywords

The value specified in connect_string can include embedded spaces. Do not put
comments on the same line with the "remotedbname" statement. Everything from
the comma following db_name to the end of line is interpreted as the connect string.
Examples:

Assume you have defined two data sources in ODBC Administrator. One is for
Microsoft SqlServer 7.0 (with a data source name of "MS SqlServer 7.0"), and the
other is for a Visual FoxPro database (with a data source name of "Visual FoxPro
DB"). The remotedbname statements look like:
remotedbname=SS70,DSN=MS SqlServer 7.0
remotedbname=VFP, DSN=Visual FoxPro DB

Your Centura application sets the variable "SqlDatabase" to either "SS70" (to connect
to the SqlServer data source) or to "VFP" (to connect to the FoxPro database), set
SqlUser and SqlPassword appropriately, and issue the SqlConnect() call.
SqlRouter/ODBC obtains all the necessary information from the configuration
maintained by the ODBC Administrator utiltity.
Additional note: The remotedbname parameter is not necessary for applications built using Centura
Team Developer. It is required if you want to use the SqlTalk utility to connect to the
ODBC data source.
When connecting to any ODBC data source where the data source name was
configured by the ODBC Administrator tool, your Centura application can bypass the
remotedbname parameter altogether, and set the variable SqlDatabase to the
actual ODBC data source name. Using the above example, if you issue the following
statements (assume SqlUser and SqlPassword are set):
Set SqlDatabase = "MS SqlServer 7.0"
Call SqlConnect (hSql)

then your Centura program will connect correctly to the Microsoft SqlServer 7.0 data
source without using the remotedbname parameter in SQL.INI.

Stored procedures
Procedures containing SQL statements and procedure logic can be compiled and
stored on SQL Server. These procedures can return more than one result set, and can
accept input bind variables (host variables) as arguments. (See also Stored procedures
on page 1-21.)

Creating stored procedures


Microsoft SQL Server comes out of the box with a number of available stored
procedures. See the SQL Server documentation for more information.
The DBA (database administrator) can create additional stored procedures for you.
The DBA needs to let you know about any such stored procedures.

Connecting Centura Objects to Databases

4-11

Chapter

Connecting to Microsoft SQL Server

You can also create your own stored procedures from within a Centura SQLWindows
application. To do this, execute the CREATE PROCEDURE statement on the server
by calling the appropriate SAL function(s), such as SqlImmediate,
SqlPrepareAndExecute, or SqlPrepare followed by SqlExecute.
Note: For more information on stored procedures and the CREATE PROCEDURE statement,
see the Microsoft SQL Server documentation.

Deleting stored procedures


The DBA can delete stored procedures on SQL Server by executing the DROP
PROCEDURE statement. You can also delete stored procedures from within a
Centura SQLWindows application. To do this, execute the DROP PROCEDURE
statement on the server by calling the appropriate SAL function(s), such as
SqlImmediate, SqlPrepareAndExecute, or SqlPrepare followed by SqlExecute.
Note: For more information on the DROP PROCEDURE statement, see the Microsoft SQL
Server documentation. For information on SqlImmediate, SqlPrepareAndExecute, SqlPrepare,
and SqlExecute, see the Centura SQLWindows Function Reference.

Executing stored procedures


Two new pairs of SAL functions have been introduced to support calling stored
procedures.
The first pair is:

OdrExecuteProcExecute the specified stored procedure.

OdrGetNextResults Get the next result set (if any) from the stored
procedure that was invoked with OdrExecuteProc.

The second pair is:

OdrPrepareProcPrepare (compile) the invocation of the specified stored


procedure.

OdrPrepareNextResultsPrepare the (implied) statement that gets the next


result set (if any).

Important: You must turn off result set mode before calling a stored procedure.
Either SqlExecute or a function that implies execution of a prepared statement
such as SalTblPopulate must be called after calling OdrPrepareProc or
OdrPrepareNextResults.

4-12 Connecting Centura Objects to Databases

SQL.INI keywords

Once the result set has been retrieved, position the cursor to the first and subsequent
rows in the result set by calling the SqlFetchNext function. (For more information
about this function, see the Centura SQLWindows Function Reference.)

Example code
The code fragment below creates the stored procedure GetNames and stores it on the
server. The procedure returns all the values in the name column and the number
column from the rooms table, then all the values in the name column from the guests
table. The code invokes the stored procedure using the shorthand ODBC procedure
syntax. (See the Microsoft ODBC 2.0 Programmers Reference and SDK Guide for
more information on the standard and shorthand syntax for calling stored procedures).
The current column values being fetched are stored in the INTO variables
:strName and :nNumber from the first result set, and the INTO variable
:strName from the second result set.
Call SqlSetResultSet(hSql, FALSE)
Set strProcedure=CREATE PROCEDURE GetNames AS ||
SELECT name,number FROM rooms ||
SELECT name FROM guests
Call SqlPrepareAndExecute(hSql, strProcedure)
If OdrExecuteProc(hSql,{call GetNames()},:strName,:nNumber)
Loop
If SqlFetchNext(hSql, nRet)
...
Else If (nRet=FETCH_EOF)
If NOT OdrGetNextResults(hSql,:strName,
bEndOfResults)
If bEndOfResults
Break

In the above code fragment, the functions OdrExecuteProc and OdrGetNextResults


were called.
Alternatively, you can prepare the invocation of the stored procedure as a separate
step by replacing OdrExecuteProc with:
If OdrPrepareProc(hSql,{call GetNames()},:strName)
If SqlExecute(hSql)...

and the call to OdrGetNextResults with:


If NOT OdrPrepareNextResults(hSql,:strName,:nNumber,
bEndofResults)
If NOT bEndOfResults
If SqlExecute(hSql)...

Error codes for stored procedures


Two new error codes have been defined for stored procedures:

Connecting Centura Objects to Databases

4-13

Chapter

Connecting to Microsoft SQL Server

30002Invalid function call sequence.


This error occurs when you do not call the functions in the correct sequence.
The correct sequence is OdrExecuteProc followed by one or more calls to
OdrGetNextResults, or OdrPrepareProc followed by one or more calls to
OdrPrepareNextResults.

30003Invalid attempt to obtain next result set.


This error occurs when an attempt is made to get another result set from a
stored procedure by calling OdrPrepareNextResults followed by a call to
SqlExecute, SalTblPopulate, or other function that executes a prepared
statement, even though there are no more result sets to retrieve.
The end of result sets can be detected by checking the bEndOfResult flag in
the OdrGetNextResults and OdrPrepareNextResults parameter list. Error
code 30003 is returned if you attempt to retrieve another result set even
though bEndOfResult is TRUE.

SAL extensions
This section describes the Scalable Application Language (SAL) extensions that
allow you to work with stored procedures on Microsoft SQL Server version 6.5 and
7.0.
Note: For more information about stored procedures and ODBC, see the Microsoft ODBC 2.0
Programmers Reference and SDK Guide. For more information about stored procedures and
Microsoft SQL Server, see the SQL Server on-line documentation (click the SQL Server Books
Online icon in the SQL Server Tools program group).

OdrExecuteProc
Syntax

bOk=OdrExecuteProc(hSql,strProc,strIntoList)
Sql Handle: hSql
String: strProc
String: strIntoList

Parameters

hSql A handle that identifies a connection context to the database.


strProc The text of the call to the stored procedure to be executed.
strIntoListThe list of INTO variables into which the stored procedures result set
values (if any) are returned.

Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

4-14 Connecting Centura Objects to Databases

SQL.INI keywords

Description

This function executes a stored procedure on Microsoft SQL Server.


Separate the variables listed in strIntoList with commas and precede each variable
name with a colon. If the stored procedure returns zero rows, the variables in
strIntoList keep whatever values they had before the call to OdrPrepareNextResults.
If you know the stored procedure does not execute a SELECT statement, use
strNull as the value for strIntoList.
If a result set is returned, its associated cursor points to just before the first row of the
result set. To set the INTO variables in strIntoList to the column values of the first
row, call SqlFetchNext. To obtain subsequent rows in the result set, continue to call
SqlFetchNext.
Once all the rows in a given result set have been retrieved, get the next result set (if
any) by calling OrdGetNextResults.

Limitations

The function OdrExecuteProc does not accept bind variables. (Compare


OdrPrepareProc on page 4-17, which does accept bind variables.)

Notes

See also OdrGetNextResults on page 4-15.

Examples

This example executes the stored procedure mysp. This procedure accepts no
arguments, and it returns a result set consisting of a single column. The call to the
stored procedure is specified using the shorthand ODBC syntax. The data type of the
INTO variable :strOut is assumed to match the column data type returned by the
stored procedure.
Call OdrExecuteProc(hSql,{call mysp()},:strOut)

See also the sample application ODBSAL1.APP in the SAMPLES subdirectory of


the Centura SQLWindows installation directory.

OdrGetNextResults
Syntax

bOk=OdrGetNextResults(hSql, strIntoList, bEndOfResults)


Sql Handle: hSql
String: strIntoList
Boolean: bEndOfResults

Parameters

hSql A handle that identifies a connection context to the database.


strIntoListThe list of INTO variables into which the stored procedures result set
values (if any) are returned.
bEndofResults Boolean variable that indicates if there were no more result sets to
be retrieved.

Return Value

bOK is set to TRUE if the function succeeds and to FALSE if it fails.


Connecting Centura Objects to Databases

4-15

Chapter

Description

Connecting to Microsoft SQL Server

If the stored procedure invoked by calling OdrExecuteProc returns more than one
result set, use OdrGetNextResults to get the second and subsequent result sets.
Separate the variables listed in strIntoList with commas and precede each variable
name with a colon. If the stored procedure returns zero rows, the variables in
strIntoList keep whatever values they had before the call to OdrPrepareNextResults.
If a result set is returned, its associated cursor points to just before the first row of the
result set. To set the INTO variables in strIntoList to the column values of the first
row, call SqlFetchNext. To obtain subsequent rows in the result set, repeatedly call
SqlFetchNext.
Once all the rows in a given result set have been retrieved, get the next result set (if
any) by again calling OrdGetNextResults.
If OdrGetNextResults is called and there are no more result sets, bOk is set to FALSE
and bEndOfResults is set to TRUE.

Notes

See also OdrExecuteProc on page 4-14.

Examples

This example gets the next result set (if any) returned by the stored procedure
invoked with OdrExecuteProc. The parameter hSql denotes the same handle that
was used in the call to OdrExecuteProc.
Call OdrGetNextResults(hSql,:strOut, bEndOfResults)

See also the sample application ODBSAL1.APP in the SAMPLES subdirectory of the
Centura SQLWindows installation directory.

OdrGetReturnStatus
Syntax

bOk=OdrGetReturnStatus(hSql, Number_Variable_Name)

Parameters

hSql A handle that identifies a connection context to the database.

Return Value

nReturn is the return value of the stored procedure.

Description

This function gets the return value of a stored procedure You should compile the
stored procedure using OrdPrepareProc only. If you use OrdExecuteProc, then this
function will fail. If you use OrdExecuteProc, the number variable will be set to 0. It
will not contain the actual return status information.

Notes

The calling status for the stored procedures is slightly different if you use
OrdGetReturnStatus. You have to use the complete ODBC syntax for stored
procedures. You have to specify the bind variable name which is expected to contain
the return status information in the call to OrdPrepareProc. See the code example
below.
This function should be called only after all the result sets from this stored procedure
have been retrieved.

4-16 Connecting Centura Objects to Databases

SQL.INI keywords

Examples

The syntax used in OrdPrepareProc is different now. You have to specify a bind
variable name before Call in order to use OrdGetReturnStatus. If you call
OrdGetReturnStatus without specifying a variable name in OrdPrepareProc, no error
is returned. But the return variable will contain 0.
Call SqlConnect(hSql)
Call OrdPrepareProc(hSql, {:nReturn=call MySP (:param1,
:param2)},:bind1)
Call SqlExecute(hSql)
While SqlFetchNext(hSql, nFetchInd)
<process fetched data>
Call OrdGetReturnStatus(hSql, nReturn)

OdrPrepareProc
Syntax

bOk = OdrPrepareProc(hSql, strProc, strIntoList)


Sql Handle: hSql
String: strProc
String: strIntoList

Parameters

hSql A handle that identifies a connection to the database.


strProc The text of the call to the stored procedure to be prepared.
strIntoListThe list of INTO variables into which the stored procedures result set
values (if any) are returned.

Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Description

This function prepares (compiles) the invocation of a stored procedure for subsequent
execution on Microsoft SQL Server. The prepared invocation of the stored procedure
must then be executed explicitly (by calling the SqlExecute function) or implicitly (by
calling, for example, the SalTblPopulate function).
Separate the variables listed in strIntoList with commas and precede each variable
name with a colon. If the stored procedure returns zero rows, the variables in
strIntoList keep whatever values they had before the call to OdrPrepareNextResults.
If you know the stored procedure does not execute a SELECT statement, use
strNull as the value for strIntoList.

Limitations

Input bind variables in the argument list of the call to a stored procedure must be
listed explicitly using the variable name preceded by a colon; you cannot use
parameter markers the question mark (?) syntax as defined in ODBC. Also,
input bind variables cannot be of type LONG STRING.
Connecting Centura Objects to Databases

4-17

Chapter

Connecting to Microsoft SQL Server

Microsoft SQL Server allows a stored procedure to be defined to pass values back to
the calling program through output bind values, a function result, or both. If the
stored procedure has output parameters, strProc must include output bind variables in
the argument list to match those parameters. However, the values assigned to those
output parameters on the server do not get assigned to the output bind variables in
your Centura SQLWindows application; the application never sees those values.
After the call to the stored procedure returns, the values of the output bind variables
are undefined. Read Retrieving output parameters from stored procedures later in
this chapter.
Likewise, a function result returned by the stored procedure never gets back to the
Centura SQLWindows application. Consequently, you cannot assign the function
result from a stored procedure to a variable or use it in an expression.
Notes

See also OdrPrepareNextResults on page 4-18.

Examples

This example prepares the stored procedure myproc. This procedure is assumed to
accept two input parameters the bind variables :v1 and :v2 need to have been
declared of the appropriate type and to return an initial result set consisting of a
single column. The call to the stored procedure is specified using the shorthand
ODBC syntax. The data type of the INTO variable :strOut is assumed to match
the column data type of the first result set returned by the stored procedure.
Call OdrPrepareProc(hSql,{call myproc(:v1,:v2)},:strOut)

See also the sample application ODBSAL2.APP in the SAMPLES subdirectory of the
Centura SQLWindows installation directory.

OdrPrepareNextResults
Syntax

bOk = OdrPrepareNextResults(hSql, strIntoList, bEndOfResults)


Sql Handle: hSql
String: strIntoList
Boolean: bEndOfResults

Parameters

hSql A handle that identifies a connection to the database.


strIntoListThe list of INTO variables into which the stored procedures result set
values (if any) are returned.
bEndofResults Boolean variable that indicates if there were no more result sets to
be retrieved.

Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Description

If the stored procedure specified in the call to OdrPrepareProc returns more than one
result set, use OdrPrepareNextResults followed by explicit execution (calling the

4-18 Connecting Centura Objects to Databases

SQL.INI keywords

SqlExecute function) or implicit execution (calling, for example, the SalTblPopulate


function) to get the next result set.
Separate the variables listed in strIntoList with commas and precede each variable
name with a colon. If the stored procedure returns zero rows, the variables in
strIntoList keep whatever values they had before the call to OdrPrepareNextResults.
If a result set is returned, its associated cursor points to just before the first row of the
result set. To set the INTO variables in strIntoList to the column values of the first
row, call SqlFetchNext. To obtain subsequent rows in the result set, continue to call
SqlFetchNext. Alternatively, you can call SalTblPopulate to fetch the rows of data in
the result set.
Once all the rows in a given result set have been retrieved, get the next result set (if
the stored procedure has another SELECT statement it can execute) by again calling
OrdPrepareNextResults.
If OdrPrepareNextResults is called and there are no more result sets, bOk is set to
FALSE and bEndOfResults is set to TRUE.
See Also

OdrPrepareProc

Example

This example gets the next result set (if any) returned by the stored procedure
specified in OdrPrepareProc. The parameter hSql denotes the same handle that was
used in the call to OdrPrepareProc
Call OdrPrepareNextResult(hSql,:strOut, bEndOfResults)

See also the sample application ODBSAL2.APP in the SAMPLES subdirectory of the
Centura SQLWindows installation directory.

Restrictions on stored procedures


When using stored procedures, the restrictions that follow apply.

Disable result set mode


Always disable result set mode before calling a stored procedure.

No scrollable cursors
The cursor associated with a result set returned by a stored procedure can scroll
forward only.

No positioned updates
You cannot do positioned updates on a result set returned by a stored procedure.

Connecting Centura Objects to Databases

4-19

Chapter

Connecting to Microsoft SQL Server

No output values
When calling a stored procedure that has output parameters in its parameter list, you
must include an output bind variable (of the appropriate type) in the argument list of
the call for each such parameter. However, the values returned by the stored
procedure on the server do not get assigned to those output bind variables on the
client, so your Centura SQLWindows application cannot access those values. After
the call to a stored procedure returns, the values of any output bind variables are
undefined.
Similarly, if the stored procedure returns a function result, that value cannot be
accessed by your Centura SQLWindows application. Consequently, the return value
cannot be assigned to a variable in your Centura SQLWindows application, or used in
an expression.

Retrieving output parameters from stored procedures


Normally, when you execute a stored procedure that returns values in output
parameters by calling OdrPrepareProc followed by SqlExecute, you cannot retrieve
those output values, even though you specify bind variables as output parameters
when you call the stored procedure. The only way a Centura SQLWindows
application can retrieve data from a stored procedure is in the result sets (if any) that
the stored procedure returns.
You can work around this restriction by executing the stored procedure inside a batch
of statements. The batch of statements retrieves the output parameter from the stored
procedure as a result set, then returns that result set to your Centura
SQLWindows application. For example:
Call OdrPrepareProc(hSql,
declare @outparm int ||
exec GTIPROC_BASICS ||
@test = 1 ||
@result = @outparm output ||
SELECT @outparm)
Here is a more complete example to illustrate calling a stored procedure and
retrieving an output parameter. In summary, for the stored procedure created below,
you call:

OdrPrepareProc (as shown above).

SqlExecute to position to the first result set (the set of authors last names).

SqlFetchNext to retrieve the rows in the first result set.

4-20 Connecting Centura Objects to Databases

SQL.INI keywords

OdrPrepareNextResults, SqlExecute, and SqlFetchNext to get the result set


from the SELECT statement against table foo.

OdrPrepareNextResults, SqlExecute, and SqlFetchNext to retrieve the value


of outparmthis is the last result set generated as part of the command batch
outside of the stored procedure.

Set strSqlCreate =CREATE PROC GTIPROC_BASICS ||


@test int, @result int output ||
AS SELECT au_lname FROM authors ||
SELECT c1 FROM foo where c1 = @test ||
SELECT @result = @test * 10 ||
RETURN -100 /* Success */
If TRUE
When SqlError
Return TRUE
Call SqlPrepareAndExecute(hSql,drop procedure
GTIPROC_BASICS)
Call SqlPrepareAndExecute(hSql,strSqlCreate)
Set strSqlExecute = declare @outparm int ||
exec GTIPROC_BASICS ||
@test = :nTest ||
@result = @outparm output ||
SELECT @outparm
Set nTest = 2
Call OdrPrepareProc(hSql,strSqlExecute, :dfAu_lname)
Call SqlExecute (hSql)
While NOT nFetchInd
Call SqlFetchNext(hSql,nFetchInd)
Call OdrPrepareNextResults (hSql, :dfFoo, bMoreResults)
Call SqlExecute (hSql)
Set nFetchInd = FALSE

Connecting Centura Objects to Databases

4-21

Chapter

Connecting to Microsoft SQL Server

While NOT nFetchInd


Call SqlFetchNext(hSql,nFetchInd)
Call OdrPrepareNextResults(hSql, :dfOutParm,
bMoreResults)
Call SqlExecute (hSql)
Set nFetchInd = FALSE
While NOT nFetchInd
Call SqlFetchNext(hSql,nFetchInd)

4-22 Connecting Centura Objects to Databases

Connecting Centura Objects to Databases

Chapter 5

Connecting to Oracle
This chapter describes how to connect Centura SQLWindows applications to Oracle
databases using the Centura native router, SQLRouter/Oracle. It describes (in
alphabetical order) various features of Oracle that can affect the way you write your
Centura SQLWindows application or the way it behaves when you connect to it with
SQLRouter/Oracle.

Connecting Centura Objects to Databases

5-1

Chapter

Connecting to Oracle

Before you begin


Please read all of Chapter 1, Overview and Chapter 2, Initializing and Testing Your
Connection before reading this chapter.
You connect Centura SQLWindows applications to Oracle databases using either the
native router, SQLRouter/Oracle, or the ODBC router, SQLRouter/ODBC. To learn
about connecting with the native router, read this chapter; to learn about connecting
with the ODBC router, read Chapter 8, Connecting to Databases using ODBC.

Autocommit
Oracle database servers support autocommit. Autocommit is off by default.
If you turn on autocommit, both DML (Data Manipulation Language) statements
(such as UPDATE, INSERT, and DELETE) and DDL (Data Definition Language)
statements (such as CREATE TABLE and DROP TABLE) are committed
immediately.
Note: With an Oracle database, DDL statements are always committed immediately, even if
autocommit is off.

If you turn on autocommit, you cannot prepare a SQL statement, then execute it
multiple times. Once you execute the statement, the prepare context is lost and you
must prepare it again. If you turn off autocommit and turn on cursor context
preservation, however, you can re-execute a prepared state multiple times (possibly
with new values for any bind variables in the prepared statement)read Cursor
context preservation on page 5-2 for more information.
For background information about autocommit, read Autocommit on page 1-3.

Cursor context preservation


Oracle databases support cursor context preservation (CCP). In Centura
SQLWindows applications that connect to Oracle, CCP is off by default.
If CCP is on (and autocommit is off), you can continue to execute prepared SQL
statements (without preparing them again) even after you commit the transaction that
those statements are a part of. If CCP is off, however, you cannot re-execute those
SQL statements once you commit the transaction unless you prepare them again.
For background information, read Cursor context preservation on page 1-7.

5-2

Connecting Centura Objects to Databases

Data types

Data types
The table that follows shows the mapping between the data types supported by a
Centura SQLWindows application and the data types supported by an Oracle
database server.
Centura SQLWindows Data Type

STRING

LONG STRING

Oracle Data Type


CHAR (254 or fewer bytes)
VARCHAR2 (254 or fewer bytes)
VARCHAR (254 or fewer bytes)
RAW
ROWID
MSLABEL
CHAR (255 bytes)
LONG (255 to 232 1 bytes)
VARCHAR2 (255 to maxvarch bytes)
VARCHAR (255 to maxvarch bytes)
RAW (255 bytes)
LONG RAW (255 to 232 1 bytes)
MLSLABEL

NUMBER

NUMBER
INT

DATE/TIME

DATE (without microseconds)

The value of maxvarch in the table above is either 2,000 or 32,000. If you have a
LONG STRING bind variable in an SQL statement, and that bind variable is
associated with a VARCHAR or VARCHAR2 column, you can store at most 2,000
bytes in that variable. If you use a PL/SQL program variable that is associated with a
VARCHAR or VARCHAR2 column, you can store at most 32,000 bytes in that
variable.
Note: The MLSLABEL data type applies only to Trusted Oracle database servers.

Dynamic PL/SQL
Centura SQLWindows applications use dynamic SQL statements to perform
operations on the databases you connect to. These statements (such as SELECT,
INSERT, UPDATE, CREATE TABLE, and so on) are compiled and executed on
the fly (while the Centura SQLWindows application is running).

Connecting Centura Objects to Databases

5-3

Chapter

Connecting to Oracle

Oracle supports a different (though similar) feature called dynamic PL/SQL. This
feature lets you assign a block of PL/SQL statements to a string variable, then have
the database compile and execute that block of statements at runtime.
You cannot execute dynamic PL/SQL blocks in your Centura SQLWindows
applications. However, you can achieve a similar effect in your application as
follows: create a stored procedure that contains the PL/SQL statements you want to
execute, invoke that stored procedure, then drop the procedure before you exit the
application (so the procedure does not continue to be stored in the database).

Empty strings
On Oracle, if you try to insert the empty string into a varying-length character string
column (or try to update such a column with the empty string), the database stores
NULL instead.
For background information, read the section Nulls, empty strings, and spaces on
page 1-15.

Isolation levels
Oracle does not support setting isolation levels if an application uses dynamic (rather
than static) SQL. Because all Centura SQLWindows applications use dynamic SQL
statements, you cannot call SqlSetIsolationLevel in your Centura SQLWindows
application when connected to Oracle.
You cannot set isolation levels when connected to an Oracle database. However, you
can affect data consistency and concurrent access to data by doing either of the
following:

Lock the entire table with the LOCK TABLE statement.

Lock certain rows with the SELECT...FOR UPDATE statement.

Locking an entire table is very heavy-handed and risky. No one other than the user
who has locked the table can do any operations on the table until it is unlocked. Even
if the application locks the table for only a short period of time, the penalty paid by
other users is usually unacceptably high.
Locking only certain rows during a transaction is much more selective and allows
other users to access all data in the database except for the locked rows. However, if
the user who has the lock takes a long time to complete the transaction, all other users
who need to access that data are forced to wait.
For some background on isolation levels, read Isolation levels on page 1-12.

5-4

Connecting Centura Objects to Databases

Lock time-out

Lock time-out
Oracle servers do not support lock time-out. However, you can enable autocommit
(see Autocommit on page 5-2), which has the side effect of eliminating deadlocks.
For some background on lock time-outs, read Lock time-out on page 1-15.

Optimizing message traffic


To speed up the flow of data between a Centura SQLWindows application and the
database server, you can use the array processing feature. This feature consists of:

Array fetchingyou fetch multiple rows from a result set, rather than one
row at a time.

Bulk executeyou send the data for UPDATE, INSERT or DELETE


operations to the server in batches, rather than row by row.

You can modify how array processing works with the fetchrow and
longbuffer keywords in the SQL.INI filesee fetchrow on page 5-6 and
longbuffer on page 5-8.

Positioned updates
Centura SQLWindows applications can perform positioned updates against an Oracle
database.
For more information, read Positioned updates on page 1-17.

Result set mode


If you turn on result set mode when your application is connected to Oracle, Centura
SQLWindows uses front-end result setsOracle does not support (backend)
scrollable cursors.
For more information, read Result set mode on page 1-19 and Front end result sets on
page 1-8.

SQL.INI keywords
This section describes the keywords you should use in the SQL.INI file when
connecting a Centura SQLWindows application to an Oracle database.
For more information about the SQL.INI file, read Initializing Centura SQLWindows
applications on page 2-4.

Connecting Centura Objects to Databases

5-5

Chapter

Connecting to Oracle

comdll
Identify the SQLRouters available between Centura SQLWindows (or a client
application created with Centura SQLWindows) and the database.
Section

[win32client.dll]

Syntax

comdll=communication_dll_name

Description

This keyword identifies the filename of a SQLRouter DLL. You can put more than
one comdll statement in the SQL.INI file. The value of
communication_dll_name to use for SQLRouter/Oracle is sqlora32.

Example

comdll=sqlora32

Notes

For related information, read Connect search order on page 1-6.

fetchrow
This keyword specifies the maximum number of rows SQLRouter/Oracle retrieves
per each network message during cursor operations (fetching) on a result set.
Section

[oragtwy]

Default

20

Syntax

fetchrow=number_of_rows

Description

number_of_rows must be a positive integer (but do not put a plus sign).


The server uses an array to hold the fetched column values. SQLRouter/Oracle
retrieves rows for each network fetch requested, according to the following
algorithm:
1.

Take the width of the widest column and divide it into the maximum size of the
array buffer.

2.

If the calculated value is smaller than the value of fetchrow, use the calculated
value.

3.

Otherwise, use the value of fetchrow. If no value is defined, use the default
value of 20.

The value assigned to fetchrow is not used if:

You use the FOR UPDATE clause in a SELECT statement (CURRENT OF


cursor).

You specify a LONG column in the SELECT list.

You can improve performance by assigning a suitable value to fetchrow. To


achieve good performance, you must balance the number of rows per fetch (which

5-6

Connecting Centura Objects to Databases

SQL.INI keywords

increases the memory used) against the operating systems need for memory (which
causes the operating system to swap memory when not enough is available).
Your Centura SQLWindows application still receives a single row for each call to
SqlFetchNext, regardless of the value assigned to fetchrow.
Example

This example indicates that you want to retrieve only 10 rows with each fetch.
fetchrow=10
This example indicates that you want to fetch only a single row (in effect, disabling
the feature).
fetchrow=1

log
Use this keyword to define the database router activity log and enable logging.
Section

[win32client.ora32]

Syntax

log=fully_qualified_path_name

Description

Specify any valid file pathname after the keyword. If the file does not exist, it is
created. If the file already exists, it is overwritten (unless the /Fa option is specified
see below). Once the log statement has been added to the SQL.INI file, logging is
performed automatically.
You can specify one or more of the options listed below after the fully qualified
pathname to customize the output:

/Bxexclude bind variable values

/Faappend to existing file

/FDdisplay fetch data

/Lddisplay LONG data read or written

/Txexclude timestamps

Enter the options exactly as shown, keeping upper-case letters upper-case and lowercase letters lower-case.
Example

This example calls for a log file that does not include timestamps on entries (to
conserve disk space), and displays the input and output of all LONG data (including
TEXT and IMAGE data items).
[win32client.ora32]
log=c:\centura\oracle.log /Tx /Ld

Connecting Centura Objects to Databases

5-7

Chapter

Connecting to Oracle

longbuffer
This keyword specifies the maximum number of bytes of long data type columns to
retrieve or send, and truncates excess bytes.
Sections

[oragtwy]

Default

Oracle7 or 8 2 gigabytes max

Syntax

longbuffer=number_of_bytes

Description

Reduce the value of this keyword to conserve memory or reduce network traffic. If
you use longbuffer to limit the number of bytes to retrieve, the retrieved data is
truncated. To avoid truncating long data, set the value equal to the largest data type
size that your applications need to read.
The longbuffer keyword applies to all databases defined in [oragtwy] section.
You cannot specify a longbuffer value larger than the maximum size for the data
type to be retrieved.

Example

longbuffer=2000

Note: You can also set this environment variable in your Centura SQLWindows application
using the SqlSetParameterAll with the DBP_LONGBUFFER parameter. (Refer to the Centura
SQLWindows Function Reference and the on-line help for more information about this
function and the parameter.)

nodefparse
Use this keyword to enable or disable deferred parsing.
Sections

[oragtwy]

Default

no

Syntax

nodefparse={yes|no}

Description

This keyword (a shortened form of no deferred parse) enables or disables deferred


parsing.
SQLRouter/Oracle uses deferred parsing for improved performance at runtime.
However, deferred parsing makes debugging more difficult because the router cannot
return the position of a column that may have generated an error.
You should especially disable deferred parsing when debugging complex SQL
statements with many columns in the result set. If deferred parsing is disabled and an
error is raised, the cursor automatically highlights the offending column in the result
set.

5-8

Connecting Centura Objects to Databases

SQL.INI keywords

When you put an application into production, you should enable deferred parsing.
Example

This example disables deferred parsing.


nodefparse=yes

remotedbname
Use this keyword to specify database names and their associated connect strings.
Section

[oragtwy]

Syntax

remotedbname=db_name,connect_string

Description

db_name specifies the value you will use as SqlDatabase for SqlConnect()
connect_string is the character @ followed by the Oracle Service Name as
understood by SQL*Net. Only use the first portion of the service name- not the
.world portion.

Example

This example assumes you have configured your Oracle 7 or Oracle 8 client for an
Oracle Service Name of ARTHUR.world.
Remotedbname=ART,@ARTHUR
You assign the variable SQLDatabase to the value ART and then issue the
SqlConnect() call. SqlRouter Oracle finds all of the necessary connection information
and connect you to the Oracle server.
Additional Requirements:
To make an OCI application work with any of their SQL*Net versions, Oracle
released OCIW32.DLL. Centura certified Oracle connectivity with OCIW32.DLL.
This lets SqlRouter/ Oracle communicate effectively with versions 7.1, 7.2, 7.3, 8.0.x,
and future versions of Oracle. To make sure the proper verson of Oracles OCI
software is used, the registry key
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE
contains a value for the parameter ORAOCI. This should be set to the correct verson
of Oracles DLL:
Oracle 7.1

ORANT71.DLL

Oracle 7.2

ORA72.DLL

Oracle 7.3

ORA73.DLL

Oracle 8.0.2

ORA802.DLL

Oracle 8.0.3

ORA803.DLL

Connecting Centura Objects to Databases

5-9

Chapter

Connecting to Oracle

Oracle 8.0.4

ORA804.DLL

Make sure the fully qualified path name is used in the registry entry.
Note: Oracle versions earlier than 7.1 are not supported by SqlRouter/Oracle.
remotedbname=ART,@ARTHUR
Refer to the Oracle documentation for more information about CONFIG.ORA,
TNSNAMES.ORA, and ORACLE.INI and how to set up these files.
Notes

For related information, read Connect search order on page 1-6.

substitute
Use this keyword to specify that the string in the first parameter should replace the
string in the second parameter whenever the first parameter appears in an SQL
statement.
Section

[oragtwy]

Syntax

substitute=original_string,substitute_string

Description

You can have an unlimited number of substitute statements in the initialization


file. However, this statement changes all occurrences of the replaced word in your
SQL statements: operators, WHERE clauses, object names, and literals (but not bind
variables).
The second string can include the first, as in:
substitute=od,odd
Important: The strings can include embedded blank spaces, but not commasyou must use
a comma to separate original_string from substitute_string.

Notes

Because each SQL statement is parsed, having substitute statements in your


SQL.INI file adds a small amount of overhead to the compilation of those statements.
If you are not running any Centura software that require substitution, you may want
to remove these statements from the file.
If you use applications that rely on the CATALOG commands, such as Quest,
Report Builder, and DB Explorer, you must include the following statement in your
SQL.INI:
substitute=SYSSQL.,

5-10 Connecting Centura Objects to Databases

Stored procedures

Include this statement exactly as shown with the upper case letters SYSSQL
followed by a period followed by a comma. Without this, Quest, Report Builder, and
or DB Explorer will not be able to use the CATALOG commands in your
application.
Example

This example replaces double quotes, which Oracle does not accept, with nulls. This
statement is useful to run a program or tool you cannot modify that

executes in the Centura Software runtime environment, and

in certain contexts, places double quotes around names it sends to the


database.

The statement causes SQLRouter/Oracle to strip off the double quotes before it sends
the data to the database.
substitute=,

Stored procedures
Centura SQLWindows applications can execute PL/SQL stored procedures on an
Oracle database. These stored procedures can also generate trigger events. To execute
a PL/SQL stored procedure, use the SqlPLSQLCommand function.
A PL/SQL stored procedure invoked by SqlPLSQLCommand can have no more than
254 arguments. Also, the string used to invoke the procedure cannot contain new line
characters, nor can it execute stand-alone functions. However, the array arguments
can be dynamic arrayssee Dynamic Array support for PL/SQL stored procedures
on page 5-14.
The SqlPLSQLCommand cannot process stored procedures without arguments. To
execute a stored procedure without arguments, use SqlPrepareAndExecute. For
example:
If NOT SqlPrepareAndExecute(hSql,
'BEGIN anonymous_PL/SQL_block;END;')

SqlPLSQLCommand supports only the following Oracle data types for both scalar
and array arguments for stored procedures:

NUMBER

CHAR

VARCHAR

VARCHAR2

You must explicitly specify the size of CHAR, VARCHAR, or VARCHAR2 data
types as arguments to a PL/SQL stored procedure. You can use either %type or define
your own data type. For example, if the stored procedure takes a CHAR argument that
Connecting Centura Objects to Databases

5-11

Chapter

Connecting to Oracle

is a value for a column in a table, use %type with table_name.column_name to


declare that variable. If the argument does not tie in with a database column, you can
define MYCHAR CHAR(20), then use %type with MYCHAR to declare your
argument.
If you do not specify the size, SQLNetwork binds the arguments with the maximum
size allowed for each data types.

Overloading stored procedures


SQLRouter/Oracle supports overloaded stored procedures in PL/SQL packages;
however, you must:

Define procedures with greater number of arguments before procedures with


fewer arguments.

Use all the same types in any argument position IN, OUT, or IN/OUT types.

Use all scalar or array types in any argument position.

Important: You cannot mix data types, nor can you use the DATE type in arguments for
overloaded procedures.

For general information about stored procedures, read Stored procedures on page 121.

SqlPLSQLCommand
Use this function to execute PL/SQL stored procedures in your Centura
SQLWindows application. Call it once for each invocation of PL/SQL.
Syntax

bOk = SqlPLSQLCommand(hSql, strCommand)

Parameters

hSqlHandleThe connected SQL handle to an Oracle database.


strCommandCommand string used to invoke a PL/SQL procedure.

Description

The first parameter identifies the SQL handle to the database. The second parameter
is a command string used to invoke a PL/SQL stored procedure. Like a stored
procedure call, this command string must have a name.
You can use PL/SQL IN variables the same way you use any other parameter in SAL
function calls.
PL/SQL OUT or IN/OUT variables must be valid SAL Receive parameters. These
parameters, like SAL Receive parameters, are set when the call returns.
You can use arrays for IN, OUT, and IN/OUT parameters.

5-12 Connecting Centura Objects to Databases

Stored procedures

IN/OUT parameters can be made to pass data to the PL/SQL stored procedure and to
receive data from a PL/SQL stored procedure in the same parameter.
Return Value

bOk is TRUE if the function succeeds and FALSE if it fails.

Example PL/SQL stored procedure


The following example shows a PL/SQL stored procedure named INVOICES that
contains a procedure, INSERT_INVOICES. This procedure inserts one master record
and a set of detail records into the database.
CREATE or REPLACE PACKAGE invoices AS
TYPE item_no_tbl IS TABLE OF invoice_detail.item_no%TYPE
INDEX BY BINARY_INTEGER;
TYPE quantity_tbl IS TABLE OF invoice_detail.quantity%TYPE
INDEX BY BINARY_INTEGER;
TYPE amount_tbl IS TABLE OF invoice_detail.amount%TYPE
INDEX BY BINARY_INTEGER;
PROCEDURE insert_invoice
(o_invoice_id OUT invoice_master.invoice_id%TYPE,
i_client_name IN invoice_master.client_name%TYPE,
i_invoice_date IN invoice_master.invoice_date%TYPE,
i_item_no IN item_no_tbl,
i_quantity IN quantity_tbl,
i_amount IN amount_tbl,
i_num_details IN NUMBER);
END INVOICES;
CREATE or REPLACE PACKAGE BODY invoices AS
next_invoice_id NUMBER;
PROCEDURE insert_invoice
(o_invoice_id OUT invoice_master.invoice_id%TYPE,
i_client_name IN invoice_master.client_name%TYPE,
i_invoice_date IN invoice_master.invoice_date%TYPE,
i_item_no IN item_no_tbl,
i_quantity IN quantity_tbl,
i_amount IN amount_tbl,
i_num_details IN NUMBER) IS
BEGIN
SELECT INVOICE_SEQ.NEXTVAL INTO next_invoice_id
FROM DUAL;
o_invoice_id:=next_invoice_id;
INSERT INTO INVOICE_MASTER
(INVOICE_ID,CLIENT_NAME,INVOICE_DATE)VALUES
(next_invoice_id,i_client_name,i_invoice_date);
FOR n IN 1..i_num_details LOOP
INSERT INTO INVOICE_DETAIL
(INVOICE_ID,ITEM_NO,QUANTITY,AMOUNT) VALUES
(next_invoice_id,i_item_no(n),i_quantity(n),
i_amount(n));
Connecting Centura Objects to Databases

5-13

Chapter

Connecting to Oracle

END LOOP;
COMMIT;
END insert_invoice;
END invoices;

Executing the sample stored procedure


The following example shows how to execute the example PL/SQL stored procedure
from a Centura SQLWindows application.
Number:ninv_id
String:strClient
String:strCommand
Date:dt_inv_dt
Number:nitem_No[3]
Number:nQnty[3]
Number:nAmt[3]
Number:nNum
Set
Set
Set
Set
Set
Set
Set
Set
Set
Set
Set
Set
Set
Set
Set
Set

ninv_id = 3
strClient = John Doe
strCommand = INVOICES.INSERT_INVOICE
strCommand = strCommand || (ninv_id,strClient,dt_inv_dt,
strCommand = strCommand || nitem_No,nQnty,nAmt,nNum)
dt_inv_dt = 1993-07-12
nitem_No[0] = 3
nitem_No[1] = 4
nitem_No[2] = 5
nQnty[0] = 13
nQnty[1] = 14
nQnty[2] = 15
nAmt[0] = 21
nAmt[1] = 22
nAmt[2] = 23
nNum = 3

SET bOK=SqlPLSQLCommand(hSql, strCommand)

Dynamic Array support for PL/SQL stored procedures


You can use dynamic arrays as input, output, and input/output arguments to Oracle8
PL/SQL stored procedures. The arrays can be of type NUMBER, STRING and
DATE/TIME.

Dynamic Arrays as INPUT arguments


Dynamic arrays grow to the size of the largest index value used in an assignment
statement using the dynamic array variables. For example, the following statements
cause nDynVar to be a dynamic array of 10 elements:

5-14 Connecting Centura Objects to Databases

Transactions, disconnects, and exits

nDynVar[0] = 0
nDynVar[1] = 1
nDynVar[9] = 9

When you pass a dynamic array as an INPUT argument to a PL/SQL stored procedure
using SqlPLSQLCommand, the number of elements created on the client are available
on the database server. For example, the stored procedure:
insert into foo values(nDynVar[9])

inserts the value 9 into the table, whereas the statement:


insert into foo values(nDynVar[10])

causes the error Attempting to fetch beyond end of result set.

Uninitialized values
Do not initialize dynamic arrays. The arrays are passed as NULL for data types
STRING and DATE/TIME, and as zero for data type NUMBER. To pass NUMBER
as a NULL, the user must explicitly assign it the value Number_Null.

Dynamic Arrays as OUTPUT arguments


The size of output arguments of type dynamic array is determined in the backend
stored procedure. For example, the following statements return an array of ten
elements to your Centura SQLWindows application:
sOutVar(1) := abc;
sOutVar(10) := def;

Uninitialized values
Values for output arguments are not initialized on the backend, but are returned as
NULL values.

Dynamic Arrays as INPUT/OUTPUT arguments


INPUT/OUTPUT dynamic arrays behave as INPUT dynamic arrays on input and as
OUTPUT dynamic arrays on OUTPUT.

Transactions, disconnects, and exits


If autocommit is off in your application, you are responsible for explicitly committing
or rolling back transactions. The rest of this section assumes that autocommit is off.
If you disconnect from the database without committing or rolling back a pending
transaction, the database commits the transaction for you.

Connecting Centura Objects to Databases

5-15

Chapter

Connecting to Oracle

If you exit the application normally without committing or rolling back a pending
transaction, the database commits the transaction for you.
If you exit the application abnormally without committing or rolling back a pending
transaction, the database rolls back the transaction for you.

Writing RAW data


To INSERT or UPDATE columns that contain RAW data, you must first assign the
data to be placed in that column to an appropriate bind variable, then prepare an
INSERT or UPDATE statement using that bind variable.
The bind variable must be of type LONG STRING. Once you have prepared the
INSERT or UPDATE statement, you must call SqlSetLongBindDatatype to bind the
LONG STRING data to the RAW data type. You then execute the INSERT or
UPDATE statement.
Important: You must prepare the INSERT or UPDATE statement without executing it, then
call SqlSetLongBindDatatype, then execute the INSERT or UPDATE statement. The binding
done by SqlSetLongBindDatatype lasts only until your application prepares the next SQL
statement.
The call to SqlSetLongBindDatatype takes two arguments: the first is the ordinal
position of the bind variable that has the LONG STRING data in the INSERT or
UPDATE statement; the second is the constant 23this constant denotes RAW data
in the case of Oracle databases. (You can declare a user constant with a symbolic
name like nRaw and assign it the value 23; this makes your code more selfdocumenting.)
For example, assume an Oracle table called PRODUCT with the following column
data types:

INTEGER for style ID information

VARCHAR(30) for style information

VARCHAR(254)for description information

DEMICAL(8,2)for price information

LONG RAWfor picture information

Also assume the following variable declarations in your application:


Number: nStyleId
String: strStyle
String: strDesc
Numnber: nPrice

5-16 Connecting Centura Objects to Databases

Writing RAW data

Long String: lstrPicture

Now assume you have assigned these variables values in your program. You can add
a row to the PRODUCT table as follows:
Set strStmnt=INSERT INTO PRODUCT VALUES
Set strStmnt=strStmnt || (:nStyleId,:strStyle,:strDesc,
Set strStmnt=strStmnt || :nPrice,:lstrPicture)
Call SqlPrepare(hOracle,strStmnt)
Call SqlSetLongBindDatatype(5,23)
Call SqlExecute(hOracle)

The first argument to SqlSetLongBindDatatype is 5 because :lstrPicture is the


bind variable that has the data to be inserted into the LONG RAW column, and it
appears as the fifth bind variable in the INSERT statement. The second argument
must be 23 (or a symbolic integer constant you define yourself that has that value).

Connecting Centura Objects to Databases

5-17

Connecting Centura Objects to Databases

Chapter 6

Connecting to Sybase
This chapter describes how to connect Centura SQLWindows applications to System
11.5 and 11.9.2.

Connecting Centura Objects to Databases

6-1

Chapter

Connecting to Sybase

Before you begin


Please read all of Chapter 1, Overview and Chapter 2, Initializing and Testing Your
Connection before reading this chapter.
You connect Centura SQLWindows applications to a System 11.x server using the
Centura native router, SQLRouter/Sybase.

Autocommit and chained transactions


System 11.x supports autocommit.
To turn autocommit on or off, set the sybautocommit keyword in the SQL.INI file
to the appropriate valuesee sybautocommit on page 6-23.
If you turn autocommit on, the database server automatically commits results from
each SQL statement that executes successfully; the server also disables chained
transactions.
If you disable autocommit, you must explicitly COMMIT (or ROLLBACK) any
changes to the database. Because disabling autocommit also enables chained
transactions, you do not need to place BEGIN TRANSACTION in front of the
statements that make up the transactionjust put a COMMIT (or ROLLBACK) at
the end of that group of statements.
Note: By default, DDL (Data Definition Language) statements, such as CREATE TABLE, are
not valid within a transaction. However, your Sybase database administrator can configure the
database to allow some DDL statements as part of a transaction.
Even if you enable autocommit, you can still precede a specific sequence of SQL
statements with the BEGIN TRANSACTION statement and follow them with a
COMMIT (or ROLLBACK) statement. The statements in between BEGIN
TRANSACTION and COMMIT are not committed until the COMMIT is executed
and they are rolled back if ROLLBACK is executed. Bracketing statements in this
way allows you to suppress autocommit for those statements.
Important: Use the sybautocommit keyword to enable or disable autocommit; do not
use the Transact-SQL SET statement.

For background information on autocommit, read Autocommit on page 1-3.

6-2

Connecting Centura Objects to Databases

Bind variables

Bind variables
System 11.x, unlike earlier Sybase databases, provide native support for pre-compiled
commands, and hence, input bind variables.
For general information about bind variables, read Bind variables on page 1-5.
There are certain limitations on how you can use bind variables with System 11.x.
For example, the following SQL statement fails because you cannot use a bind
variable to specify a table name:
Call SqlPrepare(hSql,
INSERT INTO :dfTabName VALUES(1))

Call SqlExecute(hSql)
Note: If you have existing applications that worked with a Sybase database prior to System
11.x, you may have code like this that you will have to change.

SQLRouter/Sybase implements the native input bind variable support of ClientLibrary and SQL Server whenever possible. This includes

SELECT

INSERT

UPDATE (except positioned UPDATEs)

DELETE (except positioned DELETEs)

In all other cases (stored procedures, DDL, and so on), bind variable support is
simulated through substitution of bind variable values just prior to execution. Unlike
native bind variables, input bind variables are supported merely as a programming
convenience, not as a way of improving performance.
For example, if we assume dfInput has the value 231, the code:
Call SybPrepareProc(hSql,sp_foo @var1 = :dfInput,
:dfInput)
Call SqlExecute(hSql)

sends the following SQL statement to the database server:


sp_foo @var1 = 231

Important: For maximum portability, avoid using bind variables that are not ANSIcompliant.

Connecting Centura Objects to Databases

6-3

Chapter

Connecting to Sybase

COMPUTE clause
SQLRouter/Sybase does not support the Transact-SQL extension of COMPUTE.
Any query containing a COMPUTE clause returns error #32028:
COMPUTE clause not supported.
Also, any COMPUTE results from stored procedures may result in a premature ENDOF-FETCH.

Cursor context preservation


SQLRouter/Sybase supports cursor-context preservation (CCP) through the ClientLibrary database option CLOSE ON END TRANS. In Centura SQLWindows
applications that connect to System 11.x, CCP is off by default.
System 11.x considers all cursors to belong to the same database transaction. When
CCP is enabled, all cursors maintain their contexts. Likewise, when CCP is disabled,
all cursors lose their context after a COMMIT or ROLLBACK is executed. Although
you call the function SqlSetParameter (with the parameter DBP_PRESERVE) to
enable or disable CCP, and you specify a particular SQL handle as the first parameter
in that call, the scope of CCP is not limited to that one handlethe effect is global to
the connection and to all cursors associated with the transaction being executed on
that connection. (See also enablemultipleconnections on page 6-18 for more
information about SQL handles and connections.)
Important: Call SqlSetParameter to enable or disable CCP; do not execute the TransactSQL SET statement CLOSE ON END TRANS.

If CCP is on (and autocommit is off), you can continue to execute prepared SQL
statements (without preparing them again) even after you commit the transaction that
those statements are a part of. If CCP is off, however, you cannot re-execute those
SQL statements once you commit the transaction without preparing them again.
For general background information about CCP, read Cursor context preservation on
page 1-7.

6-4

Connecting Centura Objects to Databases

Data types

Data types
The table that follows shows the mapping between the data types supported by a
Centura SQLWindows application and the data types supported by a Sybase System
11.x database server.
Mapping of Data Types to System 11.x
Centura SQLWindows
Data Type
STRING

LONG STRING

NUMBER

DATE/TIME

System 11.x Data Type


CHAR (1254 bytes)
VARCHAR (1254 bytes)
BINARY (1127 bytes)
VARBINARY (1127 bytes)
TIMESTAMP
CHAR (1255 bytes)
VARCHAR (1255)
IMAGE (1(2311) bytes)
TEXT (1(2311) bytes)
BINARY (128255 bytes)
VARBINARY (128255 bytes)
BIT
NUMERIC
TINYINT
SMALLINT
INT
FLOAT
DECIMAL
DOUBLE PRECISION
REAL
SMALLMONEY
MONEY
SMALLDATETIME
DATETIME

Note: To write more than 31,997 bytes of IMAGE or 64,000 bytes of TEXT data, you must
call the function SybWriteTextsee Writing and retrieving IMAGE and TEXT data on
page 6-37.

Using the timestamp data type


TIMESTAMP is a Sybase-supplied but user-defined data type that is treated as the
data type VARBINARY(8) for storage and retrieval. You fetch this data into a
STRING variable, where it is stored in hexadecimal format.
Connecting Centura Objects to Databases

6-5

Chapter

Connecting to Sybase

You cannot update a TIMESTAMP column. You also cannot insert a row with a
TIMESTAMP column where you specify your own TIMESTAMP valuespecify
NULL for the TIMESTAMP, and the database will insert the correct value for you.
For example, suppose you create a table as follows:
create table t1(c1 int,c2 timestamp,c3 int)

To insert a new row, you execute the statement:


insert into t1 values(1,NULL,3)

The database server stores the integer 1 in column c1, the integer 3 in column c3, and
the current system-generated timestamp value in column timestamp.

Empty strings
On System 11.x, if you try to insert the empty string into a varying-length character
string column (or try to update such a column with the empty string), the database
stores a space instead.
For background information, read the section Nulls, empty strings, and spaces on
page 1-15.

Error processing
SQLRouter/Sybase derives its error code and text from one of three possible sources:
the Centura SQLWindows file ERROR.SQL, Client-Library messages, or database
messages. SQLRouter/Sybase can receive multiple messages; it evaluates all the
messages and tries to report only the one that is most informative.
As a result, the first message returned by SybGetClientMsg or SybGetServerMsg does
not necessarily match the error code and text that SQLRouter/Sybase reports to the
application. (For more information on SybGetClientMsg and SybGetServerMsg, see
Retrieving error and info messages on page 6-8.)
A separate message buffer is created for each connection associated with a given
application, database name, and user name. All SQL handles on the same connection
share this single message buffer. The message buffer is cleared whenever a new SQL
command is sent to the database server using one of the SQL handles associated with
the connection.
The number of messages that can be saved is limited. Each saved message consumes
a small amount of fixed overhead, limiting the total number of saved messages to
5000. Attempts to save more than 5000 messages are ignored. All message text for
any single command must fit within 64,000 bytes; otherwise, the saving of messages
is suspended.

6-6

Connecting Centura Objects to Databases

Error processing

The formula for calculating memory consumption is:


nMemory = (nMaxMessages * (nMaxLength + 22))
* nConnections

Error precedence
With few exceptions (for example, connection failure or results pending), ClientLibrary messages usually indicate a problem with SQLRouter/Sybase or ClientLibrary itself.
When multiple sources are possible for reporting an error condition, the source is
based on the following order of precedence:

Centura SQLWindows runtime error code (032,767)

System 11.x message (065,536)

Client-Library message (065,536)

All of the error code ranges overlap. To help keep them separate, SQLRouter/Sybase
reports the error code to the application using the following modified ranges:

Centura SQLWindows runtime error code (0 19,999)

System 11.x message (20,00029,999)

Client-Library message (30,00032,767)

Errors greater than 32,767 always return error 32,100; the actual error number
appears at the beginning of the message text.
Note: You can always get the actual error code and text from Client-Library (System 11.x)
messages by calling the SQLRouter/Sybase Message APIread the section Retrieving error
and info messages on page 6-8 for more information.

RAISERROR
RAISERRORs are user-defined errors typically added to stored procedures. They are
considered informational and non-fatal.
SQLBase Router/Sybase returns different values depending on the value specified in
the first RAISERROR statement that is actually executed in the stored procedure:

If the value of the first RAISERROR is less than 17,000, then the Sybase
backend returns an error.

If the value of the first RAISERROR is exactly 17, 000, then SqlRouter/
Sybase will return that value plus any additional RAISERROR values (You
have to call SybGetServerMsg () repeatedly to get all ofthe RAISERROR
vlaues, and the reult set (if any )WILL be returned.

Connecting Centura Objects to Databases

6-7

Chapter

Connecting to Sybase

If the value of the first RAISERROR is greater than 17,000, then SqlRouter/
Sybase will return that value and any subsequent values of RAISERROR, but
WILL NOT return a result set, regarless if one was actually returned by the
Sybase backend.

If you plan to use RAISERROR as a warning or as an indicaor to direct further


logic in your program, then you should make sure your stored procedure always first
has a value of 17,000, an then use additonal RAISERROR statements to indicate
different coniditions. Your program can check for the first error to be exactly 17,000
and would then know to look for additional RAISERROR values. At the same time, it
could retrieve the result set from the stored procedure execution . The result set will
NOT be available if the RAISERROR statement specifies any value other than
17,000.

Retrieving error and info messages


To retrieve client and server error and informational messages, or find out how many
messages there are, call one of the SAL function listed below. These functions are
understood by SQLRouter/Sybase.
Important: To enable the saving of messages, you must include the keyword
sybmaxmessages in the SQL.INI file.

SybGetClientMsgCount
Use this function to return the number of currently buffered client messages.
Syntax

bOk=SybGetClientMsgCount(hSql, nCount)
Sql Handle: hSql
Receive Number: nCount

Parameters

hSqlA handle that identifies a connection context to the database.


nCountThe number of buffered client messages.

Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Description

This function returns the number of client messages currently buffered on handle
hSql in nCount. Messages occupy positions 1 through nCount in the buffer.

Notes

To enable the buffering of messages, include the sybmaxmessages keyword in the


SQL.INI file.

SybGetClientMsg
Use this function to retrieve the number, text, and severity of an arbitrary client
message.
6-8

Connecting Centura Objects to Databases

Error processing

Syntax

bOk=SybGetClientMsg(hSql, nPosition, nMsgNumber, strMsgText,


nSeverity)
Sql Handle: hSql
Number: nPosition
Receive Number: nMsgNumber
Receive String: strMsgText
Receive Number: nSeverity

Parameters

hSqlA handle that identifies a connection context to the database.


nPositionThe position of the message to be retrieved in the message buffer.
nMsgnumberThe number associated with the retrieved message.
strMsgtextThe text of the retrieved message.
nSeverityThe severity of the retrieved message.

Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Description

This function returns the number, text, and severity of the client message in position
nPosition of the message buffer.
The function fails if the buffer is empty, the end of the buffer has been reached, or you
supply an invalid value for nPosition.

Notes

To enable the buffering of messages, include the sybmaxmessages keyword in the


SQL.INI file.

SybGetNextClientMsg
Use this function to retrieve the number, text, and severity of the next client message.
Syntax

bOk=SybGetNextClientMsg(hSql, nMsgNumber, strMsgText, nSeverity)


Sql Handle: hSql
Receive Number: nMsgNumber
Receive String: strMsgText
Receive Number: nSeverity

Parameters

hSqlA handle that identifies a connection context to the database.


nMsgnumberThe number associated with the retrieved message.
strMsgtextThe text of the retrieved message.

Connecting Centura Objects to Databases

6-9

Chapter

Connecting to Sybase

nSeverityThe severity of the retrieved message.


Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Description

This function returns the number, text, and severity of the next client message in the
message buffer.
The function fails if the buffer is empty or the end of the buffer has been reached.

Notes

To enable the buffering of messages, include the sybmaxmessages keyword in the


SQL.INI file.

SybGetServerMsgCount
Use this function to return the number of currently buffered server messages.
Syntax

bOk=SybGetServerMsgCount(hSql, nCount)
Sql Handle: hSql
Number: nCount

Parameters

hSqlA handle that identifies a connection context to the database.


nCountThe number of buffered server messages.

Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Description

This function returns the number of server messages currently buffered on handle
hSql. Messages occupy positions 1 through nCount in the buffer.

Notes

To enable the buffering of messages, include the sybmaxmessages keyword in the


SQL.INI file.

SybGetServerMsg
Use this function to retrieve the number, text, and severity of an arbitrary server
message.
Syntax

bOk=SybGetServerMsg(hSql, nPosition, nMsgNumber, strMsgText,


nSeverity)
Sql Handle: hSql
Number: nPosition
Receive Number: nMsgNumber
Receive String: strMsgText
Receive Number: nSeverity

Parameters

hSqlA handle that identifies a connection context to the database.

6-10 Connecting Centura Objects to Databases

Error processing

nPositionThe position of the message to be retrieved in the message buffer.


nMsgnumberThe number associated with the retrieved message.
strMsgtextThe text of the retrieved message.
nSeverityThe severity of the retrieved message.
Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Description

This function returns the number, text, and severity of the server message in position
nPosition of the message buffer.
The function fails if the buffer is empty, the end of the buffer has been reached, or you
supply an invalid value for nPosition.

Notes

To enable the buffering of messages, include the sybmaxmessages keyword in the


SQL.INI file.

SybGetNextServerMsg
Use this function to retrieve the number, text, and severity of the next server message.
Syntax

bOk=SybGetNextServerMsg(hSql, nMsgNumber, strMsgText, nSeverity)


Sql Handle: hSql
Receive Number: nMsgNumber
Receive String: strMsgText
Receive Number: nSeverity

Parameters

hSqlA handle that identifies a connection context to the database.


nMsgnumberThe number associated with the retrieved message.
strMsgtextThe text of the retrieved message.
nSeverityThe severity of the retrieved message.

Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Description

This function returns the number, text, and severity of the next server message in the
message buffer.
The function fails if the buffer is empty or the end of the buffer has been reached.

Notes

To enable the buffering of messages, include the sybmaxmessages keyword in the


SQL.INI file.

Connecting Centura Objects to Databases

6-11

Chapter

Connecting to Sybase

Examples
To retrieve all messages from the DBCC (Database Consistency Checker) command,
you could code the following:
Call SqlPrepareAndExecute(hSql,dbcc checkdb)
! Establish position in message buffer.
If SybGetServerMsg(hSql, 1, nMsgno, strMsgtext,
nSeverity)
! Traverse the remaining messages.
Loop
If NOT SybGetNextServerMsg(hSql, nMsgno,
strMsgtext, nSeverity)
Break
...
...
Since this is the first time the application traverses the message buffer for this
command, the following example is functionally equivalent:
Call SqlPrepareAndExecute(hSql,dbcc checkdb)
! Traverse all the messages.
Loop
If NOT SybGetNextServerMsg(hSql, nMsgno,
strMsgText, nSeverity)
Break
...
Important: All messages belong to the connection. Individual SQL handles within the same
connection access a single message buffer and inherit their current positioning from any
positioning established by prior SQL handles.

Getting multiple connections


When you obtain multiple SQL handles by calling SqlConnect more than once, you
can choose to have all the SQL handles that are associated with the same user ID,
password and database name share the same connection, or you can choose to have
each SQL handle get its own connection. You control this behavior with the
enablemultipleconnections keyword in the SQL.INI fileread
enablemultipleconnections on page 6-18.

6-12 Connecting Centura Objects to Databases

Handles and connections

Handles and connections


SQLRouter/Sybase allows your Centura application to connect to Sybase System 11.x
with either multiple connections and a single SQL handle on each connection, or with
multiple SQL handles on a single connection. This behavior is controlled by a
keyword in the SQL.INI filesee the section enablemultipleconnections on page 618.
SQLRouter/Sybase can support no more than 50 connections per application. Each
connection can support no more than 255 SQL handles.
Note: Because each connection consumes certain resources on the client, the actual number of
connections and handles available at runtime can vary.

SQLRouter/Sybase takes advantage of native System 11.x cursors to support


temporary tables, the SET database_options statement, and the changing of
passwords (with sp_password). For more background information, read Handles,
contexts, and connections on page 1-9.

Isolation levels
System 11.x supports isolation levels through the transaction isolation level feature.
Level 1 prevents dirty reads; Level 3 prevents phantom rows.
Sybase 11.5: SQLRouter/Sybase supports these isolation levels by mapping the
Centura SQLWindows isolation level CS to Level 1 and the isolation level RR to
Level 3.
Sybase11.9.2: Transaction isolation level 2 is explicitly provided for data-only locked
tables.
This table summarizes the mapping of isolation levels:
Isolation Level Mapping
Centura
SQLWindows

System 11.5

System 11.9.2

RO

Isolation Level 0

Isolation Level 0

CS

Isolation Level 1

Isolation Level 1

RL

Isolation Level 2
(Not supported)

Isolation Level 2

RR

Isolation Level 3

Isolation Level 3

Connecting Centura Objects to Databases

6-13

Chapter

Connecting to Sybase

For background information, read Isolation levels on page 1-12.

Positioned updates
Client-Library supports positioned UPDATEs and DELETEs through its native
cursor support. Consequently, SQLRouter/Sybase does not support the FOR
BROWSE clauseuse the FOR UPDATE clause in your Centura SQLWindows
applications.
Important: To update IMAGE and TEXT data, you need to use the FOR LONG UPDATE
clause (a Centura extension) instead of the standard FOR UPDATE clause. For more
information, read the section Writing and retrieving IMAGE and TEXT data on page 6-37.

You might code a typical application as follows:


! Disable result set mode; otherwise, we will fetch

! only one row at a time.


SqlSetResultSet(hSql, FALSE)
! Compile the statement, execute it,
! and name the cursor.
SqlPrepare(hSql,SELECT key, timestamp, name ||
FROM foo into :dfKey,:dfTS,:dfName ||
FOR UPDATE)
SqlOpen(hSql,CurA)
! Position us on the appropriate row.
SqlFetchNext(hSql, nRetVal)
! Switch to another context (SQL handle)
! to handle the UPDATE.
! Point to the SELECT targeted for the UPDATE by
! referencing the named cursor.
SqlPrepare(hSql2,UPDATE foo SET name = :dfName ||
WHERE CURRENT OF CurA)
SqlExecute(hSql2)
Committing the change (assuming sybautocommit=off is in the SQL.INI file)
destroys the context of the SELECT (unless CCP has been enabled for the
appropriate cursors).
Note: Unlike FOR BROWSE (which creates a temporary copy of the results set from which
rows are fetched), FOR UPDATE is a true, positioned update operation. Intent to update
locks are held on the actual table until EOF or a COMMIT, so you get less concurrency with
FOR UPDATE than with FOR BROWSE.

6-14 Connecting Centura Objects to Databases

Positioned updates

Positioned updates and fetchrow


Rows are fetched in batches sized for the buffers allocated at the network message
layer. Handles allow the application to control the way data is sent across the network.
The keyword fetchrow in the SQL.INI file (see fetchrow on page 6-18) is used
to request of the communications layer that it bundle multiple rows of data per
network fetch message back to Net-Library.
SQLRouter/Sybase implements handles for explicit SELECT statements in stored
procedures that contain a single SELECT statement. During positioned UPDATEs
and DELETEs, rows are always fetched one at a time. Therefore, these operations are
not affected by the fetchrow setting. Since the client and server must be in sync
in terms of current row positioning, permitting multiple rows to be fetched at the
network level is not appropriate. For performance reasons, you typically do not want
to use SELECT... FOR UPDATE requests unless you have very small result sets or
you think it likely your application will need to do a positioned update or delete while
fetching rows from a result set.
Note: SQLRouter/Sybase depends on the default locking behavior of the Sybase database
(unless the user explicitly changes this behavior). You should use the SHARE option in your
SELECT statements whenever possible to avoid lock contention.
The more rows your application fetches per message, the longer it takes for control to
return to the application. Thus, users of your application may actually perceive better
performance with smaller fetchrow values, since the application can populate a
table window, list box, or other object sooner. Large fetchrow values can even
cause unnecessary rows to be fetched, if the row of interest is located at the beginning
of the result set and the buffer is filled with rows that are eventually discarded.
In general, the larger the fetchrow setting, the faster the result sets can be sent to
the client. However, pacing problems and protocol buffer limits influence the
performance level you can expect; at some point you may even experience
performance degradation with a high fetchrow setting. Factors including result set
size, typical row size, network configuration, client and server operating systems, and
application requirements, all affect the optimal setting of this value. You may also
need to increase the network packet size (see remotedbname later in this chapter) to
use this feature effectively.
Note: You can set the number of rows retrieved per network message either in the SQL.INI
file with the fetchrow keyword or in your Centura SQLWindows application by calling the
function SqlSetParameterAll.
For background information, read Positioned updates on page 1-17.

Connecting Centura Objects to Databases

6-15

Chapter

Connecting to Sybase

Releasing locks
You can expedite the releasing of locks on a result set by forcing System 11.x to close
the result set cursor once you have fetched the last row from a result set. You enable
this behavior using the closecursorateof keyword in the SQL.INI fileread
closecursorateof on page 6-17.

Reserved strings
The following are SQLRouter/Sybase reserved words, clauses, or names:

CANCEL

CANCEL ALL

WITH CURSOR

_BIN2HEX_

_HEX_

FOR LONG UPDATE

For more information about _BIN2HEX_, _HEX_, and FOR LONG UPDATE, read
the section Writing and retrieving IMAGE and TEXT data on page 6-37.

SQL.INI keywords
This section describes the SQL.INI keywords you want or need to use to initialize a
Centura SQLWindows application that connects to Sybase System 11.x.
For more information about the SQL.INI file, read Initializing Centura SQLWindows
applications on page 2-4.

checkexists
Use this keyword to get an error after executing an UPDATE or DELETE statement
that has no effect.
Section

[sybgtwy]

Default

off

Syntax

checkexists={on|off}

Description

This keyword causes SQLRouter/Sybase to return an error when the application


executes an UPDATE or DELETE statement that has no effect (that is, no rows in the
database are updated or deleted). The error that SQLRouter/Sybase returns is #380,
CHECK EXIST failure.

6-16 Connecting Centura Objects to Databases

SQL.INI keywords

Notes

If your application calls a stored procedure to execute the UPDATE or DELETE


statement (instead of executing the statement directly), SQLRouter/Sybase cannot
determine if any rows were affected. Therefore, your application will not get the
error, even if you set checkexists to on and no rows were updated or deleted by
the stored procedure.

Example

This statement causes an application to get the CHECK EXIST failure if the
application executes an UPDATE or DELETE statement that affects no rows.
checkexists=on

closecursorateof
Use this keyword to force the closing of a result set cursor once you have fetched the
last row from that result set.
Section

[sybgtwy]

Default

off

Syntax

closecursorateof={on|off}

Description

If you set this keyword to off (or you accept this value by default), you keep the
result set cursor (and your lock on the rows in the result set) until you successfully
execute a COMMIT or ROLLBACK, or until you disconnect from the database.
If you set this keyword to on (and CCP is offsee Cursor context preservation on
page 6-4), you lose the result set cursor (and your lock on the rows in the result set)
once you have fetched the last row of the result set.
Setting this keyword to on allows you to perform DML (Data Manipulation
Language) statements (such as UPDATE, DELETE, INSERT) on the same table from
which you have gotten a result set (with a SELECT statement). If you do not set this
keyword to on, a DML statement that operates on that table will fail (time out); this
is because the SELECT statement that got the result set in the first place still has a
lock on that table.

Example

This example (assuming CCP is off) causes the cursor in a result set to be closed once
the last row from that result set has been fetched; this releases the lock on the table
from which you got the result set.
closecursorateof=on

comdll
Identify the SQLRouters available between Centura SQLWindows (or a client
application created with Centura SQLWindows) and the database.
Section

[win32client.dll]

Connecting Centura Objects to Databases

6-17

Chapter

Connecting to Sybase

Syntax

comdll=communication_dll_name

Description

This keyword identifies the filename of a SQLRouter DLL. You can put more than
one comdll statement in the SQL.INI file. The value of communication_dll_name
to use for SQLRouter/Sybase is sqlsyb32.

Example

comdll=sqlsyb32

Notes

For related information, read Connect search order on page 1-6.

enablemultipleconnections
Use this keyword to force the creation of a new connection to the database for each
call to SqlConnect.
Section

[sybgtwy]

Default

off

Syntax

enablemultipleconnections={on|off}

Description

If this keyword is set to on, you get a new connection to the database each time you
call SqlConnect, even if the SQL handle argument to SqlConnect is associated with
the same user ID, password, and database name as one of the already connected SQL
handles.
If this keyword is set to off, and you have already called SqlConnect at least once,
you may or may not get a new connection to the database when you call SqlConnect
again. You do not get a new connection if the SQL handle argument in the call is
associated with the same user ID, password, and database name as one of the already
connected SQL handles; otherwise, you do get a new connection.

Example

This example forces the creation of a new connection to the database for each call to
SqlConnect.
enablemultipleconnections=on

fetchrow
This keyword specifies the maximum number of rows SQLRouter/Sybase retrieves
for each network message during cursor operations (fetching) on a result set.
Section

[sybgtwy]

Default

20

Syntax

fetchrow=number_of_rows

Description

number_of_rows must be a positive integer (but do not put a plus sign).

6-18 Connecting Centura Objects to Databases

SQL.INI keywords

The server uses an array to hold the fetched column values. SQLRouter/Sybase
retrieves rows for each network fetch requested, according to the following
algorithm:
1.

Take the width of the widest column and divide it into the maximum size of the
array buffer.

2.

If the calculated value is smaller than the value of fetchrow, use the calculated
value.

3.

Otherwise, use the value of fetchrow. If no value is defined, use the default
value of 20.

The value assigned to fetchrow is not used if:

You use the FOR UPDATE clause in a SELECT statement (CURRENT OF


cursor).

You specify a LONG column in the SELECT list.

You can improve performance by assigning a suitable value to fetchrow. To


achieve good performance, you must balance the number of rows per fetch (which
increases the memory used) against the operating systems need for memory (which
causes the operating system to swap memory when not enough is available).
Your Centura SQLWindows application still receives a single row for each call to
SqlFetchNext, regardless of the value assigned to fetchrow.
Example

This example indicates that only 10 rows are retrieved for each fetch.
fetchrow=10
This example indicates that you want to fetch only a single row (in effect, disabling
the feature).
fetchrow=1

locktimeout
Use this keyword to set the number of seconds SQLRouter/Sybase waits for System
11.x to respond to a login request or execute a statement.
Section

[sybgtwy]

Default

60 second wait for login; infinite wait for statements to execute

Syntax

locktimeout=number_of_seconds

Description

This keyword sets the login time-out and the statement execution time-out to
number_of_seconds. SQLRouter/Sybase will wait number_of_seconds to obtain a
server connection (login time-out). SQLRouter/Sybase will also wait

Connecting Centura Objects to Databases

6-19

Chapter

Connecting to Sybase

number_of_seconds for the server to obtain the resources it needs to execute a


statement (statement execution time-out).
If you set number_of_seconds to zero, SQLRouter/Sybase uses the default values of
60 seconds for the login time-out, and infinity (wait forever) for the statement
execution time-out.
When the time-out expires, SQLRouter/Sybase notifies System 11.x to abandon the
attempt to connect (login time-out) or the attempt to execute the statement (statement
execution time-out).
Notes

This keyword sets the time-out value for any Centura SQLWindows application and
for all connections the application makes to System and System 11.x. To set (or
override) the time-out value in your application, call SqlSetParameter with the
DBP_LOCKWAITTIMEOUT argument, or call SqlLockWaitTimeout.

Example

This example sets the login time-out and the statement execution time-out to three
minutes:
locktimeout=180

log
Use this keyword to activate the SQLRouter activity log.
Section

[win32client.syb32]

Syntax

log=fully_qualified_file_name

Description

You can specify any path or filename for the keyword. If the file already exists, it is
overwritten. Once the keyword is specified, logging is performed automatically with
each SQLRouter initialization. You can apply one or more of the following casesensitive options to customize the output:

/Bxexclude display of bind variable values

/Faappend to existing file

/FDdisplay fetch data

/Lddisplay LONG data read/written

/Txexclude display of timestamps

Enter the options exactly as shown, keeping upper-case letters upper-case and lowercase letters lower-case.
Example

The following example results in a log file that does not include timestamps on
entries (conserving space) and displays the input and output of all LONG (that is,
TEXT or IMAGE) data items.

6-20 Connecting Centura Objects to Databases

SQL.INI keywords

[winclient.syb32]
log=c:\centura\sybsys11.log /Tx /Ld

longbuffer
This keyword specifies the maximum number of bytes of long data type columns to
retrieve or send, and truncates excess bytes.
Sections

[sybgtwy]

Default

32650

Syntax

longbuffer=number_of_bytes

Description

Reduce the value of this keyword to conserve memory or reduce network traffic. If
you use longbuffer to limit the number of bytes to retrieve, the retrieved data is
truncated. To avoid truncating long data, set the value equal to the largest data type
size that your applications need to read.
The longbuffer keyword applies to all databases defined in the [sybgtwy]
section. You cannot specify a longbuffer value larger than the maximum size for
the data type to be retrieved.

Example

longbuffer=2000

Important: You can also set this environment variable in your Centura SQLWindows
application. If you do, call SqlSetParameterAll with the DBP_LONGBUFFER parameter; do
not set the size of this buffer with the Transact-SQL SET statement.

remotedbname
Use this keyword to specify database names and associated information.
Section

[sybgtwy]

Syntax

remotedbname=db_name1,server,db_name2,network_packet_size

Description

db_name1 specifies the database name as it is known by the Centura SQLWindows


application; the name may not be more than 8 characters long.
server specifies the name of the System 11.x server on which the database is located.
The server name can be found in the Sybase SQL.INI file located in the Open Client
installation subdirectory.
db_name2 specifies the actual database name as known by the server. This parameter
is optional; if you omit it, the name of the database is assumed to be the same as
db_name1. Unlike db_name1, the value of db_name2 is not limited to 8 characters.

Connecting Centura Objects to Databases

6-21

Chapter

Connecting to Sybase

network_packet_size is an optional parameter that specifies the network packet size


to use for this server connection. If you omit this parameter or give it a value of zero,
the connection uses the default network packet size negotiated between ClientLibrary/Net-Library and the server during connect processing.
Notes

For related information, read Connect search order on page 1-6.

Examples

This example specifies a database known by your Centura SQLWindows application


as PUBS. This database is located on the server SYBASE11. The server knows this
database as pubs2. The network packet size is the default negotiated between ClientLibrary and the server.
remotedbname=PUBS,SYBASE11,pubs2,0
This example differs from the preceding one in that SQLRouter/Sybase requests a
network packet size of 2048 bytes when it tries to connect to the database.
remotedbname=PUBS,SYBASE11,pubs2,2048

substitute
Use this keyword to specify that the string in the first parameter should replace the
string in the second parameter whenever the first parameter appears in an SQL
statement.
Sections

[sybgtwy]

Syntax

substitute=original_string,substitute_string

Description

Values for this keyword are case-sensitive and are separated by a comma (not a
space). You can have an unlimited number of substitute statements in the
initialization file. However, this statement changes all occurrences of the replaced
word in your SQL statementsoperators, WHERE clauses, object names, and
literals (but not bind variables).
The second string can include the first, as in:
substitute=od,odd
Important: The strings can include embedded blank spaces, but not commasyou must use
a comma to separate original_string from substitute_string.

Notes

Because each SQL statement is parsed, having substitute statements in your


SQL.INI file adds a small amount of overhead to the compilation of those statements.
If you are not running any Centura software that require substitution, you may want
to remove these statements from the file.

6-22 Connecting Centura Objects to Databases

SQL.INI keywords

If you do not want to have any substitutions done, leave this keyword out of the
SQL.INI file or comment out any lines that have this keyworddo not have a line
that looks like this:
substitute=

Example

The substitute statement below could be used with an application that (for
example) encloses table names in quotes. If you cannot modify the application, and if
the database you are connecting the application to does not accept double quotes, you
can have SQLRouter strip them off as follows:
substitute=,

sybapplicationname
Use this keyword to define the clients application name when logging in to the
database server.
Section

[sybgtwy]

Default

Centura Sybase App

Syntax

sybapplicationname=program_name

Description

program_name is stored in the dbo.sysprocesses of the master database for the


connection.

Notes

SQLRouter/Sybase defines the reserved identifier @APPNAME as the title of the


applications top-level window.

Example

This statement defines the client application name when logging in to the database
server as MYAPP:
sybapplicationname=MYAPP

sybautocommit
Use this keyword to turn autocommit on or off.
Section

[sybgtwy]

Default

off

Syntax

sybautocommit={on|off}

Description

To turn on autocommit, set sybautocommit to on; to turn off autocommit, set


sybautocommit to off.

Notes

For more information about autocommit, read Autocommit and chained transactions
on page 6-2.

Connecting Centura Objects to Databases

6-23

Chapter

Connecting to Sybase

You can also turn autocommit on and off in your Centura SQLWindows applications
by calling SqlSetParameter. For example, to disable autocommit, make either one of
the following calls:
Call SqlSetParameter(hSql,DBP_AUTOCOMMIT,FALSE,strNull)
Call SqlSetParameterAll(hSql,DBP_SYBAUTOCOMMIT,
FALSE,strNull,TRUE)

Calling either of these functions overrides the value of the sybautocommit


keyword in the SQL.INI file.
Example

This statement enables autocommit.


sybautocommit=on

sybmaxmessages
Use this keyword to instruct SQLRouter/Sybase how to save routine messages sent
from the server.
Section

[sybgtwy]

Default

0,0

Syntax

sybmaxmessages=max_messages,max_length

Description

max_messages specifies the maximum number of messages to be saved.


max_length specifies the maximum length of a saved message; this parameter is
optional. Any message text beyond the specified limit is truncated. If you do not
specify max_length, the default of 1024 bytes (full message length) is assumed.
Note: Message length is always preserved in favor of message count.

Example

The following example saves a maximum of 30 messages, and limits each message to
100 bytes. These settings limit the amount of memory used to store messages to 3660
bytes.
sybmaxmessages=30,100
The following example saves a maximum of 300 messages with full message length
(1024 bytes). These settings limit the amount of memory used to store messages to
313,800 bytes. Since the message buffer is limited to much less (64,000 bytes), the
actual number of messages saved may be considerably less than 300the number
saved will depend on the size of the messages.

6-24 Connecting Centura Objects to Databases

SQL.INI keywords

sybmaxmessages=300
The following example saves a maximum of 30 messages and discards all message
textonly the message number and severity level are saved. These settings limit the
amount of memory used to store messages to a mere 660 bytes.
sybmaxmessages=30,0

sybtracefile
Use this keyword to invoke the Client-Library trace facility for debugging.
Section

[sybgtwy]

Syntax

sybtracefile=c:\sybase\sybase.log

Description

The trace file can produce information useful to Sybase Technical Support when a
problem occurs in a Sybase software component. The trace file is automatically
configured to dump all available debugging information.
The trace file can quickly grow quite large. It also requires that the debugging version
of Client-Library be installed. If the debugging version is not found during the first
LOGIN attempt, SQLRouter/Sybase generates a dialog box reporting the error and
continues with tracing disabled.

Notes

If you do not want to do any tracing, leave this keyword out of the SQL.INI file or
comment out any lines that have this keyworddo not have a line that looks like this:
sybtracefile=

sybworkstationname
Use this keyword to define the machine name by which clients identify themselves.
Section

[sybgtwy]

Default

workstation_name

Syntax

sybworkstationname=hostname

Description

hostname is stored in the connection entry of the dbo.sysprocesses of the master


database. You can display it within certain system stored procedures (for example,
sp_who) whenever you have a live connection to the server.
If you do not specify a value for this keyword, the literal value used is
workstation_name.

Example

This statement defines the client machine name as MYHOST:


sybworkstationname=MYHOST

Connecting Centura Objects to Databases

6-25

Chapter

Connecting to Sybase

yieldonservercall
Use this keyword to enable and configure asynchronous processing for applications
that connect to a Sybase System 11.x server using SQLRouter/Sybase.
Section

[sybgtwy]

Default

Syntax

yieldonservercall=numeric_ value

Description

numeric_value must be an integer between 60 and 600 inclusive.


Asynchronous processing allows a Centura SQLWindows application to send
requests to the System 11.x server for processing and periodically poll for a response.
In between polls, the application can either do other work or yield to the operating
system (Microsoft Windows 95 or Windows NT) to allow other tasks to run. A
special function (the callback function) determines what the application does between
polls. Centura SQLWindows defines a default callback function for you; this function
yields to the operating system.
If you disable asynchronous processing, your Centura SQLWindows application does
not return control to the operating system between the time the application sends a
request to the server and the time it receives a reply.
To disable asynchronous processing, set yieldonservercall to zero (or
comment out the statement). To enable asynchronous processing, set
yieldonservercall to a non-zero value in the range from 60 to 600.
A non-zero value defines a polling interval for SQLRouter/Sybase. A positive value
defines a minimum polling interval measured in tenths of a second; a negative value
defines a maximum polling interval measured in seconds. After each polling request,
SQLRouter/Sybase invokes the callback function.
If you assign a positive value to yieldonservercall, you are specifying the
minimum time interval between polling requests. Upon every return from the
callback function, SQLRouter/Sybase determines whether the minimum time interval
has passed. If so, SQLRouter/Sybase polls for a response from the server; if not,
SQLRouter/Sybase returns immediately to the callback function.
If you assign a negative number to yieldonservercall, you are setting the
maximum polling interval to the absolute value of this number; it is SQLRouter /
Sybase that determines the actual polling frequency for you. SQLRouter/Sybase polls
very often initially (about twice a second), but the polling interval quickly increases
over time, up to the maximum value you set. This algorithm assumes that, over time,
a response time of perhaps even several seconds becomes far less significant relative
to the total time required to fulfill the request. Reducing unnecessary polling

6-26 Connecting Centura Objects to Databases

Stored procedures

improves the responsiveness of the environment and reduces network traffic


generally.
Under most circumstances, a setting of +10 (1 call/second) or 5 (dynamic polling
interval with a maximum of 5 seconds) permits reasonable response time and smooth
control of the operating environment. You should use these values if you assume that
any task which gains control during the callback function returns control to
SQLRouter/Sybase in a timely manner, and that the callback function yields to the
operating system. (Like any other application, SQLRouter/Sybase must wait for
return of control from the callback function before it can poll the database server
again.)

Stored procedures
You can call stored procedures, execute them on System 11.x, and retrieve results sets
and return status from them by using the following SAL functions in your Centura
SQLWindows application. These functions are:

SybExecuteProc on page 6-29

SybExecuteProcEx on page 6-30

SybGetNextResults on page 6-31

SybGetReturnStatus on page 6-32

SybPrepareNextResults on page 6-34

SybPrepareProc on page 6-33

You can also execute stored procedures using, for example, SqlPrepare and
SqlExecute. However, you should do this only for stored procedures that do not return
result setswhen you execute a stored procedure by calling SqlPrepare and
SqlExecute, SqlPrepareAndExecute, and so on, any result sets that the stored
procedure might return are discarded.
Stored procedures can perform all the usual SQL operations, including positioned
updates.
For some general information on stored procedures, read Stored procedures on page
1-21.

Using cursors with stored procedures


SQLRouter/Sybase automatically implements Client Library cursors for all SELECT
statements. You can declare your own cursors for stored procedures as follows:
Call SybPrepareProc(hSql,
sp_one_select with cursor,:dfOut1)

Connecting Centura Objects to Databases

6-27

Chapter

Connecting to Sybase

The WITH CURSOR clause is an extension to the SQL language understood by


SQLRouter/Sybase. By using WITH CURSOR, you instruct SQLRouter/Sybase to
declare a cursor for the stored procedure. You can declare a cursor only for stored
procedures that have exactly one SQL statementa SELECT statement. If a stored
procedure has more than one SELECT statement, or SQL statements that are not
SELECT statements, your attempt to declare a cursor fails.
If you attempt to execute an SQL statement on any other SQL handle while rows or
additional result sets remain unfetched from a stored procedure, you get the following
Client-Library error:
30041: "This routine cannot be called because another
command structure has results pending."
You must either fetch all remaining result sets from the stored procedure or cancel
them. If CCP is off, you can cancel an active result set (and all pending result sets for
all SQL handles on the same connection) by preparing a new statement on the same
SQL handle. The following example illustrates a technique that uses a dummy
command to cause the cancel.
Call SqlPrepare(hSql,
SELECT * FROM dbo.sysobjects WHERE 1 = 2)
If CCP is off, you can use the CANCEL statement (instead of preparing a new
command) to cancel the active result set and all pending result sets for all SQL
handles on the same connection immediately. This statement is an extension to the
SQL language understood by SQLRouter/Sybase. Using the CANCEL statement is
the most efficient way of canceling all pending result sets.
Call SqlPrepareAndExecute(hSql,cancel)
If CCP is off, and you call SqlCommit (or execute the COMMIT statement), you
implicitly cancel pending result sets on all SQL handles on the same connection, not
just the handle specified as an argument to the function. For example, the call below
does not cancel pending result sets just for hSqlA, but for all other open SQL
handles on the connection (assuming CCP is off).
Call SqlCommit(hSqlA)
Like COMMIT, a ROLLBACK implicitly cancels all pending result sets on all SQL
handles (provided CCP is off). For example, the call below does not cancel pending
result sets just for hSqlA, but for all other open SQL handles on the connection.
Call SqlPrepareAndExecute(hSqlA,rollback)
Closing the connection also cancels all pending result sets.

6-28 Connecting Centura Objects to Databases

Stored procedures

Important: If CCP is on, preparing a new statement on a given SQL handle, or executing a
CANCEL, COMMIT, or ROLLBACK cancels just the result set associated with the SQL handle
you specify, not all the result sets for all of the SQL handles on the same connection.

SybExecuteProc
Use this function to execute a stored procedure or a sequence of SQL statements.
Syntax

bOk=SybExecuteProc(hSql, strStatements, strIntoList)


Sql Handle: hSql
String: strStatements
String: strIntoList

Parameters

hSqlA handle that identifies a connection context to the database.


strStatementsThe stored procedure or SQL statements to be executed.
strIntoListThe list of INTO variables into which the stored procedures result set
values (if any) are returned.

Description

SybExecuteProc executes the stored procedure or sequence of SQL statements


specified in strStatements. It stops at the first SELECT statement (if any) and returns
the result set from that statementcall SqlFetchNext repeatedly to retrieve the rows
in the result set. If the stored procedure returns additional result sets, call
SybGetNextResults once for each additional result set.
Separate the variables listed in strIntoList with commas and precede each variable
name with a colon. If the stored procedure returns zero rows, the variables in
strIntoList keep whatever values they had before the call to SybExecuteProc. If you
know the stored procedure does not execute any SELECT statements (that is, it does
not return any result sets), specify the value strNull for strIntoList.
If the stored procedure accepts input parameters, you can specify literals, constants,
or bind variables (of any type except LONG STRING) as input arguments.
Note: Even though you cannot specify a LONG STRING bind variable as an input parameter
to a stored procedure, there is one exception: you can specify a bind variable assigned a string
of exactly 255 bytes.
If the stored procedure returns values in output parameters, you must supply output
arguments in order to call the procedure. However, you cannot retrieve the values of
the output arguments SQLRouter/Sybase does not support returning the values of
output parameters from a stored procedure to your Centura SQLWindows application.

Connecting Centura Objects to Databases

6-29

Chapter

Connecting to Sybase

Note: You can work around this restrictionread Retrieving output parameter values on
page 6-35.
Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Examples

This function is demonstrated in the sample application SQLSYBS3.APP.

SybExecuteProcEx
Use this function to execute a stored procedure or a sequence of SQL statements
when you do not know if the stored procedure returns any result sets.
Syntax

bOk=SybExecuteProcEx(hSql, strStatements, strIntoList, bRows)


Sql Handle: hSql
String: strStatements
String: strIntoList
Receive Boolean: bRows

Parameters

hSqlA handle that identifies a connection context to the database.


strStatementsThe stored procedure or SQL statements to be executed.
strIntoListThe list of INTO variables into which the stored procedures result set
values (if any) are returned.
bRowsFlag that indicates whether the stored procedure is able to return rows (but
not whether any rows are actually returned).

Description

When SybExecuteProcEx is called, it causes all statements in the stored procedure up


through the first SELECT statement to be executed, then returns the result set from
that SELECT statement. Call SqlFetchNext repeatedly to fetch the rows in the result
set, then call SybGetNextResults to execute the next statements in the stored
procedure up through the next SELECT statement.
Separate the variables listed in strIntoList with commas and precede each variable
name with a colon. If the stored procedure returns zero rows, the variables in
strIntoList keep whatever values they had before the call to SybExecuteProcEx.
The parameter bRows is set to TRUE if the stored procedure executes at least one
SELECT statement (even if the statement returns zero rows). If the stored procedure
does not execute a SELECT statement, bRows is set to FALSE.
If the stored procedure accepts input parameters, you can specify literals, constants,
or bind variables (of any type except LONG STRING) as input arguments.

6-30 Connecting Centura Objects to Databases

Stored procedures

Note: Even though you cannot specify a LONG STRING bind variable as an input parameter
to a stored procedure, there is one exception: you can specify a bind variable assigned a string
of exactly 255 bytes.
If the stored procedure returns values in output parameters, you must supply output
arguments in order to call the procedure. However, you cannot retrieve the values of
the output arguments SQLRouter/Sybase does not support returning the values of
output parameters from a stored procedure to your Centura SQLWindows application.
Note: You can work around this restrictionread Retrieving output parameter values on
page 6-35.
Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Example

This example stores a procedure on System 11.x.x, then executes that stored
procedure while checking if the procedure returns result sets.
Call SybExecuteProc(hSql,
create procedure authorproc @switch int as
if @switch = 1
select au_lname from authors
else
update authors set au_lname = \dummy\
where au_lname = \cognoscente\,)
Call SybExecuteProcEx(hSql,exec authorproc 1,:df1,bRows)
If bRows
Call SqlFetchNext(hSql,nFetchInd)
Call SybExecuteProcEx(hSql,exec authorproc 2,:df1,bRows)
If bRows
Call SqlFetchNext(hSql,nFetchInd)
Else
Call SalMessageBox(Row updated.,Procedure Results,MB_Ok)

SybGetNextResults
Use this function to get the next result set from a stored procedure.
Syntax

bOk=SybGetNextResults(hSql, strIntoList)
Sql Handle: hSql
String: strIntoList

Parameters

hSqlA handle that identifies a connection context to the database.

Connecting Centura Objects to Databases

6-31

Chapter

Connecting to Sybase

strIntoListThe list of INTO variables into which the stored procedures result set
values (if any) are returned.
Description

Results of stored procedures are returned in one or more sets with zero or more rows
in each set. SybExecuteProc returns the first result set. Use SybGetNextResult to
retrieve subsequent sets. Each set of data is returned in the variables specified by
strIntoList.
Separate the variables listed in strIntoList with commas and precede each variable
name with a colon. If the stored procedure returns zero rows, the variables in
strIntoList keep whatever values they had before the call to SybGetNextResults.

Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Notes

Once you have retrieved the next result set, call SqlFetchNext repeatedly to fetch
each row of data in the result set.

Example

This function is demonstrated in the sample application SQLSYBS1.APP.

SybGetReturnStatus
Use this function to get the return status from a stored procedure.
Syntax

bOk=SybGetReturnStatus(hSql, nRetVal)
Sql Handle: hSql
Number: nRetVal

Parameters

hSqlA handle that identifies a connection context to the database.


nRetValThe return value from a stored procedure.

Description

This function assigns the return status of a stored procedure to nRetVal. You can get
the return status (as defined by System 11.x) only after you have fetched the last row
of the last result set returned by the stored procedure.
If you prepare and execute another statement on the same handle (hSql) before calling
SybGetReturnStatus, you can no longer obtain the return status for the stored
procedure. However, you can perform operations on a different SQL handle
(including calling SybGetReturnStatus with a different handle to get the return status
of a different stored procedure) and still come back and get the return status of the
stored procedure associated with hSql.

Return Value

bOk is set to TRUE if the return status was available and to FALSE if it was not
available. If bOk is FALSE, the value of nRetVal is undefined.

Example

This function is demonstrated in the sample application SQLSYBS1.APP.

6-32 Connecting Centura Objects to Databases

Stored procedures

SybPrepareProc
Use this function to prepare a stored procedure for execution.
Syntax

bOk=SybPrepareProc(hSql, strStatements, strIntoList)


Sql Handle: hSql
String: strStatements
String: strIntoList

Parameters

hSqlA handle that identifies a connection context to the database.


strStatementsThe statements to be prepared by the database.
strIntoListThe list of INTO variables into which the stored procedures result set
values (if any) are returned.

Description

Call this function to prepare the statements in strStatements that create or invoke a
stored procedure.
If the stored procedure accepts input parameters, you can specify literals, constants,
or bind variables (of any type except LONG STRING) as input arguments.
Note: Even though you cannot specify a LONG STRING bind variable as an input parameter
to a stored procedure, there is one exception: you can specify a bind variable assigned a string
of exactly 255 bytes.
If the stored procedure returns values in output parameters, you must supply output
arguments in order to call the procedure. However, you cannot retrieve the values of
the output arguments SQLRouter/Sybase does not support returning the values of
output parameters from a stored procedure to your Centura SQLWindows application.
Note: You can work around this restrictionread Retrieving output parameter values on
page 6-35.
The INTO variables in strIntoList can be of any data type. Separate the variables
listed in strIntoList with commas and precede each variable name with a colon. If the
stored procedure returns zero rows, the variables in strIntoList keep whatever values
they had before the call to SybPrepareProc. If you know the stored procedure does
not execute any SELECT statements, specify the value strNull for strIntoList.
To actually create or invoke the stored procedure, you need to execute the prepared
statements. You can do this explicitly (by calling SqlExecute), or implicitly (for
example, by calling SalTblPopulate).

Connecting Centura Objects to Databases

6-33

Chapter

Connecting to Sybase

You cannot mix calls to SybPrepareProc with SybGetNextResult, nor


SybExecuteProc or SybExecuteProcEx with SybPrepareNextResults, in the same
execution cycle of a stored procedure. All other functions (for example,
SybGetReturnStatus, SybGetError, and so on) work with either set of functions.
As with SybExecuteProc and SybExecuteProcEx, you are not limited to specifying in
strStatements statements that create or invoke a stored procedure; you can specify
any valid SQL statements in strStatements.
Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Notes

If you do not expect the stored procedure to return result sets, call SqlPrepare instead
of SybPrepareProc.

Example

This function is demonstrated in the sample application SQLSYBS3.APP.

SybPrepareNextResults
Prepare the next SELECT statement in a stored procedure.
Syntax

bOk=SybPrepareNextResults(hSql, strIntoList, bEndOfResults)


Sql Handle: hSql
String: strIntoList
Boolean: bEndOfResults

Parameters

hSqlA handle that identifies a connection context to the database.


strIntoListThe list of INTO variables into which the stored procedures result set
values (if any) are returned.
bEndOfResultsFlag that indicates if there are no more result sets.

Description

This function prepares the next SELECT statement in the stored procedure; you must
then call SqlExecute with the same SQL handle you specified in
SybPrepareNextResults to actually retrieve the result set. All INTO variable data
types are supported.
Separate the variables listed in strIntoList with commas and precede each variable
name with a colon. If the stored procedure returns zero rows, the variables in
strIntoList keep whatever values they had before the call to SybPrepareNextResults.

Return Value

bOK is to TRUE if the function succeeds and to FALSE if it fails.

Example

This function is demonstrated in the sample application SQLSYBS3.APP.

6-34 Connecting Centura Objects to Databases

Stored procedures

Retrieving output parameter values


Normally, when you execute a stored procedure that returns values in output
parameters by calling SybPrepareProc followed by SqlExecute, you cannot retrieve
those output values, even though you specify bind variables as output parameters
when you call the stored procedure. The only way a Centura SQLWindows
application can retrieve data from a stored procedure is in the result sets (if any) that
the stored procedure returns.
You can work around this restriction by executing the stored procedure inside a batch
of statements. The batch of statements retrieves the output parameter from the stored
procedure as a result set, then returns that result set to your Centura
SQLWindows application. For example:
Call SybPrepareProc(hSql,
declare @outparm int ||
exec GTIPROC_BASICS ||
@test = 1 ||
@result = @outparm output ||
SELECT @outparm)
Here is a more complete example to illustrate calling a stored procedure and
retrieving an output parameter. In summary, for the stored procedure created below,
you call:

SybPrepareProc (as shown above).

SqlExecute to position to the first result set (the set of authors last names).

SqlFetchNext to retrieve the rows in the first result set.

SybPrepareNextResults, SqlExecute, and SqlFetchNext to get the result set


from the SELECT statement against table foo.

SybPrepareNextResults, SqlExecute, and SqlFetchNext to retrieve the value


of outparmthis is the last result set generated as part of the command batch
outside of the stored procedure.

Set strSqlCreate =CREATE PROC GTIPROC_BASICS ||


@test int, @result int output ||
AS SELECT au_lname FROM authors ||
SELECT c1 FROM foo where c1 = @test ||
SELECT @result = @test * 10 ||
RETURN -100 /* Success */

Connecting Centura Objects to Databases

6-35

Chapter

Connecting to Sybase

If TRUE
When SqlError
Return TRUE
Call SqlPrepareAndExecute(hSql,drop procedure GTIPROC_BASICS)
Call SqlPrepareAndExecute(hSql,strSqlCreate)
Set strSqlExecute = declare @outparm int ||
exec GTIPROC_BASICS ||
@test = :nTest ||
@result = @outparm output ||
SELECT @outparm
Set nTest = 2
Call SybPrepareProc(hSql,strSqlExecute, :dfAu_lname)
Call SqlExecute (hSql)
While NOT nFetchInd
Call SqlFetchNext(hSql,nFetchInd)
Call SybPrepareNextResults (hSql, :dfFoo, bMoreResults)
Call SqlExecute (hSql)
Set nFetchInd = FALSE
While NOT nFetchInd
Call SqlFetchNext(hSql,nFetchInd)
Call SybPrepareNextResults(hSql, :dfOutParm,bMoreResults)
Call SqlExecute (hSql)
Set nFetchInd = FALSE
While NOT nFetchInd
Call SqlFetchNext(hSql,nFetchInd)

Transactions, disconnects, and exits


If autocommit is off in your application, you are responsible for explicitly
committing or rolling back transactions. If autocommit is off, and you disconnect
from the database or exit the application (either normally or abnormally) without
committing or rolling back a pending transaction, the database rolls back the
transaction for you.

6-36 Connecting Centura Objects to Databases

Writing and retrieving IMAGE and TEXT data

Writing and retrieving IMAGE and TEXT data


This section tells you how to write and retrieve IMAGE and TEXT data to a Sybase
System 11.x database.

Writing data
To write IMAGE or TEXT data of up to 64K, you may use the INSERT or UPDATE
SQL statements, but you must then supply the data as a literal or a constant. You can
write IMAGE or TEXT data of any size using the function SybWriteText; assign the
data to a variable and pass that variable as an argument to SybWriteText.
Note: If you attempt to execute an INSERT or UPDATE statement using bind variables on an
IMAGE or TEXT column, the current transaction will be rolled back and you will be presented
with the error message returned by the database server. This is because Sybase does not support
dynamic parameters for TEXT and IMAGE data.

To retrieve IMAGE or TEXT data you do not intend to update


Define a normal SQL cursor to fetch the data.
(To scroll backwards and forwards in the result set, turn on result set mode.)

To retrieve IMAGE or TEXT data that you want to update


1.

Get a SQL handle (for example, hSql1).

2.

Turn off result set mode (specifying the handle hSql1). To preserve the cursor
context, turn on CCP before turning off result set mode.

3.

Execute a SELECTFOR LONG UPDATE statement, specifying hSql1. (The


FOR LONG UPDATE clause is an extension to SQL that Centura SQLWindows
uses for System 11.x only.)

4.

Position to the row you wish to update.

5.

Get another SQL handle (for example, hSql2).

6.

Call SybWriteText (using hSql2) to update the row.

To insert IMAGE or TEXT data


1.

1. Get a SQL handle (for example, hSql1).

2.

Insert a dummy value (such as a space) into the target column by preparing and
executing the SQL INSERT statement and specifying the handle hSql1.

3.

Commit the insert operation (if autocommit is off) specifying the handle hSql1.

Connecting Centura Objects to Databases

6-37

Chapter

Connecting to Sybase

4.

Turn off result set mode (specifying the handle hSql1). To preserve the cursor
context, turn on CCP before turning off result set mode.

5.

Execute a SELECTFOR LONG UPDATE statement, specifying hSql1. (The


FOR LONG UPDATE clause is an extension to SQL that Centura SQLWindows
uses for System 11.x only.)

6.

Position to the desired row.

7.

Get another SQL handle (for example, hSql2).

8.

Call SybWriteText (using hSql2) to update the row.

To delete IMAGE or TEXT data


1.

Turn on result set mode.

2.

Execute a SELECTFOR UPDATE statement.

3.

Position to the desired row.

4.

Execute the DELETE statement.

When calling SybWriteText, you can choose whether or not to log the update of the
IMAGE or TEXT column by setting the bLogging argument to this function
appropriatelyif bLogging is FALSE, the database server will not log the update.
Note that you must enable the sp_dboption option (select into/bulkcopy) on the
database server to perform operations without logging.

Retrieving data and buffer size


SQLRouter/Sybase can retrieve IMAGE or TEXT values of any length (given
enough memory on your client machine to store the value) provided the amount of
IMAGE or TEXT data does not exceed the buffer size you specified with the
longbuffer keyword in the SQL.INI filesee longbuffer on page 6-21.
SQLRouter/Sybase detects IMAGE and TEXT values during execution and allocates
its fetch buffer for the column according to the size specified for the longbuffer
keyword. If there is insufficient memory for this fetch buffer, you get the error:
Workspace limit exceeded.

You need to specify a value for the longbuffer keyword that is big enough to hold
the largest value you expect to retrieve. If the amount of long data retrieved is too
large to fit into the buffer, SQLRouter/Sybase truncates the excess data longer
without warning. If you use the truncated binary value (for example, a truncated
bitmap) in your application, you will probably get a runtime error.
Client Library pads returned VARCHAR column values with trailing spaces up to the
length of the column. SQLRouter/Sybase strips trailing spaces for returned
VARCHAR values.
6-38 Connecting Centura Objects to Databases

Writing and retrieving IMAGE and TEXT data

Note: It is still possible to encounter trailing spaces for VARCHAR values if the row value
itself was INSERTed or UPDATEd with trailing spaces. SQLRouter/Sybase strips only those
spaces that lie beyond the actual stored length. Consequently, SalStrLength indicates the true
length of the data value stored in the database.

SybWriteText
Perform a positioned update of more than 31,997 bytes of IMAGE data or more than
64,000 bytes of TEXT data on a System 11.x database.
Syntax

bOk=SybWriteText(hSql,strCursorName,nColumnNum,nColumnName,
strUpdateValue,bTimeStamp,bLogging)
Sql Handle: hSql
String: strCursorName
Number: nColumnNum
String: strColumnName
String: strUpdateValue
Boolean: bTimeStamp
Boolean: bLogging

Parameters

hSqlA handle that identifies a connection context to the database.


strCursorNameName of the cursor associated with the SQL handle on which you
executed the SELECT statement that retrieved the row to be updated.
nColumnNumOrdinal position in the SELECT statement of the column to be
updated.
strColumnNameFully qualified name of the column to be updated.
strUpdateValueValue to be written to the column.
bTimeStampFlag that indicates whether or not this function should avoid updating
the column if it has been updated since you executed.
bLoggingFlag that indicates whether or not the transaction gets logged.

Description

This function performs a positioned update on IMAGE or TEXT data in the column
named in strColumnName. The name in strColumnName must be the fully qualified
name of a column in an actual table, not a view.
You first execute a SELECT...FOR LONG UPDATE statement to retrieve the rows
and columns of interest from the table. You then call SqlFetchNext to fetch rows, and
SybWriteText to update the column strColumnName in the current row.
Connecting Centura Objects to Databases

6-39

Chapter

Connecting to Sybase

You can SELECT and update any number of columns. The value in nColumnNum is
the ordinal position of the column listed in the SELECT...FOR LONG UPDATE
statement. You vary this number with each call to SybWriteText to update more than
one column in the current row before fetching the next row.
The SQL handle you pass as an argument to SybWriteText must be different from the
SQL handle used to execute the SELECT...FOR UPDATE statement.
This function assumes the column to be updated is either not NULL, or has been set
to NULL using the UPDATE statement (not the INSERT statement).
To set a TEXT or IMAGE column to NULL, execute an UPDATE statement; do not
call SybWriteText.
Notes

You must disable result set mode before call SybWriteText because this function does
a positioned update.

Return Value

bOk is set to TRUE if the function succeeds and to FALSE if it fails.

Example

This example illustrates the typical operations that are performed when calling this
function.
! Open both cursors.
Call SqlConnect(hSql1)
Call SqlConnect(hSql2)
! Result sets must be off for positioned udpates.
Call SqlSetResultSet(hSql1,FALSE)
! Assume a bmptbl table and a bitmap column.
Set strSQLstmt = SELECT bitmap FROM bmptbl FOR LONG UPDATE
Call SqlPrepare(hSql1,strSQLstmt)
Call SqlOpen(hSql1,CURSOR1)
Loop
If NOT SqlFetchNext(hSql1,nRetVal)
Break
! Assume strNewBitMap has the new data for updating.
Call SybWriteText(hSql2,CURSOR1,1,bmptbl.bitmap,
strNewBitMap,bTimeStamp,bLogging)

6-40 Connecting Centura Objects to Databases

Connecting Centura Objects to Databases

Chapter 7

Connecting to Ingres
This chapter describes how to connect Centura SQLWindows applications to CAOpenIngres databases. It describes (in alphabetical order) various features of Ingres
that can affect the way you write your Centura SQLWindows application or the way
it behaves when you connect to it with SQLRouter/Ingres.

Connecting Centura Objects to Databases

7-1

Chapter

Connecting to Ingres

Before you begin


Please read all of Chapter 1, Overview and Chapter 2, Initializing and Testing Your
Connection before reading this chapter.
You connect Centura SQLWindows applications to CA-OpenIngres databases using
the Centura native router, SQLRouter/Ingres. On the client side, we support Ingres
version 1.2 and 1.2.x, but not 2.0. On the server side, we support Ingres version 1.2
and up, including 2.0.

Autocommit
CA-OpenIngres databases support autocommit. Autocommit is off by default.
If autocommit is off, and you disconnect from the database or exit the application
(whether normally or abnormally) before committing or rolling back a pending
transaction, the work associated with the transaction is committed.
You cannot issue an autocommit statement in a multi-statement transaction. You
must explicitly commit or rollback the current transaction before changing the
autocommit value.
For more background information, read Autocommit on page 1-4.

Cursor context preservation


CA-OpenIngres does not support cursor context preservation (CCP). Trying to set it
results in an error.

Cursors
An Centura SQLWindows application that connects to CA-OpenIngres has no limit
on the number of cursors it can create and use. You can connect to more than one
database and have multiple cursors connected to each database.

Database events
You can retrieve information about CA-OpenIngres database events. The only
information returned is the name of the event that you assigned on the create
dbevent statement. For information about database events refer to the CAOpenIngres SQL Reference Guide.
To obtain the event name, use the Centura Build SqlGetParameterAll() function. The
following is an example for obtaining the name of an event and returning it in the
receiving variable strEventName:

7-2

Connecting Centura Objects to Databases

Data types

Call SqlGetParameterAll(hSql,SQLPMSTR,,strEventName,FALSE)

Data types
The table that follows shows the mapping between the data types supported by an
Centura SQLWindows application and the data types supported by an CAOpenIngres database server.
Centura
SQLWindows
Data Type
STRING

LONG STRING

CA-OpenIngres Data
Type

Range

CHAR
VARCHAR
C
TEXT

(254 or fewer characters)


(254 or fewer characters)
(254 or fewer characters)
(254 or fewer characters)

DATE

(-800 to 800 years for date intervals)


(-9611 to 9611 months for date intervals)
(-292,559 to 292,559 days for date intervals)
(00 to 23 hours for time intervals)
(00 to 59 minutes for time intervals)
(00 to 59 seconds for time intervals)

CHAR
VARCHAR
C
LONGVARCHAR*
TEXT

(255 to 2000 characters)


(255 to 2000 characters)
(255 to 2000 characters)
(255 to 2 gigabytes)
(255 to 2000 characters)
Note: Only one row at a time can be fetched from
longvarchar column.

NUMBER

DATE/TIME

INTEGER1
SMALLINT
INTEGER
FLOAT4
FLOAT
MONEY
DECIMAL

(-128 to 127)
(-32,768 to 32,767)
(-2,147,483,648 to 2,147,483,647)
(-1.0e+38 to 1.0e+38 with 7-digit precision)
(-1.0e+38 to 1.0e+38 with 16-digit precision)
($-999,999,999,999.99 to $999,999,999,999.99)
(maximum precision is 31 digits)

DATE

(1-jan 1582 to 31-dec-2382 for absolute dates)

* Currently, only one row at a time can be fetched from a LONGVARCHAR column.

Connecting Centura Objects to Databases

7-3

Chapter

Connecting to Ingres

Empty strings
On CA-OpenIngres, if you try to insert the empty string into a character string
column (or try to update such a column with the empty string), a space or NULL will
be stored. The following table summarizes what will be stored by SQL type:
Ingres

SQL Type

Using bind variable with


defined length <= 254

Using bind variable with


defined length > 254

CHAR

space

NULL

VARCHAR

NULL

NULL

space

NULL

TEXT

NULL

NULL

LONGVARCHAR

NULL

NULL

For background information, read the section Nulls, empty strings, and spaces on
page 1-14.

Isolation levels
CA-OpenIngres servers do not support isolation levels. You can use the SET
LOCKMODE statement to set different types and levels of locks. The CAOpenIngres default lock is Shared for read (select) and Exclusive for write (delete,
insert, or update) until the end of a transaction. For information about the
relationship between locks and isolation levels, see the CA-OpenIngres Database
Administrators Guide.
If you attempt to retrieve the isolation level using SqlGetParameterAll(), a Centura
SQLWindows value of RR (Repeatable Read) will always be returned.

Lock time-out
CA-OpenIngres supports lock time-outs. To specify wait forever, specify a timeout value of 0. The default is 0, that is no timeout.
For general information on lock time-outs, read Lock time-out on page 1-13.

Positioned updates
A Centura SQLWindows application can not do positioned updates against an CAOpenIngres database. CA-OpenIngres does not support declaring a cursor for a select

7-4

Connecting Centura Objects to Databases

Result set mode

statement using FOR UPDATE OF if an application uses dynamic (rather than static)
SQL. All Centura SQLWindows applications use dynamic SQL statements.

Result set mode


If you turn on result mode when your application is connected to CA-OpenIngres,
Centura SQLWindows uses front-end result sets--CA-OpenIngres does not support
(backend) scrollable cursors.
For background information, read Result set mode on page 1-16 and Front end result
sets on page 1-8.

SQL.INI keywords
This section describes the keywords you need or may want to use in the SQL.INI file
when you connect a Centura SQLWindows application to a CA-OpenIngres database.
For general information about SQL.INI, read Initializing Centura SQLWindows
applications on page 2-4.

buffrow
Use this keyword to control the buffering of data between your Centura
SQLWindows application and SQLRouter/Ingres.
Section

[inggtwy]

Default

Syntax

buffrow=number_of_rows

Description

This keyword controls the buffering of data between your Centura SQLWindows
application and SQLRouter/Ingres. By decreasing the buffrow value, response time
can be improved significantly. In contrast, larger values increase data throughput, but
lengthen the response time.
The values for buffrow can range from 0 through 32767. Assigning a value does not
guarantee that the current INMESSAGE is of sufficient size to fulfill the request. In
these cases, the number of buffered rows may be considerably less.
The default value of zero causes SQLRouter/Ingres to revert to buffering data based
on the number of rows which will fit within the current INMESSAGE buffer size.

Example

This statement instructs SQLRouter/Ingres to perform single row fetches into the
INMESSAGE buffer:
buffrow=1

Connecting Centura Objects to Databases

7-5

Chapter

Notes

Connecting to Ingres

The buffrow keyword has no effect on the manner in which data is buffered and
transported across the network by CA-OpenIngres Net.
You can also configure the buffering of data for individual SQL handles using the
SqlSetParameterAll function. Assuming nBuffrow has already been assigned the
value desired for SQL handle hSql, you can make the following call:
SqlSetParameterAll(hSql, DBP_BUFFROW, nBuffRow, FALSE, TRUE)

comdll
Identify the SQLRouters available between Centura SQLWindows (or a client
application created with Centura SQLWindows) and the database.
Section

[win32client.dll]

Syntax

comdll=communication_dll_name

Description

This keyword identifies the filename of a SQLRouter DLL. You can put more than
one comdll statement in the SQL.INI file. The value of communication_dll_name to
use for SQLRouter/Ingres is sqling32.

Notes

For related information, read Connect search order on page 1-6.

log
Use this keyword to define the database router activity log and enable logging.
Section

[win32client.ing32]

Syntax

log=fully_qualified_path_name

Description

Specify any valid file pathname after the keyword. If the file does not exist, it is
created. If the file already exists, it is overwritten (unless the /Fa option is specified
see below). Once the log statement has been added to the SQL.INI file, logging
is performed automatically.
You can specify one or more of the options listed below after the fully qualified
pathname to customize the output:

/Bxexclude bind variable values

/Faappend to existing file

/FDdisplay fetch data

/Lddisplay LONG data read or written

/Txexclude timestamps

/INGdisplay CA-OpenIngres level calls

Enter the options exactly as shown, keeping upper-case letters upper-case and lowercase letters lower-case.
7-6

Connecting Centura Objects to Databases

SQL.INI keywords

Example

This example calls for a log file that does not include timestamps on entries (to
conserve disk space), and displays the input and output of all LONG data (including
TEXT and IMAGE data items).
[win32client.ing32]
log=c:\centura\ingres.log /Tx /Ld

longbuffer
Use this keyword to specify the maximum number of bytes of long data type columns
to retrieve or send, and truncates excess bytes.
Section

[inggtwy]

Default

2000

Syntax

longbuffer=number_of_bytes

Description

Reduce the value of this keyword to conserve memory or reduce network traffic. If
you use longbuffer to limit the number of bytes to retrieve, the retrieved data is
truncated. To avoid truncating long data, set the value equal to the largest data type
size that your client applications need to read.
The longbuffer applies to all databases defined in the [inggtwy] section. You cannot
specify a longbuffer larger than the maximum size for the data type to be retrieved.
The maximum size for C, CHAR, TEXT, and VARCHAR data types is 2000. The
maximum size for longvarchar is 2 gigabytes.

Example

This statement sets 1000 as the maximum number of bytes of long data type data to
retrieve or send.
longbuffer=1000
You can set this environment variable in your Centura SQLWindows application
using SqlSetParameterAll with the DBP_LONGBUFFER parameter. (This parameter
is defined in the SQLNWKCN.APL file.)

remotedbname
Use this keyword to specify the names of the databases your Centura SQLWindows
applications connect to and their associated connect strings.
Section

[inggtwy]

Syntax

remotedbname=db_name,connect_string

Description

db_name specifies the database. The name may not be more than 8 characters long.

Connecting Centura Objects to Databases

7-7

Chapter

Connecting to Ingres

connect_string is similar to the database in CA-OpenIngres Terminal Monitor Tool. It


contains the virtual node, two colons, the database name, the server type, and flags
for the options you want.
The syntax for the connect string is:
virtual_node::dbname/server_type[, flags]
virtual_node -- the virtual node name of the remote node where the database is
located. The virtual node is defined with CA-OpenIngres Net Utility (NETU).
dbname -- the name of a database on the server defined by virtual_node.
server_type -- the type of server being accessed. The default is INGRES, if you
do not specify one.
flags -- the optional flags that control session behavior. Separate each option flag
with a space if you specify more than one. Refer to the CA-OpenIngres SQL
Reference documentation for detailed information about the flag options and the
parameters they control.
Example

This example shows a CA-OpenIngres database on node NODE1 and no option flags
(IIDBDB is the Ingres master database; all CA-OpenIngres servers have this
database).
remotedbname=IIDBDB,node1::iidbdb/ingres

This example shows a CA-OpenIngres database IIDBDB on node NODE1, and the
option to specify locking the database for exclusive use (-l) and not to wait if the
database is not available (-w).
remotedbname=IIDBDB,node1::iidbdb/ingres,-l -w

This example shows a CA-OpenIngres database IIDBDB on node NODE1 and the
option set to use the group identifier GRP1.
remotedbname=IIDBDB,node1::iidbdb/ingres,-Ggrp1

This example shows a CA-OpenIngres database IIDBDB on node NODE1 and the
option set to use role identifier RL1 with the password PWD1.
remotedbname=IIDBDB,node1::iidbdb/ingres,-Rrl1/pwd1

substitute
Use this keyword to specify that the string in the first parameter should replace the
string in the second parameter whenever the first parameter appears in an SQL
statement.
Section

[inggtwy]

Syntax

substitute=original_string , substitute_string

7-8

Connecting Centura Objects to Databases

Stored procedures

Description

You can have an unlimited number of substitute statements in the initialization file.
However, this statement changes all occurrences of the replace word in your SQL
statements: operators, WHERE clauses, object names, and literals (but not bind
variables).
Important: The strings can include imbedded blank spaces, but not commas--you must use a
comma to separate original_string from substitute_string.

Notes

Because each SQL statement is parsed, having substitute statements in your SQL.INI
file adds a small amount of overhead to the compilation of those statements. If you
are not running any Centura software that require substitution, you may want to
remove these statements from the file.
If you do not want to have substitutions done, leave this keyword out of the SQL.INI
file or comment out any lines that have this keyword--do not have a line that looks
like this:
substitute=

Example

The substitute statement below could be used with an application that (for example)
encloses table names in quotes. If you cannot modify the application, and if the
database you are connecting the application to does not accept double quotes, you can
have SQLRouter strip them off as follows:
substitute=

Stored procedures
CA-OpenIngres stored procedures consist of input parameters , a declare section for
local variables, a procedure body, and an optional return status. Input parameters must
be all variables or all constants, but not a mixture of both. Refer to the CAOpenIngres SQL Reference for information about stored procedure characteristics.
Within a procedure, select statements must assign their results to local variables.
Also, select statements can only return a single row of data. If more rows are returned,
no error is issued and only the first row retrieved is put into the results variable. The
return status is an integer variable that receives a value from the procedure. If it is not
specified in the procedure, the value defaults to 0. The return status is the only value
a procedure can return to the calling application.
When you execute a procedure, you cannot assign parameter values by positional
referencing; a name and assignment operator must accompany any parameter value.
Also, the name must match those in the procedures definition and the data types of
the values must be compatible with the parameter to which they have been assigned.

Connecting Centura Objects to Databases

7-9

Chapter

Connecting to Ingres

Creating stored procedures


You can use SqlImmediate() or SqlPrepare() and SqlExecute() to create stored
procedures if the body does not contain bind variables. If the create procedure
statement uses bind variables, use SqlStore() instead. The following examples show
the three ways for creating a CA-OpenIngres stored procedure:
Call SqlImmediate(create procedure p
as begin
insert into tab1 (col2) values(100);
end)
Or:
Call SqlPrepare(hSql, create procedure p
as begin
insert into tab1 (col2) values(100);
end)
Call SqlExecute(hSql)
Or:
Call SqlStore(hSql, , create procedure p (i integer)
as begin
insert into tab1 (col2) values(:i);
end)

Executing stored procedures


SQLRouter/Ingres returns the stored procedure status value only if you use
SqlRetrieve(). When you use SqlRetrieve(), you must store the parameter names in
the command string because CA-OpenIngres requires the parameter names to be in
the sqlname fields of the SQL Descriptor Area (SQLDA). For example:
Call SqlRetrieve(hSql, p(i), :invar, :outvar)
Call SqlExecute(hSql)
SqlFetchNext(hSql, nRetVal)

If you do not need to return a status, you can use:


Call SqlImmediate(execute procedure p(i=:invar))

Or:
Call SqlPrepare(hSql, execute procedure p(i=:invar))
Call SqlExecute(hSql)

7-10 Connecting Centura Objects to Databases

User prefix

Dropping stored procedures


You can drop stored procedures in three ways:
Call SqlImmediate(drop procedure p)

Or:
Call SqlPrepare(hSql, drop procedure p)
Call SqlExecute(hSql)

Or:
Call SqlDropStoredCmd(hSql, p)

More information on stored procedures


For general information about stored procedures, read Stored procedures on page 117.

User prefix
You can retrieve the user name of the user currently running CA-OpenIngres. To
obtain this user name, use the Centura Build SqlGetParameterAll() function. The
following is an example for obtaining the name of the current user and returning it in
the receiving variable strUserName:
Call SqlGetParameterAll(hSql,SQLPUPRE,,strUserName,FALSE)

Connecting Centura Objects to Databases

7-11

Connecting Centura Objects to Databases

Chapter 8

Connecting to Databases
using ODBC
This chapter describes how to connect Centura SQLWindows applications to
databases using ODBC. It also describes the mapping of error codes between Centura
SQLWindows and ODBC.

Connecting Centura Objects to Databases

8-1

Chapter

Connecting to Databases using ODBC

Before you begin


Please read all of Chapter 1, Overview and Chapter 2, Initializing and Testing Your
Connection before reading this chapter.
You connect Centura SQLWindows applications to ODBC data sources with the
Centura ODBC router, SQLRouter/ODBC. This router conforms to the ODBC 3.0
specification up to core levels 1 and 2 (i.e., to the ODBC 2.0 level within the 3.0
specification).

Connecting to specific data sources


A Centura SQLWindows application can access a variety of ODBC data sources,
including:

IBM DB2/400

Microsoft SQL Server version 6.x

Microsoft Access

ORACLE

Sybase

Note: If you will be connecting to a DB2/4700 data source, be sure to read the section
Connecting to Access on page 8-3. In all other cases, be sure to read the documentation that
comes with your ODBC driver.

Your Centura SQLWindows application communicates with SQLRouter/ODBC


(supplied with your Centura software); the router talks to the Microsoft ODBC Driver
Manager (supplied with Windows NT and Windows 95); the Driver Manager talks to
the ODBC driver (supplied by a third-party vendor); finally, the ODBC driver talks to
the target database.
ODBC drivers from various vendors are available that work with SQLRouter/ODBC
to allow you to connect your Centura SQLWindows applications to a given data
source using ODBC. You need to install and configure an ODBC driver that has been
written to work with the database you want to use. The ODBC driver should also
have been certified to work with Centura SQLWindows applications by the vendor
for that driver.
Important: In addition to reading Chapter 2, Initializing and Testing Your Connection,
you must read the documentation that comes with your ODBC driver to find out what you need
to know to connect to your target database using that driver. The driver documentation should
also describe any limitations or special features of that driver.

8-2

Connecting Centura Objects to Databases

Brand information

Connecting to Access
The Access ODBC driver that we certify does not support isolation levels.

Connecting to DB2/400
Your Centura SQLWindows applications connect to DB2/400 just as they would to
any other data source. However, you need to carefully check the documentation that
comes with the StarSQL ODBC driver from StarWare, Inc. to see what kind of
support and limitations come with their DB2/400 driver. Topics you should check
include autocommit, cursor context preservation, isolation levels, stored procedures,
and transaction processing.
When you update logical files, you must use journalling. Otherwise, you must update
using physical files.
In this chapter see also Cursor context preservation on page 8-4, Stored procedures
on page 8-14, and Transactions, disconnects, and exits on page 8-15.
For background information on these topics, read Autocommit on page 1-3, Cursor
context preservation on page 1-7, Isolation levels on page 1-12, Stored procedures on
page 1-21, and Transactions on page 1-22.

About the ODBC driver for SQLBase


Your Centura development system includes an ODBC driver for the SQLBase
database. With this driver you can protect your current investment in ODBC-enabled
applications (such as Microsoft Excel or ODBC-enabled Visual Basic applications)
you migrate your data as needed to SQLBase and continue to run those same
applications.
You can also use this same ODBC driver (in conjunction with Centuras SQLHost for
DB/2 product) to access data on IBMs DB2/MVS database from any ODBC-enabled
application.
Note: Your Centura SQLWindows applications can access a SQLBase database in much the
same way they access any other database. However, you cannot use the SQLBase ODBC driver
to access SQLBaseread the SQLBase documentation to learn how to connect a Centura
SQLWindows application to SQLBase.

Brand information
If your Centura SQLWindows application needs to identify the type of database
server it is connected to, you call SqlGetParameter(hSql, DBP_BRAND, nBrand,
strNull) to retrieve the brand into the parameter nBrand. However, if you are
connected to an ODBC data source (which is also the case when you connect to

Connecting Centura Objects to Databases

8-3

Chapter

Connecting to Databases using ODBC

Microsoft SQL Server 6.x), the value returned in nBrand is always 31 (which denotes
ODBC).
If your application gets the value 31 in nBrand, you need to make additional function
calls to get more specific information. You use these functions to find out the name of
the database and ODBC driver, as well as the version number of the ODBC driver.
These function calls are:

SqlGetParameterAll (hSql, DBP_DRIVER_NAME, nNum, strDriverName)

SqlGetParameterAll (hSql, DBP_DRIVER_VER, nNum, strDriverVersion)

SqlGetParameterAll (hSql, DBP_DBMS_NAME, nNum, strDBMSName)

To get the definitions of the constants DBP_DRIVER_NAME,


DBP_DRIVER_VER, and DBP_DBMS_NAME, include the file SQLNWKCN.APL
(located in your Centura installation directory) in your application by selecting
Libraries, File Include from the Centura SQLWindows menu bar.

Cursor context preservation


When a Centura SQLWindows application connects to an ODBC data source, the
default state of cursor context preservation (CCP)whether it is on or offis a
function of the database to which you connect.
If you attempt to turn CCP on or off in your application, SQLRouter/ODBC passes
this request on to the ODBC driver. For this request to be honored, both the ODBC
driver and the data source must support the setting of CCP at runtime. Read the
documentation supplied with your ODBC driver and your database for more
information.
Important: When connecting to a DB2/400 data source using the StarSQL ODBC driver
from StarWare, your application cannot change the setting for CCP. Since CCP is off by default
in Centura SQLWindows, this means that CCP is always off when you connect to DB2/400
using StarSQL.

If CCP is on, you can continue executing SQL statements you have already prepared
even after you commit the operations you have executed. If CCP is off and you
execute a COMMIT, you must re-prepare those SQL statements if you want to reexecute them. Whether CCP is on or off, you must also re-prepare them if you
execute a ROLLBACK.
For more background information on CCP, read the section Cursor context
preservation on page 1-7.

8-4

Connecting Centura Objects to Databases

Data types

Data types
SQLRouter/ODBC maps between the four data types supported in Centura
SQLWindows applications and the SQL data types defined by the ODBC
specification. The mapping supports all ODBC SQL data types (minimum, core, and
extended) except SQL_BINARY and SQL_VARBINARY.
Date Type Mapping between Centura SQLWindows and ODBC
Centura SQLWindows

ODBC

STRING

SQL_CHAR
SQL_VARCHAR
SQL_TIMESTAMP

LONG STRING

SQL_LONGVARCHAR
SQL_LONGVARBINARY

NUMBER

SQL_DECIMAL
SQL_NUMERIC
SQL_SMALLINT
SQL_INTEGER
SQL_REAL
SQL_FLOAT
SQL_DOUBLE
SQL_BIT
SQL_TINYINT
SQL_BIGINT

DATE/TIME

SQL_DATE
SQL_TIME

Important: To learn which data types are supported by the data source you are connecting to
using your ODBC driver, read the documentation that comes with the ODBC driver.

Error processing
Centura SQLWindows has three standard functions to process errors.

SqlGetErrorreturns an error message.


If the error number is less than 20,000, the file ERROR.SQL is searched for
the error text and that text (if found) is returned; otherwise, the translated
error number and database error message from the database server are
returned

SqlErrorTextsearches only ERROR.SQL for error text reason and remedy.

Connecting Centura Objects to Databases

8-5

Chapter

Connecting to Databases using ODBC

If there is a reason and remedy for the given error number in ERROR.SQL,
the reason and remedy are returned; otherwise, the string message not
found is returned.

SqlGetErrorTextreturns an error message.


If the text for the given error number is found in ERROR.SQL, that text
is returned; otherwise, the database error message is returned.

When an error message is displayed, it has the format:


<native_error>[<vendor>][ODBC_component][data_source]<error_text>
For example:
Microsoft SQL Server:208[Microsoft][ODBC SQL Server Driver][SQL
Server] Invalid object name tyu.

The syntactical components of this example are:


native error
vendor
ODBC component
data source
error text

Microsoft SQL Server:208


Microsoft
ODBC SQL Server Driver
SQL Server
Invalid object name tyu.

Error code mapping


This section lists the mapping between ODBC alphanumeric error codes and Centura
SQLWindows decimal error numbers. The ODBC entries are listed in increasing
lexicographic order (digits preceding letters of the alphabet).

8-6

ODBC Error Code

Centura SQLWindows Error Number

01000

20087

01002

20010

01004

20011

01006

20012

01S00

20013

01S01

20090

01S02

20091

01S03

20092

Connecting Centura Objects to Databases

Error code mapping

ODBC Error Code

Centura SQLWindows Error Number

01S04

20093

07001

20014

07006

20015

08001

20016

08002

20017

08003

20018

08004

20019

08007

20020

08S01

20021

21S01

20022

21S02

20023

22001

20024

22003

20025

22005

20026

22008

20027

22012

20028

22026

20029

23000

20030

24000

20031

25000

20032

28000

20033

34000

20034

37000

20035

3C000

20036

Connecting Centura Objects to Databases

8-7

Chapter

8-8

Connecting to Databases using ODBC

ODBC Error Code

Centura SQLWindows Error Number

40001

20037

42000

20038

70100

20039

IM001

20040

IM002

20041

IM003

20042

IM004

20043

IM005

20044

IM006

20045

IM007

20046

IM008

20047

IM009

20048

IM010

20103

IM011

20104

IM012

20105

IM013

20106

S0001

20049

S0002

20050

S0011

20051

S0012

20052

S0021

20053

S0022

20054

S0023

20107

S1000

20055

Connecting Centura Objects to Databases

Error code mapping

ODBC Error Code

Centura SQLWindows Error Number

S1001

20056

S1002

20057

S1003

20058

S1004

20059

S1008

20060

S1009

20061

S1010

20062

S1011

20108

S1012

20063

S1015

20064

S1090

20065

S1091

20066

S1092

20067

S1093

20068

S1094

20069

S1095

20070

S1096

20071

S1097

20072

S1098

20073

S1099

20074

S1100

20075

S1101

20076

S1102

20077

S1103

20078

Connecting Centura Objects to Databases

8-9

Chapter

Connecting to Databases using ODBC

ODBC Error Code

Centura SQLWindows Error Number

S1104

20111

S1105

20112

S1106

20079

S1107

20080

S1108

20081

S1109

20082

S1110

20083

S1111

20113

S1C00

20084

S1DE0

20085

S1T00

20086

Lock time-out
You can establish a lock time-out in your Centura SQLWindows application when
connecting to a database using ODBC, provided that both the ODBC driver you are
using and the database you are connecting to support setting a lock time-out from a
client application. Read the vendor documentation for your driver and your database
for more information.

SQL.INI keywords
This section contains the keywords you need or may want to use in the SQL.INI file
when connecting a Centura SQLWindows application to a database using ODBC.
For more information about the SQL.INI file, read Initializing Centura SQLWindows
applications on page 2-4.

buffrow
Use this keyword to control the buffering of data between your Centura
SQLWindows application and SQLRouter/ODBC.
Section

[odbcrtr]

Default

8-10 Connecting Centura Objects to Databases

SQL.INI keywords

Syntax

buffrow=number_of_rows

Description

This keyword controls the buffering of data between your Centura SQLWindows
application and SQLRouter/ODBC. By decreasing the buffrow value, response
time can be improved significantly. In contrast, larger values increase data
throughput, but lengthen the response time.
The values for buffrow can range from 0 through 32767. Assigning a value does not
guarantee that the current INMESSAGE is of sufficient size to fulfill the request. In
these cases, the number of buffered rows may be considerably less.
The default value of zero causes SQLRouter/ODBC to revert to buffering data based
on the number of rows which will fit within the current INMESSAGE buffer size.

Example

This statement instructs SQLRouter/ODBC to perform single row fetches into the
INMESSAGE buffer:
buffrow=1

Notes

The buffrow keyword has no effect on the manner in which data is buffered and
transported across the network.
You can also configure the buffering of data for individual SQL handles using the
SqlSetParameterAll function. Assuming nBuffrow has already been assigned the
value desired for SQL handle hSql, you can make the following call:
SqlSetParameterAll(hSql,DBP_BUFFROW,nBuffRow,FALSE,TRUE)

comdll
Identify the SQLRouters available between Centura SQLWindows (or a client
application created with Centura SQLWindows) and the database.
Section

[win32client.dll]

Syntax

comdll=communication_dll_name

Description

This keyword identifies the filename of a SQLRouter DLL. You can put more than
one comdll statement in the SQL.INI file. The value of communication_dll_name
to use for SQLRouter/ODBC is sqlodb32.

Notes

For related information, read Connect search order on page 1-6.

Example

comdll=sqlodb32

log
Define the database router activity log and enable logging.
Section

[win32client.odb32]

Connecting Centura Objects to Databases

8-11

Chapter

Connecting to Databases using ODBC

Syntax

log=fully_qualified_path_name

Description

Specify any valid file pathname after the keyword. If the file does not exist, it is
created. If the file already exists, it is overwritten (unless the /Fa option is specified
see below). Once the log statement has been added to the SQL.INI file, logging
is performed automatically.
You can specify one or more of the options listed below after the fully qualified
pathname to customize the output:

/Bxexclude bind variable values

/Faappend to existing file

/FDdisplay fetch data

/Lddisplay LONG data read or written

/Txexclude timestamps

Enter the options exactly as shown, keeping upper-case letters upper-case and lowercase letters lower-case.
Example

This example calls for a log file that does not include timestamps on entries (to
conserve disk space), and displays the input and output of all LONG data (including
TEXT and IMAGE data items).
[win32client.odb32]
log=c:\gupta\odbc.log /Tx /Ld

longbuffer
Specify the maximum number of bytes of LONG column data to retrieve or send.
Sections

[odbcrtr]

Default

32 Kbytes

Syntax

longbuffer=number_of_bytes

Description

This keyword sets the size of the buffer that holds LONG data. Normally, the optimal
size that avoids data loss is the largest column of LONG data to be sent or retrieved
by the Centura SQLWindows application. A larger buffer uses more memory and
increases network traffic; a smaller buffer uses less memory and reduces network
traffic. However, if the buffer is too small to hold all of the data, the excess is
truncated.
If specified, the longbuffer statement applies to all databases connected to using
ODBC. It is recommended that you not specify a value for longbuffer larger than
the maximum LONG column size in any of the tables stored in any of those
databases.

8-12 Connecting Centura Objects to Databases

SQL.INI keywords

Example

This statement sets to 2000 the maximum number of bytes of LONG column data to
retrieve from or send to any database connected to using ODBC.
longbuffer=2000

Notes

You can also set this variable in a Centura SQLWindows program by calling
SqlSetParameterAll with the DBP_LONGBUFFER parameter (defined in
SQLNWKCN.APL). This allows you to tailor the size of the buffer to the application.

odbctrace
Trace all calls to the ODBC API.
Section

[odbcrtr]

Default

off

Syntax

odbctrace={on|off}

Description

The ODBC Driver Manager can trace all calls made to the ODBC API. The trace
information is saved in the log file whose pathname is given in the odbtracefile
statement.

Example

This statement enables ODBC API call tracing.


odbctrace=on

odbctracefile
Specify the pathname of the trace file for ODBC API calls.
Section

[odbcrtr]

Default

client_root_directory\sql.log

Syntax

odbctracefile=fully_qualified_filename

Description

This keyword specifies the pathname of the trace file for ODBC API calls. This
keyword has no effect unless the odbtrace keyword is set to onsee odbctrace
on page 8-13.

Example

This statement specifies that the trace file is called odbc.log, and that it is located
in the \logs directory on the clients c: drive.
odbctracefile=c:\logs\odbc.log

remotedbname
Use this keyword to specify database names and their associated connect strings.
Section

[odbcrtr]

Syntax

remotedbname=db_name,connect_string

Connecting Centura Objects to Databases

8-13

Chapter

Description

Connecting to Databases using ODBC

db_name specifies the database name; it cannot exceed eight characters.


connect_string is the exact connect string you will use to connect to the ODBC data
source. Typically, this entry begins with the string "DSN=" to specify the data source
name specified in the ODBC Administrator tool.
The value specified in connect_string can include embedded spaces. Do not put
comments on the same line with the "remotedbname" statement. Everything from
the comma following db_name to the end of line is interpreted as the connect string.

Examples:

Assume you have defined two data sources in ODBC Administrator. One is for
Microsoft SqlServer 7.0 (with a data source name of "MS SqlServer 7.0"), and the
other is for a Visual FoxPro database (with a data source name of "Visual FoxPro
DB"). The remotedbname statements look like:
remotedbname=SS70,DSN=MS SqlServer 7.0
remotedbname=VFP, DSN=Visual FoxPro DB

Your Centura application sets the variable "SqlDatabase" to either "SS70" (to
connect to the SqlServer data source) or to "VFP" (to connect to the FoxPro
database), set SqlUser and SqlPassword appropriately, and issue the SqlConnect()
call. SqlRouter/ODBC obtains all the necessary information from the configuration
maintained by the ODBC Administrator utiltity.
Additional note: The remotedbname parameter is not necessary for applications built using Centura
Team Developer. It is required if you want to use the SqlTalk utility to connect to
the ODBC data source.
When connecting to any ODBC data source where the data source name was
configured by the ODBC Administrator tool, your Centura application can bypass the
remotedbname parameter altogether, and set the variable SqlDatabase to the
actual ODBC data source name. Using the above example, if you issue the following
statements (assume SqlUser and SqlPassword are set):
Set SqlDatabase = "MS SqlServer 7.0"
Call SqlConnect (hSql)

then your Centura program will connect correctly to the Microsoft SqlServer 7.0 data
source without using the remotedbname parameter in SQL.INI.

Stored procedures
SQLRouter/ODBC supports calling stored procedures that accept input arguments
and return result sets. However, the router does not support obtaining values from a
stored procedure using output arguments.
Syntactically, you can legally call a stored procedure that has output parameters by
providing bind variables where the output arguments are required; however, the value
8-14 Connecting Centura Objects to Databases

Transactions, disconnects, and exits

of those variables will be undefined after you have called the stored procedure, so
they will be of no practical use to you.
Important: If your ODBC driver does not support returning values in result sets, such as the
StarSQL ODBC driver for DB2/400, you cannot get information from a stored procedure into
your Centura SQLWindows application. Read your ODBC driver documentation to find out
what kind of stored procedure support your driver provides, and what limitations or restrictions
it imposes.

For more information on stored procedures read Stored Procedures in chapter 6.

Transactions, disconnects, and exits


If autocommit is off, and your application either disconnects or exits (whether
normally or abnormally), SQLRouter/ODBC executes a ROLLBACK against the
pending transactionthis rolls back all pending Data Manipulation Language
statements (DML), such as CREATE, INSERT, and so on.
When it comes to Data Definition Language (DDL) statements, such as CREATE
TABLE, some databases commit them as soon as they are executed, regardless of
whether autocommit is on or off. For these databases, the DDL statements cannot be
rolled back along with the pending DML statements. Other databases treat DDL
statements just like DML statementsthey do not commit them until an explicit
COMMIT is executed. For these databases, the pending DDL statements are rolled
back just like the DML statements.
Note: In the case of DB2/400 and the StarSQL driver from StarWare, all the statements in the
pending transaction (both Data Definition Language and Data Manipulation Language
statements) are rolled back.

Connecting Centura Objects to Databases

8-15

Connecting Centura Objects to Databases

Chapter 9

Connecting to Multiple
Databases Concurrently
This chapter describes some of the considerations you need to take into account when
writing Centura SQLWindows applications that access multiple databases
concurrently.

Connecting Centura Objects to Databases

9-1

Chapter

Connecting to Multiple Databases Concurrently

Overview
Centura SQLWindows is a 32-bit client/server application development environment
for Microsoft Windows NT and Windows 95. Using Centura SQLWindows and other
Centura components, teams of programmers can build large, enterprise-wide client/
server applications that connect to, retrieve data from, and manipulate data at
database servers from a variety of vendors.
This chapter describes a sample application that executes transactions against three
different database servers. It tells you how to set up and run the application, it
describes some of the major design issues, and it provides code excerpts to illustrate
how different parts of the application were implemented.
Important: Be sure to read Chapter 1, Overview, for general information about database
server and Centura SQLWindows features that affect how you write your applications.

Two approaches
When writing a multi-database Centura SQLWindows application, you have two
basic approaches to choose from.
One approach (the one used in the sample application) is to take the SAL language
and certain Centura SQLWindows features and create as much common code as
possible for accessing the different databases from different vendors. These features
include dynamic table windows and automatic column variables. The rest of the
application has code specific to the database server being accessed. This approach is
easier to understand conceptually, gives a standard example of a multi-database
application, and results in more understandable code.
The other approach is more object-orienteduse Centura functional classes to handle
accessing heterogeneous databases and maximize the reuse of code. For information
on writing multi-database applications that create and use functional classes, read the
white paper Designing Multi-Database Applications with Centura Object Classes.
You can access this paper by going to the Centura Software home page at:
http://www.centurasoft.com

9-2

Connecting Centura Objects to Databases

About the application

About the application


The multi-database application MULTIDB.APP is a single Centura SQLWindows
application that a user runs to generate an invoice for a customer order. The
application connects to three different database servers to retrieve, insert, update, and
delete information from six interrelated tables.
The application is also supplied in text form in the file MULTIDB.APT.
The application includes code that:

Connects to each database.

Creates database tables.

Copies data from one database to another.

Controls the transaction environment.

Controls concurrency.

Retrieves data from multiple databases.

Manipulates data in multiple databases.

The tables are spread across SQLBase 6.1, Microsoft SQL Server 6.0, and Oracle7.
You use a local connection to connect to SQLBase, the Centura SQLRouter/Oracle to
connect (natively) to Oracle, and the Centura SQLRouter/Microsoft SQL Server to
connect (natively) to Microsoft SQL Server.

Schema and location of tables


The application uses the tables COMPANY, EMPLOYEE, INVOICE,
INVOICE_ITEM, PRODUCT, and PAYMENT (from the sample ISLAND database
supplied with SQLBase). The application has been written to let you make another
copy of the COMPANY table on SQLBase, and to copy the INVOICE,
INVOICE_ITEM, and PRODUCT tables from SQLBase to Oracle, and the
EMPLOYEE and PAYMENT tables from SQLBase to Microsoft SQL Server.
The following table summarizes the original location of the tables in the SQLBase
ISLAND database, and where the tables will reside (in bold) after you select the
Populate option. The tables must exist on the correct database server for the
application to run successfully. Also, the SQLBase tables propagated to Microsoft
SQL Server, Oracle, and SQLBase have their names prefixed with MDB_ to reduce
the possibility of a name conflict with existing tables.

Connecting Centura Objects to Databases

9-3

Chapter

Connecting to Multiple Databases Concurrently

Where the Tables are Located


SQLBase
MDB_COMPANY

Oracle
MDB_INVOICE
MDB_INVOICE_ITEM
MDB_PRODUCT

Microsoft SQL Server


MDB_EMPLOYEE
MDB_PAYMENT

Running the application


This section tells you how to run the multi-database application.

Preparing to run the application


Before you run the sample multi-database application, you must install the Centura
sample applications so that you include the sample ISLAND database on SQLBase.
You must then create a database on your Oracle server and on Microsoft SQL Server
to hold the tables that the sample application expects to find there. You also need to
define the database on Microsoft SQL Server as an ODBC data source by using the
ODBC Administrator. (Read the Microsoft Windows NT or Microsoft Windows 95
documentation for information about the ODBC Administrator.)
Important: Make sure your database administrator gives you the appropriate permissions to
create those tables.

Configuring the application


You must configure the application before connecting to any of the three databases
by modifying the SQL.INI file.
For SQLBase the installation program modifies the SQL.INI for you.
For Microsoft SQL Server modify the SQL.INI file in the section
[win32client.dll] by setting the comdll keyword to sqlodb32 and in the
section [odbcrtr] by setting the longbuffer keyword to 10000.
For Oracle modify the SQL.INI file in the section [win32client.dll] by setting
the comdll keyword to sqlora32, and in the section [oragtwy] by defining
the remotedbname keyword for your database with the correct connect string
information, setting the longbuffer keyword equal to 200000, and setting the
fetchrow keyword to 20.
For more information about configuring connections, you should read Chapter 2,
Initializing and Testing Your Connection; Chapter 4, Connecting to Microsoft SQL
Server; and Chapter 5, Connecting to Oracle.

9-4

Connecting Centura Objects to Databases

Running the application

The following is an example of the SQL.INI keywords you define to connect to


SQLBase, Microsoft SQL Server, and Oracle:
[dbntsrv]
dbdir=c:\centura
servername=server1,sqlapipe
dbname=island,sqlapipe
[dbntsrv.dll]
comdll=sqlapipe
[win32client]
clientname=client1
[win32client.dll]
comdll=sqlapipe
comdll=sqlodb32
comdll=sqlora32
[odbcrtr]
longbuffer=10000
[oragtwy]
REMOTEDBNAME=oratcp,@T:orasrvr.oracle.com:1
longbuffer=200000
fetchrow=20

Note: Refer to the sample SQL.INI file supplied with the multi-database application for help
in editing your own SQL.INI file.

Connecting to the servers


To connect to the database servers, run the sample application, then log in to each of
the servers.

Starting the sample application


1.

Start Centura SQLWindows.

2.

Select File, Open from the menu bar, then open the sample application
MULTIDB.APP. This file is located in the SAMPLES subdirectory of the Centura
installation directory.

3.

Select Project, Execute from the menu bar to execute the application.

Connecting Centura Objects to Databases

9-5

Chapter

Connecting to Multiple Databases Concurrently

Logging in to the database servers


Log in to each of three database servers (SQLBase, Microsoft SQL Server, and
Oracle) by selecting File, Connect from the menu bar. In the dialog box:
1.

Enter the name of the database you wish to connect to.

2.

Enter a valid user name.

3.

Enter a valid password.

4.

Choose the appropriate database server.

5.

Click Connect.

Note: The default value displayed for Password is ******, but the actual value of the password
is SYSADM.

Once you successfully connect to a server, the application removes the name of that
server from the server selection combo box. When you have connected to all three
servers (and you must connect to all three to run the application successfully), click
Exit.

Populating the tables


After successfully connecting to all three databases, you must populate the tables on
Oracle, Microsoft SQL Server, and SQLBase with data. (You need to do this the first
time you run the application, and any time the tables are dropped for any reason on
Oracle and Microsoft SQL Server). To populate the tables, select File, Populate
Data from the menu bar, then select either SQLBase, Oracle or Microsoft SQL
Server. The application copies the appropriate tables from the SQLBase ISLAND
database to the target database you selected; the application also creates the indexes
associated with those tables.

Deleting the tables


To delete the tables and indexes from SQLBase, Microsoft SQL Server or Oracle,
select File, Cleanup Data from the menu bar, then select either SQLBase, Oracle or
Microsoft SQL Server.

Displaying table data


To display data in a table window from the COMPANY table (SQLBase), the
EMPLOYEE table (Microsoft SQL Server), the INVOICE table (Oracle), or the
PRODUCT table (Oracle), select Table from the menu bar, then select the
appropriate table name.
The displayed form has the following push buttons:

9-6

Connecting Centura Objects to Databases

Running the application

RefreshRedisplays all the current data from the database for the selected
table window. Click this button to see any data that has been added to the
table or changed in the table.

NewPositions you to the next available empty row in the table window.
Click this button to enter data for a new row in the table.

InsertInserts new data into the database. (You first click New to enter the
new data, then you click Insert to put the data into the table.)

UpdateUpdates the database with the changed data you entered (You
select the row to update, you enter the changes in that row, then you click
Update).

DeleteDelete the selected row from the database. You first select the row
by clicking the row header (the leftmost box displayed in that row), then
clicking Delete.

Details Displays a details form. From this details form you can add, update,
or remove invoice items for the selected invoice. You can also update certain
columns in the PAYMENT table. (This button appears only on the INVOICE
table.)

Apply & Close Commits all pending changes to each database (assuming
autocommit is disabled) and returns to the main form.

Discard & ExitRolls back all pending changes to each database (assuming
autocommit is disabled) and returns to the main form.

Note: To display the bitmap picture for a given row in the PRODUCT table, click the row
header (the leftmost box) in that row.

About the details form


If you select a row in the INVOICE table and click the Details button, you see a
details form with three table windows showing the following information for the
selected invoice:

Invoice items

Payment record

PRODUCT table information

The form contains two radio buttons: Invoice Item and Payment. If you select
Invoice Item (the default), you see PRODUCT table information and the focus goes
to the invoice items table window. If you select Payment, you see no PRODUCT
table information and the focus goes to the payment record table window.

Connecting Centura Objects to Databases

9-7

Chapter

Connecting to Multiple Databases Concurrently

The details form has the following buttons:

RefreshRedisplays all the current data from the database for the table
window that has the focus. Click this button to see any data that has been
added to the table or changed in the table.

NewPositions you to the next available empty row in the table window that
has the focus. Click this button to enter data for a new row in the table. You
can click this button only if Invoice Item is selected.

InsertInserts new data into the database. (You first click New to enter the
new data, then you click Insert to put the data into the table.) You can click
this button only if Invoice Item is selected.

UpdateUpdates the database with the changed data you entered (You
select the row to update, you enter the changes in that row, then you click
Update).

DeleteDelete the selected row from the database. You first select the row
by clicking the row header (the leftmost box displayed in that row), then
clicking Delete.

Apply & Close Commits all pending changes to each database (assuming
autocommit is disabled) and returns to the form with the INVOICE table.

Discard & ExitRolls back all pending changes to each database (assuming
autocommit is disabled) and returns to the form containing the INVOICE
table.

Modifying autocommit and isolation level settings


To enable or disable autocommit or to modify the isolation levels, select File,
Options from the menu bar. The dialog box displayed shows the current autocommit
setting for each database server and the current isolation level setting for SQLBase
and Microsoft SQL Server.
To enable autocommit, check the checkbox. To disable autocommit, clear the
checkbox.
To set (or change) the isolation level, enter one of RO, RL, CS, or RR in the text
field. To find out what these isolation levels mean for Microsoft SQL Server, read the
Isolation levels on page 4-4. To find out what these isolation levels mean for
SQLBase, read the SQLBase documentation.
Note: You cannot set an isolation level with Oracle.

9-8

Connecting Centura Objects to Databases

Design issues

Disconnecting and exiting


To disconnect from all the database servers and exit the application, select File, Exit
from the menu bar.
Note: The sample application may not exit or close windows properly if you select Close from
the Windows system menuselect File, Exit from the menu bar instead.

Design issues
This section describes some of the design issues raised in the development of the
sample application.

Connecting to the databases


The application begins by logging in and connecting to SQLBase, Microsoft SQL
Server, and Oracle. You specify the name of a valid database, a user name, and
password. If you need a user name and password for these databases, contact your
database administrator. You should successfully connect to each of the databases
before you try doing anything else with the application.
The application defines a separate SQL handle variable for each database server. The
handle uniquely identifies a connection between the client application and a database.
A handle is specified for every SQL statement executed.
The following code excerpt shows the use of the login form and the combo box from
which the user selects the database to connect to. If the user succeeds in connecting to
the database, the application sets initial values for the isolation level (RR) and
disables autocommit.
Form Window: frmLogin
...
Message Actions
On SAM_Create
Call SalListAdd(cmbServer,COMBO_SQLSERVER)
Call SalListAdd(cmbServer,COMBO_ORACLE)
Call SalListAdd(cmbServer,COMBO_SQLBASE)
Call SalListSetSelect(cmbServer,2)
...
Pushbutton: pbConnect
...
Message Actions
On SAM_Click
Set SqlUser=dfUserName
Set SqlPassword=dfPassword

Connecting Centura Objects to Databases

9-9

Chapter

Connecting to Multiple Databases Concurrently

Set SqlDatabase=dfDatabase
Set nCmbIndex=SalListQuerySelection(cmbServer)
Set strServer=SalListQueryTextX(cmbServer,nCmbIndex)
If strServer=COMBO_SQLSERVER
Set bSQLServerConnect=SqlConnect(hMSSQLServer)
If bSQLServerConnect
Set strDBSQLServer=dfDatabase
Set nCmbEntries=SalListDelete(cmbServer,nCmbIndex)
Call SalListSetSelect(cmbServer,nCmbEntries - 1)
! Make isolation level Repeatable Read (RR)
Set strMSSQLSrvrIsoLvl='RR'
Call SqlSetIsolationLevel(hMSSQLServer,
strMSSQLSrvrIsoLvl)
! Disable autocommit
Set bMSSQLServerAC=FALSE
Call SqlSetParameter(hMSSQLServer,DBP_AUTOCOMMIT,
bMSSQLServerAC, '')
Else If strServer=COMBO_ORACLE
Set bOracleConnect=SqlConnect(hOracle)
If bOracleConnect
Set strDBOracle=dfDatabase
Set nCmbEntries=SalListDelete(cmbServer,nCmbIndex)
Call SalListSetSelect(cmbServer,nCmbEntries - 1)
! Oracle OCI does not allow setting an isolation
! level, so we dont in the case of Oracle.
! Disable autocommit
Set bOracleAC=FALSE
Call SqlSetParameter(hOracle,DBP_AUTOCOMMIT,
bOracleAC,)
Set dfDatabase=
Else If strServer=COMBO_SQLBASE
Set bSQLBaseConnect=SqlConnect(hSQLBase)
If bSQLBaseConnect
Set strDBSQLBase=dfDatabase
Set nCmbEntries=SalListDelete(cmbServer,nCmbIndex)
Call SalListSetSelect(cmbServer,nCmbEntries - 1)
! Make isolation level is Repeatable Read (RR)
Set strSQLBaseIsoLvl=RR
Call SqlSetIsolationLevel(hSQLBase,strSQLBaseIsoLvl)
! Disable autocommit
bSQLBaseAC=FALSE

9-10 Connecting Centura Objects to Databases

Design issues

Call SqlSetParameter(hSQLBase,DBP_AUTOCOMMIT,
bSQLBaseAC,)
Call SqlSetParameter(hSQLBasePop,DBP_AUTOCOMMIT,
bSQLBaseAC,)
Set dfDatabase=
If nCmbEntries=0
Call SalListClear(cmbServer)
Call SalDisableWindow(pbConnect)
...
Message Actions
On SAM_Create
Set dfDatabase='island'
Set dfUserName='sysadm'
Set dfPassword='sysadm'
...

Setting autocommit
In your Centura SQLWindows application you can either specify transaction
boundaries explicitly in your application code, or you can have the database server
process each SQL statement in your application as its own transaction. To specify
transaction boundaries explicitly, you first disable autocommit; you then execute
COMMIT or ROLLBACK statements in your application code at the end of every
transaction. To have the database server process each SQL statement as its own
transaction, enable autocommit. (For more general information about autocommit,
read the Autocommit on page 1-3. For information about autocommit and a given
database server, read the chapter devoted to that server.)
In the multi-database application you can enable or disable autocommit
independently for each database. When you write a multi-database application, you
need to know what each of the databases you will connect to does if you disable
autocommit, then either disconnect from that database or end the application without
executing a COMMIT or ROLLBACK statement.
For example, if you connect to SQLBase or Oracle and disable autocommit, the
database server commits your last transaction for you if you either disconnect from
the database or end your application without executing a COMMIT or ROLLBACK
statement. Under the same circumstances, however, Microsoft SQL Server rolls the
transaction back.
The application initially disables autocommit for all three databases by calling
SqlSetParameter with the two arguments DBP_AUTOCOMMIT and FALSE. With
autocommit disabled, the application can ensure that operations on the various
databases are committed only after all portions of a transaction have been completed
successfully.
The code in the application that disables autocommit on SQLBase is:
Connecting Centura Objects to Databases

9-11

Chapter

Connecting to Multiple Databases Concurrently

Call SqlSetParameter(hSQLBase,DBP_AUTOCOMMIT,FALSE,)

where hSQLBase is the SQL handle for the connection to SQLBase.


Important: The sample application controls transactions separately on each of the databases;
it does not perform distributed transactions.

Concurrency and consistency


When multiple users access the same database, it is very important to allow as many
of those users as possible to get to their data at the same time. The more users can
access data at the same time, the more concurrency there is.
However, it also important for multiple users to get consistent data. Ideally, each user
should have the impression that he or she is the only user of the database. The closer
the user is brought to this ideal, the more data consistency there is.
You influence how much concurrency and data consistency there is while accessing
your databases through the use of data locks and application code.

Locking
Intelligent locking improves both concurrency and consistency. Different databases
support different locking strategies and implement different ways for users to set
locks. For example, both SQLBase and Microsoft SQL Server lock entire pages of
data. Oracle, on the other hand, locks individual rows (when you execute a
SELECT...FOR UPDATE statement). However, you cannot choose the kind of lock
Oracle places on that row.
Note: To set a particular kind of lock in SQLBase and Microsoft SQL Server, you set a certain
isolation levelsee Isolation Levels on page 9-13.
Locking strategies are either pessimistic or optimistic. A pessimistic locking strategy
assumes that another user will attempt to update the same row you might be looking
at. If you choose this strategy, the database server locks the row first before you get to
see the data, thus ensuring a high degree of data consistency. An optimistic locking
strategy assumes the opposite: no other user will attempt to update the row you are
looking at. If you choose this strategy, the database server does not lock the row, thus
ensuring a higher degree of concurrency.
If you adopt an optimistic locking strategy, you must put checks into your code to
verify for yourself that another user of the database has not updated any of the data
that the user of your application is viewing.

9-12 Connecting Centura Objects to Databases

Design issues

Isolation Levels
SQLBase and Microsoft SQL Server allow you to set isolation levels. An isolation
level defines the degree to which transactions are prevented from interfering with
each other. You set the isolation level in your Centura SQLWindows application by
calling the SAL function SqlSetIsolationLevel.
Most databases support several isolation levels. However, the isolation levels are not
defined in the same way on all the databases. The ANSI/SQL committee has defined
a standard set of isolation levels with standard semantics, but most databases do not
implement these isolation levels with precisely those semantics.
Some of the names commonly used by database vendors for isolation levels are: Dirty
Read, Uncommitted Read, Cursor Stability, Repeatable Read, and Serializable. Other
names you will see include Browse, Read Only, Release Locks, and Hold Lock.
Warning: Some databases use the same names as those specified by the ANSI/SQL
committee for isolation levels, but they do not implement the ANSI/SQL semantics for those
isolation levels. Do not assume you know what an isolation level means just from its name. You
must read the database vendor documentation to find out what the behavior is for each of the
isolation levels defined by that vendor.
Most relational databases allow users to set isolation levels (either at the statement
level, the transaction level, or both) at run-time. These databases also define a default
isolation level, but the default varies from database to database.
Note: Oracle does not allow your application to set an isolation level. This is because Centura
SQLWindows applications use dynamic SQL, and Oracle does not support the setting of
isolation levels with dynamic SQL

For example, the default isolation level in SQLBase is called Repeatable Read (RR).
SQLBase implements this isolation level by maintaining a read lock on the requested
row until the transaction has been committed.
Another example comes from Microsoft SQL Server, where the default isolation level
is called Read Uncommitted. With this isolation level, the database may send a client
requesting a row the most recently changed data in that row even if those changes
have not yet been committed.
Even though these isolation levels vary in syntax and semantics for each database,
Centura SQLWindows allows for up to four isolation levels. The semantics of these
isolation levels depends on the database your application connects to. To learn which
isolation levels are supported for a given database, read the chapter in this book
devoted to that database.

Connecting Centura Objects to Databases

9-13

Chapter

Connecting to Multiple Databases Concurrently

For example, to set the isolation level on Microsoft SQL Server to


SQL_TXN_SERIALIZABLE, make the call:
Call SqlSetIsolationLevel(hMSSQLServer,RR)

The application chooses an initial value for the isolation level to guarantee that the
data remain consistent until the application executes a COMMIT or ROLLBACK
statement. With this isolation level other database users are prevented from changing
locked data until the application has completed the transaction.
The application executes all SQL statements as Dynamic SQL statements.
Note: Because the Oracle OCI does not support the setting of isolation levels for Dynamic SQL
statements, the application does not set an isolation level with Oracle.

Database-oriented client/server applications fall into two broad categories:


transaction-based applications and decision support applications.
Transaction-based applications generally affect one or more tables. All work related
to a single transaction should be committed only if all the operations in that
transaction completed successfully. If the application detects the violation of an
integrity constraint, it might choose to roll back the transaction.
Decision support applications typically do a lot of queries and only occasionally
change the database. Because decision support queries usually take a long time to
execute, you normally do not want to acquire any locks along the way. If you do
choose to acquire locks during the query, you normally release those locks as soon as
the query is done.
Transaction-based applications need to support a high degree of both concurrency
and consistency among users because these applications are typically run by many
users at the same time. To support a high degree of concurrency these applications
typically select the most permissive isolation levels available. These isolation levels
direct the database either to not lock data (allowing dirty reads) or to release locks
very quickly (such as releasing a lock as soon as a row is readthis isolation level is
often called cursor stability).
Decision support applications do not require high degrees of concurrency; they can
use much more restrictive locking to maintain more data consistency. However, if
you write a decision support application knowing it will access the same database as a
transaction-based application, you should design it to use (at least nearly) the same
isolation level as the transaction-based application to support the high degree of
concurrency needed by the transaction-based application.
One way applications can get both a high degree of concurrency and a high degree of
data consistency is to choose a permissive isolation level (one that releases locks

9-14 Connecting Centura Objects to Databases

Design issues

quickly), enable cursor context preservation (CCP), then commit transactions quickly
(either by enabling autocommit or executing the COMMIT statement frequently).
Note: Generally, if both decision support and transaction-based applications access the same
database, the decision support applications should use an optimistic locking strategy to reduce
their impact on the transaction-based applications.
The sample multi-database application combines elements of both a decision support
application and a transaction-based application. The portion that is like a decision
support application processes the COMPANY, PRODUCT, and EMPLOYEE tables;
the portion that is transaction-based handles the creating of invoices and the accessing
of the INVOICE_ITEM, PAYMENT, and PRODUCT tables. Because the application
is a hybrid, it needs a high degree of both consistency and concurrency. This
application sets the isolation level to Repeatable Read and disables autocommit; in
your own application you must make appropriate design decisions (such as choosing
an isolation level) that let you strike a suitable balance between concurrency and data
consistency.

Replicating table schemas and data


The application creates the schema of the INVOICE, INVOICE_ITEM, and
PRODUCT tables in the SQLBase ISLAND database on the Oracle database server
with the CREATE TABLE statement. The application copies the data from SQLBase
to Oracle using SELECT... FROM and INSERT... INTO statements.
There are some data type differences among SQLBase, Oracle, and Microsoft SQL
Server. You see these kinds of differences whenever you write a single application
that accesses heterogeneous databases. Some data types are not supported on all the
databases your application must access.
For example, the picture column in the PRODUCT table on SQLBase is a LONG
column. When the application moves this data to Oracle, it redefines this column as
LONG RAW data because the column contains binary data.
The application copies table data from SQLBase to Oracle, Microsoft SQL Server, or
SQLBase itself by executing a SELECT from SQLBase, then executing an INSERT
statement to place the data into the target database. The application also creates table
indexes on the target database.
When creating tables on one database server to receive data from tables on another
database server, you must specify suitable column type definitions in the CREATE
TABLE statement. Because different database servers do not all support the same set
of data types, you must decide which data types to use when you copy data from one
database server to another.

Connecting Centura Objects to Databases

9-15

Chapter

Connecting to Multiple Databases Concurrently

For example, most database servers support a data type called VARCHAR. However,
the length bounds for this data type vary from one database server to another.
Depending on the size of the actual VARCHAR data you are copying, you may have
to specify a column type other than VARCHAR (such as LONG, for example) on the
database server to which you are copying the data.
Depending on the databases you are accessing in your own applications, you may
want to use a different technique whenever you need to copy data from one database
to another, especially if you are moving large amounts (megabytes) of data. Read the
documentation on the databases your applications access for information that may
help you decide how to perform such an operation efficiently.
In the following excerpt, the application creates the EMPLOYEE table on Microsoft
SQL Server and the INVOICE table on Oracle; it then copies the data from the
corresponding SQLBase tables to the target database using the TransferData internal
function.
Popup Menu: &Populate Data
...
Menu Item: Microsoft SQL Server
...
Menu Settings
Enabled when: hMSSQLServer
Checked when:
Menu Actions
Set strSQL = CREATE TABLE || MDB_EMPLOYEE ||
(EMPLOYEE_ID CHAR (8), ||
LAST_NAME VARCHAR (30), ||
FIRST_NAME VARCHAR (30), ||
MI CHAR (1), ||
EXTENSION VARCHAR (4), ||
OFFICE_NO VARCHAR (5), ||
DEPT_ID CHAR (5), ||
DATE_HIRED DATETIME, ||
CURRENT_SALARY FLOAT (8))
If NOT SqlPrepareAndExecute(hMSSQLServer,strSQL)
Set strMsgPrompt=MSGBOX_MSGPART1 || MDB_EMPLOYEE ||
MSGBOX_MSGPART2
Set nMsgResult=SalMessageBox(strMsgPrompt,MSGBOX_TITLE,
MB_OkCancel)
If nMsgResult=IDCANCEL
Return -1
Else
Call TransferData(MDB_EMPLOYEE)

9-16 Connecting Centura Objects to Databases

Design issues

Call SalMessageBox('Create Index for ' || MDB_EMPLOYEE,


'Create Index',MB_Ok)
Set strSQL='CREATE UNIQUE INDEX ' || MDB_EMPLOYEE_IDX ||
' ON ' || MDB_EMPLOYEE || ' (EMPLOYEE_ID)'
If NOT SqlPrepareAndExecute(hMSSQLServer,strSQL)
Call SalMessageBox('SQL Error Creating Index ' ||
MDB_EMPLOYEE_IDX,'Error!',MB_Ok)
...

Menu Item: Oracle


...
Menu Settings
Enabled when: hOracle
Checked when:
Menu Actions
Set strSQL=CREATE TABLE || MDB_INVOICE ||
(INVOICE_NO DECIMAL(8, 0) NOT NULL, ||
COMPANY_ID SMALLINT NOT NULL, ||
COMPANY_NAME VARCHAR(30), ||
INVOICE_DATE DATE, ||
DATE_PAID DATE, ||
STATUS VARCHAR(18), ||
AMOUNT_PAID DECIMAL(8,2), ||
EMPLOYEE_ID CHAR(8))
If NOT SqlPrepareAndExecute(hOracle,strSQL)
Set strMsgPrompt = MSGBOX_MSGPART1 || MDB_INVOICE ||
MSGBOX_MSGPART2
Set nMsgResult=SalMessageBox(strMsgPrompt,MSGBOX_TITLE,
MB_OkCancel)
If nMsgResult=IDCANCEL
Return -1
Else
Call TransferData(MDB_INVOICE)
Call SalMessageBox('Create Index for ' || MDB_INVOICE,
'Create Index',MB_Ok)
Set strSQL='CREATE INDEX ' || MDB_INVOICE_IDX ||
' ON ' || MDB_INVOICE || ' (INVOICE_NO)'
If NOT SqlPrepareAndExecute (hOracle,strSQL)
Call SalMessageBox ('SQL Error Creating Index ' ||
MDB_INVOICE_IDX,'Error!',MB_Ok)
...

Connecting Centura Objects to Databases

9-17

Chapter

Connecting to Multiple Databases Concurrently

The TransferData function accepts the table name as input, then transfers data from
SQLBase to the target database. If the input table name is MDB_COMPANY, the
target database is SQLBase; if MDB_EMPLOYEE or MDB_PAYMENT, the target
database is Microsoft SQL Server; otherwise, the target database is Oracle.
Function: TransferData
Returns
Boolean: bOk
Parameters
String: strTableName
...
Actions
When SqlError
Call SalMessageBox ('SQL Error in Transfer Data function',
'Transfer Data Error!',MB_Ok)
Return FALSE
If strTableName=MDB_EMPLOYEE
! Read from SQLBase employee table into MS SQL Server
Set strTempSQL=INSERT INTO || MDB_EMPLOYEE ||
' VALUES (:dfCol1,:dfCol2,:dfCol3,:dfCol4,:dfCol5,
:dfCol6,:dfCol7,:dfCol8,:dfCol9)'
Call SqlPrepare(hMSSQLServer,strTempSQL)
Set strSQL='SELECT * FROM EMPLOYEE INTO ||
:dfCol1,:dfCol2,:dfCol3,:dfCol4,:dfCol5, ||
:dfCol6,:dfCol7,:dfCol8,:dfCol9
If SqlPrepareAndExecute(hSQLBasePop,strSQL)
Loop TData1
If SqlFetchNext(hSQLBasePop,nRetval)
Call SqlExecute(hMSSQLServer)
Else
Break TData1
! If autocommit is off for Microsoft SQL Server,
! commit the changes.
If NOT bMSSQLServerAC
Call SqlCommit(hMSSQLServer)
Return TRUE
...
If strTableName=MDB_INVOICE
! Read the SQLBase invoice table into Oracle
Set strTempSQL=INSERT INTO || MDB_INVOICE ||
VALUES(:nInvNum,:nCompId,:strCompName,:dInvDate, ||
:dDatePaid,:strStatus,:nAmtPaid,:strEmpId)
Call SqlPrepare(hOracle,strTempSQL)
Set strSQL = SELECT * FROM INVOICE INTO ||
:nInvNum,:nCompId,:strCompName,:dInvDate, ||

9-18 Connecting Centura Objects to Databases

Design issues

:dDatePaid,:strStatus,:nAmtPaid,:strEmpId
If SqlPrepareAndExecute(hSQLBasePop,strSQL)
Loop TData3
If SqlFetchNext(hSQLBasePop,nRetval)
Call SqlExecute(hOracle)
Else
Break TData3
! If autocommit is off for Oracle, commit the changes.
If NOT bOracleAC
Call SqlCommit(hOracle)
Return TRUE
...

Displaying table data


The application displays table data in dynamic table windows (by calling the SAL
function SalTblPopulate). A dynamic table window uses automatic columns, which
you can use to display the results of any query whatsoeverautomatic columns are of
type STRING, but can display data of any type (except the LONG data types). For
more information about SalTblPopulate, refer to the Centura SQLWindows
Function Reference.
In the following code excerpt, the application retrieves data from the COMPANY
table (in SQLBASE) into a dynamic table window.
Menu Item: &Company
...
Menu Settings
Enabled when: hSQLBase
Checked when:
Menu Actions
Call SalShowWindow(tblInfo)
Call SalBringWindowToTop(tblInfo)
...
Set strSQL = 'SELECT * FROM COMPANY'
Call SalTblPopulate(tblInfo,hSQLBase,strSQL,TBL_FillNormal)
...

Connecting Centura Objects to Databases

9-19

Chapter

Connecting to Multiple Databases Concurrently

In the following code excerpt, the application retrieves data from the EMPLOYEE
table (in Microsoft SQL Server) into a dynamic table window.
Menu Item: &Employee
...
Menu Settings
Enabled when: hMSSQLServer
Checked when:
Menu Actions
Call SalShowWindow(tblInfo)
Call SalBringWindowToTop(tblInfo)
...
Set strSQL=SELECT * FROM || MDB_EMPLOYEE
Call SalTblPopulate(tblInfo,hMSSQLServer,strSQL,
TBL_FillNormal)
...

In the following code excerpt, the application retrieves data from the PRODUCT
table (in Oracle) into a dynamic table window.
Menu Item: &ProductInvoice
...
Menu Settings
Enabled when: hOracle
Checked when:
Menu Actions
Call SalShowWindow(tblInfo)
Call SalBringWindowToTop(tblInfo)
Call SalShowWindow(picPicture)
...
Set strSQL='SELECT STYLE_ID,STYLE,DESCRIPTION,PRICE FROM ' ||
MDB_PRODUCT
Call SalTblPopulate(tblInfo,hOracle,strSQL,TBL_FillNormal)
...

9-20 Connecting Centura Objects to Databases

Design issues

Key columns
The key columns for the tables used in the multi-database application are:

company_id in the COMPANY table

employee_id in the EMPLOYEE table

invoice_no in the INVOICE table

style_id in the PRODUCT table

Note: You cannot update a key column.

Transaction processing
The multi-database Centura application centers around four transactions.
Three of these transactions involve just a single SQL table located on a specific
database server. None of these tables has dependencies on any other table.
The three transactions are:

Retrieve, insert, delete, and update the COMPANY table on SQLBase.

Retrieve, insert, delete, and update the PRODUCT table on Oracle.

Retrieve, insert, delete, and update the EMPLOYEE table on Microsoft SQL
Server.

The more complex transaction is the INVOICE transaction. It involves multiple


tables: the INVOICE and INVOICE_ITEM tables on Oracle and the PAYMENT
table on Microsoft SQL Server. When the user clicks the Details button for a
specified invoice (and the user has also selected the Invoice Item radio button), the
application displays a form showing all invoice items, a single payment entry, and a
PRODUCT table listing.
The sample application manages two independent transactions: one on Oracle and the
other on Microsoft SQL Server; it does not process this transaction as a distributed
transaction between Oracle and Microsoft SQL Server.
A distributed transaction is one where the transaction is shared by two or more
(possibly heterogeneous) database servers. When a client executes the COMMIT
statement, all the servers participating in the transaction must coordinate to make a
collective yet single decision whether to register all the changes in the transaction or
to undo all the changes.
A commit coordinator (sync-point manager) manages this decision-making process.
The coordinator knows about all the participants, issues a prepare for commit, and
receives acknowledgments. When the coordinator receives all the acknowledgments,
it issues a commit to all participants. Once the participants have all acknowledged a

Connecting Centura Objects to Databases

9-21

Chapter

Connecting to Multiple Databases Concurrently

successful commit, the coordinator writes a commit marker. The commit coordinator
also keeps track if a database server goes down during the second portion of the
commit phase. If that happens, the coordinator helps to resolve the transaction.
If a user adds a new invoice item for a selected invoice number, the style_id and
item_price columns in the INVOICE_ITEM table are set from the chosen product
selected from the PRODUCT table. Once a quantity is specified, the amount column
in the PAYMENT table is adjusted to reflect the new product quantity and price by
summing all invoice item quantities times their unit price for the specified invoice
number.
If the user removes an invoice item for a selected invoice number, the amount column
in the PAYMENT table is adjusted to reflect the removal of a product quantity and
price by summing all invoice item quantities times their unit price for the specified
invoice number.
If the user changes the quantity associated with a selected invoice item, the amount
column in the PAYMENT table is adjusted to reflect the modifying of a product
quantity and price by summing all invoice item quantities times their unit price for
the specified invoice number.
Note: One useful way to enhance the sample application is to make sure that another
application cannot change a row that the sample application has read until it executes a
COMMIT or ROLLBACK. You can do this on Oracle by retrieving data with the
SELECT...FOR UPDATE statement.
The application locks the PAYMENT data because it uses an isolation level of
Repeatable Read on Microsoft SQL Server.
Since the sample application is predominantly transaction-based, we disable
autocommit; this lets the application take control of the transaction boundaries. When
the user creates or updates an invoice item, the application needs to guarantee that all
changes are committed only when changes have been successfully made to all tables.
If even one of the updates fails, the application rolls back all the changes that make
up the transaction.
The application must also guarantee the integrity of each row in the tables affected by
the transaction. No client should be allowed to update a row that another client has
either read or updated. To do this the application selects the isolation level
Repeatable Read. This puts a lock on every row a user fetches and maintains that lock
until the user commits (or rolls back) the transactionother users cannot write to any
of the locked rows.
For example, when a user creates a new invoice item, the PAYMENT row needs to
be locked while the application updates the amount column, summing all invoice
item quantities and their unit prices. The PRODUCT table row for this invoice item
9-22 Connecting Centura Objects to Databases

Design issues

needs to locked so that information cannot be changed and that PRODUCT entry
itself cannot be removed. All other invoice items for the selected invoice number
need to be locked since the application uses those quantities and unit prices to
calculate a new amount in the PAYMENT table. Also, none of the invoice items
should be removed while the application does the calculation.
To manage transactions explicitly an application must disable autocommit.
If you disable autocommit and fail to commit or roll back the last transaction before
disconnecting or ending the application, some databases commit the last transaction
while others roll it back. Read your database vendor documentation to find out what
your database does in that situation.

Processing the INVOICE transaction


The application allows a user to display INVOICE_ITEM entries and PAYMENT
information for a selected invoice. A user can insert, update, or delete new invoice
items. The application adjusts the associated PAYMENT amount for the selected
invoice accordingly. The application allows the user to update a PAYMENT entry but
not delete it. Because there is only one PAYMENT record for each invoice number, a
PAYMENT record must exist as long as an invoice exists. A user cannot add a new
PAYMENT entry for a selected invoice number because there is only one
PAYMENT record for each invoice number. A user also cannot update selected fields
in either the INVOICE_ITEM or PAYMENT table.
For example, item_price in the INVOICE_ITEM table is set from the PRODUCT
table price column; item_no and invoice_no are key fields. The amount column in the
PAYMENT table is calculated by summing all invoice items (quantity column times
item_price column); invoice_no is the key field.

Dynamic binding
Dynamic binding in SQLBase and any database you access using ODBC allows you
to use column variables of type STRING as bind variables. Because you cannot use
dynamic binding with Oracle, you must define each column variable with the correct
data type.
In the following code excerpt, the application uses automatic column variables as
bind variables to update the COMPANY table on SQLBase and the EMPLOYEE
table on Microsoft SQL Server.
Pushbutton: pbUpdate
...
Message Actions
On SAM_Click
Set nNumCols=SalSendMsg(tblInfo, SAM_GETCOLCOUNT, 0, 0)
Set strSQL='UPDATE '
If nTableIndicator=SQLBASE_TABLE
Connecting Centura Objects to Databases

9-23

Chapter

Connecting to Multiple Databases Concurrently

Set strSQL=strSQL || MDB_COMPANY || ' SET '


Set hLocalSql=hSQLBase
Else If nTableIndicator = MSSQLSERVER_TABLE
Set strSQL=strSQL || MDB_EMPLOYEE || ' SET '
Set hLocalSql=hMSSQLServer
Set nIndex = 2
Loop Binding2
Call SalTblGetColumnTitle(
SalTblGetColumnWindow(tblInfo,nIndex,COL_GetPos),
strColName,MAXCOLNAME_LENGTH)
If nIndex < nNumCols
Set strSQL=strSQL || strColName || = : ||
tblInfo# || SalNumberToStrX (nIndex,0) || ,
Else If nIndex = nNumCols
Set strSQL=strSQL || strColName || = : ||
tblInfo# || SalNumberToStrX(nIndex,0)
Break Binding2
Set nIndex=nIndex + 1
Call SalTblGetColumnTitle(
SalTblGetColumnWindow(tblInfo,1,COL_GetPos),
strColName,MAXCOLNAME_LENGTH)
Set strSQL=strSQL || WHERE || strColName ||
= :tblInfo#1
Call SqlPrepare(hLocalSql,strSQL)
Call SalTblDoUpdates(tblInfo,hLocalSql,TRUE)
...

The following is an example of similar code required to update the INVOICE table
on Oracle where we cannot take advantage of STRING automatic column variables
as bind variables:
Pushbutton: pbUpdate
...
Message Actions
On SAM_Click
Set strSQL='UPDATE '
If nTableIndicator=ORACLE_TABLE1
Set strSQL=strSQL || MDB_INVOICE || ' SET '
Set hLocalSql=hOracle
Set strSQL = strSQL ||
COMPANY_ID=:nCompId, ||
COMPANY_NAME=:strCompName, ||
INVOICE_DATE=:dInvDate, ||
DATE_PAID=:dDatePaid, ||
STATUS=:strStatus, ||
AMOUNT_PAID=:nAmtPaid, ||
EMPLOYEE_ID=:strEmpId ||

9-24 Connecting Centura Objects to Databases

Implementation details

WHERE INVOICE_NO=:nInvNum
Set nInvNum=SalStrToNumber(tblInfo#1)
Set nCompId=SalStrToNumber(tblInfo#2)
Set strCompName=tblInfo#3
Set dInvDate=SalStrToDate(tblInfo#4)
Set dDatePaid=SalStrToDate(tblInfo#5)
Set strStatus=tblInfo#6
Set nAmtPaid=SalStrToNumber(tblInfo#7
Set strEmpId=tblInfo#8
Call SqlPrepare(hLocalSql,strSQL)
Call SalTblDoUpdates(tblInfo,hLocalSql,TRUE)
...

Note: The sample application assumes the first column is the key field.

Implementation details
This section describes some of the implementation details involved in updating table
data, dynamic table windows management, dynamic data type binding, isolation
levels, and autocommit.

Updating table data


The sample application assumes that the first column of a table is a key column; the
application uses this key for update or delete operations. This assumption allows the
application to make use of common code when building the WHERE clause of a
SELECT, UPDATE, or DELETE statement.
The following is an example of how the application builds the WHERE clause of a
SELECT statement:
Call SalTblGetColumnTitle(
SalTblGetColumnWindow (tblInfo,1,COL_GetPos),
strColName,MAXCOLNAME_LENGTH)
Set strSQL=strSQL || ' WHERE ' || strColName ||
' = :' || 'tblInfo#1'

Dynamic table windows management


Dynamic table windows let the developer use table windows without defining as
much about them at design time. You use dynamic table windows to display data
from different user queries. These queries can specify differing numbers of columns
and even different data types. To display data in a dynamic table window, call
SalTblPopulate.
The application specifies TBL_FillNormal when calling SalTblPopulate; this
populates only the visible portion of the table window. New rows are fetched only
Connecting Centura Objects to Databases

9-25

Chapter

Connecting to Multiple Databases Concurrently

when they are brought into view. Since the tables have only a small number of rows,
specifying TBL_FillNormal does not improve performance significantly. However,
for tables that have hundreds or perhaps thousands of rows, specifying
TBL_FillNormal can greatly improve performance.

Microsoft SQL Server and SQLBase


For the Populate menu option, the TransferData function fetches row data from
SQLBase into generic column variables of type STRINGfor example, dfCol1,
dfCol2, and so on. When the application inserts a row data into the Microsoft SQL
Server database or the SQLBase database, it uses these same generic column
variables as the program variables.
The Insert, Update, Delete, and Refresh buttons use the automatic column variables
created by SalTblPopulate as the bind variable names on the associated INSERT,
UPDATE, DELETE, or SELECT statement. The automatic column variables are of
type STRING and have the following syntax:
table_name#column_number
For example, the first column variable for dynamic table tblInfo is tblInfo#1.
If the user selects the Table menu option, the application calls SalTblPopulate to
build a dynamic table window for the selected tablethe COMPANY table on
SQLBase and the EMPLOYEE table on Microsoft SQLServer.

Oracle
The PICTURE column from the PRODUCT table is not displayed as a column in the
dynamic table window because the data is a bit map. There is a separate area on the
form where the product image is displayed if the user clicks on the row header of a
given PRODUCT table entry.
If the user selects the Table menu option, the application calls SalTblPopulate to
build a dynamic table window for the INVOICE and PRODUCT tables on Oracle.

Dynamic data type binding


Because Oracle does not support dynamic data type binding, the application does not
use the automatic column variables as bind variables for data types other than
STRING in the INSERT, UPDATE, or DELETE statements. For the NUMBER and
DATE data types, the application calls SalStrToNumber and SalStrToDate to convert
the automatic variable string data to the correct number or date formatthe
application uses a specific bind variable of that data type.

9-26 Connecting Centura Objects to Databases

Implementation details

Oracle
For the Populate menu option, the TransferData function fetches row data from
SQLBase into specific data type column variables (for example, nCompId of type
NUMBER, dDatePaid of type DATE/TIME, and so forth). When the application
inserts a row of data into the Oracle database, it uses these data-type-specific
variables as the program variables.
When the user clicks the Insert, Update, Delete, or Refresh buttons, the application
calls an appropriate SAL function to convert the data associated with each dynamic
column variable created by SalTblPopulate into a NUMBER or DATE/TIME specific
column variable. The application uses these data-type-specific column variables as
bind variable names on the associated INSERT, UPDATE, DELETE, or SELECT
statement.
To copy data from SQLBase to Oracle, the application must map the SQLBase
column data types to the Oracle data types. Because SAL has no functions for
obtaining the data type of each column in a table, the application must hard-code the
appropriate values of the CREATE TABLE statement that it executes on the target
database (the one to which it copies the data). For example, the picture column is a bit
map stored on SQLBase in a LONG column. To store this data on Oracle, the
application must use a LONG RAW column.

Microsoft SQL Server


To copy data from SQLBase to Microsoft SQL Server, the application must map the
SQLBase column data types to the Microsoft SQL Server data types. Because SAL
has no functions for obtaining the data type of each column in a table, the application
must hard-code the appropriate values of the CREATE TABLE statement that it
executes on the target database (the one to which it copies the data).

Isolation levels and Oracle


Oracle does not support the setting of isolation levels using dynamic SQL. Because of
this, you have two ways of locking data in a table on Oracle:

Lock the entire table with the LOCK TABLE statement.

Lock certain rows with the SELECT...FOR UPDATE statement.

Locking an entire table is very heavy-handed and risky. No one other than the user
who has locked the table can do any operations on the table until it is unlocked. Even
if the application locks the table for only a short period of time, the penalty paid by
other users is usually unacceptably high.
Locking only certain rows during a transaction is much more selective and allows
other users to access all data in the database except for the locked rows. However, if

Connecting Centura Objects to Databases

9-27

Chapter

Connecting to Multiple Databases Concurrently

the user who has the lock takes a long time to complete the transaction, all other users
who need to access that data are forced to wait.
The sample application favors a high degree of concurrent access to the database over
a high degree of data consistency by not locking any of the Oracle table data that it
accesses.

Autocommit
The sample application turns off autocommit for SQLBase, Microsoft SQL Server,
and Oracle. The application is responsible for committing (or rolling back) the
operations that make up a transaction.
You may find it instructive to modify the sample application by enabling autocommit
and observe how the application runs differently.
While the application does manage its own transactions, it does not manage the
operations on both Oracle and Microsoft SQL Server as a single distributed
transaction. Instead, the application commits changes to INVOICE and
INVOICE_ITEM tables (on Oracle) separately from the PAYMENT table (on
Microsoft SQL Server).
For example, if the commit fails for the PAYMENT table, the application rolls back
not only the changes in the PAYMENT table on Microsoft SQL Server, but also the
changes in the INVOICE and INVOICE_ITEM tables on Oracle. If the commit
succeeds for the PAYMENT table, the application commits the changes to the
INVOICE and INVOICE_ITEM tables on Oracle also. If the commit for those tables
fails, you can roll back the changes in those tables, but at this point you cannot go
back to Microsoft SQL Server and roll back the PAYMENT table changes already
committed.
This code excerpt shows how the application coordinates commit (and rollback, if
required) between Microsoft SQL Server and Oracle:
On SAM_Click
! Ok, commit all the changes.
If NOT bMSSQLServerAC
! If commit on MS SQL Server fails and autocommit is off,
! roll back Microsoft SQL Server and Oracle.
If NOT SqlCommit(hMSSQLServer)
If SqlPrepareAndExecute(hMSSQLServer,rollback)
Call SalMessageBox(Microsoft SQL Server changes ||
were successfully rolled back,
Rollback Status,MB_Ok)

9-28 Connecting Centura Objects to Databases

Getting more information

If NOT bOracleAC
If SqlPrepareAndExecute(hOracle,'rollback')
Call SalMessageBox(Oracle changes were ||
successfully rolled back,Rollback Status,MB_Ok)
Return -1
Else
Call SalMessageBox(Microsoft SQL Server changes were ||
successfully committed,Commit Status,MB_Ok)
!
!
!
!

If the commit was successful on Microsft SQL Server, perform


a commit on Oracle. If the commit fails, perform a rollback
on Oracle. NOTE: You cannot go back to Microsoft SQL Server
and roll back the updates if the commit on Oracle failed.
If NOT bOracleAC
If NOT SqlCommit(hOracle)
If SqlPrepareAndExecute(hOracle,'rollback')
Call SalMessageBox(Oracle changes were successfully ||
rolled back,Rollback Status,MB_Ok)
Return -1
Else
Call SalMessageBox( 'Oracle changes were successfully ||
committed,Commit Status,MB_Ok)

Important: If you successfully commit on Microsoft SQL Server, try to commit on Oracle. If
the commit on Oracle fails, you can do a rollback there, but you cannot roll back the changes
you committed on Microsoft SQL Server.

Getting more information


For more information about transactions, you can read Transaction Processing:
Concepts and Techniques by Jim Gray and Andreas Reuter. You may also want to
find out if your database servers can handle distributed transactions using industry
standard protocols such as X/Open XA+. If they do, you may want to adopt those
protocols using the External Call Functions feature of Centura SQLWindows.

Connecting Centura Objects to Databases

9-29

Connecting Centura Objects to Databases

Chapter 10

Certifying ODBC Drivers


This chapter describes how you can certify an ODBC driver for use with Centura
SQLWindows applications on your own using Database Connectivity Configuration
(DCC).

Connecting Centura Objects to Databases

10-1

Chapter

10

Certifying ODBC Drivers

About DCC
Connectivity information between Centura SQLWindows applications and databases
accessed using ODBC drivers is externalized and captured in a file called DCC.INI.
You can configure how Centura SQLWindows applications interact with an ODBC
driver that has not been certified by Centura Softwaregenerate an initial version of
the DCC.INI file for that driver, then editing the file to complete the information
needed there.
When you have finished certifying the ODBC driver and have verified the
correctness of the new DCC.INI file, you distribute that file along with the driver to
customer sites. When a Centura SQLWindows application connects to the target
database using that driver, it reads the DCC.INI file to determine how to interact
with that driver correctly.

Overview
This chapter describes the steps you need to follow to certify an ODBC driver using
the DCC (Database Connectivity Configuration) feature. An ODBC driver is
typically written by a third-party vendor; your goal in certifying that driver is to
verify that a Centura SQLWindows application can successfully use the driver to
connect to the target database.
To see an actual, complete DCC.INI file, look at DCC.INI file for Paradox 3.x on
page 10-10.
Important: For an explanation of each of the attributes you can assign a value to in the
DCC.INI file, look at the Centura Team Developer online help under Connectivity.

Prerequisites
Before you try to certify an ODBC driver, you should have:

In-depth knowledge of the ODBC driver and the characteristics of the target
database.

Complete knowledge of the output from the ODBC function calls GetInfo
and GetTypeInfo.

10-2 Connecting Centura Objects to Databases

Prerequisites

For example, some of the GetInfo parameters and the corresponding return values for
the Microsoft ODBC driver for Paradox are:
Argument to SqlGetInfo Function Call

Return Value

SQL_IDENTIFIER_QUOTE_CHARACTER

SQL_MAX_TABLE_NAME_LEN

12

SQL_OUTER_JOINS

SQL_GROUP_BY

The call for the column type information is:


SqlGetTypeInfo(SQL_ALLTYPES)

The output for GetTypeInfo is:


"TYPE_NAME", DATA_TYPE", "PRECISION",
"LITERAL_PREFIX", "LITERAL_SUFFIX","CREATE_PARAMS",
"NULLABLE", "CASE_SENSITIVE", "SEARCHABLE",
"UNSIGNED_ATTRIBUTE", "MONEY", "AUTO_INCREMENT",
"LOCAL_TYPE_NAME", "MINIMUM_SCALE", "MAXIMUM_SCALE"
"Short", 5, 5, <Null>, <Null>, <Null>, 1, 0,
2, 0, 0, 0, <Null>, 0, 0
"Number", 8, 15, <Null>, <Null>, <Null>, 1, 0,
2, 0, 0, 0, <Null>, <Null>, <Null>
"Date", 9, 10, "#", "#", <Null>, 1, 0,
2, <Null>, 0, <Null>, <Null>, <Null>, <Null>
"AlphaNumeric", 12, 255, "'", "'", "MAX LENGTH", 1, 1,
3, <Null>, 0, <Null>, <Null>, <Null>, <Null>

Refer to the Connectivity portion of the Centura Team Developer online help to get a
brief description of all the DCC attributes specified in the DCC.INI file. You can
save the contents of a help topic by selecting Edit, Copy from the Help menu bar.
Using your knowledge of your driver and your database server, compare the
GetTypeInfo output and GetInfo output with the descriptions of the DCC attributes in
the on-line help to decide how to set those attributes.

Connecting Centura Objects to Databases

10-3

Chapter

10

Certifying ODBC Drivers

Before certifying an ODBC driver


Before you certify that an ODBC driver can work with Centura SQLWindows
applications, you need to:
1.

Add an ODBC data source.

2.

Generate a new version of the DCC.INI file.

3.

Add values to entries in the DCC.INI file not automatically filled in by the DCC
utility.

Adding an ODBC data source


To add a data source to your ODBC driver, click the ODBC icon to invoke the
ODBC Administrator. (To learn where to find this icon, read your Windows NT or
Windows 95 documentation or on-line help. To learn how to fill in the dialog boxes
displayed by the ODBC Administrator, read the ODBC Administrator on-line help
and the documentation supplied by your ODBC driver vendor.)

Generating a new DCC.INI file


Create a version of the DCC.INI file with as many entries as possible filled in
automatically.

Generating a new DCC.INI file


1.

Start Centura SQLWindows.

2.

Select View, Database Explorer.

3.

Connect to the data source you added.

4.

Exit from Centura SQLWindows.

When you connect to an uncertified data source, Centura SQLWindows invokes the
DCC utility. This utility makes a number of calls to your ODBC driver, obtains
values for all needed sections and attributes, then writes them to the DCC.INI file.
The DCC utility creates a new version of the DCC.INI file regardless of the value to
which you set the DUMP keyword in the existing DCC.INI.When the DCC utility
creates a new version of the file, it keeps the information from the previous version
while adding new information about the uncertified data source you are connecting
to.
Note: The DCC utility inspects the value of the DUMP keyword only when working with
drivers that have already been certified by Centura Software.

10-4 Connecting Centura Objects to Databases

Before certifying an ODBC driver

Let us suppose you want to certify the Microsoft ODBC driver for Paradox. When
you connect to a Paradox data source that you have defined for this driver, the DCC
utility creates a new section in the DCC.INI file that begins with:
[PARADOX 3.X ODBCJT16]

This section has all the boolean, integer and string attributes in it. Any
attributes information that the DCC utility cannot obtain from your ODBC driver is
left blank in the DCC.INI file.
For example, the DCC utility cannot learn from the ODBC driver for Paradox how to
set the value for the Quoted Creator attributes, so it leaves this value blank. (The
value for this attributes indicates whether or not the creator of non-owned tables must
be enclosed in quotesTRUE means the creator must be enclosed in quotes.) It is up
to you to find out what the correct value is for this attributes (and all other attributes
for which the DCC utility supplies no values).
In the case of Paradox 3.x, the correct value of this attributes is FALSE. When you
edit the DCC.INI file, change the line with the Quoted Creator attributes to read:
Quoted Creator=FALSE

Another example involves the query processor in the Centura Database Explorer. The
query processor includes a Formula Editor to assist you in defining queries you can
run against a database. Suppose you want the Formula Editor to support simple
expressions, the modulo operator, and range expressions in queries to be run against
your target databaseassign the (decimal) value 193 to Parse Flags. You arrive at
this value by adding the hexadecimal values for each of the attributes you want to
enable, then you convert the sum to decimal. In this case we have:

0x0001simple expressions

0x0040modulo operator

0x0080range expressions

which adds up to 0x00C1 (or 193 decimal).


Suppose further that you do not want the Formula Editor to quote dates and you do
not want the Formula Editor to wrap datesassign the value 2 to Date Rule Flags.
You get this value by adding the value 0x0000 (no quoting of dates) and 0x0002 (no
wrapping of dates).
Important: Copy the DCC.INI file to another file (for example, DCC.BAK) before you edit
it. If you make mistakes editing, you can copy DCC.BAK to DCC.INI and start over.

Use the list of attributes you saved earlier (see Prerequisites on page 10-2) along with
your knowledge of the ODBC driver and the target database to fill in or modify the
entries the DCC utility creates in the DCC.INI file.

Connecting Centura Objects to Databases

10-5

Chapter

10

Certifying ODBC Drivers

Following are excerpts from the new sections of the DCC.INI that the DCC utility
generates automatically for you:
[PARADOX 3.x ODBCJT16]
Quoted Creator=
Outer Join=TRUE
Derived In GroupBy=
Label Clause=FALSE
Table Rename=FALSE
Comments=FALSE
Group By=
...
Table Name Length=12
Column Name Length=25
User Name Length=
...
Server Name=PARADOX
Row ID=
Row Version=
.....

Note: Refer to the appendix for a complete listing of the DCC.INI file that includes the
completed entries for Paradox version 3.x.

Column data types


The [PARADOX 3.x ODBCJT16] section is followed by four additional sections,
one for each of the four column data types that Paradox supports. Each section begins
with:
[Column Type(n) Info - PARADOX 3.x ODBCJT16]
In the first section n is 0; in the next, n is 1, and so on.

Below are the four sections for the columns that the DCC utility creates for our
example data source; the utility puts nothing after the equals sign if it is unable to
assign a value to a given attribute.
[Column Type(0) Info - PARADOX 3.X ODBCJT16]
Column Name=Short
Catalog Column Type=Short
Statement to Create Column=
Matching Gupta Column Type=
Maximum Size/Width=5
Precision=Required
Scale=
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE

10-6 Connecting Centura Objects to Databases

Before certifying an ODBC driver

Alternate Long Column Description=


Can NULL be specified in DDL?=TRUE
Can unique index be specified=TRUE
[Column Type(1) Info - PARADOX 3.X ODBCJT16]
Column Name=Number
Catalog Column Type=Number
Statement to Create Column=
Matching Gupta Column Type=
Maximum Size/Width=15
Precision=Required
Scale=
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE
Can unique index be specified=TRUE
[Column Type(2) Info - PARADOX 3.X ODBCJT16]
Column Name=Date
Catalog Column Type=Date
Statement to Create Column=
Matching Gupta Column Type=
Maximum Size/Width=10
Precision=Required
Scale=
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE
Can unique index be specified=TRUE
[Column Type(3) Info - PARADOX 3.X ODBCJT16]
Column Name=AlphaNumeric
Catalog Column Type=AlphaNumeric
Statement to Create Column=MAX LENGTH
Matching Gupta Column Type=
Maximum Size/Width=255
Precision=Required
Scale=
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE
Can unique index be specified=TRUE

Connecting Centura Objects to Databases

10-7

Chapter

10

Certifying ODBC Drivers

In each of these sections you must, at a minimum, supply values for the:

Matching Gupta Column Type

Scale

Maximum Scale

Once you have finished editing the DCC.INI file, copy it to another file name as a
backup before you certify (test) the driver. Once you have certified the driver (see
Certifying an ODBC driver on page 10-8) with the edited DCC.INI file, you will
need to distribute it to your customers along with the driver (see Deploying an ODBC
driver on page 10-9).

Certifying an ODBC driver


To certify your ODBC driver, you prepare and run test scripts to exercise the driver
as configured by the DCC.INI entries. To successfully certify the driver, your
Centura SQLWindows test applications must behave as you expect them to, given
your knowledge of the ODBC driver and the target database.
Among other things, you should test that:

Queries are generated correctly.

Data fetched from the database is correctly displayed in the Centura


SQLWindows test application windows.

Data written to the database is stored there correctly.

Important: To successfully certify your driver, you must correctly map all data types among
the database, the ODBC driver, and the Centura SQLWindows test applications. Also, your
entries in the DCC.INI file must allow Centura SQLWindows applications to correctly
recognize index information.
One way to do this testing is to use QuickObjects to create a QuickForm and
QuickTable for one or more tables in the database. Verify that you can correctly
fetch, update, and insert rows using one data type, then verify these same operations
with multiple data types.
Another test is to create a new table using the Database Explorer. Verify that the
control shows you all the column data types you should be able to operate on in a
Centura SQLWindows application. If you find something is wrong, or that some data
types are missing, go back to the DCC.INI file and modify the data type mappings
in the column information sections. (See Column data types on page 10-6.)
Also, verify that you can create indexes on all possible columns in a table using the
Data Access Control. You should be able to create indexes on character and integer
columns, but not on LONG data type columns.
10-8 Connecting Centura Objects to Databases

Deploying an ODBC driver

Deploying an ODBC driver


You need to provide customers who will use your ODBC driver both the driver itself
and the tested DCC.INI file. You need to modify your ODBC driver installation to
copy this DCC.INI file to the directory where Centura SQLWindows has been
installed.
Once the DCC.INI file has been copied to that directory, users need to stop any
Centura SQLWindows applications they were running and restart them.

Mapping the column types


When editing the DCC.INI file, make sure you specify at least one column matching
each of the internal Gupta column data types for the entry:
Matching Gupta Column Type=

For example, assume a database has only one character type called
ALPHANUMERIC. Even though the database has but one character type, you must
specify a value for both of the internal Gupta data types defined for character columns
(GTT_CHAR and GTT_VARCHAR). In the case of our hypothetical database that
has just the one character type, you must specify this type twice, once with the entry:
Matching Gupta Column Type=4

and once with the entry:


Matching Gupta Column Type=5

The order in which the Gupta internal data types are mapped to the database column
types is important. For example, databases typically define more than one LONG data
type. However, you should first map the databases LONG TEXT data type to the
Gupta internal data type GTT_LONG, then map the other LONG data types to
GTT_LONG. Put these other mappings after the mapping of the LONG TEXT data
type in the DCC.INI file.
Another situation arises with Paradox and numeric fields. For example, the
NUMBER data type should be mapped to GTT_INTEGER, and this mapping should
appear in the DCC.INI file before the mapping of the SHORT data type to
GTT_SMALLINT. If you order the mappings this way, you ensure that the mapping
for NUMBER is seen before the mapping for SHORT. This is important when, for
example, you copy a table from Centura Softwares SQLBase database to Paradox.

Connecting Centura Objects to Databases

10-9

Chapter

10

Certifying ODBC Drivers

The internal Gupta column data types are:


Internal Data Type

Numeric Value

GTT_INTEGER

GTT_SMALLINT

GTT_FLOAT

GTT_CHAR

GTT_VARCHAR

GTT_LONG

GTT_DECIMAL

GTT_DATE

GTT_TIME

GTT_DATETIME

10

DCC.INI file for Paradox 3.x


This section contains the actual DCC.INI file for ODBC drivers that connect to
Paradox 3.x.
[Dump Option]
DUMP=OFF
[PARADOX 3.X ODBCJT16]
Quoted Creator=TRUE
Outer Join=TRUE
Derived In GroupBy=FALSE
Label Clause=FALSE
Table Rename=FALSE
Comments=FALSE
Group By=TRUE
Alter Add=TRUE
Alter Drop=TRUE
Alter Modify=FALSE
Alter Rename=FALSE
Owner For Label=FALSE
Owner For Comment=FALSE
Qualify Index With Creator=FALSE

10-10 Connecting Centura Objects to Databases

DCC.INI file for Paradox 3.x

Only Access Owned Indexes=TRUE


Modify Index=FALSE
Pad User Names=FALSE
Not Null On Alter Table Add=FALSE
Mixed Case User Id Password=TRUE
Modify View=FALSE
With Check On Views=TRUE
Asc/Desc For Columns In Indexes=TRUE
Alter Authority=FALSE
Index Authority=FALSE
Not Null As Default=FALSE
Qualify Index On Create=FALSE
Qualify Index With Table Name=FALSE
Parantheses On Alter Table=FALSE
Alternate User Name=FALSE
Use Ordinals In Group By=TRUE
Cache Table=TRUE
Cache Column=TRUE
Cache Column Auth=FALSE
Cache Table Auth=FALSE
Qualify Table Name With DBName=FALSE
Column Type On Alter Modify=FALSE
Null On Alter Modify=TRUE
Delete Indexes=FALSE
Outer Join In From Clause=FALSE
Check Views Editable=TRUE
Support ROWID=FALSE
Support Row Version=FALSE
Support Logical Key=FALSE
Multiple Outer Joins=FALSE
Compound Outer Joins=FALSE
Qualify Indexes=FALSE
Qualified Column Names=FALSE
Commit After Result=FALSE
User Qualified Columns=FALSE
Support Create Tables=TRUE
Set Quest To Read-Only Mode=FALSE
Qualify Table Name With Creator=FALSE
Support Views=TRUE
Add Primary Keyword For Create Index=FALSE
Order By/Group By Column In Select List=TRUE
Quoted User Ids=TRUE
Quoted Table/Column Names=TRUE
Describe Mode=FALSE
Special Long Heading=FALSE
Table Name Length=12
Column Name Length=25

Connecting Centura Objects to Databases10-11

Chapter

10

Certifying ODBC Drivers

User Name Length=0


Parse Flags=
Number Of Column Types=10
Table Name Case=2
Number Of Optional Parms=
Date Rule Flags=
Maximum Row Size=1350
Default Long Binding Type=SQLPLON
RowID Type=
Column Name Case=2
DateTime Insert String=
Date Picture String=yyyy-MM-dd
Time Picture String=
DateTime Picture String=
Static Date Picture=1990-12-12
Static Time Picture=
Static DateTime Picture String=
Creator Filter=
System SQL Views Prefix=
Left Outer Join Format=
Right Outer Join Format=
Minimum Maximum Backend Version=3.0.0;9.9.9
Server Name=PARADOX
Date Insert String={d %s}
Time Insert String=
Row ID=
Row Version=
Logical Key=
Row Version Left Bind=
Row Version Right Bind=
Logical Key Left Bind=
Logical Key Right Bind=
Identifier Quote Character=
[Column Type(0) Info - PARADOX 3.X ODBCJT16]
Column Name=Short
Catalog Column Type=Short
Statement to Create Column=
Matching Gupta Column Type=2
Maximum Size/Width=5
Precision=Not Reqd
Scale=Not Reqd
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE

10-12 Connecting Centura Objects to Databases

DCC.INI file for Paradox 3.x

Can unique index be specified=TRUE


[Column Type(1) Info - PARADOX 3.X ODBCJT16]
Column Name=Number
Catalog Column Type=Number
Statement to Create Column=
Matching Gupta Column Type=1
Maximum Size/Width=15
Precision=Not Reqd
Scale=Not Reqd
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE
Can unique index be specified=TRUE
[Column Type(2) Info - PARADOX 3.X ODBCJT16]
Column Name=Date
Catalog Column Type=Date
Statement to Create Column=
Matching Gupta Column Type=8
Maximum Size/Width=10
Precision=Not Reqd
Scale=Not Reqd
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE
Can unique index be specified=TRUE
[Column Type(3) Info - PARADOX 3.X ODBCJT16]
Column Name=AlphaNumeric
Catalog Column Type=AlphaNumeric
Statement to Create Column=
Matching Gupta Column Type=5
Maximum Size/Width=255
Precision=Required
Scale=Not Reqd
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE

Connecting Centura Objects to Databases10-13

Chapter

10

Certifying ODBC Drivers

Can unique index be specified=TRUE


; These are duplicates of the column information above.
; Required for proper working of Database Explorer and
; Quick Objects. Note that except for Matching Gupta Column
; information, all other attributess retain the same value.
;
; This one maps Alphanumeric to GTT Column type of Character
[Column Type(4) Info - PARADOX 3.X ODBCJT16]
Column Name=AlphaNumeric
Catalog Column Type=AlphaNumeric
Statement to Create Column=MAX LENGTH
Matching Gupta Column Type=4
Maximum Size/Width=255
Precision=Required
Scale=Not Reqd
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE
Can unique index be specified=TRUE
; This one maps Alphanumeric to GTT Column type of Long
[Column Type(5) Info - PARADOX 3.X ODBCJT16]
Column Name=AlphaNumeric
Catalog Column Type=AlphaNumeric
Statement to Create Column=MAX LENGTH
Matching Gupta Column Type=6
Maximum Size/Width=255
Precision=Required
Scale=Not Reqd
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE
Can unique index be specified=FALSE
; This one maps Number to Decimal in GTT table.
[Column Type(6) Info - PARADOX 3.X ODBCJT16]
Column Name=Number
Catalog Column Type=Number
Statement to Create Column=
Matching Gupta Column Type=7
Maximum Size/Width=15
Precision=Not Reqd

10-14 Connecting Centura Objects to Databases

DCC.INI file for Paradox 3.x

Scale=Not Reqd
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE
Can unique index be specified=TRUE
; This one maps Number to Float in GTT table.
[Column Type(7) Info - PARADOX 3.X ODBCJT16]
Column Name=Number
Catalog Column Type=Number
Statement to Create Column=
Matching Gupta Column Type=3
Maximum Size/Width=15
Precision=Not Reqd
Scale=Not Reqd
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE
Can unique index be specified=TRUE

; This one maps Date type to Datetime in GTT table.


[Column Type(8) Info - PARADOX 3.X ODBCJT16]
Column Name=Date
Catalog Column Type=Date
Statement to Create Column=
Matching Gupta Column Type=10
Maximum Size/Width=10
Precision=Not Reqd
Scale=Not Reqd
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE
Can unique index be specified=TRUE
; This one maps Date type to Time in GTT table.
[Column Type(9) Info - PARADOX 3.X ODBCJT16]
Column Name=Date
Catalog Column Type=Date
Statement to Create Column=
Matching Gupta Column Type=9

Connecting Centura Objects to Databases10-15

Chapter

10

Certifying ODBC Drivers

Maximum Size/Width=10
Precision=Not Reqd
Scale=Not Reqd
Maximum Scale=
Alternate Column Type=
Can this Column be NULL?=TRUE
Alternate Long Column Description=
Can NULL be specified in DDL?=TRUE
Can unique index be specified=TRUE

10-16 Connecting Centura Objects to Databases

Glossary
Connecting Centura Objects to Databases
bind variableA variable that associates data to an SQL statement at runtime. You
can use bind variables in the VALUES clause of an INSERT statement, in a
WHERE clause, or in the SET clause of an UPDATE statement.
commitThe act of making permanent pending changes against a database.
cursorA work space in memory that is used for processing an SQL statement. This
work space contains the return code, number of rows, error position, number of
select list items, number of program variables, rollback flag, and the command
result. A cursor is part of a SQL handle. Alternatively, a pointer to a row in a
result set.
DCCDatabase Connectivity Configuration.
DDLSQL statements that define and alter database structures, such as tables,
views, and indexes. Example statements are CREATE TABLE and DROP
INDEX.
DMLSQL statements that add, delete, change, or retrieve data from the database,
such as INSERT, DELETE, UPDATE, or SELECT.
Data Definition Languagesee DDL.
Data Manipulation Languagesee DML.
dirty readA read of a value that was never committed to the database. For example,
transaction A changes one or more column values in a row. Transaction B reads
the same row, after which transaction A rolls back its changes. Transaction B has
now performed a dirty read, because it read values that (from a transactionoriented point of view) never existed.

Connecting Centura Objects to Databases

Glossary-1

Glossary

nonrepeatable readThe reading of data from a given row such that the values read
are not guaranteed to be always the same. For example, transaction A reads a
row, then transaction B either updates or deletes the row. Transaction A cannot
now repeat the read of that row and get the same results; either the values are
different or the row no longer exists.
phantom rowA row which appears in between two executions of the same
SELECT statement. For example, transaction A performs a SELECT on a table.
Based on the selection criteria in the SELECT statement, the database server
returns a set of rows to A. Transaction B inserts one or more new rows into the
same table with values that happen to match the selection criteria of the SELECT
statement used by A. If transaction A re-executes the same SELECT statement, it
obtains a different set of rows than it did the first time; the new rows are phantom
rows.
rollbackThe act of undoing pending changes against a database.
SALSee Scalable Application Language.
Scalable Application LanguageAn object-oriented language for writing Centura
SQLWindows/32 applications.
SQL handleA program variable that identifies a connection context to a database.
Multiple SQL handles can share the same connection to a database. It is often
true that an action performed on any one of those handles actually affects all the
handles sharing the same connection. See also cursor.
SQLRouterA software library that maps between the actions and data types of a
Centura SQLWindows/32 application and the actions and data types of a target
database or data source.
transactionA logical unit of work whose elements (changes either to database data
or to database data structures) can be potentially applied to a database. The
elements of a transaction are either all applied to the database or else all
discardedthe elements of a transaction constitute an indivisible unit.

Glossary-2 Connecting Centura Objects to Databases

Index
Symbols
_BIN2HEX_ 6-16
_HEX_ 6-16

A
ABS 3-2
Access 95
connecting to 8- 2, 8- 3
ACOS 3-2
ADD ROWIDS 3-4
ALTER FRAGMENT 3-4
array fetching 5-5
ASIN 3-2
ATAN 3-2
ATAN2 3-2
audience for this book x
autocommit 1-31-5, 3-2, 4-2, 5-2, 6-2
CCP and 1-4
defined 1-3
locks and 1-3
turning off 1-5

B
backend
cursors 1-8
result sets 1-8
backend cursors. See also scrollable cursors
BEGIN TRANSACTION 6-2
bind variables 6-3
defined 1-5
blank. See space
buffering of data 8- 10
buffrow 3-7, 4-7, 7- 5, 8- 10
bulk execute 5-5

C
CANCEL 6-16
CANCEL ALL 6-16
cascading deletes 3-4
CCP 3-2, 4-2, 5-2, 6-4, 8- 4
commit and 1-7
FERS and 1-8
rollback and 1-8
turning on 1-8
chained transactions 6-2
CHECK EXIST failure 6-16
checkexists 6-16
client/server

described 1-21-3
CLOSE ON END TRANS 6-4
closecursorateof 6-17
comdll 3-8, 4-8, 5-6, 6-17, 7- 6, 8- 11
search order for 1-61-7
commit
DDL versus DML 1-10
scope of 1-4
committed read 3-5
COMPUTE clause 6-4
concurrency
in SAL code 1-5
connecting
steps to follow 2-2
what to check first 2-22-3
connections
errors that arise with 2-13
how to test 2-6
problems with 2-10
search order for 1-61-7
to a database 1-9
connectivity parameters 1-6
include file for 1-6
COS 3-2
CREATE INDEX 3-4
cursor
as synonym for SQL handle 1-10
cursor context preservation. See CCP
cursor stability 3-5

D
database
how to specify using SAL 2-10
Database Connectivity Configuration. See DCC
databases supported ix
DB2
connecting to x
DB2/400
connecting to 8- 2, 8- 3
dBASE
connecting to 8- 2
DBP_* parameters 1-6
DBP_AUTOCOMMIT 1-6
DBP_BRAND 1-6
DBP_LOCKWAITTIMEOUT 1-6, 6-20
DBP_PRESERVE 1-6
DBP_ROLLBACKONTIMEOUT 1-6
DBP_VERSION 1-6

Connecting CENTURA Objects to Databases

Index-1

Index

DCC
column data types 10-6
deploying an ODBC driver 10-9
example file for Paradox 3.x 10-1010-16
generating a new DCC.INI file 10-4
how to certify a driver 10-8
introduced 10-2
mapping column types 10-9
prerequisites to using 10-2
sample GetTypeInfo output 10-3
what to do before certifying 10-4
defconnect 3-8
deferred parsing 5-8
dirty read 3-5
introduced 1-13
DROP ROWIDS 3-4
dynamic PL/SQL 5-3

E
empty string
distinguishing from NULL and space 1-15
introduced 1-15
empty strings 3-4, 4-4, 5-4, 6-6
enablemultipleconnections 6-18
error codes 8- 68- 10
error messages
how to resolve 2-13
EXP 3-2

F
FERS
deleting temporary files 1-9
introduced 1-8
positioned updates and 1-9
releasing shared locks 1-9
SELECT FOR UPDATE with 1-9
fetchrow 5-6, 6-18
FOR BROWSE 6-14
FOR LONG UPDATE 6-16
FRAGMENT BY 3-4
FRAGMENT BY EXPRESSION 3-4
front-end result sets. See FERS

G
GET DIAGNOSTICS 3-4

H
handle. See SQL handle

Index-2 Connecting CENTURA Objects to Databases

I
ILogin.exe 2-2
IMAGE data
introduced 1-11
writing 1-11
Informix
ANSI mode 3-2
arithmetic functions 3-2
autocommit 3-2
buffrow 3-7
CCP 3-2
comdll 3-8
cursors 3-3
data distribution 3-5
data type mapping 3-3
DBINFO 3-5
DDL statement support 3-4
default mode 3-2
defconnect 3-8
empty strings 3-4
isolation levels 3-5
lock time-out 3-5
log 3-8, 5-7, 7- 6
longbuffer 3-9, 7- 7
NLS 3-5
positioned updates 3-6
remotedbname 3-10, 7- 7
SE database and VARCHAR 3-4
SET statements 3-6
SQL.INI keywords ??3-12, ??7- 9
stored procedures 3-123-13, 7- 97- 11
creating 3-12, 7- 10
dropping 3-13, 7- 11
executing 3-12, 7- 10
fully qualifying 3-13
TRIM 3-5
yieldonservercall 3-11
INMESSAGE 4-7
isolation levels 3-5, 4-4, 5-4, 6-13
concurrency and 1-12
consistency and 1-12
example of how to set 1-14
how defined 1-13
introduced 1-12

lock time-out 3-5, 4-5, 5-5, 8- 10


how to enable 1-15

introduced 1-15
locktimeout 6-19
log 3-8, 4-8, 5-7, 6-20, 8- 11
LOG10 3-2
LOGN 3-2
LONG data
buffer size for 5-8
size of buffer for 6-21, 8- 12
truncation of 2-11
writing and retrieving 6-376-40
longbuffer 3-9, 4-9, 5-8, 6-21, 8- 12

M
Microsoft SQL Server
autocommit 4-2
buffrow 4-7
CCP 4-2
comdll 4-8
data type mapping 4-2
empty strings 4-4
IDENTITY column type 4-4
isolation levels 4-4
lock time-out 4-5
log 4-8
longbuffer 4-9
native connectivity 4-5
ODBC API level 4-5
odbctrace 4-10
odbctracefile 4-10
positioned updates 4-6
stored procedures and 4-6
result set mode 4-6
SET statement 4-6
SQL grammar level 4-5
SQL.INI keywords 4-74-10
SqlDirectoryByName 4-7
stored procedures 4-114-20
creating 4-11
deleting 4-12
error codes for 4-13
example code 4-13
executing 4-12
restrictions on 4-19
result set mode and 4-12
using keywords as table or column names 4-5
MOD 3-2
multi-database application
autocommit 9- 28

basic approaches 9- 2
concurrency and consistency 9- 129- 15
configuring 9- 4
connecting to the servers 9- 5
deleting the tables 9- 6
description 9- 3
design issues 9- 99- 25
details form 9- 7
displaying table data 9- 6, 9- 199- 20
dynamic binding 9- 23
dynamic data type binding 9- 26
dynamic table windows management 9- 25
how it connects 9- 9
how to run 9- 49- 9
implementation details 9- 259- 29
INVOICE transaction 9- 23
isolation levels 9- 139- 15
isolation levels and Oracle 9- 27
key columns 9- 21
locking strategies 9- 12
logging in to the servers 9- 6
modifying autocommit 9- 8
modifying isolation levels 9- 8
populating the tables 9- 6
replicating table schemas and data 9- 159- 19
schema and location of tables 9- 3
setting autocommit 9- 11
starting 9- 5
transaction processing 9- 219- 23
updating table data 9- 25
multithreaded execution, lack of 1-5

N
NLS 3-5
nodefparse 5-8
nonrepeatable read
introduced 1-13
NULL
distinguishing from empty string and space 1-15
introduced 1-15

O
ODBC
buffrow 8- 10
CCP 8- 4
comdll 8- 11
configuring a data source 2-3
connecting to data sources 8- 2

Connecting CENTURA Objects to Databases

Index-3

Index

connecting to SQLBase 8- 3
data type mapping 8- 5
error code mapping 8- 6
error processing 8- 5
lock time-out 8- 10
log 8- 11
logging API calls 2-11
longbuffer 8- 12
odbctrace 8- 13
odbctracefile 8- 13
SQL.INI keywords ??8- 13
stored procedures 8- 14
trace file for API calls 8- 13
tracing API calls 4-10, 8- 13
transactions, disconnects, and exits 8- 15
odbctrace 4-10, 8- 13
odbctracefile 4-10, 8- 13
OdrExecuteProc 4-14
OdrGetNextResults 4-15
OdrGetReturnStatus 4-16
OdrPrepareNextResults 4-18
OdrPrepareProc 4-17
Oracle
accessing the SYS account 2-9
array fetching 5-5
autocommit 5-2
bulk execute 5-5
CCP 5-2
comdll 5-6
connecting using ODBC 8- 2
connection prerequisites 2-82-9
data type mapping 5-3
deferred parsing 5-8
dynamic PL/SQL 5-3
empty strings 5-4
fetchrow 5-6
isolation levels 5-4
lock time-out 5-5
longbuffer 5-8
modifying the Windows Registry 2-8
nodefparse 5-8
optimizing message traffic 5-5
positioned updates 5-5
remotedbname 4-10, 5-9, 8- 13
result set mode 5-5
SQL.INI keywords ??5-11
SqlPLSQLCommand 5-12
stored procedures 5-115-15

Index-4 Connecting CENTURA Objects to Databases

data types supported 5-11


dynamic arrays 5-14
example 5-135-14
overloading 5-12
substitute 5-10
transactions, disconnects, and exits 5-15
view scripts to access stored procedures 2-9
view scripts to access tables 2-8
writing RAW data 5-165-17

P
parameters
autocommit 1-6
cursor context preservation 1-6
database vendor 1-6
database version 1-6
lock wait timeout 1-6
rollback on timeout 1-6
phantom row
introduced 1-13
positioned updates 3-6, 4-6, 5-5
coding 1-17
example code 1-18
introduced 1-17
POW 3-2
prepared statements
re-executing 3-2, 4-2, 5-2, 6-4, 8- 4

R
RAISERROR 6-7
RAW data
writing 5-165-17
READ ONLY 3-3
release notes
what they contain 2-11
remotedbname 3-10, 4-10, 5-9, 6-21, 8- 13
search order for 1-61-7
repeatable read 3-5
RESTRICT/CASCADE 3-4
result set mode 4-6, 5-5
default value 1-19
how to turn off 1-19
how to turn on 1-19
implications of 1-19
introduced 1-19
ROOT 3-2

sample applications 2-14??


scrollable cursors 4-6
defined 1-8
SET
DATASKIP 3-6
PDQPRIORITY 3-6
TRANSACTION 3-6
SIN 3-2
space
distinguishing from NULL and empty string 1-15
introduced 1-16
SQL handles
introduced 1-9
maximum number of 1-10
transaction scope and 1-10
using more than one 1-10
SQL*Plus 2-2
SQL.INI file 2-42-6
editing 2-6
multiple copies of 2-4
search path for 2-4
structure of 2-5
when it is read 2-6
SQL_TXN_READ_COMMITTED 4-4
SQL_TXN_READ_UNCOMMITTED 4-4
SQL_TXN_REPEATABLE_READ 4-4
SQL_TXN_SERIALIZABLE 4-4
SQLBase
connecting to x
connecting to using ODBC 8- 3
SqlConnect 1-9
SqlDirectoryByName 4-7
SQLGateway x
SqlGetParameter parameters 1-6
SqlGetResultSetCount 1-9
SQLHost x
SQLHost for Visual Basic x
SqlLockWaitTimeout 6-20
SQLNetwork for DB2 x
SQLNWKCN.APL 1-6
SqlPLSQLCommand 5-12
SQLRouters
listing of 1-2
SqlSetIsolationLevel 1-14
SqlSetLongBindDatatype 1-11
SqlSetParameter parameters 1-6

SqlSetParameterAll

example usage of 1-6


SQLTalk
testing connection with 2-7
SQLWNTM.DLL 2-12
SQRT 3-2
stored procedures 8- 14
introduced 1-21
substitute 5-10, 6-22
sybapplicationname 6-23
Sybase. See System 10
sybautocommit 6-23
SybExecuteProc 6-29
SybExecuteProcEx 6-30
SybGetClientMsg 6-8
SybGetClientMsgCount 6-8
SybGetNextClientMsg 6-9
SybGetNextResults 6-31
SybGetNextServerMsg 6-11
SybGetReturnStatus 6-32
SybGetServerMsg 6-10
SybGetServerMsgCount 6-10
sybmaxmessages 6-24
SybPrepareNextResults 6-34
SybPrepareProc 6-33
SYBPRIVS.EXE 2-7
sybtracefile 6-25
sybworkstationname 6-25
SybWriteText 6-39
System 10
asynchronous processing 6-26
autocommit 6-2, 6-23
bind variables 6-3
CANCEL 6-28
CCP 6-4
chained transactions 6-2
checkexists 6-16
client application name 6-23
client machine name 6-25
Client-Library trace facility 6-25
close cursor at end-of-fetch 6-17
closecursorateof 6-17
comdll 6-17
COMPUTE clause 6-4
connection prerequisites 2-7
data type mapping 6-56-6
empty strings 6-6
enablemultipleconnections 6-18
error 30041 6-28

Connecting CENTURA Objects to Databases

Index-5

Index

error precedence 6-7


error processing 6-66-12
fetchrow 6-18
getting new connections 6-18
handles and connections 6-13
IMAGE data
buffer size for 6-38
writing and retrieving 6-376-40
isolation levels 6-13
locktimeout 6-19
log 6-20
login wait 6-19
longbuffer 6-21
max rows per fetch 6-18
multiple connections 6-12
positioned updates 6-146-15
fetchrow and 6-15
RAISERROR 6-7
releasing locks 6-16
remotedbname 6-21
reserved strings 6-16
retrieving messages 6-86-12
saving messages 6-24
specify database name 6-21
SQL.INI keywords 6-166-27
statement execution wait 6-19
stored procedures 6-27??
cancelling result sets 6-28
retrieving output arguments 6-35
using cursors 6-27
substitute 6-22
sybapplicationname 6-23
sybautocommit 6-23
SybExecuteProc 6-29
SybExecuteProcEx 6-30
SybGetNextResults 6-31
SybGetReturnStatus 6-32
sybmaxmessages 6-24
SybPrepareNextResults 6-34
SybPrepareProc 6-33
sybtracefile 6-25
sybworkstationname 6-25
TEXT data
buffer size for 6-38
writing and retrieving 6-376-40
timestamp data type 6-5
transactions, disconnects, and exits 6-36
yieldonservercall 6-26

Index-6 Connecting CENTURA Objects to Databases

System 11. See System 10

T
TAN 3-2
technical support
contacting 2-12
TEXT data
automatic conversion with LONG STRING 1-12
transactions
introduced 1-22
troubleshooting problems 2-102-13
typographical conventions xi

V
view scripts
how to run 2-9
VIEWFAST.ORA 2-8
VIEWSLOW.ORA 2-8

WITH CURSOR 6-16, 6-28


WITH HOLD 3-2
WITH OPTIMIZATION 3-3
workspace limit exceeded error 6-38

yieldonservercall 3-11, 6-26

Connecting CENTURA Objects to Databases

Index-7