Stoproc
Stoproc
Stoproc
Version 6.8.1.83
September 10, 2015
Contents
1 Introduction 3
1.1 Abbreviations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Copyright Information . . . . . . . . . . . . . . . . . . . . . . . . . 4
2 Getting Started 5
2.1 A ’Hello World from Java’ Example . . . . . . . . . . . . . . . . . 5
2.1.1 Write a Stored Procedure . . . . . . . . . . . . . . . . . . . 5
2.1.2 Load your code . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.1.3 Publishing your Methods in SQL . . . . . . . . . . . . . . . 6
2.1.4 Execute your Methods . . . . . . . . . . . . . . . . . . . . . 6
2.2 A ’Hello World from C’ Example . . . . . . . . . . . . . . . . . . . 7
2.2.1 Write a User-defined Function . . . . . . . . . . . . . . . . . 7
2.2.2 Compile your code . . . . . . . . . . . . . . . . . . . . . . . 7
2.2.3 Load your code . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.4 Publishing your Methods in SQL . . . . . . . . . . . . . . . 8
2.2.5 Execute your Methods . . . . . . . . . . . . . . . . . . . . . 8
2
CONTENTS 3
7 Troubleshooting 47
7.1 The retrieval or update of an external resource, method, or option
failed, the system catalog might be corrupted (Error 16600) . . . . 47
7.2 Internal JDBC Driver not correctly installed (Error 16700) . . . . 47
7.3 Cannot create Java VM (Errors 16705 and 16720) . . . . . . . . . 47
7.4 Transbase crashes on first access to a UDF or STP . . . . . . . . . 48
7.5 System hangs or crashes during heavy UDF or STP load on Unix
/ Unexpected Signal : 11 . . . . . . . . . . . . . . . . . . . . . . . 48
7.6 Exceptions in classes from the Transbase runtime package . . . . . 48
Introduction
Stored Procedures (STP) and User-Defined Functions (UDF) enable any Trans-
base user to extend server side functionality by providing user-defined routines
explicitly callable via SQL statements or implicitly by event driven database trig-
gers. Additionally a Java enabled Transbase server also allows for implementing,
loading, and executing Java code.
The STP extension of Transbase aims to meet the the standard for SQL-invoked
routines as defined in American National Standard for Information Technology
- Database Language SQL - Part 4: Persistent Stored Modules (SQL/PSM),
ANSI/ISO/IEC 9075-4-1999.
Many features of Transbase STP extension for Java are compatible to the SQL
standard extension as defined in American National Standard for Information
Technology - Database Languages - SQLJ - Part 1: SQLJ Routines using the
Java™ Programming Language, ANSI NCITS 331.1-1999.
However, in some cases, it was more suitable to leave the standard aside, in order to
full exploit special features available in the Transbase database system. And finally
there were cases where the standard was implemented but additional features or
variations were introduced to make STPs and UDFs more powerful and easier to
use. Deviations from the standard are annotated.
To value the safety of running interpreted code inside a virtual machine over
using the performance oriented approach of loading user-defines libraries into the
address space of the database kernel, we will first discuss the Java SQL extension.
Chapter 2 of this manual is a simple example on how to create and use stored
procedures and user-defined functions. The first section addresses code written
in Java and the second section attends to code residing in dynamic libraries.
Chapter 3 is a reference of the Transbase Extension accompanied by numerous
examples to illustrate the SQL extension reference. Chapter 4 covers Java specific
SQL extension topics while Chapter 5 addresses the properties of native code in
libraries. Chapter 6 illustrates how the STP extension is used via a database
5
6 CHAPTER 1. INTRODUCTION
1.1 Abbreviations
In this manual uses a set of common abbreviations. Consult the following table if
any abbreviations should be unclear:
JRE: Java Runtime Environment
JDB: Java Debugger
JDE: Java Developer Environment
JNI: Java Native Interface
JVM: Java Virtual Machine
PSM: Persistent Stored Module
SDK: Standard Developer Kit
STP : Stored Procedure
TBJRE: Transbase Java Runtime Environment
UDF: User-Defined Function
Getting Started
The following tutorial will guide you through the required steps to write, compile,
load, publish, and execute a stored procedure and user-defined function on a Java
enabled Transbase Server in two simple ’Hello World’ examples.
Create a new file, name it ClassHelloWorld.java and paste the following code into
it.
Example:
import java.sql.*;
public class ClassHelloWorld
{
// this is a simple stored procedure
public static void ProcHelloWorld() throws SQLException,
ClassNotFoundException
{
Class.forName("transbase.jdbc.Driver");
Connection conn =
DriverManager.getConnection("jdbc:default:connection");
7
8 CHAPTER 2. GETTING STARTED
stmt.close();
conn.close();
return;
}
You can compile and debug your code with your Java Developer Kit or any available Java
IDE and load compiled classes into the database. You can also pack your classes into JAR
files. There are two ways for adding JARs to the system. JARs are either stored in the
system just like classes, refer to ’CreateExternalStatement’ for details. Otherwise they
are stored on the file system and are referenced via the CLASSPATH option as discussed
in the ’AlterExternalOption’ section.
Run the Java Compiler javac on your command line:
javac ClassHelloWorld.java
This generates a new file ClassHelloWorld.class. Have tbjdbc.jar available in you CLASS-
PATH variable for imports. To get your binary into the database, first connect to it with
your tbi and type in the following statement:
In the next step, you tell Transbase, which of your Methods you want to have available
in SQL and how you want to name them. So type the following into tbi:
CALL CreateHelloWorld();
SELECT * FROM HelloWorld;
2.2. A ’HELLO WORLD FROM C’ EXAMPLE 9
SELECT HelloWorld();
For a complete overview of built-in Java functions, please refer to this table.
Create a new file, name it HelloWorld.c and paste the following code into it.
Example:
Depending on the platform you are using there is a variety on how to compile your code
into a dynamic library. Here is a list or important requirements to consider:
To get the code into the database, first connect to it with your tbi and type in the following
statement:
or
In the next step, you tell Transbase, which of your Methods you want to have available
in SQL and how you want to name them. So type the following into tbi:
SELECT HelloWorld();
In order create and manipulate external resources, STPs, and UDFs various extensions
have been made to TB/SQL. This chapter is the Reference Manual to those extensions.
Syntax:
CreateExternalStatement ::=
CREATE EXTERNAL
ResourceSpec
FROM FileName [LOCAL]
[[NOT] FOR DEBUG]
[COMMENT "comment"]
ResourceSpec ::=
[CLASS|JAR] ResourceName]
11
12 CHAPTER 3. SQL EXTENSIONS REFERENCE
Alternatively packages can be moved to a JAR file. This file can either be loaded into
the system via this statement, there it becomes an integral part of the database, or it
may be referenced through the CLASSPATH option, as desribed in ’AlterExternalOption’
statement.
For accessing any resources, at least one of their methods has to be published by the
corresponding ’CreateProcedureStatement’.
FileName is an identifier for the file. The syntax of FileName is defined via the underly-
ing operating system. Since for Java the filename always specifies the class name and the
file extensions specifies the resource type and currently no resources of other program-
ming languages with conflicting resource names can be loaded, one can completely omit
ResourceSpec. If both, ResourceSpec and FileName are available, the systems performs
cross checks to ensure consistency. Without the LOCAL keyword, the specified file is read
by the client application and transferred to the tbkernel process. If the file is accessible by
the tbkernel process via FileName, the LOCAL clause can be used to speed up the trans-
fer process: in this case the tbkernel process directly accesses the file under the specified
name which must be an absolute path name.
The Debug clause is optional and reserved for future versions, where remote debugging of
stored resources on resource basis will be enabled. Remote debugging is currently available
through the procedure described in ’RemoteMethodDebugging’.
In the Comment clause you can describe the functionality, version, author, and other
additional information on this resource.
Note that the CreateExternalStatement is a custom Transbase SQL extension and is not
a standardized part of SQL3 or SQLJ. However, a subset of functionality of this statement
offers the same functionality as the SQLJ.INSTALL JAR built-in procedure introduced
by the ANSI standard.
Privileges: The user must have userclass DBA or RESOURCE. For the definition of
userclasses see the chapter ’GrantUserclassStatement’ in your SQL Reference Manual.
Syntax:
AlterExternalStatement ::=
ALTER EXTERNAL
[CLASS {BINARY|SOURCE}]
[{ENABLE|DISABLE}]
ResourceName
[FROM FileName [LOCAL]]
[[NOT] FOR DEBUG]
[COMMENT "comment"]
3.3. ALTER EXTERNAL OPTION STATEMENT 13
Explanation: Enable or Disable resources without changing access rights. You can
replace loaded resources with newer versions, change the debug flag or the associated com-
ment. All changed leave the usage privileges of this resource and its routines unchanged.
If you replace a java class that has already been loaded into your virtual machine, the
system will automatically unload this class, and load the new class to the system.
Note that the AlterExternalStatement is a custom Transbase SQL extension and is not a
standardized part of SQL3 or SQLJ. However, a subset of functionality of this statement
offers the same functionality as the SQLJ.REPLACE JAR built-in procedure introduced
by the ANSI standard.
Syntax:
AlterExternalOption ::=
ALTER EXTERNAL OPTION
{JAVA|JDK|CLASSPATH|JAVADEBUG|JAVAPERMISSIONS}
"optionstring"
Explanation: The JAVA option is a set of command line options you want to use with
your virtual machine. Consult your java documentation for more information or type java
-h and java -X on the command line to get short information on standard and non-
standard java options, if you have a SDK or JRE installation available on your machine.
The default setting of these options for the Transbase Java Runtime Environment is ’-
Xms2m -Xmx20m’ in order to get some control over the Java VMs heap allocation by
restricting it to a range from two to twenty megabytes.
The option JDK points to the base directory of your custom JDK installation. It is
strongly recommended to use an SDK (Standard Developer Kit) installation instead of the
smaller JRE (Java Runtime Environment) because the class compiler is only available in
the SDK. However, if you do not require class compilation, then a simple JRE installation
will be sufficient. An empty option string makes the system use the standard JDK shipped
with your Transbase installation which is located in the tbjre subdirectory. SDKs and
JREs prior to version 1.2 will not function with the Transbase system. For reasonable
performance it recommended to use SDKs and JREs featuring the Java HotSpot Server,
which is available with release 1.3 and later. MS Windows users have to download and
install the HotSpot Server separately for it is not included in the SDK Edition of Java.
Note that any Java enabled Transbase distribution always includes an up-to-date HotSpot
Server in its TBJRE.
The CLASSPATH option holds directories and jar files you want the JVM to check for
required classes. If the systems fails to find a resource in the set of loaded resources
14 CHAPTER 3. SQL EXTENSIONS REFERENCE
it consults the CLASSPATH to search the local file system. This is very similar to the
CLASSPATH environment variable as known for the JVM. This is a way to make resources
available that are not stored in the Transbase system itself, in particular jar files that
cannot be loaded to the system with this Transbase version. For information on security
issues involved in usage of external resources see ’ClassLoadingAndCompilation’.
The JAVADEBUG option is used to supply the JVM with a set of additional options
for starting the JVM in debug mode, leaving out the ’-Xrunjdwp:’ prefix. Check your
java documentation for further information. The default setting of JAVADEBUG in the
TBJRE is:
transport=dt_socket,address=5000,suspend=y,server=y
This defines the transport protocol and the address where the Transbase server listens
for a connecting Java Debugger (JDB). A simple sanity check is performed if the JVM is
to be started in debug mode, where the existence of the tokens ’transport=’, ’address=’,
’suspend=y’, ’server=y’ and the absence of ’Xrunjdwp’ is demanded.
The JAVAPERMISSIONS option makes the installed SecurityManager configurable. One
can either drop all restrictions by globally permitting any access:
Note that a change of any option requires a restart of the JVM to take effect.
Unrecognized options will be ignored by the Virtual Machine, in order to guarantee a
reliable startup behavior. The actual setting of the JVM properties can be inspected by
checking the System.Properties of a Virtual Machine with user-defined functions.
Note that AlterExternalOption is a custom Transbase SQL extension and is not a stan-
dardized part of SQL3 or SQLJ. However, a subset of functionality of this statement offers
the same functionality as the SQLJ.ALTER JAVA PATH built-in procedure introduced
by the ANSI standard.
Syntax:
DropExternalStatement ::=
DROP EXTERNAL
[CLASS|JAR]
ResourceName
3.5. CREATE PROCEDURE/FUNCTION STATEMENT 15
Privileges: The user must be owner of the external resource or of userclass DBA.
Syntax:
CreateProcedureStatement ::=
CREATE PROCEDURE
SQLName SQLSignature
[SQLProperties]
[DYNAMIC RESULT SETS integer]
ExternalBlock
CreateFunctionStatement ::=
CREATE FUNCTION
SQLName SQLSignature
RETURNS { SQLDataType | TABLE [OutFieldList] }
[SQLProperties]
[CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT]
ExternalBlock
SQLProperties ::=
[[NOT] DETERMINISTIC]
[DataAccessIndication]
[WITH[OUT] OWNER RIGHTS]
[{CHECK|IGNORE} EXCEPTION]
16 CHAPTER 3. SQL EXTENSIONS REFERENCE
[COMMENT "comment"]
DataAccessIndication ::=
{NO SQL | CONTAINS SQL | READS SQL DATA | MODIFIES SQL DATA}
Definitions:
you may cast results in SQL if another type is required or explicitly map them
with the optional JavaSignature. Resulttype TABLE may only be used with func-
tions. If resulttype is TABLE then the function may only have IN parameters in
its SQLSignature and only Parametermode OUT is allowed in the OutFieldList. If
OutFieldList is missing, then the function is a Generic Table Function.
ParameterMode Specifies whether the SQL parameter is input only (IN), output only
(OUT) or both input and output (INOUT). The ParameterMode may only be
specified for stored procedures, since user-defined functions only use parameters
in IN mode. To meet the object paradigm of the Java programming language,
two additional modes are introduced: INSTANCE and INSTANCEOUT. Consult
’ParameterModes’ for more detailed information. These two modes are not defined
in the ANSI standard. If you do not want to use non-standard ParameterMode,
you still can write a wrapper class for the exported methods in question, and have
this wrapper do the casts and type conversions (see ’JavaWrappers’).
deterministic Optimizer hint. The deterministic option tells the optimizer that for a
given set of argument values, the procedure or function returns the same values for
OUT and INOUT parameters and function result.
not deterministic Optimizer hint. Specifies that the procedure or function does not
have the deterministic property. This is the default, if neither deterministic nor not
deterministic is specified.
DataAccessIndication Specifies the SQL facilities that the Java method is allowed to
perform. The restrictions apply directly to the specified method itself and to any
methods that it invokes, directly or indirectly (e.g. through triggers). However the
access indication does not apply to finalizer methods. Finalizer are always executed
with a NO SQL access indication. If DataAccessIndication is not specified, then
contains sql is the default. Any violation of DataAccessIndication will result in an
SQLException and is a hard error. In that case the current transaction will be
rolled back.
no sql The method cannot invoke SQL operations.
contains sql The method can invoke SQL operations, but cannot read or modify SQL
data. I.e. the method cannot perform SQL open, close, fetch, select, insert, update,
or delete operations. The contains sql option is the default DataAccessIndication.
reads sql data The method can invoke SQL operations, and can read SQL data, but
cannot modify SQL data. I.e. the method cannot perform SQL insert, update, or
delete operations.
modifies sql data The method is allowed to invoke SQL operations and to read and
modify SQL data.
with[out] owner rights This options allows the programmer to specify, whether any
user executing his procedure or function inherits the creator’s specific owner rights
for the duration of the function call. This allows users to use and manipulate data
in a controlled way through ’privileged’ stored procedures or user-defined functions.
With owner rights is the default if none of these options is specified. These options
are not contained in the ANSI standard.
18 CHAPTER 3. SQL EXTENSIONS REFERENCE
check exception Optimizer hint. If check exception is specified, then explicit exception
checking is performed after any returning procedure and after any function returning
a NULL value, that is in any case when an exception may have occurred. This option
is not contained in the ANSI standard.
ignore exception Optimizer hint. The Transbase system will not check for exceptions.
The programmer has to take care that his routine does not throw any exceptions
and to take appropriate actions to detect and handle exceptions in a reasonable way
for his application, e.g. try/catch blocks in Java, indicator variable as INOUT or
OUT variable of a stored procedure and null-checking. This option is not contained
in the ANSI standard.
comment a user-defined comment on the function. The maximum length of a comment
is MAXCOMMENTSIZE (=255).
dynamic result sets Specifies that the Java method may return SQL result sets. dy-
namic result sets can only be specified in a create procedure statement, not in a
create function statement. The specified integer value is the maximum number of
result sets that the method will return. The maximum value is 255. The dynamic
result sets clause is of no practical use at the moment, since the current JDBC
Implementation does not yet support Callable statements. You may use a Table
Function returning one table instead.
returns null on null input and called on null input Specifies the action to be taken
when an argument of a function call is null. If you specify returns null on null
input, then at runtime if the value of any argument is null, then the result of the
function is set to null, and the function body is not invoked. If you specify called
on null input, then a runtime exception is thrown if an SQL null value if found
for an argument whose Java data type is boolean, byte, short, int, long, float, or
double. If you do not specify either returns null on null input or called on
null input, then called on null input is the default.
external Specifies that the create statement defines an SQL name for a routine written
in a programming language other than SQL. Optional since Java is currently the
only supported external language.
parameter style java Specifies that the runtime conventions for arguments passed to
the external routine are those of the Java programming language. Optional since
Java is currently the only supported external language.
Name Specifies the name of a Java method. A reference to the SQL name is effectively
a synonym for the specified Java method. The external name is specified in a
character string literal representing a fully qualifying method name in Java notation,
e.g. ”[[jarname:]packagename.]classname.methodname”. The surrounding double-
quotes are the delimiters of that literal. If a class is to be retrieved from the
JDK Archives or via the CLASSPATH option, then the jarname has to be added.
Transbase cannot check jarname validity, but will try to retrieve the class via the
alternative ’ClassLoading’. Note that classes residing in jars may also belong to
packages and the packagename is required for the fully qualifying method name.
Note that MethodFullName is case sensitive.
JavaSignature this optional second signature offers the possibility to substitute default
type mappings with alternative type mappings as described in table ’JavaTypeMap-
pings’. You can also supplement your custom type mapping, if your custom class
3.6. ALTER PROCEDURE/FUNCTION STATEMENT 19
Privileges: The user must be owner of the external resource or userclass DBA. If
MethodFullName references a resource that is stored outside the database, e.g. a jar file
on the local file system that is referenced through the CLASSPATH option, userclass DBA
is required.
Syntax:
AlterProcedureStatement ::=
ALTER PROCEDURE [{ENABLE|DISABLE}] SQLName SQLSignature
[NAME NewSQLName NewSQLSignature]
[SQLProperties]
[DYNAMIC RESULT SETS integer]
[ExternalBlock]
AlterFunctionStatement ::=
ALTER FUNCTION [{ENABLE|DISABLE}] SQLName SQLSignature
[NAME NewSQLName [NewSQLSignature]]
[RETURNS SQLDataType]
20 CHAPTER 3. SQL EXTENSIONS REFERENCE
[SQLProperies]
[CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT]
[ExternalBlock]
SQLProperties ::=
[[NOT] DETERMINISTIC]
[{CHECK|IGNORE} EXCEPTION]
[WITH[OUT] OWNER RIGHTS]
[{NO SQL | CONTAINS SQL | READS SQL DATA | MODIFIES SQL DATA}]
[COMMENT "comment"]
Explanation:
Privileges: The user must be owner of the external resource or userclass DBA. If
MethodFullName references a resource that is stored outside the database, e.g. a jar file
on the local file system that is referenced through the CLASSPATH option, userclass DBA
is required.
3.7. CALL STATEMENT 21
Syntax:
CallStatement ::=
CALL SQLName ( [Expression [, Expression]...] )
Privileges: The current user must have USAGE privilege on the external resource or
on the external routine. Note that one routine may call any other routine declared public
and available in database or through the CLASSPATH option. USAGE privilege is only
checked for the entry-point, whereas SQL privileges such as SELECT, INSERT, UPDATE
are checked for every issued SQL statement. SQL privileges will be checked against the
resources’ owner privileges, if the routine is called WITH OWNER RIGHTS, otherwise
the will be checked against the current users’ privileges.
Syntax:
DropProcedureStatement ::=
DROP PROCEDURE SQLName SQLSignature
DropFunctionStatement ::=
DROP FUNCTION SQLName SQLSignature
Privileges: The user must be owner of the external resource or of userclass DBA.
Syntax:
GrantUsageStatement ::=
GRANT USAGE ON Resource
TO UserList
[WITH GRANT OPTION]
Resource ::=
CLASSPATH
| EXTERNAL ResourceName
| {PROCEDURE | FUNCTION} SQLName SQLSignature
UserList ::=
UserIdent [,UserIdent] ...
UserIdent ::=
PUBLIC | UserName
Privileges: The current user must be owner of the external resource, of userclass DBA,
or must have all specified privileges with the right to grant them.
Syntax:
RevokeUsageStatement ::=
REVOKE USAGE ON Resource
FROM UserList
Resource ::=
CLASSPATH
| EXTERNAL ResourceName
| {PROCEDURE | FUNCTION} SQLName SQLSignature
UserList ::=
UserIdent [,UserIdent] ...
UserIdent ::=
PUBLIC | UserName
Explanation: If the current user is owner of the resource, then the specified privileges
are removed from the user such that none of the privileges are left for the user.
If the current user is not owner of the resource, then the privilege instances granted by
the current user are removed from the specified users. If some identical privileges had
been additionally granted by other users, they remain in effect.
Note: It is not an error to REVOKE privileges from a user which had not been granted
to the user. This case is simply treated as an operation with no effect. This enables an
error-free REVOKING for the user without keeping track of the granting history.
Note: The implementation of the RevokeUsageStatement is optional in the ANSI NCITS
331.1-1999 standard.
Privileges: The current user must be owner of the external resource, have userclass
DBA, or must have all specified privileges with the right to grant them.
Chapter 4
4.2 Transactions
SQL statements issued over the internal JDBC driver are executed within the transac-
tion context from which the STP or UDF was originally called. In particular a STP
or UDF may not begin, roll back or commit a transaction. An attempt to do this will
always thrown an SQLException. This means the transaction context before and after
the execution of a STP is exactly the same, if no error occurred. This also means that
AutoCommitMode is OFF by default for the internal JDBC Driver, whereas it is ON for
any external transbase.jdbc.Driver connection. Additionally the consistency level for
24
4.3. JAVA TYPE MAPPINGS 25
int java.lang.String.length()
maps to
Use INSTANCEOUT for procedures if you have an instance method and the first param-
eter is in INOUT mode.
Note that SQL data types are always mapped to the same java type, regardless of variable
length or precision. Thus any length or precision specifications are irrelevant for type
mapping. They will be adapted dynamically for Java IN parameters during run-time.
However, if you use a user-defined function with OUT or INOUT parameters to insert or
update data of a variable length SQL type, the function call should be accompanied by
an explicit cast specifying the length of the destination field.
method. E.g. an object of class myclass that converts to and from class String has to
have a constructor method:
Note: Only default and alternative type mappings are within the scope of the ANSI
SQL99 standard.
1. The first resolution attempt uses function name, type (function or procedure) and
parameter arity only. If resolution succeeds without type information then value
adaptation is performed on the parameter values.
2. An explicit CAST on a parameter is never overridden.
3. If the first resolution attempt (rules 1 and 2) was ambiguous, a second attempt
using the exact parameter types will commence.
4. If resolution is still ambiguous, then the method is not determinable.
This concept will allow you to write ad-hoc queries without worrying about the actual
signature of a function too much, e.g. it is legal to call function double sqrt(double) with
all sorts of scalar expressions as parameter. On the other hand, an application developer
should always keep Rule 4 in mind. If at some point in time a second function numeric
sqrt(numeric) should be added, e.g. for higher accuracy, then a call sqrt(integer) will fail
because of Rule 4 and thus an application might stop working as new methods introducing
name collisions are added to the database. A cautious application developer will avoid
this problem by using Rules 2 and 3, i.e. by explicitly casting any parameter to the correct
type or by converting to the exact signature on the client side. This should be no problem,
since UDFs and STPs are typically developed especially for one particular schema where
parameter types are defined by column types, and type safety is guaranteed.
28 CHAPTER 4. IMPLEMENTATION GUIDE - JAVA
So these types may represent SQL NULL values by using a Java null reference. But aside
from objects and arrays, Java supports a set of primitive data types, namely
In Java these parameters are always passed by value. Thus, for these types there exists
no representation of SQL NULL values. An attempt to call a UDF with a NULL value
for such an scalar parameter will raise an error condition. When you code Java methods
specifically for use in SQL, you will probably tend to specify Java parameter data types
that are the nullable Java data types. You may, however, also want to use Java methods
in SQL that were not coded for use in SQL, and that are more likely to specify Java
parameter data types that are the scalar (non-nullable) Java data types.
You can call such functions in contexts where null values will occur by invoking them
conditionally, e.g. in case expressions, e.g.:
You can also make such case expressions implicit, by specifying the returns null on null
input option in the create function statement, see ’CreateProcedureStatement’. Both
approaches are equivalent.
For OUT and INOUT parameters the corresponding parameter has be of an array type of
the mapped java type, e.g. an INOUT parameter of SQL type INTEGER is either an int[]
using default mapping or java.lang.Integer[] using alternative mapping. This array will
only contain one element. In case of an INOUT parameter, it holds the input parameter,
in case of an out parameter it will initialized with null. The stored procedure is then
responsible to supply a new valid value for output or a null value.
If the stored procedure uses SQL, then a JDBC connection to the current database context
can be acquired by opening a JDBC default connection, i.e.
Class.forName("transbase.jdbc.Driver");
Connection conn =
DriverManager.getConnection("jdbc:default:connection");
So the body of a stored procedure executing an update query and returning a success or
error indicator in a supplied boolean OUT-parameter could look like this
Example:
#import java.sql.*
Statement stmt;
ResultSet rs;
try {
rs=stmt.executeUpdate(updatequery);
} catch (SQLException e) {success[0]=false; return;}
success[0]=true;
return;
}
}
Example:
whereas
Example:
is legal code, because here an implicit instantiation of String a[0] takes place.
INOUT parameters of fixed length, precision, or range, such as CHAR, BINCHAR, BITSS,
NUMERIC, DATETIME, and TIMESPAN must not return a value of greater length,
precision, or range as OUT value, than the corresponding IN value yields. This restriction
shall provide for type safety and to ensure that the host variable storing the IN-value is
also capable of storing the OUT-value. If you know that there is more space required for
the return value, then you can explicitly cast your INOUT parameter to provide a higher
or the highest possible space for a return value.
Example:
may return any CHAR(*) value up to the max. possible length (MAXSTRINGSIZE).
OUT parameters always provide enough space for the max. possible OUT-value of that
type.
4.13. PATTERN FOR A USER-DEFINED VALUE FUNCTION 33
Class.forName("transbase.jdbc.Driver");
Connection conn =
DriverManager.getConnection("jdbc:default:connection");
Example:
#import java.sql.*
Statement stmt;
try
{
stmt.executeUpdate(updatequery);
} catch (SQLException e) {return false;}
return true;
}
}
Additionally to static methods the Transbase extension for Java offers the possibility
to use instance methods. However, instance methods do not perform as well as static
methods do, because of the additional overhead for creating and destroying the instance.
Thus it is recommended to use instance methods with care and only if it is inevitable, if
you do not have influence on the signature, e.g. for methods from rt.jar or any other third
party jar. With instance methods the first SQL parameter of a value function has to be in
parameter mode INSTANCE or INSTANCEOUT. This parameter will then be used by the
Transbase system to construct the java object by calling the parameter classes’ standard
constructor method. This parameter will then of course not appear in the java methods
signature, but it is available through its this object self reference, respectively its value
34 CHAPTER 4. IMPLEMENTATION GUIDE - JAVA
by calling this.value(). The return value of the function is set that way too, in case of an
INSTANCEOUT parameter. An example is provided in ’CreateFunctionStatement’.
Of course arbitrary instance methods can be called from a static context by writing a
wrapper method, see ’JavaWrappers’.
• one public constructor method taking all IN parameters of this method. This
method is only invoked once for a pass through a table.
• one public non-static method returning boolean and having the OUT-signature
defined by the output-table and no IN-parameters. The returned value is true if
the OUT-parameters hold valid results or false if no more rows are delivered.
• it has be guaranteed that the method returns false after a finite number of evalu-
ations.
The programmer may also supply a public void finalizer() method for cleaning up
before the instance is destroyed. Keep in mind that finalizers always run with NO SQL
access indication, and therefore no use of SQL is allowed here.
Note: If the table function takes part in a nested loop join, then constructor and
finalizer will be called several times, once for each loop. Due to the asynchronous nature
of Java’s garbage collection, that calls the finalizer method immediately before collecting
the object, it is recommended to relocate the cleaning up routines from the finalizer to the
instance method, just before it returns false for the first time. So it is always guaranteed
that used Connections, Statements, ResultSets, or other resources are closed BEFORE
the next loop is invocated. If you join two table function, keep in mind that you have to
carefully balance opened resources, since both functions concurrently use limited resources
such as cursors for open queries (i.e. ResultSets).
Note: Name resolution for table functions uses only the function name and the IN
parameter list.
The following example illustrates this by implementing a hierarchical depth first search
in a table defined by
and populated by
4.14. PATTERN FOR A USER-DEFINED TABLE FUNCTION 35
and returning records of root and all sons in depth first sort order. The function itself is
published to the SQL system by this DDL statement (cp. ’CreateFunctionStatement’)
Example:
import java.sql.*;
import transbase.tbx.TBConst;
{ id[0]=rs[usedRS].getInt(1);
• First the public constructor method is invoked, taking all IN parameters of this
method. This method is invoked twice for one pass through a table. The first call
comes from the DBMS SQL compiler in order to determine the table structure.
• Then the method public int getColumnCount() is called by the DBMS SQL
compiler to retrieve the number of columns. Now, for every column the method
public int getColumnType(int column) is invoked to get column type codes as
4.15. PATTERN FOR GENERIC TABLE FUNCTIONS 37
The following example illustrates the use of Generic Table Functions on an ArrayReader
class that returns data from several private arrays. The ArrayReader has one boolean IN
parameter showall which arranges that only the first or both columns are returned.
Example:
import java.sql.SQLException;
return java.sql.Types.CHAR;
else if(showall && col==2)
return java.sql.Types.INTEGER;
else throw new SQLException("Column index " + col + " out of bounds");
}
The function is published by using the following DDL statement (cp. CreateFunction-
Statement)
The next example is a SimpleJDBCReader that is capable of querying any JDBC data
source using an arbitrary SQL query and makes the data available to the Transbase DBMS.
Note that the corresponding JDBC Driver has to be registered before execution. Refer to
the java.sql.DriverManager documentation for an overview on how to register various
drivers. Additionally the used driver has to be available in the system’s CLASSPATH option
(see ’AlterExternalOption’).
Note: An more sophisticated version of this handy Generic Table Function is available
as built-in JDBCReader in every Transbase database where Generic Table Functions are
supported.
4.15. PATTERN FOR GENERIC TABLE FUNCTIONS 39
Example:
import java.sql.*;
if (result.next()) {
for (int i = o.length - 1; i >= 0; i--)
o[i][0] = result.getObject(i + 1);
return true;
}
else
return false;
}
}
40 CHAPTER 4. IMPLEMENTATION GUIDE - JAVA
The following steps show the necessary configuration for using third-party JDBC drivers
to be used by the JDBCReader. 1. Add the third-party driver to the JRE’s CLASSPATH.
Make sure that the file is accessible for the Transbase service. Note that the CLASSPATH
points to the JAR file, not only to the directory:
2. Make sure the driver registers with the system’s JDBC driver manager by providing
the driver’s fully qualified class name
3. Allow the driver to access network resources. Possibly other permissions are also
required:
Now the third-party database may be accessed by calling the JDBCReader using the
appropriate connection URL.
Example:
CALL Debugger();
This call will always return an error code, either 16718 (JVM DEBUG ON) if you suc-
cessfully switched to debug mode or 16719 (JVM DEBUG OFF) if the JVM is already
42 CHAPTER 4. IMPLEMENTATION GUIDE - JAVA
5.1 Limitations
In contrast to the framework for STPs from Java, there are a number limitations to the
framework for functions from native libraries at the moment.
• SQL queries from the libraries to the local Transbase instance are not supported.
• Stored Procedures are not supported.
• Table Functions are not fully supported. Only generic table functions are available.
A list of examples on how to compile and link on various platforms can also be found
there.
43
44 CHAPTER 5. IMPLEMENTATION GUIDE - NATIVE LIBRARIES
int <prefix>Open(..., int taid, int cons, void** cctx, void** sctx);
int <prefix>Next(void* sctx, void*** result, int* eod);
void TbExtLoad(void);
void TbExtUnload(void);
All calls to a table instance implemented as Generic Table Function refer to the same
Context structs/objects (sctx for statement context and cctx for connection context).
These are allocated once in the Open() routine using a freely definable set of input parame-
ters (e.g. connection string, user name, password). Additional parameters for transaction
id taid and consistency cons are compulsory. As results, query and connection contexts
are passed to the DBMS which retains them and passes them as first parameter to ev-
ery subsequent call to routines referring to this table. Finally the statement context is
freed in a call to Close() and the connection context is closed by calling Disconnect.
The structure of the output table is determined by the DBMS dynamically via routines
interface, which are called in this order:
• First the Open() routine is invoked, taking all IN parameters of this method. This
method is invoked twice for one pass through a table. The first call comes from the
DBMS SQL compiler in order to determine the table structure.
• Then the method GetColumnCount() is called by the DBMS SQL compiler to re-
trieve the number of columns. Now, for every column the method GetColumnType()
is invoked to get column type codes as defined in tbx.h. Finally the name of each
column is queried by calling GetColumnName().
• Now Close() is called to conclude the SQL compiler run. Here the Table Function
should release all resources, including the statement context structure, as there is
no guarantee that the query is executed later (e.g. in case of an abandoned stored
query).
• If the query is executed, Open() is called a second time with identical input pa-
rameters as the first time to create a new instance of the statement context. The
returned connection context should be identical to the one returned in first call.
This resembles connection pooling and guarantees transaction isolation. In partic-
ular, the table function should always reuse connections were possible, i.e. when
input parameters (including taid and cons) permit that.
5.3. PATTERN FOR GENERIC TABLE FUNCTIONS 45
• Then the iterator function Next() is called once for every returned tuple. It’s
purpose is to fill it’s OUT parameter result with the next output tuple. This should
then point to an array of GetColumnCount() pointers to Transbase data types as
defined in tbx.h. An SQL NULL is represented by setting this pointer to NULL.
If one of the columns returns Blob data, then the corresponding pointer points to
a Blob structure (as defined in tbx.h). Make sure that the size component is
set correctly and set the btype (blob type) component to a unique non-zero value
for this blob type. Do not overwrite the connid and btype components. The
remainder of the structure may be used freely to identify this particular Blob. It is
encouraged to store a pointer to whatever structure is required to identify a Blob
at Blob->blobadr.
Next() sets the output parameter eod (end-of-data) to false if the OUT parame-
ters hold valid results or true if no more rows are delivered. It has be guaranteed
that the method returns false after a finite number of evaluations.
• If one of the columns returned Blob data, any number of GetLobPart() calls might
follow to retrieve the contents of the Blobs identified via the input parameter b of
type Blob*. This call has to copy len bytes of the contents of the Blob beginning at
position offset to the provided buffer buf of len bytes. read returns the number
of bytes transferred.
• The routines Open(), Next() , and GetLobPart() return error codes. All other
functions return results. A return code different from zero means an error occurred
during the last call. Then the DBMS used GetLastError() to retrieve a human
readable error description from connection or statement context, dependent upon
where the error occurred.
• A call to the Close() method ends the flow of control for this statement and releases
all resources associated to the statement context and the statement context itself.
Note that after this point calls to GetLobPart() must still be possible.
• As the local transaction ends a final call to Disconnect releases all remaining re-
sources, closes the connection and release the connection context itself. In particular
resources connected to Blob data are to be released at this point.
Chapter 6
Since user-defined functions are always part of a select, insert, update, or delete statement,
there is no separate call interface required for that SQL extension. Stored procedures
however represent a new class of SQL statements and extensions to the APIs become
necessary.
6.1 JDBC
JDBC provides the CallableStatement class for calling stored procedures. For database
compatibility call statements may use the JDBC escape syntax. Two different notations
are possible:
{ call procedure_name[(?, ...)] }
This statement will by passed unmodified to the database, apart from the removal of the
curly braces. If the optional parameter list is missing then ”()” will be appended.
{ ? = call procedure_name[(?, ...)] }
Since Transbase Stored Procedures never return a value, this statement will be modifies in
such way that the result parameter (ordinal number: 1) will be moved to the parameter
list as first parameter. This change will create a statement corresponding to the first
syntax while preserving the original parameter numbering.
The following example illustrated how to call a stored procedure from a JDBC client. This
procedure accepts three parameters in parameter modes IN, INOUT, OUT. The parameter
types are specified by literals. Note that the value of the third (OUT) parameter has no
influence on the result, only the type specification will be used for name resolution.
Example:
Class.forName("transbase.jdbc.Driver");
String dburl = "jdbc:transbase://MYHOST:4444/DB";
String uname = "user";
46
6.2. TBX 47
String pw = "passwd";
Example:
cstmt.executeQuery();
int i = stmt.getInt(1);
BigDecimal bd = stmt.getBigDecimal(2);
Note: All OUT parameters have to registered before the query is executed. Otherwise
an SQLException will be thrown.
6.2 TBX
On the TBX interface a CALL statements to stored procedures that does not use dynamic
parameters, especially no OUT or INOUT parameters, is executed by a RUN statement.
The following to examples show a query executions where all parameters are in IN mode,
i.e. no result is returned, and a query where OUT values are returned as a result.
Example:
Result result;
char *statement = "call proc(1,2,3)"; /* all modes are IN */
TbxRun (dbid, taid, statement, & qd, NULL);
Otherwise, if parameters are required, stored procedures behave very much like stored
queries, where parameter type and value have to be specified for all input parameters,
namely IN and INOUT parameters, whereas only type information is required for mere
OUT parameters. The following example illustrates this behavior.
Example:
Error e;
Integer in[2];
Integer out[2];
Id stmtid, dbid,taid;
Parameters par;
Param param[3];
Query\_descr qd;
Result result;
if(e=TbxStore(dbid,statement,&stmtid,&qd))
goto err0;
par.param\_no = 3;
param[0].type=TB\_\_INTEGER; /* now supply type information */
param[1].type=TB\_\_INTEGER; /* for all parameters */
param[2].type=TB\_\_INTEGER;
in[0]=1;
in[1]=2;
param[0].value=&in[0];
param[1].value=NULL; /* this is an out parameter,
so no input value has to be supplied */
param[2].value=&in[1];
par.param=¶m;
if(e=TbxRunStored(dbid,taid,stmtid,&par,&qd,&result))
goto err0;
out[0]=*(Integer*) ptoattornull(result.\_var.tuple,0);
out[1]=*(Integer*) ptoattornull(result.\_var.tuple,1);
Note that IN parameters are not included in the result, thus if a procedure call has
parameters in IN and OUT, one has to be aware of the fact that the index of a parameter
in the result set may differ from its index as a parameter, e.g. the OUT parameter in the
upper example has parameter index 1 but result tuple index 0.
Chapter 7
Troubleshooting
49
50 CHAPTER 7. TROUBLESHOOTING
Error 16720: Cannot create Java VM because LD LIBRARY PATH does not comprise
’path-to-library’ or is not set at all. If you are running Transbase on any other platform
than Windows, it is utmost important that LD LIBRARY PATH points to the directories
where the libraries required to start the JVM are located. By name these are the files
libjvm.so and libjava.so and typically they are typically contained in $JDK/jre/lib/i386
and $JDK/jre/lib/i386/server for Linux.
This error occurs if LD LIBRARY PATH is not set at all or if it does not contain the paths
to the libraries libjvm.so and libjava.so in the JDK you chose by setting the EXTERNAL
OPTION JDK.
to start the JVM without any options and check if LD LIBRARY PATH (for non-Windows
platforms) is set correctly (for more details on LD LIBRARY PATH settings, see previous
section on Error 16720).
51
52 CHAPTER 8. TRANSBASE DATA DICTIONARY EXTENSIONS
rkey of sysexternalmethod: Identifies the external resource to which the entry be-
longs. The name of the resource can be retrieved via a join between sysexternal
and sysexternalmethod on the fields rkey.
mkey of sysexternalmethod: Unique numeric key that identifies a method
enabled of sysexternalmethod: Boolean flag, true if this method is enabled for exe-
cution
callonnull of sysexternalmethod: Boolean flag, true if this method is to be called if
any of the in parameters is NULL.
determ of sysexternalmethod: Boolean flag, true if this method is deterministic, i.e.
for a given set of argument values, the procedure or function returns the same values
for out and inout parameters and function result.
8.3. THE SYSEXTERNALPRIV TABLE 53
Grantor and grantee refer to field userid of table sysuser. rkey refers to field rkey of table
sysexternal and mkey refers to mkey of sysexternalmethod.