Release 10.1A: OpenEdge Data Management:
SQL Development

> ## Using the OpenEdge SQL Java classes

> This section describes how you use the OpenEdge SQL Java classes to issue and process SQL statements in Java stored procedures.

> To process SQL statements in a stored procedure, you must know whether the SQL statement generates output (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 determines which OpenEdge SQL Java classes you should use to issue it:

> - To issue SQL statements that do not generate results (such as `INSERT`, `GRANT`, or `CREATE`), use the `SQLIStatement` class for one-time execution, or the `SQLPStatement` class for repeated execution.

> - To issue 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, OpenEdge SQL provides the `DhSQLException` class so procedures can process and generate Java exceptions through the try, catch, and throw constructs.

> ##### Passing values to SQL statements

> Stored procedures must be able to pass and receive values from SQL statements they execute. They do this through the `setParam` and `getValue` methods.

> ##### setParam method: pass input values to SQL statements

> The `setParam` method sets the value of an SQL statement’s parameter marker to the specified value (a literal value, a procedure variable, or a procedure input parameter).

> The `setParam` method takes two arguments. This is the syntax for `setParam`:

> Syntax
>     setParam ( marker_num , value ) ;

> ``marker_num``

> Specifies the ordinal number of the parameter marker in the SQL statement that is to receive the value as an integer. `1` denotes the first parameter marker, `2` denotes the second, n denotes the nth.

> `value`

> Specifies a literal, variable name, or input parameter that contains the value to be assigned to the parameter marker.

> Example 9–9 shows a segment of 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 the first parameter marker and the value of the `cust_name` variable for the second parameter marker.

> Example 9–9: Stored procedure using setParam
>     SQLIStatement insert_cust = new SQLIStatement (
>          "INSERT INTO customer VALUES (?,?) ");
>          insert_cust.setParam (1, cust_number);
>          insert_cust.setParam (2, cust_name);

> ##### 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 using the following syntax:

> Syntax
>     getValue ( col_num , sql_data_type ) ;

> ``col_num``

> Specifies the desired column of the result set as integer. `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, n denotes the nth.

> ``sql_data_type``

> Specifies the corresponding SQL data type.

> This example shows how the `getValue()` method works. This method returns a Java object that must be cast to the corresponding SQL data type:

>     cnum = (Integer) NEWROW.getValue(1, INTEGER);
>     cnname = (String) NEWROW.getValue(1, CHARACTER);

> ##### 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. When applications process the `CREATE PROCEDURE` statement, the SQL engine declares Java variables of the same name. Therefore, the stored procedure can refer to input and output parameters as if they were Java variables declared in the body of the stored procedure.

> 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.

> Parameter declarations include the parameter type (`IN`, `OUT`, or `INOUT`), the parameter name, and SQL data type.

> Declare input and output parameters in the specification section of a stored procedure, as shown in Example 9–10.

> Example 9–10: Stored procedures input and 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
>     )

> When the `order_entry` stored procedures 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.

> ##### Implicit data type conversion between SQL and Java types

> When the OpenEdge SQL Engine creates a stored procedure, it converts the type of any input and output parameters.

> The java.lang package, part of the Java core classes, defines classes for all the primitive Java types that “wrap” values of the corresponding primitive type in an object. The OpenEdge SQL Engine converts the SQL data types declared for input and output parameters to one of these wrapper types, as shown in Table 9–2.

> 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 illustrates the use of the Java wrapper type Long for a SQL type `INTEGER`:

>     CREATE PROCEDURE proc1(INOUT f1 char(50), INOUT f2 integer)
>     BEGIN
>     f1 = new String("new rising sun");
>     f2 = new Integer("999");
>     END
>     CREATE PROCEDURE proc2()
>     BEGIN
>     String in1 = new String("String type");
>     String out1 = new String();
>     Long out2 = new Long("0");
>     SQLCursor call_proc = new SQLCursor("call proc1(?, ?)");
>     call_proc.setParam(1,in1);
>     // In setParam you can use either String or String type
>     // for SQL types CHAR, and VARCHAR
>     call_proc.setParam(2,new Long("111"));
>     call_proc.open();
>     out1 = (String)call_proc.getParam(1,CHAR);
>     // getParam requires String type for CHAR
>     out2 = (Long)call_proc.getParam(2,INTEGER);
>     call_proc.close();
>     END

> When the OpenEdge 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.

> To avoid type mismatch errors, use the data-type mappings shown in Table 9–2 for declaring parameters and result-set fields in the procedure specification and the Java variables in the procedure body.

> Table 9–2: Mapping between SQL and Java data types
> SQL type | Java methods | Java wrapper type
> --- | --- | ---
> `CHAR`, `VARCHAR` | All | String
> `CHAR`, `VARCHAR` | `set`, `setParam` | String
> `NUMERIC` | All | `java.math.BigDecimal`
> `DECIMAL` | All | `java.math.BigDecimal`
> `BIT` | All | Boolean
> `TINYINT` | All | Byte[1]
> `SMALLINT` | All | Integer
> `INTEGER` | All | Integer
> `REAL` | All | Float
> `FLOAT` | All | Double
> `DOUBLE PRECISION` | All | Double
> `BINARY` | All | Byte[ ]
> `VARBINARY` | All | Byte[ ]
> `DATE` | All | `java.sql.Date`
> `TIME` | All | `java.sql.Time`
> `TIMESTAMP` | All | `java.sql.Timestamp`

> ##### Executing an SQL statement

> If an SQL statement does not generate a result set, stored procedures can execute the statement in one of two ways:

> - Immediate execution. Using methods of the `SQLIStatement` class, the procedure executes a statement once.

> - Prepared execution. Using methods of the `SQLPStatement` class, the procedure prepares a statement for multiple executions in a procedure loop.

> Table 9–3 shows the SQL statements that do not generate result sets. You can execute these statements in a stored procedure using either the `SQLIStatement` or the `SQLPStatement` class.

> Table 9–3: Executable SQL statements
>     ALTER USER
>     CREATE INDEX
>     CREATE PROCEDURE
>     CREATE SYNONYM
>     CREATE TABLE
>     CREATE TRIGGER
>     CREATE USER
>     CREATE VIEW
>     DELETE
>     DROP INDEX
>     DROP PROCEDURE
>     DROP TABLE
>     DROP TRIGGER
>     DROP USER
>     DROP VIEW
>     GRANT
>     INSERT
>     REVOKE
>     UPDATE
>     UPDATE STATISTICS

> ##### Immediate execution

> Use immediate execution when a procedure must execute an SQL statement only once.

> This stored procedure in this sample script inserts a row in a table. The constructor for `SQLIStatement` takes the SQL `INSERT` statement as its only argument. In Example 9–11, the statement includes five parameter markers.

> Example 9–11: Stored procedure using INSERT statement
>     CREATE PROCEDURE insert_team(
>          IN  empnum      INTEGER not null,
>          IN  FirstName   VARCHAR(30) not null,
>          IN  LastName    VARCHAR(50) not null,
>          IN  State       VARCHAR(50) not null,
>          IN  Sport       CHAR(20)
>     )

>     BEGIN
>          SQLIStatement insert_team = new SQLIStatement (
>             "INSERT INTO team (empnum, FirstName, LastName, State, Sport)
>               VALUES ( ?,?,?,?,? ) ");
>          insert_team.setParam (1, empnum);
>          insert_team.setParam (2, FirstName);
>          insert_team.setParam (3, LastName);
>          insert_team.setParam (4, State);
>          insert_team.setParam (5, Sport) ;
>          insert_team.execute ();
>     END

>     COMMIT WORK ;

> ##### Prepared execution

> Use prepared execution when you must execute the same SQL statement repeatedly. Prepared execution avoids the overhead of creating multiple `SQLIStatement` objects for a single statement.

> There is an advantage to prepared execution when you execute the same SQL statement from within a loop. Instead of creating an object with each iteration of the loop, prepared execution creates an object once and supplies input parameters for each execution of the statement.

> Once a stored procedure creates an `SQLPStatement` object, you can execute the object multiple times, supplying different values for each execution.

> Example 9–12 extends the previous example to use prepared execution.

> Example 9–12: Stored procedure with prepared execution
>     CREATE PROCEDURE prepared_insert_customer (
>        IN  cust_number INTEGER,
>        IN  cust_name   CHAR(20)
>     )

>     BEGIN
>        SQLPStatement p_insert_cust = new SQLPStatement (
>        "INSERT INTO customer VALUES (?,?) ");
>        .
>        .
>        .
>     int i;
>     for (i = 0; i < new_custs.length; i++)
>     {
>        p_insert_cust.setParam (1, new_custs[i].cust_number);
>        p_insert_cust.setParam (2, new_custs[i].cust_name);
>        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 an SQL statement that generates a result set. The SQL statement is either a `SELECT` or a `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 result sets follows the same steps.

> | To process result sets:

> 1. Open the cursor by using the `SQLCursor.open` method.

> 2. Check whether there are any records in the result set by using the `SQLCursor.found` method.

> 3. If there are records in the result set, loop through the result set:

> - Try to fetch a record by using 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 by using the `SQLCursor.getValue` method.
> - Process the data.
> - If the fetch operation did not return a record, exit the loop.
> 4. Close the cursor by using the `SQLCursor.close` method.

> Example 9–13 uses `SQLCursor` to process the result set returned by an `SQL SELECT` statement.

> Example 9–13: Stored procedure using SQLCursor
>     CREATE PROCEDURE get_sal ()
>     IMPORT
>     import java.math.*;
>     BEGIN
>     StringBuffer ename = new StringBuffer (20) ;
>     BigDecimal esal = new BigDecimal (2) ;
>     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, NUMERIC);
>     // do something with the values here
>     }
>     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.

