Examples for the SQLJ feature of ASE 12.5


Contents

Top


Technical contacts

Yiwen Huang huangy@sybase.com (510) 922-5344
Phil Shaw pshaw@sybase.com (510) 922-5174
Top


Introduction

The Java features of ASE 12.5 extend the Java capabilities introduced in ASE 12.0.

With the ASE 12.0 Java feature you can:

With the ASE 12.5 SQLJ feature you can:

SQL result sets and output parameter values are common techniques with SQL stored procedures. These capabilities are now fully supported with the Java feature.

The following sections show the example code from the user documentation of the ASE12.5 SQLJ feature.

For guidelines on setting up the Java facilities of Adaptive Server, see the Setup section of $SYBASE/ASE-12_5/XML-examples/index.htm.

Top


Contents of the directory

The files in this directory are as follows:

Top


A simple create function example

Here's a simple select that references a built-in Java method. This select references the Java method using its Java name, as with ASE 12.0:

select java.lang.Math.sqrt(16)

With the SQLJ feature of ASE 12.5, we can define an SQL name for any Java method that we want to call in SQL:

create function squareroot
        (inputnumber double precision) returns double precision
language java parameter style java
external name 'java.lang.Math.sqrt'

Given such an SQLJ create, we can reference the Java method with its SQL name:

1> select squareroot(16)
                      
 -------------------- 
             4.000000 

(1 row affected)
Top


Sample table for the SQLJ examples

The SQLJ examples below reference the following SQL table:


create table salesemps
	(name varchar(50), id char(5),
	state char(20), sales decimal (6,2),
	jobcode integer null)


insert into salesemps values("Adams", "00001", "MN", 123.01, 1)
insert into salesemps values("Baker", "00003", "VT", 323.01, 2)
insert into salesemps values("Carter", "00005", "NH", 523.01, 3)
insert into salesemps values("Davis", "00007", "FL", 723.01, 2)
insert into salesemps values("Earl", "00009", "GA", 923.01, 1)
insert into salesemps values("Foster", "00011", "Cal", 1123.01, 2)
insert into salesemps values("George", "00013", "AZ", 3123.01, 3)
insert into salesemps values("Harris", "00015", "NV", 5123.01, 2)
insert into salesemps values("Jackson", "00017", "MN", 7123.01, 1)
insert into salesemps values("Kramer", "00019", "VT", 9123.01, 2)
	
	

Top


Installing the example Java classes

The Java classes used in the following examples are in the jar file "sqlj-examples.jar".

You can install that jar file with a client command such as the following:

	installjava -fsqlj-examples.jar -update -j"sqlj_examples_jar" -S "server_name" -Usa -P""  

The "server_name" is the name that you specify for ISQL.

This directory also contains a "makefile" with commands to compile the Java classes for the SQLJ examples, make a jar file ("sqlj-examples.jar") with them, and install the jar file.

make compile
make jar
make install
make javadoc

Before you execute those "make" commands, you will need to set environment variables as follows:

Top


The SQLJExamples class

The example methods for SQLJ are contained in the class SQLJExamples.java. That class contains the following methods (described below).

Top


Basic SQLJ functions and procedures

The following examples use two Java methods:

Top

The region and correctStates methods



	public static int region(String s) 
			throws SQLException {
		s = s.trim();
		if (s.equals("MN") || s.equals("VT") ||
			s.equals("NH") ) return 1;
		if (s.equals("FL") || s.equals("GA") ||
			s.equals("AL") ) return 2;
		if (s.equals("CA") || s.equals("AZ") ||
			s.equals("NV") ) return 3;
		else throw new SQLException
			("Invalid state code", "X2001");

	}

	public static void correctStates
		(String oldSpelling, String newSpelling)
		throws SQLException {

		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			Class.forName
				("sybase.asejdbc.ASEDriver");
			conn = DriverManager.getConnection("jdbc:default:connection");
		} 
		catch (Exception e) {
			System.err.println(e.getMessage() 
				+ ":error in connection");
		}
		try {
			pstmt = conn.prepareStatement
				("UPDATE salesemps SET state = ? "
				 + " WHERE state = ?");
			pstmt.setString(1, newSpelling);
			pstmt.setString(2, oldSpelling);
			pstmt.executeUpdate();
		}
		catch (SQLException e) {
			System.err.println("SQLException: " + e.getErrorCode() + e.getMessage());
		}
	return;
	}
}

