Published on

  • Be the first to comment

  • Be the first to like this

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide


  1. 1. RBDe/EGL and DB2 Providing Schema at Runtime for Unqualified tablenames Author: Mark Evans. Rational – EGL Development IBM Software Group 1
  2. 2. Providing a Schema name for Unqualified Table Names in Records Many companies change the qualifier for DB2 table names as the application is moved through various stages of development. To avoid having to change the source code of applications as the code is moved through these stages, the developer would like to use “unqualified” table names and provide schema/qualifier at runtime. There are many ways to do this depending on the target database and the target deployment system. This paper assumes you are using DB2 on z/OS and are deploying the EGL application as a Java application under WAS (and therefore using JDBC). One way to set the schema is to use the currentSchema property on the datasource definition for the database connection. This requires DB2 on z/OS V8 or later. Another way to set the schema is to use the currentSQLID property on the datasource definition for the database connection. This should be used with DB2 on z/OS V7. However, the currentSQLID property most likely requires a valid secondary authentication id and/or aliases/synonyms that will associate the currentSQLID to the correct tables. However, there are times that neither of the above approaches will work and therefore it is up to the programmer to programmatically provide the schema at runtime. Fortunately, EGL provides a way to specify a variable to hold the value of the table name in the SQL statement. Therefore, we will use this capability (called the tableNamesVariable property) to supply the schema name as well as the table name. This paper will show the steps to use this property. NOTE 1: This technique requires a fix to EGL to allow the “Table Labels” to be greater than 4 characters. This will be generally available in a future interim fix for RBDe V7.0 or as a fixtest to RBDe V7.0.0.5. NOTE 2: This technique would also apply to other DB2 databases where the library name (system I) or schema name (distributed environments) might need a schema name at runtime. 2
  3. 3. This paper assumes the user has already created a record definition using either the EGL Data Access Application Wizard or the SQL Retrieve function to create the record. For this example, I am using: Tablename: DEPT Qualifier: WSED01 EGL Library: DEPTLIB After running the EGL Data Access Application I have the following record definition: record Dept type sqlRecord { tablenames=[["DEPT"]], keyItems=[Deptno] } Deptno Deptno {column="DEPT.DEPTNO", maxLen=3}; Deptname1 Deptname1 {column="DEPT.DEPTNAME1", maxLen=30, isSqlNullable=yes}; Deptmgr Deptmgr {column="DEPT.DEPTMGR", maxLen=6, isSqlNullable=yes}; end Note that the tablenames property is set to “DEPT”, which is name of the table. With this record definition, EGL will always use DEPT in the FROM clause of a SQL Statement without a schema name. (see below) select DEPT.DEPTNO, DEPT.DEPTNAME1, DEPT.DEPTMGR from DEPT where DEPT.DEPTNO = :searchRecord.Deptno In order to allow the table name and schema to be set at runtime, we need to change the record definition such that it specifies a variable name for the table name vs a hard coded tablename. Then we will need to supply the values through the application before the SQL statements are executed. Follow these steps: 3
  4. 4. 1. Change the EGL record name to use the tableNamesVariable property a. Change the tablenames property to the “tableNamesVariable” property b. Add a variable name in the property settings (insert before current table name). The variable name can be of your choosing, but you the variable must be in the namespace (accessible) from the code that contains the SQL statement. In my example, I am calling it “myTable”. “DEPT” becomes the “label” or correlation ID for the SQL statement. Example record definition after change: record Dept type sqlRecord { tableNameVariables = [["myTable", "DEPT"]], keyItems=[Deptno] } Deptno Deptno {column="DEPT.DEPTNO", maxLen=3}; Deptname1 Deptname1 {column="DEPT.DEPTNAME1", maxLen=30, isSqlNullable=yes}; Deptmgr Deptmgr {column="DEPT.DEPTMGR", maxLen=6, isSqlNullable=yes}; Example SQL Statement after this change (note the variable myTable and the addition of a new Label/correlation ID, DEPT, in the FROM clause) select DEPT.DEPTNO, DEPT.DEPTNAME1, DEPT.DEPTMGR from myTable DEPT where DEPT.DEPTNO = :searchRecord.Deptno } ; The label/correlation ID will be used to “qualify” the column names in the SELECT list and to make sure the column names match the “column=” property in the field definitions. 2. Update the Library (or other logic) to set the value of “myTable” to the real tablename. There are many ways to do this, but one suggestion is to declare and set the value of “myTable” in the global section of the library. So add the statement like the following which declares the variable myTable and sets it to the tablename of “DEPT”. myTable string = "DEPT"; The resulting code in the library would look like the following LIBRARY DeptLib // Global variables for all functions myTable string = "DEPT"; // Declare and set value to the table name use ConditionHandlingLib; 4
  5. 5. //BEGIN AddDept Function AddDept(newRecord Dept, status StatusRec) 5
  6. 6. 3. You must then set the schema name in each function prior to running the EGL I/O statement. It is assumed that the schema will be a programmatically determined value and would be stored in session. Therefore, this example assumes the schema has been set in a jsfHandler by reading the data out of the session and passing it through the record StatusRecord (or status as generated by the data Access Application Wizard). The reason this record is used is that all functions created using the wizard include the status record in the pass parameters. a. Update the StatusRec record definition in the ConditionHandlingLib.egl file. Include a “schema” field. See the record layout below and the schema field at the bottom. Record StatusRec // A value of true indicates an SQLCode of 0 succeeded boolean; // The statusCode returned to the calling routine statusCode int?; // A custom success/failure message, for the calling routine message string?; // schema name schema string; end b. Change each function to use this schema and the pre-defined table name into the variable specifed as the tableNamesVariable (myTable in this example). Below is the example from the getDeptListAll function Function GetDeptListAll(deptArray Dept[] out, status StatusRec) mytable = status.schema + "." + mytable; // build the schema.tablename SysLib.writeStdout("mytable value: " + mytable); try get deptArray; … 4. To invoke the library, below is example code that could be put in the jsfHandler that is used to invoke the library. The onConstruction function is setting a session attribute for the schema name (“WSED01”) and then when the getdeptsFunc is run (on a button click), the session attribute is retrieved and put in the status record to be passed to the library. function onConstruction() J2EELib.setSessionAttr("schema", "WSED01"); end function getdeptsFunc() J2EELib.getSessionAttr("schema", status.schema); DeptLib.GetDeptListAll(depts, status); end 6
  7. 7. 5. The end result is the myTable variable will contain the value of “WSED01.DEPT”, which is the schema.tablename on the database. 7