> Example 9–14 shows an excerpt from a stored procedure that processes the result set returned by another procedure, `get_customers`.

> Example 9–14: Stored procedure processing results of another procedure
>     SQLCursor cust_cursor = new SQLCursor (
>        "CALL get_customers (?) ") ;
>         cust_cursor.setParam (1, "NE");
>         cust_cursor.open () ;
>         for (;;)
>         {
>             cust_cursor.fetch ();
>             if (cust_cursor.found ())
>             {
>                 cust_number = (Integer) cust_cursor.getValue (1, INTEGER);
>                 cust_name = (String) cust_cursor.getValue (2, CHAR) ;
>             }
>             else
>                     break;
>         }
>         cust_cursor.close () ;

> ##### Returning a procedure result set to applications: the RESULT clause and DhSQLResultSet

> The `get_sal` procedure in the previous example with a `CREATE PROCEDURE` uses the `SQLCursor.getValue` method to store the values of a database record in individual variables. The procedure did not, however, do anything with those values and they will 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 that the rows can be returned to the calling application. 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 the SQL engine 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.

> The next example extends the `get_sal` procedure to return a procedure result set:

>     CREATE PROCEDURE get_sal2 ()
>     RESULT (
>     empname CHAR(20),
>     empsal NUMERIC
>     )
>     IMPORT
>     import java.math.*;
>     BEGIN
>     StringBuffer ename = new StringBuffer (20) ;
>     BigDecimal esal = new BigDecimal (2) ;
>     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, NUMERIC);
>     // NUMERIC and DECIMAL are synonyms
>     SQLResultSet.set (1, ename);
>     SQLResultSet.set (2, esal);
>     SQLResultSet.insert ();
>     }
>     } while (empcursor.found ()) ;
>     empcursor.close () ;
>     END