Top

Calling "SQLJExamples.region" and "SQLJExamples.correctStates" with Java names

With ASE 12.0 facilities, you can call "SQLJExamples.region" and "SQLJExamples.correctStates" in SQL by referencing the Java names:

1> select state, SQLJExamples.region(state) as region 
2> from salesemps
3> where SQLJExamples.region(state)=3
4> go
 state                region      
 -------------------- ----------- 
 CA                             3 
 AZ                             3 
 NV                             3 

(3 rows affected)
1> -- Introduce a mis-spelling:
2> update salesemps set state="Cal" where state="CA"

(1 row affected)
1> -- The following now raises an exception due to the mis-spelling:
2> select name, state, SQLJExamples.region(state) as region 
3> from salesemps
4> where SQLJExamples.region(state)=3
5> go
Msg 10707, Level 16, State 1:
Line 4:
Unhandled Java Exception: 
java.sql.SQLException: Invalid state code
 at
java.lang.Throwable.fillInStackTrace(Throwable.java)
 at
java.lang.Throwable.(Throwable.java:94)
 at
java.lang.Exception.(Exception.java:42)
 at
java.sql.SQLException.(SQLException.java:64)
 at
SQLJExamples.region(SQLJExamples.java:42)
 at SQLJExamples.region(SQLJExamples.java:35)
1> -- The following call corrects the spelling "Cal" to "CA"
2> select SQLJExamples.correctStates("Cal", "CA")
3> go             
 ----------- 
        NULL 

(1 row affected)

Top

Defining an SQLJ function for "SQLJExamples.region"

The following SQLJ create function defines an SQL name for the Java method "SQLJExamples.region".

create function regionof(state char(20)) 
		returns integer
language java parameter style java
external name 'SQLJExamples.region(java.lang.String)'

The following SQL select statement calls the SQLJ function "regionof" that we created above.

1> select name, state, regionof(state) as region
2> 	from salesemps
3> where regionof(state)=3
 name                                               state               
	 region      
 -------------------------------------------------- --------------------
	 ----------- 
 Foster                                             CA                  
	           3 
 George                                             AZ                  
	           3 
 Harris                                             NV                  
	           3 

(3 rows affected)
Top

Defining an SQLJ procedure for "SQLJExamples.correctStates"

The above example showed an SQLJ function, "regionof" defined on a Java method "SQLJExamples.region". The example below shows an SQLJ procedure, "correctstates", defined on the Java method "SQLJExamples.correctStates".

create procedure correctstates(old char(20), 
		notold char(20))
	modifies sql data
	language java parameter style java
	external name
          'SQLJExamples.correctStates(java.lang.String, java.lang.String)'

Given this SQLJ definition of the "correctstates" procedure, we can call "correctstates" as we would a normal SQL stored procedure.

1> --  Introduce a mis-spelling
2> update salesemps set state="Geo" where state="GA"
3> 
4> -- Correct the mis-spelling
5> execute correctstates 'Geo', 'GA'
6> go
(1 row affected)
(return status = 0)
Top


Handling null parameter values

Top

Example Java method "SQLJExamples.job"

The following Java method, "SQLJExamples.job" maps an integer job code to a character string.


	public static String job(int jc)
			throws SQLException {
	if (jc==1) return ("Admin");

 	else if (jc==2) return ("Sales");
	else if (jc==3) return ("Clerk");
	else return ("unknown jobcode");
	}
}


Top

Calling the SQLJExamples.job method directly

You can call the "SQLJExamples.job" method directly, using its Java name as with ASE 12.0:

1> select name,  SQLJExamples.job(jobcode)
2> from salesemps
3> where SQLJExamples.job(jobcode) <> "Admin"
4> go
 name                                              
	                                                    
 --------------------------------------------------
	 -------------------------------------------------- 
 Baker                                             
	 Sales                                              
 Carter                                            
	 Clerk                                              
 Davis                                             
	 Sales                                              
 Foster                                            
	 Sales                                              
 George                                            
	 Clerk                                              
 Harris                                            
	 Sales                                              
 Kramer                                            
	 Sales                                              

(7 rows affected)

However, note that the parameter of "SQLJExamples.job" is a Java int, which cannot accept SQL nulls as argument value. For example, suppose that some "jobcode" value is null:

1> --  Change a 'jobcode' value to null:
2> update salesemps set jobcode=null where name = "Baker"
(1 row affected)
1> -- The following will now raise an exception when the null value
2> -- is passed as a parameter to "SQLJExamples.job".
3> select name,  SQLJExamples.job(jobcode)
4> from salesemps
5> where SQLJExamples.job(jobcode) <> "Admin"
Msg 10794, Level 16, State 1:
Line 6:
Cannot pass NULL as the value for parameter number 1 to the method 'job' in
class 'SQLJExamples'. The parameter is of a Java primitive datatype, and is
non-nullable.

Thus, when you call "SQLJExamples.job" directly from SQL, you have to guard against passing an SQL null value to it, with code such as the following:


select name, case when jobcode is not null 
		then SQLJExamples.job(jobcode) else null end
from salesemps 
where case when jobcode is not null 
      then SQLJExamples.job(jobcode) else null end <> "Admin"

Top

Defining an SQLJ function "jobof" for SQLJExamples.job

We can simplify the treatment of null parameter values by defining an SQLJ function for "SQLJExamples.job", specifying the null on null input clause:

create function jobof(jc integer) returns varchar(20)
returns null on null input
language java parameter style java
external name 'SQLJExamples.job(int)'

The null on null input clause makes the guard code to check for nulls implicit. When we call the SQLJ "jobof" function, Any call of "jobof" whose parameter value is null will be treated as null without ever calling the underlying Java method "SQLJExamples.job".

1> select name, jobof(jobcode)
2> 	from salesemps
3> where jobof(jobcode) <> "Admin"
4> 
 name                                                                    
 -------------------------------------------------- -------------------- 
 Carter                                             Clerk                
 Davis                                              Sales                
 Foster                                             Sales                
 George                                             Clerk                
 Harris                                             Sales                
 Kramer                                             Sales                

(6 rows affected)
Top


Output parameters with SQLJ procedures

Top

Example Java method "SQLJExamples.bestTwoEmps"

The class "SQLJExamples" contains a method "bestTwoEmps" that is designed to be called as an SQLJ procedure with output parameters. The "bestTwoEmps" method has one input parameter, "regionParm". The other parameters are output parameters in which the method returns the column values of the two employees in "salesemps" with the highest sales.

The SQLJ convention for Java methods that are called as SQLJ procedures with output parameters is to represent output parameters as single-element arrays that act as "holders" for the output values.


	public static void bestTwoEmps
		(String[] n1, String[] id1,  BigDecimal[] s1, int[] r1,
		 String[] n2, String[] id2,  BigDecimal[] s2, int[] r2,
		int regionParm) throws SQLException {

	n1[0] = "****"; n2[0] = "****";
	id1[0] = ""; id2[0] = "";
	r1[0] = 0; r2[0] = 0;
	s1[0] = new BigDecimal(0); 
	s1[0] = new BigDecimal(0);

	try {
                Class.forName("sybase.asejdbc.ASEDriver"); 
		Connection conn = DriverManager.getConnection("jdbc:default:connection"); 
		java.sql.PreparedStatement stmt =
			conn.prepareStatement("SELECT name, id, "
			     + "regionof(state) as region, sales "
			     + " FROM salesemps WHERE regionof(state)>? "
                             + " AND sales IS NOT NULL ORDER BY sales DESC");
		stmt.setInt(1, regionParm);
		ResultSet r = stmt.executeQuery();

		if(r.next()) {
			n1[0] = r.getString("name");
			id1[0] = r.getString("id");
			r1[0] = r.getInt("region");

			s1[0] = r.getBigDecimal("sales", 2);
		}
		else return;

		if(r.next()) {
			n2[0] = r.getString("name");
			id2[0] = r.getString("id");
			r2[0] = r.getInt("region");
			s2[0] = r.getBigDecimal("sales", 2);
		}
		else return;
	} catch (SQLException e) {
		System.err.println(" SQLException:"  
			+ e.getErrorCode() + e.getMessage());
	}catch (Exception e)  {
		System.err.println(" Exception:"  
			+ e.getMessage());
     
        }
    }		
}	


