目的
定義 Net.Data 從巨集呼叫的次常式。FUNCTION 區塊中的可執行檔陳述式,可以包含直接由語言環境解譯過來的語言陳述式, 也可以指示呼叫外部程式。
如果您在 FUNCTION 區塊中使用的 EXEC 區塊, 它必須是 FUNCTION 區塊中的唯一可執行檔陳述式。將可執行檔陳述式傳給語言環境之前, Net.Data 把 EXEC 區塊中的程式檔案名稱,附加到起始設定檔之 EXEC_PATH 路徑架構陳述式決定的路徑名稱中。最後將產生的字串,傳給要執行的語言環境。
語言環境處理 EXEC 區塊所用的方法,取決於特定的語言環境; REXX、System 及 Perl Net.Data 提供的語言環境支援 EXEC 區塊。
當符合 Net.Data 語言結構語法的字元於函數區塊的語言陳述式區段中使用, 作為語法有效的內含程式碼 (如 REXX 或 Perl) 的一部份時, 可能會將它們誤譯為 Net.Data 語言結構,而導致在巨集內發生錯誤或無法預測的結果。
例如,Perl 函數必須使用 COMMENT 區塊定界字元 (%{)。當執行巨集時, %{ 字元會被解譯為 COMMENT 區塊的開頭。然後,Net.Data 會尋找 COMMENT 區塊的尾端, 所以當它讀取函數區塊的尾端時,它會認為找到 COMMENT 區塊的尾端。Net.Data 隨後會繼續尋找函數區塊的尾端, 當它找不到時,便會發出錯誤。
請使用下列一種方法,使用 Net.Data 特殊字元作為內含的程式碼的一部份, 不讓 Net.Data 將它們解譯為特殊字元:
例如,下列 Perl 函數含有代表 COMMENT 區塊區隔字元 (%{) 作為 Perl 語言陳述式一部份的字元:
%function(DTW_PERL) func() { ... for $num_words (sort bynumber keys %{ $Rtitles{$num} }) { &make_links($Rtitles{$num}{$num_words}); } ... %}
若要確定 Net.Data 將 %{ 字元解譯為 Perl 原始程式,而不是 Net.Data COMMENT 區塊區隔字元, 請用下列方式之一重寫函數:
%function(DTW_PERL) func() { %EXEC{ func.prl %} %}
%define percent_openbrace = "%{" %function(DTW_PERL) func() { ... for $num_words (sort bynumber keys $(percent_openbrace) $Rtitles{$num} }) { &make_links($Rtitles{$num}{$num_words}); } ... %}
語法
>>-%FUNCTION--(--語言環境--)--函數名稱--| 參數傳送規格 |--------> .-;------------------------------------. >-----+-| 傳回規格 |--{--| 函數本體 |----%}--+----------------->< 參數傳送規格 |---(--+---------------------------------------------+---)------| | .-,-------------------------------------. | | | (1) | | | V .-IN-------. | | '----+----------+---+-----------+---名稱---+--' +-OUT------+ '-datatype--' '-INOUT----' 傳回規格 |---+----------------------+------------------------------------| '-RETURNS--(--名稱--)--' 函數本體 |---+-----------------------+-----------------------------------> | .------------------. | | V | | +----列入陳述式區塊---+-+ '-exec 區塊-------------' >-----+--------------------------------------+------------------| | .-----------------. | | V (2) | | +----報表區塊--------+---+-----------+-+ | '-訊息區塊--' | | .----------------------. | | V | | '-訊息區塊-----+----------------+--+---' | (2) | '-報表區塊-------'
註:
值
上下文
在這些上下文中可找到 FUNCTION 區塊:
限制
DB2 具有下列限制:
範例
下面是一般範例,並未涵蓋所有的語言環境。 有關在特定的語言環境中使用 FUNCTION 區塊的詳細資訊,請參閱 Net.Data 語言環境參考手冊。
範例 1:REXX 子字串函數
%DEFINE lstring = "longstring" %FUNCTION(DTW_REXX) substring(IN x, y, z) RETURNS(s) { s = substr("$(x)", $(y), $(z)); %} %DEFINE a = {@substring(lstring, "1", "4")%} %{ assigns "long" to a %}
在求 a 的值時, 找到 @ 子字串函數呼叫並執行子字串 FUNCTION 區塊。FUNCTION 區塊中的可執行陳述式會被置換, 然後字串 s = substr("longstring", 1, 4) 被傳送到 REXX 直譯器執行。 因為指定了 RETURNS 子句,所以 @子字串指定的值在 a 的運算式中被置換成"long", 即為 s 的值。
範例 2:呼叫外部 REXX 程式
%FUNCTION(DTW_REXX) my_rexx_pgm(INOUT a, b, IN c, OUT d) { %EXEC{ mypgm.cmd 這是測試 %} %} %HTML(INPUT) { <p> 原始變數值︰$(w) $(x) $(z) <p> @my_rexx_pgm(w, x, y, z) <p> 已修改之變數值︰$(w) $(x) $(z) %}
變數 w 與 x 對應至函數中的 INOUT 參數 a 與 b。 它們的值與對應至 IN 參數 c 的值 y, 應已從 HTML 表格輸入或 DEFINE 陳述式定義。 變數 a 與 b 在參數 a 與 b 傳回值時, 會被指定新值。當 OUT 參數 d 傳回一個值時,即定義了變數 z。
/* 範例 2 的 REXX 程式範例 */ /* 測試引數 */ num_args = arg(); say '有' num_args 'arguments'; do i = 1 to num_args; say 'arg' i '是"'arg(i)'"' end; /* 設定 Net.Data 傳來的變數 */ d = a || b || c; /* 連結 a, b, c 形成 d */ a = ''; /* 將 a 重設為空字串 */ b = ''; /* 將 b 重設為空字串 */ return;
有 1 引數 引數 1 是 "這是測試"
EXEC 陳述式告訴 REXX 語言環境去通知 REXX 直譯器開始執行外部 REXX 程式 mypgm.cmd。因為 REXX 語言環境可以直接與 REXX 程式共用 Net.Data 變數, 所以由它在執行 mypgm.cmd 前,會指定 REXX 變數 a、 b 及 c 為 Net.Data 變數 w、x 及 y 的值。mypgm.cmd 可以直接在 REXX 陳述式中使用變數 a、 b 及 c。 當程式終止時,REXX 變數 a、b 及 d 從 REXX 程式取回, 它們的值被指定給 Net.Data 變數 w、 x 及 z。 因為 RETURNS 子句沒有被用在 my_rexx_pgm FUNCTION 區塊的定義之內, 所以 @my_rexx_pgm 函數呼叫的值為空字串,"", (如果回覆碼為 0) 或為 REXX 程式回覆碼 (如果回覆碼不是零)。
範例 3:SQL 查詢及報告
%FUNCTION(DTW_SQL) query_1(IN x, IN y) { SELECT customer.num, order.num, part.num, status FROM customer, order, shippingpart WHERE customer.num = '$(x)' AND customer.ordernumber = order.num AND order.num = '$(y)' AND order.partnumber = part.num %REPORT{ <p>這是您的訂購狀態︰ <p>$(NLIST) <ul> %ROW{ <li>$(V1) $(V2) $(V3) $(V4) %} </ul> %} %} %DEFINE customer_name="IBM" %DEFINE customer_order="12345" %HTML(REPORT) { @query_1(customer_name, customer_order) %}
@query_1 函數呼叫在 SELECT 陳述式中以 IBM 取代 $(x),以 12345 取代 $(y)。 因為 SQL 函數 query_1 的定義中沒有定義輸出表格變數, 所以使用預設的表格 (有關詳細資料, 請參閱 TABLE 表格區塊)。REPORT 區塊中參照的 NLIST 及 Vi 變數, 是由預設的表定義所定義。REPORT 區塊產生的報告被放置在呼叫 query_1 函數的輸出 HTML。
範例 4:執行 Perl script 的系統呼叫
%FUNCTION(DTW_SYSTEM) today() RETURNS(result) { %exec{ perl "today.prl" %} %} %HTML(INPUT) { @today() %}
$date = `date`; chop $date; open(DTW, "> $ENV{DTWPIPE}") || die "無法開啟: $!"; print DTW "result = \"$date\"\n";
「系統」語言環境解譯 FUNCTION 區塊中的可執行檔陳述式時, 是經由 C 語言 system() 函數呼叫,傳給作業系統。 這個方法無法向 REXX 語言環境般,直接向可執行檔陳述式傳收 Net.Data 變數。 「系統」語言環境是以下列方法傳收變數:
遇到 @today 函數呼叫時, Net.Data 將對可執行檔陳述式進行變數替代。本例的可執行檔陳述式中沒有 Net.Data 變數, 所以不替代變數。可執行檔陳述式及參數傳給「系統」語言環境後, 此語言環境立即建立一個具名管線,並將環境變數 DTWPIPE 設定為具名管線。
然後,再以 C system() 函數呼叫,呼叫外部程式。外部程式以唯寫方式開啟管路, 再以標準資料流檔的方式將輸出參數的值寫入管路中。外部程式藉由寫入 STDOUT 產生 HTML 輸出。本例將系統日期程式的輸出, 指定至 FUNCTION 區塊 RETURNS 子句識別的變數結果中。 結果變數的這個值,則會置換 HTML 區塊中的 @today() 函數呼叫。
範例 5:Perl 語言環境
%FUNCTION(DTW_PERL) today() RETURNS(result) { $date = `date`; chop $date; open(DTW, "> $ENV{DTWPIPE}") || die "無法開啟: $!"; print DTW "result = \"$date\"\n"; %} %HTML(INPUT) { @today() %}
您可以比較本例與「範例 4」中 EXEC 陳述式的使用方式。 範例 4 的「系統」語言環境不瞭解如何解譯 Perl 程式,但知道如何呼叫外部程式。 EXEC 陳述式要它以外部程式的方式呼叫 perl 程式。 實際的 Perl 語言陳述式,是由外部 Perl 程式解譯。 範例 5 的 Perl 語言環境可以直接解譯 Perl 語言陳述式,所以沒有 EXEC 陳述式。