> For each row of the 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 `DhSQLResultSet.Set` method.

> - Inserts a row into the procedure result set with the`DhSQLResultSet.Insert` method.

> ##### Handling null values

> Stored procedures routinely must set and detect null values:

> - Stored procedures might need to set the values of SQL statement input parameters or procedure result fields to null.

> - Stored procedures must check if the value of a field in an SQL result set is null before assigning it through the `SQLCursor.getValue` method. The OpenEdge SQL Engine generates a run-time error if the result-set field specified in `getValue` is `NULL`.

> ##### Setting SQL statement input parameters and procedure result set fields to null

> Both the `setParam` method and `set` method take objects as their value arguments. You can pass a `NULL` reference directly to the method or pass a variable that has been assigned the null value.

> Example 9–15 uses both techniques to set an SQL input parameter to `NULL`.

> Example 9–15: Stored procedure setting input parameter to NULL
>     CREATE TABLE t1 (
>          c1 INTEGER,
>          c2 INTEGER,
>          c3 INTEGER);

>     CREATE PROCEDURE test_nulls( )
>     BEGIN
>          Integer pvar_int ;
>          pvar_int = null ;

>          SQLIStatement insert_t1 = new SQLIStatement
>          ( "INSERT INTO t1 (c1, c2, c3) values (?,?,?) ");

>          // Set to non-null value
>          insert_t1.setParam(1, new Integer(1));

>          // Set directly to null
>          insert_t1.setParam(2, null);

>          // Set indirectly to null
>          insert_t1.setParam(3, pvar_int);

>          insert_t1.execute();
>     END

> ##### Assigning null values from SQL result sets: the SQLCursor.wasNULL method

> If the value of the field argument to the `SQLCursor.getValue` method is `NULL`, the SQL engine returns a run-time error.

> Example 9–16 illustrates the error returned when the argument to `SQLCursor.getValue` is `NULL`.

