Net.Data lets you define and reference variables in a Net.Data macro. In addition, you can pass these variables from the macro to language environments and back. Net.Data tokens, such as variable names and quoted strings, can contain up to 64KB of data. For OS/400, the maximum size is determined by the system.
Macro variables are categorized into these types:
An identifier, which is a variable or a function call, becomes visible (that is, can be referenced) when it is declared or instantiated. The region where an identifier is visible is called its ascope. There are five types of scope:
An identifier has global scope if you can reference it anywhere within a macro file. Identifiers that have global scope are:
An identifier has this scope if its declaration appears outside of any block. A block starts with an opening "{" and ends with "%}". (Note that DEFINE blocks are excluded from this definition and should be treated as separate DEFINE statements.) An identifier with macro file scope is visible from the point it is declared to the end of the macro file.
An identifier has function block scope if its declaration or instantiation is located inside a FUNCTION block (such as an OUT variable). (This also applies to variables that are referenced within a REPORT or ROW blocks of functions, but were not explicitly defined within the macro file or implicitly defined by Net.Data).
An identifier has report block scope if it can only be referenced from within a REPORT block (for example, table column names N1, N2, ..., Nn). Only those variables that Net.Data implicitly defines as part of its table processing can have a report block scope. Any other variables that are instantiated have function block scope.
A reference to an identifier results in that identifier being replaced with the value of the identifier. If a reference to a variable has no value associated with it, or a function call does not have a return value, the reference is replaced by an empty string.
The following sections describe how to define and reference variables, and also describes different variable types and how to use them.
There are 3 ways to define variables in a Net.Data macro:
The simplest way to define a variable for use in a Net.Data macro is to use the DEFINE statement. This is syntax specific to Net.Data:
%DEFINE variable_name="variable value"
%DEFINE variable_name={ variable value on multiple
lines of text %}
The variable_name is the name you give the variable. Variable names must begin with a letter or underscore and can contain any alphanumeric characters or an underscore. All variable names are case-sensitive, except N_columnName and V_columnName, which are table variables.
To include quotes in a string, use two quotes consecutively. Two consecutive quotes alone is equal to a null string.
%DEFINE HI="say ""hello""" %DEFINE reply="hello" %DEFINE empty=""
When displayed, the variable HI reads say "hello", the variable reply reads hello, and the variable empty is null.
To define several variables with one DEFINE statement, use a DEFINE block:
%DEFINE{
variable1="value1"
variable2="value2"
variable3="value3"
variable4="value4"
%}
This example uses standard HTML form tags to define a variable:
<INPUT NAME="variable_name" TYPE=...>or
<SELECT NAME="variable_name">
The variable_name is the name you give the variable, and the value of the variable is determined from the input received in the form. See "HTML Forms"for an example of how this type of variable definition is used in a Net.Data macro.
A variable value received from an INPUT or SELECT statement overrides a variable value set by DEFINE in a Net.Data macro.
You can call Net.Data macros as URLs and include variables in the URL to send to Net.Data, such as a user ID. For example:
http://www.ibm.com/cgi-bin/db2www/stdqry1.mac/input?field=custno
The additional data, in this case field=custno, is received by Net.Data in the same manner as form data, and is processed in the same manner.
In Net.Data macros, variables are referenced by specifying the variable name inside $( and ) (except as conditions of an IF block, where only the variable name is used). For example:
$(variableName) $(homeURL)
When Net.Data finds a variable reference, the variable reference is substituted with its value. Circular references (or cycles) are not allowed. For example, the DEFINE statements below are not allowed and result in an error when the variable is referenced and the final values are evaluated:
%DEFINE a="$(b)" %DEFINE b="$(a)"
You can use variables as part of your HTML. For example, if you have defined the variable homeURL like this:
%DEFINE homeURL="http://www.ibm.com/"You can refer to the homepage as $(homeURL) and create an anchor reference this way:
<A href="$(homeURL)">Home page</A>
Variables can be referenced in any part of a Net.Data macro. If the variable has not yet been defined at the time it is referenced, Net.Data defines the variable and gives it an initial value of null. As the Net.Data macro is parsed, when a variable reference is found, it is evaluated and replaced inline with the current value of the variable.
Conditional variables determine if a variable exists and is not null. If it does exist, the variable is given the first value, otherwise it is given the second value. The syntax for a conditional variable is:
varA = varB ? "value_1" : "value_2"
If varB is defined, varA="value_1", otherwise varA="value_2". This is equivalent to this example using an IF block:
%IF ( varB )
varA = "value_1"
%ELSE
varA = "value_2"
%ENDIF
See *** for an example of using conditional variables with list variables.
You can reference Net.Data environment variables that exist in the process under which Net.Data is running, for example:
The client is @DTW_rGETENV("SERVER_NAME")
The output looks like this:
The HTTPD server is IBM Internet Connection Server/4.1
See Net.Data Reference Guide for more information about the @DTW_GETENV and @DTW_rGETENV functions.
You can invoke other programs from a variable reference using the executable variable feature. An executable variable is defined in a Net.Data macro this way:
%DEFINE runit=%exec "testProg"Net.Data looks for the executable program in the EXEC_PATH in the Net.Data initialization file. See "EXEC_PATH" for details.
The program testProg is executed when a valid variable reference is made to the variable runit in a Net.Data macro. A simple example is to reference an execute variable from another variable definition:
%DEFINE date=%exec "date" %DEFINE dateRpt="Today is $(date)"
Wherever $(dateRpt) appears in the Net.Data macro, Net.Data returns:
Today is Tue 11-07-1995
An execute variable is never set to the value of the output of the executable program it calls. Using the previous example, the value of date is null. If you use it in a DTW_ASSIGN function call to assign its value to another variable, the value of the new variable after the assignment is null also. The only purpose of an execute variable is to invoke the program it defines. You can also pass parameters to the program to be executed by specifying them with the program name on the variable definition. In this example, the values of distance and time are passed to the program calcMPH.
%DEFINE mph=%exec "calcMPH $(distance) $(time)"
This next example returns the system date as part of the HTML report:
%DEFINE database="celdial"
%DEFINE tstamp=%exec "date"
%FUNCTION(DTW_SQL) myQuery() {
SELECT CUSTNO, CUSTNAME from dist1.customer
%REPORT{
%ROW{
<A HREF="/cgi-bin/db2www/exmp.mac/report?value1=$(V1)&value2=$(V2)">
$(V1) $(V2) </A> <BR>
%}
%}
%}
%HTML(report){
<H1>Report made: $(tstamp) </H1>
@myQuery()
%}
Each report displays the date for easy tracking. This example also puts the customer number and name in an anchor reference for another Net.Data macro. Clicking on any customer in the report calls the exmp.mac Net.Data macro, passing the number and name to the Net.Data macro.
Hidden variables can be used to conceal the actual name of a variable from people who choose to view your HTML source with their Web browser.
%HTML(INPUT) {
<FORM ...>
<P>Select fields to view:
<SELECT NAME="Field">
<OPTION VALUE="$$(name)"> Name
<OPTION VALUE="$$(addr)"> Address
</FORM>
%}
%DEFINE{
name="customer.name"
addr="customer.address"
%}
%FUNCTION(DTW_SQL) mySelect() {
SELECT $(Field) FROM customer
%}
When the HTML form is displayed on a Web browser, $$(name) and $$(addr) are replaced with $(name) and $(addr) respectively, so the actual table and column names never appear on the HTML form and there is no way to tell that the true variable names are hidden. When the customer submits the form, the HTML(REPORT) block is called. When @mySelect() calls the FUNCTION block, $(Field) is substituted in the SQL statement with customer.name or customer.addr in the SQL query.
List variables allow you to build a delimited string of values. They are particularly useful in helping you construct an SQL query with multiple items like those found in some WHERE or HAVING clauses. The syntax for a list variable is:
%LIST " value_separator " variable_name
The blanks are significant. We recommend a space before and after the value separator for most cases. Most queries use boolean or mathematical operators (for example, AND, OR, or >) for the value separator. This example illustrates the use of conditional, hidden, and list variables:
%HTML(INPUT){
<FORM METHOD="POST" ACTION="/cgi-bin/db2www/example2.mac/report">
<H2>Select one or more cities:</H2>
<INPUT TYPE="checkbox" NAME="conditions" VALUE="$$(cond1)">Sao Paola<BR>
<INPUT TYPE="checkbox" NAME="conditions" VALUE="$$(cond2)">Seattle<BR>
<INPUT TYPE="checkbox" NAME="conditions" VALUE="$$(cond3)">Shanghai<BR>
<INPUT TYPE="submit" VALUE="Submit Query">
</FORM>
%}
%DEFINE{
DATABASE="custcity"
%LIST " OR " conditions
cond1="Sao Paolo"
cond2="Seattle"
cond3="Shanghai"
whereClause=Conditions ? "WHERE $(conditions)" : ""
%}
%FUNCTION(DTW_SQL) mySelect(){
SELECT name, city FROM citylist
$(whereClause)
%}
%HTML(REPORT){
@mySelect()
%}
In the HTML form, if no boxes are checked, conditions is null so whereClause is also null in the query. Otherwise, whereClause has the values selected separated by OR. For example, if all three cities are selected, the SQL query is:
SELECT name, city FROM citylist WHERE cond1='Sao Paolo' OR cond2='Seattle' OR cond3='Shanghai'This figure shows Seattle selected, which results in this SQL query:
SELECT name, city FROM citylist WHERE cond1='Seattle'
The table variable defines a collection of related data. It contains an array of identical records, or rows, and an array of column names describing the fields in each row. A table is defined in the Net.Data macro with a statement like this:
%DEFINE myTable=%TABLE(30)
The number following TABLE is the limit on the number of rows this table can contain. To specify a table with no limit on the number of rows, use the default or specify ALL, as shown in these examples:
%DEFINE myTable2=%TABLE %DEFINE myTable3=%TABLE(ALL)
You can pass a table between functions by referring to the table variable name. The individual elements of a table can be referred to in a REPORT block of a function. Table variables are usually used for output from a SQL function and input to a report, but you can pass them as IN, OUT, or INOUT parameters to any non-SQL function. Tables can be passed to SQL functions only as OUT parameters.
The column names and field values in a table are addressed as array elements with an origin 1, rather than the standard C and C++ language convention of starting arrays at 0.
Defining a table variable causes Net.Data to implicitly define two sets
of variables that you can use to refer to the column names and field contents
of the table. One set of these implicit variables is referenced in the REPORT
block of a FUNCTION block in a Net.Data macro, and the other set is referenced
in programs called from language environments. You cannot refer to these
variables in any other block of the Net.Data macro.
| N1, N2, ..., Nj | The name of the jth column. |
| N_columnName | The value is that of columnName. |
| NLIST | A concatenation of all the column names N1 through Nj. |
| V1, V2, ..., Vj | Contains the value of the jth column in the current row. |
| V_columnName | Contains the value of the jth column in the current row. |
| VLIST | A concatenation of all the field values for V1 through Vj in the current row. |
| ROW_NUM | Contains the row number of the current row. |
| NUM_COLUMNS | Contains the number of columns in the table. |
| TOTAL_ROWS | Contains the number of rows in the table. |