Top

Defining an SQLJ procedure "best2" for "SQLJExamples.bestTwoEmps"

The following SQLJ create procedure creates an SQL stored procedure named "best2" for the Java method "SQLJExamples.bestTwoEmps".

create procedure best2
	(out n1 varchar(50), out id1 varchar(5), out s1 decimal(6,2), out r1 integer, 
	out n2 varchar(50), out id2 varchar(50), out r2 integer, out s2 decimal(6,2), 
	in region integer)
	language java parameter style java
	external name 'SQLJExamples.bestTwoEmps(java.lang.String[],
		java.lang.String[], int[],
		java.math.BigDecimal[], java.lang.String[],
		java.lang.String[], int[],
		java.math.BigDecimal[], int)'

Top

Calling the SQLJ procedure "best2"

The following shows a call of the SQLJ procedure "best2". Note that this is the same call that you would write if the "best2" procedure were a TSQL procedure.


1> declare @n1 varchar(50), @id1 varchar(5), @s1 decimal (6,2), @r1 integer, 
2>         @n2 varchar(50), @id2 varchar(50), @r2 integer, @s2 decimal(6,2),
3> 	@region integer
4> select @region = 0
5> execute best2 @n1 out, @id1 out, @s1 out, @r1 out, @n2 out, @id2 out,  @s2 out, @r2 out, @region 
6> 
(1 row affected)
(return status = 0)
Return parameters:
 -------------------------------------------------- ----- --------- -----------
	 --------------------------------------------------
	 -------------------------------------------------- ---------
	 ----------- 
 Adams 00001    123.01  1 Baker  00003  323.01 1 

(1 row affected)

You can get descriptive information about SQLJ procedures and functions in the same manner as for TSQL.

1> sphelp best2
 Name                           Owner                         
	 Type                   
 ------------------------------ ------------------------------
	 ---------------------- 
 best2                          dbo                           
	 SQLJ procedure         

(1 row affected)
 Datalocatedonsegment        Whencreated               
 ------------------------------ -------------------------- 
 not applicable                        Mar  8 2001  4:09PM 
 Parametername  Type            Length      Prec Scale Paramorder 
 --------------- --------------- ----------- ---- ----- ----------- 
 @n1             varchar                  50 NULL  NULL           1 
 @id1            varchar                   5 NULL  NULL           2 
 @s1             decimal                   4    6     2           3 
 @r1             int                       4 NULL  NULL           4 
 @n2             varchar                  50 NULL  NULL           5 
 @id2            varchar                  50 NULL  NULL           6 
 @s2             decimal                   4    6     2           7 
 @r2             int                       4 NULL  NULL           8 
 @region         int                       4 NULL  NULL           9 
(return status = 0)
Top


Result sets with SQLJ procedures

Top

Example Java method "orderedEmps"

The Java class "SQLJExamples" has a method "orderedEmps" that is intended to be called as an SQLJ procedure that returns an SQL result set.