> Example 9–16: Stored procedure error message
>     (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.

> The `SQLCursor.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.

> Example 9–17 illustrates using the `wasNULL` method.

> Example 9–17: Stored procedure using wasNULL method
>     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_t1.getValue(2, INTEGER);
>     if ((select_t1.wasNULL(3)) == true)
>     pvar_int3 = null;
>     else
>     pvar_int3 = (Integer) select_t1.getValue(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();
>     select_t1.fetch();
>     }
>     // Close the SQL result set.
>     select_t1.close();
>     END

> ##### Handling errors

> OpenEdge SQL stored procedures use standard Java try/catch constructs to process exceptions.

> Any errors in SQL statement execution result in the creation of a `DhSQLException` class object. When OpenEdge 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. See Table 9–4 for explanations of the `getDiagnostics` error-handling options.

> Table 9–4: getDiagnostics error-handling options
> 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 returned null.
>     SUBCLASS_ORIGIN
> | Not currently used. Always returned null.

> Example 9–18 shows an excerpt from a stored procedure that uses `DhSQLException.getDiagnostics`.

> Example 9–18: Stored procedure using DhSQLException.getDiagnostics
>     try
>     {
>          SQLIStatement insert_cust = new SQLIStatement (
>          "INSERT INTO customer VALUES (1,2) ");
>     }
>     catch (DhSQLException e)
>     {
>          errstate = e.getDiagnostics (DhSQLException.RETURNED_SQLSTATE) ;
>          errmesg  = e.getDiagnostics (DhSQLException.MESSAGE_TEXT) ;
>               .
>               .
>               .
>     }

> 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.

> Example 9–19 illustrates using the `DhSQLException` constructor to create an exception object called `excep`. It then throws the `excep` object under all conditions.

> Example 9–19: Stored procedure using DhSQLException constructor
>     CREATE PROCEDURE sp1_02()
>     BEGIN
>     // raising exception
>          DhSQLException excep =
>             new DhSQLException(777,new String("Entered the tst02 procedure"));
>          if (true)
>          throw excep;
>     END

> ##### Calling stored procedures from other 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 for assembling 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.

> ##### Stored procedure parameter requirements and usage

> When one stored procedure is calling another stored procedure, the following requirements must be met for using the three parameter types in order to properly allocate the SQLDA structure to the correct size:

> - An `IN` parameter calls only the `SetParam` function.

> - An `OUT` parameter calls only the `RegisterOutParam` function.

> - An `INOUT` parameter calls both the `SetParam` and `RegisterOutParam` functions in any order.

> ##### INOUT and OUT parameters when one Java stored procedure calls another

> If an `OUT` or `INOUT` parameter is of data type `CHARACTER`, then `getParam()` returns a Java String Object. You must declare a procedure variable of type String, and explicitly cast the value returned by `getParam` to type String. Before calling `getParam()` you must call the `SQLCursor.wasNULL` method to test whether the returned value is null. If `getParam()` is called for a null value, it raises a `DhSQLException`.

> The `getParam()` method returns the value of an `INOUT` or `OUT` parameter identified by the number you specify in the `fieldIndex` parameter. `getParam()` returns the value as an object of the data type you specify in the `fieldType` parameter. Since `getParam()` returns the result as an instance of class `Object`, you must explicitly cast your `inout_var` variable to the correct data type.

> These are the general steps to follow when calling one Java stored procedure from another:

> 1. Register `OUT` parameters in the calling stored procedure.

> 2. Declare Java variables in the snippet of the calling procedure.

> 3. Invoke the other stored procedure.

> Example 9–20 illustrates the steps required for calling one Java stored procedure from another.

> Example 9–20: Stored procedure calling another
>     create procedure lotusp(
>     IN f1 char(50),
>     INOUT f2 char(50),
>     OUT f3 char(50)
>     )
>     RESULT(f4 char(50))
>     BEGIN
>          f2 = new String("new rising sun");
>          f3 = new String("new rising lotus");
>          SQLResultSet.set(1, new String("the fog - the snow - the ice"));
>          SQLResultSet.insert();
>     END

>     commit work;

>     create procedure proc1()
>     BEGIN
>          String inout_param = new String("sun");
>          String out_param = new String();

>          SQLCursor call_proc = new SQLCursor("call lotusp(?,?,?)");
>          call_proc.setParam(1, new String("moon"));
>          call_proc.setParam(2, inout_param);
>          call_proc.registerOutParam(3, CHAR);
>          //  OR you can specify the optional scale parameter
>          //  call_proc.registerOutParam(3, CHAR, 15);
>          call_proc.open();
>          inout_param = (String)call_proc.getParam(2, CHAR);
>          out_param = (String)call_proc.getParam(3, CHAR);
>          call_proc.close();
>     END

Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095