Upload
others
View
28
Download
0
Embed Size (px)
Citation preview
Developer Guide
Java & .NET Stored Procedures Guide
All Rights Reserved ii www.faircom.com
Contents
1. Introduction to Stored Procedures, Triggers, and User Defined
Functions ............................................................................................................. 1
2. Java Stored Procedures, Triggers, and UDFs .................................................. 2
2.1 Creating Stored Procedures .................................................................................. 2
2.2 Calling Stored Procedures .................................................................................... 3
2.3 Java Stored Procedure and Triggers require JDK V1.7 or newer ......................... 4
3. Java Quick Tour .................................................................................................. 6
3.1 Introductory Tutorial .............................................................................................. 9
Init 10
Define ................................................................................................................................ 11
Manage ............................................................................................................................. 12
Done .................................................................................................................................. 14
Additional Resources ........................................................................................................ 15
3.2 Record/Row Locking ........................................................................................... 16
Init 17
Define ................................................................................................................................ 18
Manage ............................................................................................................................. 19
Done .................................................................................................................................. 21
Additional Resources ........................................................................................................ 22
3.3 Transaction Processing ....................................................................................... 23
Init 24
Define ................................................................................................................................ 25
Manage ............................................................................................................................. 28
Done .................................................................................................................................. 32
Additional Resources ........................................................................................................ 33
4. NetBeans Plugin for Java ................................................................................. 34
4.1 Setting up the Connection to the Server.............................................................. 34
4.2 Installing the NetBeans Plugin ............................................................................ 36
4.3 Editing Stored Procedures .................................................................................. 37
4.4 Enabling Debugging ............................................................................................ 39
5. Using Java Stored Procedures ........................................................................ 40
5.1 Introduction .......................................................................................................... 40
5.2 Stored Procedure Basics ..................................................................................... 40
Introduction to Stored Procedures, Triggers, and User Defined Functions
All Rights Reserved iii www.faircom.com
What Is a Java Snippet? ................................................................................................... 41
Structure of Stored Procedures ........................................................................................ 41
Setting Up Your Environment to Write Stored Procedures ............................................... 43
Writing Stored Procedures ................................................................................................ 44
Invoking Stored Procedures .............................................................................................. 45
Modifying and Deleting Stored Procedures ...................................................................... 47
Debugging Stored Procedures .......................................................................................... 47
Transactions and Stored Procedures ............................................................................... 49
Stored Procedure Security ................................................................................................ 49
Restrictions on Calling Java Methods in Stored Procedures ............................................ 49
5.3 Using c-treeACE SQL Java Classes ................................................................... 50
Passing Values to SQL Statements .................................................................................. 50
Passing Values to and From Stored Procedures: Input and Output Parameters ............. 52
Implicit Data Type Conversion Between SQL and Java Types ........................................ 53
Executing an SQL Statement ............................................................................................ 54
Retrieving Data: the SQLCursor Class ............................................................................. 56
Returning a Procedure Result Set: the RESULT Clause and DhSQLResultSet .............. 59
Handling Null Values ......................................................................................................... 60
Handling Errors ................................................................................................................. 62
Calling Stored Procedures from Stored Procedures ......................................................... 63
6. Using Triggers ................................................................................................... 64
6.1 Trigger Basics ..................................................................................................... 64
Triggers vs. Stored Procedures vs. Constraints ............................................................... 64
Typical Uses for Triggers .................................................................................................. 65
Restrictions on creating Triggers ...................................................................................... 65
6.2 Structure of Triggers ............................................................................................ 65
6.3 Create Trigger ..................................................................................................... 67
6.4 OLDROW and NEWROW Objects: Passing Values to Triggers ......................... 67
7. Using User Defined Scalar Functions ............................................................. 70
7.1 Introduction .......................................................................................................... 70
7.2 Structure of User Defined Functions ................................................................... 70
7.3 Create Function ................................................................................................... 71
7.4 Drop Function ...................................................................................................... 72
7.5 Invoking User Defined Scalar Functions ............................................................. 72
With Constants .................................................................................................................. 72
With Constants and Column References .......................................................................... 72
With parameter reference (ODBC/JDBC) ......................................................................... 73
7.6 User Defined Scalar Function Security ................................................................ 73
7.7 Calling Scalar Functions from a User Defined Scalar Function ........................... 73
Introduction to Stored Procedures, Triggers, and User Defined Functions
All Rights Reserved iv www.faircom.com
8. Java Class Reference ....................................................................................... 74
8.1 Introduction .......................................................................................................... 74
8.2 DhSQLException ................................................................................................. 75
DhSQLException.getDiagnostics ...................................................................................... 76
8.3 DhSQLResultSet ................................................................................................. 77
DhSQLResultSet.insert ..................................................................................................... 77
DhSQLResultSet.makeNULL ............................................................................................ 78
DhSQLResultSet.set ......................................................................................................... 79
8.4 SQLCursor .......................................................................................................... 80
SQLCursor.close ............................................................................................................... 81
SQLCursor.fetch ............................................................................................................... 81
SQLCursor.found .............................................................................................................. 82
SQLCursor.getParam ....................................................................................................... 82
SQLCursor.getValue ......................................................................................................... 84
SQLCursor.makeNULL ..................................................................................................... 85
SQLCursor.open ............................................................................................................... 86
SQLCursor.registerOutParam ........................................................................................... 86
SQLCursor.rowCount ........................................................................................................ 87
SQLCursor.setParam ........................................................................................................ 88
SQLCursor.wasNULL........................................................................................................ 89
8.5 SQLIStatement .................................................................................................... 89
SQLIStatement.execute .................................................................................................... 90
SQLIStatement.getParam ................................................................................................. 91
SQLIStatement.makeNULL .............................................................................................. 92
SQLIStatement.registerOutParam .................................................................................... 92
SQLIStatement.rowCount ................................................................................................. 93
SQLIStatement.setParam ................................................................................................. 94
8.6 SQLPStatement .................................................................................................. 95
SQLPStatement.execute .................................................................................................. 95
SQLPStatement.getParam ............................................................................................... 96
SQLPStatement.makeNULL ............................................................................................. 97
SQLPStatement.registerOutParam ................................................................................... 98
SQLPStatement.rowCount ................................................................................................ 98
SQLPStatement.setParam ................................................................................................ 99
9. .NET Support ................................................................................................... 101
9.1 Visual Studio .NET Development ...................................................................... 101
9.2 .NET Tutorials ................................................................................................... 102
9.3 Mapping Between SQL Types and .NET Types ................................................ 104
10. Writing .NET Stored Procedures .................................................................... 105
Introduction to Stored Procedures, Triggers, and User Defined Functions
All Rights Reserved v www.faircom.com
10.1 Writing a New SP, UDF, or Trigger ................................................................... 106
10.2 Deploying the SP, UDF, or Trigger .................................................................... 107
10.3 Testing the SP, UDF, or Trigger ........................................................................ 107
10.4 Debugging the SP, UDF, or Trigger .................................................................. 107
10.5 Altering the SP, UDF, or Trigger........................................................................ 108
10.6 Writing the Code ................................................................................................ 108
10.7 Returning a Result Set from a Stored Procedure .............................................. 109
10.8 Returning a UDF Result .................................................................................... 109
10.9 Accessing Old and New Rows in Triggers ........................................................ 109
11. The .NET Ctree.SqlSP Assembly ................................................................... 110
11.1 SqlSpBase ......................................................................................................... 110
11.2 SqlStoredProc ................................................................................................... 111
11.3 SqlUdf ................................................................................................................ 112
11.4 SqlTrigger .......................................................................................................... 112
11.5 SqlSpRow .......................................................................................................... 113
11.6 SqlSpColumn .................................................................................................... 113
11.7 SqlSpCommand ................................................................................................ 115
11.8 SqlException ..................................................................................................... 116
12. Glossary ........................................................................................................... 117
13. Document History ........................................................................................... 125
14. Index ................................................................................................................. 129
All Rights Reserved 1 www.faircom.com
1. Introduction to Stored Procedures,
Triggers, and User Defined Functions
Stored procedures and triggers provide the ability to write Java and .NET routines that contain
SQL statements and store those routines within a c-treeACE SQL database. Tools and
applications can then execute the procedures.
A stored procedure is a snippet of code embedded in an SQL CREATE PROCEDURE statement.
The snippet can use all standard Java or .NET features as well as c-treeACE SQL supplied Java
classes for processing any number of SQL statements.
A trigger is a special type of stored procedure that helps ensure referential integrity for a
database. Like stored procedures, triggers also contain Java or .NET code (embedded in a
CREATE TRIGGER statement) and classes. However, triggers are automatically invoked (“fired”)
by certain SQL operations (an insert, update, or delete operation) on the trigger’s target table.
User defined functions (UDFs) extend the availability of built-in scalar functions with modules
written by the user. The user can transform data with custom routines for their unique business
needs. These procedures are created with the c-treeACE SQL CREATE FUNCTION statement.
Advantages of Stored Procedures
Stored procedures and triggers provide a flexible, general mechanism to store a collection of SQL
statements and program constructs in a database enforcing business rules and performing
administrative tasks.
The ability to write stored procedures and triggers expands the flexibility and performance of
applications that access a c-treeACE SQL environment:
In a client/server environment, applications make only a single client/server request for the
entire procedure, instead of one or more requests for each c-treeACE SQL statement in the
stored procedure or trigger.
Stored procedures and triggers are stored in compiled form (as well as source-code form), so
they execute much faster than a corresponding c-treeACE SQL script.
Stored procedures can implement elaborate algorithms to enforce complex business rules.
The details of the procedure implementation can change without requiring changes in an
application that calls the procedure.
All Rights Reserved 2 www.faircom.com
2. Java Stored Procedures, Triggers, and
UDFs
The c-treeACE SQL implementation of stored procedures allows use of standard Java
programming constructs instead of requiring proprietary flow-control language. To do this, the
c-treeACE SQL interacts with Java in the following ways:
When you create a stored procedure, c-treeACE SQL processes the Java code, submits it to
the Java compiler, and receives the compiled results to store in the database.
When applications call a stored procedure, c-treeACE SQL interacts with the Java virtual
machine (JRE) to execute the stored procedure and receive any results.
2.1 Creating Stored Procedures
The Java source code that makes up the body of a stored procedure is not a complete program.
It is a snippet that c-treeACE SQL converts into a Java class when it processes a CREATE
PROCEDURE statement.
Creating a stored procedure involves the following steps:
1. Some application or tool (c-treeACE SQL Explorer, Interactive SQL utility, or an application)
issues a CREATE PROCEDURE statement containing the Java snippet.
2. c-treeACE SQL adds additional supporting code to the Java snippet to create a complete Java class and submits the combined code to the Java compiler (javac).
3. Presuming there are no Java compilation errors, the Java compiler sends compiled bytecode back to c-treeACE SQL. If there are compilation errors, c-treeACE SQL passes the first error
generated back to the application or tool that issued the CREATE PROCEDURE statement.
4. c-treeACE SQL stores both the Java source code and the bytecode form of the procedure in the database.
Java Stored Procedures, Triggers, and UDFs
All Rights Reserved 3 www.faircom.com
The following figure illustrates the steps in creating a stored procedure:
Figure 1: Creating Stored Procedures
2.2 Calling Stored Procedures
Once a stored procedure is created and stored in the database, any application (or other stored
procedure) can execute it by calling it. You can call stored procedures from ODBC, JDBC, or
.NET applications, or directly from the Interactive SQL utility, isql.
For example, the following example shows an excerpt from an ODBC application that calls a
stored procedure (order_parts) using the ODBC syntax:
{ call procedure_name ( param ) }.
Executing a Stored Procedure Through ODBC
SQLUINTEGER Part_num;
SQLINTEGER Part_numInd = 0;
// Bind the parameter.
SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0,
&Part_num, 0, Part_numInd);
// Place the department number in Part_num.
Part_num = 318;
// Execute the statement.
SQLExecDirect(hstmt, "{call order_parts(?)}", SQL_NTS);
Executing a stored procedure involves the following steps:
1. The application calls the stored procedure through its native calling mechanism (for example, using the ODBC call escape sequence).
2. c-treeACE SQL retrieves the compiled bytecode-form of the procedure and submits it to the Java virtual machine for execution.
Java Stored Procedures, Triggers, and UDFs
All Rights Reserved 4 www.faircom.com
3. For every c-treeACE SQL statement in the procedure, the Java virtual machine calls c-treeACE SQL.
4. c-treeACE SQL manages interaction with the underlying database system and execution of the SQL statements, and returns any results to the Java virtual machine.
5. The Java virtual machine returns results (output parameters and result sets) of the procedure to c-treeACE SQL, which in turn passes them to the calling application.
The following figure illustrates the steps in executing a stored procedure.
Figure 2: Executing Stored Procedures
2.3 Java Stored Procedure and Triggers require JDK V1.7
or newer
Note: The c-treeACE SQL Java Stored Procedure and Trigger support requires a Java
Development Kit (JDK). c-treeACE V11.5 requires JDK V1.7 or newer. For the tutorials to work
correctly, be sure you have installed a suitable JDK, and be sure the following paths for the
following environments in ctsrvr.cfg point to your JDK installation folder and are active (meaning
the ";" has been removed from the beginning of each environment variable). For example, if your
Java version and installation is located in C:\Java\jdk1.7.0_75 and your FairCom installation
directory is C:\FairCom\V*, you should have the following in ctsrvr.cfg:
; JDK environment settings - Be sure to set the JDK to your version.
SETENV CLASSPATH=C:\Program
Files\Java\jdk1.7.0_75\jre\lib\rt.jar;C:\FairCom\v11.5.0\win32\bin\ace\sql\classes\ctreeSQLSP
.jar
SETENV JVM_LIB=C:\Program Files\Java\jdk1.7.0_75\jre\bin\server\jvm.dll
SETENV JAVA_COMPILER=C:\Program Files\Java\jdk1.7.0_75\bin\javac.exe
Java Stored Procedures, Triggers, and UDFs
All Rights Reserved 5 www.faircom.com
Classpath: The classpath shown is for a default c-treeACE installation. If you are using
c-treeRTG, adjust the path to match your version, e.g., V2.2.0.RTG, and replace sdk with Driver.
All Rights Reserved 6 www.faircom.com
3. Java Quick Tour
This QuickStart is composed of four simple tutorials designed to guide you through the basic use
of the c-treeACE SQL Stored Procedures technology.
Like all other tutorials in the c-tree series, each example simplifies the concepts of database
programming into four simple steps: Initialize(), Define(), Manage(), and You're Done() !
No matter what c-treeACE Interface language you are using, FairCom follows this same
high-level flow in all tutorials. This makes it easy for developers to "cross-over" from one
language interface to another as these basic concepts apply to all.
Initialize()
Every language requires some form of initial "logon" or "connection" procedure to establish a session with the database. This is done in the Initialize() stage of the program.
Define()
Database definitions (DDL), Table/File schema definitions, Index definitions, Table/File creation, and Table/File open operations are all addressed in the Define() stage of the program.
Manage()
This stage of the program is where the database is operated on, as in managing your data. Adding/Reading/Updating/Deleting records/rows are handled in this stage of the program.
Done()
When the program ends, the database session should be closed. This stage handles the necessities to "de-init", by closing Tables/Files and issuing any required "logoff" or "disconnect" type procedures.
Presented here are tutorials that follow the "Initialize(), Define(), Manage(), and You're Done() ! "
approach.
Four SQL scripts have been included in the SQL Stored Procedures Tutorial directory, located in:
C:\FairCom\V*\win32\sdk\sql.stored.procs\tutorials (where C:\FairCom\V* is your installation
directory. The default installation directory was C:\FairCom\V*).
The following is a conceptual overview of these tutorials:
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) file/table.
Java Quick Tour
All Rights Reserved 7 www.faircom.com
Manage() - Adds a few records/rows; Reads the records/rows back from the database and
displays their content; and then deletes the records/rows.
Done() - Disconnects from c-treeACE Database Engine.
Tutorial #2: Relational Model and Indexing
Here we now 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"
files/tables with related indices.
Manage() - Adds some related records/rows to all files/tables. Then queries this order
database.
Done() - Disconnects from c-treeACE Database Engine.
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) file/table.
Manage() - Adds a few records/rows; Reads the records/rows back from the database and
displays their content. Then demonstrates an update operation under locking control, and a
scenario that shows a locking conflict.
Done() - Disconnects from c-treeACE database engine.
Tutorial #4: Transaction Processing
Here we demonstrate transaction control.
Java Quick Tour
All Rights Reserved 8 www.faircom.com
Initialize() - Connects to the c-treeACE database engine.
Define() - Defines and creates our four file/tables.
Manage() - Adds records/rows to multiple tables under transaction control.
Done() - Disconnects from c-treeACE Database Engine.
Java Quick Tour
All Rights Reserved 9 www.faircom.com
3.1 Introductory Tutorial
..\sdk\sql.stored.procs\tutorials\SPTTutorial1.sql
If you are using c-treeRTG, adjust the path to match your version, e.g., V2.2.0.RTG, and replace
sdk with Driver.
This tutorial will take you through the basic use of the c-treeACE SQL Stored Procedures
Technology.
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 these sections in our SQL Script:
-- Initialize
ECHO INIT;
-- Define
ECHO DEFINE;
-- Manage
ECHO MANAGE;
-- Done
ECHO DONE;
We suggest opening the source code with your own editor.
Continue now to review these four steps.
Java Quick Tour
All Rights Reserved 10 www.faircom.com
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():
SET ECHO OFF
-- Initialize
ECHO INIT;
SET AUTOCOMMIT ON;
Java Quick Tour
All Rights Reserved 11 www.faircom.com
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():
DROP PROCEDURE Define;
CREATE PROCEDURE Define()
BEGIN
SQLIStatement st = new SQLIStatement (
"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))"
);
st.execute();
END
-- Define
ECHO DEFINE;
CALL Define();
Java Quick Tour
All Rights Reserved 12 www.faircom.com
Manage
The manage step provides data management functionality for your application and/or process.
Below is the code for Manage():
DROP PROCEDURE Add_Records;
DROP PROCEDURE Display_Records;
DROP PROCEDURE Delete_Records;
CREATE PROCEDURE Add_Records (
IN cm_custnumb CHAR(4),
IN cm_custzipc CHAR(9),
IN cm_custstat CHAR(2),
IN cm_custrtng CHAR(1),
IN cm_custname VARCHAR(47),
IN cm_custaddr VARCHAR(47),
IN cm_custcity VARCHAR(47)
)
BEGIN
SQLIStatement st = new SQLIStatement (
"INSERT INTO custmast VALUES (?,?,?,?,?,?,?) "
);
st.setParam (1, cm_custnumb);
st.setParam (2, cm_custzipc);
st.setParam (3, cm_custstat);
st.setParam (4, cm_custrtng);
st.setParam (5, cm_custname);
st.setParam (6, cm_custaddr);
st.setParam (7, cm_custcity);
st.execute();
END
CREATE PROCEDURE Display_Records ()
RESULT (
Numb CHAR(4),
Name CHAR(47)
)
BEGIN
SQLCursor cur = new SQLCursor ("SELECT cm_custnumb, cm_custname FROM custmast");
cur.open();
cur.fetch();
while (cur.found())
{
SQLResultSet.set(1, cur.getValue(1, CHAR));
SQLResultSet.set(2, cur.getValue(2, CHAR));
SQLResultSet.insert();
cur.fetch();
}
cur.close();
END
CREATE PROCEDURE Delete_Records ()
Java Quick Tour
All Rights Reserved 13 www.faircom.com
BEGIN
SQLIStatement sp_DeleteTable = new SQLIStatement ("DELETE FROM custmast");
sp_DeleteTable.execute();
END
-- Manage
ECHO MANAGE;
ECHO Delete records...;
CALL Delete_Records ();
ECHO Add records...;
CALL Add_Records('1000', '92867', 'CA', '1', 'Bryan Williams', '2999 Regency', 'Orange');
CALL Add_Records('1001', '61434', 'CT', '1', 'Michael Jordan', '13 Main', 'Harford');
CALL Add_Records('1002', '73677', 'GA', '1', 'Joshua Brown', '4356 Cambridge', 'Atlanta');
CALL Add_Records('1003', '10034', 'MO', '1', 'Keyon Dooling', '19771 Park Avenue', 'Columbia');
ECHO Display records...;
CALL Display_Records();
ECHO Delete records...;
CALL Delete_Records ();
Java Quick Tour
All Rights Reserved 14 www.faircom.com
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
ECHO DONE;
Java Quick Tour
All Rights Reserved 15 www.faircom.com
Additional Resources
We encourage you to explore the additional resources listed here:
Complete SQL script for this tutorial can be found in SPTTutorial1.sql in your installation
directory, within the sql.stored.procs\tutorials directory for your platform. Example for the
Windows platform:
C:\FairCom\V*\win32\sdk\sql.stored.procs\tutorials\SPTTutorial1.sql
(If you are using c-treeRTG, adjust the path to match your version, e.g., V2.2.0.RTG, and
replace sdk with Driver.)
Additional documentation may be found on the FairCom Web site at: www.faircom.com.
Java Quick Tour
All Rights Reserved 16 www.faircom.com
3.2 Record/Row Locking
..\sdk\sql.stored.procs\tutorials\SPTTutorial3.sql
If you are using c-treeRTG, adjust the path to match your version, e.g., V2.2.0.RTG, and replace
sdk with Driver.
Now we will explore row/record locks using the c-treeACE SQL Stored Procedures Technology.
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 these sections in our SQL Script:
-- Initialize
ECHO INIT;
-- Define
ECHO DEFINE;
-- Manage
ECHO MANAGE;
-- Done
ECHO DONE;
We suggest opening the source code with your own editor.
Continue now to review these four steps.
Java Quick Tour
All Rights Reserved 17 www.faircom.com
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():
SET ECHO OFF
-- Initialize
ECHO INIT;
SET AUTOCOMMIT OFF;
Java Quick Tour
All Rights Reserved 18 www.faircom.com
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():
DROP PROCEDURE Define;
CREATE PROCEDURE Define()
BEGIN
SQLIStatement cm = new SQLIStatement (
"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))"
);
cm.execute();
SQLIStatement cmi = new SQLIStatement (
"CREATE UNIQUE INDEX cm_custnumb_idx ON custmast (cm_custnumb)"
);
cmi.execute();
END
-- Define
ECHO DEFINE;
CALL Define();
COMMIT WORK;
Java Quick Tour
All Rights Reserved 19 www.faircom.com
Manage
The manage step provides data management functionality for your application and/or process.
Below is the code for Manage():
DROP PROCEDURE Add_CustomerMaster_Record;
DROP PROCEDURE Delete_Records;
CREATE PROCEDURE Add_CustomerMaster_Record (
IN cm_custnumb CHAR(4),
IN cm_custzipc CHAR(9),
IN cm_custstat CHAR(2),
IN cm_custrtng CHAR(1),
IN cm_custname VARCHAR(47),
IN cm_custaddr VARCHAR(47),
IN cm_custcity VARCHAR(47)
)
BEGIN
SQLIStatement st = new SQLIStatement (
"INSERT INTO custmast VALUES (?,?,?,?,?,?,?)"
);
st.setParam (1, cm_custnumb);
st.setParam (2, cm_custzipc);
st.setParam (3, cm_custstat);
st.setParam (4, cm_custrtng);
st.setParam (5, cm_custname);
st.setParam (6, cm_custaddr);
st.setParam (7, cm_custcity);
st.execute();
END
CREATE PROCEDURE Delete_Records (
IN tablename CHAR(256)
)
BEGIN
SQLIStatement st = new SQLIStatement (
"DELETE FROM " + tablename
);
st.execute();
END
-- Manage
ECHO MANAGE;
ECHO Delete records...;
CALL Delete_Records('custmast');
ECHO Add records...;
CALL Add_CustomerMaster_Record('1000', '92867', 'CA', '1', 'Bryan Williams', '2999 Regency',
'Orange');
CALL Add_CustomerMaster_Record('1001', '61434', 'CT', '1', 'Michael Jordan', '13 Main',
'Harford');
CALL Add_CustomerMaster_Record('1002', '73677', 'GA', '1', 'Joshua Brown', '4356 Cambridge',
Java Quick Tour
All Rights Reserved 20 www.faircom.com
'Atlanta');
CALL Add_CustomerMaster_Record('1003', '10034', 'MO', '1', 'Keyon Dooling', '19771 Park Avenue',
'Columbia');
COMMIT WORK;
UPDATE custmast SET cm_custname = 'KEYON DOOLING' WHERE cm_custnumb = '1003';
ECHO Issue a COMMIT WORK to commit changes and release locks
Java Quick Tour
All Rights Reserved 21 www.faircom.com
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
*/
Java Quick Tour
All Rights Reserved 22 www.faircom.com
Additional Resources
We encourage you to explore the additional resources listed here:
Complete SQL script for this tutorial can be found in SPTTutorial3.sql in your installation
directory, within the sql.stored.procs\tutorials directory for your platform. Example for the
Windows platform:
C:\FairCom\V*\win32\sdk\sql.stored.procs\tutorials\SPTTutorial3.sql
(If you are using c-treeRTG, adjust the path to match your version, e.g., V2.2.0.RTG, and
replace sdk with Driver.)
Additional documentation may be found on the FairCom Web site at: www.faircom.com.
Java Quick Tour
All Rights Reserved 23 www.faircom.com
3.3 Transaction Processing
..\sdk\sql.stored.procs\tutorials\SPTTutorial4.sql
If you are using c-treeRTG, adjust the path to match your version, e.g., V2.2.0.RTG, and replace
sdk with Driver.
Now we will discuss transaction processing as it relates to the c-treeACE SQL Stored Procedures
Technology.
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 ensures 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 these sections in our SQL Script:
-- Initialize
ECHO INIT;
-- Define
ECHO DEFINE;
-- Manage
ECHO MANAGE;
-- Done
ECHO DONE;
We suggest opening the source code with your own editor.
Continue now to review these four steps.
Java Quick Tour
All Rights Reserved 24 www.faircom.com
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():
SET ECHO OFF
-- Initialize
ECHO INIT;
SET AUTOCOMMIT OFF;
Java Quick Tour
All Rights Reserved 25 www.faircom.com
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():
DROP PROCEDURE Define;
CREATE PROCEDURE Define()
BEGIN
int TABLE_ALREADY_EXIST = -20041;
int INDEX_ALREADY_EXIST = -20028;
try
{
SQLIStatement cm = new SQLIStatement (
"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))"
);
cm.execute();
}
catch (DhSQLException e)
{
if (e.sqlErr != TABLE_ALREADY_EXIST)
throw e;
}
try
{
SQLIStatement cm1 = new SQLIStatement (
"CREATE INDEX cm_custnumb_idx ON custmast (cm_custnumb)"
);
cm1.execute();
}
catch (DhSQLException e)
{
if (e.sqlErr != INDEX_ALREADY_EXIST)
throw e;
}
try
{
SQLIStatement co = new SQLIStatement (
"CREATE TABLE custordr (" +
"co_ordrdate DATE, " +
"co_promdate DATE, " +
"co_ordrnumb CHAR(6), " +
"co_custnumb CHAR(4))"
Java Quick Tour
All Rights Reserved 26 www.faircom.com
);
co.execute();
}
catch (DhSQLException e)
{
if (e.sqlErr != TABLE_ALREADY_EXIST)
throw e;
}
try
{
SQLIStatement co1 = new SQLIStatement (
"CREATE INDEX co_ordrnumb_idx ON custordr (co_ordrnumb)"
);
co1.execute();
}
catch (DhSQLException e)
{
if (e.sqlErr != INDEX_ALREADY_EXIST)
throw e;
}
try
{
SQLIStatement co2 = new SQLIStatement (
"CREATE INDEX co_custnumb_idx ON custordr (co_custnumb)"
);
co2.execute();
}
catch (DhSQLException e)
{
if (e.sqlErr != INDEX_ALREADY_EXIST)
throw e;
}
try
{
SQLIStatement oi = new SQLIStatement (
"CREATE TABLE ordritem (" +
"oi_sequnumb SMALLINT, " +
"oi_quantity SMALLINT, " +
"oi_ordrnumb CHAR(6), " +
"oi_itemnumb CHAR(5))"
);
oi.execute();
}
catch (DhSQLException e)
{
if (e.sqlErr != TABLE_ALREADY_EXIST)
throw e;
}
try
{
SQLIStatement oi1 = new SQLIStatement (
"CREATE INDEX oi_ordrnumb_idx ON ordritem (oi_ordrnumb, oi_sequnumb)"
);
oi1.execute();
}
catch (DhSQLException e)
{
if (e.sqlErr != INDEX_ALREADY_EXIST)
throw e;
}
Java Quick Tour
All Rights Reserved 27 www.faircom.com
try
{
SQLIStatement oi2 = new SQLIStatement (
"CREATE INDEX oi_itemnumb_idx ON ordritem (oi_itemnumb)"
);
oi2.execute();
}
catch (DhSQLException e)
{
if (e.sqlErr != INDEX_ALREADY_EXIST)
throw e;
}
try
{
SQLIStatement im = new SQLIStatement (
"CREATE TABLE itemmast (" +
"im_itemwght INTEGER, " +
"im_itempric MONEY, " +
"im_itemnumb CHAR(5), " +
"im_itemdesc VARCHAR(47))"
);
im.execute();
}
catch (DhSQLException e)
{
if (e.sqlErr != TABLE_ALREADY_EXIST)
throw e;
}
try
{
SQLIStatement im1 = new SQLIStatement (
"CREATE INDEX im_itemnumb_idx ON itemmast (im_itemnumb)"
);
im1.execute();
}
catch (DhSQLException e)
{
if (e.sqlErr != INDEX_ALREADY_EXIST)
throw e;
}
END
-- Define
ECHO DEFINE;
CALL Define();
COMMIT WORK;
Java Quick Tour
All Rights Reserved 28 www.faircom.com
Manage
The manage step provides data management functionality for your application and/or process.
Below is the code for Manage():
DROP PROCEDURE Add_CustomerMaster_Record;
DROP PROCEDURE Add_CustomerOrders_Record;
DROP PROCEDURE Add_OrderItems_Record;
DROP PROCEDURE Add_ItemMaster_Record;
DROP PROCEDURE Delete_Records;
DROP TRIGGER Validate_CustomerOrders_Record;
DROP TRIGGER Validate_OrderItems_Record;
CREATE PROCEDURE Add_CustomerMaster_Record (
IN cm_custnumb CHAR(4),
IN cm_custzipc CHAR(9),
IN cm_custstat CHAR(2),
IN cm_custrtng CHAR(1),
IN cm_custname VARCHAR(47),
IN cm_custaddr VARCHAR(47),
IN cm_custcity VARCHAR(47)
)
BEGIN
SQLIStatement st = new SQLIStatement (
"INSERT INTO custmast VALUES (?,?,?,?,?,?,?)"
);
st.setParam (1, cm_custnumb);
st.setParam (2, cm_custzipc);
st.setParam (3, cm_custstat);
st.setParam (4, cm_custrtng);
st.setParam (5, cm_custname);
st.setParam (6, cm_custaddr);
st.setParam (7, cm_custcity);
st.execute();
END
CREATE PROCEDURE Add_CustomerOrders_Record (
IN co_ordrdate DATE,
IN co_promdate DATE,
IN co_ordrnumb CHAR(6),
IN co_custnumb CHAR(4)
)
BEGIN
SQLIStatement st = new SQLIStatement (
"INSERT INTO custordr VALUES (?,?,?,?)"
);
st.setParam (1, co_ordrdate);
st.setParam (2, co_promdate);
st.setParam (3, co_ordrnumb);
st.setParam (4, co_custnumb);
st.execute();
END
Java Quick Tour
All Rights Reserved 29 www.faircom.com
CREATE PROCEDURE Add_OrderItems_Record (
IN oi_sequnumb SMALLINT,
IN oi_quantity SMALLINT,
IN oi_ordrnumb CHAR(6),
IN oi_itemnumb CHAR(5)
)
BEGIN
SQLIStatement st = new SQLIStatement (
"INSERT INTO ordritem VALUES (?,?,?,?)"
);
st.setParam (1, oi_sequnumb);
st.setParam (2, oi_quantity);
st.setParam (3, oi_ordrnumb);
st.setParam (4, oi_itemnumb);
st.execute();
END
CREATE PROCEDURE Add_ItemMaster_Record (
IN im_itemwght INTEGER,
IN im_itempric MONEY,
IN im_itemnumb CHAR(5),
IN im_itemdesc VARCHAR(47)
)
BEGIN
SQLIStatement st = new SQLIStatement (
"INSERT INTO itemmast VALUES (?,?,?,?)"
);
st.setParam (1, im_itemwght);
st.setParam (2, im_itempric);
st.setParam (3, im_itemnumb);
st.setParam (4, im_itemdesc);
st.execute();
END
CREATE TRIGGER Validate_CustomerOrders_Record
BEFORE INSERT ON custordr
REFERENCING NEWROW
FOR EACH ROW
BEGIN
SQLCursor cur = new SQLCursor ("SELECT cm_custnumb FROM custmast WHERE cm_custnumb = ?");
String custnumb = (String) NEWROW.getValue(4, CHAR);
cur.setParam(1, custnumb);
cur.open();
cur.fetch();
if (!cur.found())
{
cur.close();
DhSQLException ex = new DhSQLException (666, new String("Invalid customer number"));
throw ex;
}
cur.close();
END
CREATE TRIGGER Validate_OrderItems_Record
BEFORE INSERT ON ordritem
REFERENCING NEWROW
FOR EACH ROW
BEGIN
SQLCursor cur = new SQLCursor ("SELECT co_ordrnumb FROM custordr WHERE co_ordrnumb = ?");
Java Quick Tour
All Rights Reserved 30 www.faircom.com
String ordrnumb = (String) NEWROW.getValue(3, CHAR);
cur.setParam(1, ordrnumb);
cur.open();
cur.fetch();
if (!cur.found())
{
cur.close();
DhSQLException ex = new DhSQLException (666, new String("Invalid order number"));
throw ex;
}
cur.close();
cur = new SQLCursor ("SELECT im_itemnumb FROM itemmast WHERE im_itemnumb = ?");
String itemnumb = (String) NEWROW.getValue(4, CHAR);
cur.setParam(1, itemnumb);
cur.open();
cur.fetch();
if (!cur.found())
{
cur.close();
DhSQLException ex = new DhSQLException (666, new String("Invalid item number"));
throw ex;
}
cur.close();
END
CREATE PROCEDURE Delete_Records (
IN tablename CHAR(256)
)
BEGIN
SQLIStatement st = new SQLIStatement (
"DELETE FROM " + tablename
);
st.execute();
END
-- Manage
ECHO MANAGE;
ECHO Delete records...;
CALL Delete_Records('custmast');
CALL Delete_Records('custordr');
CALL Delete_Records('ordritem');
CALL Delete_Records('itemmast');
ECHO Add records...;
CALL Add_CustomerMaster_Record('1000', '92867', 'CA', '1', 'Bryan Williams', '2999 Regency',
'Orange');
CALL Add_CustomerMaster_Record('1001', '61434', 'CT', '1', 'Michael Jordan', '13 Main',
'Harford');
CALL Add_CustomerMaster_Record('1002', '73677', 'GA', '1', 'Joshua Brown', '4356 Cambridge',
'Atlanta');
CALL Add_CustomerMaster_Record('1003', '10034', 'MO', '1', 'Keyon Dooling', '19771 Park Avenue',
'Columbia');
CALL Add_ItemMaster_Record(10, 19.95, '1', 'Hammer');
CALL Add_ItemMaster_Record(3, 9.99, '2', 'Wrench');
CALL Add_ItemMaster_Record(4, 16.59, '3', 'Saw');
Java Quick Tour
All Rights Reserved 31 www.faircom.com
CALL Add_ItemMaster_Record(1, 3.98, '4', 'Pliers');
COMMIT WORK;
CALL Add_CustomerOrders_Record ('09/01/2002', '09/05/2002', '1', '1001');
CALL Add_OrderItems_Record (1, 2, '1', '1');
CALL Add_OrderItems_Record (2, 1, '1', '2');
CALL Add_CustomerOrders_Record ('09/02/2002', '09/06/2002', '2', '9999');
ECHO NOTE: trigger execution failure expected
CALL Add_OrderItems_Record (1, 1, '2', '3');
ECHO NOTE: trigger execution failure expected
CALL Add_OrderItems_Record (2, 3, '2', '4');
ECHO NOTE: trigger execution failure expected
CALL Add_CustomerOrders_Record ('09/22/2002', '09/26/2002', '3', '1003');
CALL Add_OrderItems_Record (1, 2, '3', '3');
CALL Add_OrderItems_Record (2, 2, '3', '99');
ECHO NOTE: trigger execution failure expected
COMMIT WORK;
SELECT co_ordrnumb "Order", co_custnumb "Name" FROM custordr;
SELECT oi_ordrnumb "Order", oi_itemnumb "Item" FROM ordritem;
Java Quick Tour
All Rights Reserved 32 www.faircom.com
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
ECHO DONE;
DROP TRIGGER Validate_CustomerOrders_Record;
DROP TRIGGER Validate_OrderItems_Record;
COMMIT WORK;
Java Quick Tour
All Rights Reserved 33 www.faircom.com
Additional Resources
We encourage you to explore the additional resources listed here:
Complete SQL script for this tutorial can be found in SPTTutorial4.sql in your installation
directory, within the sql.stored.procs\tutorials directory for your platform. Example for the
Windows platform:
C:\FairCom\V*\win32\sdk\sql.stored.procs\tutorials\SPTTutorial4.sql
(If you are using c-treeRTG, adjust the path to match your version, e.g., V2.2.0.RTG, and
replace sdk with Driver.)
Additional documentation may be found on the FairCom Web site at: www.faircom.com.
All Rights Reserved 34 www.faircom.com
4. NetBeans Plugin for Java
c-treeACE SQL has supported basic procedural development leveraging Java due to its language
flexibility and cross-platform feature. While very complex procedure development was possible, a
full-featured development environment was not easily supported.
NetBeans is a complete and easy-to-use IDE for Java developers, which provides a natural
framework for Java stored procedure development. FairCom now provides a NetBeans plug-in
enhancing stored procedure development and testing. This includes expected modern features
such as syntax checking and in-line debugging.
This plug-in allows developers to compile and test Java procedure code via a client-side interface
and deploy final procedure code to the server. Debugging within the IDE is possible by retrieving
procedure source code from the server. It is not necessary to provide a full JDK on the server as
development can now be centralized at the developer workstation.
4.1 Setting up the Connection to the Server
To set up the connection to the server:
1. In NetBeans, click the Window menu and select Services.
2. Open the Databases branch. Create an entry called ctreeACE JDBC for Stored Procedures, which should use the c-treeJDBC driver.
NetBeans Plugin for Java
All Rights Reserved 35 www.faircom.com
3. Right-click on ctreeACE JDBC for Stored Procedures and set its properties as shown below:
Verify the "Database URL" (also commonly known in SQL terms as the connection string).
The format is as follows:
jdbc:ctree:port@host_name:db_name
The string is made of the following components:
• jdbc:ctree - An identifying protocol and subprotocol string for the c-treeACE SQL JDBC
Driver.
• :port - The port number associated with the c-treeACE SQL server on the host system
(e.g., 6597).
• @host - The name of the server system where the database resides (@localhost is
default)
• :dbname - This is the c-treeACE SQL database name (see SQL_DATABASE in ctsrvr.cfg)
or any applicable database registered with the c-treeACE SQL database, such as
ctreeSQL.
The default will be:
jdbc:ctree:6597@localhost:ctreeSQL
4. Double-click on ctreeACE JDBC for Stored Procedures. The icon should become "unbroken."
NetBeans Plugin for Java
All Rights Reserved 36 www.faircom.com
4.2 Installing the NetBeans Plugin
To install the plugin in NetBeans:
1. From the Tools menu, select Plugins. On the Downloaded tab click Add Plugins.
2. Look for FairCom-SP-NetBeans.nbm located in:
\FairCom\V10.4.0\win32\sdk\sql.stored.procs\netbeans
Select it and click Open.
You will see two .NBN files. Install both.
3. Click Install.
NetBeans Plugin for Java
All Rights Reserved 37 www.faircom.com
4.3 Editing Stored Procedures
To edit stored procedures in NetBeans:
1. Create a new project using File > New Project.
2. In Categories, select FairCom and in Projects select Stored Procedures & ... then click Next. Update the project name and location information as you desire then click Next.
3. Select the desired JDBC connection for the project to be able to deploy and retrieve stored procedures. This selection can be changed later in the project properties under FairCom Server.
4. Click Finish.
5. Create a new stored procedure using these steps:
a. Right-click the project and select New then select Other (if the project is not already listed).
NetBeans Plugin for Java
All Rights Reserved 38 www.faircom.com
b. Click Categories > FairCom > File types and select the appropriate type for the project you desire to build (e.g., FairCom Stored Procedure). Follow the wizard for additional steps.
c. Write the code for your stored procedure.
Note: Stored procedure names are case-sensitive (as is any other database object). To
NetBeans Plugin for Java
All Rights Reserved 39 www.faircom.com
reference a case, you need to quote it as is done for other identifiers. For example: CALL "Tutorial1"()
6. Import the project from the server by right-clicking on the project stored_proc package and clicking Import from server.
4.4 Enabling Debugging
To debug a stored procedure, add the following keywords to ctsrvr.cfg. Be sure to restart the
c-treeACE Database Server so these changes will take effect.
;JAVA DEBUG
SETENV DEBUG_JVM=S
SETENV DEBUG_JVM_PORT=45987
All Rights Reserved 40 www.faircom.com
5. Using Java Stored Procedures
5.1 Introduction
This chapter describes basic stored procedure operations (such as creating and deleting) and
provides a tutorial on using supplied c-treeACE SQL classes. See Java Class Reference (page
74) for detailed reference information on the classes and their methods.
Stored procedures extend the SQL capabilities of a database by adding control flow through Java
program constructs that enforce business rules and perform administrative tasks.
Stored procedures can take advantage of the power of Java programming features. Stored
procedures can:
Receive and return input and output parameters
Handle exceptions
Include any number and kind of SQL statements to access the database
Return a procedure result set to the calling application
Make calls to other procedures
Use predefined and external Java classes
c-treeACE SQL provides support for SQL statements in Java through several classes. The
following table summarizes the functionality of these c-treeACE SQL - supplied classes. (See
Java Class Reference (page 74) for detailed reference information.)
Summary of c-treeSQL Java Classes
Functionality c-treeACE SQL Java Class
Immediate (one-time) execution of c-treeACE SQL statements
SQLIStatement
Prepared (repeated) execution of c-treeACE SQL statements
SQLPStatement
Retrieval of c-treeACE SQL result sets SQLCursor
Returning a procedure result set to the application DhSQLResultSet
Exception handling for c-treeACE SQL statements DhSQLException
5.2 Stored Procedure Basics
This section discusses how to get started writing stored procedures.
Using Java Stored Procedures
All Rights Reserved 41 www.faircom.com
The c-treeACE SQL CREATE PROCEDURE statement provides the basic framework for stored
procedures. Use the CREATE PROCEDURE statement to submit a Java code snippet that will be
compiled and stored in the database. The syntax for the CREATE PROCEDURE statement is:
CREATE PROCEDURE [ owner_name. ] procname
( [ parameter_decl [ , ... ] ) ] ]
[ RESULT ( column_name data_type [ , ... ] ) ]
[ IMPORT
java_import_clause ]
BEGIN
java_snippet
END
parameter_decl ::
{ IN | OUT | INOUT } parameter_name data_type
Note: When creating stored procedures, the key words BEGIN, RESULT, IMPORT and END
should start at the first column of the line.
What Is a Java Snippet?
The core of the stored procedure is the Java snippet. The snippet contains a sequence of Java
statements. When it processes a CREATE PROCEDURE statement, c-treeACE SQL adds header
and footer “wrapper” code to the Java snippet. This wrapper code:
Declares a class with the name username_procname_SP (username is the user name of the
database connection that issued the CREATE PROCEDURE statement and procname is the
name supplied in the CREATE PROCEDURE statement).
Declares a method within that class that includes the Java snippet.
When an application calls the stored procedure, c-treeACE SQL calls the Java virtual machine to
invoke the method of the username_procname_SP class.
Structure of Stored Procedures
There are two parts to any stored procedure:
The procedure specification must provide the name of the procedure and may include
other optional clauses.
The procedure body contains the Java code that executes when an application invokes the
procedure.
A simple stored procedure requires only the procedure name in the specification and a statement
that requires no parameters in the body, as shown in the following example. The procedure in the
following example assumes a table called HelloWorldTBL exists, and inserts a string into that
table.
Using Java Stored Procedures
All Rights Reserved 42 www.faircom.com
A Simple Stored Procedure Example
CREATE PROCEDURE HelloWorld () Procedure Specification
BEGIN
SQLIStatement Insert_HelloWorld
= new SQLIStatement (“INSERT INTO
HelloWorldTBL(fld1) values
('Hello World!')”);
Insert_HelloWorld.execute();
END
Procedure Body
From the Interactive SQL utility, isql, you could execute the procedure as follows:
ISQL> CREATE TABLE helloworldTBL (fld1 CHAR(100));
ISQL> CALL HelloWorld();
0 records returned
ISQL> SELECT * FROM helloworldTBL;
FLD1
----
Hello World!
1 record selected
The procedure specification can also contain other optional clauses:
Parameter declarations specify the name and type of parameters that the calling application
will pass and receive from the procedure. Parameters can be of type input, output, or both.
The procedure result set declaration details the names and types of fields in a result set the
procedure generates. The result set is a set of rows that contain data generated by the
procedure. If a procedure retrieves rows from a database table, for instance, it can store the
rows in a result set for access by applications and other procedures.
Note: names specified in the result-set declaration are not used within the stored procedure body. Instead, methods of the c-treeACE SQL Java classes refer to fields in the result set by ordinal number, not by name.)
The import clause specifies which packages the procedure needs from the Java core API.
By default, the Java compiler imports the java.lang package. The IMPORT clause must list
any other packages the procedure uses.
The following example shows a more complex procedure specification that contains these
elements.
Using Java Stored Procedures
All Rights Reserved 43 www.faircom.com
Complete Stored Procedure Example
CREATE PROCEDURE new_sal
(IN deptnum INTEGER, Parameter
IN pct_incr INTEGER) } declarations
RESULT
(empname CHAR(20), Procedure result
oldsal NUMERIC, } set declaration
newsal NUMERIC)
IMPORT
import java.dbutils.SequenceType; } Import clause
Procedure Specification
BEGIN
.
.
.
END
Procedure Body
Setting Up Your Environment to Write Stored Procedures
Before you create stored procedures, you need to have a Java development environment running
on your system. c-treeACE SQL stored procedures support the following environments:
On Unix and Windows XP/2003/Vista: JavaSoft JDK™ Version 1.5
Specific c-treeACE SQL configuration options set the environment related paths required to
enable stored procedure support.
Java Related Configuration Options
Configuration Option (ctsrvr.cfg)
Example Configuration (Windows)
SETENV CLASSPATH SETENV CLASSPATH=C:\Program
Files\Java\jdk1.6.0_13\jre\lib\rt.jar;C:\FairCo
m\V9.1.0\win32\bin\ace\sql\classes\ctreeSQLSP.j
ar
SETENV JVM_LIB SETENV JVM_LIB=C:\Program
Files\Java\jdk1.6.0_13\jre\bin\server\jvm.dll
Using Java Stored Procedures
All Rights Reserved 44 www.faircom.com
Configuration Option (ctsrvr.cfg)
Example Configuration (Windows)
SETENV JAVA_COMPILER SETENV JAVA_COMPILER=C:\Program
Files\Java\jdk1.6.0_13\bin\javac.exe
Note: The JAVA_COMPILER configuration option is only required to submit and compile stored
procedures. It is not necessary to specify this option for calling and executing already compiled
procedures.
Writing Stored Procedures
Use any text editor to write the CREATE PROCEDURE statement, and save the source code as a
text file. That way, you can easily modify the source code and try again if it generates syntax or
Java compilation errors.
Submit the file containing the CREATE PROCEDURE statement to interactive SQL as a script, as
shown in the following example.
Submitting Scripts to Create Stored Procedures
$ type helloworldscript.sql
SET ECHO ON;
SET AUTOCOMMIT OFF;
CREATE PROCEDURE HelloWorld ()
BEGIN
SQLIStatement Insert_HelloWorld = new SQLIStatement
("INSERT INTO HelloWorldTBL(fld1) values ('Hello World!')");
Insert_HelloWorld.execute();
END
commit work;
$ isql -s hello_world_script.sql example_db
SET AUTOCOMMIT OFF;
CREATE PROCEDURE HelloWorld ()
BEGIN
SQLIStatement Insert_HelloWorld = new
SQLIStatement ("INSERT INTO HelloWorld(fld1)
values ('Hello World!')");
Insert_HelloWorld.execute();
END
;
commit work;
$
Keep in mind that the Java snippet within the CREATE PROCEDURE statement does not execute
as a standalone program. Instead, it executes in the context of an application call to the method
of the class created by c-treeACE SQL. This characteristic has the following implications:
It is meaningless for a snippet to declare a main method, since it will never be executed.
If the snippet declares any classes, it must instantiate them within the snippet to invoke their
methods.
Using Java Stored Procedures
All Rights Reserved 45 www.faircom.com
c-treeACE SQL redirects the standard output stream to a file, sql_server.log. Method
invocations such as System.out.println() will not display messages on the screen, however,
instead writes to that file.
The Java System.exit() call is not allowed.
Invoking Stored Procedures
How applications call stored procedures depends on their environment.
From the Interactive SQL utility, isql, simply issue the c-treeACE SQL CALL statement. The
following example shows the CALL statement that invokes the order_parts stored procedure,
using a literal value instead of a parameter marker.
Invoking a Stored Procedure from Interactive SQL CALL order_parts (318);
Calling Stored Procedures from ODBC
From ODBC, applications use the ODBC call escape sequence:
{ call proc_name [ ( parameter [ , ... ] ) ] }
Use parameter markers (question marks used as placeholders) for input or output parameters to
the procedure. You can also use literal values for input parameters only. c-treeACE SQL stored
procedures do not support return values in the ODBC escape sequence. See the Microsoft
ODBC Programmer’s Reference, Version 3.0, for more detail on calling procedures from ODBC
applications.
Embed the escape sequence in an ODBC SQLExecDirect() call to execute the procedure. The
following example shows a call to a stored procedure named order_parts that passes a single
input parameter using a parameter marker.
Invoking a Stored Procedure from an ODBC Application
SQLUINTEGER Part_num;
SQLINTEGER Part_numInd = 0;
// Bind the parameter.
SQLBindParameter (hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0,
&Part_num, 0, Part_numInd);
// Place the department number in Part_num.
Part_num = 318;
// Execute the statement.
SQLExecDirect(hstmt, "{call order_parts(?)}", SQL_NTS);
Calling Stored Procedures from JDBC
The JDBC call escape sequence is the same as in ODBC:
{ call proc_name [ ( parameter [ , ... ] ) ] }
Using Java Stored Procedures
All Rights Reserved 46 www.faircom.com
Embed the escape sequence in a JDBC CallableStatement.prepareCall() method invocation.
The following example shows the JDBC code parallel to the ODBC code excerpt shown in the
previous example.
Invoking a Stored Procedure from a JDBC Application
try {
CallableStatement statement;
int Part_num = 318;
// Associate the statement with the procedure call
// (conn is a previously-instantiated connection object)
statement = conn.prepareCall("{call order_parts(?)}");
// Bind the parameter.
statement.setInt(1, Part_num);
// Execute the statement.
statement.execute();
}
Calling Stored Procedures from .NET
From .NET applications, use the CtreeSqlCommand() object to execute stored procedures. The
following example illustrates use of a stored procedure with parameters.
Invoking a Stored Procedure from a .Net Application
// Create a new connection object.
String conString = "User=ADMIN;Password=ADMIN;Database=ctreeSQL";
CtreeSqlConnection hConnection = new CtreeSqlConnection(conString);
// Open the connection.
hConnection.Open();
// Create a new command object.
CtreeSqlCommand hCommand = new CtreeSqlCommand(hConnection);
hCommand.CommandText = "order_parts";
// Set the command type.
hCommand.CommandType = CommandType.StoredProcedure;
// Construct a parameter and add to the command.
CtreeSqlParameter param1 = hCommand.Parameters.Add("part_num", CtreeSqlDbType.Integer);
// Set the value for part number.
param1.Value = 318;
// Execute the command and create a DataReader object.
CtreeSqlDataReader hReader = hCommand.ExecuteReader();
Using Java Stored Procedures
All Rights Reserved 47 www.faircom.com
Calling Stored Procedures from ISQL
From interactive SQL, simply issue a SQL CALL statement. The following example demonstrates
how a CALL statement invokes an order_parts stored procedure, using a literal value instead of a
parameter marker.
Example
Invoking a Stored Procedure from Interactive SQL
CALL order_parts (318);
For an example of executing a stored procedure using parameters from Interactive SQL see
section 1.4 of the ISQL and Tools Reference Manual.
A stored procedure can be used in place of a table reference in a SQL SELECT statement if the
stored procedure meets certain criteria:
• The stored procedure must return a result set.
• The stored procedure may not have any IN/OUT parameters or any OUTPUT parameters
Example
As a Tabled Valued Function in a SELECT Statement
select * from myproc() where col1 < 20;
Modifying and Deleting Stored Procedures
There is no “ALTER PROCEDURE” statement. To modify a procedure, you will need to drop and
recreate it. To recreate the procedure, you need the original source of the CREATE PROCEDURE
statement. Before you drop the procedure, decide which approach you will use to recreate it:
If you kept the original procedure definition in an c-treeACE SQL script file, simply edit the file
and resubmit it through interactive SQL.
Query system tables to extract the source of the CREATE PROCEDURE statement to a file.
The c-treeACE SQL DROP PROCEDURE statement deletes stored procedures from the database.
Exercise care in dropping procedures, since any procedure that calls the dropped procedure will
fail.
Debugging Stored Procedures
Compiling Errors
If there’s a Java compilation error, c-treeACE SQL returns the error at create time and does not
create the procedure.
Note: If the compilation of the procedure fails, c-treeACE SQL returns only the first error to the calling application.
The following example invokes an ISQL script that attempts to create a procedure that fails and
generates a Java compilation error.
Using Java Stored Procedures
All Rights Reserved 48 www.faircom.com
Example C:\example_scripts>type type_mismatch.sql
CREATE PROCEDURE error_proc()
BEGIN
Double dbl_val;
Integer int_val = new Integer(1234);
dbl_val = int_val;
END
C:\example_scripts>isql -s type_mismatch.sql testdb
error(-20141): error in compiling the stored procedure
:03: Incompatible type for =. Can't convert java.lang.Integer to java.lang.Double.
At run time, c-treeACE SQL creates a log file, sql_server.log.
Run Time
Custom message logging can be added with the log() and err() methods which write a
character-string message to the SQL log file, sql_server.log.
Note: The log() method is not logged to sql_server.log by default and is intended for development use. Calling log() includes internal details useful in procedure design and should be disabled in production. Enable Java debugging with the c-treeACE SQL debugging flags configuration option:
SETENV TPESQLDBG=NNNNNNNNNNYN
The SQL Explorer tool has an -adv command-line switch to enable setting specific debug flags
and will be found on the File menu option as Debug Flags. Check the Java checkbox and click Set.
You can include the values of variables or return values of methods in the string using the
standard Java concatenation operator (+) as shown in the following example.
Example
SQLCursor select_syscalctable = new SQLCursor (
"SELECT fld FROM ADMIN.syscalctable ");
select_syscalctable.open();
select_syscalctable.fetch();
err ("Any records? Found returned " + select_syscalctable.found());
.
.
.
The err() invocation in the previous example writes the following line to the sql_server.log file:
Any records? Found returned true
Using Java Stored Procedures
All Rights Reserved 49 www.faircom.com
V11 Changes to Stored Procedure Server-side Debugging
Server-side stored procedure execution logging can now be turned on and off using the
TPESQLDBG environment variable. TPESQLDBG is an array of 'Y'/'N' characters that determine
which debug options are enabled.
Prior to this revision, this was achieved by setting the 11th element (offset 10, java_debug) in
the TPESQLDBG environment variable. The logging produced in this way is quite verbose and
included information that was useful only to FairCom Technicians.
The interpretation of TPESQLDBG (and other methods setting the same debug features) has
been modified as follows:
TPESQLDBG (which was an array of 12 'Y'/'N' characters) has been expanded to 13
elements.
The element at offset 12 is a new element named stp_logging that controls the "log"
method used in stored procedures to generate log messages.
Note that activating element #11 (java_debug) activates internal logging and "log" method for
ANY stored procedure language, not just Java.
Transactions and Stored Procedures
Any updates done by a stored procedure become part of the transaction that called the
procedure. The transaction behavior is similar to executing the sequence of c-treeACE SQL
statements in the procedure directly by the calling application.
Stored procedures cannot contain COMMIT or ROLLBACK statements.
Stored Procedure Security
Users issuing the CREATE PROCEDURE statement must have the DBA privilege or
RESOURCE privilege.
The owner or users with the DBA privilege can execute or drop any stored procedure, and
grant the EXECUTE privilege to other users.
When a procedure is being executed on behalf of a user with EXECUTE privilege on that
procedure, for the objects that are accessed by the procedure, the procedure owner’s
privileges are checked and not the user’s. This enables a user to execute a procedure
successfully even when he does not have the privileges to directly access the objects that are
accessed by the procedure, so long as he has EXECUTE privilege on the procedure.
Restrictions on Calling Java Methods in Stored Procedures
Java stored procedures cannot use the System.exit() method. Calling this method in Stored
Procedure body results in a compilation error.
Using Java Stored Procedures
All Rights Reserved 50 www.faircom.com
5.3 Using c-treeACE SQL Java Classes
This section describes how to use included c-treeACE SQL Java classes to issue and process
c-treeACE SQL statements in Java stored procedures. c-treeACE SQL Java classes are found in
the ctreeSQLSP.jar file located in the C:\FairCom\V9.1.0\win32\bin\ace\sql\classes directory of
your c-treeACE installation.
To process c-treeACE SQL statements in a stored procedure, you need to know whether the SQL
statement generates results (in other words, if the statement is a query) or not. SELECT
statements, for example, generate results: they retrieve data from one or more database tables
and return the results as rows in a table.
Whether a statement generates such an SQL result set dictates which c-treeACE SQL Java
classes you use to issue it:
To issue c-treeACE SQL statements that do not generate results (such as INSERT, GRANT,
or CREATE), use either the SQLIStatement class (for one-time execution) or the
SQLPStatement class (for repeated execution).
To issue c-treeACE SQL statements that generate results (SELECT and, in some cases,
CALL), use the SQLCursor class to retrieve rows from a database or another procedure’s
result set.
In either case, if you want to return a result set to the application, use the DhSQLResultSet class
to store rows of data in a procedure result set. You must use DhSQLResultSet() methods to
transfer data from an SQL result set to the procedure result set for the calling application to
process it. You can also use DhSQLResultSet() methods to store rows of data generated
internally by the procedure.
In addition, c-treeACE SQL provides the DhSQLException class so procedures can process and
generate Java exceptions through the standard Java try { }, catch { }, and throw { } constructs.
Passing Values to SQL Statements
Stored procedures need to be able to pass and receive values from c-treeACE SQL statements
they execute. They do this through the setParam() and getValue() methods.
The setParam Method: Pass Input Values to SQL Statements
The setParam() method sets the value of a c-treeACE SQL statement’s parameter marker to the
specified value (a literal, a procedure variable, or a procedure input parameter).
The setParam() method takes two arguments:
setParam ( marker_num , value ) ;
marker_num is an integer that specifies which parameter marker in the SQL statement is to
receive the value (1 denotes the first parameter marker, 2 denotes the second, and so on).
value is a literal or the name of a variable or input parameter that contains the value to be
assigned to the parameter marker.
The following example shows an excerpt from a stored procedure that uses setParam() to assign
values from two procedure variables to the parameter markers in an SQL INSERT statement.
When the procedure executes, it substitutes the value of the cust_number procedure variable for
Using Java Stored Procedures
All Rights Reserved 51 www.faircom.com
the first parameter marker and the value of the cust_name variable for the second parameter
marker.
setParam() and c-treeACE SQL Statement Input Parameters
SQLIStatement insert_cust = new SQLIStatement (
"INSERT INTO customer VALUES (?,?) ");
insert_cust.setParam (1, cust_number);
insert_cust.setParam (2, cust_name);
.
.
.
The getValue Method: Pass Values from SQL Result Sets to Variables
The getValue() method of the SQLCursor class assigns a single value from an SQL result set
(returned by an SQL query or another stored procedure) to a procedure variable or output
parameter.
The format and arguments for getValue() are as follows:
getValue ( col_num , data_type ) ;
The getValue() interface returns an object, it should be explicitly typecasted to appropriate type.
col_num is an integer that specifies which column of the result set is of interest. getValue()
retrieves the value in the currently-fetched record of the column denoted by col_num. (1
denotes the first column of the result set, 2 denotes the second, and so on).
data_type specifies the expected c-treeACE SQL type of the returned parameter (see Implicit
Data Type Conversion Between SQL and Java Types (page 53) for details on how c-treeACE
SQL data types map to Java data types).
The following example shows an excerpt from a stored procedure that uses getValue() to assign
values from two result-set columns to procedure variables. In this example, the result set is
generated by a c-treeACE SQL SELECT statement.
Using getValue() to Pass Values from Result Sets
StringBuffer ename = new StringBuffer (20) ;
java.math.BigDecimal esal = new java.math.BigDecimal () ;
SQLCursor empcursor = new SQLCursor (
"SELECT name, sal FROM emp " ) ;
empcursor.open () ;
empcursor.fetch ();
if (empcursor.found ())
{
ename = (StringBuffer)empcursor.getValue (1, CHAR);
esal = (BigDecimal)empcursor.getValue (2, DECIMAL);
.
.
.
Using Java Stored Procedures
All Rights Reserved 52 www.faircom.com
In the SELECT statement in previous example, it was clear that the result set had two columns,
name and sal. If the SELECT statement had used a wildcard in its select list (SELECT * FROM
EMP) you have to know the structure of the EMP table in order to correctly specify the column
numbers in the getValue() method.
Passing Values to and From Stored Procedures: Input and Output
Parameters
Applications need to pass and receive values from the stored procedures they call. They do this
through input and output parameters declared in the procedure specification.
Applications can pass and receive values from stored procedures using input and output
parameters declared in the stored procedure specification. When it processes the CREATE
PROCEDURE statement, c-treeACE SQLc-treeACE SQL declares Java variables of the same
name. This means the body of the stored procedure can refer to input and output parameters as if
they were Java variables declared in the body of the stored procedure.
Note: Procedure result sets are another way for applications to receive output values from a stored procedure. Procedure result sets provide output in a row-oriented tabular format. See Returning a Procedure Result Set: the RESULT Clause and DhSQLResultSet (page 59).
Parameter declarations include the parameter type (IN, OUT, or INOUT), the parameter name,
and c-treeSQL data type (see Implicit Data Type Conversion Between SQL and Java Types
(page 53) for details of how c-treeACE SQL data types map to Java data types).
Declare input and output parameters in the specification section of a stored procedure, as shown
in the following example.
Example Input, Output, and Input-Output Parameters
CREATE PROCEDURE order_entry (
IN cust_name CHAR(20),
IN item_num INTEGER,
IN quantity INTEGER,
OUT status_code INTEGER,
INOUT order_num INTEGER
)
.
.
.
Note: The input parameter cust_name in the procedure above should be of type CHAR in ANSI
versions of c-treeACE SQL.
When the order_entry stored procedure executes, the calling application passes values for the
cust_name, item_num, quantity, and order_num input parameters. The body of the procedure
refers to them as Java variables. Similarly, Java code in the body of order_entry processes and
returns values in the status_code and order_num output parameters. The variable order_num can
be used for both passing input and receiving output value from the procedure.
Using Java Stored Procedures
All Rights Reserved 53 www.faircom.com
Note: Procedure parameter names should always be lower case as arameter names are treated as identifiers in the c-treeACE SQL statement and are converted to lowercase by c-treeACE SQL. Parameter names used within the procedure body are not converted to lower case. Hence declaring parameters with upper case may lead to compilation errors.
Implicit Data Type Conversion Between SQL and Java Types
When c-treeACE SQL creates a stored procedure, it converts the type of any input and output
parameters (see The setParam Method: Pass Input Values to SQL Statements (page 50)) from
the c-treeACE SQL data types in the procedure specification to Java wrapper types.
The Java.lang package defines classes for all the primitive Java types that “wrap” values of the
corresponding primitive type in an object. c-treeACE SQL converts the c-treeACE SQL data types
declared for input and output parameters to one of these wrapper types, described Mapping
Between SQL and Java Data Types.
You must be sure to use wrapper types when declaring procedure variables to use as arguments
to the getValue(), setParam(), and set methods. These methods take objects as arguments and
will generate compilation errors if you pass a primitive type to them.
The following example shows two stored procedures. The first tries to use a variable declared as
the Java int primitive type as an argument to the SQLResultSet.set() method, and will generate a
compilation error. The second correctly declares the variable using the integer wrapper class.
Using Wrapper Types as Arguments to c-treeACE SQL Classes
CREATE PROCEDURE type_mismatch( )
RESULT (res_int INTEGER )
BEGIN
// Create a variable as (primitive) type int
// to test the working of set method of SQLResultSet
int pvar_int = 4;
// Transfer the value from the procedure variable to the result set.
SQLResultSet.set(1,pvar_int); //Error!
// Insert the row into the procedure result set.
SQLResultSet.insert();
END
CREATE PROCEDURE type_okmatch( )
RESULT (res_int INTEGER )
BEGIN
// Create a variable as (wrapper) type Integer
Integer pvar_int = new Integer(4);
// Transfer the value from the procedure variable to the result set.
SQLResultSet.set(1,pvar_int); //Success!
// Insert the row into the procedure result set.
SQLResultSet.insert();
END
When the SQL engine submits the Java class it creates from the stored procedure to the Java
compiler, the compiler checks for data-type consistency between the converted parameters and
variables you declare in the body of the stored procedure.
Using Java Stored Procedures
All Rights Reserved 54 www.faircom.com
To avoid type mismatch errors, use the data-type mappings shown in the following table for
declaring parameters and result-set fields in the procedure specification and the Java variables in
the procedure body.
SQL Type Java Wrapper Type Enumeration Type
CHAR String CHAR
NCHAR String NCHAR
VARCHAR String VARCHAR
LONGVARCHAR String LONGVARCHAR
NVARCHAR String NVARCHAR
NUMERIC java.math.BigDecimal NUMERIC
DECIMAL java.math.BigDecimal DECIMAL
MONEY java.math.BigDecimal MONEY
BIT Boolean BIT
TINYINT byte[1] TINYINT
SMALLINT Integer SMALLINT
INTEGER Integer INTEGER
BIGINT Long BIGINT
REAL Float REAL
FLOAT Double FLOAT
DOUBLE PRECISION Double DOUBLE
BINARY byte[ ] BINARY
VARBINARY byte[ ] VARBINARY
LONGVARBINARY byte[ ] LONGVARBINARY
DATE java.sql.Date DATE
TIME java.sql.Time TIME
TIMESTAMP java.sql.Timestamp TIMESTAMP
Executing an SQL Statement
If a c-treeACE SQL statement does not generate a result set, stored procedures can execute it in
one of two ways:
Immediate execution, using methods of the SQLIStatement class, executes a statement
once.
Prepared execution, using methods of the SQLPStatement class, prepares a statement so
you can execute it multiple times in a procedure loop.
Both SQLIStatement and SQLPStatement classes can be used to call stored procedures that do
not have a RESULT clause (that is, the JSPs that do not return any resultset). Note that values of
Using Java Stored Procedures
All Rights Reserved 55 www.faircom.com
OUT and INOUT arguments can be retrieved using the getParam() method of SQLIStatement,
SQLPStatement, and SQLCursor.
The following table shows the SQL statements that do not generate result sets. You can execute
these statements in a stored procedure using either the SQLIStatement or SQLPStatement class.
Executable SQL Statements
ALTER TABLE DROP PROCEDURE
CALL (if no result set) DROP TABLE
CREATE INDEX DROP TRIGGER
CREATE SYNONYM DROP VIEW
CREATE PROCEDURE GRANT
CREATE TABLE INSERT
CREATE TRIGGER RENAME
CREATE VIEW REVOKE
DELETE UPDATE
DROP INDEX UPDATE STATISTICS
DROP SYNONYM
Immediate Execution
Use immediate execution when a procedure needs to execute an SQL statement only once. The
following example shows an instance of immediate execution.
Immediate Execution Example
CREATE PROCEDURE insert_customer (
IN cust_number INTEGER,
IN cust_name CHAR(20)
)
BEGIN
SQLIStatement insert_cust = new SQLIStatement (
"INSERT INTO customer VALUES (?,?) ");
insert_cust.setParam (1, cust_number);
insert_cust.setParam (2, cust_name);
insert_cust.execute ();
END
Note: The input parameter cust_name in the procedure above should be of type CHAR in ANSI
versions of c-treeACE SQL.
This example inserts a row in a table. The constructor for SQLIStatement() takes the c-treeACE
SQL INSERT statement as its only argument. In this example, the statement includes two
parameter markers.
Using Java Stored Procedures
All Rights Reserved 56 www.faircom.com
Prepared Execution
Use prepared execution when you need to execute the same SQL statement repeatedly.
Prepared execution avoids the overhead of creating multiple SQLIStatement objects for a single
statement.
The advantage of prepared execution comes when you have the same c-treeACE SQL statement
executed from within a loop. Instead of creating an object during each pass through the loop,
prepared execution creates an object once and only passes input parameters for each execution
of the statement.
Once a stored procedure creates a SQLPStatement object, it can execute it multiple times,
supplying different values for each execution.
The following example extends the previous example to use prepared execution.
Prepared Execution Example
CREATE PROCEDURE prepared_insert_customer ()
IMPORT
import java.math.*;
BEGIN
SQLPStatement p_insert_cust = new SQLPStatement (
"INSERT INTO customer VALUES (?,?) ");
int i;
String [] [] new_custs ={
{"01","ABC"},
{"02","PQR"},
{"03","XYZ"}
};
for (i=0; i<new_custs.length; i++)
{
p_insert_cust.setParam (1, Integer.valueOf (new_custs[i] [0]));
p_insert_cust.setParam (2, new_custs[i] [1]);
p_insert_cust.execute ();
}
END
Retrieving Data: the SQLCursor Class
Methods of the SQLCursor class let stored procedures retrieve rows of data.
When stored procedures create an object from the SQLCursor class, they pass as an argument a
c-treeACE SQL statement that generates a result set. The c-treeACE SQL statement is either a
SELECT or CALL statement:
A SELECT statement queries the database and returns data that meets the criteria specified
by the query expression in the SELECT statement.
A CALL statement invokes another stored procedure that returns a result set specified by the
RESULT clause of the CREATE PROCEDURE statement.
Either way, once the procedure creates an object from the SQLCursor class, the processing of
results sets follows the same steps:
1. Open the cursor with the SQLCursor.open() method
Using Java Stored Procedures
All Rights Reserved 57 www.faircom.com
2. Check whether there are any records in the result set with the SQLCursor.found() method
3. If there are records in the result set, loop through the result set:
• Try to fetch a record with the SQLCursor.fetch() method
• Check whether the fetch returned a record with the SQLCursor.found() method
• If the fetch operation returned a record, assign values from the result-set record’s fields to
procedure variables or procedure output parameters with the SQLCursor.getValue()
method
• Process the data in some manner
• If the fetch operation did not return a record, exit the loop
4. Close the cursor with the SQLCursor.close() method
The following example shows an example that uses SQLCursor() to process the result set
returned by a c-treeACE SQL SELECT statement.
Processing a Result Set from a SELECT Statement
CREATE PROCEDURE get_sal ()
IMPORT
import java.math.BigDecimal;
BEGIN
StringBuffer ename = new StringBuffer (20) ;
BigDecimal esal = new BigDecimal () ;
SQLCursor empcursor = new SQLCursor (
"SELECT name, sal FROM emp " ) ;
empcursor.open () ;
empcursor.fetch ();
while (empcursor.found ())
{
ename = (StringBuffer)empcursor.getValue (1, CHAR);
esal = (BigDecimal)empcursor.getValue (2, DECIMAL);
empcursor.fetch();
}
empcursor.close () ;
END
Stored procedures also use SQLCursor objects to process a result set returned by another stored
procedure. Instead of a SELECT statement, the SQLCursor() constructor includes a CALL
statement that invokes the desired procedure.
The following example shows an excerpt from a stored procedure that processes the result set
returned by another procedure, get_customers() customers which takes dept_no as input and
returns two columns cust_number and cust_name as its result set.
Processing a Result Set from a CALL Statement
CREATE PROCEDURE get_customer()
IMPORT
import java.math.BigDecimal;
BEGIN
SQLCursor cust_cursor = new SQLCursor ("CALL get_customers (?) ") ;
Integer cust_number;
StringBuffer cust_name;
Using Java Stored Procedures
All Rights Reserved 58 www.faircom.com
cust_cursor.setParam (1, new Integer(10));
cust_cursor.open ();
cust_cursor.fetch();
while (cust_cursor.found())
{
cust_number = (Integer)cust_cursor.getValue (1, INTEGER);
cust_name = (Stringz)cust_cursor.getValue (2, CHAR);
cust_cursor.fetch ();
}
cust_cursor.close () ;
END
registerOutParam Method: registering the Type of OUT and INOUT Variables
Before executing a stored procedure call, you must explicitly call registerOutParam() to register
the type of each OUT and INOUT parameter.
The registerOutParam() method of the SQLCursor class registers the type of OUT and INOUT
parameters.
Syntax
The format and arguments for the registerOutParam() method are as follows:
registerOutParam( param_num , data_type ) ;
param_num - An integer that specifies which parameter of the called procedure is to be
registered. (1 denotes the first parameter, 2 denotes the second, and so on).
data_type - Specifies the required SQL type of the returned parameter (see "Implicit Data
Type Conversion Between SQL and Java Types" (page 53) details of how SQL data types
map to Java data types).
Limit: The number of arguments is limited to 50.
The following example shows an excerpt from a stored procedure that uses registerOutParam()
interface to register the OUT and INOUT parameters.
registerOutParam() Interface Example
CREATE PROCEDURE get_sal (IN cust_num INTEGER,
OUT dept_num INTEGER,
INOUT salary DOUBLE PRECISION
)
BEGIN
Integer dept = new Integer(40);
Double incr = 0.25;
// select department number into dept using cust_num.
dept_num = dept;
salary = new Double(salary.doubleValue() + (salary.doubleValue) *
incr.double_Value());
END
CREATE PROCEDURE call_get_sal()
BEGIN
Integer num = new Integer(54);
Double sal = new Double(25000.00);
SQLCursor cust_cur = new SQLCursor("call get_sal(?,?,?)");
cust_cur.setParam(1,num);
Using Java Stored Procedures
All Rights Reserved 59 www.faircom.com
cust_cur.registerOutParam(2,INTEGER);
cust_cur.registerOutParam(3,DOUBLE);
cust_cur.setParam(3,sal);
cust_cur.open();
// process the data
cust_cur.close();
END
If all the OUT and INOUT parameters are not registered, then sql engine returns an error:
error(-20161): Not all OUT/INOUT parameters are registered.
Returning a Procedure Result Set: the RESULT Clause and
DhSQLResultSet
The get_sal() procedure in the previous example used the SQLCursor.getValue() method to
store the values of a database record in individual variables. But the procedure did not do
anything with those values, and they would be overwritten in the next iteration of the loop that
fetches records.
The DhSQLResultSet class provides a way for a procedure to store rows of data in a procedure
result set so the rows can be returned to the application that calls it. There can only be one
procedure result set in a stored procedure.
A stored procedure must explicitly process a result set to return it to the calling application:
Declare the procedure result set through the RESULT clause of the procedure specification
Populate the procedure result set in the body of the procedure using the methods of the
DhSQLResultSet class
When c-treeACE SQL creates a Java class from a CREATE PROCEDURE statement that contains
the RESULT clause, it implicitly instantiates an object of type DhSQLResultSet(), and calls it
SQLResultSet(). Invoke methods of the SQLResultSet() instance to populate fields and rows of
the procedure result set.
Limit: SQLResultSet is limited to 50 columns.
The following example processes a result set from a SELECT statement to return a procedure
result set. For each row of the c-treeACE SQL result set assigned to procedure variables, the
procedure:
Assigns the current values in the procedure variables to corresponding fields in the procedure
result set with the SQLResultSet.set() method
Inserts a row into the procedure result set with the SQLResultSet.insert() method
Example Returning a Procedure Result Set From a Stored Procedure
CREATE PROCEDURE get_sal2 ()
RESULT (
empname CHAR(20),
empsal NUMERIC
)
IMPORT
Using Java Stored Procedures
All Rights Reserved 60 www.faircom.com
import java.math.BigDecimal;
BEGIN
StringBuffer ename = new StringBuffer (20) ;
BigDecimal esal = new BigDecimal () ;
SQLCursor empcursor = new SQLCursor (
"SELECT name, sal FROM emp " ) ;
empcursor.open () ;
do
{
empcursor.fetch ();
if (empcursor.found ())
{
ename = (StringBuffer)empcursor.getValue (1, CHAR);
esal = (BigDecimal)empcursor.getValue (2, DECIMAL);
SQLResultSet.set (1, ename);
SQLResultSet.set (2, esal);
SQLResultSet.insert ();
}
} while (empcursor.found ()) ;
empcursor.close () ;
END
Note: The resultset parameter empname in the procedure above should be of type CHAR in ANSI
versions of c-treeACE SQL.
Handling Null Values
Stored procedures need to routinely set and detect null values:
Stored procedures may need to set the values of a c-treeACE SQL statement input
parameters or procedure result fields to null.
Stored procedures must check if the value of a field in a c-treeACE SQL result set is null
before assigning it through the SQLCursor.getValue() method. (c-treeACE SQL generates a
runtime error if the result-set field specified in getValue() is null.)
Setting SQL Statement Input Params & Procedure Result SetFields to Null
Both the setParam() method (see “The setParam Method: Pass Input Values to SQL Statements”
(page 50)) and set() method (see “Returning a Procedure Result Set: the RESULT Clause and
DhSQLResultSet” (page 59)) take objects as their value arguments. You can pass a null
reference directly to the method or pass a variable which has been assigned the null value. The
following example shows using both techniques to set a c-treeACE SQL input parameter to null.
Example Passing Null Values to setParam()
CREATE PROCEDURE test_nulls( )
BEGIN
Integer pvar_int1 = new Integer(0);
Integer pvar_int2 = new Integer(0);
Integer pvar_int3;
pvar_int3 = null;
SQLIStatement insert_t1 = new SQLIStatement
( "INSERT INTO ADMIN.t1 (c1,c2, c3) values (?,?,?) ");
insert_t1.setParam(1, new Integer(1)); // Set to non-null value
insert_t1.setParam(2, null); // Set directly to null
Using Java Stored Procedures
All Rights Reserved 61 www.faircom.com
insert_t1.setParam(3, pvar_int3); // Set indirectly to null
insert_t1.execute();
END
Assigning Null Values from SQL Result Sets:SQLCursor.wasNULL Method
If the value of the field argument to the SQLCursor.getValue() method is null, c-treeACE SQL
returns a runtime error:
(error(-20144): Null value fetched.)
This means you must always check whether a value is null before attempting to assign a value in
a c-treeACE SQL result set to a procedure variable or output parameter. The SQLCursor class
provides the wasNULL() method for this purpose.
The SQLCuror.wasNULL() method returns TRUE if a field in the result set is null. It takes a
single integer argument that specifies which field of the current row of the result set to check.
The following example illustrates using wasNULL().
Example Result Sets for Null Values with wasNULL()
CREATE PROCEDURE test_nulls2( )
RESULT ( res_int1 INTEGER ,
res_int2 INTEGER ,
res_int3 INTEGER )
BEGIN
Integer pvar_int1 = new Integer(0);
Integer pvar_int2 = new Integer(0);
Integer pvar_int3 = new Integer(0);
SQLCursor select_t1 = new SQLCursor
( "SELECT c1, c2, c3 from t1" );
select_t1.open();
select_t1.fetch();
while ( select_t1.found() )
{
// Assign values from the current row of the SQL result set
// to the pvar_intx procedure variables. Must first check
// whether the values fetched are null: if they are, must set
// pvars explicitly to null.
if ((select_t1.wasNULL(1)) == true)
pvar_int1 = null;
else
pvar_int1 = (Integer)select_t1.getValue(1, INTEGER);
if ((select_t1.wasNULL(2)) == true)
pvar_int2 = null;
else
pvar_int2 = (Integer)select_t2.getValue(2, INTEGER);
if ((select_t1.wasNULL(3)) == true)
pvar_int3 = null;
else
pvar_int3 = (Integer)select_t13getValue(3, INTEGER);
// Transfer the value from the procedure variables to the
// columns of the current row of the procedure result set.
SQLResultSet.set(1,pvar_int1);
SQLResultSet.set(2,pvar_int2);
SQLResultSet.set(3,pvar_int3);
// Insert the row into the procedure result set.
SQLResultSet.insert();
Using Java Stored Procedures
All Rights Reserved 62 www.faircom.com
select_t1.fetch();
}
// Close the SQL result set.
select_t1.close();
END
Handling Errors
c-treeACE SQL stored procedures use standard Java try/catch constructs to process exceptions.
Any errors in a c-treeACE SQL statement execution result in the creation of an DhSQLException
class object. When c-treeACE SQL detects an error in an SQL statement, it throws an exception.
The stored procedure should use try/catch constructs to process such exceptions. The
getDiagnostics() method of the DhSQLException class object provides a mechanism to retrieve
different details of the error.
The getDiagnostics() method takes a single argument whose value specifies which error
message detail it returns:
getDiagnostics Method Arguments
Argument Value Returns
RETURNED_SQLSTATE The SQLSTATE returned by execution of the previous SQL statement.
MESSAGE_TEXT The condition indicated by RETURNED_SQLSTATE.
CLASS_ORIGIN Not currently used. Always returns null.
SUBCLASS_ORIGIN Not currently used. Always returns null.
The error messages and the associated SQLSTATE and c-treeACE SQL error code values are
documented in the c-treeACE SQL Reference Manual, Table B-2.
The following example shows an excerpt from a stored procedure that uses
DhSQLException.getDiagnostics().
Example Exception Handling with DhSQLException.getDiagnostics()
CREATE PROCEDURE test_proc()
BEGIN
try
{
SQLIStatement insert_cust = new SQLIStatement (
"INSERT INTO customer VALUES (1,2) ");
}
catch (DhSQLException e)
{
String errstate = e.getDiagnostics (DhSQLException.RETURNED_SQLSTATE) ;
String errmesg = e.getDiagnostics (DhSQLException.MESSAGE_TEXT) ;
}
END
Using Java Stored Procedures
All Rights Reserved 63 www.faircom.com
Stored procedures can also throw their own exceptions by instantiating a DhSQLException object
and throwing the object when the procedure detects an error in execution. The conditions under
which the procedure throws the exception object are completely dependent on the procedure.
The following example illustrates using the DhSQLException() constructor to create an
exception object called excep. It then throws the excep object under all conditions.
Example Throwing Procedure-Specific Exceptions
CREATE PROCEDURE sp1_02()
BEGIN
// raising exception
DhSQLException excep = new DhSQLException(666,new String("Entered the tst02 procedure"));
if (true)
throw excep;
END
Calling Stored Procedures from Stored Procedures
Stored procedures and triggers can call other stored procedures. Nesting procedures lets you
take advantage of existing procedures. Instead of rewriting the code, procedures can simply issue
CALL statements to the existing procedures.
Another use for nesting procedures is to assemble result sets generated by queries on different
databases into a single result set. With this technique, the stored procedure processes multiple
SELECT statements through multiple instances of the SQLCursor class. For each of the
instances, the procedure uses the DhSQLResultSet class to add rows to the result set returned
by the procedure.
All Rights Reserved 64 www.faircom.com
6. Using Triggers
Triggers are a special type of stored procedure that are automatically invoked (“fired”) when
certain c-treeACE SQL operations are performed on the trigger’s target table. This chapter
explains how to create and use triggers.
6.1 Trigger Basics
Triggers are a special type of stored procedure used to maintain database integrity.
Like stored procedures, triggers also contain Java code (embedded in a CREATE TRIGGER
statement) and use c-treeACE SQL Java classes. However, triggers are automatically invoked
(“fired”) by certain c-treeACE SQL operations (an INSERT, UPDATE, or DELETE operation) on the
trigger’s target table.
This chapter provides a general description of triggers and discusses in detail where trigger
procedures differ from stored procedures. Unless otherwise noted, much of the material in Using
Stored Procedures (page 40) also applies to triggers.
Triggers vs. Stored Procedures vs. Constraints
Triggers are identical to stored procedures in many respects. There are three main differences:
Triggers are automatic. When the trigger event (an INSERT, UPDATE, or DELETE statement)
affects the specified table (and, optionally in UPDATE operations, the specified columns), the
Java code contained in the body of the trigger executes. Stored procedures, on the other
hand, must be explicitly invoked by an application or another procedure.
Triggers cannot have output parameters or a result set. Since triggers are automatic, there is
no calling application to process any output they may generate. The practical consequence of
this is that the Java code in the trigger body cannot invoke methods of the DhSQLResultSet
class.
Triggers have limited input parameters. The only possible input parameters for triggers are
values of columns in the rows affected by the trigger event. If the trigger includes the
REFERENCING clause, c-treeACE SQL passes the values (either as they existed in the
database or are specified in the INSERT or UPDATE statement) of each row affected. The
Java code in the trigger body can use those values in its processing by invoking the
getValue() method of the OLDROW and NEWROW objects (see “OLDROW and NEWROW
Objects: Passing Values to Triggers” (page 67)).
The automatic nature of triggers make them well-suited for enforcing referential integrity. In this
regard, they are like constraints, since both triggers and constraints can help insure 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.
However, triggers differ from constraints in the following ways:
Using Triggers
All Rights Reserved 65 www.faircom.com
Triggers are active, while constraints are passive. While constraints prevent updates that
violate referential integrity, triggers perform explicit actions in addition to the update
operation.
Triggers can do much more than enforce referential integrity. Because they are passive,
constraints are limited to preventing updates in a narrow set of conditions. Triggers are more
flexible. The following section outlines some common uses for triggers.
Typical Uses for Triggers
Typical uses for triggers include combinations of the following:
Cascading deletes
A delete operation on one table causes additional rows to be deleted from other tables that are
related to the first table by key values. This is an active way of enforcing referential integrity that a
table constraint enforces passively.
Cascading updates
An update operation on one table causes additional rows to be updated in other tables that are
related to the first table by key values. These updates are commonly limited to the key fields
themselves. This is an active way of enforcing referential integrity that a table constraint enforces
passively.
Summation updates
An update operation in one table causes a value in a row of another table to be updated by being
increased or decreased.
Automatic archiving
A delete operation on one table creates an identical row in an archive table that is not otherwise
used by the database.
Restrictions on creating Triggers
Triggers can be created only on user tables. An attempt to create triggers on system tables
(systrigger, systables, sysprocedures etc.) results in an error: (error (20158) : Can’t create
triggers on system tables).
6.2 Structure of Triggers
Like a stored procedure, a trigger has a specification and a body.
The body of a trigger is the same as that of a stored procedure: BEGIN and END delimiters
enclosing a Java snippet. The Java code in the snippet defines the triggered action that executes
when the trigger is fired. As with stored procedures, when it processes a CREATE TRIGGER
statement, c-treeACE SQL adds wrapper code to create a Java class and method that is invoked
when the trigger is fired.
Using Triggers
All Rights Reserved 66 www.faircom.com
The trigger specification, however, is different from a stored procedure specification. It contains
the following elements:
The CREATE clause specifies the name of the trigger. c-treeACE SQL stores the CREATE
TRIGGER statement in the database under trigname. It also uses trigname in the name of the
Java class that c-treeACE SQL declares to wrap around the Java snippet. The class name
uses the format username_trigname_TP, where username is the user name of the database
connection that issued the CREATE TRIGGER statement.
The BEFORE or AFTER keywords specify the trigger action time: whether the triggered action
implemented by java_snippet executes before or after the triggering INSERT, UPDATE, or
DELETE statement.
The INSERT, DELETE, or UPDATE keyword specifies the trigger event: which data
modification command activates the trigger. If UPDATE is the trigger event, this clause can
include an optional column list. Updates to any of the specified columns or use of a specified
column in a search condition to update other values will activate the trigger. As long as a
specified column is not used in either case then the trigger will not be activated. If an
UPDATE trigger does not include the optional column list, an update statement specifying
any of the table columns will activate the trigger.
The ON table_name clause specifies the trigger table: the table for which the specified trigger
event activates the trigger. The ON clause cannot specify a view or a remote table.
The optional REFERENCING clause is allowed only if the trigger also specifies the FOR EACH
ROW clause. It provides a mechanism for c-treeACE SQL to pass row values as input
parameters to the stored procedure implemented by java_snippet. The code in java_snippet
uses the getValue() method of the NEWROW and OLDROW objects to retrieve values of
columns in rows affected by the trigger event and store them in procedure variables. See
OLDROW and NEWROW Objects: Passing Values to Triggers (page 67) for details.
The FOR EACH clause specifies the frequency with which the triggered action implemented by
java_snippet executes:
• FOR EACH ROW means the triggered action executes once for each row being updated by
the triggering statement. CREATE TRIGGER must include the FOR EACH ROW clause if it
also includes a REFERENCING clause.
• FOR EACH STATEMENT means the triggered action executes only once for the whole
triggering statement. FOR EACH STATEMENT is the default.
The IMPORT clause is the same as in stored procedures. It specifies standard Java classes
to import.
The following example shows the elements of a trigger.
Using Triggers
All Rights Reserved 67 www.faircom.com
Structure of a Trigger
Trigger action time
Trigger table
CREATE TRIGGER BUG_UPDATE_TRIGGER
AFTER
UPDATE OF (STATUS, PRIORITY) Trigger event
ON BUG_IN
REFERENCING OLDROW, NEWROW
FOR EACH ROW
IMPORT
import java.sql*; } Import clause
Trigger Specification
BEGIN
.
.
.
END
Trigger Body
6.3 Create Trigger
Use the c-treeACE SQL CREATE TRIGGER statement to create a trigger. The syntax for the
CREATE TRIGGER statement is:
CREATE TRIGGER [ owner_name. ] trigname
{ BEFORE | AFTER }
{ INSERT | DELETE | UPDATE [ OF (column_name [ , ... ] ) }
ON table_name
[ REFERENCING { OLDROW [ , NEWROW ] | NEWROW [ , OLDROW ] } ]
[ FOR EACH { ROW | STATEMENT } ]
[ IMPORT java_import_clause ]
BEGIN
java_snippet
END
6.4 OLDROW and NEWROW Objects: Passing Values to
Triggers
The OLDROW and NEWROW objects provide a mechanism for c-treeACE SQL to pass row values as
input parameters to the stored procedure in a trigger that executes once for each affected row. If
the CREATE TRIGGER statement contains the REFERENCING clause, c-treeACE SQL implicitly
instantiates an OLDROW or NEWROW object (or both, depending on the arguments to the
REFERENCING clause) when it creates the Java class.
This allows the Java code in the snippet to use the getValue() method of those objects to retrieve
values of columns in rows affected by the trigger event and store them in procedure variables:
Using Triggers
All Rights Reserved 68 www.faircom.com
The OLDROW object contains values of a row as it exists in the database before an update or
delete operation. It is instantiated when triggers specify an UPDATE...REFERENCING
OLDROW or DELETE...REFERENCING OLDROW clause. It is meaningless and not available
for insert operations.
The NEWROW object contains values of a row as specified in an INSERT or UPDATE
statement. It is instantiated when triggers specify an UPDATE...REFERENCING NEWROW or
INSERT...REFERENCING NEWROW clause. It is meaningless and not available for delete
operations.
UPDATE is the only triggering statement that allows both NEWROW and OLDROW in the
REFERENCING clause.
Triggers use the OLDROW.getValue() and NEWROW.getValue() methods to assign a value
from a row being modified to a procedure variable. The format and arguments for getValue() are
the same as in other c-treeSQL Java classes:
getValue ( col_num , data type ) ;
col_num is an integer that specifies which column affected row is of interest. getValue()
retrieves the value in the column denoted by col_num (1 denotes the first column of the result
set, 2 denotes the second, and so on).
data_type specifies the required c-treeACE SQL type of the returned column value (see
Implicit Data Type Conversion Between SQL and Java Types (page 53) for details on how
c-treeACE SQL data types map to Java data types).
The following example shows an excerpt from a trigger that uses getValue() to assign values
from both OLDROW and NEWROW objects.
Using getValue() to Process Row Values within Triggers
CREATE TRIGGER BUG_UPDATE_TRIGGER
AFTER UPDATE OF (STATUS, PRIORITY) ON BUG_INFO
REFERENCING OLDROW, NEWROW
FOR EACH ROW
IMPORT
import java.sql.* ;
BEGIN
try
{
// column number of STATUS is 10
String old_status, new_status;
old_status = (String)OLDROW.getValue(10,CHAR);
new_status = (String)NEWROW.getValue(10,CHAR);
if ((old_status.compareTo("OPEN") == 0) &&
(new_status.compareTo("FIXED") == 0))
{
// If STATUS has changed from OPEN to FIXED
// increment the bugs_fixed_cnt by 1 in the
// row corresponding to current month
// and current year
SQLIStatement update_stmt = new SQLIStatement (
" update BUG_STATUS set bugs_fixed_cnt = bugs_fixed_cnt + 1 "
" where month = ? and year = ?");
Using Triggers
All Rights Reserved 69 www.faircom.com
Integer current_month = 10;
Integer current_year = 1997;
update_stmt.setParam(1, current_month);
update_stmt.setParam(2, current_year);
update_stmt.execute();
}
}
catch(DhSQLException e)
{throw e;}
END
All Rights Reserved 70 www.faircom.com
7. Using User Defined Scalar Functions
7.1 Introduction
Scalar functions are an integral part of the support provided by c-treeACE SQL for query
expression. c-treeACE SQL provides several built-in scalar functions that transform data in
different ways. However, at times there is a requirement for custom-transformation of data—a
transformation that is not provided by the provided functions. This problem is solved by the
concept of a user-defined scalar function (UDF)—a scalar function that is defined by the user.
c-treeACE SQL UDFs allow the user to define their own functions to transform data in some
custom manner.
User Defined Scalar Functions are an extension to the existing built-in scalar functions and return
a single value each time one is invoked. These functions can be used in queries in the same way
that system defined scalar functions are used.
The user defines functions by creating Java Stored Functions, modules written in Java that are
similar to the ones written for stored procedures and triggers. The java code snippet contained in
the User Defined Scalar Function definition is processed by c-treeACE SQL into a Java class
definition and stored in the database in text and compiled form. User Defined Scalar Functions
can be created, executed and dropped using ISQL, ODBC and JDBC.
7.2 Structure of User Defined Functions
The CREATE FUNCTION command creates a new User Defined Scalar Function in the current
database
function_name is the name that is to be assigned to the function. Different owners can have
functions with the same name in the same database
Each parameter_decl is of the form:
[ARG_TYPE] ARG_NAME DATA_TYPE
and is separated by a comma (‘,’)
ARG_TYPE is optional. When specified it can only be IN.
ARG_NAME specifies the name of the argument to the function. The function can access the
values through the corresponding Java variables.
DATA_TYPE is any valid supported c-treeACE SQL data type which specifies the type of the
argument.
The return value of the function is specified with the RETURNS key word followed by the data_type
declaration.
Using User Defined Scalar Functions
All Rights Reserved 71 www.faircom.com
The Java IMPORT statements which are needed for the correct functioning of the java snippet
(the code between BEGIN and END -- see below) need to be placed in the section between the
IMPORT and BEGIN keywords. This section need not be present if there are no import
statements.
The function cannot be created without specifying all the import statements needed by the
snippet. (For details refer to any Java manual or book)
The Function body, referred to as the Java snippet, needs to be placed between the BEGIN and
END keywords. Any valid Java code other than class or function definitions can be present here.
The snippet must have a return statement.
Note: Each of the keywords IMPORT, BEGIN and END need to be upper case and be present on
a separate line. Once the IMPORT or BEGIN are specified, the statement is terminated by an END
but not a semicolon (‘;’).
Creating a User Defined Scaler Function ISQL> CREATE FUNCTION str_cat(IN org_string VARCHAR(20), IN string_to_concat VARCHAR(20))
RETURNS VARCHAR(40)
IMPORT
import java.math.*;
BEGIN
String new_str = org_string + string_to_concat ;
return new_str;
END
The above example creates a User Defined Scalar Function, str_cat, that takes two input
arguments and returns the concatenated string.
7.3 Create Function
User Defined Scalar Functions are created using the CREATE FUNCTION command. User
Defined Scalar Functions can be created by any user with resource privilege.
The syntax for the CREATE FUNCTION statement is:
CREATE FUNCTION [ owner_name.]function_name
( [parameter_decl , ...] )
RETURNS (data_type)
[ IMPORT
java_import_clause ]
BEGIN
java_snippet
END
parameter_decl ::
[ IN ] parameter_name data_type
When creating stored procedures, the key words BEGIN, RETURNS, IMPORT and END should start
at the first column of the line. The function name is limited to 64 characters
Using User Defined Scalar Functions
All Rights Reserved 72 www.faircom.com
7.4 Drop Function
Deletes a User Defined Scalar Function.
Syntax
DROP FUNCTION function_name
Dropping a User Defined Scaler Function ISQL> DROP FUNCTION str_cat;
7.5 Invoking User Defined Scalar Functions
User Defined Scalar Function are a type of c-treeACE SQL expression that return a value based
on the argument(s) supplied. User Defined Scalar Functions are invoked in exactly the same
manner as built in scalar functions.
User Defined Scalar Functions can be used in the SELECT list or in the WHERE clause. They can
be used as parameters of other scalar functions or included with other SQL expressions. The
parameter passed to a user defined scalar function can be a literal, field reference or any
expression
With Constants
Example with Constants
SELECT str_cat('abcd','efgh') FROM syscalctable;
STR_CAT(ABCD,EFGH)
-------------------------------
abcdefgh
1 record selected
With Constants and Column References
Example with Constants and Column References
SELECT empfname, str_cat(empfname, emplname) FROM emp WHERE str_cat('mary', 'john') = 'maryjohn';
EMPFNAME STR_CAT(EMPFNAME,EMPLNAME)
---------------- ---------------------------------------------
Mary MaryJohn
1 records selected
Using User Defined Scalar Functions
All Rights Reserved 73 www.faircom.com
With parameter reference (ODBC/JDBC)
Example with Parameter References
SELECT str_cat(?, ?) FROM emp
SELECT * FROM emp WHERE str_cat(?, ?) = 'MaryJohn'
7.6 User Defined Scalar Function Security
Users issuing the CREATE FUNCTION statement must have the DBA privilege or RESOURCE
privilege.
The owner or users with the DBA privilege can execute or drop any User Defined Scalar
Function, and grant the EXECUTE privilege to other users.
7.7 Calling Scalar Functions from a User Defined Scalar
Function
c-treeACE SQL does not have a mechanism for calling a scalar function directly from a
user-defined function. To use scalar functions, it is necessary to call the function from within a
c-treeACE SQL statement. c-treeACE SQL defines the special table SYSCALCTABLE which has
only one row for use in situations where all the data is in the inputs.
Example
CREATE FUNCTION myuser.TO_NATIVE_DATE(IN UNIX_TYPE_DATE INT)
RETURNS TIMESTAMP
IMPORT
import java.sql.*;
BEGIN
StringBuffer query_str = new StringBuffer(“SELECT TIMESTAMPADD(SQL_TSI_SECOND,”);
query_str.append(UNIX_TYPE_DATE).append(“, TO_TIMESTAMP('01/01/1970 00:00:00')) FROM
SYSCACLTABLE”);
SQLCursor SelCursor = new SQLCursor(query_str.toString());
SelCursor.open();
SelCursor.fetch();
return(Timestamp)SelCursor.getValue(1, TIMESTAMP);
END
All Rights Reserved 74 www.faircom.com
8. Java Class Reference
8.1 Introduction
This chapter provides reference material on the c-treeACE SQL Java classes and methods. The
following table lists all the methods in the c-treeACE SQL Java classes and shows which classes
declare them. Following sections are arranged alphabetically and describe each class and its
methods in more detail. Some methods are common to more than one class.
Methods in the c-treeACE SQL Java Classes
Method SQLI-Statement
SQLP-Statement
SQLCursor DhSQL-ResultSet
DhSQL-Exception
Purpose
setParam X X X Sets the value of an SQL statement’s input parameter to the specified value (a literal, procedure variable, or procedure input parameter)
makeNULL X X X Sets the value of an SQL statement’s input parameter to null
execute X X Executes the SQL statement
rowCount X X X Returns the number of rows affected (selected, inserted, updated, or deleted) by the SQL statement
open X Opens the result set specified by the SELECT or CALL statement
close X Closes the result set specified by the SELECT or CALL statement
fetch X Fetches the next record in a result set
found X Checks whether a fetch operation returned a record
wasNULL X Checks if the value in a fetched field is null
getValue X Returns the value of the specified field from the fetched row as an Object.
getParam X X X Returns the value of the specified OUT/INOUT parameter as an Object. (This method is called after executing a CALL statement).
registerOutParam
X X X Registers the return type of the OUT and INOUT parameters.
set X Sets the field in the currently-active row of a
Java Class Reference
All Rights Reserved 75 www.faircom.com
Method SQLI-Statement
SQLP-Statement
SQLCursor DhSQL-ResultSet
DhSQL-Exception
Purpose
procedure’s result set to the specified value (a literal, procedure variable, or procedure input parameter)
makeNULL X Sets a field of the currently-active row in a procedure’s result set to null
insert X Inserts the currently-active row into a procedure’s result set
getDiagnostics
X Returns the specified detail of an error message
log X X X X X Writes a message to the file sql_server.log. Inherited by all the c-treeACE SQLc-treeACE SQL classes. See Debugging Stored Procedures (page 47).
err X X X X X Writes a message to the file sql_server.log. Inherited by all the c-treeACE SQLc-treeACE SQL classes. See Debugging Stored Procedures (page 47).
8.2 DhSQLException
Description
The DhSQLException class extends the general java.lang.Exception class to provide detail about
errors in c-treeACE SQL statement execution. Any such errors raise an exception with an
argument that is an SQLException class object. The getDiagnostics() method retrieves details of
the error.
Constructors public DhSQLException(int ecode, String errMsg)
Parameters
ecode
The error number associated with the exception condition.
errMsg
The error message associated with the exception condition.
The following example illustrates the DhSQLException() constructor to create an exception
object called excep. It then throws the excep object under all conditions.
Example
CREATE PROCEDURE sp1_02()
BEGIN
// raising exception
DhSQLException excep = new DhSQLException(666,new String
Java Class Reference
All Rights Reserved 76 www.faircom.com
("Entered the sp1_02 procedure"));
if (true)
throw excep;
END
DhSQLException.getDiagnostics
Returns the requested detail about an exception.
Format public String getDiagnostics(int diagType)
Returns
A string containing the information specified by the diagType parameter, as shown in the table
below.
Parameters
diagType
One of the values shown in the following table.
Argument Values for DhSQLException.getDiagnostics
Argument Value Returns
RETURNED_SQLSTATE The SQLSTATE returned by execution of the previous SQL statement.
MESSAGE_TEXT The condition indicated by RETURNED_SQLSTATE.
CLASS_ORIGIN Not currently used. Always returns null.
SUBCLASS_ORIGIN Not currently used. Always returns null.
Throws DhSQLException
Example
CREATE PROCEDURE test_proc()
BEGIN
String errstate;
String errmesg;
try
{
SQLIStatement insert_cust = new SQLIStatement ( "INSERT
INTO customer VALUES (1,2) ");
insert_cust.execute();
}
catch (DhSQLException e)
{
errstate = e.getDiagnostics (
DhSQLException.RETURNED_SQLSTATE) ;
errmesg = e.getDiagnostics (
DhSQLException.MESSAGE_TEXT) ;
}
Java Class Reference
All Rights Reserved 77 www.faircom.com
END
8.3 DhSQLResultSet
Description
Methods of the DhSQLResultSet class populate a result set that the stored procedure returns to
the application that called the procedure.
The Java code in a stored procedure does not explicitly create DhSQLResultSet objects. Instead,
when c-treeACE SQL creates a Java class from a CREATE PROCEDURE statement that contains a
RESULT clause, it implicitly instantiates an object of type DhSQLResultSet, and calls it
SQLResultSet.
Procedures invoke methods of the SQLResultSet() instance to populate fields and rows of the
result set.
Limit: DhSQLResultSet is limited to 50 columns.
Constructors
No explicit constructor
Parameters
None
Throws DhSQLException
DhSQLResultSet.insert
Inserts the currently-active row into a procedure’s result set.
Format public void insert()
Returns
None
Parameters
None
Throws DhSQLException
Example
CREATE PROCEDURE get_sal2 ()
RESULT (
Java Class Reference
All Rights Reserved 78 www.faircom.com
empname CHAR(20),
empsal NUMERIC,
)
IMPORT
import java.math.BigDecimal;
BEGIN
StringBuffer ename = new StringBuffer (20) ;
BigDecimal esal = new BigDecimal () ;
SQLCursor empcursor = new SQLCursor (
"SELECT name, sal FROM emp " ) ;
empcursor.open () ;
do
{
empcursor.fetch ();
if (empcursor.found ())
{
ename = (String)empcursor.getValue (1, CHAR);
esal = (BigDecimal)empcursor.getValue (2, NUMERIC);
SQLResultSet.set (1, ename);
SQLResultSet.set (2, esal);
SQLResultSet.insert ();
}
} while (empcursor.found ()) ;
empcursor.close () ;
END
Note: The resultset parameter empname in the procedure above should be of type CHAR in ANSI
versions of c-treeACE SQL.
DhSQLResultSet.makeNULL
Sets a field of the currently-active row in a procedure's result set to null. This method is redundant
with using the DhSQLResultSet.set() method to set a procedure result-set field to null.
Format public void makeNULL(int field)
Returns
None
Parameters
field
An integer that specifies which field of the result-set row to set to null (1 denotes the first field in
the row, 2 denotes the second, and so on).
Throws DhSQLException
Example
CREATE PROCEDURE test_makeNULL2(
Java Class Reference
All Rights Reserved 79 www.faircom.com
IN char_in CHAR(20))
RESULT ( res_char CHAR(20) , res_vchar VARCHAR(30))
BEGIN
SQLResultSet.set(1,char_in);
SQLResultSet.makeNULL(2);
END
Note: The input parameter char_in in the procedure above should be of type CHAR in ANSI
versions of c-treeACE SQL.
DhSQLResultSet.set
Sets the field in the currently-active row of a procedure’s result set to the specified value (a literal,
procedure variable, or procedure input parameter).
Format public void set(int field, Object val)
Returns
None
Parameters
field
An integer that specifies which field of the result-set row to set to the value specified by val (1
denotes the first field in the row, 2 denotes the second, and so on).
val
A literal or the name of a variable or input parameter that contains the value to be assigned to the
field.
Throws DhSQLException
Example
CREATE PROCEDURE get_sal2 ()
RESULT (
empname CHAR(20),
empsal NUMERIC,
)
BEGIN
StringBuffer ename = new StringBuffer (20) ;
BigDecimal esal = new BigDecimal () ;
SQLCursor empcursor = new SQLCursor (
"SELECT name, sal FROM emp " ) ;
empcursor.open () ;
do
{
empcursor.fetch ();
if (empcursor.found ())
{
Java Class Reference
All Rights Reserved 80 www.faircom.com
ename = (StringBuffer)empcursor.getValue (1, CHAR);
esal = (BigDecimal)empcursor.getValue (2, NUMERIC);
SQLResultSet.set (1, ename);
SQLResultSet.set (2, esal);
SQLResultSet.insert ();
}
} while (empcursor.found ()) ;
empcursor.close () ;
END
Note: The resultset parameter empname in the procedure above should be of type CHAR in ANSI
versions of c-treeACE SQL.
8.4 SQLCursor
Description
Methods of the SQLCursor class retrieve rows of data from a database or another stored
procedure’s result set.
Constructors SQLCursor (String statement)
Parameters
statement
A c-treeACE SQL statement that generates a result set. Enclose the statement in double quotes.
The c-treeACE SQL statement is either a SELECT or CALL statement:
• A SELECT statement queries the database and returns data that meets the criteria
specified by the query expression in the SELECT statement.
• A CALL statement invokes another stored procedure that returns a result set specified by
the RESULT clause of the CREATE PROCEDURE statement.
Throws DhSQLException
The following excerpt from a stored procedure instantiates an SQLCursor object called
cust_cursor that retrieves data from a database table.
Example
SQLCursor empcursor = new SQLCursor ("SELECT name, sal FROM emp " ) ;
The following excerpt from a stored procedure instantiates an SQLCursor object called
cust_cursor that calls another stored procedure.
Java Class Reference
All Rights Reserved 81 www.faircom.com
Example with Nested Stored Procedure
SQLCursor cust_cursor = new SQLCursor ("CALL get_customers (?) ") ;
SQLCursor.close
Closes the result set specified by the SELECT or CALL statement.
Format public void close()
Returns
None
Parameters
None
Throws DhSQLException
Example
.
.
.
if (cust_cursor.Found ())
{
cust_cursor.getValue (1, INTEGER);
cust_cursor.getValue (2, CHAR) ;
}
else
break;
}
cust_cursor.close () ;
SQLCursor.fetch
Fetches the next record in a result set, if there is one.
Format public void fetch()
Returns
None
Parameters
None
Java Class Reference
All Rights Reserved 82 www.faircom.com
Throws DhSQLException
Example
for (;;)
{
cust_cursor.fetch ();
if (cust_cursor.found ())
{
cust_cursor.getValue (1, INTEGER);
cust_cursor.getValue (2, CHAR) ;
}
else
break;
}
SQLCursor.found
Checks whether a fetch operation returned a record.
Format public boolean found ()
Returns
True if the previous call to fetch() returned a record, false otherwise.
Parameters
None
Throws DhSQLException
Example
for (;;)
{
cust_cursor.fetch ();
if (cust_cursor.found ())
{
cust_cursor.getValue (1, INTEGER);
cust_cursor.getValue (2, CHAR) ;
}
else
break;
}
SQLCursor.getParam
When a procedure is called from another procedure, this method returns the value of the
specified OUT/INOUT parameter of the called procedure as a Java object. This returned object
Java Class Reference
All Rights Reserved 83 www.faircom.com
must be typecasted to the appropriate type. This method is common to the SQLCursor,
SQLIStatement, and SQLPStatement classes.
Format public Object getParam(int field, short dType)
Returns
Returns the Object specified by the field value.
Parameters
field
An integer that specifies which argument value of the called procedure is to be returned (1
denotes the first parameter, 2 denotes the second, and so on).
If the specified parameter does not exist, c-treeACE SQL returns an error:
(error(-20145): Invalid field reference.)
dType
The expected data type of the returning parameter.
Throws
DhSQLException
Example
CREATE PROCEDURE swap_proc(IN param1 INTEGER,
OUT param2 INTEGER,
INOUT param3 INTEGER
)
BEGIN
param2 = param3;
param3 = param1;
END
CREATE PROCEDURE call_swap_proc()
BEGIN
Integer val1 = new Integer(10);
Integer val2;
Integer val3 = new Integer(20);
SQLCursor tmp_cur = new SQLCursor("CALL swap_proc(?,?,?)");
tmp_cur.registerOutParam(2, INTEGER);
tmp_cur.registerOutParam(3, INTEGER);
tmp_cur.setParam(1, val1);
tmp_cur.setParam(3, val3);
tmp_cur.open();
val2 = (Integer)tmp_cur.getParam(2, INTEGER);
val3 = (Integer)tmp_cur.getParam(3, INTEGER);
// process the val2 and val3
- - -
tmp_cur.close();
END
Java Class Reference
All Rights Reserved 84 www.faircom.com
SQLCursor.getValue
Returns the value of the specified field of the fetched row of a cursor or result set as a Java
object. This returned object must be typecasted to an appropriate SQL type.
Format public Object getValue(int field, short dType)
Returns
Returns the Object specified by the field value.
Parameters
field
An integer that specifies which field of the fetched record is of interest. getValue() retrieves the
value in the currently-fetched record of the column denoted by field (1 denotes the first column of
the result set, 2 denotes the second, and so on).
The value in the column denoted by field cannot be null, or c-treeACE SQL returns an error:
(error(-20144): Null value fetched.)
This means you must always check whether a value is null before attempting to assign a value in
an SQL result set to a procedure variable or output parameter. The SQLCursor class provides the
wasNULL() method for this purpose. See Section "SQLCursor.wasNULL" (page 89) for details.
dType
The expected data type of the return Object being returned.
Throws DhSQLException
Example
CREATE PROCEDURE test_nulls2()
RESULT (col1 INTEGER,
col2 INTEGER,
col3 INTEGER)
BEGIN
Integer pvar_int1 = new Integer(0);
Integer pvar_int2 = new Integer(0);
Integer pvar_int3 = new Integer(0);
SQLCursor select_t1 = new SQLCursor
( "SELECT c1, c2, c3 from t1" );
select_t1.open();
select_t1.fetch();
while ( select_t1.found() )
{
// Assign values from the current row of the SQL result set
// to the pvar_intx procedure variables. Must first check
// whether the values fetched are null: if they are, must set
// pvars explicitly to null.
if ((select_t1.wasNULL(1)) == true)
pvar_int1 = null;
Java Class Reference
All Rights Reserved 85 www.faircom.com
else
pvar_int1 = (Integer)select_t1.getValue(1,INTEGER);
if ((select_t1.wasNULL(2)) == true)
pvar_int2 = null;
else
pvar_int2 = (Integer)select_t1.getValue(2,INTEGER);
if ((select_t1.wasNULL(3)) == true)
pvar_int3 = null;
else
pSQLResultSet.set(1,pvar_int1);
SQLResultSet.set(2,pvar_int2);
SQLResultSet.set(3,pvar_int3);
SQLResultSet.insert();
select_t1.fetch();
}
select_t1.close();
END
SQLCursor.makeNULL
Sets the value of a c-treeACE SQL statement’s input parameter to null. This method is common
to the SQLCursor, SQLIStatement, and SQLPStatement classes. This method is redundant with
using the setParam() method to set a statement’s input parameter to null.
Format public void makeNULL(int f)
Returns
None
Parameters
f
An integer that specifies which input parameter of the c-treeACE SQL statement string to set to
null (1 denotes the first input parameter in the statement, 2 denotes the second, and so on).
Throws DhSQLException
Example
CREATE PROCEDURE sc_makeNULL()
BEGIN
SQLCursor select_btypes = new SQLCursor (
"SELECT small_fld from sfns where small_fld = ? ");
select_btypes.makeNULL(1);
select_btypes.open();
select_btypes.fetch();
select_btypes.close();
END
Java Class Reference
All Rights Reserved 86 www.faircom.com
SQLCursor.open
Opens the result set specified by the SELECT or CALL statement.
Format public void open()
Returns
None
Parameters
None
Throws DhSQLException
Example
SQLCursor empcursor = new SQLCursor (
"SELECT name, sal FROM emp " ) ;
empcursor.open () ;
SQLCursor.registerOutParam
Registers the expected type of OUT and INOUT parameters. This method is common for
SQLCursor, SQLIStatement and SQLPStatement classes.
Format public void registerOutParam(int pIndex, short dType)
Returns
None
Parameters
pindex
An integer that specifies which OUT/INOUT parameter is to be registered (1 denotes the first
parameter, 2 denotes the second, and so on).
dtype
The expected type of the OUT/INOUT parameter.
Note: SQLCursor class has another form of registerOutParam(), which takes three arguments. The syntax of this method is:
public void registerOutParam(int pIndex, short dType, short scale)
pIndex and dType are the same as the two arguments in SQLCursor.registerOutParam() method. The scale specifies the number of digits after the decimal point. This method is not implemented in c-treeACE SQL and invocation of this method results in error:
Java Class Reference
All Rights Reserved 87 www.faircom.com
“Scale for registerOutParam not implemented”.
Throws DhSQLException
Example
CREATE PROCEDURE register_proc()
BEGIN
// cust_proc is a procedure with an IN, OUT and an INOUT arguments of type
// integer, string and numeric respectively.
SQLCursor cust_cur = new SQLCursor("call cust_proc(?,?,?)");
cust_cur.registerOutParam(2, CHAR);
cust_cur.registerOutParam(3, NUMERIC);
cust_cur.open();
// Process results
cust_cur.close();
END
SQLCursor.rowCount
Returns the number of rows affected (selected, inserted, updated, or deleted) by the c-treeACE
SQL statement. This method is common to the SQLCursor, SQLIStatement, and SQLPStatement
classes.
Format public int rowCount()
Returns
An integer indicating the number of rows.
Parameters
None
Throws DhSQLException
The following example uses the rowCount() method of the SQLIStatement class. It nests the
method invocation within SQLResultSet.set() to store the number of rows affected (1, in this
case) in the procedure’s result set.
Example
CREATE PROCEDURE sis_rowCount()
RESULT ( ins_recs BIGINT )
BEGIN
SQLIStatement insert_test103 = new SQLIStatement (
"INSERT INTO test103 (fld1) values (17)");
insert_test103.execute();
SQLResultSet.set(1,new Long(insert_test103.rowCount()));
SQLResultSet.insert();
Java Class Reference
All Rights Reserved 88 www.faircom.com
END
SQLCursor.setParam
Sets the value of a c-treeACE SQL statement’s input parameter to the specified value (a literal,
procedure variable, or procedure input parameter). This method is common to the SQLCursor,
SQLIStatement, and SQLPStatement classes.
Format public void setParam(int f, Object val)
Returns
None
Parameters
f
An integer that specifies which parameter marker in the c-treeACE SQL statement is to receive
the value (1 denotes the first parameter marker, 2 denotes the second, and so on).
val
A literal or the name of a variable or input parameter that contains the value to be assigned to the
parameter marker.
Throws DhSQLException
Example
CREATE PROCEDURE sps_setParam()
BEGIN
// Assign local variables to be used as SQL input parameter references
Integer ins_fld_ref = new Integer(1);
Integer ins_small_fld = new Integer(3200);
Integer ins_int_fld = new Integer(21474);
Double ins_doub_fld = new Double(1.797E+30);
StringBuffer ins_char_fld = new StringBuffer("Athula");
StringBuffer ins_vchar_fld = new StringBuffer("Scientist");
Float ins_real_fld = new Float(17);
SQLPStatement insert_sfns1 = new SQLPStatement ("INSERT INTO sfns"
+ "(fld_ref,small_fld,int_fld,doub_fld,char_fld,vchar_fld)"
+ "values (?,?,?,?,?,?)" );
insert_sfns1.setParam(1,ins_fld_ref);
insert_sfns1.setParam(2,ins_small_fld);
insert_sfns1.setParam(3,ins_int_fld);
insert_sfns1.setParam(4,ins_doub_fld);
insert_sfns1.setParam(5,ins_char_fld);
insert_sfns1.setParam(6,ins_vchar_fld);
insert_sfns1.execute();
END
Java Class Reference
All Rights Reserved 89 www.faircom.com
SQLCursor.wasNULL
Checks if the value in a fetched field is null.
Format public boolean wasNULL(int field)
Returns
True if the field is null, false otherwise.
Parameters
field
An integer that specifies which field of the fetched record is of interest (1 denotes the first column
of the result set, 2 denotes the second, and so on). wasNULL() checks whether the value in the
currently-fetched record of the column denoted by field is null.
Throws DhSQLException
Example
CREATE PROCEDURE test_wasNULL()
BEGIN
int small_sp = new Integer(0);
SQLCursor select_btypes = new SQLCursor ("SELECT small_fld from sfns");
select_btypes.open();
select_btypes.fetch();
if ((select_btypes.wasNULL(1)) == true)
small_sp = null;
else
select_btypes.getValue(1,INTEGER);
select_btypes.close();
END
8.5 SQLIStatement
Description
Methods of the SQLIStatement class provide for immediate (one-time) execution of c-treeACE
SQL statements that do not generate a result set.
Note: SQLIStatement can be used to call stored procedures that do not have result sets.
Constructors SQLIStatement (String statement)
Parameters
statement
Java Class Reference
All Rights Reserved 90 www.faircom.com
A c-treeACE SQL statement that does not generate a result set. Enclose the statement in double
quotes.
Throws DhSQLException
Example
CREATE PROCEDURE insert_customer (
IN cust_number INTEGER,
IN cust_name CHAR(20)
)
BEGIN
SQLIStatement insert_cust = new SQLIStatement
("INSERT INTO customer VALUES (?,?) ");
insert_cust.execute();
END
Note: The input parameter cust_name in the procedure above should be of type CHAR in ANSI
versions of c-treeACE SQL.
SQLIStatement.execute
Executes the c-treeACE SQL statement. This method is common to the SQLIStatement and
SQLPStatement classes.
Format public void execute()
Returns
None
Parameters
None
Throws DhSQLException
Example
CREATE PROCEDURE insert_customer (
IN cust_number INTEGER,
IN cust_name CHAR(20)
)
BEGIN
SQLIStatement insert_cust = new SQLIStatement (
"INSERT INTO customer VALUES (?,?) ");
insert_cust.setParam (1, cust_number);
insert_cust.setParam (2, cust_name);
insert_cust.execute ();
Java Class Reference
All Rights Reserved 91 www.faircom.com
END
SQLIStatement.getParam
When a procedure is called from another procedure, this method returns the value of the
specified OUT/INOUT parameter of called procedure as a Java object. This returned object must
be typecasted to the appropriate type.
Format public Object getParam(int field, short dType)
Returns
Returns the Object specified by the field value.
Parameters
field
An integer that specifies which argument value of the called procedure is to be returned (1
denotes the first parameter, 2 denotes the second, and so on).
If the specified parameter does not exists, c-treeACE SQL returns an error:
(error(-20145): Invalid field reference.)
dType
The expected data type of the returning parameter.
Throws DhSQLException
Example
CREATE PROCEDURE swap_proc(IN param1 INTEGER,
OUT param2 INTEGER,
INOUT param3 INTEGER
)
BEGIN
param2 = param3;
param3 = param1;
END
CREATE PROCEDURE call_swap_proc()
BEGIN
Integer val1 = new Integer(10);
Integer val2;
Integer val3 = new Integer(20);
SQLIStatement istmt = new SQLIStatement("CALL swap_proc(?,?,?)");
istmt.registerOutParam(2, INTEGER);
istmt.registerOutParam(3, INTEGER);
istmt.setParam(1, val1);
istmt.setParam(3, val3);
istmt.execute();
val2 = (Integer)istmt.getParam(2, INTEGER);
val3 = (Integer)istmt.getParam(3, INTEGER);
Java Class Reference
All Rights Reserved 92 www.faircom.com
// process the val2 and val3
END
SQLIStatement.makeNULL
Sets the value of a c-treeACE SQL statement’s input parameter to null. This method is common
to the SQLCursor, SQLIStatement, and SQLPStatement classes. This method is redundant with
using the setParam() method to set a statement’s input parameter to null.
Format public void makeNULL(int f)
Returns
None
Parameters
f
An integer that specifies which input parameter of the c-treeACE SQL statement string to set to
null (1 denotes the first input parameter in the statement, 2 denotes the second, and so on).
Throws DhSQLException
Example
CREATE PROCEDURE sis_makeNULL()
BEGIN
SQLIStatement insert_sfns1 = new SQLIStatement ("INSERT INTO sfns"
+ "(fld_ref,small_fld,int_fld,doub_fld,char_fld,vchar_fld)"
+ "values (?,?,?,?,?,?)");
insert_sfns1.setParam(1,new Integer(66));
insert_sfns1.makeNULL(2);
insert_sfns1.makeNULL(3);
insert_sfns1.makeNULL(4);
insert_sfns1.makeNULL(5);
insert_sfns1.makeNULL(6);
insert_sfns1.execute();
END
SQLIStatement.registerOutParam
This method registers the expected type of OUT and INOUT parameters. This method is common
for SQLCursor, SQLIStatement and SQLPStatement classes.
Format public void registerOutParam(int pIndex, short dType)
Returns
None
Java Class Reference
All Rights Reserved 93 www.faircom.com
Parameters
pIndex
An integer that specifies which OUT/INOUT parameter is to be registered (1 denotes the first
parameter, 2 denotes the second, and so on).
dType
The expected type of the OUT/INOUT parameter.
Throws DhSQLException
Example
CREATE PROCEDURE register_proc()
BEGIN
// cust_proc is a procedure with an IN, OUT and an INOUT arguments of type
// integer, string and numeric respectively.
SQLIStatement istmt = new SQLIStatement("call cust_proc(?,?,?)");
istmt.registerOutParam(2, CHAR);
istmt.registerOutParam(3, NUMERIC);
istmt.execute();
// Process results
END
SQLIStatement.rowCount
Returns the number of rows affected (selected, inserted, updated, or deleted) by the c-treeACE
SQL statement. This method is common to the SQLCursor, SQLIStatement, and SQLPStatement
classes.
Format public int rowCount()
Returns
An integer indicating the number of rows.
Parameters
None
Throws DhSQLException
The following example uses the rowCount() method of the SQLIStatement class. It nests the
method invocation within SQLResultSet.set() to store the number of rows affected (1, in this
case) in the procedure’s result set.
Example
CREATE PROCEDURE sis_rowCount()
RESULT ( ins_recs BIGINT )
Java Class Reference
All Rights Reserved 94 www.faircom.com
BEGIN
SQLIStatement insert_test103 = new SQLIStatement (
"INSERT INTO test103 (fld1) values (17)");
insert_test103.execute();
SQLResultSet.set(1,new Long(insert_test103.rowCount()));
SQLResultSet.insert();
END
SQLIStatement.setParam
Sets the value of a c-treeACE SQL statement’s input parameter to the specified value (a literal,
procedure variable, or procedure input parameter). This method is common to the SQLCursor,
SQLIStatement, and SQLPStatement classes.
Format public void setParam(int f, Object val)
Returns
None
Parameters
f An integer that specifies which parameter marker in the c-treeACE SQL statement is to
receive the value (1 denotes the first parameter marker, 2 denotes the second, and so on).
val A literal or the name of a variable or input parameter that contains the value to be
assigned to the parameter marker.
Throws DhSQLException
Example
CREATE PROCEDURE sps_setParam()
BEGIN
// Assign local variables to be used as SQL input parameter references
Integer ins_fld_ref = new Integer(1);
Integer ins_small_fld = new Integer(3200);
Integer ins_int_fld = new Integer(21474);
Double ins_doub_fld = new Double(1.797E+30);
StringBuffer ins_char_fld = new StringBuffer("Athula");
StringBuffer ins_vchar_fld = new StringBuffer("Scientist");
Float ins_real_fld = new Float(17);
SQLPStatement insert_sfns1 = new SQLPStatement ("INSERT INTO sfns"
+ "(fld_ref,small_fld,int_fld,doub_fld,char_fld,vchar_fld)"
+ "values (?,?,?,?,?,?)" );
insert_sfns1.setParam(1,ins_fld_ref);
insert_sfns1.setParam(2,ins_small_fld);
insert_sfns1.setParam(3,ins_int_fld);
insert_sfns1.setParam(4,ins_doub_fld);
insert_sfns1.setParam(5,ins_char_fld);
insert_sfns1.setParam(6,ins_vchar_fld);
insert_sfns1.execute();
Java Class Reference
All Rights Reserved 95 www.faircom.com
END
8.6 SQLPStatement
Description
Methods of the SQLPStatement class provide for prepared (repeated) execution of c-treeSQL
statements that do not generate a result set.
Note: SQLPStatement can be used to call stored procedures that do not have result sets.
Constructors SQLPStatement (String statement)
Parameters
statement
A c-treeSQL statement that does not generate a result set. Enclose the statement in double
quotes.
Throws DhSQLException
Example
SQLPStatement pstmt = new SQLPStatement (
"INSERT INTO T1 VALUES (?, ?) ") ;
.
.
.
SQLPStatement.execute
Executes the c-treeACE SQL statement. This method is common to the SQLIStatement and
SQLPStatement classes.
Format public void execute()
Returns
None
Parameters
None
Throws DhSQLException
Java Class Reference
All Rights Reserved 96 www.faircom.com
Example
CREATE PROCEDURE test_pstmt()
BEGIN
SQLPStatement pstmt = new SQLPStatement ( "INSERT INTO T1 VALUES (?, ?) ") ;
pstmt.setParam (1, new Integer(10));
pstmt.setParam (2, new Integer(10));
pstmt.execute ();
pstmt.setParam (1, new Integer(20));
pstmt.setParam (2, new Integer(20));
pstmt.execute ();
END
SQLPStatement.getParam
When a procedure is called from another procedure, this method returns the value of the
specified OUT/INOUT parameter of the called procedure as a Java object. This returned object
must be typecasted to the appropriate type.
Format public Object getParam(int field, short dType)
Returns
Returns the Object specified by the field value.
Parameters
field
An integer that specifies which argument value of the called procedure is to be returned (1
denotes the first parameter, 2 denotes the second, and so on).
If the specified parameter does not exists, c-treeACE SQL returns an error:
(error(-20145): Invalid field reference.)
dType
The expected data type of the returning parameter.
Throws DhSQLException
Example
CREATE PROCEDURE swap_proc(IN param1 INTEGER,
OUT param2 INTEGER,
INOUT param3 INTEGER)
BEGIN
param2 = param3;
param3 = param1;
END
CREATE PROCEDURE call_swap_proc()
BEGIN
Integer val1 = new Integer(10);
Java Class Reference
All Rights Reserved 97 www.faircom.com
Integer val2;
Integer val3 = new Integer(20);
SQLPStatement pstmt = new SQLPStatement("CALL swap_proc(?,?,?)");
pstmt.registerOutParam(2, INTEGER);
pstmt.registerOutParam(3, INTEGER);
pstmt.setParam(1, val1);
pstmt.setParam(3, val3);
pstmt.execute();
val2 = (Integer)pstmt.getParam(2, INTEGER);
val3 = (Integer)pstmt.getParam(3, INTEGER);
// process the val2 and val3
END
SQLPStatement.makeNULL
Sets the value of a c-treeACE SQL statement’s input parameter to null. This method is common
to the SQLCursor, SQLIStatement, and SQLPStatement classes. This method is redundant with
using the setParam() method to set a statement’s input parameter to null.
Format public void makeNULL(int f)
Returns
None
Parameters
f
An integer that specifies which input parameter of the c-treeACE SQL statement string to set to
null (1 denotes the first input parameter in the statement, 2 denotes the second, and so on).
Throws DhSQLException
Example
CREATE PROCEDURE sps_makeNULL()
BEGIN
SQLPStatement insert_sfns1 = new SQLPStatement ("INSERT INTO sfns"
+ "(fld_ref,small_fld,int_fld,doub_fld,char_fld,vchar_fld)"
+ "values (?,?,?,?,?,?)" );
insert_sfns1.setParam(1,new Integer(666));
insert_sfns1.makeNULL(2);
insert_sfns1.makeNULL(3);
insert_sfns1.makeNULL(4);
insert_sfns1.makeNULL(5);
insert_sfns1.makeNULL(6);
insert_sfns1.execute();
END
Java Class Reference
All Rights Reserved 98 www.faircom.com
SQLPStatement.registerOutParam
This method registers the expected Type of OUT and INOUT parameters. This method is
common for SQLCursor, SQLIStatement and SQLPStatement classes.
Format public void registerOutParam(int pIndex, short dType)
Returns
None
Parameters
pIndex
An integer that specifies which OUT/INOUT parameter is to be registered (1 denotes the first
parameter, 2 denotes the second, and so on).
dType
The expected type of the OUT/INOUT parameter.
Throws DhSQLException
Example
CREATE PROCEDURE register_proc()
BEGIN
// cust_proc is a procedure with an IN, OUT and an INOUT arguments of types
// integer, string and numeric respectively.
SQLPStatement pstmt = new SQLPStatement("call cust_proc(?,?,?)");
pstmt.registerOutParam(2, CHAR);
pstmt.registerOutParam(3, NUMERIC);
pstmt.execute();
// Process results
END
SQLPStatement.rowCount
Returns the number of rows affected (selected, inserted, updated, or deleted) by the SQL
statement. This method is common to the SQLCursor, SQLIStatement, and SQLPStatement
classes.
Format public int rowCount()
Returns
An integer indicating the number of rows.
Parameters
None
Java Class Reference
All Rights Reserved 99 www.faircom.com
Throws DhSQLException
This example uses the rowCount() method of the SQLIStatement class. It nests the method
invocation within SQLResultSet.set() to store the number of rows affected (1, in this case) in the
procedure’s result set.
Example
CREATE PROCEDURE sis_rowCount()
RESULT ( ins_recs BIGINT )
BEGIN
SQLIStatement insert_test103 = new SQLIStatement (
"INSERT INTO test103 (fld1) values (17)");
insert_test103.execute();
SQLResultSet.set(1,new Long(insert_test103.rowCount()));
SQLResultSet.insert();
END
SQLPStatement.setParam
Sets the value of a c-treeACE SQL statement’s input parameter to the specified value (a literal,
procedure variable, or procedure input parameter). This method is common to the SQLCursor,
SQLIStatement, and SQLPStatement classes.
Format public void setParam(int f, Object val)
Returns
None
Parameters
f
An integer that specifies which parameter marker in the c-treeACE SQL statement is to receive
the value (1 denotes the first parameter marker, 2 denotes the second, and so on).
val
A literal or the name of a variable or input parameter that contains the value to be assigned to the
parameter marker.
Throws DhSQLException
Example
CREATE PROCEDURE sps_setParam()
BEGIN
// Assign local variables to be used as SQL input parameter references
Integer ins_fld_ref = new Integer(1);
Integer ins_small_fld = new Integer(3200);
Java Class Reference
All Rights Reserved 100 www.faircom.com
Integer ins_int_fld = new Integer(21474);
Double ins_doub_fld = new Double(1.797E+30);
StringBuffer ins_char_fld = new StringBuffer("Athula");
StringBuffer ins_vchar_fld = new StringBuffer("Scientist");
Float ins_real_fld = new Float(17);
SQLPStatement insert_sfns1 = new SQLPStatement ("INSERT INTO sfns"
+ "(fld_ref,small_fld,int_fld,doub_fld,char_fld,vchar_fld)"
+ "values (?,?,?,?,?,?)" );
insert_sfns1.setParam(1,ins_fld_ref);
insert_sfns1.setParam(2,ins_small_fld);
insert_sfns1.setParam(3,ins_int_fld);
insert_sfns1.setParam(4,ins_doub_fld);
insert_sfns1.setParam(5,ins_char_fld);
insert_sfns1.setParam(6,ins_vchar_fld);
insert_sfns1.execute();
END
All Rights Reserved 101 www.faircom.com
9. .NET Support
Microsoft .NET framework provides a common runtime functionality for Windows applications.
This allows a consistent and comprehensive programming model for Windows developers.
c-treeACE SQL now extends .NET support for our stored procedure programming framework
which is a more suitable and native environment for Windows developers than our existing
cross-platform Java framework.
Key features of this environment include:
SP, UDF, and triggers can be written in any language that compiles to a CLI.
SQL classes, similar to ADO, are exposed.
SP, UDF, and triggers can be debugged by attaching to the server.
Visual Studio 2012 and later are supported.
With this .NET support, you can use Visual Studio to create, edit, and debug your SP, UDF, and
triggers. An API is provided along with a Visual Studio extension for complete .NET development.
You can compile on the client and deploy binaries to the server.
Tutorials, which follow the format of the standard FairCom tutorials, are provided. See .NET
Tutorials (page 102).
9.1 Visual Studio .NET Development
To aid in developing stored procedures (SP), user-defined functions (UDF), and triggers, FairCom
provides an extension to the Visual Studio IDE.
.NET Framework 4.0, available from Microsoft, is required for writing SP, UDF, and triggers.
Extension Installation
FairCom distributes ctreeSP.vsix, which is a package installer. To install this extension,
double-click the .vsix file.
The FairCom extension can be installed in Microsoft Visual Studio 2012 or 2013.
Extension Removal
Should you need to remove this extension, go to the Visual Studio Tools menu, select
Extensions and Updates, locate the template, and click Uninstall.
.NET Support
All Rights Reserved 102 www.faircom.com
9.2 .NET Tutorials
Two C# tutorials are included to guide you through the .NET Stored Procedure support. These
tutorials are located in the following directory by default:
\FairCom\V11.0.0\win32\sdk\sql.stored.procs\tutorials\cSharp
To get started, simply load the Microsoft Visual Solution File labeled Tutorials.sln. The code
behind the two tutorials is located in the Stored_Procedures folder:
\FairCom\V11.0.0\win32\sdk\sql.stored.procs\tutorials\cSharp\Stored_Procedures
The image below shows the first tutorial, tutorial_1.cs, loaded in the Solution Explorer:
To execute tutorial_1.cs, right-click tutorial_1.cs under Stored-Procedures and choose Deploy
to Server. You should see a screen similar to the following:
.NET Support
All Rights Reserved 103 www.faircom.com
Next, right-click tutorial_1.cs under Stored-Procedures again, choose Test Procedure, and
click Execute.
After you execute tutorial_1, you should see the following window:
The window shows the resultset obtained from running the tutorial.
Similar procedures can be used to run the other C# tutorial, tutorial_2.cs.
.NET Support
All Rights Reserved 104 www.faircom.com
9.3 Mapping Between SQL Types and .NET Types
SQL TYPE .NET Type
CHAR String
VARCHAR String
LVC String
CLOB String
NCHAR String
NVARCHAR String
CHAR_CS String
VARCHAR_CS String
NCHAR_CS String
NVARCHAR_CS String
NUMERIC Nullable<Decimal>
MONEY Nullable<Decimal>
SMALLINT Nullable<Int16>
INTEGER Nullable<Int32>
REAL Nullable<Single>
FLOAT Nullable<Double>
DOUBLE PRECISION Nullable<Double>
DATE Nullable<DateTime>
TIME Nullable<TimeSpan>
TIMESTAMP Nullable<DateTime>
TINYINT Nullable<Int16>
BINARY Byte[]
VARBINARY Byte[]
LVB Byte[]
BLOB Byte[]
BIT Nullable<Boolean>
BIGINT Nullable<Int64>
All Rights Reserved 105 www.faircom.com
10. Writing .NET Stored Procedures
To write a .NET stored procedure (SP), user-defined function (UDF), or trigger, a new project
must be created using one of the supplied templates (page 101). The steps below will create a
C# stored procedure project.
Tutorials, which follow the format of the standard FairCom tutorials, are provided. See .NET
Tutorials (page 102).
Note: The extension for Visual Studio must be installed before you can perform the procedures in this section. See .NET Development (page 101).
1. Open Visual Studio.
2. Create a new project and, from the templates, select Visual C# > c-tree > Stored Procedure, Trigger and UDF.
3. Set the project name and location and click OK.
4. From the resulting dialog, pick the Data Source (pre-configured in Visual Studio) or Custom and provide the necessary server connection information (the server does not need to be running).
A new Solution and a new project will be created and opened. In Solution Explorer, you should
see one folder for each type of project: Stored Procedures, Triggers, and UDFs.
Writing .NET Stored Procedures
All Rights Reserved 106 www.faircom.com
10.1 Writing a New SP, UDF, or Trigger
To write a new SP, UDF, or trigger, follow these steps after creating your solution and /or projects
from the previous topic:
1. Right-click on your project (created in Writing .NET SP, UDF, and Triggers) or in any folder under your project in Solution Explorer and chose Add/New Item.
2. When the dialog appears, choose Visual C# Items > c-tree and choose the appropriate item.
You may consider customizing the name of the .cs file that will be created. This name is not
in any way associated with your stored procedure name.
3. When done, click Add.
4. A new dialog appears. Fill in the fields:
• Specify your stored procedure name.
• Adjust the namespace if you require or prefer a customized project. This namespace
does affect execution or definition of your stored procedure; however your choice may
help organize your work.
• Set the procedure owner, parameters, and result set.
Click OK.
A new source file is created. The class you implement is already prepared and you implement the
ExecuteSP method with your application logic, as described later.
Writing .NET Stored Procedures
All Rights Reserved 107 www.faircom.com
10.2 Deploying the SP, UDF, or Trigger
Once coded, your SP, UDF, or trigger needs to be compiled and “deployed” to a server.
Right-click it in Solution Explorer and choose Deploy to Server. One or more SP, UDF, or
triggers can be deployed at the same time.
You are notified if any problems are encountered while the code is compiled and deployed to a
c-treeACE SQL server.
10.3 Testing the SP, UDF, or Trigger
A stored procedure can be run to test its behavior by right-clicking in Solution Explorer and
choosing Test Procedure. A window appears allowing you to set the stored procedure’s
parameters, execute it, and see the result generated.
10.4 Debugging the SP, UDF, or Trigger
By right-clicking in Solution Explorer and choosing Debug Server it is possible to debug a SP,
UDF, or trigger while the server runs it.
The server must be active and reachable while debugging. For simplicity, the server should be
running on the same machine, although it is possible to debug a remote server using Microsoft
remote debugger.
You can set a breakpoint in the code, launch a debug server (not necessarily in this sequence),
and execute your stored procedure via external tools such as c-treeACE SQL Explorer, your own
program, or Test Procedure (page 107) as described above.
Stored Procedure Server-side Debugging
Server-side stored procedure execution logging can now be turned on and off using the
TPESQLDBG environment variable. TPESQLDBG is an array of 'Y'/'N' characters that determine
which debug options are enabled.
Prior to this revision, this was achieved by setting the 11th element (offset 10, java_debug) in
the TPESQLDBG environment variable. The logging produced in this way is quite verbose and
included information that was useful only to FairCom Technicians.
The interpretation of TPESQLDBG (and other methods setting the same debug features) has
been modified as follows:
TPESQLDBG (which was an array of 12 'Y'/'N' characters) has been expanded to 13
elements.
The element at offset 12 is a new element named stp_logging that controls the "log"
method used in stored procedures to generate log messages.
Note that activating element #11 (java_debug) activates internal logging and "log" method for
ANY stored procedure language, not just Java.
Writing .NET Stored Procedures
All Rights Reserved 108 www.faircom.com
10.5 Altering the SP, UDF, or Trigger
During development, it is often desirable to make code modifications and re-deploy a stored
procedure, UDF, or trigger. This is supported by the FairCom extension for the Visual Studio IDE.
Importing Existing Code
It is possible to retrieve existing stored procedure source code located on the server but not in the
project/solution. The Import from Server option is used to accomplish this. If the stored
procedure was deployed with source code, this option retrieves that code and adds it to the
current project to allow modification.
Altering Properties
By right-clicking on a stored procedure module in Solution Explorer and selecting c-tree
Properties it is also possible to alter stored procedure parameters, result set, name and owner.
10.6 Writing the Code
The FairCom Visual Studio extension created a stored procedure skeleton for you. By default, the
document created is shown with generated code automatically collapsed. Usually, you should not
need to alter this code; however, for advanced customization, contact FairCom for additional
customization details.
You write actual stored procedure code by implementing the ExecuteSP methods (see
SqlStoredProc (page 111), SqlUdf (page 112), or SqlTrigger (page 112)). In writing your code,
you can add new methods if necessary.
Note: You should not change the prototype of the ExecuteSP methods, which reflect actual stored procedure arguments.
Returning Errors
A stored procedure throws an exception to generate an error sent to the client. An end user
always sees a c-treeACE SQL error -20142 returned in this case. The error message indicates an
error in executing the stored procedure followed by the error number and an associated
message, such as:
error(-20142): Error in Stored Procedure/function Execution - error(-34567): my error message.
The API used to write stored procedure and the .NET runtime may also throw exceptions. If these
are not caught by your exception handling, they are passed to the c-treeACE SQL runtime and
result in a -20142 error.
Null Handling
For easier null value handling, SQL types are mapped into nullable .NET types. Whenever a
“SQL value” is referenced, the type used is nullable. Whenever an object representing a SQL
value is set to null, it indicates a “SQL value” was null (reading a column/parameter value) or it is
set to null when updating (setting a column/parameter value).
Writing .NET Stored Procedures
All Rights Reserved 109 www.faircom.com
10.7 Returning a Result Set from a Stored Procedure
A stored procedure may return a result set. In this case you must add columns to the result set
row and then add the row to a result set.
This is accomplished as shown below:
1. Create an instance of the SqlSpResulsetRow class by invoking the NewResultSetRow() method.
SqlSpRow RSrow = NewResultSetRow();
2. Set column values in a result set using the column index. For easier code writing, the generated code contains constants with the name of the result set columns and the values are the column indexes.
RSrow[RSCol.mycolumn].Value = "";
3. Add the row using ResultSetAddRow(SqlSpRow RSrow). Notice that this method creates a copy of the row, so the SqlSpRow object can be reused for additional rows.
A stored procedure may also have OUT parameters that must be set before returning. This is
enforced by the C# language as the ExecuteSP prototype implements “out” for OUT parameters.
A stored procedure may also have INOUT parameters that may or may not be set before
returning. In this case the ExecuteSP prototype implements “ref” for INOUT parameters.
10.8 Returning a UDF Result
A user-defined function is declared with a “return” value that is the return value of the ExecuteSP
method.
10.9 Accessing Old and New Rows in Triggers
Triggers do not have IN, INOUT, or OUT parameters but may receive one or two rows depending
on the definitions of REFERENCING, OLDROW, and NEWROW.
These rows are passed, when referenced, as SqlSpRow objects to the ExecuteSP method.
The methods of the SqlSpRow class can then be used to retrieve the definition and values of
columns. As is the case with stored procedure result set columns, the generated code contains
constants with the names of the result set columns and the values of the column index.
All Rights Reserved 110 www.faircom.com
11. The .NET Ctree.SqlSP Assembly
.NET stored procedures rely on an assembly named ctree.SqlSP.dll. This assembly includes a
single namespace.
The Ctree.SqlSP namespace exports classes that are specific to .NET Stored Procedures, UDFs,
and Triggers:
1. SqlSpBase (page 110)
2. SqlStoredProc (page 111)
3. SqlUdf (page 111)
4. SqlTrigger (page 111)
5. SqlSpRow (page 113)
6. SqlSpColumn (page 113)
7. SlqSpCommand (page 115)
8. SqlException (page 116)
11.1 SqlSpBase
SqlSpBase is the base class for SqlStoredProc (page 111), SqlUdf (page 112), and SqlTrigger
(page 112) classes.
This class must not be used by itself.
Constructor SqlSpBase()
Public Methods Object GetParameterValue(String name)
Return the value of the parameter with the specified name.
Object GetParameterValue(int index)
Return the value of the parameter at the specified index.
SqlSpCommand NewSqlSpCommand()
Return a new object implementing the SqlSpCommand interface to be used to execute SQL
commands.
void SetParameterValue(String name, Object value)
Set the value of the parameter with the specified name.
void SetParameterValue(int index, Object value)
Set the value of the parameter at the specified index.
The .NET Ctree.SqlSP Assembly
All Rights Reserved 111 www.faircom.com
void Err(String message)
Write a character-string message to the SQL log file, sql_server.log. You may include values
of variables or return values of methods in the string using the standard concatenation
operator (+).
void Log(String message)
Write a character-string message to the SQL log file, sql_server.log. Log includes internal
details intended for development use and should be disabled in production. You can include
the values of variables or return values of methods in the string using the standard
concatenation operator (+).
11.2 SqlStoredProc
SqlStoredProc is the class that implements a .NET stored procedure. To create a stored
procedure, a new class derived from the SqlStoredProc class must be created. This class must
implement the Execute() method, which is the method called by the server. The Visual Studio
Extension automatically performs the following:
It generates the class.
It generates the Execute() method and adds proper code to exchange the stored procedure
parameters with the server.
It creates an ExecuteSP method, which is the method to be implemented.
SqlStoredProc Class Description
This class inherits from SqlSpBase (page 110). It adds the following additional methods.
Constructor SqlStoredProc()
Public Methods void NewResultSetRow()
Return an SqlSpRow (page 113) object having columns defined as per the stored procedure
result set definition. See the SqlSpRow (page 113) description to learn how to obtain access
to column definition and values.
void ResultSetAddRow(SqlSpRow row)
Add a row to stored procedure result set. The row content is copied into an internal structure
such that the row object can be reused.
The .NET Ctree.SqlSP Assembly
All Rights Reserved 112 www.faircom.com
11.3 SqlUdf
SqlUdf is the class that implements a User Defined Function (UDF). To create a UDF, a new
class derived from SqlUdf class must be created. This class must implement the Execute()
method, which is the method called by the server. The Visual Studio Extension automatically
performs the following:
It generates the class.
It generates the Execute() method and adds proper code to exchange the UDF parameters
and return code.
It creates an ExecuteSP method, which is the method to be implemented.
SqlUdf Class Description
This class inherits from SqlSpBase (page 110). It adds the following additional methods.
Constructor SqlUdf()
Public Methods void SetReturnValue(Object obj)
Set the UDF return value.
11.4 SqlTrigger
SqlTrigger is the class that implements a Trigger. To create a Trigger, a new class derived from
the SqlTrigger class must be created. This class must implement the Execute() method, which is
the method called by the server. The Visual Studio Extension automatically performs the
following:
It generates the class.
It generates the Execute() method and adds proper code to exchange the Trigger old and
new rows (when referenced) and return code.
It creates an ExecuteSP method for you complete the implementation.
SqlTrigger Class Description
This class inherits from SqlSpBase (page 110). It adds the following additional methods.
Constructor SqlTrigger()
Public SqlSpRow GetNewRow()
The .NET Ctree.SqlSP Assembly
All Rights Reserved 113 www.faircom.com
The method above returns an SqlSpRow (page 113) object containing “newrow” columns’
values. See the SqlSpRow (page 113) description to learn how to access the columns’
definitions and values.
SqlSpRow GetOldRow()
The method above returns a SqlSpRow (page 113) object containing “oldrow” columns’
values. See the SqlSpRow (page 113) description to learn how to access the columns’
definitions and values.
11.5 SqlSpRow
SqlSpRow contains the columns of rows.
SqlSpRow Class Description
The enumerator returns an object that allows you to iterate in sequence through the
SqlSpColumn (page 113) objects in the row.
Public Methods IEnumerator GetEnumerator()
Return an enumerator for the entire row.
Public Properties SqlSpColumn this[int column]
Return the column number “column”.
int ColumnCount
Return the number of columns defined for the row.
11.6 SqlSpColumn
SqlSpColumn contains a column definition and value.
SqlSpColumn Interface Description
Public Read-Only Properties Nullability IsNullable
Get the column nullability.
String Name
Get the column name.
int Precision
Get the column precision.
The .NET Ctree.SqlSP Assembly
All Rights Reserved 114 www.faircom.com
int Scale
Get the column scale.
SqlDataType SqlType
Get the column SQL TYPE.
Boolean IsNull
Return if the SQL value is null or not.
Public Read/Write Properties Object Value
Get/Set the column value. The “object” must be of a type compatible with the column SQL
TYPE.
Byte[] BinaryValue
Get/Set a Binary column value.
DateTime? DateValue
Get/Set a Date value.
Double? FloatValue
Get/Set a Float/Double (SQL) column value.
Int32? IntegerValue
Get/Set an Integer column value.
Decimal? MoneyValue
Get/Set a Money column value.
Decimal? NumericValue
Get/Set a Numeric column value.
Boolean? BitValue
Get/Set a Bit column value.
Int64? BigIntValue
Get/Set a BigInt column value.
Single? RealValue
Get/Set a Real column value.
Int16? SmallIntValue
Get/Set a SmallInt column value.
TimeSpan? TimeValue
Get/Set the column value.
DateTime? TimeStampValue
Get/Set a TimeStamp column value.
The .NET Ctree.SqlSP Assembly
All Rights Reserved 115 www.faircom.com
Int16? TinyIntValue
Get/Set a TinyInt column value.
String CharValue
Get/Set a [Var]Char column value.
11.7 SqlSpCommand
SqlSpCommand is the class used to execute SQL commands within Stored Procedures, UDFs,
and triggers.
Public Methods int AffectedRows()
Return the number of rows affected by a command.
int Execute()
Execute a c-treeACE SQL command after it has been prepared with Prepare().
int ExecuteNonQuery(string SqlCommand)
Execute a c-treeACE SQL command directly without the need for a previous preparation of
the statement. Should the command generate a result set, it will be automatically closed and
there is no possibility to fetch it. In such case use the Prepare() followed by the Execute()
methods.
bool IsProcedureCall()
Return an indication if the statement is a SP call or not.
bool IsSelect()
Return an indication if the statement is a “SELECT ...” or not.
bool MoveNext()
Retrieve the next row from cursor.
int Prepare(string SqlCommand)
Prepare a SQL statement for execution. To execute the statement, use Execute().
Public Read-Only Properties SqlSpRow CurrentRow
Get the current row in a recordset returned by the Execute method.
SqlSpRow Parameter
Get the parameters (organized as a row) for the command (to be set before Execute, and get
after Execute).
string ErrorMessage
Return the last error’s message text.
The .NET Ctree.SqlSP Assembly
All Rights Reserved 116 www.faircom.com
11.8 SqlException
SqlException is a class representing fatal errors that occur during execution.
Constructor SqlException(int errorCode, String ErrorMessage)
Creates a new instance of Ctree.SqlSP.SqlException.
Public Properties
int ErrorCode
The numeric value of the error.
All Rights Reserved 117 www.faircom.com
12. Glossary
.NET Data Provider
A .NET Data Provider is a bridge used for connecting ADO.NET applications to a database,
executing commands and retrieving results.
add [an ODBC data source]
Make a data source available to ODBC through the Add operation of the ODBC Administrator
utility. Adding a data source tells ODBC where a specific database resides and which ODBC
driver to use to access it. Adding a data source also invokes a setup dialog box for the particular
driver so you can provide other details the driver needs to connect to the database.
ADMIN
The default owner name for all system tables in a c-treeACE SQL database. Users must qualify
references to system tables as ADMIN.tablename.
alias
A temporary name for a table or column specified in the FROM clause of an SQL query
expression. Also called correlation name. Derived tables and search conditions that join a table
with itself must specify an alias. Once a query specifies an alias, references to the table or
column must use the alias and not the underlying table or column name.
applet
A special kind of Java program whose compiled class files a Java-enabled browser can download
from the Internet and run.
ASCII
(American Standard Code for Information Interchange) A 7-bit character set that provides 128
character combinations.
bytecode
Machine-independent code generated by the Java compiler and executed by the Java interpreter.
cardinality
Number of rows in a result table.
Cartesian product
Also called cross-product. In a query expression, the result table generated when a FROM clause
lists more than one table but specifies no join conditions. In such a case, the result table is
formed by concatenating every row of every table with all other rows in all tables. Typically,
Cartesian products are not useful and are slow to process.
client
Generally, in client/server systems, the part of the system that sends requests to servers and
processes the results of those requests.
Glossary
All Rights Reserved 118 www.faircom.com
client character set
A client character set is a character set used by a client application for representing SQL
statements and data.
collation
The rules used to control how character strings in a character set compare with each other. Each
character set specifies a collating sequence that defines relative values of each character for
comparing, merging and sorting character strings.
column alias
An alias specified for a column. See alias.
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.
Along with triggers, 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.
correlation name
Another term for alias.
cross product
Another term for Cartesian product.
data dictionary
Another term for system catalog.
data source
See ODBC data source.
derived table
A virtual table specified as a query expression in the FROM clause of another query expression.
driver manager
See JDBC driver manager and ODBC driver manager.
form of use
The storage format for characters in a character set. Some character sets, such as ASCII, require
one byte (octet) for each character. Others, such as Unicode, use two bytes, and are called
multi-octet character sets.
input parameter
In a stored procedure specification, an argument that an application must pass when it calls the
stored procedure. In an SQL statement, a parameter marker in the statement string that acts as a
placeholder for a value that will be substituted when the statement executes.
interface
Glossary
All Rights Reserved 119 www.faircom.com
In Java, a definition of a set of methods that one or more objects will implement. Interfaces
declare only methods and constants, not variables. Interfaces provide multiple-inheritance
capabilities.
Java snippet
See snippet.
JDBC
Java Database Connectivity: a part of the Java language that allows applications to embed
standard SQL statements and access any database that implements a JDBC driver.
JDBC driver
Database-specific software that receives calls from the JDBC driver manager, translates them
into a form that the database can process, and returns data to the application.
JDBC driver manager
A Java class that implements methods to route calls from a JDBC application to the appropriate
JDBC driver for a particular JDBC URL.
join
A relational operation that combines data from two tables.
metadata
Data that details the structure of tables and indexes in c-tree Plus. c-treeACE SQL stores
metadata in the system catalog.
octet
A group of 8 bits. Synonymous with byte, and often used in descriptions of character-set
encoding format.
ODBC application
Any program that calls ODBC functions and uses them to issue SQL statements. Many vendors
have added ODBC capabilities to their existing Windows-based tools.
ODBC data source
In ODBC terminology, a specific combination of a database system, the operating system it uses,
and any network software required to access it. Before applications can access a database
through ODBC, you use the ODBC Administrator to add a data source -- register information
about the database and an ODBC driver that can connect to it -- for that database. More than one
data source name can refer to the same database, and deleting a data source does not delete
the associated database.
ODBC driver
Vendor-supplied software that processes ODBC function calls for a specific data source. The
driver connects to the data source, translates the standard SQL statements into syntax the data
source can process, and returns data to the application. c-treeSQL includes an ODBC driver that
provides access to c-tree Plus underlying the c-treeSQL Server.
ODBC driver manager
Glossary
All Rights Reserved 120 www.faircom.com
A Microsoft-supplied program that routes calls from an application to the appropriate ODBC driver
for a data source.
output parameter
In a stored procedure specification, an argument in which the stored procedure returns a value
after it executes.
package
A group of related Java classes and interfaces, like a class library in C++. The Java development
environment includes many packages of classes that procedures can import. The Java runtime
system automatically imports the java.lang package. Stored procedures must explicitly import
other classes by specifying them in the IMPORT clause of a CREATE PROCEDURE statement.
parameter marker
A question mark (?) in a procedure call or SQL statement string that acts as a placeholder for an
input or output parameter supplied at runtime when the procedure executes. The CALL statement
(or corresponding ODBC or JDBC escape clause) use parameter markers to pass parameters to
stored procedures, and the SQLIStatement, SQLPStatement, and SQLCursor objects use them
within procedures.
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.
procedure body
In a stored procedure, the Java code between the BEGIN and END keywords of a CREATE
PROCEDURE statement.
procedure result set
In a stored procedure, a set of data rows returned to the calling application. The number and data
types of columns in the procedure result set are specified in the RESULT clause of the CREATE
PROCEDURE statement. The procedure can transfer data from an SQL result set to the
procedure result set or it can store data generated internally. A stored procedure can have only
one procedure result set.
procedure specification
In a CREATE PROCEDURE statement, the clauses preceding the procedure body that specify
the procedure name, any input and output parameters, any result set columns, and any Java
packages to import.
procedure variable
A Java variable declared within the body of a stored procedure, as compared to a procedure input
parameter or output parameter, which are declared outside the procedure body and are visible to
the application that calls the stored procedure.
query expression
The fundamental element in SQL syntax. Query expressions specify a result table derived from
some combination of rows from the tables or views identified in the FROM clause of the
Glossary
All Rights Reserved 121 www.faircom.com
expression. Query expressions are the basis of SELECT, CREATE VIEW, and INSERT
statements, and can be used in some expressions and search conditions.
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. SQL provides two
mechanisms to enforce referential integrity: constraints specified as part of CREATE TABLE
statements prevent updates that violate referential integrity, and triggers specified in CREATE
TRIGGER statements execute a stored procedure to enforce referential integrity.
repertoire
The set of characters allowed in a character set.
result set
In a stored procedure, either an SQL result set or a procedure result set. More generally, another
term for result table.
result table
A virtual table of values derived from columns and rows of one or more tables that meet
conditions specified by an SQL query expression.
row identifier
Another term for tuple identifier.
search condition
The SQL syntax element that specifies a condition that is true or false about a given row or group
of rows. Query expressions and UPDATE statements can specify a search condition. The search
condition restricts the number of rows in the result table for the query expression or UPDATE
statement. Search conditions contain one or more predicates. Search conditions follow the
WHERE or HAVING keywords in SQL statements.
selectivity
The fraction of a table’s rows returned by a query.
server
Generally, in client/server systems, the part of the system that receives requests from clients and
responds with results to those requests.
snippet
In a stored procedure, the sequence of Java statements between the BEGIN and END keywords
in the CREATE PROCEDURE (or CREATE TRIGGER) statement. The Java statements become
a method in a class the SQL engine creates and submits to the Java compiler.
SQL diagnostics area
A data structure that contains information about the execution status (success, error or warning
conditions) of the most recent SQL statement. The SQL-92 standard specified the diagnostics
area as a standardized alternative to widely varying implementations of the SQLCA. c-treeACE
SQL supports both the SQLCA and the SQL diagnostics area. The SQL GET DIAGNOSTICS
Glossary
All Rights Reserved 122 www.faircom.com
statement returns information about the diagnostics area to an application, including the value of
the SQLSTATE status parameter.
SQL engine
The core component of the c-treeACE SQL environment. The SQL engine receives requests from
applications, processes them, and returns results.
SQLCA
SQL Communications area: A data structure that contains information about the execution status
(success, error or warning conditions) of the most recent SQL statement. The SQLCA includes an
SQLCODE field. The SQLCA provides the same information as the SQL diagnostics area, but is
not compliant with the SQL-92 standard. c-treeACE SQL supports both the SQLCA and the SQL
diagnostics area.
SQLCODE
An integer status parameter whose value indicates the condition status returned by the most
recent SQL statement. An SQLCODE value of zero means success, a positive value means
warning, and a negative value means an error status. SQLCODE is superseded by SQLSTATE in
the SQL-92 standard. Applications declare either SQLSTATE or SQLCODE, or both. SQL returns
the status to SQLSTATE or SQLCODE after execution of each SQL statement.
SQL result set
In a stored procedure, the set of data rows generated by an SQL statement (SELECT and, in
some cases, CALL).
SQLSTATE
A 5-character status parameter whose value indicates the condition status returned by the most
recent SQL statement. SQLSTATE is specified by the SQL-92 standard as a replacement for the
SQLCODE status parameter (which was part of SQL-89). SQLSTATE defines many more
specific error conditions than SQLCODE, which allows applications to implement more portable
error handling. Applications declare either SQLSTATE or SQLCODE, or both. SQL returns the
status to SQLSTATE or SQLCODE after execution of each SQL statement.
stored procedure
A snippet of Java source code embedded in an SQL CREATE PROCEDURE statement. The
source code can use all standard Java features as well as use c-treeACE SQL supplied Java
classes for processing any number of SQL statements.
system catalog
Tables created by c-treeACE SQL that store information about tables, columns, and indexes that
make up the database. c-treeACE SQL creates and manages the system catalog.
system tables
Another term for system catalog.
tid
Another term for tuple identifier.
transaction
Glossary
All Rights Reserved 123 www.faircom.com
A group of operations whose changes can be made permanent or undone only as a unit to
protect against data corruption.
trigger
A special type of stored procedure that helps insure referential integrity for a database. Like
stored procedures, triggers also contain Java source code (embedded in a CREATE TRIGGER
statement) and use c-treeACE SQL Java classes. However, triggers are automatically invoked
(“fired”) by certain SQL operations (an insert, update, or delete operation) on the trigger’s target
table.
trigger action time
The BEFORE or AFTER keywords in a CREATE TRIGGER statement. The trigger action time
specifies whether the actions implemented by the trigger execute before or after the triggering
INSERT, UPDATE, or DELETE statement.
trigger event
The statement that causes a trigger to execute. Trigger events can be SQL INSERT, UPDATE, or
DELETE statements that affect the table for which a trigger is defined.
triggered action
The Java code within the BEGIN END clause of a CREATE TRIGGER statement. The code
implements actions to be completed when a triggering statement specifies the target table.
tuple identifier
A unique identifier for a tuple (row) in a table. Storage managers return a tuple identifier for the
tuple that was inserted after an insert operation. The SQL engine passes a tuple identifier to the
delete, update, and fetch stubs to indicate which tuple is affected. The SQL scalar function
ROWID and related functions return tuple identifiers to applications.
Unicode
A superset of the ASCII character set that uses two bytes for each character rather than ASCII’s
7-bit representation. Able to handle 65,536 character combinations instead of ASCII’s 128,
Unicode includes alphabets for many of the world’s languages. The first 128 codes of Unicode
are identical to ASCII, with a second-byte value of zero.
URL
In general, a Universal Resource Locator used to specify protocols and locations of items on the
Internet. In JDBC, a database connection string in the form jdbc:subprotocol:subname. The
c-treeACE SQL JDBC Driver format for database URLs is jdbc:ctree:T:host_name:db_name.
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.
virtual machine
The Java specification for a hardware-independent and portable language environment. Java
language compilers generate code that can execute on a virtual machine. Implementations of the
Glossary
All Rights Reserved 124 www.faircom.com
Java virtual machine for specific hardware and software platforms allow the same compiled code
to execute without modification.
virtual table
A table of values that is not physically stored in a database, but instead derived from columns and
rows of other tables. SQL generates virtual tables in its processing of query expressions: the
FROM, WHERE, GROUP BY and HAVING clauses each generate a virtual table based on their
input.
All Rights Reserved 125 www.faircom.com
13. Document History
01/24/2018 Updated data type mapping table in Implicit Data Type Conversion Between SQL and Java Types (page 53).
12/03/2015 Added new V11 support:
• NetBeans Plugin for Java (page 34)
• .NET Support (page 101)
• Writing .NET Stored Procedures (page 105)
• The .NET Ctree.SqlSP Assembly (page 110)
11/11/2015 First published.
Last published Monday, October 7, 2019.
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 Type of Information
Bold Used to emphasize a point or for variable expressions such as parameters
CAPITALS Names of keys on the keyboard. For example, SHIFT, CTRL, or ALT+F4
FairCom Terminology FairCom technology term
FunctionName() c-treeACE Function name
Parameter c-treeACE Function Parameter
Code Example Code example or Command line usage
utility c-treeACE executable or utility
filename c-treeACE file or path name
CONFIGURATION KEYWORD c-treeACE Configuration Keyword
CTREE_ERR c-treeACE Error Code
All Rights Reserved cxxvii www.faircom.com
Copyright Notice
Copyright © 1992-2019 FairCom USA. 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 USA. Printed in the
United States of America.
Information in this document is subject to change without notice.
Trademarks
c-treeACE, c-treeRTG, c-treeEDGE, c-treeAMS, c-tree Plus, c-tree, r-tree, FairCom and FairCom’s circular disc logo are
trademarks of FairCom USA, 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
Portions © 1987-2019 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.
10/7/2019
All Rights Reserved 129 www.faircom.com
14. Index
.
.NET Support ........................................................ 101
.NET Tutorials ....................................................... 102
A Accessing Old and New Rows in Triggers ........... 109 Additional Resources .................................. 15, 22, 33 Altering the SP, UDF, or Trigger ........................... 108 Assigning Null Values from SQL Result Sets
SQLCursor.wasNULL Method ............................ 61 Automatic archiving ................................................ 65
C Calling Scalar Functions from a User Defined
Scalar Function ................................................... 73 Calling stored procedures ......................................... 3
from stored procedures ....................................... 63 Calling Stored Procedures ........................................ 3 Calling Stored Procedures from .NET .................... 46 Calling Stored Procedures from ISQL .................... 47 Calling Stored Procedures from JDBC ................... 45 Calling Stored Procedures from ODBC .................. 45 Calling Stored Procedures from Stored
Procedures.......................................................... 63 Cascading deletes .................................................. 65 Cascading updates ................................................. 65 Class
SQLCursor .......................................................... 56 Class reference, Java ............................................. 74 Copyright Notice ............................................... cxxviii Create Function ...................................................... 71 Create Trigger ......................................................... 67 Creating stored procedures ...................................... 2 Creating Stored Procedures ..................................... 2 c-treeSQL Java class methods ............................... 74 c-treeSQL Java classes .............................. 40, 49, 50
D Debugging stored procedures ................................ 47 Debugging Stored Procedures ............................... 47 Debugging the SP, UDF, or Trigger ..................... 107 Define ......................................................... 11, 18, 25 Deleting stored procedures .................................... 47 Deploying the SP, UDF, or Trigger ....................... 107 DhSQLException .................................................... 75 DhSQLException.getDiagnostics ........................... 76 DhSQLResultSet .................................................... 77 DhSQLResultSet procedure ................................... 59 DhSQLResultSet.insert .......................................... 77 DhSQLResultSet.makeNULL ................................. 78 DhSQLResultSet.set............................................... 79 Document History ................................................. 125
Done .......................................................... 14, 21, 32 Drop Function ........................................................ 72
E Editing Stored Procedures ..................................... 37 Enabling Debugging .............................................. 39 Environment variables ........................................... 43 Error handling ........................................................ 62 Executing an SQL Statement ................................ 54 Executing SQL statements .................................... 54
F FairCom Typographical Conventions ................ cxxvi Functions
User Defined Scaler Functions .......................... 70
G getValue method .................................................... 51 Glossary ............................................................... 117
H Handling errors ...................................................... 62 Handling Errors ...................................................... 62 Handling Null Values ............................................. 60
I Immediate execution .............................................. 55 Immediate Execution ............................................. 55 Implicit Data Type Conversion Between SQL
and Java Types .................................................. 53 Implicit data type conversions ................................ 53 Init .............................................................. 10, 17, 24 Installing the NetBeans Plugin ............................... 36 Introduction ................................................ 40, 70, 74 Introduction to Stored Procedures, Triggers, and
User Defined Functions ....................................... 1 Introductory Tutorial ................................................. 9 Invoking stored procedures ................................... 45 Invoking Stored Procedures .................................. 45 Invoking User Defined Scalar Functions ............... 72
J Java class reference .............................................. 74 Java Class Reference ............................................ 74 Java classes ........................................ 40, 49, 50, 74 Java c-treeSQL interaction ...................................... 2 Java data type conversions ................................... 53 Java environment variables ................................... 43 Java Quick Tour ....................................................... 6 Java snippet ........................................................... 41 Java Stored Procedure and Triggers require
JDK V1.7 or newer ............................................... 4 Java Stored Procedures, Triggers, and UDFs ......... 2
M Manage ...................................................... 12, 19, 28 Mapping Between SQL Types and .NET Types .. 104 Methods ................................................................. 74
Index
All Rights Reserved 130 www.faircom.com
getValue .............................................................. 51 setParam ............................................................. 50
Modifying and Deleting Stored Procedures ............ 47 Modifying stored procedures .................................. 47
N NetBeans Plugin for Java ....................................... 34 NEWROW ............................................................... 67 Null values .............................................................. 60
O OLDROW ................................................................ 67 OLDROW and NEWROW Objects
Passing Values to Triggers ................................. 67
P Passing input values to SQL statements ................ 50 Passing values from SQL result sets ...................... 51 Passing values to and from stored procedures ...... 52 Passing Values to and From Stored Procedures
Input and Output Parameters ............................. 52 Passing Values to SQL Statements ....................... 50 Prepared execution................................................. 56 Prepared Execution ................................................ 56 Procedures
DhSQLReslutSet ................................................ 59
R Record/Row Locking ............................................... 16 registerOutParam Method
registering the Type of OUT and INOUT Variables ......................................................... 58
Restrictions on Calling Java Methods in Stored Procedures.......................................................... 49
Restrictions on creating Triggers ............................ 65 RESULT clause ...................................................... 59 Retrieving data ........................................................ 56 Retrieving Data
the SQLCursor Class .......................................... 56 Returning a Procedure Result Set
the RESULT Clause and DhSQLResultSet ........ 59 Returning a result set.............................................. 59 Returning a Result Set from a Stored Procedure . 109 Returning a UDF Result ....................................... 109
S Security ................................................................... 49 setParam method ................................................... 50 Setting SQL Statement Input Params &
Procedure Result SetFields to Null ..................... 60 Setting up the Connection to the Server................. 34 Setting Up Your Environment to Write Stored
Procedures.......................................................... 43 Snippet, Java .......................................................... 41 SQL data type conversions .................................... 53 SQL statement execution ....................................... 54 SQL statements, immediate execution ................... 55
SQL statements, prepared execution .................... 56 SQLCursor ............................................................. 80 SQLCursor class .................................................... 56 SQLCursor.close .................................................... 81 SQLCursor.fetch .................................................... 81 SQLCursor.found ................................................... 82 SQLCursor.getParam ............................................ 82 SQLCursor.getValue .............................................. 84 SQLCursor.makeNULL .......................................... 85 SQLCursor.open .................................................... 86 SQLCursor.registerOutParam ............................... 86 SQLCursor.rowCount ............................................ 87 SQLCursor.setParam ............................................ 88 SQLCursor.wasNULL ............................................ 89 SqlException ........................................................ 116 SQLIStatement ...................................................... 89 SQLIStatement.execute ......................................... 90 SQLIStatement.getParam ...................................... 91 SQLIStatement.makeNULL ................................... 92 SQLIStatement.registerOutParam ......................... 92 SQLIStatement.rowCount ...................................... 93 SQLIStatement.setParam ...................................... 94 SQLPStatement ..................................................... 95 SQLPStatement.execute ....................................... 95 SQLPStatement.getParam .................................... 96 SQLPStatement.makeNULL .................................. 97 SQLPStatement.registerOutParam ....................... 98 SQLPStatement.rowCount .................................... 98 SQLPStatement.setParam .................................... 99 SqlSpBase ........................................................... 110 SqlSpColumn ....................................................... 113 SqlSpCommand ................................................... 115 SqlSpRow ............................................................ 113 SqlStoredProc ...................................................... 111 SqlTrigger ............................................................ 112 SqlUdf .................................................................. 112 Stored Procedure Basics ....................................... 40 Stored Procedure Security ..................................... 49 Stored procedures
basic coding ....................................................... 40 calling ................................................................... 3 calling from stored procedures .......................... 63 creating ................................................................ 2 debugging .......................................................... 47 deleting............................................................... 47 environment ....................................................... 43 environment variables ........................................ 43 invoking .............................................................. 45 modifying ............................................................ 47 passing values ................................................... 52 security ............................................................... 49 structure ............................................................. 41 transactions ........................................................ 49 using ................................................................... 40 versus constraints .............................................. 64 versus triggers ................................................... 64
Index
All Rights Reserved 131 www.faircom.com
writing .................................................................. 44 Structure of stored procedures ............................... 41 Structure of Stored Procedures .............................. 41 Structure of triggers .......................................... 65, 70 Structure of Triggers ............................................... 65 Structure of User Defined Functions ...................... 70 Summation updates ................................................ 65
T Testing the SP, UDF, or Trigger ........................... 107 The .NET Ctree.SqlSP Assembly ......................... 110 The getValue Method
Pass Values from SQL Result Sets to Variables ......................................................... 51
The setParam Method Pass Input Values to SQL Statements ............... 50
Transaction Processing .......................................... 23 Transactions ........................................................... 49 Transactions and Stored Procedures ..................... 49 Trigger
basics ............................................................ 64, 70 passing values .................................................... 67 structures ...................................................... 65, 70 uses .................................................................... 65 versus constraints ............................................... 64 versus stored procedures ................................... 64
Trigger Basics ......................................................... 64 Triggers vs. Stored Procedures vs. Constraints ..... 64 Typical Uses for Triggers ........................................ 65
U User Defined Scalar Function Security................... 73 User Defined Scaler Functions ............................... 70 Using c-treeACE SQL Java Classes ...................... 50 Using Java Stored Procedures ............................... 40 Using stored procedures ........................................ 40 Using Triggers ........................................................ 64 Using User Defined Scalar Functions ..................... 70
V Visual Studio .NET Development ......................... 101
W What Is a Java Snippet? ......................................... 41 With Constants ....................................................... 72 With Constants and Column References ............... 72 With parameter reference (ODBC/JDBC)............... 73 Writing .NET Stored Procedures .......................... 105 Writing a New SP, UDF, or Trigger ...................... 106 Writing stored procedures ...................................... 44 Writing Stored Procedures ..................................... 44 Writing the Code ................................................... 108