* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download Embedded SQL Developer`s Guide
Survey
Document related concepts
Relational algebra wikipedia , lookup
Concurrency control wikipedia , lookup
Tandem Computers wikipedia , lookup
Entity–attribute–value model wikipedia , lookup
Functional Database Model wikipedia , lookup
Microsoft Jet Database Engine wikipedia , lookup
Extensible Storage Engine wikipedia , lookup
Clusterpoint wikipedia , lookup
Microsoft SQL Server wikipedia , lookup
Open Database Connectivity wikipedia , lookup
Database model wikipedia , lookup
Transcript
c-treeSQL Embedded SQL Developer's Guide c-treeSQL Embedded SQL Developer's Guide Copyright Notice Copyright © 1992-2017 FairCom Corporation. All rights reserved. No part of this publication may be stored in a retrieval system, or transmitted in any form or by any means, electronic, mechanical, photocopying, recording or otherwise without the prior written permission of FairCom Corporation. Printed in the United States of America. Information in this document is subject to change without notice. Trademarks c-treeACE, c-treeRTG, c-treeAMS, c-tree Plus, c-tree, r-tree, FairCom and FairCom’s circular disc logo are trademarks of FairCom, registered in the United States and other countries. The following are third-party trademarks: AMD and AMD Opteron are trademarks of Advanced Micro Devices, Inc. Macintosh, Mac, Mac OS, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. Embarcadero, the Embarcadero Technologies logos and all other Embarcadero Technologies product or service names are trademarks, service marks, and/or registered trademarks of Embarcadero Technologies, Inc. and are protected by the laws of the United States and other countries. Business Objects and the Business Objects logo, BusinessObjects, Crystal Reports, Crystal Decisions, Web Intelligence, Xcelsius, and other Business Objects products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of Business Objects Software Ltd. Business Objects is an SAP company. HP and HP-UX are registered trademarks of the Hewlett-Packard Company. AIX, IBM, POWER6, POWER7, and pSeries are trademarks or registered trademarks of International Business Machines Corporation in the United States, other countries, or both. Intel, Intel Core, Itanium, Pentium and Xeon are trademarks or registered trademarks of Intel Corporation or its subsidiaries in the United States and other countries. Microsoft, the .NET logo, the Windows logo, Access, Excel, SQL Server, Visual Basic, Visual C++, Visual C#, Visual Studio, Windows, Windows Server, and Windows Vista are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. Novell and SUSE are registered trademarks of Novell, Inc. in the United States and other countries. Oracle and Java are registered trademarks of Oracle and/or its affiliates. QNX and Neutrino are registered trademarks of QNX Software Systems Ltd. in certain jurisdictions. CentOS, Red Hat, and the Shadow Man logo are registered trademarks of Red Hat, Inc. in the United States and other countries, used with permission. UNIX and UnixWare are registered trademarks of The Open Group in the United States and other countries. Linux is a trademark of Linus Torvalds in the United States, other countries, or both. Python and PyCon are trademarks or registered trademarks of the Python Software Foundation. OpenServer is a trademark or registered trademark of Xinuos, Inc. in the U.S.A. and other countries. Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the United States and other countries. Btrieve is a registered trademark of Actian Corporation. ACUCOBOL-GT, MICRO FOCUS, RM/COBOL, and Visual COBOL are trademarks or registered trademarks of Micro Focus (IP) Limited or its subsidiaries in the United Kingdom, United States and other countries. isCOBOL and Veryant are trademarks or registered trademarks of Veryant in the United States and other countries. All other trademarks, trade names, company names, product names, and registered trademarks are the property of their respective holders. Portions Copyright © 1991-2016 Unicode, Inc. All rights reserved. Portions Copyright © 1998-2016 The OpenSSL Project. All rights reserved. This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/). Portions Copyright © 1995-1998 Eric Young ([email protected]). All rights reserved. This product includes cryptographic software written by Eric Young ([email protected]). This product includes software written by Tim Hudson ([email protected]). Portions © 1987-2017 Dharma Systems, Inc. All rights reserved. This software or web site utilizes or contains material that is © 1994-2007 DUNDAS DATA VISUALIZATION, INC. and its licensors, all rights reserved. Portions Copyright © 1995-2013 Jean-loup Gailly and Mark Adler. 4/27/2017 Contents 1. Introduction ......................................................................................................... 1 1.1 Overview ............................................................................................................... 1 1.2 The Relational View of Data .................................................................................. 1 1.3 Using c-treeSQL in a Host Language .................................................................... 2 1.4 Advantages of Using ESQL ................................................................................... 3 1.5 Components of an ESQL Application .................................................................... 3 1.6 Developing an Embedded SQL Application .......................................................... 3 2. Quick Tour ........................................................................................................... 4 2.1 Introductory Tutorial .............................................................................................. 5 Init 6 Define .................................................................................................................................. 7 Manage ............................................................................................................................... 8 Done .................................................................................................................................. 11 Additional Resources ........................................................................................................ 12 2.2 Relationships ....................................................................................................... 13 Init 15 Define ................................................................................................................................ 16 Manage ............................................................................................................................. 19 Done .................................................................................................................................. 24 Additional Resources ........................................................................................................ 25 2.3 Record/Row Locking ........................................................................................... 26 Init 27 Define ................................................................................................................................ 28 Manage ............................................................................................................................. 29 Done .................................................................................................................................. 32 Additional Resources ........................................................................................................ 33 2.4 Transaction Processing ....................................................................................... 34 Init 35 Define ................................................................................................................................ 36 Manage ............................................................................................................................. 39 Done .................................................................................................................................. 44 Additional Resources ........................................................................................................ 45 3. Using the esqlc Command ............................................................................... 46 3.1 Introduction .......................................................................................................... 46 3.2 esqlc Command Line Reference ......................................................................... 46 All Rights Reserved iv www.faircom.com Introduction 3.3 esqlc Command Examples .................................................................................. 48 Precompiling, Compiling, and Linking Multiple Files with esqlc ........................................ 48 Issuing Separate Commands for Precompiling, Compiling, and Linking .......................... 49 Mixing Precompiler/Compiler Options in the esqlc Command ......................................... 49 4. ESQL Program Structure .................................................................................. 50 4.1 Introduction .......................................................................................................... 50 4.2 ESQL Declare Statements .................................................................................. 50 Host Variables and their Usage ........................................................................................ 51 Indicator Variables and their Usage .................................................................................. 51 Limitations of the Declare Section .................................................................................... 53 4.3 ESQL Executable Statements ............................................................................. 54 Types of Executable Statements ...................................................................................... 54 4.4 The c-treeSQL Communications Area................................................................. 54 The COMMIT WORK and ROLLBACK WORK Statements ............................................. 55 5. ESQL Application Development....................................................................... 57 5.1 Introduction .......................................................................................................... 57 5.2 Guidelines ........................................................................................................... 57 5.3 Using c-treeSQL for Computation and Conversion ............................................. 58 5.4 Using c-treeSQL for Condition Evaluation ........................................................... 59 5.5 Using Indicator Variables .................................................................................... 60 5.6 Using Scalar Functions ....................................................................................... 60 5.7 Using Static and Dynamic Statements ................................................................ 61 6. Connection Management in ESQL ................................................................... 62 6.1 Introduction .......................................................................................................... 62 6.2 The CONNECT Statement .................................................................................. 62 Connection Using a Connection Name ............................................................................. 62 Connection by Default ....................................................................................................... 63 Connection to a Remote Database ................................................................................... 63 6.3 The SET CONNECTION Statement .................................................................... 64 6.4 The DISCONNECT Statement ............................................................................ 64 7. c-treeSQL Data Definition Statements............................................................. 66 7.1 Introduction .......................................................................................................... 66 7.2 Creating/Dropping Tables ................................................................................... 66 Creating Tables ................................................................................................................. 66 Dropping Tables ................................................................................................................ 67 All Rights Reserved v www.faircom.com Introduction 7.3 Creating/Dropping Indices ................................................................................... 68 Creating Indices ................................................................................................................ 68 Dropping Indices ............................................................................................................... 69 7.4 Creating/Dropping Views ..................................................................................... 69 Creating Views .................................................................................................................. 69 Dropping Views ................................................................................................................. 70 7.5 Integrity Constraints ............................................................................................ 71 Need for Integrity Constraints ........................................................................................... 71 Types of Integrity Constraints ........................................................................................... 71 Check Constraints ............................................................................................................. 71 7.6 Primary Keys ....................................................................................................... 73 Column-Level Primary Key Constraint .............................................................................. 73 Table-Level Primary Key Constraint ................................................................................. 74 7.7 Candidate Keys ................................................................................................... 74 Column-Level Candidate Key Constraint .......................................................................... 75 Table-Level Candidate Key Constraint ............................................................................. 75 7.8 Referential Constraints ........................................................................................ 75 Column-Level Foreign Key Constraint .............................................................................. 76 Table-Level Foreign Key Constraint ................................................................................. 77 7.9 Handling Cycles in Referential Integrity .............................................................. 77 Creation of Tables in Cycles ............................................................................................. 78 Insertion of Rows in Cycles ............................................................................................... 78 Dropping the Tables in Cycles .......................................................................................... 78 7.10 DDL Statements in Long Running Transactions ................................................. 79 8. c-treeSQL Data Manipulation Statements ....................................................... 80 8.1 Introduction .......................................................................................................... 80 8.2 Using DML Statements ....................................................................................... 80 Inserting Rows into a Table .............................................................................................. 80 Deleting Rows from a Table .............................................................................................. 82 Updating Rows in a Table ................................................................................................. 83 8.3 Input Host Variables in DML Statements............................................................. 84 9. Query Statements .............................................................................................. 85 9.1 Introduction .......................................................................................................... 85 9.2 Elements of a Query ............................................................................................ 85 Input Host Variables in Query Statements ........................................................................ 86 Output Host Variables in Query Statements ..................................................................... 86 9.3 Queries Returning a Single Row ......................................................................... 86 9.4 Queries Returning Multiple Rows ........................................................................ 87 All Rights Reserved vi www.faircom.com Introduction Introduction to Cursors ...................................................................................................... 87 Associating a Cursor with a Query.................................................................................... 88 Opening a Cursor .............................................................................................................. 88 Retrieving Rows Using a Cursor ....................................................................................... 89 Closing a Cursor ............................................................................................................... 90 Deleting or Updating the Current Row .............................................................................. 90 Array Fetches: Retrieving Multiple Rows with One FETCH Statement .......................... 91 10. NULL Value Handling in ESQL ......................................................................... 94 10.1 Introduction .......................................................................................................... 94 10.2 Inserting NULL Values ........................................................................................ 94 Inserting NULL Values by Default ..................................................................................... 94 Using the NULL Keyword to Insert NULL Values ............................................................. 95 Using Indicator Variables to Insert NULL Values .............................................................. 95 10.3 Updating with NULL Values ................................................................................ 96 10.4 Retrieving NULL Values ...................................................................................... 97 Using Indicator Variables to Retrieve NULL Values ......................................................... 97 Using the Scalar Function NVL to Retrieve NULL values................................................. 97 10.5 Using NULL Values in Expressions ..................................................................... 98 10.6 Using NULL Values in the WHERE Clause ......................................................... 98 10.7 Using NULL Values in GROUP BY Clause ......................................................... 99 10.8 Using NULL Values in ORDER BY Clause ......................................................... 99 10.9 Using NULL Values in Scalar Functions.............................................................. 99 10.10 Using NULL Values in Aggregate Functions ....................................................... 99 11. Error Handling in ESQL .................................................................................. 100 11.1 Introduction ........................................................................................................ 100 11.2 Using SQLCA for Error Handling ....................................................................... 100 Fields of the SQLCA ....................................................................................................... 100 Using SQLCA for Checking Errors.................................................................................. 102 Using SQLCA for Checking Warnings ............................................................................ 104 Using the WHENEVER Statement for Error Handling .................................................... 105 Handling the SQL_NOT_FOUND Condition with WHENEVER ..................................... 107 Using WHENEVER Along With Explicit Error Checking ................................................. 107 Using Indicator Variables for Error Handling .................................................................. 107 12. Dynamic SQL Management in ESQL ............................................................. 109 12.1 Introduction ........................................................................................................ 109 12.2 Overview ........................................................................................................... 109 12.3 Preparing Statements ........................................................................................ 110 All Rights Reserved vii www.faircom.com Introduction Non-SELECT Statements ............................................................................................... 111 SELECT Statements ....................................................................................................... 112 12.4 ESQL Descriptor Statement .............................................................................. 114 ALLOCATE DESCRIPTOR ............................................................................................. 114 DEALLOCATE DESCRIPTOR........................................................................................ 115 GET DESCRIPTOR ........................................................................................................ 115 SET DESCRIPTOR......................................................................................................... 117 12.5 The c-treeSQL Descriptor Area - SQLDA.......................................................... 118 The Components of SQLDA ........................................................................................... 119 The DESCRIBE Statement ............................................................................................. 127 Using SQLDA for Input Variables ................................................................................... 128 Using SQLDA for Output Variables................................................................................. 129 13. Transaction Management in ESQL ................................................................ 131 13.1 Introduction ........................................................................................................ 131 13.2 Transaction Overview ........................................................................................ 131 Starting a Transaction ..................................................................................................... 131 Transaction Isolation Levels ........................................................................................... 134 Locking and Transactions ............................................................................................... 135 Abnormal Termination of an ESQL Application Program ............................................... 136 14. Data Type Handling in ESQL .......................................................................... 138 14.1 Introduction ........................................................................................................ 138 14.2 Data Type Descriptions ..................................................................................... 138 CHARACTER Data Type ................................................................................................ 138 SMALLINT Data Type ..................................................................................................... 139 INTEGER Data Type....................................................................................................... 139 BIGINT ............................................................................................................................ 140 REAL Data Type ............................................................................................................. 140 FLOAT Data Type ........................................................................................................... 140 DOUBLE PRECISION..................................................................................................... 141 NUMERIC or DECIMAL Data Type ................................................................................ 141 DATE Data Type ............................................................................................................. 145 TIME Data Type .............................................................................................................. 145 TIMESTAMP ................................................................................................................... 146 BIT 146 BINARY [(length)]............................................................................................................ 146 LVARBINARY | LONG VARBINARY .............................................................................. 146 Data Conversion ............................................................................................................. 146 Data Comparison ............................................................................................................ 150 15. ESQL Reference .............................................................................................. 153 All Rights Reserved viii www.faircom.com Introduction 15.1 Introduction ........................................................................................................ 153 15.2 BEGIN-END DECLARE SECTION.................................................................... 153 15.3 CLOSE .............................................................................................................. 155 15.4 DECLARE CURSOR ......................................................................................... 155 15.5 DESCRIBE ........................................................................................................ 156 15.6 END DECLARE SECTION ................................................................................ 159 15.7 EXEC SQL ........................................................................................................ 159 15.8 EXECUTE ......................................................................................................... 159 15.9 EXECUTE IMMEDIATE .................................................................................... 161 15.10 FETCH .............................................................................................................. 161 15.11 OPEN ................................................................................................................ 163 15.12 PREPARE ......................................................................................................... 164 15.13 Query Expressions ............................................................................................ 166 15.14 Search Conditions ............................................................................................. 166 LIKE Predicate ................................................................................................................ 166 IN Predicate .................................................................................................................... 167 15.15 Single-Row SELECT Statement ........................................................................ 167 15.16 Type Specifications for Variable and Type Declarations ................................... 169 Database Types .............................................................................................................. 170 Host Language Types ..................................................................................................... 171 Table-Column Types ....................................................................................................... 172 Static Array Types ........................................................................................................... 172 Record Types .................................................................................................................. 174 Table Record Types ........................................................................................................ 174 15.17 WHENEVER ...................................................................................................... 175 15.18 Long Data Type Support ................................................................................... 176 DECLARE Section .......................................................................................................... 177 INSERT Operation .......................................................................................................... 177 SELECT Operation ......................................................................................................... 177 16. Programmatic Interfaces ................................................................................ 178 16.1 Introduction ........................................................................................................ 178 16.2 Programmatic Interfaces ................................................................................... 179 sqld_alloc ........................................................................................................................ 179 sqld_free ......................................................................................................................... 179 dh_alloc_sqlenv .............................................................................................................. 180 dh_compare_data ........................................................................................................... 181 dh_conv_data.................................................................................................................. 182 dh_dayofweek ................................................................................................................. 184 All Rights Reserved ix www.faircom.com Introduction dh_free_sqlenv................................................................................................................ 184 dh_get_curdbhdl ............................................................................................................. 185 dh_get_curtmhdl ............................................................................................................. 185 dh_num_add ................................................................................................................... 186 dh_set_cursor ................................................................................................................. 187 dh_set_ptrs ..................................................................................................................... 188 dh_set_sqlda ................................................................................................................... 189 dh_sqlclose ..................................................................................................................... 190 dh_sqlconnect ................................................................................................................. 191 dh_sqldeclare .................................................................................................................. 192 dh_sqldescribe ................................................................................................................ 193 dh_sqldescribe_param .................................................................................................... 195 dh_sqldisconnect ............................................................................................................ 196 dh_sqlexecute ................................................................................................................. 197 dh_sqlfetch ...................................................................................................................... 198 dh_sqlgetdata.................................................................................................................. 199 dh_sqlopen...................................................................................................................... 200 dh_sqlprepare ................................................................................................................. 202 dh_sqlselect .................................................................................................................... 203 dh_tm_alloc_handle ........................................................................................................ 204 dh_tm_begin_trans ......................................................................................................... 205 dh_tm_end_trans ............................................................................................................ 206 dh_tm_mark_abort .......................................................................................................... 206 dh_sqlputdata.................................................................................................................. 207 dh_sqlallocdesc............................................................................................................... 209 dh_sqlgetsqldaptr ............................................................................................................ 209 dh_sqldeallocdesc........................................................................................................... 210 dh_sqlgetdesc ................................................................................................................. 211 dh_sqlsetdesc ................................................................................................................. 212 dh_sqlgetdiag .................................................................................................................. 213 dh_tm_set_level .............................................................................................................. 214 dh_sqltables .................................................................................................................... 215 dh_sqlcolumns ................................................................................................................ 215 dh_sqlstatistics ................................................................................................................ 215 dh_sqlprimarykeys .......................................................................................................... 215 dh_sqlforeignkeys ........................................................................................................... 215 17. Sample ESQL Programs ................................................................................. 216 17.1 Static Non-Select Statements ........................................................................... 216 Compiling and Running ................................................................................................... 216 Program Source Code .................................................................................................... 216 17.2 Static SELECT Statements ............................................................................... 218 Compiling and Running ................................................................................................... 218 All Rights Reserved x www.faircom.com Introduction Program Source Code .................................................................................................... 218 17.3 Dynamic Non-SELECT Statements................................................................... 220 Compiling and Running ................................................................................................... 220 Program Source Code .................................................................................................... 221 17.4 Dynamic SELECT Statements .......................................................................... 223 Compiling and Running ................................................................................................... 223 Program Source code ..................................................................................................... 223 17.5 Long Data Type Support ................................................................................... 226 Sample ESQLC Program for lvarchar Data Type ........................................................... 226 Sample ESQLC Program for lvarbinary Data Type ........................................................ 230 18. Glossary ........................................................................................................... 234 19. Index ................................................................................................................. 239 All Rights Reserved xi www.faircom.com FairCom Typographical Conventions Before you begin using this guide, be sure to review the relevant terms and typographical conventions used in the documentation. The following formatted items identify special information. Formatting convention Bold CAPITALS Type of Information Used to emphasize a point or for variable expressions such as parameters Names of keys on the keyboard. For example, SHIFT, CTRL, or ALT+F4 FairCom Terminology FairCom technology term FunctionName() c-treeACE Function name Parameter Code Example utility filename CONFIGURATION KEYWORD CTREE_ERR c-treeACE Function Parameter Code example or Command line usage c-treeACE executable or utility c-treeACE file or path name c-treeACE Configuration Keyword c-treeACE Error Code All Rights Reserved xiii www.faircom.com 1. Introduction 1.1 Overview This chapter gives an introduction to Embedded c-treeSQL (ESQL) and discusses: The concept of embedding c-treeSQL statements in a host language The advantages of using ESQL The components of an ESQL program An introduction to the ESQL precompiler 1.2 The Relational View of Data A relational database gives a perception of data as a collection of tables (also called relations). Each table is an unordered collection of rows (also called tuples or records). Each row in a table is a collection of column values. Views are virtual tables derived from the real tables. Views are virtual tables because when a view is created, the view data is not derived and stored in the database. Instead, just the view definition is stored in the database. Once a view is created, it can be used in the same way as using a table, for accessing the database. A table column can optionally have an index associated with it. An index can be thought of as a list of pointers to the rows of a table, ordered based on the values of the associated column. Indices are created only for performance improvement. SQL (Structured Query Language) is the most popular language for accessing relational databases. Commands in SQL specify what is to be done and not how it is to be done, leaving all the details of query processing to the language implementation. All these have made SQL the de facto standard in the relational database world. Most of the SQL implementations provide two types of interfaces for accessing the database. The first interface is the Embedded SQL Interface. This interface supports embedding of SQL statements in a third generation programming language like C or COBOL. The second interface is the Interactive SQL Facility which enables ad hoc queries to be performed on the database in an interactive fashion. In addition to the language support for querying the database, SQL also supports constructs for handling transactions. A transaction is a sequence of operations on the database that has the properties of being atomic and durable. Atomicity refers to the property that either all the operations in a transaction are done (if the transaction is committed) or none are done (if the All Rights Reserved 1 www.faircom.com Introduction transaction is rolled back). Durability refers to the property that once a transaction is committed, the changes done by the transaction are permanent. 1.3 Using c-treeSQL in a Host Language The c-treeSQL data language is a non-procedural language that uses SQL statements for defining, manipulating, and controlling data in a relational database. The ESQL tool gives you the ability to embed c-treeSQL statements in a host language program. Embedding c-treeSQL statements in a procedural language program lets you take advantage of the flow-control and other features of the host language as well as the standardized query capabilities of c-treeSQL. ESQL supports C language host programs. It provides a precompiler, esqlc, that translates each embedded SQL statements in a host program to the equivalent C calls to functions in the c-treeSQL application programming interface (API). The following example shows a brief C code fragment with embedded SQL statements. Note that all embedded SQL statements start with the prefix EXEC SQL and end with a semicolon character ( ; ). For more information on EXEC SQL statements, see “EXEC SQL (page 159)”. Note also that, in addition to standard SQL statements, you use EXEC SQL to embed other ESQL constructs in host programs, such as BEGIN DECLARE … END DECLARE blocks. Example ESQL Code EXEC SQL BEGIN DECLARE SECTION ; long order_no_v ; char order_date_v [10] ; char product_v [5] ; long qty_v ; EXEC SQL END DECLARE SECTION ; … /* C code to get values for host variables */ order_no_v = 1001 ; strcpy (order_date_v, "02/02/1993") ; strcpy (product_v, "COG") ; qty_v = 10000 ; printf ("Registering the order…") ; EXEC SQL INSERT INTO orders (order_no, order_date, product, qty) VALUES (:order_no_v, :order_date_v, :product_v, :qty_v) ; All Rights Reserved 2 www.faircom.com Introduction 1.4 Advantages of Using ESQL The advantages of using ESQL as an application development tool are listed below: One of the major advantages of using ESQL is that it allows the application developer to combine the flexibility of a host language and the power of SQL for data access. The ESQL constructs are simple and provide better readability when compared to the API calls. Using the ESQL constructs reduces the source code size and complexity of an application without reducing the implementation flexibility. 1.5 Components of an ESQL Application ESQL constructs fall into the following categories: ESQL declare statements declare variables for use in other ESQL constructs. Such variables are also available for use in host-language constructs. ESQL executable statements result in the execution of instructions on a specified database at runtime. The executable statements are typically standard SQL statements and include Data Manipulation Language (DML) statements, Data Definition Language (DDL) statements and Data Control Language (DCL) statements. See “ESQL Program Structure (page 50)” for more details on ESQL program components. 1.6 Developing an Embedded SQL Application The ESQL precompiler, esqlc, translates SQL statements embedded in a C host program and generates a pure C program. The C program generated by the ESQL precompiler is used to build the application program executable. The general steps involved in building an ESQL program executable are as follows: Write ESQL source-code files. Use the ESQL precompiler, esqlc, to precompile ESQL files and generate corresponding C source files. Use a standard C compiler to generate object files from the C source files. Link the object files the ESQL libraries to generate an executable application. See “Using the esqlc Command” (page 46) for more details on invoking and using esqlc. All Rights Reserved 3 www.faircom.com 2. Quick Tour All Rights Reserved 4 www.faircom.com Quick Tour 2.1 Introductory Tutorial ..\sdk\sql.embedded\tutorials\eSQL_Tutorial1.pc This tutorial will take you through the basic use of the c-treeACE SQL ESQL - Embedded SQL Interface Like all other examples in the c-tree tutorial series, this tutorial simplifies the creation and use of a database into four simple steps: Initialize(), Define(), Manage(), and You’re Done() ! Tutorial #1: Introductory - Simple Single Table We wanted to keep this program as simple as possible. This program does the following: Initialize() - Connects to the c-treeACE Database Engine. Define() - Defines and creates a "customer master" (custmast) table/file. Manage() - Adds a few rows/records; Reads the rows/records back from the database; displays the column/field content; and then deletes the rows/records. Done() - Disconnects from c-treeACE Database Engine. Note our simple mainline: /* * main() * * The main() function implements the concept of "init, define, manage * and you're done…" */ int main(int argc, char* argv[]) { Initialize(); Define(); Manage(); Done(); printf(DH_STRING_LITERAL("\nPress <ENTER> key to exit . . .\n")); getchar(); return(0); } We suggest opening the source code with your own editor. Continue now to review these four steps. All Rights Reserved 5 www.faircom.com Quick Tour Init First we need to open a connection to a database by providing the c-treeACE Database Engine with a user name, password and the database name. Below is the code for Initialize(): /* * Initialize() * * Perform the minimum requirement of logging onto the c-tree Server */ void Initialize(void) { os_printf(DH_STRING_LITERAL("INIT\n")); os_setenv (DH_STRING_LITERAL("DH_USER"), DH_STRING_LITERAL("ADMIN")); os_setenv (DH_STRING_LITERAL("DH_PASSWD"), DH_STRING_LITERAL("ADMIN")); os_setenv (DH_STRING_LITERAL("DB_NAME"), DH_STRING_LITERAL("ctreeSQL")); EXEC SQL CONNECT TO DEFAULT ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } All Rights Reserved 6 www.faircom.com Quick Tour Define The define step is where specific data definitions are established by your application and/or process. This involves defining columns/fields and creating the tables/files with optional indices. Below is the code for Define(): /* * Define() * * Create the table for containing a list of existing customers */ void Define(void) { os_printf(DH_STRING_LITERAL("DEFINE\n")); /* create table */ os_printf(DH_STRING_LITERAL("\tCreate table…\n")); EXEC SQL CREATE TABLE custmast ( cm_custnumb CHAR(4), cm_custzipc CHAR(9), cm_custstat CHAR(2), cm_custrtng CHAR(1), cm_custname VARCHAR(47), cm_custaddr VARCHAR(47), cm_custcity VARCHAR(47) ) ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL COMMIT WORK; } All Rights Reserved 7 www.faircom.com Quick Tour Manage The manage step provides data management functionality for your application and/or process. Below is the code for Manage(): /* * Manage() * * This function performs simple record functions of add, delete and gets */ void Manage(void) { os_printf(DH_STRING_LITERAL("MANAGE\n")); /* delete any existing records */ Delete_Records(); /* populate the table with data */ Add_Records(); /* display contents of table */ Display_Records(); } /* * Add_Records() * * This function adds records to a table from an array of strings */ void Add_Records(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; dh_char_t *data[] = { DH_STRING_LITERAL("('1000','92867','CA','1','Bryan Williams','2999 Regency','Orange')"), DH_STRING_LITERAL("('1001','61434','CT','1','Michael Jordan','13 Main','Harford')"), DH_STRING_LITERAL("('1002','73677','GA','1','Joshua Brown','4356 Cambridge','Atlanta')"), DH_STRING_LITERAL("('1003','10034','MO','1','Keyon Dooling','19771 Park Avenue','Columbia')") }; int i; int nRecords = sizeof(data) / sizeof(data[0]); os_printf(DH_STRING_LITERAL("\tAdd records…\n")); /* add one record at time to table */ for (i = 0; i < nRecords; i++) { os_sprintf (sCommand, DH_STRING_LITERAL("INSERT INTO custmast VALUES %s"), data[i]); All Rights Reserved 8 www.faircom.com Quick Tour EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } EXEC SQL COMMIT WORK; } /* * Delete_Records() * * This function deletes all the records in the table */ void Delete_Records(void) { os_printf(DH_STRING_LITERAL("\tDelete records…\n")); EXEC SQL DELETE FROM custmast ; if (sqlca.sqlcode < 0) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL COMMIT WORK ; } /* * Display_Records() * * This function displays the contents of a table. */ void Display_Records(void) { EXEC SQL BEGIN DECLARE SECTION ; CHAR custnumb[5+1]; CHAR custname[47+1]; EXEC SQL END DECLARE SECTION ; os_printf(DH_STRING_LITERAL("\tDisplay records…")); EXEC SQL DECLARE curs CURSOR FOR SELECT custmast.cm_custnumb, custmast.cm_custname FROM custmast; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL OPEN curs; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL FETCH curs INTO :custnumb, :custname; /* fetch and display each individual record */ while (!sqlca.sqlcode) { os_printf(DH_STRING_LITERAL("\n\t\t%-8s%10s\n"),custnumb, custname); EXEC SQL FETCH curs INTO :custnumb, :custname; } EXEC SQL CLOSE curs ; All Rights Reserved 9 www.faircom.com Quick Tour } All Rights Reserved 10 www.faircom.com Quick Tour Done When an application and/or process has completed operations with the database, it must release resources by disconnecting from the database engine. Below is the code for Done(): /* * Done() * * This function handles the housekeeping of closing connection and * freeing of associated memory */ void Done(void) { os_printf(DH_STRING_LITERAL("DONE\n")); /* disconnect from server */ EXEC SQL DISCONNECT CURRENT ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } All Rights Reserved 11 www.faircom.com Quick Tour Additional Resources We encourage you to explore the additional resources listed here: Complete source code for this tutorial can be found in eSQL_Tutorial1.pc in your installation directory, within the 'sdk\sql.embedded\tutorials' directory for your platform. Example for the Windows platform: C:\FairCom\V11.x.x\win32\sdk\sql.embedded\tutorials\eSQL_Tutorial1.pc. Additional documentation may be found on the FairCom Web site at: www.faircom.com All Rights Reserved 12 www.faircom.com Quick Tour 2.2 Relationships ..\sdk\sql.embedded\tutorials\eSQL_Tutorial2.pc Now we will build some table/file relationships using the c-treeACE SQL ESQL - Embedded SQL Interface This tutorial will advance the concepts introduced in the first tutorial by expanding the number of tables. We will define key columns/fields and create specific indices for each table to form a relational model database. Like all other examples in the c-tree tutorial series, this tutorial simplifies the creation and use of a database into four simple steps: Initialize(), Define(), Manage(), and You’re Done() ! Tutorial #2: Relational Model and Indexing Here we add a bit more complexity, introducing multiple tables, with related indices in order to form a simple "relational" database simulating an Order Entry system. Here is an overview of what will be created: Initialize() - Connects to the c-treeACE Database Engine. Define() - Defines and creates the "custmast", "custordr", "ordritem" and the "itemmast" tables/files with related indices. Manage() database. - Adds some related rows/records to all tables/files. Then queries the Done() - Disconnects from c-treeACE Database Engine. Note our simple mainline: /* * main() * * The main() function implements the concept of "init, define, manage * and you're done…" */ int main(int argc, char* argv[]) { All Rights Reserved 13 www.faircom.com Quick Tour Initialize(); Define(); Manage(); Done(); os_printf(DH_STRING_LITERAL("\nPress <ENTER> key to exit . . .\n")); getchar(); return(0); } We suggest opening the source code with your own editor. Continue now to review these four steps. All Rights Reserved 14 www.faircom.com Quick Tour Init First we need to open a connection to a database by providing the c-treeACE Database Engine with a user name, password and the database name. Below is the code for Initialize(): /* * Initialize() * * Perform the minimum requirement of logging onto the c-tree Server */ void Initialize(void) { os_printf(DH_STRING_LITERAL("INIT\n")); os_setenv (DH_STRING_LITERAL("DH_USER"), DH_STRING_LITERAL("ADMIN")); os_setenv (DH_STRING_LITERAL("DH_PASSWD"), DH_STRING_LITERAL("ADMIN")); os_setenv (DH_STRING_LITERAL("DB_NAME"), DH_STRING_LITERAL("ctreeSQL")); EXEC SQL CONNECT TO DEFAULT ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } All Rights Reserved 15 www.faircom.com Quick Tour Define The define step is where specific data definitions are established by your application and/or process. This involves defining columns/fields and creating the tables/files with optional indices. Below is the code for Define(): /* * Define() * * Create the tables */ void Define(void) { os_printf(DH_STRING_LITERAL("DEFINE\n")); Create_CustomerMaster_Table(); Create_CustomerOrders_Table(); Create_OrderItems_Table(); Create_ItemMaster_Table(); EXEC SQL COMMIT WORK ; } /* * Create_CustomerMaster_Table() * * Create the CustomerMaster */ void Create_CustomerMaster_Table(void) { /* define table CustomerMaster */ os_printf(DH_STRING_LITERAL("\ttable CustomerMaster\n")); EXEC SQL CREATE TABLE custmast ( cm_custnumb CHAR(4), cm_custzipc CHAR(9), cm_custstat CHAR(2), cm_custrtng CHAR(1), cm_custname VARCHAR(47), cm_custaddr VARCHAR(47), cm_custcity VARCHAR(47) ); if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL CREATE UNIQUE INDEX cm_custnumb_idx ON custmast (cm_custnumb) ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } All Rights Reserved 16 www.faircom.com Quick Tour /* * Create_CustomerOrders_Table() * * Create the CustomerOrders */ void Create_CustomerOrders_Table(void) { /* define table CustomerOrders */ os_printf(DH_STRING_LITERAL("\ttable CustomerOrders\n")); EXEC SQL CREATE TABLE custordr ( co_ordrdate DATE, co_promdate DATE, co_ordrnumb CHAR(6), co_custnumb CHAR(4) ) ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL CREATE UNIQUE INDEX co_ordrnumb_idx ON custordr (co_ordrnumb) ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL CREATE INDEX co_custnumb_idx ON custordr (co_custnumb) ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } /* * Create_OrderItems_Table() * * Create the OrderItems */ void Create_OrderItems_Table(void) { /* define table OrderItems */ os_printf(DH_STRING_LITERAL("\ttable OrderItems\n")); EXEC SQL CREATE TABLE ordritem ( oi_sequnumb SMALLINT, oi_quantity SMALLINT, oi_ordrnumb CHAR(6), oi_itemnumb CHAR(5) ) ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL CREATE UNIQUE INDEX oi_ordrnumb_idx ON ordritem (oi_ordrnumb, oi_sequnumb) ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL CREATE INDEX oi_itemnumb_idx ON ordritem (oi_itemnumb) ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } /* * Create_ItemMaster_Table() * All Rights Reserved 17 www.faircom.com Quick Tour * Create the ItemMaster */ void Create_ItemMaster_Table(void) { /* define table ItemMaster */ os_printf(DH_STRING_LITERAL("\ttable ItemMaster\n")); EXEC SQL CREATE TABLE itemmast ( im_itemwght INTEGER, im_itempric MONEY, im_itemnumb CHAR(5), im_itemdesc VARCHAR(47) ) ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL CREATE UNIQUE INDEX im_itemnumb_idx ON itemmast (im_itemnumb) ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } All Rights Reserved 18 www.faircom.com Quick Tour Manage The manage step provides data management functionality for your application and/or process. Below is the code for Manage(): /* * Manage() * * Populates table and perform a simple query * */ void Manage(void) { EXEC SQL BEGIN DECLARE SECTION; CHAR custname[47+1]; FLOAT total; EXEC SQL END DECLARE SECTION; os_printf(DH_STRING_LITERAL("MANAGE\n")); /* populate the tables with data */ Add_CustomerMaster_Records(); Add_CustomerOrders_Records(); Add_OrderItems_Records(); Add_ItemMaster_Records(); /* perform a query: list customer name and total amount per order name @@@@@@@@@@@@@ total $xx.xx for each order in the CustomerOrders table fetch order number fetch customer number fetch name from CustomerMaster table based on customer number for each order item in OrderItems table fetch item quantity fetch item number fetch item price from ItemMaster table based on item number next next */ os_printf(DH_STRING_LITERAL("\n\tQuery Results\n")); /* declare cursor for fetching orders */ EXEC SQL DECLARE curs CURSOR FOR SELECT cm_custname, SUM(im_itempric * oi_quantity) FROM custmast, custordr, ordritem, itemmast WHERE co_custnumb = cm_custnumb AND co_ordrnumb = oi_ordrnumb AND oi_itemnumb = im_itemnumb GROUP BY cm_custnumb, cm_custname; if (sqlca.sqlcode) All Rights Reserved 19 www.faircom.com Quick Tour Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL OPEN curs; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); while (1) { /* for each order in the CustomerOrders table */ EXEC SQL FETCH curs INTO :custname, :total; if (sqlca.sqlcode == SQL_NOT_FOUND) break; else if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); /* output data to stdout */ os_printf(DH_STRING_LITERAL("\t\t%-20s %.2f\n"), custname, total); } EXEC SQL CLOSE curs ; } /* * Delete_Records() * * This function deletes all the records in the table */ void Delete_Records(dh_char_t* table) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; os_printf(DH_STRING_LITERAL("\tDelete records…\n")); os_sprintf (sCommand, DH_STRING_LITERAL("DELETE FROM %s"), table); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode < 0) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL COMMIT WORK ; } /* * Add_CustomerMaster_Records() * * This function adds records to table CustomerMaster from an * array of strings */ void Add_CustomerMaster_Records(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; dh_char_t *data[] = { DH_STRING_LITERAL("('1000','92867','CA','1','Bryan Williams','2999 Regency','Orange')"), DH_STRING_LITERAL("('1001','61434','CT','1','Michael Jordan','13 Main','Harford')"), DH_STRING_LITERAL("('1002','73677','GA','1','Joshua Brown','4356 Cambridge','Atlanta')"), All Rights Reserved 20 www.faircom.com Quick Tour DH_STRING_LITERAL("('1003','10034','MO','1','Keyon Dooling','19771 Park Avenue','Columbia')") }; int i; int nRecords = sizeof(data) / sizeof(data[0]); Delete_Records(DH_STRING_LITERAL("custmast")); os_printf(DH_STRING_LITERAL("\tAdd records in table CustomerMaster…\n")); /* add one record at time to table */ for (i = 0; i < nRecords; i++) { os_sprintf (sCommand, DH_STRING_LITERAL("INSERT INTO custmast VALUES %s"), data[i]); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } EXEC SQL COMMIT WORK; } /* * Add_CustomerOrders_Records() * * This function adds records to table CustomerOrders from an * array of strings */ void Add_CustomerOrders_Records(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; dh_char_t *data[] = { DH_STRING_LITERAL("('09/01/2002','09/05/2002','1','1001')"), DH_STRING_LITERAL("('09/02/2002','09/06/2002','2','1002')") }; int i; int nRecords = sizeof(data) / sizeof(data[0]); Delete_Records(DH_STRING_LITERAL("custordr")); os_printf(DH_STRING_LITERAL("\tAdd records in table CustomerOrders…\n")); /* add one record at time to table */ for (i = 0; i < nRecords; i++) { os_sprintf (sCommand, DH_STRING_LITERAL("INSERT INTO custordr VALUES %s"), data[i]); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } EXEC SQL COMMIT WORK; } /* All Rights Reserved 21 www.faircom.com Quick Tour * Add_OrderItems_Records() * * This function adds records to table OrderItems from an * array of strings */ void Add_OrderItems_Records(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; dh_char_t *data[] = { DH_STRING_LITERAL("(1,2,'1','1')"), DH_STRING_LITERAL("(2,1,'1','2')"), DH_STRING_LITERAL("(3,1,'1','3')"), DH_STRING_LITERAL("(1,3,'2','3')") }; int i; int nRecords = sizeof(data) / sizeof(data[0]); Delete_Records(DH_STRING_LITERAL("ordritem")); os_printf(DH_STRING_LITERAL("\tAdd records in table OrderItems…\n")); /* add one record at time to table */ for (i = 0; i < nRecords; i++) { os_sprintf (sCommand, DH_STRING_LITERAL("INSERT INTO ordritem VALUES %s"), data[i]); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } EXEC SQL COMMIT WORK; } /* * Add_ItemMaster_Records() * * This function adds records to table ItemMaster from an * array of strings */ void Add_ItemMaster_Records(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; dh_char_t *data[] = { DH_STRING_LITERAL("(10,19.95,'1','Hammer')"), DH_STRING_LITERAL("(3, 9.99,'2','Wrench')"), DH_STRING_LITERAL("(4, 16.59,'3','Saw')"), DH_STRING_LITERAL("(1, 3.98,'4','Pliers')") }; int i; int nRecords = sizeof(data) / sizeof(data[0]); Delete_Records(DH_STRING_LITERAL("itemmast")); os_printf(DH_STRING_LITERAL("\tAdd records in table ItemMaster...\n")); All Rights Reserved 22 www.faircom.com Quick Tour /* add one record at time to table */ for (i = 0; i < nRecords; i++) { os_sprintf (sCommand, DH_STRING_LITERAL("INSERT INTO itemmast VALUES %s"), data[i]); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } EXEC SQL COMMIT WORK; } All Rights Reserved 23 www.faircom.com Quick Tour Done When an application and/or process has completed operations with the database, it must release resources by disconnecting from the database engine. Below is the code for Done(): /* * Done() * * This function handles the housekeeping of closing connection and * freeing of associated memory */ void Done(void) { os_printf(DH_STRING_LITERAL("DONE\n")); /* disconnect from server */ EXEC SQL DISCONNECT CURRENT ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } All Rights Reserved 24 www.faircom.com Quick Tour Additional Resources We encourage you to explore the additional resources listed here: Complete source code for this tutorial can be found in eSQL_Tutorial2.pc in your installation directory, within the 'sdk\sql.embedded\tutorials' directory for your platform. Example for the Windows platform: C:\FairCom\V11.x.x\win32\sdk\sql.embedded\tutorials\eSQL_Tutorial2.pc. Additional documentation may be found on the FairCom Web site at: www.faircom.com All Rights Reserved 25 www.faircom.com Quick Tour 2.3 Record/Row Locking ..\sdk\sql.embedded\tutorials\eSQL_Tutorial3.pc Now we will explore row/record locks using the c-treeACE SQL ESQL - Embedded SQL Interface The functionality for this tutorial focuses on inserting/adding rows/records, then updating a single row/record in the customer master table under locking control. The application will pause after a LOCK is placed on a row/record. Another instance of this application should then be launched, which will block, waiting on the lock held by the first instance. Pressing the <Enter> key will enable the first instance to proceed. This will result in removing the lock thereby allowing the second instance to continue execution. Launching two processes provides a visual demonstration of the effects of locking and a basis for experimentation on your own. Like all other examples in the c-tree tutorial series, this tutorial simplifies the creation and use of a database into four simple steps: Initialize(), Define(), Manage(), and you’re Done() ! Tutorial #3: Locking Here we demonstrate the enforcement of data integrity by introducing record/row "locking". Initialize() - Connects to the c-treeACE Database Engine. Define() - Defines and creates a "customer master" (custmast) table/file. Manage() - Adds a few rows/records; Reads the rows/records back from the database; displays the column/field content. Then demonstrates an update operation under locking control, and a scenario that shows a locking conflict. Done() - Disconnects from c-treeACE Database Engine. Note our simple mainline: /* * main() * * The main() function implements the concept of "init, define, manage * and you're done..." */ int main(int argc, char* argv[]) { Initialize(); Define(); Manage(); Done(); os_printf(DH_STRING_LITERAL("\nPress <ENTER> key to exit . . .\n")); getchar(); return(0); } We suggest opening the source code with your own editor. Continue now to review these four steps. All Rights Reserved 26 www.faircom.com Quick Tour Init First we need to open a connection to a database by providing the c-treeACE Database Engine with a user name, password and the database name. Below is the code for Initialize(): /* * Initialize() * * Perform the minimum requirement of logging onto the c-tree Server */ void Initialize(void) { os_printf(DH_STRING_LITERAL("INIT\n")); os_setenv (DH_STRING_LITERAL("DH_USER"), DH_STRING_LITERAL("ADMIN")); os_setenv (DH_STRING_LITERAL("DH_PASSWD"), DH_STRING_LITERAL("ADMIN")); os_setenv (DH_STRING_LITERAL("DB_NAME"), DH_STRING_LITERAL("ctreeSQL")); EXEC SQL CONNECT TO DEFAULT ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } All Rights Reserved 27 www.faircom.com Quick Tour Define The define step is where specific data definitions are established by your application and/or process. This involves defining columns/fields and creating the tables/files with optional indices. Below is the code for Define(): /* * Define() * * Create the table for containing a list of existing customers */ void Define(void) { os_printf(DH_STRING_LITERAL("DEFINE\n")); /* create table */ os_printf(DH_STRING_LITERAL("\tCreate table...\n")); EXEC SQL CREATE TABLE custmast ( cm_custnumb CHAR(4), cm_custzipc CHAR(9), cm_custstat CHAR(2), cm_custrtng CHAR(1), cm_custname VARCHAR(47), cm_custaddr VARCHAR(47), cm_custcity VARCHAR(47) ) ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL CREATE UNIQUE INDEX cm_custnumb_idx ON custmast (cm_custnumb) ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL COMMIT WORK; } All Rights Reserved 28 www.faircom.com Quick Tour Manage The manage step provides data management functionality for your application and/or process. Below is the code for Manage(): /* * Manage() * * This function performs simple record functions of add, delete and gets */ void Manage(void) { os_printf(DH_STRING_LITERAL("MANAGE\n")); /* delete any existing records */ Delete_Records(); /* populate the table with data */ Add_CustomerMaster_Records(); /* display contents of table */ Display_Records(); /* update a record under locking control */ Update_CustomerMaster_Record(); /* display again after update and effects of lock */ Display_Records(); } /* * Delete_Records() * * This function deletes all the records in the table */ void Delete_Records(void) { os_printf(DH_STRING_LITERAL("\tDelete records...\n")); EXEC SQL DELETE FROM custmast ; if (sqlca.sqlcode < 0) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL COMMIT WORK ; } /* * Add_CustomerMaster_Records() * * This function adds records to table CustomerMaster from an * array of strings */ All Rights Reserved 29 www.faircom.com Quick Tour void Add_CustomerMaster_Records(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; dh_char_t *data[] = { DH_STRING_LITERAL("('1000','92867','CA','1','Bryan Williams','2999 Regency','Orange')"), DH_STRING_LITERAL("('1001','61434','CT','1','Michael Jordan','13 Main','Harford')"), DH_STRING_LITERAL("('1002','73677','GA','1','Joshua Brown','4356 Cambridge','Atlanta')"), DH_STRING_LITERAL("('1003','10034','MO','1','Keyon Dooling','19771 Park Avenue','Columbia')") }; int i; int nRecords = sizeof(data) / sizeof(data[0]); Delete_Records(); os_printf(DH_STRING_LITERAL("\tAdd records...\n")); /* add one record at time to table */ for (i = 0; i < nRecords; i++) { os_sprintf (sCommand, DH_STRING_LITERAL("INSERT INTO custmast VALUES %s"), data[i]); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } EXEC SQL COMMIT WORK; } /* * Display_Records() * * This function displays the contents of a table. */ void Display_Records(void) { EXEC SQL BEGIN DECLARE SECTION ; CHAR custnumb[5+1]; CHAR custname[47+1]; EXEC SQL END DECLARE SECTION ; os_printf(DH_STRING_LITERAL("\tDisplay records...")); EXEC SQL DECLARE curs CURSOR FOR SELECT custmast.cm_custnumb, custmast.cm_custname FROM custmast; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL OPEN curs; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL FETCH curs INTO :custnumb, :custname; /* fetch and display each individual record */ while (!sqlca.sqlcode) All Rights Reserved 30 www.faircom.com Quick Tour { os_printf(DH_STRING_LITERAL("\n\t\t%-8s%10s\n"),custnumb, custname); EXEC SQL FETCH curs INTO :custnumb, :custname; } EXEC SQL CLOSE curs ; } /* * Update_CustomerMaster_Records() * * Update one record under locking control to demonstrate the effects * of locking */ void Update_CustomerMaster_Record(void) { os_printf(DH_STRING_LITERAL("\tUpdate record...\n")); EXEC SQL UPDATE custmast SET cm_custname = 'KEYON DOOLING' WHERE cm_custnumb = '1003'; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); os_printf(DH_STRING_LITERAL("\tPress <ENTER> key to unlock\n")); getchar(); EXEC SQL COMMIT WORK; } All Rights Reserved 31 www.faircom.com Quick Tour Done When an application and/or process has completed operations with the database, it must release resources by disconnecting from the database engine. Below is the code for Done(): /* * Done() * * This function handles the housekeeping of closing connection and * freeing of associated memory */ void Done(void) { os_printf(DH_STRING_LITERAL("DONE\n")); /* disconnect from server */ EXEC SQL DISCONNECT CURRENT ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } All Rights Reserved 32 www.faircom.com Quick Tour Additional Resources We encourage you to explore the additional resources listed here: Complete source code for this tutorial can be found in eSQL_Tutorial3.pc in your installation directory, within the 'sdk\sql.embedded\tutorials' directory for your platform. Example for the Windows platform: C:\FairCom\V11.x.x\win32\sdk\sql.embedded\tutorials\eSQL_Tutorial3.pc. Additional documentation may be found on the FairCom Web site at: www.faircom.com All Rights Reserved 33 www.faircom.com Quick Tour 2.4 Transaction Processing ..\sdk\sql.embedded\tutorials\eSQL_Tutorial4.pc Now we will discuss transaction processing as it relates to the c-treeACE SQL ESQL Embedded SQL Interface Transaction processing provides a safe method by which multiple database operations spread across separate tables/files are guaranteed to be atomic. By atomic, we mean that, within a transaction, either all of the operations succeed or none of the operations succeed. This "either all or none" atomicity insures that the integrity of the data in related tables/files is secure. Like all other examples in the c-tree tutorial series, this tutorial simplifies the creation and use of a database into four simple steps: Initialize(), Define(), Manage(), and You’re Done() ! Tutorial #4: Transaction Processing Here we demonstrate transaction control. Initialize() - Connects to the c-treeACE Database Engine. Define() - Defines and creates our four tables/files. Manage() - Adds rows/records to multiple tables/files under transaction control. Done() - Disconnects from c-treeACE Database Engine. Note our simple mainline: /* * main() * * The main() function implements the concept of "init, define, manage * and you're done..." */ int main(int argc, char* argv[]) { Initialize(); Define(); Manage(); Done(); os_printf(DH_STRING_LITERAL("\nPress <ENTER> key to exit . . .\n")); getchar(); return(0); } We suggest opening the source code with your own editor. Continue now to review these four steps. All Rights Reserved 34 www.faircom.com Quick Tour Init First we need to open a connection to a database by providing the c-treeACE Database Engine with a user name, password and the database name. Below is the code for Initialize(): /* * Initialize() * * Perform the minimum requirement of logging onto the c-tree Server */ void Initialize(void) { os_printf(DH_STRING_LITERAL("INIT\n")); os_setenv (DH_STRING_LITERAL("DH_USER"), DH_STRING_LITERAL("ADMIN")); os_setenv (DH_STRING_LITERAL("DH_PASSWD"), DH_STRING_LITERAL("ADMIN")); os_setenv (DH_STRING_LITERAL("DB_NAME"), DH_STRING_LITERAL("ctreeSQL")); EXEC SQL CONNECT TO DEFAULT ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } All Rights Reserved 35 www.faircom.com Quick Tour Define The define step is where specific data definitions are established by your application and/or process. This involves defining columns/fields and creating the tables/files with optional indices. Below is the code for Define(): /* * Define() * * Create the tables */ void Define(void) { os_printf(DH_STRING_LITERAL("DEFINE\n")); /* delete tables ... */ Delete_Tables(); /* ...and re-create them with constraints */ Create_CustomerMaster_Table(); Create_ItemMaster_Table(); Create_CustomerOrders_Table(); Create_OrderItems_Table(); EXEC SQL COMMIT WORK ; } /* * Create_CustomerMaster_Table() * * Create the CustomerMaster */ void Create_CustomerMaster_Table(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; /* define table CustomerMaster */ os_printf(DH_STRING_LITERAL("\ttable CustomerMaster\n")); os_sprintf (sCommand, DH_STRING_LITERAL("CREATE TABLE custmast ( \ cm_custnumb CHAR(4) PRIMARY KEY, \ cm_custzipc CHAR(9), \ cm_custstat CHAR(2), \ cm_custrtng CHAR(1), \ cm_custname VARCHAR(47), \ cm_custaddr VARCHAR(47), \ cm_custcity VARCHAR(47) \ )")); EXEC SQL EXECUTE IMMEDIATE :sCommand ; All Rights Reserved 36 www.faircom.com Quick Tour if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } /* * Create_CustomerOrders_Table() * * Create the CustomerOrders */ void Create_CustomerOrders_Table(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; /* define table CustomerOrders */ os_printf(DH_STRING_LITERAL("\ttable CustomerOrders\n")); os_sprintf (sCommand, DH_STRING_LITERAL("CREATE TABLE custordr ( \ co_ordrdate DATE, \ co_promdate DATE, \ co_ordrnumb CHAR(6) PRIMARY KEY, \ co_custnumb CHAR(4), \ FOREIGN KEY (co_custnumb) REFERENCES custmast \ )")); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } /* * Create_OrderItems_Table() * * Create the OrderItems */ void Create_OrderItems_Table(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; /* define table OrderItems */ os_printf(DH_STRING_LITERAL("\ttable OrderItems\n")); os_sprintf (sCommand, DH_STRING_LITERAL("CREATE TABLE ordritem ( \ oi_sequnumb SMALLINT, \ oi_quantity SMALLINT, \ oi_ordrnumb CHAR(6), \ oi_itemnumb CHAR(5), \ FOREIGN KEY (oi_itemnumb) REFERENCES itemmast, \ FOREIGN KEY (oi_ordrnumb) REFERENCES custordr \ )")); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } All Rights Reserved 37 www.faircom.com Quick Tour /* * Create_ItemMaster_Table() * * Create the ItemMaster */ void Create_ItemMaster_Table(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; /* define table ItemMaster */ os_printf(DH_STRING_LITERAL("\ttable ItemMaster\n")); os_sprintf (sCommand, DH_STRING_LITERAL("CREATE TABLE itemmast ( \ im_itemwght INTEGER, \ im_itempric MONEY, \ im_itemnumb CHAR(5) PRIMARY KEY, \ im_itemdesc VARCHAR(47) \ )")); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } All Rights Reserved 38 www.faircom.com Quick Tour Manage The manage step provides data management functionality for your application and/or process. Below is the code for Manage(): /* * Manage() * * Populates table and perform a simple query * */ void Manage(void) { os_printf(DH_STRING_LITERAL("MANAGE\n")); /* populate the tables with data */ Add_CustomerMaster_Records(); Add_ItemMaster_Records(); Add_Transactions(); /* display the orders and their items */ Display_CustomerOrders(); Display_OrderItems(); } /* * Delete_Tables() * * This function removes all existing tables */ void Delete_Tables(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; os_sprintf (sCommand, DH_STRING_LITERAL("DROP TABLE EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); os_sprintf (sCommand, DH_STRING_LITERAL("DROP TABLE EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); os_sprintf (sCommand, DH_STRING_LITERAL("DROP TABLE EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); os_sprintf (sCommand, DH_STRING_LITERAL("DROP TABLE EXEC SQL EXECUTE IMMEDIATE :sCommand ; All Rights Reserved 39 ordritem")); custordr")); itemmast")); custmast")); www.faircom.com Quick Tour if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } /* * Add_CustomerMaster_Records() * * This function adds records to table CustomerMaster from an * array of strings */ void Add_CustomerMaster_Records(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; dh_char_t *data[] = { DH_STRING_LITERAL("('1000','92867','CA','1','Bryan Williams','2999 Regency','Orange')"), DH_STRING_LITERAL("('1001','61434','CT','1','Michael Jordan','13 Main','Harford')"), DH_STRING_LITERAL("('1002','73677','GA','1','Joshua Brown','4356 Cambridge','Atlanta')"), DH_STRING_LITERAL("('1003','10034','MO','1','Keyon Dooling','19771 Park Avenue','Columbia')") }; int i; int nRecords = sizeof(data) / sizeof(data[0]); os_printf(DH_STRING_LITERAL("\tAdd records in table CustomerMaster...\n")); /* add one record at time to table */ for (i = 0; i < nRecords; i++) { os_sprintf (sCommand, DH_STRING_LITERAL("INSERT INTO custmast VALUES %s"), data[i]); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } EXEC SQL COMMIT WORK; } /* * Add_ItemMaster_Records() * * This function adds records to table ItemMaster from an * array of strings */ void Add_ItemMaster_Records(void) { EXEC SQL BEGIN DECLARE SECTION ; char sCommand[512]; EXEC SQL END DECLARE SECTION ; dh_char_t *data[] = { DH_STRING_LITERAL("(10,19.95,'1','Hammer')"), DH_STRING_LITERAL("(3, 9.99,'2','Wrench')"), DH_STRING_LITERAL("(4, 16.59,'3','Saw')"), DH_STRING_LITERAL("(1, 3.98,'4','Pliers')") }; All Rights Reserved 40 www.faircom.com Quick Tour int int i; nRecords = sizeof(data) / sizeof(data[0]); os_printf(DH_STRING_LITERAL("\tAdd records in table ItemMaster...\n")); /* add one record at time to table */ for (i = 0; i < nRecords; i++) { os_sprintf (sCommand, DH_STRING_LITERAL("INSERT INTO itemmast VALUES %s"), data[i]); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } EXEC SQL COMMIT WORK; } /* * Add_Transactions() * * Add an Order and associated Items "as a transaction" to their * respective tables. A transaction is committed or aborted if the * customer number on the order is confirmed valid. Likewise each * item in the order is verified to be a valid item. */ typedef struct { dh_char_t *ordrdate, *promdate, *ordrnumb, *custnumb; } ORDER_DATA; typedef struct { dh_char_t* ordrnumb; short sequnumb; short quantity; dh_char_t* itemnumb; } ORDERITEM_DATA; ORDER_DATA orders[] = { {DH_STRING_LITERAL("09/01/2002"), DH_STRING_LITERAL("1001")}, {DH_STRING_LITERAL("09/02/2002"), DH_STRING_LITERAL("9999")}, /* bad {DH_STRING_LITERAL("09/22/2002"), DH_STRING_LITERAL("1003")} }; ORDERITEM_DATA items[] = { {DH_STRING_LITERAL("1"), {DH_STRING_LITERAL("1"), {DH_STRING_LITERAL("2"), {DH_STRING_LITERAL("2"), {DH_STRING_LITERAL("3"), {DH_STRING_LITERAL("3"), }; 1, 2, 1, 2, 1, 2, 2, 1, 1, 3, 2, 2, DH_STRING_LITERAL("09/05/2002"), DH_STRING_LITERAL("1"), DH_STRING_LITERAL("09/06/2002"), DH_STRING_LITERAL("2"), customer number */ DH_STRING_LITERAL("09/26/2002"), DH_STRING_LITERAL("3"), DH_STRING_LITERAL("1")}, DH_STRING_LITERAL("2")}, DH_STRING_LITERAL("3")}, DH_STRING_LITERAL("4")}, DH_STRING_LITERAL("3")}, DH_STRING_LITERAL("99")} /* bad item number */ void Add_Transactions(void) { EXEC SQL BEGIN DECLARE SECTION ; CHAR sCommand[512]; EXEC SQL END DECLARE SECTION ; All Rights Reserved 41 www.faircom.com Quick Tour int int int i, j = 0; nOrders = sizeof(orders) / sizeof(ORDER_DATA); nItems = sizeof(items) / sizeof(ORDERITEM_DATA); os_printf(DH_STRING_LITERAL("\tAdd transaction records... \n")); for (i = 0; i < nOrders; i++) { /* add order record */ os_sprintf(sCommand, DH_STRING_LITERAL("INSERT INTO custordr VALUES ('%s', '%s', '%s', '%s')"), orders[i].ordrdate, orders[i].promdate, orders[i].ordrnumb, orders[i].custnumb); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); /* process order items */ while (!(strcmp(items[j].ordrnumb, orders[i].ordrnumb))) { /* add item record */ os_sprintf(sCommand, DH_STRING_LITERAL("INSERT INTO ordritem VALUES (%d, %d, '%s', '%s')"), items[j].sequnumb, items[j].quantity, items[j].ordrnumb, items[j].itemnumb); EXEC SQL EXECUTE IMMEDIATE :sCommand ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); /* bump to next item */ j++; /* exit the while loop on last item */ if (j >= nItems) break; } EXEC SQL COMMIT WORK; } } /* * Display_CustomerOrders() * * This function displays the contents of CustomerOrders table */ void Display_CustomerOrders(void) { EXEC SQL BEGIN DECLARE SECTION ; CHAR ordrnumb[6+1]; CHAR custnumb[4+1]; EXEC SQL END DECLARE SECTION ; os_printf(DH_STRING_LITERAL("\n\tCustomerOrders Table...\n")); EXEC SQL DECLARE curs CURSOR FOR All Rights Reserved 42 www.faircom.com Quick Tour SELECT co_ordrnumb, co_custnumb FROM custordr; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL OPEN curs; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL FETCH curs INTO :ordrnumb, :custnumb; /* fetch and display each individual record */ while (!sqlca.sqlcode) { os_printf(DH_STRING_LITERAL("\t %s %s\n"), ordrnumb, custnumb); EXEC SQL FETCH curs INTO :ordrnumb, :custnumb; } EXEC SQL CLOSE curs ; } /* * Display_OrderItems() * * This function displays the contents of OrderItems table */ void Display_OrderItems(void) { EXEC SQL BEGIN DECLARE SECTION ; CHAR ordrnumb[6+1]; CHAR itemnumb[5+1]; EXEC SQL END DECLARE SECTION ; os_printf(DH_STRING_LITERAL("\n\tOrderItems Table...\n")); EXEC SQL DECLARE cur2 CURSOR FOR SELECT oi_ordrnumb, oi_itemnumb FROM ordritem; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL OPEN cur2; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL FETCH cur2 INTO :ordrnumb, :itemnumb; /* fetch and display each individual record */ while (!sqlca.sqlcode) { os_printf(DH_STRING_LITERAL("\t %s %s\n"), ordrnumb, itemnumb); EXEC SQL FETCH cur2 INTO :ordrnumb, :itemnumb; } EXEC SQL CLOSE cur2 ; } All Rights Reserved 43 www.faircom.com Quick Tour Done When an application and/or process has completed operations with the database, it must release resources by disconnecting from the database engine. Below is the code for Done(): /* * Done() * * This function handles the housekeeping of closing connection and * freeing of associated memory */ void Done(void) { os_printf(DH_STRING_LITERAL("DONE\n")); Delete_Tables(); EXEC SQL COMMIT WORK ; /* disconnect from server */ EXEC SQL DISCONNECT CURRENT ; if (sqlca.sqlcode) Handle_Error(sqlca.sqlcode, sqlca.sqlerrm); } All Rights Reserved 44 www.faircom.com Quick Tour Additional Resources We encourage you to explore the additional resources listed here: Complete source code for this tutorial can be found in eSQL_Tutorial4.pc in your installation directory, within the 'sdk\sql.embedded\tutorials' directory for your platform. Example for the Windows platform: C:\FairCom\V11.x.x\win32\sdk\sql.embedded\tutorials\eSQL_Tutorial4.pc. Additional documentation may be found on the FairCom Web site at: www.faircom.com All Rights Reserved 45 www.faircom.com 3. Using the esqlc Command 3.1 Introduction The esql command takes as input a set of esql source files (by convention, files with .pc as the file name extension) and generates corresponding C source files (.c files). The C source files are compiled and linked using the C compiler and linker to create and application executable ( .exe file). The following figure illustrates the sequence of using esql to create executable files. ESQL Compilation Process Equation 1: -1: ESQL Compilation Process 3.2 esqlc Command Line Reference The esql command invokes the ESQL precompiler. Without any arguments, the esql command displays a summary of the command syntax and options described here. The esql command also accepts the following arguments, detailed in this section: Options specific to the esql precompiler Options to be passed to the C compiler and linker for processing The names of esql source code files, and optionally, C-language source and object files Depending on the options included in the esql command, the precompiler translates the esql source files specified into C source files and then invokes the C compiler to compile and link them into executable objects. All Rights Reserved 46 www.faircom.com Using the esqlc Command Before invoking esql, make sure the PATH environment variable includes the directory that contains the esql image (the default location is C:\FairCom\Vx.xx\c-treeServers\Utils\bin). Syntax esqlc [ [ esql_option … ] [ c_option … ] file_name … ] esql_option :: +T | +P | +B | +L | +V | +K | +G | +M | +D connect_string | +U user_name | +A password Arguments esql_option A list of precompiler-specific options. Precede esql-specific options with a plus sign ( + ) to avoid confusion with C compiler and linker options. The esql command passes all command line options that it does not recognize to the C compiler., providing the user a means to specify C compiler options directly as options to the esql command. +T - Translates the embedded SQL source code to C source code withinvoking the C compiler to generate the object or executable files. If the command line omits this option, the precompiler invokes the C compiler +P - Runs the C preprocessor on the input file before translating the c-treeSQL statements in the input file. This allows using #define symbols in ESQL declarations and statements. If the command line omits this option, the precompiler does not run the C preprocessor. +B - Specifies that the precompiler link with shared libraries instead of static libraries. The effect of specifying the +B option is the same as setting the TPE_DLL environment variable to Y. For either to work correctly, the c-treeSQL libraries and executables must have been built specifying the USE_SHARED_LIBS directive through the TPE_ENV environment variable. See the c-treeSQL Installation and Release Notes for details. If the esql command omits the +B option, the default is to link with static libraries. +L - Suppresses redefinition of source line numbers in the generated C code, to simplify debugging of host language statements. If the command line omits this option, the precompiler redefines source line numbers. +V - Displays the commands the precompiler invokes as it processes the files. +K - Keeps intermediate C source code and object files. If the command line omits this option, the precompiler does not keep the intermediate files. +G - Inserts debugging code. +M - Produces an executable that links the front and back end of the c-treeSQL engine in a single merged image. Specify this option with the -l C compiler option and the appropriate object library in $TPEROOT/lib. For example: All Rights Reserved 47 www.faircom.com Using the esqlc Command esqlc +M progname -l$TPEROOT/lib/libstubs.a +D connect_string - A string that specifies which database to connect to at compile time. The database is used for accessing the definition of tables used in the application code. The connect string can be a simple database name or a complete connect string. See the CONNECT statement in the c-treeSQL Reference Manual for details on how to specify a complete connect string. If omitted, the default value depends on the environment (on UNIX, the value of the DB_NAME environment variable specifies the default connect string). +U user_name - The user name c-treeSQL uses to connect to the database specified in the connect_string. c-treeSQL verifies the user name against a corresponding password before it connects to the database. If omitted, the default value depends on the environment. (On Unix the value of the DH_USER environment variable specifies the default user name. If DH_USER is not set, the value of the USER environment variable specifies the default user name. +A password - The password c-treeSQL uses to connect to the database specified in the connect_string. c-treeSQL verifies the password against a corresponding user name before it connects to the database. If omitted, the default value depends on the environment (on Unix the value of the DH_PASSWD environment variable specifies the default password). c_option C compiler options. The esql command passes any command line options that it does not recognize to the C compiler. Typical C compiler options you might use include: -o To specify the name of the output executable object -c To suppress linking of object files generated by the C compiler See the documentation for the C compiler in your environment for details on valid options. file_name A list of esql source files (by convention, with a .pc file-name extension) for the precompiler to translate into C source files (which the precompiler generates with .c file-name extensions). The file_name argument can include C source files and object files. The precompiler passes them to the compiler and linker, respectively. 3.3 esqlc Command Examples The following examples illustrate different ways of using the esql command. Precompiling, Compiling, and Linking Multiple Files with esqlc The most straightforward use of esql is to accept the various default values of both the precompiler and compiler. These defaults result in the precompiler automatically invoking the compiler, which in turn invokes the linker, generating an executable in one step. All Rights Reserved 48 www.faircom.com Using the esqlc Command Consider a report-generating application with source code contained in two esql source files, rep1.pc and rep2.pc. The following example accepts all the precompiler defaults but specifies the -o C compiler option to specify the name of the output executable file as report. Equation 2: -1: ESQL Compilation Process Issuing Separate Commands for Precompiling, Compiling, and Linking Alternatively, the following sequence of commands generates the same executable and illustrates how you can combine options and commands: esqlc cc -c esqlc cc -c esqlc +T rep1.pc rep1.c +T rep2.pc rep2.c -o report rep1.o rep2.o The esql +T commands specify a single embedded SQL source file. The +T precompiler option generates the C source code but suppresses automatic invocation of the C compiler. The cc -c commands explicitly invoke the C compiler and specify the C source-code file from the corresponding esql +T command. The -c compiler option generates an object file but suppresses linking. Finally, the esql -o command specifies both the object files generated by the preceding cc -c commands. It does not actually invoke the precompiler, but passes the object files to the C compiler. The -o option is a C compiler option that names the executable. Mixing Precompiler/Compiler Options in the esqlc Command The esql command can include both precompiler and compiler options. For instance, the following command uses the -o compiler option and the +P precompiler option: esqlc -o report +P rep1.pc rep2.pc The -o option names the executable generated by the compiler. The +P option runs the C preprocessor before translating c-treeSQL statements. If c-treeSQL statements embedded in the files rep1.pc and rep2.pc use symbolic names specified through #define precompiler directives, then the esqlc command must include the +P option. All Rights Reserved 49 www.faircom.com 4. ESQL Program Structure 4.1 Introduction This chapter describes the overall program structure of an ESQL program and discusses: The ESQL declare statements ESQL executable statements The c-treeSQL Communications Area COMMIT and ROLLBACK statements 4.2 ESQL Declare Statements The ESQL precompiler is used to parse and translate ESQL constructs, prefixed with EXEC SQL, to C language statements. ESQL does not allow the use of host language defined variables in ESQL constructs. To declare variables for use in the ESQL constructs, ESQL provides declare statements. The ESQL constructs within which the variables can be declared for use in ESQL statements are referred to as the declare section. For more information on the declare section, see "BEGIN-END DECLARE SECTION" (page 153). The following ESQL constructs are used to mark the beginning and end of a declare section: EXEC SQL BEGIN DECLARE SECTION ; ... EXEC SQL END DECLARE SECTION ; The declare section should appear before any other ESQL constructs are used. Only C statements can precede the declare section in an ESQL program. The variables appearing in the declare section can either be declared as local variables or global variables. The following is an example showing the declaration for variables that would be used in the order processing application program: ... EXEC SQL BEGIN DECLARE SECTION ; long char char long order_no_v ; order_date_v [10] ; product_v [5] ; qty_v ; EXEC SQL END DECLARE SECTION ; ... All Rights Reserved 50 www.faircom.com ESQL Program Structure The above ESQL constructs declare the variable order_no_v to be of type long, product_v to be an array of char and qty_v to be a variable of type long. The ESQL precompiler generates the corresponding host language declarations for these variables and hence these variables can be used by the C language statements at the application developer’s convenience. The variables that could be declared in the declare section are host variables and indicator variables. These variables and their usage are discussed in more detail in the following sections. Note: The ESQL precompiler does not check for or generate messages about unused variables in the declare section. Host Variables and their Usage The host language variables that are used in the ESQL statements appearing in an ESQL program are called host variables. Host variables must be declared in the declare section prior to its usage in an ESQL program. The data types used to declare the host variables can be the same as database types. For example, to declare a host variable of type SHORT, the variable can be declared as the database type SMALLINT. The general format of using the host variable in an ESQL construct is shown below: :host_variable_name When a host variable is used in the ESQL constructs, the variable has to be prefixed with a colon. The following sample ESQL code shows the usage of host variables: ... EXEC SQL INSERT INTO orders (order_no, order_date, product, qty) VALUES (:order_no_v, :order_date_v, :product_v, :qty_v) ; ... In the above example, it can be seen that whenever host variables are used, they are prefixed with a colon. The host variables can also be used by C language statements as and when desired. Keep the following points in mind while using host variables in ESQL. Host variables must: Explicitly declare the host variable in the ESQL declare section. Precede the host variable by a colon (:) when used in an ESQL statement. Do not precede the host variable by a colon when used in C statements. Name of the host variable must not be an SQL reserved word. Use the host variable in an ESQL statement only where a constant can be used. The host variable can have an associated indicator variable. Indicator variables are discussed in the following section. Indicator Variables and their Usage Indicator variables are optional variables used to handle null values. Each indicator variable is associated with one host variable. Indicator variables should be of type short or SMALLINT. All Rights Reserved 51 www.faircom.com ESQL Program Structure Programs use indicator variables to insert null values into the database. (There are other techniques to do this; see "Inserting NULL Values" (page 94) and "Using NULL Values in Expressions" (page 98) for more details.) SQL uses indicator variables to indicate that it returned a null value from the database, or that it returned a value that it was forced to truncate. (Again, there are other ways to check for null values; see "Using NULL Values in the WHERE Clause" (page 98) for more details.) Referring to Indicator Variables The general format for referring to indicator variables in an ESQL program is shown below: :host_variable_name [ INDICATOR ] :indicator_variable_name Always use a host variable name when you use an indicator variable reference, and always precede both references with a colon. The optional keyword INDICATOR clarifies the presence and purpose of the indicator variable. Valid values for an indicator variable and their meaning is as follows: 0 The associated host variable contains a non-null value. If set by c-treeSQL, a value of 0 also indicates the value in the host variable has not been truncated. -1 The value of the associated host variable is null. >0 The value in the associated host variable was truncated because the variable was too small. The value in the indicator variable is the actual length of the value before truncation. Keep in mind the following points about indicator variables. Indicator variables must: Be explicitly declared in the ESQL declare section. Be declared as short or SMALLINT type. Be preceded by a colon (:) when used in an ESQL statement. Not be preceded by a colon when used in a C statement. Not be named an c-treeSQL reserved word. Must be preceded by its associated input host variable when used in an ESQL statement. Inserting Null Values With Indicator Variables To insert a null value in the table, the application program has to set the indicator variable to negative one and then execute an INSERT or UPDATE c-treeSQL statement specifying the indicator variable. The following example shows the declaration and usage of an indicator variable (qty_i) to insert a null value into the orders table. Example Using Indicator Variables to Insert Null Values ... EXEC SQL BEGIN DECLARE SECTION ; long order_no_v ; char order_date_v [10] ; char product_v [5] ; long qty_v ; short qty_i ; All Rights Reserved 52 www.faircom.com ESQL Program Structure EXEC SQL END DECLARE SECTION ; /* set indicator variable for qty */ /* as -1 for inserting null */ qty_i = -1 ; ... EXEC SQL INSERT INTO orders (order_no, product, qty) VALUES (:order_no_v, :product_v, :qty_v:qty_i) ; ... Checking Indicator Variables to Test for Returned Null Values Indicator variables can also be used to test whether a returned value is a null value. This is done by using the indicator variables along with host variables used for output. The following example shows how to use indicator variables in the INTO clause of a SELECT statement to check for null values. Example Using Indicator Variables to Check for Returned Null Values EXEC SQL BEGIN DECLARE SECTION ; long cust_no ; char phone [13] ; short i_phone ; EXEC SQL END DECLARE SECTION ; cust_no = 1001 ; EXEC SQL SELECT c_phone INTO :phone:i_phone FROM customer WHERE cust_no = :cust_no ; if (i_phone == -1) printf ("No Phone Number\\n") ; else printf ("Phone Number is %s\\n", phone) ; For more information on indicator variables, see "NULL Value Handling in ESQL" (page 94) and "Error Handling in ESQL" (page 100). Limitations of the Declare Section The ESQL declare section does not allow some of the statements to declare variables as found in the C language. The limitations of the declare section are listed below: Referring to names declared in typedef statements is not allowed in the declare section. Such names are unknown to the ESQL precompiler. Hence, their use would result in an error condition. Declaration of a variable to be of a STRUCTURE type is not allowed. All Rights Reserved 53 www.faircom.com ESQL Program Structure Declaring pointers as host variables is not allowed. Declaring the VARCHAR type in the declare section is not allowed. Instead, CHAR type is to be used. 4.3 ESQL Executable Statements The ESQL constructs that result in the execution of instructions on a specified database at runtime are called the ESQL executable statements. The executable statements form the body of an ESQL program and are used to access the database. The following example shows a sample ESQL executable statement: EXEC SQL UPDATE orders SET qty = qty + 1000 WHERE order_no = 1244 ; The above SQL statement adds 1000 units to the existing quantity for the row in the orders table, having order number 1244. Types of Executable Statements The ESQL executable statements can be categorized into the following types: DML statements These statements perform data manipulation operations that can be used to manipulate the database. The DML operations are SELECT, INSERT, UPDATE and DELETE. The DML statements are the most frequently used statements in ESQL programs. DDL statements These statements perform data definitions on a given database. The DDL statements include statements for creating tables/views, dropping tables/views etc. DCL statements These statements are used basically for maintaining the security of a database. Transaction management statements The transaction statements are used for transaction management. The statements include COMMIT WORK and ROLLBACK WORK. 4.4 The c-treeSQL Communications Area The ESQL tool provides the error handling facility by returning the status code for every ESQL executable statement. The status code is returned in the c-treeSQL Communications Area (SQLCA). The SQLCA contains information about the status of the execution of the most recently executed c-treeSQL statement. The SQLCA is a structure with components that give additional information on the status of execution. The SQLCA includes information such as: All Rights Reserved 54 www.faircom.com ESQL Program Structure Warning flags Error code Diagnostic text Number of rows processed for INSERT, UPDATE, and DELETE statements For example, the application can check to see whether an c-treeSQL statement executed successfully, and if so, how many rows were inserted or updated. Hence, the SQLCA gives an application developer the option of taking different actions, based on feedback obtained about the work just attempted. The two most frequently used SQLCA components are: SQLCODE This component holds a status code after the execution of every executable c-treeSQL statement. The SQLCODE is of long type that indicates the success or failure of the statement execution. A zero value returned in SQLCODE indicates a successful execution. A negative SQLCODE indicates an error in the c-treeSQL statement execution. A positive SQLCODE indicates a successful execution with a status code. Currently, the only positive status code is SQL_NOT_FOUND which is returned when there are no more rows to be fetched. SQLWARN This component is a character array of size eight where each array element is set to the warning flag, ‘W’ or a blank. The first element, SQLWARN[0], is set to ‘W’, if any of the other flags is set, and so indicates that a warning has occurred during the execution. An alternative way of handling errors is by using the WHENEVER statement. The WHENEVER statement allows an application developer to take specific actions under cases of exceptions. The exception cases could be, NOT FOUND, SQLERROR or SQLWARNING. The actions can include stopping the program, branching, or continuing with the execution. For more information on error handling refer to "Error Handling in ESQL" (page 100). The COMMIT WORK and ROLLBACK WORK Statements Whenever a c-treeSQL statement is executed by an ESQL program, there is an active transaction associated with that ESQL program. The execution of the first ESQL executable statement in an ESQL program starts a transaction. All subsequent c-treeSQL statements are executed as part of this transaction until the transaction is committed or rolled back. After this, the first execution of a c-treeSQL statement starts a new transaction. The primary statements that are used for transaction management are COMMIT WORK and ROLLBACK WORK. The COMMIT WORK statement is used to make permanent, the changes made on a database. The following example shows the usage of the COMMIT WORK statement: ... EXEC SQL UPDATE orders SET qty = 2000 WHERE order_no = 1001 ; EXEC SQL COMMIT WORK ; All Rights Reserved 55 www.faircom.com ESQL Program Structure ... The normal termination of a transaction occurs with the successful execution of the COMMIT WORK statement. In contrast, the ROLLBACK WORK statement means abnormal termination of a transaction. If a transaction executes the ROLLBACK WORK statement, all changes made to the database in that transaction are canceled. The usage of the ROLLBACK WORK statement is similar to the COMMIT WORK statement and is shown below: ... EXEC SQL UPDATE orders SET qty = 2000 WHERE order_no = 1001 ; EXEC SQL ROLLBACK WORK ; ... For more information on transaction statements refer to "Transaction Management in ESQL" (page 131). All Rights Reserved 56 www.faircom.com 5. ESQL Application Development 5.1 Introduction This chapter contains hints and tips for developing ESQL applications: General guidelines SQL for computation SQL for condition evaluation Indicator variables Scalar functions Static and dynamic statements 5.2 Guidelines Some general coding guidelines for an application developer using ESQL are listed below. The character strings used in an ESQL program must be null terminated. The WHENEVER statement can be used in an ESQL program to check for error conditions. This statement provides more flexibility and reduces the code size of the application. There will be problems if any of the c-treeSQL reserved words happen to have been used as symbol names in #define directives in any included header file, and if the +P option is used while executing esql. When the +P option is used in esqlc, the source files are passed through the C preprocessor before the esql statements are translated. One frequent problem is the reserved word NULL that is used as a symbol name in the standard header file stdio.h. To work around the name conflict, use one of the following suggestions: • Avoid using the +P option. • Avoid the inclusion of the header file that contains the definition of the reserved word. • Reverse the case of the reserved word when used in the ESQL statement, as shown below. This would not affect esqlc since reserved words in ESQL statements are not case sensitive. EXEC SQL SELECT ename FROM employee WHERE commission is null ; It is recommended that the owner name of the table be used while referencing tables in an ESQL program, instead of using a non-qualified table name. For example, to access the table “customer” the SELECT statement could be: All Rights Reserved 57 www.faircom.com ESQL Application Development EXEC SQL SELECT CUST_NO, name FROM john.customer ; Here, john is the owner name of the table customer. While declaring host variable arrays, expressions are not allowed within the array subscript. For example, the following declaration in the declare section is not allowed: #define MAXNAMELEN 18 EXEC SQL BEGIN DECLARE SECTION ; char name [MAXNAMELEN + 1] ; EXEC SQL END DECLARE SECTION ; /* not allowed */ Here, the symbol MAXNAMELEN is defined. To handle such cases, define a new symbol for the required value and use that symbol, as shown below: ... #define MAXNAMELEN_P1 19 EXEC SQL BEGIN DECLARE SECTION ; char name [MAXNAMELEN_P1] ; EXEC SQL END DECLARE SECTION ; /* allowed */ #define symbols can be used in c-treeSQL statements wherever constants can be used. The following example shows the usage of the #define symbol, MAX_SALARY: #define MAX_SALARY 10000 SELECT ename, salary FROM employee WHERE salary = MAX_SALARY ; It is a good practice to specify all the columns in the SELECT list of a SELECT statement instead of specifying a ‘*’. This improves the readability of the SELECT statement. In addition, if the database table schema is changed later on, the ESQL statement need not be changed. 5.3 Using c-treeSQL for Computation and Conversion The c-treeSQL SELECT statement can be used to make computations in an ESQL program. The computations can be done using the SYSCALCTABLE table. The SYSCALCTABLE is a table with owner as admin and contains exactly one row with a single column. Programs can use c-treeSQL SELECT statements and scalar functions to perform a wide range of computations and conversions. c-treeSQL provides a system table called SYSCALCTABLE to facilitate such operations. The SYSCALCTABLE table contains a single row, which means SELECT statements that specify SYSCALCTABLE will return at most a single row. This makes it convenient to use SELECT INTO statements for computations and conversions. (Of course, you don’t have to use the table SYSCALCTABLE but it is guaranteed to be available in any c-treeSQL environment.) In general, the format for using SYSCALCTABLE in this manner is as follows: EXEC SQL SELECT expression INTO :host_var FROM admin.syscalctable ; All Rights Reserved 58 www.faircom.com ESQL Application Development The expression in the SELECT list can have constants or host variables and can include scalar functions. The following example shows some of the computations that can be done using the SELECT statement: Example Using c-treeSQL for Computation ... EXEC SQL BEGIN DECLARE SECTION ; long result ; long num ; long val ; DATE dtval ; EXEC SQL END DECLARE SECTION ; ... EXEC SQL SELECT (100 * 12 (1234 - 354)) INTO :result FROM admin.syscalctable ; EXEC SQL SELECT (:num * 10 + ABS ((360 - :val))) INTO :result FROM admin.syscalctable ; EXEC SQL SELECT NEXT_DAY (TO_DATE (11/12/1992), WEDNESDAY) INTO :dtval FROM admin.syscalctable ; ... 5.4 Using c-treeSQL for Condition Evaluation A c-treeSQL SELECT statement can be used for condition evaluation in an ESQL program. The condition evaluation is done using the SYSCALCTABLE. The following example shows the usage of the SELECT statement to check whether the ship_date is valid: Example Using c-treeSQL for Condition Evaluation EXEC SQL SELECT INTO FROM WHERE 1 :result admin.syscalctable :ship_date > SYSDATE AND :ship_date < ADD_MONTHS (:order_date, 1) ; if (sqlca.sqlcode == 0) printf ("ship_date valid ") ; else if (sqlca.sqlcode == SQL_NOT_FOUND) All Rights Reserved 59 www.faircom.com ESQL Application Development printf ("ship_date invalid ") ; else printf ("Error ") ; The previous example returns the value 1 if the validation is successful. If not, the validation is unsuccessful. 5.5 Using Indicator Variables Programs can use indicator variables along with input and output host variables. With input host variables, programs can insert a NULL value by setting the indicator variable is set to -1. With output variables, programs check indicator variables for NULL values and other error conditions. The value of an indicator variable is interpreted as given below: 0 The value has been placed in the host variable and is not NULL and has not been truncated. -1 The returned value is NULL and the value of the host variable is not defined. >0 The returned value was truncated since the host variable size was too small. The indicator value is the actual value length before truncation. When a query is made, it is suggested that an indicator variable be used to check for NULL values, on columns that can contain NULL values. 5.6 Using Scalar Functions Scalar functions take as arguments a collection of values derived from one or more columns corresponding to one row from either a database table or an intermediate result table and returns one value. Salar Functions used in c-treeSQL Statements EXEC SQL SELECT order_no, product FROM orders WHERE ABS (qty - :old_qty) > 10000 ; EXEC SQL SELECT order_no, product, qty FROM orders WHERE order_date = TO_DATE ('01/02/1993') ; EXEC SQL SELECT MONTHS_BETWEEN (SYSDATE, order_date) FROM orders WHERE order_no = 1005 ; The DECODE function accepts the column name, column value and its substitute value. Optionally, a default value can be specified. All Rights Reserved 60 www.faircom.com ESQL Application Development DECODE Example SELECT ename, DECODE (deptno, 10, 'ACCOUNTS 20, 'RESEARCH 30, 'SALES 40, 'SUPPORT 'NOT ASSIGNED' ) FROM employee ; ', ', ', ', In the above example, the column deptno is compared with the department code and the corresponding department name is returned. If no match is found, the default value, NOT ASSIGNED, is returned. The DECODE function is similar to the switch statement in C. The NVL function can be used to check whether a column value is NULL. If NULL, a substitute value can be returned. Consider the following example: EXEC SQL SELECT salary + NVL (commission, 0) FROM employee ; In the above example, a zero value is substituted if the column commission contains NULL value. 5.7 Using Static and Dynamic Statements Static c-treeSQL statements are simple and easy to use relative to dynamic c-treeSQL statements. Use static c-treeSQL statements wherever possible. All Rights Reserved 61 www.faircom.com 6. Connection Management in ESQL 6.1 Introduction This chapter describes connection management statements in ESQL and discusses the following statements that can be used in an ESQL program: CONNECT SET CONNECTION DISCONNECT The ESQL statements in an ESQL program are used to access and manipulate data in a database. In order to access/manipulate the database, it is necessary to have a valid connection with the database. This accessibility is managed by using the connection management statements. Connection management statements can be used to make a connection to a database, set an existing connection as current or to drop an existing connection. The following are the connection management statements in ESQL: CONNECT - Enables an ESQL application to establish a connection with a database. The database specified by the CONNECT statement becomes the current connection. SET CONNECTION - Allows the application to make a particular database connection current. DISCONNECT - Terminates the connection between an application and the associated database. Note: The database must be started successfully before an ESQL program can connect to it. 6.2 The CONNECT Statement The CONNECT statement establishes a valid connection with a database. There are several types of database connections possible: Using a connection name By default connection To a remote database Connection Using a Connection Name A simple CONNECT statement accepts the database name and the connection name as arguments to make a valid connection. The format for this statement is as shown: All Rights Reserved 62 www.faircom.com Connection Management in ESQL EXEC SQL CONNECT TO database_name AS connection_name ; For example, to connect to a database custdb using the connection name conn_1, the statement would be: EXEC SQL CONNECT TO 'custdb' AS 'conn_1' ; The connection name, conn_1, has to be unique. If the connection name is not specified, then the database name is taken as the connection name. For example, consider the above example without the connection name specification: EXEC SQL CONNECT TO 'custdb' ; Here the connection name is taken to be custdb. Connection by Default The CONNECT statement allows connection to a default database using the DEFAULT keyword. The default database is specified by the environment variable DB_NAME. To connect to the default database the CONNECT statement would be: EXEC SQL CONNECT TO DEFAULT; Note that no connection name is specified in the above statement. No connection is needed for the default connection since this connection can always be referred to using the keyword DEFAULT. If an application executes an SQL statement before connecting to a database, an attempt is made to connect to the environment defined database, if any. If the connection is successful, the c-treeSQL statement is executed on that database. Connection to a Remote Database A connection to a database can be made either in the local mode or in the remote mode. At most one connection could be in the local mode. For example, to connect to the custdb database in the local mode and associate this connection with a connection name conn_1, the statement would be: EXEC SQL CONNECT TO '6597@localhost:custdb' as 'conn_1' ; Here the string “6597@localhost:custdb” is referred to as the connect string. The connect string specifies the port, the target host for the database, and the database name. To connect to a database in the remote mode, the statement would be: EXEC SQL CONNECT TO '6597@remotehost:salesdb' as 'conn_2' ; Here “6597@remotehost:salesdb” is the connect string that has the database name, salesdb, to be connected to and conn_2 is the connection name associated with this connection. remotehost is the name of the remote machine having the database salesdb. All Rights Reserved 63 www.faircom.com Connection Management in ESQL 6.3 The SET CONNECTION Statement The SET CONNECTION statement lets the application switch between one valid connection to another. It resumes the connection associated with the connection name, restoring the context of that database to its exact state that prevailed at the time of suspension. For example, to set the database associated with the connection name conn_1 as the current database, the statement would be: EXEC SQL SET CONNECTION 'conn_1' ; Here, conn_1 is the connection name associated with a connection. The connection name must have been previously established by a CONNECT statement and must not have been terminated by a DISCONNECT statement. To set the default connection as current, the statement would be: EXEC SQL SET CONNECTION DEFAULT; 6.4 The DISCONNECT Statement The DISCONNECT statement terminates the connection between an application and a database. For example, to disconnect the connection associated with the connection name conn_1, the c-treeSQL statement would be: EXEC SQL DISCONNECT 'conn_1' ; If the DISCONNECT statement specifies the current connection, then c-treeSQL makes the connection to the default database (made through an earlier CONNECT TO DEFAULT statement) the current connection. Otherwise, there is no current connection. To disconnect all connections, the statement would be: EXEC SQL DISCONNECT ALL; When the option ALL is specified, all established connections are disconnected. After the execution of this statement, a current connection does not exist. To disconnect the current connection, the statement would be: EXEC SQL DISCONNECT CURRENT; When the option CURRENT is specified, the current connection, if any, is disconnected. Here too, the connection to the default database, if any, is made the current connection; otherwise, no current connection exists. To disconnect the default connection, the statement would be: EXEC SQL DISCONNECT DEFAULT; If the default connection happens to be the current connection, there is no current connection after a DISCONNECT DEFAULT statement. All Rights Reserved 64 www.faircom.com Connection Management in ESQL All Rights Reserved 65 www.faircom.com 7. c-treeSQL Data Definition Statements 7.1 Introduction This chapter introduces the data definition statements (DDL) that can be used in an ESQL program and discusses: Statements to create/drop tables, views, and indices Integrity constraints Long running transactions 7.2 Creating/Dropping Tables This section describes creating and dropping tables in ESQL. Creating Tables The CREATE TABLE statement allows creation of a new table and definition of its columns and their data types in an existing database. A sample code using CREATE TABLE statement in an ESQL program is shown below: Example Creating Tables ... /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; /* create a table named customer in the database */ EXEC SQL CREATE TABLE customer ( CUST_NO INTEGER NOT NULL, cstname CHAR (30), street CHAR (30), city CHAR (20), state CHAR (2) ) ; if (sqlca.sqlcode) { fprintf (stderr, "Create table statement failed (%ld : %s) \n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; All Rights Reserved 66 www.faircom.com c-treeSQL Data Definition Statements exit (1); } /* Commit changes */ EXEC SQL COMMIT WORK ; printf ("Table customer created. \n"); /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; ... The CREATE TABLE statement shown above specifies the table name, customer, for the table to be created. In addition, the statement specifies the column definitions such as the column name and the column type. The integer column, CUST_NO, specified as NOT NULL indicates that no row in the table customer can have a NULL value in the column, CUST_NO. The CREATE TABLE statement allows specification of DEFAULT clause along with a column definition. The DEFAULT clause specifies the default value to be used for a column, if the value for the same is not supplied while inserting the row. The following CREATE TABLE statement shows the usage of the DEFAULT clause: CREATE TABLE employee ( empno INTEGER NOT NULL, deptno INTEGER DEFAULT 10 ) ; In this example, a default value of 10 is specified for the column deptno. Dropping Tables The DROP TABLE statement deletes all data and indices for a table and erases its entry in the system catalog. The following example uses the DROP TABLE statement to drop the table tmp_customer. Example Dropping Tables ... /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; /* drop the table tmp_customer from the database */ EXEC SQL DROP TABLE tmp_customer ; if (sqlca.sqlcode) { fprintf (stderr, "Drop table statement failed (%ld : %s) \n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1); } /* Commit changes */ EXEC SQL COMMIT WORK ; All Rights Reserved 67 www.faircom.com c-treeSQL Data Definition Statements printf ("Table dropped. \n"); /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; ... 7.3 Creating/Dropping Indices This section discusses creating and dropping indices in ESQL. Creating Indices The CREATE INDEX statement creates an index on one or more columns of a table. The existence of an index improves the accessing speed for rows in a table. The following example shows how to use the CREATE INDEX statement in an ESQL program: Example Creating Indices ... /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; EXEC SQL CREATE INDEX idx_cust ON customer (CUST_NO ASC) ; if (sqlca.sqlcode) { fprintf (stderr, "Create index statement failed (%ld : %s) \n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1); } /* Commit changes */ EXEC SQL COMMIT WORK ; printf ("Index idx_cust created. \n"); /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; ... The index in the previous example is specified on only one column, CUST_NO, and the index is specified to be of ascending order on the value of the CUST_NO column. The index can also be specified to be descending on a column value using the keyword DESC. All Rights Reserved 68 www.faircom.com c-treeSQL Data Definition Statements Dropping Indices The DROP INDEX statement is used to delete a table index. The following example uses the DROP INDEX statement to drop the index idx_cust, on the table customer. Example Dropping Indices ... /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; /* drop the index idx_cust from the database */ EXEC SQL DROP INDEX idx_cust ON customer ; if (sqlca.sqlcode) { fprintf (stderr, "Drop index statement failed (%ld : %s) \n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1); } /* Commit changes */ EXEC SQL COMMIT WORK ; printf ("Index dropped. \n"); /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; ... 7.4 Creating/Dropping Views This section discusses creating and dropping views in ESQL. Creating Views The CREATE VIEW statement allows creation of a view with the specified name on existing tables or views. The following example shows the usage of CREATE VIEW statement in ESQL programs: Example Creating Views ... /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; /* create a view ne_customer in the database */ EXEC SQL CREATE VIEW ne_customer AS SELECT CUST_NO, name, street, city, state All Rights Reserved 69 www.faircom.com c-treeSQL Data Definition Statements FROM customer WHERE state IN ('NH', 'MA', 'NY', 'ME', 'VT') ; if (sqlca.sqlcode) { fprintf (stderr, "Create view statement failed (%ld : %s) \n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1); } /* Commit changes */ EXEC SQL COMMIT WORK ; printf ("View ne_customer created. \n"); /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; ... The previous example shows creation of a view ne_customer on the table customer. Dropping Views The DROP VIEW statement deletes an existing view from the database. The following example shows the use of a DROP VIEW statement to drop the view, ne_customer on the table customer. Example Dropping Views ... /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; /* drop a view, newcust, from the database */ EXEC SQL DROP VIEW ne_customer ; if (sqlca.sqlcode) { fprintf (stderr, "Drop view statement failed (%ld : %s). \n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1); } /* Commit changes */ EXEC SQL COMMIT WORK ; printf ("View dropped. \n"); /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; ... All Rights Reserved 70 www.faircom.com c-treeSQL Data Definition Statements 7.5 Integrity Constraints Integrity constraints are the constraints defined on base tables in order to ensure the data integrity in a database. Integrity constraints could either be a specification of uniqueness for values of a column, validation for values of a column, or referential integrity constraints. Referential integrity ensures that the relationships among different rows of the same or different tables are valid. For example, the referential integrity ensures that a master row is inserted before a detail row and a detail row is deleted before the master row. Need for Integrity Constraints The need for integrity constraints arises because of the necessity that the data in a database must be valid and consistent at any point of time. For example, in the table containing employee information, it is to be ensured that the employee numbers be unique. This can be ensured by specifying a constraint on the column containing the employee number. Similarly, for each order entry made in the orders table, it is to be ensured that the associated item entry be present in the items table. This can be ensured by specifying a referential integrity constraint on the column containing the item code in the orders table. Types of Integrity Constraints Integrity constraints can be of the following types: Check constraints Primary key specification Candidate key specification Referential constraints An integrity constraint can optionally be referred to by its name. The following example shows the specification of the constraint name, prim_constr, on the supplier_item table: CREATE TABLE supplier_item ( supp_no INTEGER NOT NULL, item_no INTEGER NOT NULL, qty INTEGER NOT NULL DEFAULT 0 CONSTRAINT prim_constr PRIMARY KEY (supp_no, item_no) ) ; In the above example, note that the constraint name is specified using the keyword, CONSTRAINT. The following sections give more information on various types of constraints. Check Constraints It is necessary that the values entered for a row be valid, so that the data in the database remains consistent. For example, while entering city names into the supplier table, the value must correspond to one of the cities where the suppliers are located. Hence, whenever city name is entered, a check has to be made so that the value corresponds to one of the valid city names. All Rights Reserved 71 www.faircom.com c-treeSQL Data Definition Statements These sorts of validations can be achieved by specifying CHECK constraints during the definition of the table schema for which validation is required. Check constraints are used where a column has to be restricted to contain only a set of valid values. The following example shows the specification of check constraint on the supplier table: CREATE TABLE supplier ( supp_no INTEGER NOT NULL, name CHAR (30), status SMALLINT, city CHAR (20) CHECK ( supplier.city IN ('NEWYORK', 'BOSTON', 'DALLAS')) ) ; In the above example, the column city has a check constraint that validates whether the city is one of NEWYORK, BOSTON, or DALLAS. A check constraint on a table specifies a condition on the column values of a row in that table. Whenever an INSERT/UPDATE operation is done on a table containing check constraints, the column values are validated. The INSERT/UPDATE operation would be successful only if the validation is successful. A check constraint can be specified at the column level or at the table level. The following sections discuss the column level and table level check constraints. Column-Level Check Constraint In an application, it might be necessary that a particular column be checked for valid data whenever an attempt is made to insert or update values for that column. For example, it might be necessary that the city name entered for the supplier table is not MOSCOW. A column-level check constraint is used for such validations. The column level check constraint on the table supplier could be specified as: CREATE TABLE supplier ( supp_no INTEGER NOT NULL, name CHAR (30), status SMALLINT, city CHAR (20) CHECK ( supplier.city <> 'MOSCOW') ) ; In the above example, the specification of the check constraint involves only the city column. Whenever an INSERT/UPDATE operation is done on the supplier table involving the city column, a validation is done on that column so that the column does not contain the value MOSCOW. If the INSERT/UPDATE statement is given such that it violates the check condition, then a constraint violation error is indicated. For example, the following INSERT statement results in an error and the corresponding row is not inserted into the table. INSERT INTO supplier VALUES (1001, 'Alexander', 20, 'MOSCOW') ; Table-Level Check Constraint Some applications might have a need to specify a constraint on more than one column of a table. For example, if a validation check has to be made on the supplier status along with the supplier city, the check constraint could be specified as: CREATE TABLE supplier ( supp_no INTEGER NOT NULL, All Rights Reserved 72 www.faircom.com c-treeSQL Data Definition Statements name status city CHAR (30), SMALLINT CHECK (supplier.status BETWEEN 1 AND 100 ), CHAR (20) CHECK (supplier.city IN ('NEWYORK', 'BOSTON', 'CHICAGO')), CHECK (supplier.city <> 'CHICAGO' OR supplier.status = 20) ) ; A check constraint is defined at table level if the check condition involves one or more columns. In the above example, the table-level check constraint validates such that if city is CHICAGO then the status should be 20. Since the check constraint specification involves more than one column, it has to be specified at the table level. If the INSERT/UPDATE statement is given such that it violates the check condition then an error is indicated. For example, the following are invalid INSERT statements for the table supplier shown above: INSERT INTO supplier VALUES (1001, 'John', 40, 'CHICAGO') ; 7.6 Primary Keys An application might require that database table contain one or more columns that can uniquely identify a row. For example, in a supplier table, it is necessary that the column supp_no uniquely identify a row. Every row of the table is uniquely identified by this column value. A single column or a group of columns that is the principal unique identifier of the table is referred to as the primary key. A table can contain only one primary key constraint. The following example shows the creation of a primary key column on the table supplier. CREATE TABLE supplier ( supp_no INTEGER NOT NULL PRIMARY KEY, name CHAR (30), status SMALLINT, city CHAR (20) ) ; During an INSERT operation, if a duplicate value is given for a primary key column, the INSERT operation results in an error. Column-Level Primary Key Constraint In a database table, there might be only one column that distinguishes the given row from other rows. That is, a single column is the unique identifier of the table. For example, the column supp_no is a column level primary key of the table supplier. Column-level primary key constraints are defined in the column definitions of a table. The following example shows the creation of the column-level primary key on the supplier table. CREATE TABLE supplier ( supp_no INTEGER NOT NULL PRIMARY KEY, name CHAR (30), status SMALLINT, city CHAR (20) ) ; All Rights Reserved 73 www.faircom.com c-treeSQL Data Definition Statements In the above example, the column supp_no is a unique identifier of the table supplier and the key consists of only one column. Hence it is defined at column level. Table-Level Primary Key Constraint In some database tables, it might not be possible to uniquely identify a row with just one column. But there might exist a combination of columns that when taken together, can uniquely identify a row. For example, the columns supp_no, item_no uniquely identify a row of the table supplier_item. Hence, a combination of columns that form a primary key should be specified at the table level. The following example shows the table level primary key specification: CREATE TABLE supplier_item ( supp_no INTEGER NOT NULL, item_no INTEGER NOT NULL, qty INTEGER NOT NULL DEFAULT 0 CONSTRAINT prim_constr PRIMARY KEY (supp_no, item_no) ) ; Since more than one column (supp_no, item_no) are contained in the primary key, the constraint is defined at the table level. In the above example, the constraint prim_constr is the primary key of table supplier_item. 7.7 Candidate Keys A column or a set of columns from a table are to be declared as a candidate key, if it is to be enforced that the values for the column or the set of columns be distinct for each row of the table. For example, in an employee table,the employee number uniquely identifies the row, and is usually the primary key of the employee table. But there exists another column containing the social security number for the employee. Since it is to be enforced that the values for this column be distinct for each row in the table, this column can be declared as a candidate key. The following example shows the specification of a candidate key on the employee table: CREATE TABLE employee ( empno INTEGER NOT NULL PRIMARY KEY, ss_no INTEGER NOT NULL UNIQUE, ename CHAR (19), sal NUMERIC (10, 2), deptno INTEGER NOT NULL ) ; A column is declared as a candidate key using the keyword UNIQUE. It can be noted that the UNIQUE specification has to be preceded by a NOT NULL specification for that column. Like a primary key, a candidate key also uniquely identifies a row in a table. But, whereas a table can have at most one primary key, there could be any number of candidate keys on a table. During the INSERT/UPDATE operation, if a duplicate value is given for a candidate key, the INSERT/UPDATE operation results in an error. All Rights Reserved 74 www.faircom.com c-treeSQL Data Definition Statements Column-Level Candidate Key Constraint In an application, it might be necessary that a column be specified as the unique column. For example, the column ss_no in table employee must be unique, since it contains an employee’s Social Security number. Such a unique column can be specified using the column level candidate key constraint. A column-level candidate key constraint contains only one column as a candidate key. It is specified in the column definition. Consider the following example: CREATE TABLE employee ( empno INTEGER NOT NULL PRIMARY KEY, ss_no INTEGER NOT NULL UNIQUE, ename CHAR (19), sal NUMERIC (10, 2), deptno INTEGER NOT NULL ) ; In the above example, the column ss_no is the candidate key of the table employee. Table-Level Candidate Key Constraint If an application requires that the values for a combination of columns be unique, then the candidate key specification is to be done at the table level. For example, in an order_item table the columns order_no and item_no together form a unique key. Consider the following example: CREATE TABLE order_item ( order_no INTEGER NOT NULL, item_no INTEGER NOT NULL, qty INTEGER, price MONEY UNIQUE (order_no, item_no) ) ; In the above example, the combination of columns order_no and item_no is the unique identifier of the table order_item. 7.8 Referential Constraints For some applications, a table might require that each row’s values for a column, or for a group of columns taken together (provided none are null), be identical to a corresponding set of columns in some other table in the database. The requirement that a matching row exist in the referenced table for each referencing row is called a referential constraint. For example, an employee number in the employee table might be within a valid range, but the employee number might no longer exist in the master employee table because the employee has resigned. Referential constraints are used for such validation of data in the database. Consider the following example: CREATE TABLE supplier_item ( suppl_no INTEGER NOT NULL PRIMARY KEY, item_no INTEGER REFERENCES item (item_no), quantity INTEGER, All Rights Reserved 75 www.faircom.com c-treeSQL Data Definition Statements price MONEY ) ; In the above example, the REFERENCES clause in the supplier_item table definition means that values in the column supplier_item. item_no must either be NULL or be equal to some value in the column item_no in another table, item. The column item_no is called the foreign key of table supplier_item. A foreign key is a column or combination of columns that references a primary or a candidate key of some other table. A foreign key value is either NULL or exists as a primary key value. The table that contains a foreign key is called the referencing table and the table that contains the primary or the candidate key is called the referenced table. A referential constraint can be specified at the column level or at the table level. During INSERT/UPDATE operations on a table containing a foreign key, a check is made to see if the foreign key value matches with a corresponding primary key value. If it does not match, the INSERT/UPDATE operation results in an error. During INSERT/UPDATE operations on a table containing a primary/candidate key, if the values to be deleted/updated match the foreign key of the referencing table, the INSERT/UPDATE operation results in an error. Hence, a value corresponding to a primary/candidate key cannot be updated/deleted if there are references to it. When a table containing a primary/candidate key is to be dropped, a check is made as to whether the table has any references to it. If there are tables containing foreign keys that reference the primary/candidate key of the table to be dropped, the drop operation results in an error. Column-Level Foreign Key Constraint If a foreign key constraint specification involves only one column, then the foreign key constraint can be specified at the column level. Consider the following example: CREATE TABLE supplier_item ( supp_no INTEGER NOT NULL PRIMARY KEY, item_no INTEGER NOT NULL REFERENCES item, qty INTEGER ) ; In the above example, item_no is the foreign key, referencing the table item. Since the foreign key involves only one column, they are defined at the column level. If a foreign key references a candidate key, then the specification of the referenced column list is mandatory. If a foreign key references a primary key, then the referenced column list is optional. Consider the following example: CREATE TABLE invoice ( inv_no INTEGER NOT NULL PRIMARY KEY, item_no INTEGER REFERENCES item, part_no CHAR (3) NOT NULL REFERENCES parts (part_no), qty INTEGER NOT NULL, amount MONEY NOT NULL, balance MONEY NOT NULL ) ; All Rights Reserved 76 www.faircom.com c-treeSQL Data Definition Statements In the above example, item_no references the primary key of table item. The column part_no references primary or candidate key of table parts depending on whether part_no is the primary key or the candidate key of the table parts. Table-Level Foreign Key Constraint If a foreign key constraint specification involves more than one column, then the constraint is to be specified at the table level. Consider the following example: CREATE TABLE hours_worked ( empno INTEGER NOT NULL, projno INTEGER NOT NULL, date DATE, hours TIME FOREIGN KEY (empno, projno) REFERENCES assignments (empno, projno) ) ; In this example, the foreign key (empno, projno) of table hours_worked, references the primary/candidate key (empno, projno) of table assignments. Since the foreign key involves more than one column, it is defined at the table level. 7.9 Handling Cycles in Referential Integrity A cycle is formed when there are a list of base tables, where the first table has a foreign key that references the second table, the second table has a foreign key that references the third table and so on and the last table has a foreign key that references the first table. Consider the following examples. Example Creating Tables in “Cycles” CREATE TABLE parts part_no part_name distrib_no ( INTEGER NOT NULL PRIMARY KEY, CHAR (19), INTEGER REFERENCES distributor ) ; CREATE TABLE distributor ( distrib_no INTEGER NOT NULL PRIMARY KEY, distrib_name CHAR (19), address CHAR (30), phone_no CHAR (10), part_no INTEGER REFERENCES parts ) ; In the above example, the column distrib_no of table parts references the primary key of the table distributor and the column part_no of table distributor references the primary key of table parts. That is, each of the two tables is referencing the other. Hence a cycle is formed. A special case of the cycle in referential integrity is when a foreign key of a table references the primary key of the same table. The following example shows an example of such a cycle: All Rights Reserved 77 www.faircom.com c-treeSQL Data Definition Statements Example Foreign Key Referring to Same Table CREATE TABLE employee ( empno INTEGER NOT NULL PRIMARY KEY, ename CHAR (30) NOT NULL, deptno INTEGER NOT NULL, mgr_code INTEGER REFERENCES employee(empno) ) ; Creation of Tables in Cycles Creation of tables in cycles involves the following steps: First, a table is created with a reference to a table that is not yet created. The table creation is done, but is marked incomplete. No operations (INSERT/UPDATE/SELECT/DELETE) are allowed on an incomplete table. Next, when the table with a primary/candidate key is created, the previous table definition becomes complete. If this table also contains the foreign key referencing a table that is not yet created, this table also is marked incomplete. This procedure follows till the last table is created. Insertion of Rows in Cycles Insertion of rows into tables where cycles are defined involves two steps. Insert the rows into one of the tables that forms the cycle with NULL value in the foreign key column(s). If the foreign key is NULL, no check is made to match the foreign key to the corresponding primary key. Hence the insertion would be successful. After the value corresponding to the primary key is inserted, update the foreign key values of the referencing table. The following example shows insertion/updating of values into the employee table: CREATE TABLE employee ( empno INTEGER NOT NULL PRIMARY KEY, ename CHAR (30) NOT NULL, deptno INTEGER NOT NULL, mgr_code INTEGER REFERENCES employee (empno) ) ; INSERT INSERT INSERT INSERT INTO INTO INTO INTO employee employee employee employee VALUES VALUES VALUES VALUES (100, (500, (101, (501, 'JOHN', 10, NULL) ; 'MARY', 30, NULL) ; 'ANITA', 10, NULL) ; 'ROBERT', 30, NULL) ; UPDATE employee set mgr_code = 101 where empno = 100 ; UPDATE employee set mgr_code = 501 where empno = 500 ; In this example, the column mgr_code references the column empno of the same table that forms the special case of a cycle. As shown above, the NULL values are inserted in column mgr_code and after all the rows are entered, the values of the column mgr_code are updated. Dropping the Tables in Cycles Dropping a table in a cycle involves the following steps: All Rights Reserved 78 www.faircom.com c-treeSQL Data Definition Statements Drop the foreign key constraints that are referencing the table. Drop the table. Consider the following table definitions: CREATE TABLE parts part_no part_name distrib_no ( INTEGER NOT NULL PRIMARY KEY, CHAR (19), INTEGER CONSTRAINT parts_constr REFERENCES distributor ) ; CREATE TABLE distributor distrib_no distrib_name address phone_no part_no ( INTEGER NOT NULL PRIMARY KEY, CHAR (19), CHAR (30), CHAR (10), INTEGER REFERENCES parts ) ; The following example shows dropping these tables in cycles: ALTER TABLE parts DROP CONSTRAINT parts_constr ; DROP TABLE distributor ; DROP TABLE parts ; 1. First the constraint parts_constr of table parts is dropped. 2. Next, since there are no references to table distributor, the table can be dropped. After table distributor is dropped, there are no references to table parts and hence table parts can also be dropped. 7.10 DDL Statements in Long Running Transactions In an ESQL program, Data Definition Language (DDL) statements have the same transaction semantics as other c-treeSQL statements. DDL statements must be explicitly committed or rolled back in an ESQL application. DDL statements can be executed as part of a long running transaction, but it is better to commit the DDL statements. This will avoid locking of database resources like tables or views for a longer period. This also increases the concurrency of database operations. All Rights Reserved 79 www.faircom.com 8. c-treeSQL Data Manipulation Statements 8.1 Introduction This chapter describes the usage of Data Manipulation statements (DML) in ESQL programs and discusses: Types of DML statements: • SELECT • INSERT • DELETE • UPDATE Input host variables that can be used in DML statements 8.2 Using DML Statements Data Manipulation Language (DML) statements are the most frequently used statements in an ESQL program. The SELECT statement (also called query statement) is one type of DML statement and is discussed in detail in the next chapter. DML statements are used to change data in a database in one of the three ways: INSERT - Adds one or more rows to a table. UPDATE - Modifies the data in one or more rows of a table. DELETE - Deletes one or more rows from a table. DML statements are used to modify only one table at a time. Host variable references can be made in a DML statement. The INSERT, UPDATE, and DELETE statements are discussed in more detail in the following sections. Inserting Rows into a Table An INSERT statement adds one or more rows to an existing table. The following INSERT statement adds a new customer ‘LEVIEN’ to the customer table: INSERT INTO customer (CUST_NO, name, street, city, state) VALUES (1006, 'LEVIEN', '15 Heath Street', 'Scotia', 'NY') ; All Rights Reserved 80 www.faircom.com c-treeSQL Data Manipulation Statements When an INSERT statement is used in an ESQL program, host variables can be used to supply the values, as shown in the following example. Example Inserting A Row EXEC SQL BEGIN DECLARE SECTION ; long cust_no_v ; char name_v [20] ; char street_v [40] ; char city_v [10] ; char state_v [2] ; EXEC SQL END DECLARE SECTION ; /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; /* Get values for input host variables */ cust_no_v = 1006 ; strcpy (name_v, "LEVIEN") ; strcpy (street_v, "15 Heath street") ; strcpy (city_v, "Scotia") ; strcpy (state_v, "NY") ; EXEC SQL INSERT INTO customer (CUST_NO, name, street, city, state) VALUES (:cust_no_v, :name_v, :street_v, :city_v, :state_v) ; if (sqlca.sqlcode) { fprintf (stderr, "Insert statement failed (%ld : %s). \n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1); } /* Commit changes */ EXEC SQL COMMIT WORK ; printf ("Inserted one row \n\n"); /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; ... In the previous example, the values for the host variables are assigned and then inserted into the customer table using the INSERT statement. The columns of the table customer listed in the INSERT statement are referred to as the column list. The list of host variables specified in the VALUES clause of the INSERT statement is referred to as the value list. To insert more than one row, an insert statement with a subquery must be executed. The following sample code shows insertion of rows from the table customer into a table ny_customer. ... All Rights Reserved 81 www.faircom.com c-treeSQL Data Manipulation Statements EXEC SQL CREATE TABLE ny_customer ( CUST_NO INTEGER, name CHAR (20), street CHAR(40), city CHAR(15), state CHAR(2) ); EXEC SQL INSERT INTO ny_customer (CUST_NO, name, street, city, state) SELECT CUST_NO, name, street, city, state FROM customer WHERE state = 'NY' ; ... It is necessary that the table ny_customer be created first before insertion is done. The above query expression option allows for insertion of multiple rows at a time. All the column values in the INSERT statement must be returned by the query expression. Deleting Rows from a Table A DELETE statement deletes one or more rows from an existing table, depending on the selection criteria used in the WHERE clause. The following example shows the use of a DELETE statement to delete a row in the customer table: Example Deleting a Row ... /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; /* Get value for cust_no_v */ cust_no_v = 1005 ; EXEC SQL DELETE FROM customer WHERE CUST_NO = :cust_no_v; if (sqlca.sqlcode) { fprintf (stderr, "Delete statement failed (%ld : %s)\n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1); } /* Commit changes */ EXEC SQL COMMIT WORK ; printf ("Deleted one row \n\n"); All Rights Reserved 82 www.faircom.com c-treeSQL Data Manipulation Statements /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; ... In the previous example, the host variable cust_no_v is used to delete the row with CUST_NO 1005 from the customer table. The deletion can be on more than one row if the WHERE clause selects multiple rows. The following example shows the deletion of all orders from the orders table where order_date is less than 2/2/1993. EXEC SQL DELETE FROM WHERE orders order_date < TO_DATE ('02/02/1993') ; Updating Rows in a Table An UPDATE statement modifies data in one or more rows of a table. The following UPDATE statement updates the phone number of a row in the customer table. Example Updating a Row ... /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; cust_no_v = 1004 ; EXEC SQL UPDATE customer SET phone = '(203)-465-2703' WHERE CUST_NO = :cust_no_v ; if (sqlca.sqlcode) { fprintf (stderr, "Update statement failed (%ld : %s)\n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1); } /* Commit changes */ EXEC SQL COMMIT WORK ; printf ("Update Successful\n\n"); /* Disconnect from the database */ EXEC SQL D The following UPDATE statement gives a 10 percent increase in salary to all employees of department 10. Note that multiple rows are updated here by one statement. EXEC SQL All Rights Reserved 83 www.faircom.com c-treeSQL Data Manipulation Statements UPDATE employee SET sal = sal * 1.1 WHERE deptno = 10 ; 8.3 Input Host Variables in DML Statements The host variables that are used for input in a c-treeSQL statement are referred to as input host variables. These variables must be declared in the declare section prior to their usage in the ESQL program. They can be used in an ESQL statement, wherever a constant can be used. DML statements can have only input host variable references. The following are some examples showing input host variable references in DML statements: EXEC SQL INSERT INTO customer (CUST_NO, name, street, city, state) VALUES (:cust_no_v, :name_v, :street_v, :city_v, :state_v) ; EXEC SQL UPDATE SET WHERE customer phone = '(203)-465-2703' CUST_NO = :cust_no_v ; All the host variable references, as can be seen, must be prefixed with a colon while using them in the c-treeSQL statements. All Rights Reserved 84 www.faircom.com 9. Query Statements 9.1 Introduction This chapter describes c-treeSQL queries and their usage in ESQL programs, introduces the SELECT statement and discusses: Query statements with host variables Queries returning single row Queries returning multiple rows Cursors and their usage Array fetches 9.2 Elements of a Query ESQL supports SELECT statements for performing queries. A SELECT statement could return one or more rows. The following example shows a SELECT statement that retrieves the customer name and city values for a given customer number. Example Basic Query Elements EXEC SQL BEGIN DECLARE SECTION ; CHAR CHAR LONG name_v [30] ; city_v [20] ; cust_no_v ; EXEC SQL END DECLARE SECTION ; ... EXEC SQL SELECT name, city INTO :name_v, :city_v FROM customer WHERE CUST_NO = :cust_no_v; The previous example uses the following four clauses of the SELECT statement: SELECT clause All Rights Reserved 85 www.faircom.com Query Statements INTO clause FROM clause WHERE clause The column names specified in the SELECT clause is referred to as the SELECT list. In the above example, the columns named name and city form the SELECT list. Based on the selection criteria, specified in the WHERE clause, values are returned into the host variables name_v and city_v. Queries can return multiple rows depending on the selection criteria. Note: If a query returns more than one row, the INTO clause is not used in the SELECT statement; instead a cursor is used to return the results of a query. Input Host Variables in Query Statements The host variables that are used as input variables in the c-treeSQL statement are referred to as input host variables. In a SELECT statement, input host variables can be used in the WHERE clause. In the previous example, the host variable, cust_no_v used in the WHERE clause is an input host variable. Output Host Variables in Query Statements The host variables that are used for receiving the query results, are referred to as output host variables. In a query statement the output host variables are specified in the INTO clause. In the example given in “Elements of a Query (page 85)” the host variables, name_v and city_v specified in the INTO clause are output host variables. Whenever the output host variables are used in a SELECT statement, the number of output host variables specified must equal the number of columns specified in the SELECT list. 9.3 Queries Returning a Single Row Queries returning a single row are the simplest of queries. When a query is known to return a single row, then the INTO clause can be used to obtain the result of the query. The following example shows a query on the customer table to retrieve the columns name, city, and state. Example Query Returning a Single Row ... /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; EXEC SQL SELECT INTO FROM WHERE name, city, state :name_v, :city_v, :state_v customer CUST_NO = 1001 ; if (sqlca.sqlcode) { fprintf (stderr, All Rights Reserved 86 www.faircom.com Query Statements "Select statement failed (%ld : %s)\n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1); } printf ("name : %s, city : %s, state : %s\n", name_v, city_v, state_v); /* Commit changes */ EXEC SQL COMMIT WORK ; /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; ... Note that the statement execution would fail if the above form of SELECT statement is used for statements that return more than one row. 9.4 Queries Returning Multiple Rows When a query returns more than one row, you must use a cursor in association with a SELECT statement. The following sections discuss the use of cursors. Introduction to Cursors A cursor is a c-treeSQL object that is associated with a specific SELECT statement. A named cursor is associated with a SELECT operation by declaring the cursor. To access the rows corresponding to the SELECT operation, the user must: Associate a cursor with a query with the DECLARE CURSOR statement. Open the cursor with the OPEN statement. Execute a loop on the opened cursor to retrieve all the rows in the result set with FETCH statements. Close the cursor with the CLOSE statement. A cursor can be in one of the two states: open or closed. When a cursor is in open state, it is associated with an active set and points to the current row, before the first row, or after the last row. When the query operation is completed, the cursor is closed using the CLOSE statement. When a cursor is in the closed state, the cursor no longer is associated with an active set, although it remains associated with the SELECT statement. The following sections explain the use of cursors to process rows returned by a SELECT statement. All Rights Reserved 87 www.faircom.com Query Statements Associating a Cursor with a Query The DECLARE CURSOR statement is used to associate a cursor with a SELECT statement. The DECLARE CURSOR statement declares a cursor, by assigning it a name and associating it with a query (SELECT statement). For more information on the DECLARE CURSOR statement, see "DECLARE CURSOR" (page 155). The syntax for DECLARE cursor is as shown below: EXEC SQL DECLARE cursor_name CURSOR FOR SELECT ... FROM ... The following example shows the declaration of a cursor, cust_cur, for a SELECT statement: EXEC SQL DECLARE cust_cur CURSOR FOR SELECT name, city, state FROM customer WHERE CUST_NO = :cust_no_v; The DECLARE CURSOR statement is a declarative c-treeSQL statement. The DECLARE CURSOR statement for a cursor must occur before any other c-treeSQL statement referencing that cursor. ESQL cannot interpret a reference to a cursor that is not declared. A cursor declared in one esqlc source file can not be referred to in another esqlc source file. The cursor name used in the DECLARE CURSOR statement must be unique. Opening a Cursor A cursor is opened using the OPEN statement. When a cursor is opened, the SELECT statement associated with the cursor is executed and the result set is identified. Such a result set is referred to as the active set. The cursor always points to a row in the active set. This row is referred to as the current row. The rows that are retrieved as a result of the execution form the active set. For more information on the OPEN statement, see "OPEN" (page 163). The syntax for the OPEN statement is shown below: EXEC SQL OPEN cursor_name ; The following sample code shows the usage of the OPEN statement: ... EXEC SQL DECLARE cust_cur CURSOR FOR SELECT name, city, state FROM customer WHERE CUST_NO = :cust_no_v; EXEC SQL OPEN cust_cur ; ... The OPEN statement puts the cursor in the open state. The OPEN statement causes the SELECT statement to be processed with the current program variables and leaves the cursor pointing just before the first row of the resulting active set. While the cursor is in the open state, subsequent All Rights Reserved 88 www.faircom.com Query Statements changes to any program variables that appear in the SELECT statement associated with the cursor, do not affect the active set. The input host variable values are not used while the cursor is opened. Hence the result of the query is not affected if the variable values are changed after the cursor is opened. For these changes to be reflected in the results of the query, the cursor must be closed and reopened. Retrieving Rows Using a Cursor The FETCH statement is used to read the rows of the active set and return the values in host variables. The SELECT statement associated with the cursor does not include the INTO clause; rather, the INTO clause with the list of output host variables is included in the FETCH statement. For more information on the FETCH statement, see "FETCH" (page 161). The syntax of the FETCH statement is: EXEC SQL FETCH cursor_name INTO :hostvar1, :hostvar2 ... ; The following example shows fetching of rows opened by the cursor, cust_cur: Example Query Returning Multiple Rows ... /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; /* Declare the cursor for retrieving */ /* customer information. */ EXEC SQL DECLARE cust_cur CURSOR FOR SELECT name, city, state FROM customer WHERE CUST_NO = :cust_no_v; /* Open cursor */ EXEC SQL OPEN cust_cur ; /* Fetch the query results into host variables */ for (;;) { EXEC SQL FETCH cust_cur INTO :cust_no_v, :name_v, :city_v ; if (sqlca.sqlcode) break ; } EXEC SQL CLOSE cust_cur ; ... Before issuing a FETCH statement, the cursor named in the FETCH statement must have been previously declared and opened. The first time the FETCH statement is executed, the cursor is positioned on the first row of the active set. This row becomes the current row. Each subsequent All Rights Reserved 89 www.faircom.com Query Statements execution of FETCH advances the cursor to the next row in the active set. The only way to return to a row that has been previously fetched is to close and reopen the cursor. If the cursor is positioned on the last row of the active set or if the active set does not contain any rows, then the execution of the FETCH statement will return the status code SQL_NOT_FOUND in the SQLCA. In this case, to do any further operations with the cursor, the cursor has to be closed and reopened. Closing a Cursor The CLOSE cursor statement puts the cursor in the closed state. Once the cursor is closed, no FETCH calls can be issued on the cursor until it is reopened. For more information on the CLOSE statement, see "CLOSE" (page 155). The syntax of the CLOSE cursor statement would be: EXEC SQL CLOSE cursor_name ; The following example shows the usage of the CLOSE cursor statement to close the cursor cust_cur. EXEC SQL CLOSE cust_cur ; No fetches can be executed against a closed cursor, as its active set becomes undefined. After the cursor is closed, no statements referring to the cursor, other than open cursor, are operative. Deleting or Updating the Current Row ESQL allows operations such as UPDATE and DELETE on the row that a cursor is currently pointing to in the active set. This is possible with the usage of the CURRENT OF cursor construct, in the WHERE clause of either the UPDATE or the DELETE statement. The format of such a WHERE clause is shown below: WHERE CURRENT OF cursor_name Note the following: Upon successful execution, the number of rows deleted/updated will be returned in sqlca.sqlerrd [2]. sqlca.sqlwarn [4] is set to ‘W’ if the DELETE/UPDATE statement does not have a WHERE clause so that unconditional deletes can be noted and the action either confirmed or rolled back. Use of the WHERE CURRENT OF clause is called to positioned DELETE/UPDATE operation: • The positioned DELETE can be used only if the cursor has been declared with the FOR UPDATE clause. The positioned DELETE operation can be specified only on an opened cursor. The cursor is first positioned on the desired row to be deleted and then the positioned DELETE operation executed. • The positioned UPDATE can only be specified on an open cursor where the cursor has been declared for a SELECT statement with a FOR UPDATE clause. The following example shows the usage of the CURRENT OF cursor construct, in an UPDATE statement: All Rights Reserved 90 www.faircom.com Query Statements ... EXEC SQL DECLARE ord_cur CURSOR FOR SELECT product, qty FROM orders WHERE order_no = :order_no_v FOR UPDATE OF qty ; EXEC SQL OPEN ord_cur ; EXEC SQL FETCH ord_cur INTO :product_v, :qty_v ; EXEC SQL UPDATE orders SET qty = :qty_v + 1000 WHERE CURRENT OF ord_cur ; ... The above example shows the updating of qty on the current row where the cursor is positioned in the active set. The positioned update can be performed only on an open cursor where the cursor has been declared for the SELECT statement with a FOR UPDATE clause. The positioned delete operation deletes the row that the cursor is currently positioned to in the active set. After the positioned delete operation, the cursor is positioned before the row immediately following the row just deleted, or after the last row if no such immediately following row exists. The following sample code shows positioned delete, to delete the current row from the orders table. ... EXEC SQL DECLARE ord_cur CURSOR FOR SELECT product, qty FROM orders WHERE order_no = :order_no_v ; EXEC SQL OPEN ord_cur ; EXEC SQL FETCH ord_cur INTO :product_v, :qty_v ; EXEC SQL DELETE FROM orders WHERE CURRENT OF ord_cur ; ... Array Fetches: Retrieving Multiple Rows with One FETCH Statement As discussed in the previous sections, the FETCH statement would return one row at a time from the active set selected by the OPEN statement. All Rights Reserved 91 www.faircom.com Query Statements ESQL also provides support for fetching multiple rows at a time from the active set. This is more efficient for fetching a large number of rows since it reduces the number of calls made to the database. This section describes using explicitly-declared esqlcarrays to retrieve multiple rows in one fetch operation. (Refer to "Using SQLDA for Array Fetches" (page 125) for information on using the SQLDA for array fetches in dynamic c-treeSQL.) Note: Array fetches are an extension to the SQL standard. All esqlc arrays (excluding character arrays) are mapped into a host language structure consisting of both the actual array and the current size of the array. The C language structure is of the following form: struct new_type_name { long tpe_size; element_type_name tpe_array[constant_id]; }; Host language statements can manipulate the array assuming that it is a structure with the same name as the array name and having two components tpe_array and tpe_size. The tpe_array component contains the actual array and the tpe_size component contains the current size of the array. (See "ESQL Reference" (page 153) for details on declaring esqlc arrays.) When esqlc executes the FETCH statement, it sets tpe_size to the actual number of rows returned. The following sample code shows the use of two arrays, customer_name_array and customer_id_array to select up to fifty rows in one fetch call. Example /* Fetch up to 50 rows in one fetch call */ #define ARRAYSZ 50 #define NAMESZ 30 EXEC SQL BEGIN DECLARE SECTION; TYPE customer_name_t IS AN ARRAY OF CHAR WITH SIZE NAMESZ ; TYPE customer_id_t IS OF TYPE LONG INTEGER ; customer_name_array IS AN ARRAY OF customer_name_t WITH SIZE ARRAYSZ ; customer_id_array IS AN ARRAY OF customer_id_t WITH SIZE ARRAYSZ ; EXEC SQL END DECLARE SECTION; ... EXEC SQL DECLARE customer_cursor CURSOR FOR SELECT name, CUST_NO FROM customer ; if (sqlca.sqlcode) goto err ; EXEC SQL OPEN customer_cursor ; if (sqlca.sqlcode) goto err ; for (;;) { All Rights Reserved 92 www.faircom.com Query Statements int i ; EXEC SQL FETCH customer_cursor INTO :customer_name_array, :customer_id_array; /* Note that in case of array fetches, one or more rows could have been returned by the current execution of FETCH statement even if the status code returned is SQL_NOT_FOUND. */ if (sqlca.sqlcode && sqlca.sqlcode != SQL_NOT_FOUND) break ; for (i = 0 ; i < customer_name_array.tpe_size ; i++) { printf ("Customer id = %ld Customer Name : %s\n", customer_id_array.tpe_array [i], customer_name_array.tpe_array [i]) ; } if (sqlca.sqlcode) break ; } if (sqlca.sqlcode != SQL_NOT_FOUND) goto err ; EXEC SQL CLOSE customer_cursor ; if (sqlca.sqlcode) goto err ; EXEC SQL COMMIT WORK ; if (sqlca.sqlcode) fprintf (stderr, "COMMIT WORK returned error %ld\n", sqlca.sqlcode) ; return ; err: EXEC SQL ROLLBACK WORK ; return ; All Rights Reserved 93 www.faircom.com 10. NULL Value Handling in ESQL 10.1 Introduction This chapter describes the handling of NULL values in ESQL and discusses: Inserting NULL values Retrieving NULL values Using NULL values in different clauses of a SELECT statement NULL values are used in a database when the value of a column is not known or when the value is not applicable. For example, when an employee has not been assigned to a department, the department number in the corresponding row could be set to a NULL value. As another example, the column commission of the employee table would be applicable only to sales persons and hence, for employees of all other departments, this column would contain a NULL value. Note that, a column value is distinguished between a numeric zero and a NULL value. Similarly, a distinction is made between a string of blanks and a NULL value. In c-treeSQL, the default value for a column is NULL, provided the column definition does not contain the DEFAULT clause. A column of any data type can have a NULL value. It can be specified that a column of any type not have NULL values using the NOT NULL clause in the CREATE TABLE statement. The usage of NULL values is discussed in the following sections. 10.2 Inserting NULL Values A NULL value can be inserted into a column when a column value is not known or not applicable. A NULL value can be inserted into a column: By default Using the NULL keyword Using indicator variables The following sections discuss each of these methods. Inserting NULL Values by Default In c-treeSQL, the default value for a column is NULL, if the column definition does not contain the DEFAULT clause. For example, consider the employee table with the following schema: All Rights Reserved 94 www.faircom.com NULL Value Handling in ESQL CREATE TABLE employee (empno ename job hiredate sal commission deptno projno INTEGER NOT NULL, CHAR(10), CHAR(10), DATE, NUMERIC (10,2), NUMERIC(10,2), INTEGER NOT NULL, INTEGER) ; The following statement inserts a row in the employee table, but omits values for some of the columns: EXEC SQL INSERT INTO employee (empno, ename, job, hiredate, sal, deptno) VALUES (8585, 'RALPH', 'CLERK', '02/02/1992', 2000, 10) ; When the above INSERT statement is executed, a null value is inserted into the columns commission and projno. A column of any type can be restricted not to have a NULL value by specifying NOT NULL in the CREATE TABLE statement for that particular column. A column for which a unique index is created can have at most one NULL value. Using the NULL Keyword to Insert NULL Values The keyword NULL can be used in the value list to indicate that a column in the column list should be assigned a NULL value. The following example shows insertion of NULL for the columns commission and projno using the NULL keyword: EXEC SQL INSERT INTO employee VALUES (8585, 'RALPH', 'CLERK', '02/02/1992', 2000, NULL, 10, NULL) ; Using Indicator Variables to Insert NULL Values Indicator variables are special variables (declared as short or SMALLINT) associated with host variables for the purpose of handling NULL values. Indicator variables can be used to insert NULL values into a column. Set the indicator variable for a particular column to be -1 and use the indicator variable along with the corresponding host variable in the value list of the INSERT statement. The following example shows insertion of NULL values for the columns commission and projno in the employee table using indicator variables: Example Using Indicator Variables to Insert NULL Values ... EXEC SQL BEGIN DECLARE SECTION ; long empno_v ; char ename_v [10] ; char job_v [10] ; All Rights Reserved 95 www.faircom.com NULL Value Handling in ESQL char hiredate_v [20] ; long sal_v ; long commission_v ; short commission_i ; long deptno_v ; long projno_v ; short projno_i ; EXEC SQL END DECLARE SECTION ; ... empno_v = 2402 ; strcpy (ename_v, 'RALPH') ; strcpy (job_v, 'CLERK') ; strcpy (hiredate_v, '02/02/1992') ; sal_v = 2000 ; commission_i = -1 ; deptno_v = 10 ; projno_i = -1 ; EXEC SQL INSERT INTO employee VALUES (:empno_v, :ename_v, :job_v, :hiredate_v, :sal_v, :commission_v:commission_i, :deptno_v, :projno_v:projno_i) ; ... This is a better programming alternative than hard coding NULL in the insert statement. Here, the indicator variable is preset to -1 so that a NULL value is used instead of the value of the host variable. 10.3 Updating with NULL Values A column value can be modified to contain a NULL value by using the UPDATE statement. This can be done by setting the desired column with the keyword NULL in the UPDATE statement. The following example shows the updating of the column projno since there is no project currently assigned to the employee with empno 2040. EXEC SQL UPDATE employee SET projno = NULL WHERE empno = 2040 ; Alternatively, a column value can be modified to contain NULL values by using indicator variables. The indicator variable can be set to -1 and used along with the host variable to set a value to NULL. The following example shows the employee table being updated using an indicator variable: projno_i = -1 ; EXEC SQL UPDATE employee SET projno = projno_v:projno_i WHERE empno = 2040 ; All Rights Reserved 96 www.faircom.com NULL Value Handling in ESQL 10.4 Retrieving NULL Values NULL values can be handled while retrieving the rows in the following ways using a SELECT statement with: An indicator variable The scalar function NVL The following sections discuss each of these methods. Using Indicator Variables to Retrieve NULL Values Indicator variables are special variables (declared as short or SMALLINT) associated with host variables for the purpose of handling NULL values. During a query, NULL values can be identified using the indicator variables along with the output host variables in the INTO clause. The following example shows how to identify NULL values while retrieving rows. Example Using Indicator Variables to Retrieve NULL Values ... EXEC SQL BEGIN DECLARE SECTION ; long empno_v ; char ename_v [10] ; char job_v [10] ; char hiredate_v [20] ; long sal_v ; long commission_v ; short commission_i ; long deptno_v ; long projno_v ; short projno_i ; ... EXEC SQL END DECLARE SECTION ; EXEC SQL SELECT ename, job, deptno, projno INTO :ename_v, :job_v, :deptno_v, :projno_v:projno_i FROM employee WHERE empno = 1250 ; if (projno_i == -1) printf ("project number is NULL\n") ; ... Using the Scalar Function NVL to Retrieve NULL values The scalar function NVL, can be used to identify NULL values in a column. The syntax of the NVL function is as shown below: All Rights Reserved 97 www.faircom.com NULL Value Handling in ESQL NVL (expression, expression) ; The NVL function returns the value of the first expression, if the first expression value is not NULL. If the first expression value is NULL, the value of the second expression is returned. The following example shows the usage of NVL to identify NULL values in the column commission of the employee table. EXEC SQL SELECT sal + NVL (commission, 0) 'Total Salary' FROM employee If the column commission is NULL, then a zero is added to the salary of the employee and returned as Total Salary. 10.5 Using NULL Values in Expressions Expressions can be used in the SELECT list for retrieving NULL values. If any value that participates in an arithmetic expression is NULL, the value of the entire expression is NULL. Consider the following example: EXEC SQL SELECT ename, sal, sal + commission FROM employee WHERE empno = 2452 ; In the above example if the commission for empno 2452 is NULL, then the value of the expression sal + commission in the SELECT list would evaluate to NULL. 10.6 Using NULL Values in the WHERE Clause A row gets selected if the search condition specified using the WHERE clause evaluates to TRUE and not if evaluated to FALSE or unknown. Consider the following WHERE clause: WHERE ((sal + commission) < 5000) AND empno = 2004 ; In the above example, if commission is NULL for empno 2004, then the search condition is not satisfied. Instead, the following search condition with an OR would evaluate to TRUE: WHERE ((sal + commission) < 5000) OR empno = 2004 ; A row containing NULL values can be selected or rejected using the search condition: column IS [NOT] NULL The following example shows the selection of employee names and department numbers for employees who have not been assigned to any project. EXEC SQL SELECT ename, deptno FROM employee WHERE projno IS NULL ; If a join is performed between two tables using the WHERE clause: All Rights Reserved 98 www.faircom.com NULL Value Handling in ESQL WHERE column1 = column2 Rows will not be selected if either of the columns column1 or column2 is NULL. Also, rows will not be selected if both column1 and column2 are NULL. 10.7 Using NULL Values in GROUP BY Clause If a GROUP BY clause is applied on a column containing NULL values, then all NULL values are grouped as a separate group. The following is an example showing the grouping of employees based on the project numbers: EXEC SQL SELECT ename, COUNT (*) FROM employee GROUP BY projno ; 10.8 Using NULL Values in ORDER BY Clause When an ORDER BY clause is applied on a column containing NULL values, the NULL value is treated as being less than any non-NULL value. Hence, when the ordering is ascending, the NULL values come first; and when the ordering is descending, the NULL values come last. The following example shows the selection of employees ordered by the project numbers: EXEC SQL SELECT ename, deptno FROM employee ORDER BY projno ; 10.9 Using NULL Values in Scalar Functions Except with scalar functions like NVL, that specifically check for NULL value, most of the scalar functions return NULL value if any of the arguments evaluate to NULL. 10.10 Using NULL Values in Aggregate Functions The aggregate functions ignore rows with NULL values for their argument and return the value based on the rest of the rows. The function COUNT can also have an expression as the argument. For example, to count all the columns including NULL values in the commission column, the SELECT statement would be: EXEC SQL SELECT COUNT (NVL (commission, 0)) FROM employee ; If the column contains only NULL values, the COUNT (DISTINCT column_name) returns zero and the rest of the aggregate functions return NULL for that column. An exception is the usage COUNT(*). Irrespective of the column values this would get the number of rows. All Rights Reserved 99 www.faircom.com 11. Error Handling in ESQL 11.1 Introduction This chapter describes the handling of errors in ESQL and discusses the use of: SQLCA The WHENEVER statement Indicator variables 11.2 Using SQLCA for Error Handling The c-treeSQL Communication Area (SQLCA) is used to return the status of a c-treeSQL statement’s execution in an ESQL program. For example, SQLCA indicates an error if a SELECT statement has a reference to a table that does not exist in the database. In esqlc, SQLCA is implemented as a structure. The precompiler automatically declares and defines a global SQLCA structure. Fields of the SQLCA structure give details on the status of the execution of a c-treeSQL statement. Fields of the SQLCA SQLCA Structure struct sqlca { char long long unsigned short char char long char char cost_val_t } ; sqlcaid[8] ; sqlcabc ; sqlcode ; sqlerrml ; sqlerrm[72] ; sqlerrp[8] ; sqlerrd[6] ; sqlwarn[8] ; sqlext[8] ; estimated_cost, actual_cost; Fields of the SQLCA sqlcaid All Rights Reserved 100 www.faircom.com Error Handling in ESQL Contains the string “SQLCA”. sqlcabc Contains the size of the structure SQLCA. sqlcode Summarizes the results of a c-treeSQL statement’s execution. sqlcode Description zero Indicates successful execution. positive Indicates successful execution with a status code. The only positive error code c-treeSQL returns is SQL_NOT_FOUND. negative Indicates an error in the SQL statement or a system failure. See Appendix B in the c-treeSQL Reference Manual for valid values of error codes. sqlerrml Contains the length of the error message contained in sqlerrm. sqlerrm A null terminated character string that is the error text corresponding to the code returned in the field sqlcode. sqlerrp Currently unused. sqlerrd An array of six 4 byte integers used to describe the internal state of the c-treeSQL kernel. Currently, only the third integer sqlerrd[2] is used and indicates the number of rows processed for INSERT, UPDATE and DELETE statements. sqlerrd[2] is set to the cumulative number of rows for a FETCH call associated with a cursor. sqlwarn A character array of size eight where each character position can either be a blank or a ‘W’. ‘W’ indicates a warning during the execution of an c-treeSQL statement. Currently, only elements [0], [1], [2], [3], [4], and [6] of the array are used. sqlwarn[0] If this field is set to ‘W’, then one or more of the other sqlwarn fields have been set. If this field is blank, then it can be assumed that no warning has been set. sqlwarn[1] If this field is set to ‘W’, it indicates that one or more of the returned character string fields have been truncated. The indicator variables can be used to determine which of the character strings have been truncated. sqlwarn[2] If this field is set to ‘W’, then one or more null values were ignored in the computation of an aggregate function such as SUM, AVG, MIN, and MAX. sqlwarn[3] If this field is set to ‘W’, it indicates that the number of items in the SELECT list does not equal the number of host variables in the INTO clause. The data is returned with the number of elements being returned being the least of the two numbers. All Rights Reserved 101 www.faircom.com Error Handling in ESQL sqlwarn[4] This field is set to ‘W’ after a successful execution of an UPDATE or a DELETE statement that does not have a WHERE clause. sqlwarn[6] This field is set to ‘W’ if the SQLkernel had to perform an implicit rollback due to a system failure and/or due to a deadlock situation. sqlext Not used. estimated_cost The cost estimated by the optimizer for executing the statement. The type cost_val_t is defined as follows: typedef struct { long cost; long card; long treesize; long rss_calls; } cost_val_t ; actual_cost The actual cost of executing the statement. Using SQLCA for Checking Errors The execution of an ESQL statement can either be a success or failure. In case of failure, the SQLCA can be used to check for the error code and the corresponding error message. The following components of the SQLCA structure are used to get the error codes and error messages: sqlcode indicates the return status of the execution of an ESQL statement. sqlcode is set to zero for a successful execution and is negative for an unsuccessful execution. Also sqlcode can be set to SQL_NOT_FOUND which is set while using a FETCH call and when there are no more rows to be fetched. sqlerrm is a null terminated character string which is the diagnostic text corresponding to the sqlcode. sqlerrml contains the length of the error message contained in sqlerrm. sqlerrd is an array of six variables of type integer. The following example shows the use of the SQLCA components sqlcode and sqlerrm: Example Using SQLCA ... < connect to a default database > EXEC SQL BEGIN DECLARE SECTION ; long deptno_v ; char dname_v [20] ; char loc_v [10] ; EXEC SQL END DECLARE SECTION ; /* Get values for input host variables */ All Rights Reserved 102 www.faircom.com Error Handling in ESQL deptno_v = 30 ; strcpy (dname_v, "ACCOUNTS") ; strcpy (loc_v, "BOSTON") ; EXEC SQL INSERT INTO department (deptno, dname, loc) VALUES (:deptno_v, :dname_v, :loc_v) ; if (sqlca.sqlcode) { fprintf (stderr, "Insert statement failed (%ld : %s)\n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; < disconnect from the database > exit (1); } /* Commit changes */ EXEC SQL COMMIT WORK ; printf ("Inserted one row \n\n"); < disconnect from the database > ... The following example shows how to check for SQL_NOT_FOUND status code while using the FETCH call: Example Checking for SQL_NOT_FOUND ... EXEC SQL CONNECT TO DEFAULT ; /* Declare cursor for retrieving customer information */ EXEC SQL DECLARE cust_cur CURSOR FOR SELECT name, city, state FROM customer WHERE CUST_NO = :cust_no_v; if (sqlca.sqlcode) { fprintf (stderr, "Declare cursor statement failed (%ld : %s)\n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1); } /* Open cursor */ EXEC SQL OPEN cust_cur ; if (sqlca.sqlcode) All Rights Reserved 103 www.faircom.com Error Handling in ESQL { fprintf (stderr, "Open cursor statement failed (%ld : %s)\n", sqlca.sqlcode, sqlca.sqlerrm); EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1); } /* Fetch rows and return result values into host variables */ for (;;) { EXEC SQL FETCH cust_cur INTO :cust_no_v, :name_v, :city_v ; if (sqlca.sqlcode == SQL_NOT_FOUND) break ; if (sqlca.sqlcode) { fprintf (stderr, "FETCH cursor statement failed (%ld : %s)\n", sqlca.sqlcode, sqlca.sqlerrm); EXEC EXEC EXEC exit SQL CLOSE cust_cur ; SQL ROLLBACK WORK ; SQL DISCONNECT DEFAULT ; (1); } printf ("CUST_NO : %d, name : %s, city : %s\n", cust_no_v, name_v, city_v) ; } EXEC SQL CLOSE cust_cur ; EXEC SQL COMMIT WORK ; EXEC SQL DISCONNECT DEFAULT ; ... Using SQLCA for Checking Warnings Warnings that occur during the execution of an ESQL statement can be checked using SQLCA. The component sqlwarn of SQLCA is an array of eight characters. Each element of the array can either be a blank or ‘W’. Currently, only the elements [0], [1], [2], [3], [4], and [6] of the array are used. The warning flags could be set: If one or more string values returned by a query are truncated. If one or more NULL values were ignored in a computation of an aggregate function. If the number of items in the SELECT list does not equal the number of host variables in the INTO clause. If the database implicitly marks the transaction for rollback. The following example shows the computation of the average commission for employees in the sales department. All Rights Reserved 104 www.faircom.com Error Handling in ESQL Example Using sqlwarn Component of SQLCA ... EXEC SQL BEGIN DECLARE SECTION ; FLOAT comm_v ; EXEC SQL END DECLARE SECTION ; ... EXEC SQL CONNECT TO DEFAULT ; EXEC SQL SELECT INTO FROM WHERE AVG (commission) :comm_v employee deptno = 20 ; if (sqlcode == 0) { printf ("commission : %d\n", comm_v) ; /* Check for SQLCA warnings */ if (sqlca.sqlwarn[2] == 'W') printf ("(One or more NULL values ignored\n") ; printf (" in the computation of average commission !)\n") ; } ... In the previous example, the sqlwarn[2] component of SQLCA is used to determine whether some null values were ignored in the computation of the average commission. Using the WHENEVER Statement for Error Handling The WHENEVER statement specifies an action (stop, continue, or branch) for the host program to take when one of three common c-treeSQL runtime exceptions arises. The syntax for the WHENEVER statement is as follows: WHENEVER { NOT FOUND | SQLERROR | SQLWARNING } { STOP | CONTINUE | { GOTO | GO TO } host_language_label } ; See "WHENEVER" (page 175) for details on the WHENEVER statement. The scope of a WHENEVER statement starts from the point where the statement appears until another WHENEVER statement for the same exception encountered or until the end of the esqlc source file. The specification of the action GOTO host_language_label causes control to pass to the statement at the specified label. The specification of the action STOP results in program termination. The specification of the action CONTINUE ignores the SQLCA status and causes the next statement to be executed in the program. All Rights Reserved 105 www.faircom.com Error Handling in ESQL Use the CONTINUE action in a WHENEVER statement within exception handling code. This prevents the WHENEVER statement from passing control to the same label (which would result in a program loop), if any of the ESQL statements within the label fails. Avoid use of the action STOP. Though valid, using it means that the program will terminate without any final reporting. The following example shows the use of WHENEVER statement for exception handling in an ESQL program that deletes a row: Example Using the WHENEVER Statement ... /* code to connect to a database */ EXEC SQL CONNECT TO DEFAULT ; /* Upon error branch to label do_rollback */ EXEC SQL WHENEVER SQLERROR GOTO do_rollback ; EXEC SQL WHENEVER NOT FOUND GOTO do_rollback ; /* Get value for cust_no_v */ cust_no_v = 1002 ; EXEC SQL DELETE FROM customer WHERE CUST_NO = :cust_no_v ; /* Commit work and disconnect from database */ EXEC SQL COMMIT WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (0) ; do_rollback: if (sqlca.sqlcode == SQL_NOT_FOUND) fprintf (stderr, "Customer number not found in table\n"); else if (sqlca.sqlcode < 0) { strncpy (errmesg, sqlca.sqlerrm, sqlca.sqlerrml); errmesg [sqlca.sqlerrml] = '\0' ; fprintf (stderr, "Error : %s\n", errmesg); } EXEC SQL WHENEVER SQLERROR CONTINUE ; EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1) ; ... All Rights Reserved 106 www.faircom.com Error Handling in ESQL Handling the SQL_NOT_FOUND Condition with WHENEVER When the FETCH call is made, SQL_NOT_FOUND is set in the SQLCA if there are no more rows to be fetched that satisfy the query. Hence, when a FETCH call returns SQL_NOT_FOUND, the application can close the cursor. The SQL_NOT_FOUND status could also be returned by the execution of UPDATE/DELETE statements. These statements return SQL_NOT_FOUND when no rows are updated/deleted because none satisfied the condition specified. Using WHENEVER Along With Explicit Error Checking In addition to using WHENEVER statements, the SQLCA can also be explicitly checked in an ESQL program. Consider the following example: ... EXEC SQL WHENEVER SQLERROR GOTO do_rollback ; ... /* Fetch rows and return result values into host variables */ for (;;) { EXEC SQL FETCH cust_cur INTO :cust_no_v, :name_v, :city_v ; if (sqlca.sqlcode == SQL_NOT_FOUND) break ; } ... In the above example, explicit SQLCA check is done in addition to having a WHENEVER statement. Using Indicator Variables for Error Handling Indicator variables can be used in the ESQL application program to detect whether the retrieved value is null or whether the value is truncated. The value would be truncated if the size of the returned value is larger than the size of the host variable used to retrieve the value. The value of an indicator variable is interpreted as shown below: -1 The returned value is NULL and the value of the corresponding host variable is not defined. >0 The returned value was truncated because the host variable size was too small. The value contained in the indicator variable is the actual length before truncation. All Rights Reserved 107 www.faircom.com Error Handling in ESQL The following example shows the usage of indicator variables to detect null: ... EXEC SQL SELECT ename, deptno, commission INTO :ename_v, :deptno_v, :commission_v:commission_i FROM employee WHERE empno = 2002 ; if (commission_i == -1) printf ("Commission is NULL\n") ; ... In the above example, the indicator variable commission_i is used to detect whether the retrieved value for commission is NULL. All Rights Reserved 108 www.faircom.com 12. Dynamic SQL Management in ESQL 12.1 Introduction Dynamic SQL provides a set of special statements and a structure that lets programs accept or generate c-treeSQL statements at run time. Unlike conventional precompiled programs, in which c-treeSQL statements are embedded in the source code, dynamic SQL programs can accept input (from a user or another application) and formulate c-treeSQL statements at run time. Dynamic SQL is useful when programs cannot predict before they execute the type of c-treeSQL statement they will need to process. Interactive SQL is an example of dynamic SQL program that executes c-treeSQL statements dynamically. This chapter describes how to use the special statements (PREPARE, DESCRIBE, EXECUTE, and EXECUTE IMMEDIATE) and structure (the SQLDA). See "ESQL Reference" (page 153) for detailed reference material on the statements. 12.2 Overview It is assumed that the c-treeSQL statements are known when an ESQL program is written. Such statements are called static SQL statements. However, there are several applications where the c-treeSQL statement is not known at compile time. Such c-treeSQL statements are called dynamic SQL statements. For example, the c-treeSQL statements issued in Interactive SQL (ISQL) are not known beforehand. Any ISQL statement could be a SELECT or a non-SELECT statement. These statements are processed by ISQL as dynamic SQL statements. While dynamic SQL statements provide much more flexibility in what their programs can accomplish, the cost of this flexibility is increased complexity. The following steps are involved in the execution of a dynamic SELECT statement: 1. PREPARE statement 2. DECLARE cursor 3. OPEN cursor 4. FETCH rows using cursor 5. CLOSE cursor The following are the steps involved in the execution of a dynamic non-SELECT statement: 1. PREPARE statement All Rights Reserved 109 www.faircom.com Dynamic SQL Management in ESQL 2. EXECUTE statement 12.3 Preparing Statements The PREPARE statement is used by the application programs to prepare a c-treeSQL statement for execution. When a c-treeSQL statement is prepared using PREPARE, the c-treeSQL statement is parsed to check for syntax errors. Then a statement identifier is assigned to the c-treeSQL statement. The c-treeSQL statement used in the PREPARE statement can be specified either as a character string or a reference to a host variable. If the c-treeSQL statement is specified through a host variable reference, the host variable must be a character array. PREPARE statements can be used for both SELECT as well as non-SELECT statements. The c-treeSQL statement is prepared once but is executed as often as necessary, within the same transaction. If the current transaction is committed or rolled back, and the c-treeSQL statement is to be re-executed, the statement must be prepared again. For more information on the PREPARE statement, see "PREPARE" (page 164). The following example shows the usage of the PREPARE statement: ... EXEC SQL BEGIN DECLARE SECTION ; char sql_str [256] ; EXEC SQL END DECLARE SECTION ; ... strcpy (sql_str, "delete from customer where CUST_NO = :p1") ; EXEC SQL PREPARE delstmt FROM :sql_str ; ... The statement identifier used in the PREPARE statement is delstmt. This identifier is for further referencing of the statement by ESQL statements. It can also be seen that the host variable, sql_str, is declared in the declare section. The host variable reference made in the c-treeSQL statement, such as p1, is just a marker. The name of the host variable reference marker used in the prepared c-treeSQL statement is in no way related to the name of the host variable that would contain the corresponding value. For example, in the prepared c-treeSQL statement string, the name p1 could be used where as the name of the host variable used to supply the value could be cust_no_v. The following is an example showing the usage of a character string in the PREPARE statement: EXEC SQL PREPARE selstmt FROM select * from customer ; Note: The dynamic SQL statements must not contain the terminating semicolon. The ESQL statements that cannot be prepared include: All Rights Reserved 110 www.faircom.com Dynamic SQL Management in ESQL CLOSE DECLARE EXECUTE FETCH OPEN PREPARE SELECT with an INTO clause Non-SELECT Statements A non-SELECT dynamic SQL statement can be executed using a two step process. The statement should be first prepared using the PREPARE statement. The second step is to execute the prepared statement by supplying values, if any, to the input host variables specified in the PREPARE statement. This execution is done using the EXECUTE statement. For more information on the PREPARE or EXECUTE statement, see "ESQL Reference" (page 153). Executing a Non-SELECT Statement The EXECUTE statement takes the statement identifier of a prepared statement and executes the statement. The following example shows the usage of the EXECUTE statement in an ESQL program: Example Dynamic non-SELECT Statement EXEC SQL BEGIN DECLARE SECTION ; char sql_str [256] ; long cust_no_v ; EXEC SQL END DECLARE SECTION ; /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; strcpy (sql_str, "delete from customer where CUST_NO = :p1") ; EXEC SQL PREPARE stmt FROM :sql_str ; cust_no_v = 1001 ; EXEC SQL EXECUTE stmt USING :cust_no_v ; /* Commit changes */ EXEC SQL COMMIT WORK ; /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; The EXECUTE statement executes the prepared statement using the values supplied for each host variable. In the above example, the host variable supplied is cust_no_v. All Rights Reserved 111 www.faircom.com Dynamic SQL Management in ESQL The c-treeSQL statement is prepared just once, but is executed as often as necessary, within the same transaction. If the current transaction is committed or rolled back, and the c-treeSQL statement is to be re-executed, the statement must be prepared again. The EXECUTE IMMEDIATE Statement The c-treeSQL executable statement, EXECUTE IMMEDIATE, is similar to using PREPARE and EXECUTE. The EXECUTE IMMEDIATE statement accepts as input, a character string or a host variable of character array type. For more information on the EXECUTE IMMEDIATE statement, see "ESQL Reference" (page 153). The following example shows the usage of EXECUTE IMMEDIATE statement: Example Using EXECUTE IMMEDIATE Statement ... EXEC SQL BEGIN DECLARE SECTION ; char sql_str [256] ; EXEC SQL END DECLARE SECTION ; gets (sql_str) ; EXEC SQL EXECUTE IMMEDIATE :sql_str ; ... A character string can be used in the place of a host variable reference as shown below: EXEC SQL EXECUTE IMMEDIATE "delete from customer where CUST_NO = 1001" ; It can be noted that the c-treeSQL string given to a EXECUTE IMMEDIATE statement should not have host variable references. Note:The EXECUTE IMMEDIATE statement is a non-ANSI feature. SELECT Statements Dynamic SELECT statements have to be executed differently since they return information as compared to non-SELECT statements where the return information is restricted to the SQLCA. The statements used for dynamic SELECT include OPEN, FETCH, and CLOSE. A simple form of a dynamic SELECT statement is the one that allows queries whose SELECT list is known but whose search criteria (as in the WHERE clause) or ordering (as in the ORDER BY clause) might vary. The processing of a dynamic SELECT statement involves the following steps: 1. PREPARE statement 2. DECLARE cursor 3. OPEN cursor 4. FETCH rows using a cursor 5. CLOSE cursor All Rights Reserved 112 www.faircom.com Dynamic SQL Management in ESQL Opening a Cursor The OPEN statement puts a cursor in an open state. When a cursor is opened, the SELECT statement associated with the cursor is executed and the result set is obtained. Such a result set is referred to as the active set. The execution of the SELECT statement uses the current program variables and leaves the cursor positioned just before the first row in the active set. When the cursor is in the open state, any changes to the program variables of the SELECT statement do not change the rows retrieved in the active set. The following example shows the opening of the cursor, custcur. /* Open the cursor */ EXEC SQL OPEN custcur ; Fetching Rows Using a Cursor The FETCH statement advances the cursor to the next row in the active set and retrieves the values from that row. If the FETCH statement is executed for the first time, the cursor is positioned on the first row and all the values of the first row are retrieved. Subsequent calls to FETCH retrieve rows one by one from the active set. When all the rows in the active set are retrieved, SQL_NOT_FOUND is set in the SQLCA to indicate that all rows have been retrieved. The following example code shows the usage of the FETCH statement: Example Dynamic SELECT Statement ... /* connect to a default database */ EXEC SQL CONNECT TO DEFAULT ; EXEC SQL PREPARE cust_sel_stmt FROM SELECT CUST_NO, name, city FROM customer ; EXEC SQL DECLARE cust_cursor CURSOR FOR cust_sel_stmt ; /* Open the cursor declared */ EXEC SQL OPEN custcur ; /* fetch rows and print them */ for (;;) { EXEC SQL FETCH cust_cursor INTO :cust_no_v, :name_v, :city_v ; if (sqlca.sqlcode) break; printf ("%d, %s, %s\n", cust_no_v, name_v, city_v) ; } EXEC SQL CLOSE cust_cursor ; /* Commit changes */ EXEC SQL COMMIT WORK ; All Rights Reserved 113 www.faircom.com Dynamic SQL Management in ESQL /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; ... Closing a Cursor The CLOSE statement puts the cursor that is in an open state to a closed state. After a cursor is closed the cursor becomes invalid unless it is opened using the OPEN statement. The following statement closes the cursor, cust_cursor. EXEC SQL CLOSE cust_cursor ; 12.4 ESQL Descriptor Statement c-treeSQL statements for dynamic SQL specify the DESCRIPTOR keyword to use the SQL-92 descriptor area instead of the SQLDA. ALLOCATE DESCRIPTOR Description Use this statement to allocate a c-treeSQL descriptor area. Syntax The syntax for this non-preparable statement is: ALLOCATE DESCRIPTOR desc_name [ WITH MAX occurrences ] Arguments desc_name Literal/host variable/parameter containing the name of the SQL Descriptor Area. Occurrences The integer value that gives the number of items for which the descriptor area is allocated. If the WITH MAX clause is not mentioned, then a default value of 10 number of items are allocated in the c-treeSQL Descriptor Area. Example EXEC SQL ALLOCATE DESCRIPTOR dn 15; All Rights Reserved 114 www.faircom.com Dynamic SQL Management in ESQL DEALLOCATE DESCRIPTOR Description Use this statement to deallocate a c-treeSQL descriptor area that has been previously allocated, to free memory. Syntax The syntax for this non-preparable statement is : DEALLOCATE DESCRIPTOR desc_name Arguments desc_name Literal/host variable/parameter containing the name of a previously allocated c-treeSQL Descriptor Area. Example EXEC SQL DEALLOCATE DESCRIPTOR dn; GET DESCRIPTOR Description Use to obtain Information from the c-treeSQL Descriptor Area. There are two variations of the Get Descriptor statement. Syntax 1 GET DESCRIPTOR descriptor_name target = COUNT This returns the number of filled-in items in the Descriptor Area. Arguments descriptor_name The name of the Descriptor Area. target Host variable that is specified to receive the number of items that are in use in the Descriptor Area. Syntax 2 GET DESCRIPTOR descriptor_name VALUE item_number { :hv0 = COUNT | VALUE item_number :hv1 = item_name1 [ {, :hvN = item_nameN}] } ; This retrieves information from a specific item in the Descriptor Area. All Rights Reserved 115 www.faircom.com Dynamic SQL Management in ESQL Arguments descriptor_name The name of the Descriptor Area. target Host variable/parameter of the appropriate data type that is specified to receive the number of items that are in use in the Descriptor Area. item_number The position of the item in the SQL statement. item_number can be a variable or a constant. If item_number is greater than COUNT, the “no data found” condition is returned. item_number must be greater than 0. hv1 .. hvN These are host variables to which values are transferred. item_name1 .. item_nameN The descriptor item names corresponding to the host variables Descriptor Item Name Descriptor Item Name Meaning TYPE Data Type of the Field. LENGTH Length of data in the column: in characters for NCHAR; in bytes otherwise. Set by the DESCRIBE OUTPUT. OCTET_LENGTH Length of data in bytes. RETURNED_LENGTH The actual data length after a FETCH. PRECISION The number of digits. SCALE For exact numeric types, the number of digits to the right of the decimal point. DATETIME_INTERVAL_CODE Code for datetime/interval substrings. DATETIME_INTERVAL_PRECISION Precision for interval’s leading field. NULLABLE If 1, the column can have NULL values. If 0, the column cannot have NULL values. INDICATOR The associated indicator value. DATA The data value. NAME Column name. COLLATION_NAME Character string with character set SQL_TEXT. CHARACTER_SET_NAME Column’s character set. TABLE_NAME Contains the table name of the result set column. All Rights Reserved 116 www.faircom.com Dynamic SQL Management in ESQL Descriptor Item Name Meaning BASE_TABLE_NAME Contains the base table name for the result set column. BASE_COLUMN_NAME Contains the base column name for the result set column. GET DESCRIPTOR Example EXEC SQL GET DESCRIPTOR dn :h1 = COUNT ; EXEC SQL GET DESCRIPTOR dn VALUE 1 :h1 = TYPE, :h2 = LENGTH, :h3 = PRECISION, :h4 = SCALE, :h5 = OCTET_LENGTH,:h6=RETURNED_LENGTH,:h7= DATETIME_INTERVAL_CODE,:h8=DATETIME_INTERVAL_PRECISION, :h9 = NULLABLE, :h10 = UPDATABLE, :h11 = SEARCHABLE, :h12 = PARAMETER_TYPE, :h13 = VERBOSE_TYPE,:h14 = CASE_SENSITIVE, :h15 = INDICATOR, :h16 = AUTO_UNIQUE_VALUE,:h17 = UNSIGNED, :h18 = UNNAMED, :c1 = NAME, :c2 = DATA,:c3 = COLLATION_NAME, :c4 = CHARACTER_SET_NAME, :c5 = TABLE_NAME,:c6 = BASE_COLUMN_NAME, :c7 = BASE_TABLE_NAME; SET DESCRIPTOR Description Use this statement to set information in the descriptor area from host variables. The SET DESCRIPTOR statement supports only host variables for the item names. Example If the host variable or parameter has a slightly different type than what the c-treeACE SQL Server has written into the c-treeSQL Descriptor Area, then this statement can be used to set certain fields in the c-treeSQL Descriptor Area. This forces the c-treeACE SQL Server to cast the Data field in the c-treeSQL Descriptor Area to the type of the host variable/parameter. The end-user doesn’t have to explicitly cast the data from the c-treeSQL Descriptor Area. There are two variants of this statement as in GET DESCRIPTOR. Syntax 1 SET DESCRIPTOR desc_name COUNT = value Arguments desc_name Name of a valid c-treeSQL Descriptor Area. Value Integer value for the no. of items in the c-treeSQL Descriptor Area. if ( value>occurrences || value<1 ) All Rights Reserved 117 www.faircom.com Dynamic SQL Management in ESQL Syntax 2 SET DESCRIPTOR desc_name VALUE item_number item_name1 = value1 [ , item_nameN = valueN ] Arguments descriptor_name The name of the Descriptor Area. item_number Integer that identifies a specific item in the Descriptor Area. item_name1 .. item_nameN The descriptor item names corresponding to the host variables. value1.. valueN These are host variables that you set. SET DESCRIPTOR Example EXEC SQL SET DESCRIPTOR dn COUNT = 10 ; EXEC SQL SET DESCRIPTOR dn VALUE 1 TYPE = 5, LENGTH = 20, DATETIME_INTERVAL_CODE = 3, DATETIME_INTERVAL_PRECISION = 4, UPDATABLE = 1, UNNAMED = 1,PARAMETER_TYPE = 1, VERBOSE_TYPE = 5, PRECISION = 10,SCALE = 7, NULLABLE = 1, SEARCHABLE = 2, UNSIGNED = 1,CASE_SENSITIVE = 1, AUTO_UNIQUE_VALUE = 1, INDICATOR = 0,NULLABLE = 1, AUTO_UNIQUE_VALUE = 1, NAME = :c1,DATA = :c2, COLLATION_NAME = :c3, CHARACTER_SET_NAME = :c4, TABLE_NAME = :c5, COLUMN_NAME=:c6, TABLE_NAME = :c7; 12.5 The c-treeSQL Descriptor Area - SQLDA A c-treeSQL Descriptor Area (SQLDA) is a storage area for descriptive information pertaining to dynamic SQL statements. An SQLDA can be used while passing parameter values for the execution of a dynamic SQL statement and while retrieving results of a dynamic SELECT statement. Dynamic SELECT statements have to be executed differently since they return information as compared to non-SELECT statements where the return information is restricted to the SQLCA. A program executing a dynamic SELECT statement needs to know the lengths and types of values being returned. Similarly, a program executing a dynamic non-SELECT statement needs to know the input values that must be supplied to the parameters referenced in the statement. This can be achieved using the DESCRIBE statement. The DESCRIBE statement obtains information about a prepared statement. For more information on the DESCRIBE statement, refer to "The DESCRIBE Statement" (page 127). The SQLDA can be used to hold information about the input host variables: All Rights Reserved 118 www.faircom.com Dynamic SQL Management in ESQL That contain input values for a dynamic SELECT/non-SELECT statement. The SQLDA used for this purpose is an input SQLDA. An input SQLDA can be used in the following statements: • EXECUTE statement • OPEN cursor statement corresponding to a dynamic SELECT statement. Where the values are to be returned by a dynamic SELECT statement. The SQLDA used for this purpose is an output SQLDA. An output SQLDA can be used in the following statements: • DESCRIBE statement associated with a dynamic SELECT statement. • FETCH statement associated with a dynamic SELECT statement. In esqlc, SQLDA is implemented as a structure. An SQLDA must be explicitly declared before its usage in the ESQL program. The Components of SQLDA Structure struct short short char short short short short short short short short char char short sqlda { sqld_size ; sqld_nvars ; **sqld_varptrs ; *sqld_lengths ; *sqld_types ; *sqld_precision; *sqld_scale ; *sqld_flags ; **sqld_ivarptrs; sqld_varnmsize ; sqld_indvarnmsz; **sqld_varnames; **sqld_indvarnames; sqld_arraysz ; /***For the support of SQL_92 descriptor area*/ short * sqld_date_int_code ; short * sqld_date_int_prec; char ** sqld_collat_name ; char ** sqld_charset_name; short sqld_max_size; /*** For long * long * char ** char ** short * short * short * char ** short * } ; the support of ODBC 3.0 interfaces ***/ sqld_clengths; sqld_retruned_lengths ; sqld_base_column_name; sqld_base_table_name ; sqld_updatable; sqld_searchable; sqld_param_type; sqld_table_name; sqld_verbose_types; /* function for allocating a descriptor area */ extern sqlda *sqld_alloc (size, varnmsize) short size ; short varnmsize ; All Rights Reserved 119 www.faircom.com Dynamic SQL Management in ESQL /* function for freeing a descriptor area */ extern void sqld_free (sqldaptr) sqlda *sqldaptr ; Description The c-treeSQL Descriptor Area (SQLDA) is used in the DESCRIBE statement to hold information about input host variables and/or to hold information corresponding to returned values of a dynamic SQL statement. Fields of the SQLDA sqld_size Number of entries in the SQLDA. c-treeSQL expects that with OPEN or FETCH statements that refer to an SQLDA, there will be sqld_size variables and indicator variables. sqld_nvars Number of variables found by the DESCRIBE statement. sqld_varptrs Array of pointers to host variables. The application sets elements in sqld_varptrs to point to memory it allocates. While executing the FETCH statement, c-treeSQL assumes that sqld_varptrs [i] points to a buffer of size (sqld_lengths [i] * sqld_arraysz). sqld_lengths Array of lengths of host variables or retrieved data. sqld_types Array containing the data types of host variables or retrieved data. sqld_precision Array containing the precision for applicable data types. sqld_scale Array containing the scale for applicable data types. sqld_flags Array containing a code that specifies whether a column accepts null values. A value of [1] (true) indicates the column accepts null values, [0] (false) indicates it does not, and [2] indicates unknown. sqld_ivarptrs Array of pointers to indicator variables. The application sets elements in sqld_ivarptrs to point to memory it allocates. c-treeSQL assumes that sqld_ivarptrs [i], if not a null pointer, points to a buffer of size (sizeof (short) * sqld_arraysz). sqld_varnmsize Maximum size of variable names. All Rights Reserved 120 www.faircom.com Dynamic SQL Management in ESQL sqld_indvarnmsz Maximum size of indicator variable names. Not currently used. sqld_varnames Array of pointers to host variable names. sqld_indvarnames Array of pointers to indicator variable names. Not currently used. sqld_arraysz Size of arrays allocated by application. If multiple tuples are to be fetched in single FETCH statement execution, then application must set the field sqld_arraysz accordingly. sqld_date_int_code Code for Datetime/interval subtypes(SQL92 ODBC) sqld_date_int_prec Precision for Datetime/interval subtypes(SQL92 ODBC) sqld_collat_name Array of Collation name of column’s collation(SQL92) sqld_charset_name Array of Collation name for column’s char. set(SQL92) sqld_max_size Size of SQLDA in number of entries while allocating the descriptor sqld_clengths Character length for strings sqld_retruned_lengths Length retruned by dBMS sqld_base_column_name Base column name (ODBC) sqld_base_table_name Base table name (ODBC) sqld_catalog_name Base table catalog name(ODBC) sqld_schema_name Base table schema name(ODBC) sqld_searchable Whether column is searchable(ODBC) sqld_updatable All Rights Reserved 121 www.faircom.com Dynamic SQL Management in ESQL Whether column is updatable(ODBC) sqld_param_type Parameter type sqld_verbose_types Parameter type sqld_table_name Table/View name Notes An SQLDA structure should always be allocated by calling the function sqld_alloc() rather than declaring it statically. The sqld_alloc() function takes a size argument that specifies the maximum number of variables for which the structure should be allocated. An SQLDA structure can be reused as long as the two dynamic SQL statements using the descriptor area are not active simultaneously and the maximum SQLDA size required is the same for both the c-treeSQL statements. An SQLDA structure should be freed by calling the sqld_free() routine that takes a pointer to the SQLDA structure. The esqlc application must allocate memory for holding the data values returned by the c-treeSQL statement and for holding the indicator variables. The application sets the elements of the pointer arrays sqld_varptrs and sqld_ivarptrs appropriately. If multiple tuples are to be fetched in a single FETCH statement execution, then the application must set the field sqld_arraysz accordingly. While executing the FETCH statement, it is assumed that sqld_varptrs [i] points to a buffer of size (sqld_lengths [i] * sqld_arraysz). It is also assumed that sqld_ivarptrs [i], if not a null pointer, points to a buffer of size (sizeof (short) * sqld_arraysz). All Rights Reserved 122 www.faircom.com Dynamic SQL Management in ESQL The following figure shows the structure of SQLDA. Note that only the relevant fields are shown. Also note that the field sqld_varnames would be a null pointer if the second argument to the API call sqld_alloc() is 0. Figure 1: SQLDA Structure Allocating an SQLDA The SQLDA structure should be allocated by calling the function sqld_alloc() (not by declaring it statically). A pointer to SQLDA must be declared. The following is a valid declaration: struct sqlda *sqldaptr ; ... sqldaptr = sqld_alloc (...) ; ... The following example shows an invalid declaration of the SQLDA structure: struct sqlda All Rights Reserved sqlda1 ; /* not correct */ 123 www.faircom.com Dynamic SQL Management in ESQL The sqld_alloc() function takes a size argument that specifies the maximum number of variables for which the structure should be allocated. The syntax for the function sqld_alloc() is: #include "sqlda.h" struct sqlda *sqld_alloc (size, varnmsz) short size ; short varnmsz ; The sqld_alloc() function allocates an SQLDA from heap. size specifies the maximum number of variables for which SQLDA would be allocated. varnmsz is the maximum number of characters for the name of the column in the result table corresponding to the SQL statement. If names of the columns in the result table are not of interest, zero can be passed for varnmsz. The following example shows the allocation of the SQLDA. Allocating an SQLDA Example ... #define #define MAXVARS MAXVARNAMELEN 20 20 /* declare the pointer to SQLDA */ struct sqlda *sqldaptr = (struct sqlda *)0 ; ... if (!(sqldaptr = sqld_alloc (MAXVARS, MAXVARNAMELEN))) { fprintf (stderr, "sqld_alloc returned error\n") ; exit (1) ; } ... Note The sqld_alloc() function does not allocate for the data buffers and the indicator variable buffers. Allocation for data buffers and indicator variables must be done by the application separately and the pointers to these data buffers and indicator variables must be set in the SQLDA. Setting the SQLDA Types and Lengths As discussed earlier, SQLDA can be used for both input host variables as well as output host variables. These variables are used to hold the values that are not known beforehand. When an SQLDA is used to supply values to input host variables referenced in a dynamic non-SELECT statement, it is necessary to set the type and length of the values in the SQLDA. The SQLDA components sqld_lengths and sqld_types must be set appropriately. In the case of dynamic SELECT statements, a DESCRIBE call can be issued to obtain the types and lengths of the values returned by a SELECT statement. All Rights Reserved 124 www.faircom.com Dynamic SQL Management in ESQL Allocating for SQLDA Data Buffers and Indicator Variables The sqld_alloc() function does not allocate space for data buffers and indicator variable buffers. These allocations should be done by the application program and the pointers in SQLDA must be set to point to these allocations. The program must set the SQLDA components sqld_lengths and sqld_types before the it allocates the data buffers and indicator variable buffers. The following example shows the allocation of data buffers and indicator variable buffers, and setting SQLDA elements to point to the allocations: SQLDA Setup Example ... /* * Allocate for sqld_varptrs and sqld_ivarptrs and * set these pointers to point to the allocation. */ for (colindex = 0 ; colindex < sqldaptr->sqld_size ; colindex++) { if (!( sqldaptr->sqld_varptrs [colindex] = (char *) calloc ( sqldaptr->sqld_lengths [colindex], sizeof (char) )) || ! ( sqldaptr->sqld_ivarptrs [colindex] = (short *) calloc ( sizeof (short), sizeof (char) ))) { fprintf (stderr, "No memory !\n") ; exit (1) ; } } ... Using SQLDA for Array Fetches As mentioned in "Query Statements" (page 85), esqlc supports multiple-row fetch statements through the use of explicitly-declared esqlc arrays. Programs can use the same technique using the SQLDA and dynamically-allocated arrays. When more than one row is to be fetched in one execution of the FETCH statement, the SQLDA component, sqld_arraysz must be set to the maximum number of rows that could be fetched. The allocation done for the data buffers and indicator variable buffers should be of appropriate size such that the buffers can hold the values retrieved by the query statement. Hence when an array fetch is done using SQLDA, care must be taken to set the SQLDA components, sqld_varptrs and sqld_ivarptrs, to the correct size. The following example shows the allocation done for sqld_varptrs and sqld_ivarptrs for array fetches. All Rights Reserved 125 www.faircom.com Dynamic SQL Management in ESQL Array Fetch Example ... short arraysz = 10 ; /* array size for array fetches */ /* set the array size in sqlda */ sqldaptr->sqld_arraysz = arraysz ; /* * Allocate for sqld_varptrs and sqld_ivarptrs and * set these pointers to point to the allocation. */ for (colindex = 0 ; colindex < sqldaptr->sqld_size ; colindex++) { if (!( sqldaptr->sqld_varptrs [colindex] = (char *) calloc ( sqldaptr->sqld_lengths [colindex] * arraysz, sizeof (char) )) || !(sqldaptr->sqld_ivarptrs [colindex] = (short *) calloc ( sizeof (short) * arraysz, sizeof (char) ))) { fprintf (stderr, "No memory !\n") ; exit (1) ; } } ... Here, sqld_varptrs [colindex] points to a buffer of size (sqld_lengths [colindex] * sqld_arraysz). Also, sqld_ivarptrs [colindex], if not a null pointer, points to a buffer of size (sizeof (short) * sqld_arraysz). Freeing an SQLDA A previously allocated SQLDA can be freed using the sqld_free() function call. The syntax for the sqld_free() function is: #include "sqlda.h" void sqld_free (sqldaptr) struct sqlda *sqldaptr ; The following sample code shows the freeing of SQLDA: sqld_free (sqldaptr) ; The allocations made for the data buffers and the indicator variable buffers should be freed before calling the sqld_free() function. Note: Passing an invalid argument to sqld_free() or freeing an already-freed SQLDA generates unpredictable results. One possible result is a fatal error. All Rights Reserved 126 www.faircom.com Dynamic SQL Management in ESQL The DESCRIBE Statement The DESCRIBE statement is used to obtain information about a prepared statement. This is an executable statement that can only be embedded in an ESQL program and cannot be dynamically prepared. The DESCRIBE statement can be used to describe input host variables as well as output host variables. For more information on the DESCRIBE statement, see "DESCRIBE" (page 156). The DESCRIBE statement has the following format: EXEC SQL DESCRIBE BIND VARIABLES FOR statement_name INTO input_sqlda_name; EXEC SQL DESCRIBE SELECT LIST FOR statement_name INTO output_sqlda_name; The DESCRIBE BIND statement should be executed after the c-treeSQL statement has been prepared and before the OPEN statement has been executed for the cursor. The input SQLDA should be specified in the OPEN cursor statement with the USING DESCRIPTOR clause as shown: EXEC SQL OPEN cursor_name USING DESCRIPTOR input_sqlda_name ; A sample DESCRIBE statement that gets information from a prepared c-treeSQL statement into an SQLDA is shown in the following example: DESCRIBE Statement Example ... EXEC SQL BEGIN DECLARE SECTION ; CHAR stmt_str [256] ; EXEC SQL END DECLARE SECTION ; struct sqlda *sqldaptr ; ... EXEC SQL PREPARE sel_stmt FROM :stmt_str ; EXEC SQL DECLARE sel_cur CURSOR FOR sel_stmt ; EXEC SQL OPEN sel_cur ; /* Allocate for SQLDA */ if (!(sqldaptr = sqld_alloc (20, 30))) { fprintf (stderr, "No memory !\n") ; exit (1) ; } EXEC SQL DESCRIBE SELECT LIST FOR sel_stmt INTO sqldaptr ; ... All Rights Reserved 127 www.faircom.com Dynamic SQL Management in ESQL Here sel_stmt is a prepared statement obtained from the PREPARE statement. When the DESCRIBE statement is executed, values are assigned to the variables in the SQLDA as follows: sqld_nvars would contain the number of outputs returned. • If the size of the SQLDA passed is not enough to return information about all the result columns of the SELECT statement, the value of sqld_nvars would be negative. In this case, the absolute value of sqld_nvars gives the actual number of result columns of SELECT statement. The application can use this to deallocate the SQLDA, allocate a new SQLDA for the required size, and then execute the DESCRIBE statement again. sqld_types would contain the data types of each column specified in the SELECT list. sqld_lengths would contain the lengths of each column depending on the data type of the column. Using SQLDA for Input Variables The input SQLDA is used to store the values for input host variables used in evaluating the c-treeSQL statement. The DESCRIBE BIND statement is used for input SQLDA and the syntax is: EXEC SQL DESCRIBE BIND VARIABLES FOR statement_name INTO input_sqlda_name ; The DESCRIBE BIND statement must appear after the PREPARE statement and before the OPEN statement. The following example shows the usage of DESCRIBE BIND statement to get the number of input host variable references in an c-treeSQL statement. DESCRIBE BIND: Using the SQLDA for Input Variables Example ... struct sqlda *isqlda ; EXEC SQL BEGIN DECLARE SECTION ; char stmt_str [100] ; EXEC SQL END DECLARE SECTION ; strcpy (stmt_str, "insert into dept (deptno, dname, loc) values (:p1, :p2, :p3)") ; EXEC SQL PREPARE ins_stmt FROM :stmt_str ; EXEC SQL DECLARE ins_cur CURSOR FOR ins_stmt ; /* Allocate for SQLDA */ if (!(isqlda = sqld_alloc (20, 0))) { fprintf (stderr, "No memory !\n") ; exit (1) ; } /* Call DESCRIBE to get number of host variable references */ EXEC SQL DESCRIBE BIND VARIABLES FOR ins_stmt INTO isqlda ; All Rights Reserved 128 www.faircom.com Dynamic SQL Management in ESQL nvars = isqlda->sqld_nvars ; if (nvars < 0) nvars = -nvars ; /* Free SQLDA */ sqld_free (isqlda) ; /* Allocate SQLDA for exact number of host variable references */ if (!(isqlda = sqld_alloc (nvars, 0))) { fprintf (stderr, "No memory !\n") ; exit (1) ; } EXEC SQL OPEN ins_cur USING DESCRIPTOR isqlda ; ... In the previous example, SQLDA is first allocated for 20. After the DESCRIBE is done on the prepared statement, the SQLDA is once again allocated for the exact number of host variable references. It can be noted that the second argument for sqld_alloc is zero while allocating for input SQLDA. Using SQLDA for Output Variables For a dynamic SQL query, a DESCRIBE statement is required to associate items in the SELECT list with an output SQLDA. The DESCRIBE SELECT statement is used for the output SQLDA and the syntax is as shown: EXEC SQL DESCRIBE SELECT LIST FOR statement_name INTO output_sqlda_name ; The DESCRIBE SELECT must occur after PREPARE, DESCRIBE BIND and OPEN statements, and before the FETCH statement. The following example shows the usage of DESCRIBE SELECT statement DESCRIBE SELECT: Using the SQLDA for Select List Items Example struct sqlda *osqlda = (struct sqlda *)0 ; strcpy (stmt, "select qty, product from orders where order_no < :p1") ; EXEC SQL PREPARE stmtid FROM :stmt ; EXEC SQL DECLARE dyncur CURSOR FOR stmtid ; for (order_no_v = 1002 ; order_no_v <= 1004 ; order_no_v++) { EXEC SQL OPEN dyncur USING :order_no_v ; /* maxvars = 2, varnmsz = 20 */ if (!(osqlda = sqld_alloc (2, 20))) { fprintf (stderr, "sqld_alloc returned err\n") ; goto err ; All Rights Reserved 129 www.faircom.com Dynamic SQL Management in ESQL } for (;;) { short nvars ; EXEC SQL DESCRIBE SELECT LIST FOR stmtid INTO osqlda ; if ((nvars = osqlda->sqld_nvars) < 0) { sqld_free (osqlda) ; if (!(osqlda = sqld_alloc (-(nvars), 20))) { fprintf (stderr, "sqld_alloc returned err\n") ; goto err ; } continue ; } break ; } } In the previous example, the SQLDA is allocated again because, if the size (first argument) provided in the sqld_alloc() function is not enough, then the SQLDA component, sqld_nvars would contain a negative number equal to the negative of the actual number of outputs found. All Rights Reserved 130 www.faircom.com 13. Transaction Management in ESQL 13.1 Introduction This chapter describes the transaction management in ESQL and explains: Starting and ending a transaction Using transaction isolation levels Locking in transactions. 13.2 Transaction Overview A transaction is a sequence of operations on the database that has the properties of being atomic and durable. Atomicity refers to the property that either all the operations in a transaction are done (if the transaction is committed) or none are done (if the transaction is rolled back). Durability refers to the property that once a transaction is committed, the changes done by the transaction are permanent. Any executable statement is executed as part of a transaction. In an ESQL program, when a statement is executed, if there already exists an active transaction for that ESQL program, this statement would execute as part of that transaction. If an active transaction does not exist, the execution of the c-treeSQL statement would start a new transaction. This transaction would be the active transaction for that ESQL program. All subsequent c-treeSQL statements would execute as part of this transaction until the application ends the transaction by explicitly committing or rolling back the transaction. Starting a Transaction A transaction is implicitly started by the first executable c-treeSQL statement in an ESQL program. ... EXEC SQL CONNECT TO DEFAULT ; /* Create table, customer, in the database. * Since this is the first executable statement * a new transaction is started implicitly. */ EXEC SQL CREATE TABLE customer ( All Rights Reserved 131 www.faircom.com Transaction Management in ESQL street CUST_NO name CHAR (30), city state INTEGER NOT NULL, CHAR (30), CHAR (20), CHAR (2) ) ; /* Insert values in the customer table */ EXEC SQL INSERT INTO customer (CUST_NO, name, street, city, state) VALUES (:cust_no_v, :name_v, :street_v, :city_v, :state_v) ; EXEC SQL COMMIT WORK ; EXEC SQL DISCONNECT DEFAULT ; ... In the above example, the execution of the CREATE TABLE statement starts a new transaction. The execution of the INSERT statement would not start a new transaction since an active transaction already exists (the one started by the execution of the CREATE TABLE statement). Note: Declarative statements do not start a transaction. The COMMIT WORK Statement A transaction can be successfully terminated in an application using the COMMIT WORK statement. When a COMMIT WORK statement is executed, all the changes made to the database by the transaction are made permanent. Depending on the isolation level of the transaction, changes made by one transaction may or may not be visible to other transactions before the transaction is committed. The default behavior is that database changes made by one transaction are not visible to any other transaction until and unless the transaction is committed. Once committed, changes made to the database are guaranteed never to be canceled. The following example shows the usage of the COMMIT WORK statement: /* End Transaction */ EXEC SQL COMMIT WORK ; The COMMIT WORK statement has no effect on the contents of the host variables or on the control flow of the ESQL program. The following example shows conditionally executing a COMMIT WORK statement based on the result of the sqlcode in the SQLCA. COMMIT WORK Statement Example < Code for connecting to the database > EXEC SQL INSERT INTO customer (cust_no, name) VALUES (:cust_no, :name) ; All Rights Reserved 132 www.faircom.com Transaction Management in ESQL if (sqlca.sqlcode) end_prog () ; <perform input/output to the user> EXEC SQL INSERT INTO orders (order_no, cust_no) VALUES (:order_no, :cust_no) ; if (sqlca.sqlcode) end_prog () ; EXEC SQL COMMIT WORK ; The ROLLBACK WORK Statement The ROLLBACK WORK statement undoes all the changes made to the database within a transaction. The following example shows the usage of the ROLLBACK WORK statement: /* Undo transaction changes */ EXEC SQL ROLLBACK WORK ; The ROLLBACK WORK statement has no effect on the contents of the host variables or the control flow of the ESQL program. c-treeSQL automatically executes a rollback operation when there is an abnormal termination of an application program. c-treeSQL closes all cursors opened within the transaction and releases all locks held by the transaction. Usually, the ROLLBACK WORK statement is used in exception handlers. The following example illustrates conditionally executing a ROLLBACK WORK statement based on the result of the sqlcode in the SQLCA. ROLLBACK WORK Statement Example EXEC SQL BEGIN DECLARE SECTION ; long cust_no ; EXEC SQL END DECLARE SECTION ; void drop_customer () { EXEC SQL DELETE FROM customer WHERE cust_no = :cust_no ; if (sqlca.sqlcode) { status = sqlca.sqlcode ; /* roll back the transaction */ EXEC SQL ROLLBACK WORK ; return ; } EXEC SQL DELETE FROM orders WHERE cust_no = :cust_no ; if (sqlca.sqlcode) { status = sqlca.sqlcode ; /* roll back the transaction */ EXEC SQL ROLLBACK WORK ; All Rights Reserved 133 www.faircom.com Transaction Management in ESQL return ; } status = STATUS_OK; EXEC SQL COMMIT WORK ; return ; } ... Transaction Isolation Levels The degree to which one transaction can interfere with other transactions by accessing the same rows concurrently can be specified by setting the transaction isolation level in the ESQL program. The syntax for SET TRANSACTION ISOLATION LEVEL statement is: SET TRANSACTION ISOLATION LEVEL { 0 | 1 | 2 | 3 }; The SET TRANSACTION ISOLATION LEVEL statement is used to set the isolation level explicitly in an ESQL program. The scope of the isolation level set is the current transaction. The isolation_level is specified as an integer with the value being 0, 1, 2, or 3. The following table shows how the isolation level integers correspond to ANSI/ISO standard isolation level keywords. Number Isolation Level 0 UNCOMMITTED READ 1 COMMITTED READ 2 REPEATABLE READ 3 SERIALIZABLE The isolation level SERIALIZABLE guarantees the highest consistency and is the default. The isolation level READ UNCOMMITTED guarantees the least consistency. For details of the definitions of the different isolation levels, see the SET TRANSACTION ISOLATION LEVEL statement in the c-treeSQL Reference Manual. Note: c-treeSQL only supports transaction isolation levels 1 (COMMITTED READ) and 2 (REPEATABLE READ). The following example executes a query in the COMMITTED READ isolation level. Setting Transaction Isolation Level Example ... EXEC SQL CONNECT TO DEFAULT ; EXEC SQL WHENEVER SQLERROR GOTO do_rollback ; EXEC SQL SET TRANSACTION ISOLATION LEVEL 0 ; All Rights Reserved 134 www.faircom.com Transaction Management in ESQL EXEC SQL SELECT INTO FROM WHERE name, city :cust_no_v, :name_v customer CUST_NO = 1024 ; ... EXEC SQL COMMIT WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (0) ; do_rollback: if (sqlca.sqlcode) { strncpy (errmesg, sqlca.sqlerrm, sqlca.sqlerrml); errmesg [sqlca.sqlerrml] = '\0' ; fprintf (stderr, "Error : %s\n", errmesg); } EXEC SQL WHENEVER SQLERROR CONTINUE ; EXEC SQL ROLLBACK WORK ; EXEC SQL DISCONNECT DEFAULT ; exit (1) ; ... Locking and Transactions During the execution of an ESQL program, transactions implicitly lock tables in a database. This is done so that the data in the database remains consistent. The implicit locks are released by committing the transaction or by disconnecting from the database. c-treeSQL supports two types of implicit locks: SHARE locks are acquired on rows that have been read by a transaction. A SHARE lock allows other transactions to read the row but prevents others from modifying the row until this transaction either commits or performs a rollback. EXCLUSIVE locks are acquired on rows that have been modified by a transaction. EXCLUSIVE locks prevent other transactions from either reading or modifying the rows until this transaction either commits or performs a rollback. In applications where a large number of rows will be accessed for either reading or modifying, ESQL provides an explicit locking construct for locking all the rows of a table. The LOCK TABLE statement explicitly locks a table in either SHARE or EXCLUSIVE mode. The following example shows acquiring a lock in the EXCLUSIVE mode for a table called customer: EXEC SQL LOCK TABLE customer IN EXCLUSIVE MODE; The above statement will prevent other transactions from either reading or modifying the table customer until the transaction either commits or performs a rollback. The following example shows acquiring lock in the SHARE mode for a table called orders: All Rights Reserved 135 www.faircom.com Transaction Management in ESQL EXEC SQL LOCK TABLE orders IN SHARE MODE; The above statement will prevent other transactions from modifying the orders table until the transaction either commits or performs a rollback. Explicit locking can be used to improve the performance of a single transaction at the cost of decreasing the concurrency of the system and potentially blocking other transactions. The increased performance comes from reducing the overhead imposed by the implicit locking mechanism, along with eliminating any potential waits for acquiring row level locks for the table. Abnormal Termination of an ESQL Application Program If an active transaction exists when an ESQL application disconnects from a database, then the transaction is rolled back automatically. The behavior is similar when an ESQL application terminates abnormally. In this case, disconnecting from the database is also automatic. Forced Rollback of a Transaction As mentioned in the previous section, a forced rollback of the transaction, if an active transaction exists, is done when an ESQL program disconnects or makes an abnormal exit. This forced rollback is performed to keep the database consistent. When some serious errors occur, a transaction might be implicitly marked for rollback. This can be detected by the information in the SQLCA. If a transaction is marked for rollback, no c-treeSQL statement can be executed on behalf of that transaction. In such a case, the application must rollback the current transaction before proceeding with execution of the next c-treeSQL statement. Interrupting the Execution of an SQL Statement An interruption to the database could be issued during the execution of an c-treeSQL statement. When an interruption occurs, the statement that is getting executed fails and an error code is returned in the SQLCA. The changes made by this particular statement are rolled back and the database gets back to the state that it was before execution of the c-treeSQL statement. Consider the following example: ... EXEC SQL CONNECT TO DEFAULT ; ... EXEC SQL INSERT INTO orders VALUES (:no_v, :date_v, :prod_v, :qty_v) ; /* * If the following statement execution is * interrupted, any database modifications that * might have been done by the UPDATE statement up to * the point of interruption are undone. But all * database modifications done by the * application on behalf of this transaction up * to the previous statement are not undone. * */ All Rights Reserved 136 www.faircom.com Transaction Management in ESQL EXEC SQL UPDATE orders SET product = :prod_x WHERE order_date > :ord_date ; /* End Transaction */ EXEC SQL COMMIT WORK ; EXEC SQL DISCONNECT DEFAULT ; ... In the sequence of operations shown above, if the interruption occurs during the execution of the UPDATE statement, then the UPDATE statement returns an error and all the changes made by the UPDATE statement are undone. But the changes done by the INSERT statement are retained. If the statement execution proceeds to the COMMIT WORK statement, then only the INSERT operation is made permanent. All Rights Reserved 137 www.faircom.com 14. Data Type Handling in ESQL 14.1 Introduction This chapter describes the data types that can be used in an ESQL application program. It also discusses the converting and comparing data of different types. The database types allowed in c-treeSQL have two representations: A database storage representation A host language representation The database storage representation refers to the way a value is stored in the database and the host language representation refers to the way a value is represented in the host language (C language). Necessary data conversions from one form to another are taken care of by c-treeSQL and therefore the application does not have to deal with the database storage representation. 14.2 Data Type Descriptions This section discusses the different data types supported by c-treeSQL and how they can be used in ESQL programs as input and output host variables. The material supplements the description of data types in the c-treeSQL Reference Manual. CHARACTER Data Type CHARACTER [(length)] Type CHARACTER (abbreviated as CHAR) corresponds to a null terminated character string with the maximum length specified. The default length is 1. The maximum length is 2000. The c-treeSQL engine representation is a variable length string. The host language representation is equivalent to the C language character string. As an input host variable, a literal character string or a host variable declared as a character array can be used. String constants or literals are enclosed within single/double quotes. In the following example, the SELECT statement uses both input and output character type host variables: Example: Using CHAR Data Type EXEC SQL BEGIN DECLARE SECTION ; All Rights Reserved 138 www.faircom.com Data Type Handling in ESQL CHAR city_v [19] ; CHAR name_v [19] ; EXEC SQL END DECLARE SECTION ; ... EXEC SQL SELECT city INTO :city_v FROM customer WHERE name = :name_v ; Here city_v is an output host variable and name_v is an input host variable, both declared as character arrays in the declare section. The input host variable can also be a character literal as shown: WHERE name = 'JOHN' ; Use scalar functions like SUBSTR, INSTR, LENGTH, LOWER, and UPPER for manipulating character strings. VARCHAR [(length)] Embedded c-treeSQL does not support the VARCHAR type. Use CHARACTER instead. LVARCHAR | LONG VARCHAR Refer to "Long Data Type Support" (page 176) for more information. SMALLINT Data Type The SMALLINT data type corresponds to an integer value of length two bytes. The database representation as well as the host language representation is a signed short INTEGER. The range of values corresponding to a column of this type is -32768 to +32767. The following example shows the declaration and usage of the SMALLINT data type: EXEC SQL BEGIN DECLARE SECTION ; SHORT deptno_v ; CHAR ename_v [19] ; EXEC SQL END DECLARE SECTION ; ... EXEC SQL SELECT ename, deptno INTO :ename_v, :deptno_v FROM employee WHERE empno = 2828 ; INTEGER Data Type The INTEGER data type corresponds to an integer of length 4 bytes. The database representation as well as host language representation is a long INTEGER. Integer constants must be expressed in decimal notation without embedded commas and without a decimal point. The INTEGER data may be preceded with an optional plus or minus sign. The range of values for a column of this type is -2147483648 to +2147483647. The following example shows the usage of the INTEGER data type: All Rights Reserved 139 www.faircom.com Data Type Handling in ESQL EXEC SQL BEGIN DECLARE SECTION ; LONG qty_v ; EXEC SQL END DECLARE SECTION ; EXEC SQL SELECT qty INTO :qty_v FROM orders WHERE order_no = 1002 ; BIGINT The BIGINT data type corresponds to an integer of length 8 bytes. The range of values for BIGINT columns is -2 ** 63 to 2 ** 63 -1. Both the c-treeSQL engine representation and the host language representation are equivalent to the following C structure: typedef struct { long ll ; long hl ; } tpe_bigint_t ; REAL Data Type The REAL data type corresponds to a single precision floating point number. The database representation and the host language representation are the same as the C language float type. The following example shows the usage of the REAL data type: EXEC SQL BEGIN DECLARE SECTION ; FLOAT val ; EXEC SQL END DECLARE SECTION ; EXEC SQL SELECT INTO FROM 120.00 + 100.50 :val syscalctable ; FLOAT Data Type The FLOAT data type corresponds to a double precision floating point number. The database representation and the host language representation are the same as the C language double type. The following example shows the usage of the FLOAT data type: EXEC SQL BEGIN DECLARE SECTION ; DOUBLE salary_v ; CHAR ename_v [19] ; EXEC SQL END DECLARE SECTION ; EXEC SQL SELECT ename, salary INTO :ename_v, :salary_v FROM employee All Rights Reserved 140 www.faircom.com Data Type Handling in ESQL WHERE empno = 2040 ; DOUBLE PRECISION The DOUBLE PRECISION data type corresponds to a double precision floating point number equivalent to the C language double type. Both the c-treeSQL engine representation and the host language representation are equivalent to the C language double type. V11 and later releases support DOUBLE as an alias for DOUBLE PRECISION. NUMERIC or DECIMAL Data Type Type NUMERIC corresponds to a number with the given precision (maximum number of digits) and scale (the number of digits to the right of the decimal point). By default, NUMERIC columns have a precision of 32 and scale of 0. In c-treeSQL, the format for specifying a NUMERIC column is as follows: { NUMERIC | NUMBER | DECIMAL } [ ( precision [ , scale ] ) ] See the c-treeSQL Reference Manual for details on storing NUMERIC values using c-treeSQL. Internally, c-treeSQL uses the tpe_num_t structure to store and return values of NUMERIC type. Host programs can access tpe_num_t to directly store and retrieve NUMERIC values, as discussed in the rest of this section. However, programs can avoid the complexities of dealing with the NUMERIC storage format directly by using the tpe_conv_data() function or c-treeSQL scalar conversion functions. Internal Storage Format for NUMERIC Data The tpe_num_t structure is as follows: typedef struct { short dec_num ; char dec_digits [17] ; } tpe_num_t ; dec_num The dec_num field of the structure contains the number of valid bytes in the dec_digits array. dec_digits [17] The dec_digits array contains the actual numeric data, stored in two parts: The first byte of dec_digits (dec_digits[0]) contains a sign bit and the exponent for the value, stored in “excess-64” notation. The second and subsequent valid bytes of dec_digits (dec_digits[1] through dec_digits[dec_num - 1]) contain base-100 values each representing two digits. The following figure shows the format for the dec_digits array. All Rights Reserved 141 www.faircom.com Data Type Handling in ESQL Figure: Format for NUMERIC Data Stored in the tpe_num_t Structure The following section describes in detail how to interpret data in the dec_digits array. Interpreting the Sign/Exponent Byte of dec_digits The high-order bit of dec_digits[0] specifies the sign of the NUMERIC data: 1 means positive and 0 means negative. The 7 lower-order bits of dec_digits[0] contain the exponent, stored in excess 64 notation. In excess-64 notation, you subtract 64 from the stored value to determine the actual value. For dec_digits[0], this means you subtract 64 from the value stored in the 7 lower-order bits to determine the value of the exponent. However, if the sign bit of dec_digits[0] is 0 (indicating a negative value), you must first perform a one’s complement of the 7 lower-order bits before subtracting 64. (To perform a one’s complement, swap zeroes with ones and ones with zeroes.) The following example shows how to determine the sign of the NUMERIC data and the value of its exponent when dec_digits[0] contains a base-10 value of 223. Example: Determining Sign and Exponent of NUMERIC Values Decimal value in dec_digits[0] 223 Binary equivalent 11011111 Sign bit 1 (Positive) One’s complement of exponent bits Not necessary, since sign bit is positive Binary value of exponent bits (excess-64 notation) 1011111 Decimal value of exponent bits (excess-64 notation) 95 Actual value of exponent 95 -64 = 31 The following example shows another example of dec_digits[0], containing the base-10 value of 100, which represents a negative data value and a negative exponent value. Example: Determining Sign and Exponent of NUMERIC Values Decimal value in dec_digits[0] 100 Binary equivalent 01100100 Sign bit 0 (Negative) One’s complement of exponent bits 0011011 Binary value of exponent bits (excess-64 notation) 0011011 All Rights Reserved 142 www.faircom.com Data Type Handling in ESQL Decimal value of exponent bits (excess-64 notation) 27 Actual value of exponent 27 - 64 + -37 Interpreting the Data Values Bytes of dec_digits The rest of the bytes in the dec_digits array contain the base-100 digits of the NUMERIC data, two digits in each byte. To extract the values from each data byte: 1. Convert the binary value to decimal. 2. If the sign bit indicated a negative number: • Perform a 99’s complement on the value (subtract the value from 99) for all but the last data value in the dec_digits array (dec_digits[1] to dec_digits[dec_num-2]). • Perform a 100’s complement on the value (subtract the value from 100) for the last data value in the f array (dec_digits[dec_num-1]). If the sign bit indicated a negative number, perform a 100’s complement on the value (subtract the value from 100). The resulting base-100 digits represent a number between 0 and 1. Multiply that result by 100 raised to the value of the exponent to get the final NUMERIC value. Complete Examples: Interpreting Sign/Exponent and Data Bytes of dec_digits The following examples detail how to extract base-10 values from dec_digits. Use them as a guide for interpreting values returned by c-treeSQL in tpe_num_t or to store values in the database using tpe_num_t. Example: Interpreting NUMERIC Storage: Positive Exponent and Data This example shows how the (base-10) value 123456 is stored in dec_digits. 11000011 1101 100011 111001 dec_digits[0] dec_digits[1] dec_digits[2] dec_digits[3] Sign/Exponent Byte Binary value in desc_digits[0] 11000011 Sign bit 1 (Positive) One’s complement of exponent bits Not necessary, since sign bit is positive Binary value of exponent bits (excess-64 notation) 1000011 Decimal value of exponent bits (excess-64 notation) 67 Actual value of exponent 67 - 64 = 3 All Rights Reserved 143 www.faircom.com Data Type Handling in ESQL Data Value Bytes 1 2 3 Binary value 1100 100010 111000 Decimal equivalent 12 34 56 99’s complement of all but last value N/A N/A N/A 100’s complement of all but last value N/A N/A N/A Base-100 digits 12 34 56 The resulting numeric value is 0.123456 x 1003, or 123456. Example: Interpreting NUMERIC Storage: Negative Exponent and Data This example shows how the (base-10) value -123456.789 is stored in dec_digits. 00111100 01010111 01000001 00101011 00010101 00001010 dec_digits[0] dec_digits[1] dec_digits[2] dec_digits[3] dec_digits[4] dec_digits[5] Sign/Exponent Byte Binary value in desc_digits[0] 00111100 Sign bit 0 (Negative) One’s complement of exponent bits 11000011 Binary value of exponent bits (excess-64 notation) 1000011 Decimal value of exponent bits (excess-64 notation) 67 Actual value of exponent 67 - 64 = 3 Data Value Bytes 1 2 3 4 5 Binary value 101011 1 1000001 101011 10101 1010 Decimal equivalent 87 65 43 21 10 99’s complement of all but last value 12 34 56 78 N/A 100’s complement of all but last value N/A N/A N/A N/A 90 Base-100 digits 12 34 56 78 90 The resulting numeric value is - 0.1234567890 x 1003, or 123456.789 All Rights Reserved 144 www.faircom.com Data Type Handling in ESQL DATE Data Type The DATE data type corresponds to a DATE value with three parts namely, day-of-month, month and year. The database representation is a long INTEGER. The host language representation is equivalent to the following C structure: typedef struct { short unsigned char unsigned char } tpe_date_t ; year ; month ; day ; The range for the year part is 1 to 9999. The range for the month part is 1 to 12. The lower limit for the day part is 1 and the upper limit depends on the month and the year. The following example shows the usage of the DATE data type: EXEC SQL BEGIN DECLARE SECTION ; DATE date_v ; EXEC SQL END DECLARE SECTION ; EXEC SQL SELECT INTO FROM WHERE order_date :date_v orders CUST_NO = 2002 ; The DATE data type can also be used in the WHERE clause as shown: WHERE order_date = :date_v ; Some of the scalar functions used to manipulate date values are ADD_MONTHS, MONTHS_BETWEEN, and TO_DATE. TIME Data Type The TIME data type corresponds to the time value with four parts: hours, minutes, seconds, and milliseconds. The database representation is a long integer. The host language representation is equivalent to the following C structure: typedef struct { unsigned char hours ; unsigned char mins ; unsigned char secs ; unsigned short msecs ; } tpe_time_t ; The range for the hours part is 0 to 23. The range for the minutes part is 0 to 59. The range for the seconds part is 0 to 59. The range for the milliseconds part is 0 to 999. The following example shows the usage of TIME data type: All Rights Reserved 145 www.faircom.com Data Type Handling in ESQL EXEC SQL BEGIN DECLARE SECTION ; TIME time_v ; EXEC SQL END DECLARE SECTION ; EXEC SQL SELECT INTO FROM WHERE arrival_time :time_v arrivals train_no = 230 ; Some of the scalar functions used to manipulate TIME data are TO_TIME, HOUR, MINUTE, SECOND, etc. TIMESTAMP The TIMESTAMP data type combines the parts of DATE and TIME. The c-treeSQL engine representation and the host language representation is equivalent to the following C structure: typedef struct { tpe_date_t tpe_time_t } tpe_timestamp_t ; ts_date ; ts_time ; BIT Type BIT corresponds to a single bit value of 0 or 1. The host language representation is unsigned CHAR. BINARY [(length)] The BINARY data type corresponds to a bit field of the specified length of bytes. The default length is 1 byte. The maximum length is 900 bytes. The host language representation of a BIT column is equivalent to the following structure: typedef struct { long tb_len ; unsigned char tb_data [TPE_MAX_FLDLEN+1] ; } tpe_binary_t ; LVARBINARY | LONG VARBINARY Refer to "Long Data Type Support" (page 176) for more information. Data Conversion This section discusses various methods that ESQL programs can use to convert data from one type to another: Implicit conversion through c-treeSQL Explicit conversion using the c-treeSQL API function tpe_conv_data() Explicit conversion using c-treeSQL scalar functions All Rights Reserved 146 www.faircom.com Data Type Handling in ESQL Note: For better portability, use implicit conversion or c-treeSQL scalar functions for data type conversion in ESQL programs. Use the c-treeSQL API call tpe_conv()_data for best performance. Implicit Data Type Conversion c-treeSQL performs the required data conversions between data types wherever possible. For example, while delivering each SELECT list value to the host variables in the INTO clause, c-treeSQL implicitly converts the data value, if necessary, from the database representation to the host language representation. If the database column is of type SMALLINT, while retrieving the value of that column into a host variable of type long, the value is automatically converted from SMALLINT to long INTEGER type. Implicit type conversions between all data types are not allowed. For example, using an INTEGER host variable to hold a character value will generate an error. The following example shows the implicit conversion of the MONEY data type to DOUBLE data type. Using c-treeSQL for Implicit Data Type Conversion EXEC SQL BEGIN DECLARE SECTION ; MONEY amount_v ; DOUBLE double_val ; EXEC SQL END DECLARE SECTION ; EXEC SQL SELECT :amount_v INTO :double_val FROM admin.syscalctable ; Using the SQL API Function tpe_conv_data for Data Type Conversion Host programs can use the c-treeESQL API call tpe_conv_data() to explicitly convert data from one type to the desired type. Unlike implicit type conversion, tpe_conv_data() performs type conversions between character and NUMERIC types. Syntax #include "sql_lib.h" tpe_status_t tpe_conv_data (dtype, bufl, buf, fmt, odtype, obufl, obuf) int dtype; int bufl; void *buf; char *fmt; int odtype; int obufl; void *obuf; Returns A negative error code on failure and a zero value on success. All Rights Reserved 147 www.faircom.com Data Type Handling in ESQL Parameters dtype The data type of the input value in buf. dtype must be one the following data-type symbolic names specified in #define directives in $TPEROOT/include/sql_lib.h: TPE_DT_ERR TPE_DT_CHAR TPE_DT_NUMERIC TPE_DT_SMALLINT_ TPE_DT_INTEGER TPE_DT_SMALLFLOAT TPE_DT_REAL TPE_DT_FLOAT TPE_DT_DATE TPE_DT_MONEY TPE_DT_TIME TPE_DT_TIMESTAMP TPE_DT_TINYINT TPE_DT_BINARY TPE_DT_BIT TPE_DT_LVC TPE_DT_LVB TPE_DT_BIGINT bufl The length of buf. buf The buffer containing the input data. fmt A format string that specifies the output format. Valid only if dtype is TPE_DT_DATE and odtype is TPE_DT_CHAR. See the discussion of date-time format strings in the c-treeSQL Reference Manual for details. odtype The data type of the output required after conversion. obufl The length of obuf. obuf The output buffer that receives the converted data. The following example shows the conversion from character data to INTEGER data. In the example, data is the buffer containing input data and outval is the output data returned. Using tpe_conv_data to Convert Character to Integer Data EXEC SQL BEGIN DECLARE SECTION ; CHAR data [20] ; LONG outval ; EXEC SQL END DECLARE SECTION ; strcpy (data, "1234") ; status = tpe_conv_data (TPE_DT_CHAR, strlen (data), data, "", TPE_DT_INTEGER, sizeof (long), &outval) ; All Rights Reserved 148 www.faircom.com Data Type Handling in ESQL The following example shows using tpe_conv_data() to convert NUMERIC data retrieved from the database into character data for use by the host program. In the example, var7 is the buffer containing input data and var0 is the output data returned. Using tpe_conv_data to Convert Numeric to Character Data EXEC SQL BEGIN DECLARE SECTION; char var0[50]; numeric var7; EXEC SQL END DECLARE SECTION; ... EXEC SQL SELECT fld2 INTO :var7 FROM compt WHERE fld1='10'; tpe_conv_data( TPE_DT_NUMERIC,sizeof(tpe_num_t),&var7, " ", TPE_DT_CHAR,50,var0); fprintf(stdout,"var0 = %s\n",var0); ... Using SQL Scalar Functions for Data Type Conversion Alternatively, one data value can be converted to another data value of a data type using scalar functions. The following example shows some of conversions that can be done using scalar functions. Using Scalar Functions for Data Type Conversion EXEC SQL BEGIN DECLARE SECTION ; NUMERIC num_val ; DATE date_val ; EXEC SQL END DECLARE SECTION ; EXEC SQL SELECT INTO FROM TO_DATE ('10/10/1992') :date_val admin.syscalctable ; EXEC SQL SELECT INTO FROM TO_NUMBER ('1234') :num_val admin.syscalctable ; In the first example, the character expression is converted to DATE type using the TO_DATE scalar function and the result is fetched into date_val. In the second example, the character expression is converted to the NUMERIC type using the TO_NUMBER scalar function and the result is fetched into num_val. Some of the other scalar functions available for conversion are TO_CHAR and TO_TIME. All Rights Reserved 149 www.faircom.com Data Type Handling in ESQL Data Comparison This section discusses methods that ESQL programs can use to compare data values from one type to another: Using the c-treeESQL API function tpe_compare_data() Comparison through c-treeSQL arithmetic expressions Note: For better portability, use c-treeSQL arithmetic expressions for data comparison. Use the c-treeESQL API call tpe_compare_data() for best performance. Using the SQL API Function tpe_compare_data for Data Comparison Host programs can use the c-treeESQL API call tpe_compare_data() to compare two data values of the same type. The tpe_compare_data() function is similar to the C language function strcmp(). Syntax #include "sql_lib.h" tpe_status_t tpe_compare_data (dtype, buf1len, buf1, buf2len, buf2, result) int int void int void short dtype; buf1len; *buf1; buf2len; *buf2; *result ; Returns A negative error code on failure and a zero value on success. Parameters dtype The data type of the two objects that are being compared. dtype must be one the following data-type symbolic names specified in #define directives in $TPEROOT/include/sql_lib.h: TPE_DT_ERR TPE_DT_CHAR TPE_DT_NUMERIC TPE_DT_SMALLINT TPE_DT_INTEGER TPE_DT_SMALLFLOAT TPE_DT_REAL TPE_DT_FLOAT TPE_DT_DATE TPE_DT_MONEY TPE_DT_TIME TPE_DT_TIMESTAMP TPE_DT_TINYINT TPE_DT_BINARY TPE_DT_BIT TPE_DT_LVC TPE_DT_LVB TPE_DT_BIGINT buf1len The length of the first data object. buf1 The buffer containing the first data object. All Rights Reserved 150 www.faircom.com Data Type Handling in ESQL buf2len The length of the second data object. buf2 The buffer containing the second data object. result Pointer to a location for returning the result. result is a short integer with one of the following values: 1 First data object is greater than second data object. -1 First data object is less than second data object. 0 The two data objects are equal. tpe_compare_data() returns 0 if the comparison is successful, a non zero error code, otherwise. The following example shows the comparison of two NUMERIC data elements. The examples compares the values in val1 and val2 while tpe_compare_data() stores the result in result. Using the tpe_compare_data API Function for Data Comparison EXEC SQL BEGIN DECLARE SECTION ; NUMERIC val1 ; NUMERIC val2 ; SHORT result ; EXEC SQL END DECLARE SECTION ; ... status = tpe_compare_data (TPE_DT_NUMERIC, sizeof (tpe_num_t), (void *)&val1, sizeof (tpe_num_t), (void *)&val2, &result) ; if (status == 0) { if (result > 0) printf ("val1 > val2 ") ; else if (result < 0) printf ("val1 < val2 ") ; else printf ("val1 = val2 ") ; } Using SQL Arithmetic Expressions for Data Comparison Two data values can be also compared using c-treeSQL arithmetic expressions. The following example shows using date arithmetic to compare two dates, date1 and date2. c-treeSQL returns the difference, as the number of days between the two dates, in result. Using SQL for Data Comparison EXEC SQL BEGIN DECLARE SECTION ; DATE date1 ; DATE date2 ; SHORT result ; All Rights Reserved 151 www.faircom.com Data Type Handling in ESQL EXEC SQL END ... EXEC SQL SELECT INTO FROM DECLARE SECTION ; :date1 - :date2 :result admin.syscalctable ; if (sqlca.sqlcode == 0) { if (result > 0) printf ("date1 > date2 ") ; else if (result < 0) printf ("date1 < date2 ") ; else printf ("date1 = date2 ") ; } All Rights Reserved 152 www.faircom.com 15. ESQL Reference 15.1 Introduction This chapter contains reference material on c-treeSQL statements specific to ESQL. For reference information on all other c-treeSQL statements, see the c-treeSQL Reference Manual. 15.2 BEGIN-END DECLARE SECTION Declares variables and types for use in: Variables referred to in an embedded c-treeSQL statement must be declared in a BEGIN-END DECLARE SECTION. Variables must be declared as a host language type or as a type previously declared in a BEGIN-END DECLARE SECTION. Syntax EXEC SQL BEGIN DECLARE SECTION variable_or_type_declaration [...] EXEC SQL END DECLARE SECTION variable_or_type_declaration :: { host_language_type variable_name [ , … ] ; | { variable_name [ , … ] | TYPE new_type_name } } type_spec ; Arguments host_language_type variable_name [ , … ] esqlc A conventional C-language variable declaration. This form of variable declaration conforms to ANSI standards. The following host language C types are supported by ESQL: host_language_type :: { [unsigned] char | [unsigned] short | [unsigned] long | float | double } The host language C type int is not supported in ESQL. Type int maps to 16- or 32-bits depending on the machine architecture. This has the potential of creating rounding errors at All Rights Reserved 153 www.faircom.com ESQL Reference runtime in shipping values in the transaction execution calls across different machine architectures. { variable_name [ , … ] | TYPE new_type_name } type_spec A variable or type declaration that uses ESQL-specific TYPE syntax. This form of declaration is an extension to the SQL standard: The variable_name clause declares one or more variables of the type specified in type_spec. The TYPE new_type_name clause declares a user-defined type of the type specified in type_spec. Type declarations inherit all the properties of a host language type or a previously-declared type. The new type can be used to declare variables or other types in either ESQL or in the host language. Notes Variables can be used in host language statements as if they had been declared directly in the host language with the same name. The scope of variables follow host-language scoping rules. ESQL variables are not visible outside the file in which they are declared. DECLARE sections are permissible only where host language declarations are permissible in the host language syntax. This restriction is due to the translation of DECLARE SECTION blocks into host language declarations. Avoid DECLARE sections in header files that are included in more than one file. They might cause creation of duplicate variables with the same name. The form of the variable created by ESQL for each type is specified so that it can be manipulated from host language statements. Declaration of variables in ESQL provides for their use in both host language and ESQL statements. Example EXEC SQL BEGIN DECLARE SECTION ; long cust_id ; short i_cust_id ; char cust_name [30] ; short i_custname ; EXEC SQL END DECLARE SECTION ; EXEC SQL BEGIN DECLARE SECTION; long cust_no ; char name [30] ; EXEC SQL END DECLARE SECTION; Authorization None. SQL Compliance Declarations that use host-language types are SQL-92 compliant. Other declarations are c-treeSQL extensions. Related Statements TYPE All Rights Reserved 154 www.faircom.com ESQL Reference 15.3 CLOSE Description Closing a cursor sets the state of the cursor to be closed. Syntax EXEC SQL CLOSE cursor_name ; Notes A cursor can be closed only if it is in the open state. A cursor is automatically closed when the transaction ends. Once a cursor is closed, FETCH, DELETE, or UPDATE operations cannot be performed on the cursor. It is a good practice to close cursors explicitly. Example EXEC SQL OPEN cust_cur ; EXEC SQL FETCH cust_cur INTO ... ; EXEC SQL CLOSE cust_cur ; Authorization None (see Authorization for "OPEN" (page 163)). 15.4 SQL Compliance SQL-92 Related Statements DECLARE, OPEN, FETCH, positioned UPDATE, positioned DELETE DECLARE CURSOR Description Associates a cursor with a static query or a prepared dynamic query statement. The query and/or the prepared statement can have references to host variables. Syntax EXEC SQL DECLARE cursor_name CURSOR FOR { query_expression [ORDER BY clause] [ FOR UPDATE clause] | prepared_statement_name } ; All Rights Reserved 155 www.faircom.com ESQL Reference Notes Declare a cursor before any OPEN, FETCH, or CLOSE statements. The scope of the cursor declaration is the entire source file in which it is declared. The operations on the cursor such as OPEN, CLOSE, and FETCH can occur only within the same compilation unit as the cursor declaration. The use of a cursor allows the execution of the positioned forms of the update and delete statements. If the declare corresponds to a static c-treeSQL statement containing parameter references then, the DECLARE statement must be executed before each execution of OPEN statement for the same cursor. Also, the DECLARE statement and the following OPEN statement for the same cursor must occur within the same transaction definition (within the same task). In addition, if the statement contains parameter references to stack variables (auto variables or function arguments) the DECLARE statement and the following OPEN statement for the same cursor must occur within the same C function. See "Single-Row SELECT Statement" (page 167) for descriptions of ORDER BY and FOR UPDATE clauses. Example EXEC SQL DECLARE custcur CURSOR FOR SELECT cust_no, name, street, city, state FROM customer ; Authorization None (See Authorization for "OPEN" (page 163)). 15.5 SQL Compliance SQL-92. c-treeSQL extensions: support for prepared_statement_name. Related Statements PREPARE, OPEN, FETCH, CLOSE, Select Statement, Query Expression DESCRIBE Description Writes information about a prepared statement to the c-treeSQL Descriptor Area (SQLDA). The DESCRIBE statement is one of several dynamic SQL statements that allow programs to accept or generate c-treeSQL statements at run time. Such dynamically generated statements are not necessarily part of a program’s source code, but can be generated at run time. There are two forms of the DESCRIBE statement: The DESCRIBE BIND VARIABLES statement writes information about input variables (either substitution names or parameter markers) in expressions to an SQLDA. All Rights Reserved 156 www.faircom.com ESQL Reference The DESCRIBE SELECT LIST statement writes information about select list items in a prepared SELECT statement to an SQLDA. The SQLDA is a host-language data structure used in dynamic SQL. DESCRIBE statements write information about the number, data types, and sizes of input variables or select-list items to SQLDA structures. Programs read that information in the SQLDA structures to allocate storage. OPEN, EXECUTE, and FETCH statements read SQLDA structures for the addresses of the allocated storage. For more information on the SQLDA, see "Dynamic SQL Management in ESQL" (page 109). Syntax EXEC SQL DESCRIBE INTO EXEC SQL DESCRIBE INTO BIND VARIABLES FOR statement_name input_sqlda_name ; SELECT LIST FOR statement_name output_sqlda_name ; Arguments BIND VARIABLES Specifies that the DESCRIBE statement should write information about any input variables in the prepared statement to an input SQLDA structure. Input variables represent values supplied at run time by the program to S and UPDATE statements, and to predicates in DELETE, UPDATE, and SELECT statements. The DESCRIBE BIND VARIABLES statement writes the number of input variables to the sqld_nvars field of the SQLDA. If the sqld_size field of the SQLDA is not equal to or greater than this number, DESCRIBE writes the value as a negative number to sqld_nvars. Programs should check sqld_nvars for a negative number to determine if they allocated enough storage for a particular SQLDA. Programs supply input variables to the PREPARE statement either as substitution names or as parameter markers. See "PREPARE" (page 164) for more information. Programs must issue a DESCRIBE BIND VARIABLES statement after the PREPARE statement but before the corresponding EXECUTE or OPEN statement for the dynamic SQL statement. statement_name The name of a c-treeSQL statement to be dynamically executed. Use the name supplied in the corresponding PREPARE statement. input_sqlda_name The name of the SQLDA structure to which DESCRIBE will write information about input variables. SELECT LIST Specifies that the DESCRIBE statement should write information about select-list items in a prepared SELECT statement to an output SQLDA structure. Select list items are column names and expressions in a SELECT statement. A FETCH statement writes the values returned by the SELECT statement to the addresses stored in the output SQLDA. All Rights Reserved 157 www.faircom.com ESQL Reference The DESCRIBE SELECT LIST statement writes the number of select list items to the sqld_nvars field of the SQLDA. If the sqld_size field of the SQLDA is not equal to or greater than this number, DESCRIBE writes the value as a negative number to sqld_nvars. Programs should check sqld_nvars for a negative number to determine if they allocated enough storage for a particular SQLDA. Programs must issue a DESCRIBE SELECT LIST statement after the DECLARE CURSOR, PREPARE, and OPEN statements for a dynamic SELECT statement, but before the first corresponding FETCH statement for the cursor. statement_name The name of a SELECT statement to be dynamically executed. Use the name supplied in the corresponding PREPARE statement. output_sqlda_name The name of the SQLDA structure to which DESCRIBE will write information about select list items. This example shows a series of embedded c-treeSQL statements that process a dynamic SELECT statement. It omits intervening host language source code: Example EXEC SQL DECLARE CURSOR dyn_cursor FOR dyn_select EXEC SQL PREPARE dyn_select FROM :sql_string EXEC SQL DESCRIBE SELECT LIST FOR dyn_select INTO outputsqlda ; EXEC SQL DESCRIBE BIND VARIABLES FOR dyn_select INTO inputsqlda ; EXEC SQL OPEN dyn_cursor USING DESCRIPTOR inputsqlda ; EXEC SQL FETCH dyn_cursor USING DESCRIPTOR outputsqlda ; Authorization None. SQL Compliance SQL-92 Related Statements PREPARE, DECLARE, OPEN, FETCH, CLOSE All Rights Reserved 158 www.faircom.com ESQL Reference 15.6 END DECLARE SECTION See the discussion on "BEGIN-END DECLARE SECTION" (page 153). 15.7 EXEC SQL Description In programs, precede embedded c-treeSQL statements with EXEC SQL so that they can be distinguished from the host language statements. (Do not use EXEC SQL prefixes for constructs within a BEGIN-END DECLARE section, such as type or variable declarations.) Terminate c-treeSQL statements with a semicolon to denote the end of the statement. Syntax EXEC SQL sql_statement; Example EXEC SQL BEGIN DECLARE SECTION; long cust_no ; char name [30] ; EXEC SQL END DECLARE SECTION; EXEC SQL DELETE FROM customer WHERE customer.name = 'Ralph' ; Notes The esqlc compiler does not, in general, parse host language statements and therefore does not detect any syntax or semantic errors of the host language statements. The exceptions to this rule are the recognition of host language blocks and #define constants. Host language blocks are recognized to determine the scope of variables and types declared in esqlc constructs. #define constants are evaluated by calling the C preprocessor, before the esqlc compilation process as they can occur in ESQL constructs. 15.8 SQL Compliance SQL-92 Related Statements BEGIN-END DECLARE, TYPE EXECUTE Description Executes the prepared statement specified in statement_name. All Rights Reserved 159 www.faircom.com ESQL Reference If there are any host variable references in the prepared statement, then the actual host variables have to be specified in the optional USING clause in the order they are encountered in the prepared statement. Syntax EXEC SQL EXECUTE statement_name [ USING { :host_variable [:indicator_variable] } [ , … ] | USING DESCRIPTOR descriptor_name ] ; Notes The statement to be executed must be prepared within the same transaction. A prepared statement can be executed one or more times with different host variables by repeated calls to the EXECUTE statement within the same transaction. EXECUTE can specify only host variables which are input arguments to the c-treeSQL statement. All c-treeSQL statements except SELECT statements can be prepared and executed in this manner. If a descriptor is not used in the USING clause, EXECUTE is restricted in that the number of host variable references and the types have to be known when the program is compiled. This is necessary since they have to be declared in the DECLARE SECTION before they can be used in the USING clause of the EXECUTE statement. If a descriptor is used, the allocation for the input variables can be done at runtime. Example EXEC SQL BEGIN DECLARE SECTION ; char sql_string [256] ; long cust_no ; EXEC SQL END DECLARE SECTION ; ... strcpy (sql_string, "DELETE FROM customer WHERE cust_no = :cust_no_marker") ; EXEC SQL PREPARE stmt1 FROM :sql_string ; EXEC SQL EXECUTE stmt1 USING :cust_no ; ... The following example shows the usage of the USING DESCRIPTOR clause in the EXECUTE statement. EXEC SQL BEGIN DECLARE SECTION ; char stmt [256] ; EXEC SQL END DECLARE SECTION ; ... EXEC SQL PREPARE stmtid FROM :stmt ; EXEC SQL EXECUTE stmt USING DESCRIPTOR sqldaptr ; ... Authorization The user executing this statement must have authorization for the c-treeSQL statement that is being executed (see Authorization of the relevant statement). SQL Compliance All Rights Reserved SQL-92 160 www.faircom.com ESQL Reference Related Statements 15.9 EXECUTE IMMEDIATE, PREPARE, SQLCA structure EXECUTE IMMEDIATE Description Executes the SQL statement specified in statement_string or host_variable. Syntax EXEC SQL EXECUTE IMMEDIATE { host_variable | statement_string } ; Example EXEC SQL EXECUTE IMMEDIATE "DELETE FROM customer WHERE cust_no = 1404 " ; Notes The character string form of the statement is referred to as a statement string. The EXECUTE IMMEDIATE statement accepts either a statement string or a host variable. The statement string must not contain host variable references or parameter markers. The statement string must not start with EXEC SQL and must not terminate with a semicolon. When an EXECUTE IMMEDIATE statement is executed, the specified statement string is parsed and checked for errors. Any error in the statement execution is reported in the SQLCA. If the same c-treeSQL statement is to be executed more than once, it is more efficient to use PREPARE and EXECUTE statements, rather than the EXECUTE IMMEDIATE statement. Authorization The user executing this statement must have authorization for the c-treeSQL statement that is being executed (see Authorization of the relevant statement). SQL Compliance SQL-92 Related Statements EXECUTE, SQLCA structure 15.10 FETCH Description Moves the position of the cursor to the next row of the active set and fetches the column values of the current row into the specified host variables. All Rights Reserved 161 www.faircom.com ESQL Reference Syntax EXEC SQL FETCH cursor_name { INTO { :host_variable [:indicator_variable] } [ , ... ] | USING DESCRIPTOR descriptor_name } ; Notes The cursor should be open for the FETCH operation to succeed. The positioning of the cursor on each FETCH operation is as follows: • Execution of the FETCH statement the first time after the cursor has been opened positions the cursor to the first row of the active set. • Subsequent FETCH operations advance the cursor position in the active set making the next row the current row. • When the current row is deleted using the positioned DELETE statement, the cursor will be positioned before the next row of the deleted row in the active set. The cursor can only be moved forward in the active set by executing FETCH statements. The cursor can be moved to the beginning of the active set only by closing the cursor and reopening the cursor. If the cursor is positioned on the last row of the active set or if the active set does not contain any rows, then the execution of a FETCH will return the status code SQL_NOT_FOUND in SQLCA. Upon successful execution, the cumulative number of rows fetched so far for this cursor after the last open, is returned in sqlca.sqlerrd [2]. Multiple rows can be fetched in one fetch call by using esqlc array variables in the INTO clause. In this case, SQL_NOT_FOUND status code is returned in SQLCA when the end of the active set is reached even if one or more rows are returned by the current execution of FETCH statement. If esqlc array variables are used in a fetch statement, the array sizes are set to the number of tuples fetched after an execution of the FETCH statement. Example EXEC SQL BEGIN DECLARE SECTION ; long cust_no_v ; char name_v [20] ; char street_v [40] ; char city_v [10] ; char state_v [2] ; EXEC SQL END DECLARE SECTION ; ... EXEC SQL OPEN cust_cur ; for (;;) { EXEC SQL FETCH cust_cur INTO :cust_no_v, :name_v, :street_v, :city_v, :state_v ; ... } ... All Rights Reserved 162 www.faircom.com ESQL Reference The usage of the DESCRIPTOR clause in the FETCH statement is shown below: ... EXEC SQL FETCH cust_cur USING DESCRIPTOR sqldaptr ; ... Authorization None. (See Authorization for "OPEN" (page 163).) SQL Compliance SQL-92. c-treeSQL extensions: USING DESCRIPTOR clause Related Statements DECLARE, OPEN, CLOSE 15.11 OPEN Description Executes the prepared c-treeSQL query associated with the cursor and creates a result set composed of the rows that satisfy the query. The collection of rows identified is called the active set. The optional USING clause specifies the location of values that c-treeSQL uses to substitute for input variables in the prepared c-treeSQL query. (See the discussion on "PREPARE" (page 164) for more detail.) Syntax EXEC SQL OPEN cursor_name [ USING { :host_variable [:indicator_variable] } [ , … ] | USING DESCRIPTOR descriptor_name ] ; Notes The cursor is placed in an open state and the cursor positioned just before the first row of the active set. Once the cursor is opened the active set does not change and the host variables are not reexamined. If a host variable value is changed and a new active set is to be determined, then the cursor should be closed and reopened. Execution of the COMMIT or ROLLBACK statement implicitly closes the cursors which have been opened within the transaction. It is always better to close an OPEN cursor explicitly. An OPEN statement is not allowed on a cursor which is already in the open state. If the declare corresponds to a static c-treeSQL statement and contains parameter references then, the DECLARE statement must be executed before each execution of OPEN statement for the same cursor. All Rights Reserved 163 www.faircom.com ESQL Reference Also, the DECLARE statement and the following OPEN statement for the same cursor must occur within the same transaction definition (within the same task, if tasking is supported). In addition, if the statement contains parameter references to stack variables (auto variables or function arguments) the DECLARE statement and the following OPEN statement for the same cursor must occur within the same C function. Example EXEC SQL OPEN cust_cur ; EXEC SQL OPEN ord_cur USING :order_no_v ; EXEC SQL OPEN dyn_cur USING DESCRIPTOR sqldaptr ; Authorization The user executing this statement must have any of the following privileges: DBA privilege SELECT privilege on all the tables/views referred to in the SELECT statement associated with the cursor. SQL Compliance SQL-92. c-treeSQL extensions: USING DESCRIPTOR clause Related Statements DECLARE, CLOSE, FETCH, UPDATE positioned, DELETE positioned 15.12 PREPARE Description Parses and assigns a name to a dynamically-generated c-treeSQL statement for execution. The PREPARE statement is one of several dynamic SQL statements that allow programs to accept or generate c-treeSQL statements at run time. Such dynamically-generated statements are not necessarily part of a program’s source code, but can be generated at run time. Syntax EXEC SQL PREPARE statement_name FROM { :variable_name | statement_string } ; Arguments statement_name A name for the dynamically-generated statement. DESCRIBE, EXECUTE, and DECLARE CURSOR statements refer to the statement name. Statement names must be unique within a program file. All Rights Reserved 164 www.faircom.com ESQL Reference :variable_name | statement_string Specifies the c-treeSQL statement to be prepared for dynamic execution. Use either the name of a host-language string variable that contains the statement string, or specify the string directly, enclosed in quotes. Either way, the statement string must be a character string that is a dynamically executable c-treeSQL statement. If it contains a syntax error, the PREPARE statement returns an error in the SQLCA. The statement string can have one or more references to input variables. Input variables represent values supplied at run time by the program to INSERT and UPDATE statements, and to predicates in DELETE, UPDATE, and SELECT statements. Programs supply input variables to the PREPARE statement either as substitution names or as parameter markers: Substitution names are names preceded by a colon ( : ) in the statement strings. They do not refer to host-language variable names, but act only as placeholders for input variables. Parameter markers are question marks (?) in the statement string, and also act as placeholders for input variables. The USING clauses of EXECUTE (for non-SELECT statements) and OPEN (for SELECT statements) statements specify host-language storage for values to substitute for substitution names and parameter markers. Programs can execute the same prepared statement many times within a transaction and supply different values for input variables each time. However, a statement string must be prepared again if the transaction commits or rolls back. The following example shows embedded c-treeSQL statements for preparing a DELETE statement. It uses the statement name del_cust_stmt and specifies a substitution name of :cust_no_marker. The USING clause of the EXECUTE statement specifies a host variable, :cust_no, to supply the value at run time. Example ... EXEC SQL BEGIN DECLARE SECTION ; char sql_string [256] ; long cust_no ; EXEC SQL END DECLARE SECTION ; strcpy ( sql_string, "DELETE FROM cust WHERE cust_no = :cust_no_marker") ; EXEC SQL PREPARE del_cust_stmt FROM :sql_string ; EXEC SQL EXECUTE del_cust_stmt USING :cust_no ; ... Authorization The user executing this statement must have any of the following privileges: DBA privilege Authorization for the c-treeSQL statement that is being executed. (See Authorization for the relevant statement) SQL Compliance All Rights Reserved SQL-92 165 www.faircom.com ESQL Reference Related Statements EXECUTE, OPEN, CLOSE, FETCH, and SQLCA structure 15.13 Query Expressions Note: The following information is specific to ESQL. For more detail on query expressions, see the c-treeSQL Reference Manual. SELECT expr [ ' column_title ' ] [, expr [ ' column_title ' ] ] ... Specifies a list of expressions, called a select list, whose results will form columns of the result table. Typically, the expression is a column name from a table named in the FROM clause. The expression can also be any supported mathematical expression, scalar function, or aggregate function that returns a value. The optional 'column_title' argument specifies a new heading for the associated column in the result table. Enclose the new title in single quotation marks: SELECT customer_id 'Number', customer_name 'Name' FROM customer ; column_title is also the column name returned when a DESCRIBE SELECT LIST statement is executed for a cursor associated with the SELECT statement. 15.14 Search Conditions Note: This section pertains to ESQL specifically and supplements the discussion of search conditions in the c-treeSQL Reference Manual. LIKE Predicate Description The LIKE predicate searches for strings that have a certain pattern. The pattern is specified after the LIKE keyword in either a host variable or as a string constant. The pattern can be specified by a string in which the underscore ( _ ) and percent sign ( % ) characters have special semantics. The ESCAPE clause can be used to disable the special semantics given to characters ‘ _ ’ and ‘ % ’. The escape character specified must precede the special characters in order to disable their special semantics. Syntax like_predicate :: column_name [ NOT ] LIKE { host_variable | string_constant } [ ESCAPE escape-character ] All Rights Reserved 166 www.faircom.com ESQL Reference Notes The column name specified in the LIKE predicate must refer to a character string column. If a host variable is specified then it must be a character string type variable. IN Predicate Description The IN predicate can be used to compare a value with a set of values. If an IN predicate specifies a query expression, then the result table it returns can contain only a single column. Syntax in_predicate :: expr [ NOT ] IN { ( query_expression ) | ( { host_variable | constant } [ , … ] ) } Example address.state IN ('MA', 'NH') 15.15 Single-Row SELECT Statement Description The single-row form of the SELECT statement can return at most one row in a result table. Use it in embedded c-treeSQL programs to assign the values of a one-row result table directly to host variables. The syntax for the single-row form is similar to the general form, with the following differences: The single-row form cannot specify SELECT *. The single-row form must include an INTO clause. The single-row form cannot use set operators. Syntax single_row_select_statement :: SELECT [ALL | DISTINCT] { expr [column_title] [, expr [column_title], ...] } INTO :parameter, :parameter, ... FROM table_name[alias_name], table_name[alias_name], ... [WHERE search_condition] [GROUP BY clause] [HAVING clause] [ORDER BY clause] [FOR UPDATE clause] ; Arguments SELECT [ ALL | DISTINCT ] All Rights Reserved 167 www.faircom.com ESQL Reference If the DISTINCT keyword is specified then duplicate rows will be automatically eliminated from the rows retrieved by the system. The default action corresponds to the ALL keyword where all the selected rows including duplicates are returned. INTO In the single-row form of the SELECT statement, the selected values are assigned to the host variables specified in the INTO clause. The INTO clause must precede the FROM clause. If no rows are selected, the condition SQL_NOT_FOUND is returned in the SQLCA structure. FROM If the selected column name appears in more than one table specified in the FROM clause then the column name should be prefixed by the optional table name, or an alias, to resolve ambiguity. WHERE The WHERE clause specifies the conditions to be satisfied for row selection. If the WHERE clause is not specified then all the rows of the specified table or the Cartesian product of all the tables specified in the FROM clause are returned. For more detail, see the discussion of query expressions and search conditions in the c-treeSQL Reference Manual. GROUP BY The GROUP BY clause specifies the grouping of rows returned by the SELECT statement. For more detail, see the discussion of query expressions in the c-treeSQL Reference Manual. HAVING The HAVING clause allows conditions to be set on the groups returned by the SELECT statement. For more detail, see the discussion of query expressions in the c-treeSQL Reference Manual. ORDER BY The ORDER BY clause allows the specification of the ordering in which rows are returned by the SELECT statement. For more detail, see the reference section on the SELECT statement in the c-treeSQL Reference Manual. FOR UPDATE The FOR UPDATE clause specifies the update intention on the selected rows. For more detail, see the reference section on the SELECT statement in the c-treeSQL Reference Manual. Example SELECT cust_no INTO :cust_v FROM customer WHERE name = :cust_name ; Authorization The user executing this statement must have either DBA privilege or SELECT privilege on all the tables referred to in the statement. All Rights Reserved 168 www.faircom.com ESQL Reference 15.16 Type Specifications for Variable and Type Declarations Description In addition to standard host-language variable declarations, ESQL supports several forms for declaring variables and user-defined types. All ESQL variable and type declarations must be within a BEGIN-END DECLARE SECTION. This section summarizes the type-specification syntax, and subsequent sections detail syntax and usage for the various type specifications. Syntax { variable_name [ , … ] | TYPE new_type_name } type_spec type_spec :: { IS OF TYPE database_type; | IS OF TYPE host_language_type ; | IS LIKE table_name.table_column_name ; | IS AN ARRAY OF type_name WITH SIZE constant_id; | IS A RECORD OF field_name IS OF TYPE type_name; [ ... ] END OF RECORD ; | IS A RECORD LIKE table_name [ WITH ( table_column_name [ , ... ] ) ] ; } Arguments { variable_name [ , … ] | TYPE new_type_name } If the declaration omits the TYPE keyword at the beginning, esqlc declares one or more variables of the type specified in type_spec. Such variables can be used in embedded SQL statements. They can also be used in host language statements as if they had been declared directly in the host language. If the declaration begins with the TYPE keyword, esqlc declares a user-defined type. User-defined types inherit all the properties of a host language type or a previously-declared type. The new type introduced by the declaration can be used to declare variables or other types in either esqlc or in the host language. IS OF TYPE database_type Specifies a type supported by c-treeSQL. See "Database Types" (page 170). IS OF TYPE host_language_type Specifies a type supported by the host language. IS LIKE table_name.table_column_name Specifies a type that corresponds to the type of a table column in the database. IS AN ARRAY OF type_name WITH SIZE constant_id Specifies a static-sized array type consisting of elements of any type. See "Static Array Types" (page 172) for details. IS A RECORD OF …END OF RECORD ; All Rights Reserved 169 www.faircom.com ESQL Reference Specifies a record that consists of one or more fields of the specified types. IS A RECORD LIKE table_name [ WITH ( table_column_name [ , ... ] ) ] Specifies record consisting of all the columns or a subset of the columns of the specified table. This specification is a shortcut for declaring a RECORD and then using the table field type declarations. Authorization None. SQL Compliance c-treeSQL extension Related Statements BEGIN-END DECLARE SECTION Database Types Description Declares a variable or type that corresponds to a data type supported by c-treeSQL. This declaration must be within a BEGIN-END DECLARE SECTION (see "BEGIN-END DECLARE SECTION" (page 153) for details). Syntax { variable_name [ , … ] | TYPE new_type_name } IS OF TYPE database_type; Arguments { variable_name [ , … ] | TYPE new_type_name } If the declaration omits the TYPE keyword at the beginning, esqlc declares one or more variables of the specified type. If the declaration begins with the TYPE keyword, esqlc declares a user-defined type. database_type Name of a data type supported by the c-treeACE SQL Server. See "Data Type Descriptions" (page 138) for a description of supported database data types. Notes It is not necessary to have a type declaration for a database type to declare a variable in esqlc. The following variable declaration can also be used with the same effect: variable_name IS OF TYPE NUMERIC; For convenience, users can define new types that inherit all the properties of a database type or a previously declared type. The new type introduced by the declaration can be used to declare variables or other types in either ESQL or in the host language. Example ... All Rights Reserved 170 www.faircom.com ESQL Reference EXEC SQL BEGIN DECLARE SECTION ; TYPE customer_id IS OF TYPE NUMERIC; EXEC SQL END DECLARE SECTION ; ... Host Language Types Description Declares a variable or type that corresponds to a type supported by the host language. This declaration must be within a BEGIN-END DECLARE SECTION. Syntax { variable_name [ , … ] | TYPE new_type_name } IS OF TYPE host_language_type ; Notes The following host language C types are supported by esqlc: host_language_type :: { [unsigned] char | [unsigned] short | [unsigned] long | float | double } The host language C type int is not supported in esqlc. Type int maps to 16 or 32 bits depending on the machine architecture. This has the potential of creating rounding errors at runtime in shipping values in the transaction execution calls across different machine architectures. It is not necessary to have a type declaration for a host language type to declare a variable in esqlc. The following variable declaration can also be used with the same effect: variable_name IS OF TYPE unsigned long; For convenience, users can define new types which inherit all the properties of a host language type or a previously-declared type. The new type introduced by the declaration can be used to declare variables or other types in either esqlc or in the host language. esqlc variables of host types can also be declared in C syntax in the following form: host_language_type variable_name ; For example, the following declaration declares cust_no to be a variable of type long (as in C language): long cust_no ; Example EXEC SQL BEGIN DECLARE SECTION ; TYPE customer_no IS OF TYPE unsigned long; EXEC SQL END DECLARE SECTION ; ... All Rights Reserved 171 www.faircom.com ESQL Reference Table-Column Types Description Declares a variable or type that corresponds to a table column in the database. This declaration must be within a BEGIN-END DECLARE SECTION. Syntax { variable_name [ , … ] | TYPE new_type_name } IS LIKE table_name.table_column_name ; Notes Modification of the database schema would automatically change (on recompilation) the program types if the type is inherited using the above form of the type declaration. This makes the user programs more manageable. The host language type into which the type is mapped is as specified for database types. Example EXEC SQL BEGIN DECLARE SECTION ; TYPE customer_name_type IS LIKE customer_relation.customer_name; EXEC SQL END DECLARE SECTION ; Static Array Types Description Declares a static-sized array or array type consisting of elements of any type. This declaration must be within a BEGIN-END DECLARE SECTION. Syntax { variable_name [ , … ] | TYPE new_type_name } IS AN ARRAY OF type_name WITH SIZE constant_id; Notes esqlc does not allow the definition of open size arrays. All esqlc arrays (excluding character arrays) are mapped into a host language structure consisting of both the actual array and the current size of the array. The C language structure is of the following form: struct new_type_name { long tpe_size; element_type_name tpe_array[constant_id]; }; Host language statements can manipulate the array assuming that it is a structure with the same name as the array name and having two components tpe_array and tpe_size. The tpe_array component contains the actual array and the tpe_size component contains the current size of the array. All Rights Reserved 172 www.faircom.com ESQL Reference All esqlc statements that manipulate the array will update the current size associated with the array. The host language statements that manipulate the array are expected to update the current size. Character arrays are treated as a special case by esqlc. They are not mapped to a record but rather as a null terminated string. This simplifies their manipulation from C and their use with system provided functions. When a character array is manipulated by esqlc statements the null termination is always guaranteed. While referring to an array element in a c-treeSQL statement, the array name followed by the element index within square brackets should be specified, even though esqlc generates a structure for an array type. This is illustrated in the following example: EXEC SQL BEGIN DECLARE SECTION ; #define NAMESZ 20 #define ARRAYSZ 10 cust_name_t IS AN ARRAY OF char WITH SIZE NAMESZ ; cust_name IS AN ARRAY OF cust_name_t WITH SIZE ARRAYSZ ; EXEC SQL END DECLARE SECTION ; ... for (i = 0 ; i < ARRAYSZ ; i++) { EXEC SQL FETCH cust_cursor INTO :cust_name[i] ; if (sqlca.sqlcode) break ; printf ("Customer Name : %s\\n", cust_name.tpe_array [i]) ; } ... If array variables are specified in the INTO clause of a FETCH statement, esqlc retrieves multiple rows . For example: EXEC SQL BEGIN DECLARE SECTION ; cust_name_t IS AN ARRAY OF char WITH SIZE 20 ; cust_name IS AN ARRAY OF cust_name_t WITH SIZE 10 ; EXEC SQL END DECLARE SECTION ; ... EXEC SQL FETCH cust_cursor INTO :cust_name ; ... When arrays are used for multiple-row-fetch, the sizes of all array variables and indicator array variables must be the same. If they are different, esqlc will use the minimum of the array sizes. If the FETCH statement is used to fetch multiple rows by using array variables, the array sizes are set appropriately after the fetch. Example EXEC SQL BEGIN DECLARE SECTION ; TYPE customer_array_type IS AN ARRAY OF customer_record WITH SIZE 50; EXEC SQL END DECLARE SECTION ; ... All Rights Reserved 173 www.faircom.com ESQL Reference Record Types Description Declares a RECORD variable or type that consists of one or more fields of the same or of different types. This declaration must be within a BEGIN-END DECLARE SECTION (see "BEGIN-END DECLARE SECTION" (page 153) for details). Syntax { variable_name [ , … ] | TYPE new_type_name } IS A RECORD OF field_name IS OF TYPE type_name; [ ... ] END OF RECORD ; Notes A RECORD is equivalent to a structure in C or a record in Pascal. A record is directly mapped into the appropriate type in the host language with the same user defined name. A component of a RECORD is called a field and can be denoted by using the dot ( . ) operator, as in record_variable_name.field_name. Example EXEC SQL BEGIN DECLARE SECTION ; TYPE customer_type IS A RECORD OF customer_id IS OF TYPE long; customer_name IS AN ARRAY OF CHAR WITH SIZE 20; END OF RECORD; EXEC SQL END DECLARE SECTION ; ... Table Record Types Description Declares a variable or type that is a RECORD consisting of all the columns or a subset of the columns of the specified table. This form of declaration is a shortcut to declaring a RECORD and then using the table field type declarations. This declaration must be within a BEGIN-END DECLARE SECTION (see "BEGIN-END DECLARE SECTION" (page 153) for details). Syntax { variable_name [ , … ] | TYPE new_type_name } IS A RECORD LIKE table_name [ WITH ( table_column_name [ , ... ] ) ] ; Notes If the table column list is not specified, then by default the record will contain all the columns of the specified table. When the database schema for the table is changed, the program (on recompilation) will automatically reflect the new types simplifying the maintenance of the program. All Rights Reserved 174 www.faircom.com ESQL Reference The types created in the host programming language are the same as specified for database types. The esqlc command line must include the +D connect_string option for the program to declare table records. (See "esqlc Command Line Reference" (page 46) for more detail.) Example ... EXEC SQL BEGIN DECLARE SECTION ; TYPE customer_record IS A RECORD LIKE EXEC SQL END DECLARE SECTION ; ... customer_table; 15.17 WHENEVER Description Specifies actions for three c-treeSQL runtime exceptions. Syntax WHENEVER { NOT FOUND | SQLERROR | SQLWARNING } { STOP | CONTINUE | { GOTO | GO TO } host_language_label } ; Arguments { NOT FOUND | SQLERROR | SQLWARNING } The exception NOT FOUND is set when sqlca.sqlcode is set to SQL_NOT_FOUND. The exception SQLERROR is set when sqlca.sqlcode is set to a negative value after a statement execution. The exception SQLWARNING is set when sqlca.sqlwarn [0] is set to ‘W’ after a statement execution. { STOP | CONTINUE | { GOTO | GO TO } host_language_label } STOP results in the esqlc program stopping execution whenever the specified exception is raised. CONTINUE results in the esqlc program ignoring the specified exception and continuing execution. GOTO | GO TO host_language_label results in the esqlc program execution to branch to the statement corresponding to the host_language_label. The default action for each exception is CONTINUE. Notes There can be multiple WHENEVER statements in an esqlc file for the same exception. Each WHENEVER statement overrides the previous WHENEVER statement specified for the same exception. All Rights Reserved 175 www.faircom.com ESQL Reference Correctness of a WHENEVER statement with GOTO | GO TO host_language_label action is subject to the scoping rules of the host language. The host_language_label must be within the scope of all c-treeSQL statements for which the GOTO | GO TO host_language_label action is active. The GOTO | GO TO host_language_label action is active starting from the corresponding WHENEVER statement until another WHENEVER statement for the same exception or until end of (esqlc) source file. Example EXEC SQL WHENEVER SQLERROR GOTO err ; ... EXEC SQL UPDATE customer SET name = 'RALPH' WHERE cust_no = 1001 ; ... err: EXEC SQL WHENEVER SQLERROR CONTINUE ; EXEC SQL ROLLBACK WORK ; return ; Authorization None. SQL Compliance SQL-92. c-treeSQL extensions: SQLWARNING exception condition and STOP action Related Statements FETCH 15.18 Long Data Type Support In the esqlc, the long data select operation is done using the c-treeESQL programmatic interface tpe_sqlgetdata() and the insert operation is done using the interface tpe_sqlputdata(). These C interfaces require the field handle as their argument. Two field handle types have been introduced for this purpose. They are: lvc_fld_hdl_t : Field handle type for LVARCHAR column. lvb_fld_hdl_t : Field handle type for LVARBINARY column. The above field handles type host variable need to be used in the EXEC SQL statement to get the field handle of the long column. The LVARCHAR data type is recommended for CLOB support. The LVARBINARY data type is recommended for BLOB support. All Rights Reserved 176 www.faircom.com ESQL Reference DECLARE Section The field handle type variable can be declared in DECLARE section as follows: EXEC SQL BEGIN DECLARE SECTION; lvc_fld_hdl_t fld_hdl_buffer ; ........ ........ EXEC SQL END DECLARE SECTION; INSERT Operation While performing the insert operation, the field handle is obtained through the USING clause of the EXECUTE statement. EXEC SQL EXECUTE S1 USING: fld_hdl_buffer; This field handle is used in the tpe_sqlputdata () call. tpe_sqlputdata ( tpe_get_curtmhdl(), tpe_get_curdbhdl(), tpe_pcur0, TPE_DT_CHAR, (void *)fld_hdl_buffer, data_buflen, fe_offset, data_buf, &sqlca ); /* /* /* /* /* /* /* /* /* IN transaction handle IN db handle IN cursor htypeid hdl to field IN bufferlen IN offset into field IN buffer OUT sqlca pointer */ */ */ */ */ */ */ */ */ SELECT Operation For the select from long column, the field handle is obtained using FETCH statement. EXEC SQL FETCH long_cursor INTO: fld_hdl_buffer; This field handle is used in the tpe_sqlgetdata () call. tpe_sqlgetdata ( tpe_get_curtmhdl(), tpe_get_curdbhdl(), tpe_pcur0, TPE_DT_CHAR, (void *)fld_hdl_buffer, 101, fe_offset, buffer, &fe_val_len, &sqlca ); Refer to "Long Data Type Support" (page 176) for sample programs that demonstrate the Long data type support in ESQL. All Rights Reserved 177 www.faircom.com 16. Programmatic Interfaces 16.1 Introduction c-treeSQL Interfaces are the programming language interfaces for c-treeSQL database connectivity. c-treeSQL database capabilities are exposed through these interfaces. ESQL is layered over these interfaces. When an ESQL program is precompiled with esqlc, it generates a program in C Language wherein all the c-treeSQL statements are converted into the corresponding programming language interface calls. These c-treeSQL Interfaces are exported from the c-treeSQL libraries. Database applications written using these interfaces need to link with the libraries. Note: As of c-treeACE SQL Server V8.14, the c-treeSQL programmatic interface is thread safe and can be used in multi-threaded applications. Because of this modification, new functions have been added while others have been deprecated. The programmatic interfaces described in this chapter can be used in conjunction and/or as a substitute to the statements provided by the ESQL environment. The programmatic interfaces provide the following functionality. Functionality provided by the programmatic interfaces Programmatic Interface Functionality SQL Functions Provide functionality for connecting to a database and disconnecting from a database and executing static and dynamic SQL statements. Transaction Functions Provide functionality for beginning and ending transactions. Type Conversion Functions Provide functionality for converting values in one database type form to another compatible database type form. The programmatic interfaces provide the developer the option of using the c-treeSQL functionality either through the esqlc compiler and/or through programmatic interfaces. The advantage of the programmatic interfaces is that they can be easily integrated into existing code without a major rewrite of the application. The programmatic interfaces are also more flexible in applications which are being developed in languages other than C and applications being developed using RPC code generators. If the library functions are used in a C program that is not compiled using esqlc, then appropriate C preprocessor symbols are to be defined for indicating the environment. For example the following are the preprocessor options used on the SCO UNIX platform. -DDH_OS_UNIX All Rights Reserved -DDH_OS_UNIX_SCO 178 www.faircom.com Programmatic Interfaces The following pages include the descriptions for the programmatic interfaces and are arranged alphabetically. 16.2 Programmatic Interfaces sqld_alloc Syntax #include “sql_lib.h” struct sqlda *sqld_alloc(size, varnmsz) short size; short varnmsz; Description The sqld_alloc() function allocates an SQLDA from the heap. Parameters size Size of the SQLDA (number of output columns in the result table corresponding to a c-treeSQL statement). varnmsz The maximum number of characters in the name of the column of the result table corresponding to the c-treeSQL statement. If names of columns in the result table are not of interest, a zero value can be passed for varnmsz. Note The allocation for buffers for the results of a FETCH statement and allocation for indicator variables are not done by sqld_alloc(). These allocations are to be done by the application program and the SQLDA should be set to point to these buffers. Returns None. Related Functions sqld_free(), dh_set_sqlda() sqld_free Syntax #include “sql_lib.h” void sqld_free (sqldaptr) struct sqlda *sqldaptr; All Rights Reserved 179 www.faircom.com Programmatic Interfaces Description The sqld_free() function frees the memory occupied by an SQLDA, allocated using the sql_alloc() function. Parameters sqldaptr Points to SQLDA, that was returned by sqld_alloc() call. Notes The buffers that receive the results of a FETCH statement and indicator variable buffers are not freed by sqld_free(). These buffers are to be freed by the application program before freeing the SQLDA using the sqld_free() call. Returns None. Related Functions sql_alloc(), dh_set_sqlda() dh_alloc_sqlenv Syntax #include "sql_lib.h" typedef void *dh_sqlenv_hdl_t;. void dh_alloc_sqlenv(sqlenv_hdl) dh_sqlenv_hdl_t *sqlenv_hdl; Description The function dh_alloc_sqlenv() allocates the c-treeSQL environment required for containing the context for use by the C programmatic interfaces and returns a handle to the allocated c-treeSQL environment. This environment handle cannot be shared across multiple connections, hence each connection should allocate a separate sql_env_t handle. Parameters sqlenv_hdl This is the address of a variable of type dh_sqlenv_hdl_t. After successful completion, this function returns the variable pointed to by this parameter would contain the allocated c-treeSQL environment handle. Returns None All Rights Reserved 180 www.faircom.com Programmatic Interfaces Related Functions dh_free_sqlenv() dh_compare_data Syntax #include “sql_lib.h” tpe_status_t dh_compare_data(dtype, buf1len, buf1, buf2len, buf2, result) int dtype; int buf1len; void *buf1; int buf2len; void *buf2; short *result; Description Compares two data objects of a given type. Parameters dtype The data type of the two objects that are being compared. buf1len The length of the first data object. buf1 The buffer containing the first data object. buf2len The length of the second data object. buf2 The buffer containing the second data object. result Should point to a location for returning the result. result is a short integer with the following values: 1 first data object is greater than second data object. -1 first data object is less than second data object. 0 the two data objects are equal. Returns A negative error code on failure and a zero value on success. Notes The data types supported are defined in the include file sql_lib.h and are listed below: All Rights Reserved 181 www.faircom.com Programmatic Interfaces • TPE_DT_CHAR • TPE_DT_NUMERIC • TPE_DT_SMALLINT • TPE_DT_INTEGER • TPE_DT_SMALLFLOAT • TPE_DT_REAL • TPE_DT_FLOAT • TPE_DT_DATE • TPE_DT_MONEY • TPE_DT_TIME • TPE_DT_TIMESTAMP • TPE_DT_TINYINT • TPE_DT_BINARY • TPE_DT_BIT • TPE_DT_LVC • TPE_DT_LVB • TPE_DT_BIGINT Related Functions dh_conv_data() dh_conv_data Syntax #include “sql_lib.h” tpe_status_t dh_conv_data(dtype, buf1, buf, fmt, odtype, obuf1, obuf) int dtype; int buf1; void *buf; char *fmt; int odtype; int obuf1 void *obuf; Description Converts data from one type representation to the desired type representation. Parameters dtype The data type of the input buffer which is being converted. buf1 The length of the input buffer being converted. buf The buffer containing the input data and whose type is specified in dtype. All Rights Reserved 182 www.faircom.com Programmatic Interfaces fmt A format string to be used for formatting the output if the desired data output data type is a character string type. odtype The data type of the output required after conversion. obuf1 The length of the buffer reserved for the output type. obuf The output data is returned in this buffer. Returns Returns a negative error code on failure and a zero value on success. Notes The data types supported are defined in the include file sql_lib.h and are listed below: • TPE_DT_CHAR • TPE_DT_NUMERIC • TPE_DT_SMALLINT • TPE_DT_INTEGER • TPE_DT_SMALLFLOAT • TPE_DT_REAL • TPE_DT_FLOAT • TPE_DT_DATE • TPE_DT_MONEY • TPE_DT_TIME • TPE_DT_TIMESTAMP • TPE_DT_TINYINT • TPE_DT_BINARY • TPE_DT_BIT • TPE_DT_LVC • TPE_DT_LVB • TPE_DT_BIGINT Currently a format string can be specified only if the input is of type TPE_DT_DATE and the output is of type TPE_DT_CHAR. Related Functions dh_dayofweek() All Rights Reserved 183 www.faircom.com Programmatic Interfaces dh_dayofweek Syntax #include “sql_lib.h” int dh_dayofweek(date) tpe_date_t date; Description Returns the day of the week of the specified date. Arguments date The date for which the day of the week is required. Returns The day of the week is returned as an integer value ranging from 0 to 6 where 0 represents a Sunday and 6 represents a Saturday. Related Functions dh_conv_data() dh_free_sqlenv Syntax #include "sql_lib.h" void dh_free_sqlenv(sqlenv_hdl) dh_sqlenv_hdl_t sqlenv_hdl; Description The dh_free_sqlenv() function frees c-treeSQL environment allocated using the dh_alloc_sqlenv() function. Parameters sqlenv_hdl This is the c-treeSQL environment handle. Returns None Related Functions dh_alloc_sqlenv() All Rights Reserved 184 www.faircom.com Programmatic Interfaces dh_get_curdbhdl Syntax #include “sql_lib.h” tpe_db_hdl_t dh_get_curdbhdl(sqlenv_hdl); dh_sqlenv_hdl_t sqlenv_hdl; Description The dh_get_curdbhdl() function gets the current database handle. Parameters sqlenv_hdl c-treeSQL environment handle. Returns A null handle is returned if no database is attached to. Notes The current database handle. All the c-treeSQL statements in a program by default use the current database handle. Related Functions dh_sqlattach(), dh_set_curdbhdl() dh_get_curtmhdl Syntax #include “sql_lib.h” tpe_tm_hdl_t dh_get_curtmhdl(sqlenv_hdl); dh_sqlenv_hdl_t sqlenv_hdl; Description The dh_get_curtmhdl() function gets the current transaction handle. Parameters sqlenv_hdl c-treeSQL environment handle. Returns Returns the current transaction handle. Notes The very first call into this function, results in allocation of a transaction handle. This handle is set as the current transaction handle and the same handle is returned. All Rights Reserved 185 www.faircom.com Programmatic Interfaces All the c-treeSQL statements and transaction statements in a program by default use the current transaction handle. Related Functions dh_tm_alloc_handle(), dh_set_curtmhdl() dh_num_add Syntax #include “sql_lib.h” tpe_status_t dh_get_num_add(num1,num2, num3) tpe_num_t *num1; tpe_num_t *num2; tpe_num_t *num3; tpe_status_t dh_get_num_sub(num1,num2, num3) tpe_num_t *num1; tpe_num_t *num2; tpe_num_t *num3; tpe_status_t dh_get_num_mul(num1,num2, num3) tpe_num_t *num1; tpe_num_t *num2; tpe_num_t *num3; tpe_status_t dh_get_num_add(num1,num2, num3) tpe_num_t *num1; tpe_num_t *num2; tpe_num_t *num3; Description Implements the addition, subtraction, multiplication and division operations on numeric types. Arguments num1 The first operand to the specified operation. If the operation is division this is the divisor. num2 The second operand to the specified operation. If the operation is division this is the dividend. num3 The result of the operation is returned here with the maximum precision possible. Returns A value 0 is returned on success and a value -1 on failure. Related Functions dh_conv_data() All Rights Reserved 186 www.faircom.com Programmatic Interfaces dh_set_cursor Syntax #include “sql_lib.h” void dh_set_cursor(sqlenv_hdl,tmhdl, dbhdl, cursorptr, stmtuid, isdynamic, statement, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tmhdl; tpe_db_hdl_t dbhdl; tpe_cursor_t *cursorptr; tpe_uuid_t *stmtuid; int isdynamic; char *statement; struct sqlca *ca; Description The dh_set_cursor() function sets information in a cursor structure. This information is used by other c-treeSQL calls. Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl Transaction handle. dbhdl Database handle. cursorptr Pointer to a variable of the type tpe_cursor_t. This variable is expected to be NULL at the time of the very first call to this function for this cursor in a program. stmtuid Pointer to a buffer containing the universal unique identifier for the c-treeSQL statement. isdynamic An integer flag, if nonzero, indicates that the statement is a dynamic c-treeSQL statement. statement A pointer to the statement string. ca A pointer to SQLCA structure for returning the status. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. All Rights Reserved 187 www.faircom.com Programmatic Interfaces Notes The argument tmhdl should have been obtained through a successful call to either dh_get_curtmhdl() or dh_tm_alloc_handle(). The argument dbhdl should have been obtained through a successful call to dh_sqlattach(). Each call to any of the functions dh_sqlexecute(), dh_sqlprepare(), dh_sqldescribe() and dh_sqlclose() should be preceded by a dh_set_cursor_call(). Related Functions dh_sqlattach(), dh_get_curdbhdl(), dh_get_curtmhdl(), dh_sqlexecute(), dh_sqldeclare(), dh_sqlselect(), dh_sqlopen(), dh_sqlfetch(), dh_sqlprepare(), dh_sqldescribe(), dh_sqlclose() dh_set_ptrs Syntax #include “sql_lib.h” void dh_set_ptrs(ptrarray, nptrs, ptr1, ptr2,.......) void *ptrarray[]; int nptrs; void *ptr1; void *ptr2; Description The dh_set_ptrs() function sets pointer values in the given pointer list. This function call is useful if the SQLDA is being allocated on the stack. Parameters ptrarray Pointer to the array in which the pointer values are to be set. nptrs Number of pointers being passed. ptr1, ptr2, ... Pointer values to be set in the ptrarray. Returns None. Related Functions dh_set_sqlda() All Rights Reserved 188 www.faircom.com Programmatic Interfaces dh_set_sqlda Syntax #include “sql_lib.h” void dh_set_sqlda(sqldaptr, sqldsz, arraysz, types, lengths, varptrs, ivarptrs) struct sqlda *sqldaptr; int sqldsz; int arraysz; short types[]; short lengths[]; char *varptrs[]; short *ivarptrs[]; Description The dh_set_sqlda() function sets the fields of the given SQLDA with the values passed. This function call is useful if the SQLDA is being allocated on the stack. Parameters sqldaptr Pointer to the SQLDA structure whose fields are to be set. sqldsz Size of the SQLDA. arraysz Array size (>1 for multiple tuple fetch in a single call). types Points to an array (of size sqldsz) of short integers representing the types of values contained in the SQLDA. lengths Points to an array (of size sqldsz) of short integers representing the lengths of values contained in the SQLDA. varptrs Points to an array (of size sqldsz) of pointers, each pointer pointing to an array (of size arraysz) of variables. The type of the variable is given by the corresponding entry in the types array. ivarptrs Points to an array (of size sqldsz) of pointers, each pointer pointing to an array (of size arraysz) of variables. The variable is of type short integer. Returns None Related Functions dh_set_ptrs() All Rights Reserved 189 www.faircom.com Programmatic Interfaces dh_sqlclose Syntax #include “sql_lib.h” void dh_sqlclose(sqlenv_hdl,tmhdl, dbhdl, cursor, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tmhdl; tpe_db_hdl_t dbhdl; tpe_cursor_t cursor; struct sqlca *ca; Description The dh_set_sqlclose() function closes a cursor. The function call corresponds to the CLOSE statement of ESQL. Parameters sqlenv_hdl c-treeSQL environment handle tmhdl Transaction handle. sqldsz Database handle returned by a prior successful call to dh_get_curdbhdl(). cursor A variable of the type tpe_cursor_t(). This variable is expected to be NULL at the time of the very first call to dh_set_cursor() function in a program for this cursor. ca A pointer to SQLCA structure for returning the status. Notes The argument tmhdl should have been obtained through a successful call to either dh_get_curtmhdl() or dh_tm_alloc_handle(). The argument dbhdl should have been obtained through a successful call to dh_get_curdbhdl(). The cursor should have been successfully opened using the dh_sqlopen() call. All open cursors are closed automatically when a transaction is committed. This call to dh_sqlclose() function should be preceded by a dh_set_cursor(). For example, see the code generated by the esqlc compiler for a CLOSE statement. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. All Rights Reserved 190 www.faircom.com Programmatic Interfaces Related Functions dh_sqlconnect(), dh_get_curdbhdl(), dh_get_curtmhdl(), dh_set_cursor(), dh_sqldeclare(), dh_sql_open(), dh_sqlfetch(), dh_sqlprepare() dh_sqlconnect Syntax #include “sql_lib.h” void dh_sqlconnect(sqlenv_hdl,dbname, connection_name, user_identifier, user_authentication, ca) dh_sqlenv_hdl_t sqlenv_hdl; char *dbname; char *connection_name; char *user_identifier; char *user_authentication; struct sqlca *ca; Description Connects to the database specified, for performing database operations. The database handle associated with the connection name is obtained. Parameters sqlenv_hdl c-treeSQL environment handle. dbname The name of the database to which the process invoking the operation needs to connect to. connection_name The optional connection_name is a unique identifier the application can use to reference the connection in subsequent connection management statements. If the application does not provide a connection_name, the database name itself becomes the connection_name. user_identifier Optional user name for the connection. If supplied, it will be matched with a password for authentication. If omitted, the default value depends on the environment. (On UNIX, the value of the DH_USER environment variable specifies the default user name.) user_authentication Optional password for the connection. If supplied, it will be matched with a user name for authentication. If omitted, the default value depends on the environment. (On UNIX, the value of the DH_PASSWD environment variable specifies the default password.) ca The pointer to sqlca for returning status. All Rights Reserved 191 www.faircom.com Programmatic Interfaces Notes In the event of the database environment being DEFAULT, an attempt is made to connect to the environment defined database, if any; if not successful, an error message is given and the execution terminates. A connection to a database can be made either in the local mode or in the remote mode. At most one connection is allowed in the local mode. The parameter dbname must be a connect string to connect in the remote mode. The connect string specifies the port, the target host for the database, and the database name. To connect to a database salesdb in the remote mode, the connect string could be: 6597@remotehost:salesdb An application process can make a particular connection a current connection by calling the dh_sql_setconnection() call. The operation will fail if the database is not started. An application can disconnect itself from a database by calling the dh_sqldisconnect() call. The sqlcode in the returned SQLCA structure contains the success/failure status. Returns On successful connect, a zero value is returned in ca->sqlcode. On failure, a negative error code is returned in ca->sqlcode. Related Functions dh_sql_setconnection(), dh_sql_disconnect() dh_sqldeclare Syntax #include “sql_lib.h” void dh_sqldeclare(sqlenv_hdl,tmhdl, dbhdl, cursor, i_sqlda, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tmhdl; tpe_db_hdl_t dbhdl; tpe_cursor_t cursor; struct sqlda *i_sqlda; struct sqlca *ca; Description The dh_sqldeclare() function declares a cursor. This function call corresponds to the DECLARE CURSOR statement of ESQL. Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl Transaction handle. All Rights Reserved 192 www.faircom.com Programmatic Interfaces dbhdl Database handle. cursor A variable of the type tpe_cursor_t. This variable initially is expected to be NULL. i_sqlda A pointer to the SQLDA structure containing input parameters for the ESQL statements. A NULL pointer is expected if there are no parameter references in the c-treeSQL statement. A NULL pointer is expected also when the corresponding c-treeSQL statement is a dynamic statement in which case the parameters are passed to the dh_sqlopen() call. ca A pointer to SQLCA structure for returning the status. Notes The argument tmhdl should have been obtained through a successful call to either dh_get_curtmhdl() or dh_tm_alloc_handle(). The argument dbhdl should have been obtained through a successful call to dh_get_curdbhdl(). This call to dh_sqldeclare() function should be preceded by a dh_set_cursor(). For example, see the code generated by the esqlc compiler for a DECLARE CURSOR statement. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. Related Functions dh_sqlconnect(), dh_get_curdbhdl(), dh_get_curtmhdl(), dh_set_cursor(), dh_sqlexecute(), dh_sqlselect(), dh_sqlopen(), dh_sqlfetch(), dh_sqlprepare(), dh_sqldescribe(), dh_sqlclose() dh_sqldescribe Syntax #include “sql_lib.h” void dh_sqldescribe(sqlenv_hdl,tmhdl, dbhdl, cursor, o_sqlda, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tmhdl; tpe_db_hdl_t dbhdl; tpe_cursor_t cursor; struct sqlda *o_sqlda; struct sqlca *ca; Description The dh_sqldescribe() function returns the number, types and lengths of the outputs of dynamic select c-treeSQL statement. This function call corresponds to the DESCRIBE statement of ESQL. All Rights Reserved 193 www.faircom.com Programmatic Interfaces Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl Transaction handle. dbhdl Database handle. cursor A variable of the type tpe_cursor_t. This variable initially is expected to be NULL. o_sqlda The SQLDA structure for returning the number, types and lengths of the outputs of the select statement. ca A pointer to SQLCA structure for returning the status. Notes The argument tmhdl should have been obtained through a successful call to either dh_get_curtmhdl() or dh_tm_alloc_handle(). The argument dbhdl should have been obtained through a successful call to dh_get_curdbhdl(). Describe call can be issued only for a dynamic select statement after the corresponding cursor has been successfully opened. The call to dh_sqldescribe() function should be preceded by a dh_set_cursor(). For example, see the code generated by the esqlc compiler for a DESCRIBE statement. If the size of the SQLDA s not sufficient, then the field sqld_nvars is set to negative of the actual number of outputs found. If the sqld_varnmsize field is nonzero, then the output names are returned in the buffers pointed by pointers in sqld_varnames. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. If the call is successful, the field sqld_nvars of o_sqlda contains the number of outputs. Related Functions dh_sqlconnect(), dh_get_curdbhdl(), dh_get_curtmhdl(), dh_set_cursor(), dh_sqlexecute(), dh_sqlselect(), dh_sqlopen(), dh_sqlfetch(), dh_sqlprepare(), dh_sqldeclare(), dh_sqlclose() All Rights Reserved 194 www.faircom.com Programmatic Interfaces dh_sqldescribe_param Syntax #include “sql_lib.h” void dh_sqldescribe_param(sqlenv_hdl,tmhdl, dbhdl, cursor, i_sqlda, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tmhdl; tpe_db_hdl_t dbhdl; tpe_cursor_t cursor; struct sqlda *i_sqlda; struct sqlca *ca; Description Returns the number, types and lengths of the input variables in expressions of a dynamic SQL statement. This function call corresponds to the DESCRIBE BIND VARIABLES statement of ESQL. Before calling the dh_sqldescribeparam() function, programs must first call the dh_set_cursor() function. Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl Transaction handle. Get this value through a successful call to either dh_get_curtmhdl() or dh_tm_alloc_handle(). dbhdl Database handle. Get this value through a successful call to dh_get_curdbhdl(). cursor A variable of the type tpe_cursor_t. This variable is expected to be NULL at the time of very first call to dh_set_cursor() function in a program for the cursor. i_sqlda The SQLDA structure for returning the number, types and lengths of the input variable. If the size of the SQLDA is not sufficient, then the field sqld_nvars is set to negative of the actual number of input variables found. If the sqld_varnmsize field is nonzero, then the input variable names are returned in the buffers pointed by pointers in sqld_varnames. ca A pointer to SQLCA structure for returning the status. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. If the call is successful, the field sqld_nvars of i_sqlda contains the number of outputs. All Rights Reserved 195 www.faircom.com Programmatic Interfaces Related Functions dh_sqlconnect(), dh_get_curdbhdl(), dh_get_curtmhdl(), dh_set_cursor(), dh_sqlexecute(), dh_sqlselect(), dh_sqlopen(), dh_sqlfetch(), dh_sqlprepare(), dh_sqlclose() dh_sqldisconnect Syntax #include “sql_lib.h” void dh_sql_disconnect(sqlenv_hdl,format_sp, connection_name, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_formattype_t format_sp; char *connection_name; struct sqlca *ca; Description Terminates the connection between an application and a database environment. Parameters sqlenv_hdl c-treeSQL environment handle. format_sp The format specification is a #defined entity that could have any of the following four values: SQL_DISCONNECT_CONNECTION SQL_DISCONNECT_CURRENT SQL_DISCONNECT_ALL SQL_DISCONNECT_DEFAULT connection_name connection_name is a unique identifier, used by the application to reference the connection to a database. ca The pointer to SQLCA for returning status. Returns On successful disconnect, a zero value is returned in ca->sqlcode. On failure, a negative error code is returned in ca->sqlcode. Related Functions dh_sqlconnect(), dh_sql_setconnection() All Rights Reserved 196 www.faircom.com Programmatic Interfaces dh_sqlexecute Syntax #include “sql_lib.h” void dh_sqlexecute(sqlenv_hdl,tmhdl, dbhdl, cursor, i_sqlda, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tmhdl; tpe_db_hdl_t dbhdl; tpe_cursor_t cursor; struct sqlda *i_sqlda; struct sqlca *ca; Description The dh_sqlexecute() function executes a non-select c-treeSQL statement. Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl Transaction handle. dbhdl Database handle. cursor A variable of the type tpe_cursor_t. This variable initially is expected to be NULL at the time of the very first call to dh_set_cursor() function in a program for this cursor. i_sqlda A pointer to SQLDA structure containing input parameters for the c-treeSQL statement. A NULL pointer is expected if there are no parameter references in the c-treeSQL statement. ca A pointer to SQLCA structure for returning the status. Notes The argument tmhdl should have been obtained through a successful call to either dh_get_curtmhdl() or dh_tm_alloc_handle(). The argument dbhdl should have been obtained through a successful call to dh_sqlconnect(). This call to dh_sqlexecute() function should be preceded by a dh_set_cursor(). For example, see the code generated by the esqlc compiler for a non-SELECT statement. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. All Rights Reserved 197 www.faircom.com Programmatic Interfaces Related Functions dh_sqlconnect(), dh_get_curdbhdl(), dh_get_curtmhdl(), dh_set_cursor(), dh_sqldeclare(), dh_sqlselect(), dh_sqlopen(), dh_sqlfetch(), dh_sqlprepare(), dh_sql_describe(), dh_sqlclose() dh_sqlfetch Syntax #include “sql_lib.h” void dh_sqlfetch(sqlenv_hdl,tmhdl, dbhdl, cursor, o_sqlda, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tmhdl; tpe_db_hdl_t dbhdl; tpe_cursor_t cursor; struct sqlda *o_sqlda; struct sqlca *ca; Description The dh_sqlfetch() function fetches one or more tuples corresponding to an open cursor. This function call corresponds to the FETCH statement of ESQL. Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl Transaction handle. dbhdl Database handle. cursor A variable of the type tpe_cursor_t. This variable initially is expected to be NULL at the time of the very first call to dh_set_cursor() function in a program for this cursor. o_sqlda A pointer to SQLDA structure containing information about the variables in which the output parameters of the c-treeSQL statements are returned. ca A pointer to SQLCA structure for returning the status. Notes The argument tmhdl should have been obtained through a successful call to either dh_get_curtmhdl() or dh_tm_alloc_handle(). The argument dbhdl should have been obtained through a successful call to dh_get_curdbhdl(). All Rights Reserved 198 www.faircom.com Programmatic Interfaces This call to dh_sqlfetch() function should be preceded by a dh_set_cursor(). For example, see the code generated by the esqlc compiler for a FETCH statement. The sqld_arraysz field should be set to 1 for single tuple fetches and to the appropriate array size (>1) for doing multiple tuple fetches in a single call. If the specified array size is greater than one, all the variables and the non-null indicator variables are assumed to be arrays of size greater than or equal to the specified array size. For a multiple tuple fetch call, tuples may have been returned even if the status code returned is SQL_NOT_FOUND. The number of tuples returned for this call is returned in sqlca.sqlerrd[3]. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. A positive status code SQL_NOT_FOUND is returned in the sqlcode field if there are no more tuples to be fetched. Related Functions dh_sqlconnect(), dh_get_curdbhdl(), dh_get_curtmhdl(), dh_set_cursor(), dh_sqlexecute(), dh_sqldeclare(), dh_sqlselect(), dh_sqlopen(), dh_sqlprepare(), dh_sql_describe(), dh_sqlclose() dh_sqlgetdata Syntax #include “sql_lib.h” void dh_sqlgetdata(sqlenv_hdl,tmhdl, dbhdl, cursor, typeid, colhdl, buflen, offset, buf, colbal, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tmhdl; tpe_db_hdl_t dbhdl; tpe_cursor_t cursor; long typeid; void *colhdl; long buflen; long offset; void *buf; long *colbal; struct sqlca *ca; Description Reads a portion of a LONGVARCHAR or LONGVARBINARY column and writes it to a buffer, and returns the length of data remaining to be retrieved. Programs must call the dh_sqlfetch() function before calling dh_sqlgetdata() to get the data for the column. Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl All Rights Reserved 199 www.faircom.com Programmatic Interfaces Transaction handle. Get this value through a successful call to dh_get_curtmhdl() or dh_tm_alloc_handle(). dbhdl Database handle. Get this value through a successful call to dh_get_curdbhdl(). cursor A variable of the type tpe_cursor_t. This variable initially is expected to be NULL at the time of the very first call to dh_set_cursor() function in a program for this cursor. typeid The column type. The program must set this variable to either TPE_DT_LVC or TPE_DT_LVB. colhdl The handle for the LONG_VARCHAR or LONG_VARBINARY column. The program must set this variable to the value in sqlda.sqld_varptrs, which itself is set by a call to the dh_sqlfetch() function. buflen The length of the portion of the column that dh_sqlgetdata() writes to the buffer. offset The offset, in bytes from the beginning of the VARCHAR or LONG VARBINARY column, to the portion that dh_sqlgetdata() writes to the buffer. buf A pointer to the buffer containing the portion of the column that dh_sqlgetdata() writes. colbal The length, in bytes, of remaining data in the column from the end of the offset to the end of the column. ca A pointer to SQLCA structure for returning the status. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. Related Functions dh_sqldeclare(), dh_sqlopen(), dh_sqlprepare(), dh_sql_describe(), dh_sqlclose(), dh_sqlfetch() dh_sqlopen Syntax #include “sql_lib.h” void dh_sqlopen(sqlenv_hdl,tmhdl, dbhdl, cursor, i_sqlda, ca) All Rights Reserved 200 www.faircom.com Programmatic Interfaces dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tmhdl; tpe_db_hdl_t dbhdl; tpe_cursor_t cursor; struct sqlda *i_sqlda; struct sqlca *ca; Description The dh_sqlopen() function opens a cursor. This function call corresponds to the OPEN statement of ESQL. Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl Transaction handle. dbhdl Database handle. cursor A variable of the type tpe_cursor_t. This variable initially is expected to be NULL at the time of the first call to dh_set_cursor() function in a program for this cursor. i_sqlda A pointer to SQLDA structure containing input parameters for the c-treeSQL statements. A NULL pointer is expected if there are no parameter references in the c-treeSQL statement or if the statement is static. For a static c-treeSQL statement, the input parameters are specified in the call to dh_sql_declare() function. ca A pointer to SQLCA structure for returning the status. Notes The argument tmhdl should have been obtained through a successful call to either dh_get_curtmhdl() or dh_tm_alloc_handle(). The argument dbhdl should have been obtained through a successful call to dh_get_curdbhdl(). This call to dh_sqlopen() function should be preceded by a dh_set_cursor(). For example, see the code generated by the esqlc compiler for an OPEN statement. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. All Rights Reserved 201 www.faircom.com Programmatic Interfaces Related Functions dh_sqlconnect(), dh_get_curdbhdl(), dh_get_curtmhdl(), dh_set_cursor(), dh_sqldeclare(), dh_sqlselect(), dh_sqlexecute(), dh_sqlfetch(), dh_sqlprepare(), dh_sql_describe(), dh_sqlclose() dh_sqlprepare Syntax #include “sql_lib.h” void dh_sqlprepare(sqlenv_hdl,tmhdl, dbhdl, cursor, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tmhdl; tpe_db_hdl_t dbhdl; tpe_cursor_t cursor; struct sqlca *ca; Description The dh_sqlprepare() function prepares a dynamic select/non-select c-treeSQL statement. This function call corresponds to the PREPARE statement of ESQL. Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl Transaction handle. dbhdl Database handle. cursor A variable of the type tpe_cursor_t. This variable initially is expected to be NULL at the time of the first call to dh_set_cursor() function in a program for this cursor. ca A pointer to SQLCA structure for returning the status. Notes The argument tmhdl should have been obtained through a successful call to either dh_get_curtmhdl() or dh_tm_alloc_handle(). The argument dbhdl should have been obtained through a successful call to dh_get_curdbhdl(). A dynamic non-select statement has to be prepared before it can be executed. A dynamic select statement has to be prepared before the corresponding cursor can be opened. This call to dh_sqlprepare() function should be preceded by a dh_set_cursor(). For example, see the code generated by the esqlc compiler for a PREPARE statement. All Rights Reserved 202 www.faircom.com Programmatic Interfaces Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. Related Functions dh_sqlconnect(), dh_get_curdbhdl(), dh_get_curtmhdl(), dh_set_cursor(), dh_sqldeclare(), dh_sqlselect(), dh_sqlexecute(), dh_sqlfetch(), dh_sqlprepare(), dh_sql_describe(), dh_sqlclose() dh_sqlselect Syntax #include “sql_lib.h” void dh_sqlselect(sqlenv_hdl,tmhdl, dbhdl, cursor, i_sqlda, o_sqlda, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tmhdl; tpe_db_hdl_t dbhdl; tpe_cursor_t cursor; struct sqlda *i_sqlda; struct sqlda *o_sqlda; struct sqlca *ca; Description The dh_sqlselect() function performs a single-tuple select. This function call corresponds to the SELECT .... INTO ... statement of ESQL. Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl Transaction handle. dbhdl Database handle. cursor A variable of the type tpe_cursor_t. This variable is expected to be NULL at the time of the first call to dh_set_cursor() function in a program for this cursor. i_sqlda A pointer to SQLDA structure containing input parameters for the c-treeSQL statements. A NULL pointer is expected if there are no parameter references in the c-treeSQL statement. o_sqlda A pointer to SQLCA structure containing information about output parameters for the c-treeSQL statement. All Rights Reserved 203 www.faircom.com Programmatic Interfaces ca A pointer to SQLCA structure for returning the status. Notes The argument tmhdl should have been obtained through a successful call to either dh_get_curtmhdl() or dh_tm_alloc_handle(). The argument dbhdl should have been obtained through a successful call to dh_sqlconnect(). This call to dh_sqlselect() function should be preceded by a dh_set_cursor(). For example, see the code generated by the esqlc compiler for a SELECT .... INTO ... statement. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. Related Functions dh_sqlconnect(), dh_get_curdbhdl(), dh_get_curtmhdl(), dh_sqlopen(), dh_set_cursor(), dh_sqldeclare(), dh_sqlselect(), dh_sqlexecute(), dh_sqlfetch(), dh_sqlprepare(), dh_sql_describe(), dh_sqlclose() dh_tm_alloc_handle Syntax #include “sql_lib.h” tpe_tm_hdl_t dh_tm_alloc_handle(); Description Allocates and initializes a transaction handle that can be used to start a transaction. The transaction handle maintains the current state of the transaction and the transaction can be passed across clients and servers to execute database operations as a single atomic transaction. Notes The transaction handle is initialized to contain the identification of the user on whose behalf the transaction handle has been created. The identification is used when executing database operations on behalf of the user on the database. A transaction/sub-transaction can be started by invoking the dh_tm_begin_trans() with the allocated transaction handle. A transaction/sub-transaction can be committed by invoking the dh_tm_end_trans() with the transaction handle. Returns Returns an initialized transaction handle. Related Functions dh_get_curtmhdl(), dh_tm_begin_trans(), dh_tm_end_trans(), dh_tm_mark_abort() All Rights Reserved 204 www.faircom.com Programmatic Interfaces dh_tm_begin_trans Syntax #include “sql_lib.h” void dh_tm_begin_trans(sqlenv_hdl,trans_level, tmhdl, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_trans_level_t trans_level; tpe_tm_hdl_t tmhdl; struct sqlca *ca; Description Starts a transaction/sub-transaction in the ESQL program. The transaction handle is modified by the function to reflect the current state of the transaction. Parameters sqlenv_hdl c-treeSQL environment handle. trans_level Specifies the transaction level. The only valid value for this parameter currently is TR_LVL_STRICT. tmhdl The transaction handle. ca Points to SQLCA structure for returning the status. Notes The argument tmhdl should have been obtained through a successful call to either dh_get_curtmhdl() or dh_tm_alloc_handle(). For every dh_tm_begin_trans() a corresponding dh_tm_end_trans() should be executed to preserve the consistency of the transaction handle. The calls to dh_tm_begin_trans() can be nested to start sub-transactions within the same and/or different processes but the transaction will be committed only when the outer most dh_tm_end_trans() is executed. A c-treeSQL statement can be executed successfully only if there is a current transaction, started by the dh_tm_begin_trans() function, associated with the current transaction handle. Returns A negative error code on failure or a value zero on success is returned in ca->sqlcode. Related Functions dh_tm_alloc_handle(), dh_tm_end_trans(), dh_tm_mark_abort() All Rights Reserved 205 www.faircom.com Programmatic Interfaces dh_tm_end_trans Syntax #include “sql_lib.h” void dh_tm_end_trans(sqlenv_hdl,tmhdl, ca) dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tmhdl; struct sqlca *ca; Description The dh_tm_end_trans() has a different behavior depending on the state of the transaction which is maintained in the transaction handle. The following list describes the behavior when the function is executed: If this corresponds to the end of a transaction which has not been marked for abort then it is equivalent to committing the transaction. If this corresponds to the end of a transaction which has been marked for abort then it is equivalent to rolling back the transaction. Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl A transaction handle associated with the transaction. ca Points to SQLCA structure for returning the status. Notes For each call to the dh_tm_begin_trans() there should be a corresponding call to the dh_tm_end_trans() function in the same process to preserve the consistency of the transaction handle. The dh_tm_end_trans() function call modifies the transaction handle to set the correct state of the transaction. Returns A negative error code on failure or a value zero on success is returned in ca->sqlcode. Related Functions dh_tm_begin_trans, dh_tm_mark_abort dh_tm_mark_abort Syntax #include “sql_lib.h” void dh_tm_mark_abort(sqlenv_hdl,tmhdl, ca) dh_sqlenv_hdl_t sqlenv_hdl; All Rights Reserved 206 www.faircom.com Programmatic Interfaces tpe_tm_hdl_t *tmhdl; struct sqlca *ca; Description Marks a transaction for abortion but does not perform the rollback of the database modifications at this point. The database is rolled back when the appropriate dh_tm_end_trans() is executed. Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl The transaction handle. Notes The transaction handle is updated to reflect that the transaction has been marked for abortion. Modification on a database are rolled back when the outer most transaction/sub-transaction on that database executes the dh_tm_end_trans() function. No c-treeSQL statements can be executed successfully on behalf of a transaction that has been marked for abort. Returns A negative error code on failure or a value zero on success is returned in ca->sqlcode. Related Functions dh_tm_begin_trans(), dh_tm_end_trans() dh_sqlputdata Syntax #include "sql_lib.h" void dh_sqlputdata (sqlenv_hdl,tmhdl, dbhdl, cursor, typeid, colhdl, buflen, buflen, offset, buf, ca); dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_hdl_t tpe_db_hdl_t tpe_cursor_t dh_i32_t void dh_i32_t dh_i32_t void struct sqlca All Rights Reserved tmhdl; dbhdl; cursor; typeid; *colhdl; buflen; offset; *buf; * ca; 207 www.faircom.com Programmatic Interfaces Description Put a piece of data into a field of LONG type. Assumed that an insertion/update was done previous to this call. Parameters sqlenv_hdl c-treeSQL environment handle. tmhdl Transaction handle. Get this value through a successful call to dh_get_curtmhdl() or dh_tm_alloc_handle(). dbhdl Database handle. Get this value through a successful call to dh_get_curdbhdl(). cursor A variable of the type tpe_cursor_t. This variable initially is expected to be NULL at the time of the very first call to dh_set_cursor() function in a program for this cursor. typeid The column type. The program must set this variable to either TPE_DT_LVC or TPE_DT_LVB. colhdl The handle for the LONG_VARCHAR or LONG_VARBINARY column. The program must set this variable to the value in sqlda.sqld_varptrs, which itself is set by a call to the dh_sqlfetch() function. buflen The length of the portion of the column that dh_sqlputdata() writes to the buffer. offset The offset, in bytes from the beginning of the VARCHAR or LONG VARBINARY column, to the portion that dh_sqlputdata() writes to the buffer. buf A pointer to the buffer containing the portion of the column that dh_sqlputdata() writes. ca A pointer to SQLCA structure for returning the status. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. Related Functions dh_cancel(), dh_sqlexecute() All Rights Reserved 208 www.faircom.com Programmatic Interfaces dh_sqlallocdesc Syntax void dh_sqlallocdesc(sqlenv_hdl,desc_name, num_item , sqlca ) dh_sqlenv_hdl_t sqlenv_hdl; dh_char_t *desc_name; dh_i32_t num_item; struct sqlca *sqlca; Description The dh_sqlallocdesc() function allocates memory for a new c-treeSQL Descriptor Area. Before allocation this function checks whether the list exists. If yes check whether the desc_name is already allocated. If yes return error. If no allocate using sqld_alloc() (use sqlda_t). If no list, create the list and allocate. Before allocating check whether the size exceeds the maximum. This function corresponds to the ALLOCATE DESCRIPTOR function of ESQL. Parameters sqlenv_hdl c-treeSQL environment handle. desc_name Descriptor name. num_item Number of item. sqlca A pointer to SQLCA structure for returning the status. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. dh_sqlgetsqldaptr Syntax struct sqlda *sqlda_ptr = dh_sqlgetsqldaptr(sqlenv_hdl,desc_name,&sqlca) dh_sqlenv_hdl_t sqlenv_hdl; dh_char_t *desc_name; struct sqlca *sqlca; Description The dh_sqlgetsqldaptr() function returns the c-treeSQL Descriptor Area Pointer, given the descriptor name that was allocated before. All Rights Reserved 209 www.faircom.com Programmatic Interfaces Parameters sqlenv_hdl c-treeSQL environment handle. desc_name Descriptor name. sqlca A pointer to SQLCA structure for returning the status. sqlda_ptr Pointer to SQLDA . Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. dh_sqldeallocdesc Syntax void dh_sqldeallocdesc(sqlenv_hdl,desc_name , sqlca) dh_sqlenv_hdl_t sqlenv_hdl; dh_char_t *desc_name; struct sqlca *sqlca; Description The dh_sqldeallocdesc() function deallocates the already allocated c-treeSQL Descriptor Area. Before deallocation this function checks whether the list exists. If not returns error. If yes checks whether the desc_name is allocated. If yes deallocates using sqld_free() and sqld_dealloc_buffer(). This function corresponds to the DEALLOCATE DESCRIPTOR function of ESQL. Parameters sqlenv_hdl c-treeSQL environment handle. desc_name Descriptor name. sqlca A pointer to SQLCA structure for returning the status. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. All Rights Reserved 210 www.faircom.com Programmatic Interfaces dh_sqlgetdesc Syntax void dh_sqlgetdesc (sqlenv_hdl,sqlda_ptr, item_num, tgt_lst, lst_length,sqlca) dh_sqlenv_hdl_t sqlenv_hdl; struct sqlda *sqlda_ptr; dh_i32_t item_num; item_lst *tgt_lst; dh_i32_t lst_length; struct sqlca *sqlca; Description The dh_sqlgetdesc() function gets the information about the particular item in a particular c-treeSQL Descriptor Area. This function corresponds to the GET DESCRIPTOR function of ESQL. Parameter sqlenv_hdl c-treeSQL environment handle. sqlda_ptr A pointer to SQLDA structure. item_num Integer that identifies a specific item in the Descriptor Area. tgt_lst Pointer to structure containing the field and host variable information. Following is the structure. item_lst typedef struct { descr_kwd_t dh_char_t dh_boolean }item_lst; field_info[DESC_MAX_VAR]; ** host_info; is_const[DESC_MAX_VAR]; field_info An array of enumerated field type descr_kwd_t. Following is the structure for Enumerated data type descr_kwd_t: typedef enum { COUNT_T, TYPE_T, LEN_T, OCT_LEN_T, RET_LEN_T, PREC_T, SCALE_T, DATE_INT_CODE_T, DATE_INT_PREC_T, NULL_T, NAME_T, UNNAMED_T, All Rights Reserved 211 www.faircom.com Programmatic Interfaces COLLAT_NAME_T, CHAR_SET_NAME_T, DAT_T, IND_T, COL_NAME_T, TBL_NAME_T, CS_T, SEARCH_T, UNSIGN_T, UPD_T, PARAM_T, TBL_T, AUTO_T, VERBOSE_T }descr_kwd_t; For more details on the elements of descr_kwd_t data type, refer to the table Descriptor Item Name. host_info An array of host variables. is_const Array of boolean to store the constant information for the related field of field_info. lst_length Number of fields. sqlca A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. dh_sqlsetdesc Syntax void dh_sqlsetdesc(sqlenv_hdl,sqlda_ptr, item_num, &it_lst, num_of_tgt, &sqlca) dh_sqlenv_hdl_t sqlenv_hdl; struct sqlda *sqlda_ptr; dh_i32_t item_num; item_lst it_lst; dh_i32_t num_of_tgt; struct sqlca sqlca; Description The dh_sqlsetdesc() function sets the information about a particular item in a particular SQL Descriptor Area. This function corresponds to the SET DESCRIPTOR function of ESQL. All Rights Reserved 212 www.faircom.com Programmatic Interfaces Parameter sqlenv_hdl c-treeSQL environment handle. sqlda_ptr A pointer to SQLDA structure. item_num Integer that identifies a specific item in the Descriptor Area. tgt_lst Pointer to structure containing the field and host variable information. Refer to the parameter “item_1st” in "dh_sqlgetdesc" (page 211). lst_length Number of fields. sqlca A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. dh_sqlgetdiag Syntax void dh_sqlgetdiag (sqlenv_hdl,arg_sqlca, fld_arr, arr_length, status_recnum, diagstate, o_sqlda); dh_sqlenv_hdl_t sqlenv_hdl; struct sqlca *arg_sqlca; diag_kwd_t *fld_arr; dh_i16_t arr_length; dh_i32_t status_recnum; dh_char_t *diagstate; struct sqlda *o_sqlda; Description The dh_sqlgetdiag() function returns the current value of a field of a record of the diagnostic data structure that contains error, warning, and status information. The contents of the diagnostics structure data members are copied to the osqlda, after making some validation on the data types and diagnostics field names. Parameter sqlenv_hdl All Rights Reserved 213 www.faircom.com Programmatic Interfaces c-treeSQL environment handle. arg_sqlca Diagnostics struct pointer. fld_arr Array of diagnostics fields. arr_length Length of the diag_kwd_t. status_recnum Detail area number. diagstate Sqlstate for this statement. o_sqlda Output SQLDA. Returns A negative error code on failure and a zero value on success is returned in the sqlcode field of the o_sqlda structure. dh_tm_set_level Syntax dh_tm_set_level(sqlenv_hdl,isln_lvl, sqlca); dh_sqlenv_hdl_t sqlenv_hdl; tpe_tm_isolation_lvl_t sln_lvl; struct sqlca sqlca; Description The dh_tm_set_level() function sets the degree to which one transaction can interfere with other transactions while accessing the same rows concurrently. This function corresponds to the SET TRANSLATION ISOLATION LEVEL function of ESQL. Parameter sqlenv_hdl c-treeSQL environment handle. isln_lvl Isolation level. sqlca A negative error code on failure and a zero value on success is returned in the sqlcode field of the SQLCA structure. All Rights Reserved 214 www.faircom.com Programmatic Interfaces dh_sqltables Description The dh_sqltables() returns the list of table, catalog, or schema names, and table types, stored in a specific data source. The corresponding c-treeSQL ODBC API is SQLTables(). dh_sqlcolumns Description The dh_sqlcolumns() returns the list of column names in specified tables. The corresponding c-treeSQL ODBC API is SQLColumns(). dh_sqlstatistics Description The dh_sqlstatistics() retrieves a list of statistics about a single table and the indices associated with the table. The corresponding c-treeSQL ODBC API is SQLStatistics(). dh_sqlprimarykeys Description The dh_sqlprimarykeys() returns the column names that make up the primary key for a table. The corresponding c-treeSQL ODBC API is SQLPrimaryKeys(). dh_sqlforeignkeys Description The dh_sqlforeignkeys() returns a list of foreign keys in the specified table. The corresponding c-treeSQL ODBC API is SQLForeignKeys(). All Rights Reserved 215 www.faircom.com 17. Sample ESQL Programs 17.1 Static Non-Select Statements Compiling and Running E:\v621\esql_samples> esqlc -o dynamic_select dynamic_select.pc FairCom/esqlc 1 file(s) copied. Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 11.00.7022 for 80x86 Copyright (C) Microsoft Corp 1984-1997. All rights reserved. static_non_select.c Creating library static_non_select.lib and object static_non_select.exp E:\v621\esql_samples> static_non_select Static non-select statement executed successfully E:\v621\esql_samples> Program Source Code The following is the complete code listing of an ESQL program for demonstrating the use of static non-SELECT statements. /* * * * * * * */ /* * */ Copyright (C) Dharma Systems Inc. Copyright (C) Dharma Computers (P) Ltd. 1988-97. 1988-97. This Module contains Proprietary Information of Dharma Systems Inc. and Dharma Computers (P) Ltd. and should be treated as Confidential. Example program showing usage of static non-select statements. #include #include #include #include static main () { All Rights Reserved "stdio.h" "sql_lib.h" "string.h" "stdlib.h" void static_update () ; 216 www.faircom.com Sample ESQL Programs /* Connect to the default database */ EXEC SQL CONNECT TO DEFAULT USER 'hum'; /* Call function to execute a static non-select statement */ static_update () ; /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; exit (0) ; err: if (sqlca.sqlcode) { printf ("SQL Error (%ld) %s\\n", sqlca.sqlcode, sqlca.sqlerrm) ; exit (1) ; } } /* * * * */ static_update : demonstrates the usage of a static non-select statement. Updates quantity in orders table. static void static_update () { char errmesg[80]; EXEC SQL BEGIN DECLARE SECTION ; short order_no_v ; EXEC SQL END DECLARE SECTION ; /* Handle error conditions when SQLERROR or when SQL_NOT_FOUND */ EXEC SQL WHENEVER SQLERROR GOTO err ; EXEC SQL WHENEVER NOT FOUND GOTO err ; /* Set order number */ order_no_v = 341 ; /* Update Orders table */ EXEC SQL UPDATE orders SET cust_no = 100011 WHERE order_no = :order_no_v ; EXEC SQL COMMIT WORK ; printf ("\nStatic non-select statement executed successfully\n") ; return ; err: if (sqlca.sqlcode == SQL_NOT_FOUND) { fprintf (stderr, "Order entry not found in table\\n\\n"); } else All Rights Reserved 217 www.faircom.com Sample ESQL Programs if (sqlca.sqlcode < 0) { strncpy (errmesg, sqlca.sqlerrm, sqlca.sqlerrml); errmesg [sqlca.sqlerrml] = '\\0' ; fprintf (stderr, "SQL Error : %s\\n", errmesg); } EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK WORK ; exit (1); } 17.2 Static SELECT Statements Compiling and Running E:\v621\esql_samples> esqlc -o dynamic_select dynamic_select.pc FairCom/esqlc 1 file(s) copied. Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 11.00.7022 for 80x86 Copyright (C) Microsoft Corp 1984-1997. All rights reserved. static_select.c Creating library static_select.lib and object static_select.exp E:\v621\esql_samples> static_select orders orders Static select statement executed successfully E:\v621\esql_samples> Program Source Code The following is the complete code listing of an ESQL program for demonstrating the use of static SELECT statements. /* * * * * * * */ /* * * */ Copyright (C) Dharma Systems Inc. Copyright (C) Dharma Computers (P) Ltd. 1988-97. 1988-97. This Module contains Proprietary Information of Dharma Systems Inc. and Dharma Computers (P) Ltd. and should be treated as Confidential. Example program showing usage of static select statements. All Rights Reserved 218 www.faircom.com Sample ESQL Programs #include #include #include #include "stdio.h" "sql_lib.h" "string.h" "stdlib.h" static void static_select () ; main () { /* Connect to the default database */ EXEC SQL CONNECT TO DEFAULT USER 'hum'; /* Handle error conditions */ EXEC SQL WHENEVER SQLERROR GOTO err ; /* Call function to execute a static select statement */ static_select () ; /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; exit (0) ; err: if (sqlca.sqlcode) { printf ("SQL Error (%ld) %s\\n", sqlca.sqlcode, sqlca.sqlerrm) ; exit (1) ; } } /* * * * */ static_select : demonstrates the usage of a static select statement. Gets the list of tables whose names do not have a prefix 'sys'. static void static_select () { char errmesg[80]; EXEC SQL BEGIN DECLARE SECTION ; char tname [20] ; EXEC SQL END DECLARE SECTION ; /* Handle error conditions when SQLERROR */ EXEC SQL WHENEVER SQLERROR GOTO err ; EXEC SQL /* * */ DECLARE stcur CURSOR FOR SELECT tbl FROM admin.systables WHERE TBL NOT LIKE :tname ; Note: the input parameter value should be set before the cursor is opened. All Rights Reserved 219 www.faircom.com Sample ESQL Programs strcpy (tname, "sys%") ; /* * * */ Note: For static statements, if the declare cursor statement contains references to auto variables, OPEN statement should be in the same C function. EXEC SQL OPEN stcur ; EXEC SQL WHENEVER NOT FOUND GOTO over ; for (;;) { tname [0] = '\0' ; EXEC SQL FETCH stcur INTO :tname ; printf ("%s \n", tname) ; } over: EXEC SQL CLOSE stcur ; EXEC SQL COMMIT WORK ; printf ("Static select statement executed successfully\n") ; return ; err: if (sqlca.sqlcode < 0) { strncpy (errmesg, sqlca.sqlerrm, sqlca.sqlerrml); errmesg [sqlca.sqlerrml] = '\\0' ; fprintf (stderr, "SQL Error : %s\\n", errmesg); } EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK WORK ; exit (1); } /* end */ 17.3 Dynamic Non-SELECT Statements Compiling and Running E:\v621\esql_samples> esqlc -o dynamic_select dynamic_select.pc FairCom/esqlc 1 file(s) copied. Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 11.00.7022 for 80x86 Copyright (C) Microsoft Corp 1984-1997. All rights reserved. All Rights Reserved 220 www.faircom.com Sample ESQL Programs dynamic_non_select.c Creating library dynamic_non_select.lib and object dynamic_non_select.exp E:\v621\esql_samples> dynamic_non_select Current cust_no for order number = 342 is 342 Order number 342 updated Current cust_no for order number = 343 is 343 Order number 343 updated Dynamic non-select statement executed successfully Program Source Code The following is the complete code listing of an ESQL program for demonstrating the use of dynamic non-SELECT statements. /* * * * * * * */ /* * * */ Copyright (C) Dharma Systems Inc. Copyright (C) Dharma Computers (P) Ltd. 1988-97. 1988-97. This Module contains Proprietary Information of Dharma Systems Inc. and Dharma Computers (P) Ltd. and should be treated as Confidential. Example program showing usage of dynamic non-select statements. #include #include #include #include static main () { "stdio.h" "sql_lib.h" "string.h" "stdlib.h" void dynamic_update () ; /* Connect to the default database */ EXEC SQL CONNECT TO DEFAULT USER 'hum'; /* Call function to execute a dynamic non-select statement */ dynamic_update () ; /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; exit (0) ; err: if (sqlca.sqlcode) { printf ("SQL Error (%ld) %s\\n", sqlca.sqlcode, sqlca.sqlerrm) ; exit (1) ; } } /* All Rights Reserved 221 www.faircom.com Sample ESQL Programs * dynamic_update : demonstrates the use of a dynamic non-select statement. * updates the orders table. */ static void dynamic_update () { char errmesg[80]; EXEC SQL BEGIN DECLARE SECTION ; char stmt[1024] ; long cust_no; long qty_v ; short order_no_v ; EXEC SQL END DECLARE SECTION ; order_no_v = 341; qty_v = 10001; strcpy (stmt, "update orders set cust_no = qty_v where order_no = :order_no_v ") ; /* Prepare the SQL statement */ EXEC SQL PREPARE stmtid FROM :stmt ; for (order_no_v = 342 ; order_no_v <= 343 ; order_no_v++) { EXEC SQL SELECT order_no INTO :cust_no FROM orders WHERE order_no = :order_no_v ; printf ("Current cust_no for order number = %d is %d\n", order_no_v, cust_no) ; /* Execute the prepared statement with values */ EXEC SQL EXECUTE stmtid USING :cust_no, :order_no_v ; printf ("Order number %d updated\n", order_no_v) ; } EXEC SQL COMMIT WORK ; printf ("Dynamic non-select statement executed successfully\n") ; return ; err: if (sqlca.sqlcode == SQL_NOT_FOUND) { fprintf (stderr, "Order entry not found in table\\n\\n"); } else if (sqlca.sqlcode < 0) { strncpy (errmesg, sqlca.sqlerrm, sqlca.sqlerrml); errmesg [sqlca.sqlerrml] = '\\0' ; fprintf (stderr, "SQL Error : %s\\n", errmesg); } EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK WORK ; All Rights Reserved 222 www.faircom.com Sample ESQL Programs exit (1); } 17.4 Dynamic SELECT Statements Compiling and Running E:\v621\esql_samples> esqlc -o dynamic_select dynamic_select.pc FairCom/esqlc 1 file(s) copied. Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 11.00.7022 for 80x86 Copyright (C) Microsoft Corp 1984-1997. All rights reserved. dynamic_select.c Creating library dynamic_select.lib and object dynamic_select.exp E:\v621\esql_samples> dynamic_select nflds = 2 ; fldnames : order_no cust_no types : [4, 4] ; lengths : [4, 4] order_no =341 cust_no =10001 order_no =342 cust_no =10001 order_no =343 cust_no =10001 order_no =344 cust_no =10002 order_no =345 cust_no =10002 order_no =346 cust_no =10002 order_no =347 cust_no =10009 nflds = 2 ; fldnames : order_no cust_no types : [4, 4] ; lengths : [4, 4] order_no =341 cust_no =10001 order_no =342 cust_no =10001 order_no =343 cust_no =10001 order_no =344 cust_no =10002 order_no =345 cust_no =10002 order_no =346 cust_no =10002 order_no =347 cust_no =10009 nflds = 2 ; fldnames : order_no cust_no types : [4, 4] ; lengths : [4, 4] order_no =341 cust_no =10001 order_no =342 cust_no =10001 order_no =343 cust_no =10001 order_no =344 cust_no =10002 order_no =345 cust_no =10002 order_no =346 cust_no =10002 order_no =347 cust_no =10009 Dynamic select statement executed successfully E:\v621\esql_samples> Program Source code The following is the complete code listing of an ESQL program for demonstrating the use of dynamic SELECT statements. All Rights Reserved 223 www.faircom.com Sample ESQL Programs /* * * * * * * */ /* * * */ Copyright (C) Dharma Systems Inc. Copyright (C) Dharma Computers (P) Ltd. 1988-97. 1988-97. This Module contains Proprietary Information of Dharma Systems Inc. and Dharma Computers (P) Ltd. and should be treated as Confidential. Example program showing usage of dynamic select statements. #include"stdio.h" #include"sql_lib.h" #include "string.h" #include "stdlib.h" static void dynamic_select () ; static void usage (prog) char *prog ; { fprintf (stderr, "Usage: %s <dbname>\\n\\n", prog) ; exit (1) ; } main() { /* Connect to the default database */ EXEC SQL CONNECT TO DEFAULT USER 'hum'; /* Call function to execute a dynamic select statement */ dynamic_select () ; /* Disconnect from the database */ EXEC SQL DISCONNECT DEFAULT ; exit (0) ; err: if (sqlca.sqlcode) { printf ("SQL Error (%ld) %s\\n", sqlca.sqlcode, sqlca.sqlerrm) ; exit (1) ; } } /* * dynamic_select : demonstrates the use of * a dynamic select statement. * Gets quantity and product name from orders * table for order numbers less than x. * x is 1002 in the first iteration * and 1004 in the last iteration. */ static void dynamic_select () { char errmesg[80]; struct sqlda *sqldaptr ; All Rights Reserved 224 www.faircom.com Sample ESQL Programs EXEC SQL BEGIN DECLARE SECTION ; char stmt [1024] ; short order_no_v ; long qty_v ; char cust_v [30] ; EXEC SQL END DECLARE SECTION ; order_no_v = 342; strcpy (stmt, "select order_no, cust_no from orders where order_no < :order_no_v") ; /* Handle error conditions when SQLERROR */ EXEC SQL WHENEVER SQLERROR GOTO err ; EXEC SQL PREPARE stmtid FROM :stmt ; EXEC SQL DECLARE dyncur CURSOR FOR stmtid ; for (order_no_v = 1002 ; order_no_v <= 1004 ; order_no_v++) { EXEC SQL OPEN dyncur USING :order_no_v ; /* maxvars = 2, varnmsz = 20 */ if (!(sqldaptr = sqld_alloc (2, 20))) { fprintf (stderr, "sqld_alloc returned err\\n") ; goto err ; } /* Note: sqldaptr in the following statement is not * declared ESQL DECLARE section. */ for (;;) { short nvars ; EXEC SQL DESCRIBE SELECT LIST FOR stmtid INTO sqldaptr ; if ((nvars = sqldaptr->sqld_nvars) < 0) { sqld_free (sqldaptr) ; if (!(sqldaptr = sqld_alloc (-(nvars), 20))) { fprintf (stderr, "sqld_alloc returned err\\n") ; goto err ; } continue ; } break ; } printf ("\n nflds = %d ;\n fldnames : %s %s \n", sqldaptr->sqld_nvars, sqldaptr->sqld_varnames [0], sqldaptr->sqld_varnames [1]) ; printf ("types : [%d, %d] ; lengths : [%d, %d]\n", sqldaptr->sqld_types [0], sqldaptr->sqld_types [1], sqldaptr->sqld_lengths [0], sqldaptr->sqld_lengths [1]) ; fflush (stdout); All Rights Reserved 225 www.faircom.com Sample ESQL Programs sqldaptr->sqld_varptrs [0] = (char *) &qty_v ; sqldaptr->sqld_varptrs [1] = (char *) &cust_v [0] ; EXEC SQL WHENEVER NOT FOUND GOTO over ; for (;;) { EXEC SQL FETCH dyncur INTO :qty_v, :cust_v ; printf ("order_no =%d cust_no =%s\n", qty_v, cust_v) ; fflush (stdout); } over: printf ("\n") ; fflush (stdout); EXEC SQL CLOSE dyncur ; sqld_free (sqldaptr) ; sqldaptr = (struct sqlda *)0 ; } EXEC SQL COMMIT WORK ; printf ("Dynamic select statement executed successfully\n") ; return ; err: if (sqlca.sqlcode < 0) { strncpy (errmesg, sqlca.sqlerrm, sqlca.sqlerrml); errmesg [sqlca.sqlerrml] = '\\0' ; fprintf (stderr, "SQL Error : %s\\n", errmesg); } if (sqldaptr) sqld_free (sqldaptr) ; EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK WORK ; exit (1); } 17.5 Long Data Type Support Sample ESQLC Program for lvarchar Data Type The following is the complete code listing of an ESQL program for demonstrating the use of tpe_sqlgetdata() and tpe_sqlputdata() for LVARCHAR column. /* * * * * * Copyright (C) Dharma Systems Inc. Copyright (C) Dharma Systems (P) Ltd. 1988-2003. 1988-2003. This Module contains Proprietary Information of Dharma Systems Inc. and Dharma Systems (P) Ltd. All Rights Reserved 226 www.faircom.com Sample ESQL Programs * */ and should be treated as Confidential. /* * Purpose : * Example program showing the usage long varchar * data type of Dharma/SQL. * * The following functionalities are covered in this test : * # Insert using tpe_sqlputdata(). * # Fetch using tpe_sqlgetdata(). * */ #include "stdio.h" #include "string.h" #include "stdlib.h" #include "sql_lib.h" /* * Inserting the data using tpe_sqlputdata(). */ void insert_part() { dh_i32_t fe_offset; int i, data_buflen; EXEC SQL BEGIN DECLARE SECTION; /* New handle of lvarchar is declared. */ lvc_fld_hdl_t fld_hdl_buffer; char data_buf[101]; char stmt[100]; EXEC SQL END DECLARE SECTION; /* Prepare insert statement. */ printf("Inserting into table longvar by parts ...\n"); /* Set 50 bytes data. */ memset(data_buf, 'A', 50); data_buflen = strlen(data_buf); strcpy ( stmt, "INSERT INTO longvar VALUES (?)"); EXEC SQL prepare S1 from :stmt; /* Handle returned from server is stored in fld_hdl_buffer. */ EXEC SQL execute S1 USING :fld_hdl_buffer; if ( sqlca.sqlcode == 0 ) printf ("Got the field handle value." ); else { printf ("Error in getting the field handle value."); exec sql rollback work; exit(0); } printf("\nExecuting tpe_sqlputdata ...\n"); fe_offset = 0; /* Insert 150 characters. */ for(i=0; i<3; i++) { tpe_sqlputdata( tpe_get_curtmhdl(), /* IN transaction handle */ tpe_get_curdbhdl(), /* IN db handle tpe_pcur0, /* IN cursor TPE_DT_CHAR, /* htypeid All Rights Reserved 227 */ */ */ www.faircom.com Sample ESQL Programs (void *)fld_hdl_buffer,/* hdl to field */ data_buflen, /* IN bufferlen */ fe_offset, /* IN offset into field */ data_buf, /* IN buffer */ &sqlca /* OUT sqlca pointer */ ); fe_offset += data_buflen; } if ( sqlca.sqlcode == 0 ) { printf("Inserting into table longvar by parts successful ...\n"); EXEC SQL commit work; } else { printf("Inserting into table longvar by parts failed ...\n"); EXEC SQL rollback work; } } /* Fetch the inserted record using tpe_sqlgetdata(). */ void fetch_part() { dh_i32_t fe_offset; dh_i32_t fe_val_len; EXEC SQL BEGIN DECLARE SECTION; /* New handle of lvarchar is declared. */ lvc_fld_hdl_t fld_hdl_buffer; char data_buf[101]; char stmt[100]; EXEC SQL END DECLARE SECTION; /* Prepare select statement. */ strcpy ( stmt, "SELECT * FROM longvar"); printf (" STMT STRING : %s \n", stmt); EXEC SQL prepare S1 from:stmt; if (sqlca.sqlcode) { printf("Prepare failed (%ld : %s)\n",sqlca.sqlcode,sqlca.sqlerrm); exit(0); } /* Declare cursor for the select statement. */ printf("Declaring cursor ...\n"); EXEC SQL declare long_cursor cursor for S1; if (sqlca.sqlcode) { printf("Declare failed (%ld : %s)\n",sqlca.sqlcode,sqlca.sqlerrm); exit(0); } printf("Opening cursor ... \n"); EXEC SQL open long_cursor; if (sqlca.sqlcode) { printf("Open failed (%ld : %s)\n",sqlca.sqlcode,sqlca.sqlerrm); exit(0); } /* Fetch the rows and display the same. */ printf("Fetching rows ...\n"); for (;;) { All Rights Reserved 228 www.faircom.com Sample ESQL Programs EXEC SQL fetch long_cursor INTO :fld_hdl_buffer; if (sqlca.sqlcode && sqlca.sqlcode == SQL_NOT_FOUND) { printf("\nNo more data present.\n"); break; } fe_offset = 0; printf("\nExecuting tpe_sqlgetdata ...\n"); for (;;) { tpe_sqlgetdata (tpe_get_curtmhdl(), tpe_get_curdbhdl(), tpe_pcur0, TPE_DT_CHAR, (void *)fld_hdl_buffer, 101, fe_offset, data_buf, &fe_val_len, &sqlca); /* Print the data. */ printf ( "%s", data_buf); fe_offset += 100; if ( fe_val_len <= 0 ) break; } } if (sqlca.sqlcode && sqlca.sqlcode != SQL_NOT_FOUND) exec sql rollback work; /* Close the cursor. */ EXEC SQL close long_cursor; if (sqlca.sqlcode) exec sql commit work; } /* Connect to the default database. */ void attach_db() { /* Connect to the default database. */ EXEC SQL CONNECT TO DEFAULT USER 'systpe'; if (sqlca.sqlcode) { printf("Connect failed (%ld : %s )\n", sqlca.sqlcode, sqlca.sqlerrm); exit(0); } } /* Disconnect from the database. */ detach_db() { EXEC SQL DISCONNECT DEFAULT ; if (sqlca.sqlcode) { printf("Disconnect failed (%ld : %s )\n", sqlca.sqlcode, sqlca.sqlerrm); exit(0); } } All Rights Reserved 229 www.faircom.com Sample ESQL Programs main() { /* Connect to default database. */ attach_db(); /* Insert using tpe_sqlputdata(). */ insert_part(); /* Select using tpe_sqlputdata(). */ fetch_part(); /* Disconnect from default database. */ detach_db(); exit(0); } Sample ESQLC Program for lvarbinary Data Type The following is the complete code listing of an ESQL program for demonstrating the use of tpe_sqlgetdata() and tpe_sqlputdata() for LVARBINARY column. /* * Copyright (C) Dharma Systems Inc. 1988-2003. * Copyright (C) Dharma Systems (P) Ltd. 1988-2003. * * This Module contains Proprietary Information of * Dharma Systems Inc. and Dharma Systems (P) Ltd. * and should be treated as Confidential. */ /* * Purpose : * Example program showing the usage of long varbinary data * type of Dharma/SQL. * * The following functionalities are covered in this test : * # Insert using tpe_sqlputdata(). * # Fetch using tpe_sqlgetdata(). * */ #include "stdio.h" #include "sql_lib.h" #include "string.h" #include "stdlib.h" /* * Inserting the data using tpe_sqlputdata(). */ void insert_part() { dh_i32_t fe_offset; tpe_binary_t binary_buf; int i; EXEC SQL BEGIN DECLARE SECTION; /* New handle of type lvarbinary is declared. */ lvb_fld_hdl_t fld_hdl_buffer; static char stmt[100]; EXEC SQL END DECLARE SECTION; All Rights Reserved 230 www.faircom.com Sample ESQL Programs /* Prepare insert statement. */ printf("\nInserting into table longvarbin by parts ...\n"); /* Set 80 bytes of binary data. */ memset(binary_buf.tb_data,0xff,80); /* Set binary data length. */ binary_buf.tb_len = 80; strcpy ( stmt, "INSERT INTO longvarbin VALUES (?)"); EXEC SQL prepare S1 from :stmt; EXEC SQL execute S1 USING :fld_hdl_buffer; if ( sqlca.sqlcode == 0 ) printf ("Got the field handle value." ); else { printf ("Error in getting the field handle value."); exit(0); } printf("\nExecuting tpe_sqlputdata ...\n"); fe_offset = 0; /* Insert 240 bytes of data. */ for(i=0; i<3; i++) { tpe_sqlputdata( tpe_get_curtmhdl(), /* IN transaction handle.*/ tpe_get_curdbhdl(), /* IN db handle. tpe_pcur0, /* IN cursor. TPE_DT_BINARY, /* htypeid. (void *)fld_hdl_buffer,/* hdl to field. binary_buf.tb_len, /* bufferlen. fe_offset, /* offset into field. &binary_buf, /* buffer. &sqlca /* OUT sqlca pointer. ); fe_offset += 80; } exec sql commit work; printf("Inserting into table longvarbin by parts successful ...\n"); */ */ */ */ */ */ */ */ } /* Fetch the inserted record using tpe_sqlgetdata(). */ void fetch_part() { dh_i32_t fe_offset; dh_i32_t fe_val_len; dh_i32_t i; tpe_binary_t binary_buf; EXEC SQL BEGIN DECLARE SECTION; /* New handle of type lvarbinary is declared. */ lvb_fld_hdl_t fld_hdl_buffer; char stmt[100]; EXEC SQL END DECLARE SECTION; printf("Selecting from table longvarbin (fetch_part) ...\n"); /* Prepare select statement. */ strcpy ( stmt, "SELECT * FROM longvarbin"); printf (" STMT STRING : %s \n", stmt); EXEC SQL prepare S1 from:stmt; if (sqlca.sqlcode) { printf("Prepare failed (%ld : %s )\n", sqlca.sqlcode, sqlca.sqlerrm); exit(0); } /* Declare cursor for the select statement. */ printf("Declaring cursor ...\n"); All Rights Reserved 231 www.faircom.com Sample ESQL Programs EXEC SQL declare long_cursor cursor for S1; if (sqlca.sqlcode) { printf("Declare cursor failed(%ld: %s)\n",sqlca.sqlcode,sqlca.sqlerrm); exit(0); } printf("Opening cursor ... \n"); EXEC SQL open long_cursor; if (sqlca.sqlcode) { printf("Open cursor failed(%ld: %s)\n",sqlca.sqlcode,sqlca.sqlerrm); exit(0); } /* Fetch the rows and display the same. */ printf("Fetching rows ...\n"); for (;;) { /* Server returns handle in fld_hdl_buffer. */ EXEC SQL fetch long_cursor INTO :fld_hdl_buffer; if (sqlca.sqlcode && sqlca.sqlcode == SQL_NOT_FOUND) { printf("\nNo more data present.\n"); break; } fe_offset = 0; printf("\nExecuting tpe_sqlgetdata ...\n"); for (;;) { tpe_sqlgetdata (tpe_get_curtmhdl(), /* IN transaction handle */ tpe_get_curdbhdl(), /* IN db handle tpe_pcur0, /* IN cursor TPE_DT_BINARY, /* htypeid */ (void *)fld_hdl_buffer,/* hdl to field */ 80, /* bufferlen */ fe_offset, /* offset into field */ &binary_buf, /* buffer */ &fe_val_len, /* balance data from offset */ &sqlca); /* OUT sqlca pointer */ for(i = 0; i<binary_buf.tb_len ; i++) printf ("%x", binary_buf.tb_data[i]); fe_offset += 80; if ( fe_val_len <= 0 ) break; } } if (sqlca.sqlcode && sqlca.sqlcode != SQL_NOT_FOUND) exec sql rollback work; /* Close the cursor. */ EXEC SQL close long_cursor; */ */ } /* Connect to the default database. */ void attach_db() { /* Connect to the default database. */ EXEC SQL CONNECT TO DEFAULT USER 'systpe'; if (sqlca.sqlcode) { printf("Connect failed (%ld : %s )\n", sqlca.sqlcode, sqlca.sqlerrm); All Rights Reserved 232 www.faircom.com Sample ESQL Programs exit(0); } } /* Disconnect from the database. */ detach_db() { EXEC SQL DISCONNECT DEFAULT ; if (sqlca.sqlcode) { printf("Disconnect failed (%ld : %s )\n", sqlca.sqlcode, sqlca.sqlerrm); exit(0); } } main() { /* Connect to default database. */ attach_db(); /* Insert using tpe_sqlputdata(). */ insert_part(); /* Select using tpe_sqlputdata(). */ fetch_part(); /* Disconnect from default database. */ detach_db(); exit(0); } All Rights Reserved 233 www.faircom.com Glossary 18. Glossary active set The collection of rows that SQL identifies when it opens a cursor and executes the query associated with the cursor. Also called result set. atomicity A property of transactions that either all the operations in a transaction are done (if the transaction is committed) or none are done (if the transaction is rolled back). candidate key Another term for unique key. commit Make permanent all changes made during a transaction. constraint Part of an SQL table definition that restricts the values that can be stored in a table. When you insert, delete, or update column values, the constraint checks the new values against the conditions specified by the constraint. If the value violates the constraint, it generates an error. Constraints enforce referential integrity by insuring that a value stored in the foreign key of a table must either be null or be equal to some value in the matching unique or primary key of another table. current row The current row of the active set of an open cursor. After an OPEN statement, the cursor is positioned just before the first row of the active set. The first FETCH statement advances the cursor position and makes the first row the current row. Subsequent FETCH statements make subsequent rows the current row. cursor The active set defined by the query in a DECLARE CURSOR statement. Host programs use cursors to retrieve multiple rows of data returned by queries. cycle The process of creating database tables when the first table has a foreign key that references the second table, the second table has a foreign key that references the third table and so on, and the last table has a foreign key that references the first table. Data Control Language (DCL) statements SQL GRANT and REVOKE statements. DCL statements control access to data and the rights to issue DCL statements. Data Definition Language (DDL) statements All Rights Reserved 234 www.faircom.com Glossary SQL CREATE, ALTER, and DROP statements used to manage tables, views, indices, and other database objects. Data Manipulation Language (DML) statements SQL SELECT, INSERT, UPDATE, and DELETE statements that access or modify data. database storage representation The format used by c-treeSQL to store value in the database. This format is different than host language representation for some data types. durability A characteristic of transactions that requires that all changes made during a transaction be permanent after the transaction is committed. dynamic SQL A set of special SQL statements (PREPARE, DESCRIBE, EXECUTE, and EXECUTE IMMEDIATE) and data structures (SQLCA and SQLDA) that let programs accept or generate SQL statements at run time. Such dynamically-generated statements are not necessarily part of a program’s source code, but can be generated at run time. embedded SQL SQL statements that are embedded within a host language program. The esqlc precompiler translates embedded SQL statements to equivalent C-language calls to routines in the c-treeSQL application programming interface. esqlc The c-treeSQL precompiler for C host programs, and the command-line syntax to invoke it. exception handler Host program code that tests for a variety of possible errors and specifies what action will be taken if they arise. EXCLUSIVE locks Locks that SQL acquires on rows that have been modified by a transaction. EXCLUSIVE locks prevent other transactions from either reading or modifying the rows until the transaction either commits or performs a rollback. foreign key A column or columns in a table whose values must either be null or equal to some value in a corresponding columns (called the primary key) in another table. Use the REFERENCES clause in the SQL CREATE TABLE statement to create foreign keys. host language Any programming language in which SQL statements can be embedded for database access. The esqlc precompiler supports embedding SQL statements in C-language programs. host language representation The format used by a host language to represented values. This format is different from the database storage representation used by c-treeSQL for some data types. In some cases, All Rights Reserved 235 www.faircom.com Glossary applications must explicitly convert between data types to insert data or manipulate data retrieved from the database. host program An application program in which SQL statements are embedded. host variable Any host language variable that is used in embedded SQL statements. Programs must declare host variables in the BEGIN-END DECLARE SECTION. Host variables can be declared as a database, host-language, or user-defined types. Depending on how they are used in an SQL statement, host variables are either input (where values stored by the program are used as an expression in an SQL statement) or output (where SQL stores values returned by queries for use by the program). index A database structure that speeds access to particular rows in a table. Indices specify one or more columns as an index key. Queries that use the index key retrieve data faster than those that do not take advantage of an index. indicator variable A variable that is used to represent null values in an application program. Indicator variables must be associated with a host variable. If the value retrieved by a query is null, SQL stores a negative in the indicator variable. Programs set indicator variables to -1 to specify a null value for insertion into the database. Programs declare indicator variables as short or SMALLINT. input host variable A host variable that is used as input to an embedded SQL statement. Embedded SQL statements can refer to host variables anywhere they can refer to an expression. Host programs use input variables to provide values to insert and update data in the database, and as arguments to search conditions. input SQLDA An SQLDA used by a dynamic SQL program to determine the number and data type of input parameters of an SQL statement, and to store values for those input parameters. DESCRIBE BIND VARIABLES, EXECUTE and OPEN statements can specify an input SQLDA that SQL uses to store information about input parameters. integrity constraint Another term for constraint. isolation level The degree by which a transaction is isolated from the database modification operations of other concurrently active transactions. null value The absence of a value. Host programs use indicator variables or SQL constructs to specify null values and retrieve null values from the database. output host variable All Rights Reserved 236 www.faircom.com Glossary A host variable that SQL uses to store results from a query. output SQLDA An SQLDA used by a dynamic SQL program to determine the number and data type of columns in the result set returned by a query, and to retrieve values of that result set. DESCRIBE SELECT LIST and FETCH statements can specify an output SQLDA that SQL uses to store the column information and data. parameter marker Question marks (?) in the statement string of a PREPARE statement. Parameter markers act as placeholders for input variables in dynamic SQL statements. precompiler A translator that translates embedded SQL statements in a host program to the equivalent C calls to functions in the c-treeSQL application programming interface (API). primary key A subset of the fields in a table, characterized by the constraint that no two records in a table may have the same primary key value, and that no fields of the primary key may have a null value. Primary keys are specified in a CREATE TABLE statement. referential constraint Another term for constraint. referential integrity The condition where the value stored in a database table’s foreign key must either be null or be equal to some value in another table’s the matching unique or primary key. Constraints specified as part of CREATE TABLE statements prevent updates that violate referential integrity. relation Another term for table. result set Another term for active set. result table A temporary table of values returned by a query. rollback Undo all changes made during a transaction. SHARE locks Locks that SQL acquires on rows that have been read by a transaction. SHARE locks allow other transactions to read the row but prevent them from modifying the row until this transaction either commits or performs a rollback. SQLCA A host structure that SQL uses to store information about the execution of an SQL statement. The SQLCA contains information about the most recently executed SQL statement. All Rights Reserved 237 www.faircom.com Glossary SQLCODE One of the components of the SQLCA that contains a long INTEGER indicating the status of the execution of an SQL statement. SQLDA A host structure used in dynamic SQL programs. The host program uses the SQLDA to determine the number and data type of input and output parameters of a dynamically-generated SQL statement. SQL uses the SQLDA to determine where to retrieve input parameter values or to store query results. statement string In dynamic SQL, the SQL statement used as an argument to the EXECUTE IMMEDIATE and PREPARE statements. static SQL statement An SQL statements that is known to the application at compile time, as opposed to a dynamically-generated SQL statement. substitution name In the statement string of a PREPARE statement, a name preceded by a colon ( : ). Substitution names do not refer to host-language variable names, but act only as placeholders for input variables in dynamic SQL statements. table The representation of data in a relational database as a collection of columns and rows. Also called relation. transaction A group of database operations whose changes can be made permanent or undone only as a unit. transaction isolation level Another term for isolation level. unique key A column or columns in a table whose value (or combination of values) must be unique. Use the UNIQUE clause of the SQL CREATE TABLE statement to create unique keys. Unique keys are also called candidate keys. view A virtual table that recreates the result table specified by a SELECT statement. No data is stored in a view, but other queries can refer to it as if it were a table containing data corresponding to the result table it specifies. All Rights Reserved 238 www.faircom.com 19. Index using arithmetic expressions............................ 151 using dh_compare_data .................................. 150 Data conversion ................................................... 146 implicit .............................................................. 147 using dh_conv_data ......................................... 147 using scalar functions ...................................... 149 Data type handling, ESQL ................................... 138 Data types BIGINT ............................................................. 140 BINARY ............................................................ 146 BIT.................................................................... 146 CHARACTER ................................................... 138 DATE................................................................ 145 DECIMAL ......................................................... 141 DOUBLE PRECISION ..................................... 141 FLOAT.............................................................. 140 INTEGER ......................................................... 139 LVARBINARY (not supported) ......................... 146 NUMERIC ........................................................ 141 NUMERIC internal storage format ................... 141 REAL ................................................................ 140 SMALLINT ....................................................... 139 TIME................................................................. 145 TIMESTAMP .................................................... 146 Data types, ESQL ................................................ 138 Database types .................................................... 170 DATE data type.................................................... 145 DCL statements ..................................................... 54 DDL statements ............................................... 54, 66 examples ............................................................ 66 long running transactions ................................... 79 DEALLOCATE DESCRIPTOR ............................ 115 DECIMAL data type ............................................. 141 DECLARE CURSOR ........................................... 155 Declare section limitations ..................................... 53 Declare statements in ESQL ................................... 3 example.............................................................. 50 Deleting rows in tables ........................................... 82 DESCRIBE................................................... 127, 156 dh_compare_data ........................................ 150, 181 dh_conv_data .............................................. 147, 182 dh_dayofweek ...................................................... 184 dh_get_curdbhdl .................................................. 185 dh_get_curtmhdl .................................................. 185 dh_num_add ........................................................ 186 dh_set_cursor ...................................................... 187 dh_set_ptrs .......................................................... 188 dh_set_sqlda........................................................ 189 dh_sqlallocdesc ................................................... 209 dh_sqlclose .......................................................... 190 dh_sqlcolumns ..................................................... 215 dh_sqlconnect ...................................................... 191 dh_sqldeallocdesc ............................................... 210 dh_sqldeclare....................................................... 192 dh_sqldescribe ..................................................... 193 dh_sqldescribe_param ........................................ 195 A Aggregate functions NULL values ....................................................... 99 ALLOCATE DESCRIPTOR .................................. 114 Application development ........................................ 57 Array Fetches ......................................................... 91 Associating a Cursor with a Query ......................... 88 B BEGIN-END DECLARE SECTION....................... 153 BIGINT data type .................................................. 140 BINARY data type................................................. 146 BIT data type ........................................................ 146 C C programs using ESQL ........................................... 3 Candidate Keys ...................................................... 74 CHARACTER data type ....................................... 138 Check constraints ................................................... 71 CLOSE .................................................................. 155 Closing a Cursor ..................................................... 90 Coding guidelines ................................................... 57 Column-level candidate key constraint ................... 75 Column-level check constraints .............................. 72 Column-level foreign key constraint ....................... 76 Column-level primary key constraint ...................... 73 Command ESQL .................................................................. 46 ESQL example commands ................................. 54 ESQL syntax ....................................................... 46 COMMIT WORK .............................................55, 132 Compiling, ESQL .................................................... 48 Computations, ESQL .............................................. 58 Condition evaluation, ESQL ................................... 59 CONNECT .............................................................. 62 example .............................................................. 62 Connecting to a remote database .......................... 63 Connection management ....................................... 62 Connection name.................................................... 62 Creating Indices ...................................................... 68 Creating tables........................................................ 66 Creating tables in cycles ......................................... 78 Creating views ........................................................ 69 Cursors ................................................................... 87 associating with a query ..................................... 88 closing .........................................................90, 114 fetching rows ..................................................... 113 opening .......................................................88, 113 retrieving ............................................................. 89 D Data comparison................................................... 150 All Rights Reserved 239 www.faircom.com Index dh_sqldisconnect .................................................. 196 dh_sqlexecute....................................................... 197 dh_sqlfetch ........................................................... 198 dh_sqlforeignkeys ................................................. 215 dh_sqlgetdata ....................................................... 199 dh_sqlgetdesc....................................................... 211 dh_sqlgetdiag ....................................................... 213 dh_sqlgetsqldaptr ................................................. 209 dh_sqlopen ........................................................... 200 dh_sqlprepare ....................................................... 202 dh_sqlprimarykeys ................................................ 215 dh_sqlputdata ....................................................... 207 dh_sqlselect .......................................................... 203 dh_sqlsetdesc ....................................................... 212 dh_sqlstatistics ..................................................... 215 dh_sqltables.......................................................... 215 dh_tm_alloc_handle.............................................. 204 dh_tm_begin_trans ............................................... 205 dh_tm_end_trans .................................................. 206 dh_tm_mark_abort................................................ 206 dh_tm_set_level.................................................... 214 DISCONNECT ........................................................ 62 example .............................................................. 64 DML statement host variables ................................ 84 DML statements................................................54, 80 types of ............................................................... 80 DOUBLE PRECISION data type .......................... 141 Dropping indices ..................................................... 69 Dropping tables....................................................... 67 Dropping tables in cycles ........................................ 78 Dropping views ....................................................... 70 Dynamic non-SELECT statements ....................... 220 Dynamic SELECT statements .............................. 223 data type .......................................................... 138 data type handling............................................ 138 declare section limitations .................................. 53 declare statements definition ............................... 3 declare statements example .............................. 50 DML.................................................................... 80 error handling ................................................... 100 executable statement definition ........................... 3 executable statement examples ........................ 54 host program development .................................. 3 host variables ..................................................... 51 implicit data conversion.................................... 147 indicator variables, definition ............................. 51 indicator variables, using ................................... 60 null value handling ............................................. 94 overview ............................................................... 1 precompile ........................................................... 3 precompiling ....................................................... 48 program structure............................................... 50 sample programs ............................................. 216 scalar functions .................................................. 60 SQL management ............................................ 109 SQL statements ............................................... 153 statement types .................................................. 54 status codes ....................................................... 54 syntax ................................................................. 46 transaction management ................................. 131 types of executable statements ......................... 54 ESQL descriptor statement.................................. 114 EXEC ................................................................... 159 Executable statement types................................... 54 Executable statements in ESQL examples ............................................................ 54 Executable statements, ESQL ................................. 3 EXECUTE ............................................................ 159 EXECUTE IMMEDIATE ............................... 112, 161 E END DECLARE SECTION ................................... 159 Error checking SQLCA .............................................................. 102 Error handling ....................................................... 100 indicator variables ............................................. 107 SQLCA .............................................................. 100 WHENEVER statement .................................... 105 ESQL abnormal termination ........................................ 136 advantages ........................................................... 3 application development ..................................... 57 command ............................................................ 46 command examples............................................ 48 compiling ............................................................. 48 compiling, running.................... 216, 218, 220, 223 components .......................................................... 3 computation ........................................................ 58 condition evaluation ............................................ 59 connection management .................................... 62 data comparison ............................................... 150 data conversion ................................................ 146 All Rights Reserved F FETCH ................................................................. 161 Fetches arrays ................................................................. 91 SQLDA array fetches ....................................... 125 using a cursor .................................................. 113 FLOAT data types ................................................ 140 Functions NVL .................................................................... 97 scalar.................................................................. 60 G GET DESCRIPTOR ............................................. 115 GROUP BY clause NULL values ........................... 99 H Host language types ............................................ 171 Host variables ........................................................ 51 in DML statements ............................................. 84 240 www.faircom.com Index NUMERIC data type ............................................ 141 internal storage format ..................................... 141 NVL function .......................................................... 97 I IN predicate .......................................................... 167 Indicator variables definition.............................................................. 51 error handling .................................................... 107 insert NULL values ............................................. 95 retrieve NULL value ............................................ 97 using ................................................................... 60 Indices creating/dropping ................................................ 68 Input host variables in query statements ............................................ 86 Input variables SQLDA .............................................................. 128 Inserting NULL values ............................................ 94 Inserting rows in tables ........................................... 80 Inserting rows in tables in cycles ............................ 78 INTEGER data type .............................................. 139 Integrity constraints................................................. 71 check constraints ................................................ 71 column-level candidate key constraints .............. 75 column-level check constraint ............................ 72 column-level foreign key constraints .................. 76 column-level primary key constraints ................. 73 table-level candidate key constraints.................. 75 table-level check constraints............................... 72 table-level foreign key constraints ...................... 77 table-level primary key constraints ..................... 74 types of ............................................................... 71 Isolation levels ...................................................... 134 O OPEN ........................................................... 113, 163 Opening a cursor ................................................... 88 ORDER BY clause NULL values ........................... 99 Output host variables in query statements............................................ 86 Output variables SQLDA ............................................................. 129 Overview of ESQL ................................................... 1 P Precompiling, ESQL .............................................. 48 Predicates IN 167 LIKE ................................................................. 166 PREPARE .................................................... 110, 164 Primary keys .......................................................... 73 Programmatic Interfaces ...................................... 179 Q Queries multiple row ........................................................ 87 single row ........................................................... 86 Query Expressions............................................... 166 Query statements................................................... 85 R REAL data type .................................................... 140 Record types ........................................................ 174 Referential constraints ........................................... 75 Referential integrity ................................................ 77 Relational views ....................................................... 1 Retrieving a cursor ................................................. 89 Retrieving NULL values ......................................... 97 Rollback transaction ............................................ 136 ROLLBACK WORK........................................ 55, 133 K Keys candidate ............................................................ 74 primary ................................................................ 73 L LIKE predicate ...................................................... 166 Long data type support ......................................... 226 Long running transactions ...................................... 79 LVARBINARY data type (not supported).............. 146 S Sample ESQL programs ...................................... 216 Scalar functions ..................................................... 60 data type conversions ...................................... 149 NULL values ...................................................... 99 NVL .................................................................... 97 Search Conditions................................................ 166 SELECT ............................................................... 112 SET CONNECTION ............................................... 62 example.............................................................. 64 SET DESCRIPTOR ............................................. 117 SINGLE-ROW SELECT ....................................... 167 SMALLINT data type ........................................... 139 SQL Management .................................................... 109 queries ............................................................... 85 M Multiple row queries ................................................ 87 N non-SELECT......................................................... 111 NULL values ........................................................... 94 in aggregate functions ........................................ 99 in expressions ..................................................... 98 in GROUP BY clause.......................................... 99 in ORDER BY clause .......................................... 99 in scalar functions ............................................... 99 in WHERE clause ............................................... 98 inserting .............................................................. 94 retrieving ............................................................. 97 updating .............................................................. 96 All Rights Reserved 241 www.faircom.com Index statements ........................................................ 153 SQL communication area ....................................... 54 SQLCODE .......................................................... 54 SQLWARN .......................................................... 54 SQL Descriptor Area............................................. 118 allocating ........................................................... 123 array fetches ..................................................... 125 components ...................................................... 119 diagram ............................................................. 123 fields.................................................................. 119 freeing ............................................................... 126 input variables ................................................... 128 output variables ................................................ 129 types and lengths .............................................. 124 SQL in a host language ............................................ 2 SQL statement input host variables........................ 86 SQL statement output host variables ..................... 86 SQL statements BEGIN-END DECLARE SECTION ................... 153 CLOSE .............................................................. 155 DECLARE CURSOR ........................................ 155 DESCRIBE........................................................ 156 END DECLARE SECTION ............................... 159 EXEC SQL ........................................................ 159 EXECUTE ......................................................... 159 EXECUTE IMMEDIATE .................................... 161 FETCH .............................................................. 161 OPEN ................................................................ 163 PREPARE ......................................................... 164 QUERY EXPRESSIONS .................................. 166 SEARCH CONDITIONS ................................... 166 SINGLE-ROW SELECT.................................... 167 TYPE DECLARATIONS ................................... 169 TYPE SPECIFICATIONS ................................. 169 WHENEVER ..................................................... 175 SQL_NOT_FOUND .............................................. 107 SQLCA .................................................................... 54 error checking ................................................... 102 error handling .................................................... 100 SQLCODE .......................................................... 54 SQLWARN .......................................................... 54 warning checking .............................................. 104 SQLCODE .............................................................. 54 sqld_alloc .............................................................. 179 sqld_free ............................................................... 179 SQLDA .................................................................. 118 allocating ........................................................... 123 array fetches ..................................................... 125 components ...................................................... 119 diagram ............................................................. 123 fields.................................................................. 119 freeing ............................................................... 126 input variables ................................................... 128 output variables ................................................ 129 types and lengths .............................................. 124 SQLWARN .............................................................. 54 All Rights Reserved Statements ........................................................... 153 BEGIN-END DECLARE SECTION .................. 153 CLOSE ............................................................. 155 COMMIT WORK ........................................ 55, 132 CONNECT ......................................................... 62 CONNECT, example.......................................... 62 DDL .................................................................... 66 DECLARE CURSOR ....................................... 155 DESCRIBE ............................................... 127, 156 DISCONNECT ................................................... 62 DISCONNECT, example.................................... 64 DML.................................................................... 80 dynamic non-SELECT ..................................... 220 dynamic SELECT............................................. 223 END DECLARE SECTION .............................. 159 EXEC SQL ....................................................... 159 EXECUTE ........................................................ 159 EXECUTE IMMEDIATE ........................... 112, 161 FETCH ............................................................. 161 non-SELECT .................................................... 111 OPEN ....................................................... 113, 163 PREPARE ................................................ 110, 164 QUERY EXPRESSIONS ................................. 166 ROLLBACK WORK.......................................... 133 SEARCH CONDITIONS .................................. 166 SELECT ........................................................... 112 SET CONNECTION ........................................... 62 SET CONNECTION, example ........................... 64 SINGLE-ROW SELECT ................................... 167 SQL SELECT ..................................................... 58 static non-SELECT .......................................... 216 static SELECT .................................................. 218 TYPE DECLARATIONS................................... 169 TYPE SPECIFICATIONS................................. 169 WHENEVER ............................................ 105, 175 Static array types ................................................. 172 Static non-SELECT statements ........................... 216 Static SELECT statements .................................. 218 Syntax, ESQL ........................................................ 46 T Table record types ............................................... 174 Table-column types ............................................. 172 Table-level candidate key constraint ..................... 75 Table-level check constraint .................................. 72 Table-level foreign key constraint .......................... 77 Table-level primary key constraint ......................... 74 Tables creating in cycles ............................................... 78 creating/dropping ............................................... 66 deleting rows ...................................................... 82 dropping in cycles .............................................. 78 inserting rows ..................................................... 80 inserting rows in cycles ...................................... 78 updating rows ..................................................... 83 TIME data type..................................................... 145 242 www.faircom.com Index TIMESTAMP data type ......................................... 146 Transaction management ..................................... 131 forced rollback .................................................. 136 isolation levels .................................................. 134 locking ............................................................... 135 statements .......................................................... 54 Transactions long running ........................................................ 79 TYPE DECLARATIONS ....................................... 169 TYPE SPECIFICATIONS ..................................... 169 Types of ESQL executable statements .................. 54 U Updating NULL values ............................................ 96 Updating rows in tables .......................................... 83 Using NULL Values ................................................ 98 V Variables indicator .............................................................. 97 input host ......................................................84, 86 output host .......................................................... 86 Views ........................................................................ 1 creating/dropping ................................................ 69 W Warning checking SQLCA .............................................................. 104 WHENEVER ......................................................... 175 WHERE clause NULL values ................................. 98 All Rights Reserved 243 www.faircom.com