The SQLJ convention for Java methods that are called as SQLJ procedures returning result sets is to include one or more additional parameters in the Java method for the result sets.


	public static void orderedEmps
			(int regionParm, ResultSet[] rs) throws
			SQLException {		

		Connection conn = null;
		PreparedStatement pstmt = null;

		try {
			Class.forName("sybase.asejdbc.ASEDriver");
			conn = DriverManager.getConnection("jdbc:default:connection");
		} 
		catch (Exception e) {
			System.err.println(e.getMessage() + ": error in connection" );
		}

		try {
			java.sql.PreparedStatement 
				stmt = conn.prepareStatement 
				("SELECT name, regionof(state) as region, "
				  + "sales FROM salesemps " 
  				  + "WHERE regionof(state) > ? "
				  + " AND sales IS NOT NULL ORDER BY sales DESC");
			stmt.setInt(1, regionParm);
			rs[0] = stmt.executeQuery();
			return;
		}
		catch (SQLException e) {
			System.err.println("SQLException: "
			 + e.getErrorCode() + e.getMessage());
		}
		return;
	} 
}

Top

Defining an SQLJ procedure "rankedemps" for SQLJExamples.orderedEmps

The following is an SQLJ create procedure to define an SQLJ procedure named "rankedemps" for the Java method "SQLJExamples.orderedEmps".

1> create procedure rankedemps(region integer)
2> 	dynamic result sets 1
3> 	language java parameter style java
4> 	external name 'SQLJExamples.orderedEmps(int, java.sql.ResultSet[])'
5> 
1> 
2> exec rankedemps 0
 name                                               region      sales     
 -------------------------------------------------- ----------- --------- 
 Adams                                                        1    123.01 
 Baker                                                        1    323.01 
 Carter                                                       1    523.01 
 Davis                                                        2    723.01 
 Earl                                                         2    923.01 
 Foster                                                       3   1123.01 
 George                                                       3   3123.01 
 Harris                                                       3   5123.01 
 Jackson                                                      1   7123.01 
 Kramer                                                       1   9123.01 

(10 rows affected)
(return status = 0)
Top

Calling the SQLJ procedure "rankedemps" from a Java client

The following is the Java statements you would execute in a Java client to call the SQLJ procedure "rankedemps" and retrieve the result set that it returns.

Note that this code is exactly the same as the code you would use if the "rankedemps" procedure were written in TSQL.

java.sql.CallableStatement stmt =
	conn.prepareCall({call rankedemps(?)});
stmt.setInt(1,3);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
	String name = rs.getString(1);
	int.region = rs.getInt(2);
	BigDecimal sales = rs.get.BigDecimal(3);
	System.out.print(Name =  + name);
	System.out.print(Region =  + region);
	System.out.print(Sales =  + sales);
	System.out.printIn():
}

This code is contained in the "main" method of "CallRankedEmps". That method takes two parameters:

For example:

java CallRankedEmps "yourserver:11111"   2
java CallRankedEmps "yourserver:11111?user=smith&password=xxx"  2
Top


Other SQLJ examples

When you create a SQLJ function or stored procedure, you typically specify a SQL signature and a Java method signature. For example, in the create procedure statement for the correctStates stored procedure, the SQL stored procedure signature is old char(20), notold char(20):


create procedure correctstates(old char(20), 
		notold char(20))
	modifies sql data
	language java parameter style java
	external name	
		'SQLJExamples.correctStates(java.lang.String, java.lang.String)'

You can also omit the Java method signature from the create statement and allow Adaptive Server to infer it from the routine's SQL signature according to standard JDBC datatype correspondence rules


create procedure correctstates(old char(20), 
		notold char(20))
	modifies sql data
	language java parameter style java
	external name	 'SQLJExamples.correctStates'

If you specify an explicit Java method signature, you must include the trailing result sets in the signature.


create procedure rankedemps (region integer)
			dynamic result sets 1
			language java parameter style java
			external name 'SQLJExamples.orderedEmps
				(int, java.sql.ResultSet[])'

Top


Dropping SQLJ functions and procedures

You drop an SQLJ function or procedure with a normal SQL drop command.

drop function squareroot
drop table salesemps
drop procedure correctstates
drop function regionof
drop function jobof22
drop procedure best2
drop procedure rankedemps