30.13. 內部

這一節解釋 ECPG 在內部是如何 運轉的。這些信息有時候可以幫助用戶理解如何使用 ECPG

ecpg 寫到輸出裡的頭四行是固定的行。 兩行是注釋,另外兩行是與庫接口的必要的頭文件行。 然後預處理器讀取文件並且寫輸出流。通常它只是把所有東西 都回顯到輸出中去。

如果它看到一個 EXEC SQL 語句, 它就變換並且修改它。命令以 EXEC SQL 開頭, 以 ; 結尾。所有在中間的東西都被當作一個 SQL 語句並且進行變量代換的解析。

如果一個符號以一個冒號(:)開頭,則發生 變量代換。預編譯器在前面的 EXEC SQL DECLARE 段裡聲明的 變量中找出該名字的變量。

庫裡面最重要的函數是 ECPGdo,它負責執行 大多數命令。它接受變元的參數個數。這些參數的個數可能很容易達到 50 個或者更多,我們希望在任何平台上這都不是問題。

參數是:

一個行號

這是原始行的行號;只是在錯誤信息中使用。

一個字串

這是要發出的 SQL 命令。它被輸入變量修改,也就是說, 在編譯時未知的,但是需要輸入到命令中的變量。在放變量的地方,字串包含 ?

輸入變量

每個輸入變量都導致十個參數的生成。(見下文。)

ECPGt_EOIT

一個 enum,告訴我們沒有更多輸入變量了。

輸出變量

每個輸出變量導致十個參數的創建。(見下文。) 這些變量被這些函數填充。

ECPGt_EORT

一個指出沒有更多變量的 enum

對于每個屬于 SQL 命令一部分的變量, 函數都獲得十個參數:

  1. 一個表明變量類型的特殊符號。

  2. 一個指向其數值的指針,或者一個指向指針的指針。

  3. 如果變量是 char 或者 varchar,則是變量的大小。

  4. 數組中的元素個數(用于抓取數組)。

  5. 指向數組中下一個元素的偏移量(用于抓取數組)。

  6. 以一種特殊符號表示的指示器變量的類型。

  7. 一個指向指示器變量的指針。

  8. 0

  9. 指示器數組中的元素個數(用于抓取數組)。

  10. 指向指示器數組的下一個元素的偏移量(用于抓取數組)。

請注意,不是所有 SQL 命令都這麼對待。比如,一個像 下面這樣的打開遊標的語句:

EXEC SQL OPEN cursor;

不會被拷貝到輸出中。而是使用遊標的 DECLARE 命令, 因為它同樣也打開遊標。

下面是一個完整的例子,描述了文件 foo.pgc 經過于編譯器處理後的輸出(細節可能隨著每個不同的預處理器版本而變化):

EXEC SQL BEGIN DECLARE SECTION;
int index;
int result;
EXEC SQL END DECLARE SECTION;
...
EXEC SQL SELECT res INTO :result FROM mytable WHERE index = :index;

is translated into:

/* Processed by ecpg (2.6.0) */
/* These two include files are added by the preprocessor */
#include <ecpgtype.h>;
#include <ecpglib.h>;

/* exec sql begin declare section */

#line 1 "foo.pgc"

 int index;
 int result;
/* exec sql end declare section */
...
ECPGdo(__LINE__, NULL, "SELECT res FROM mytable WHERE index = ?     ",
        ECPGt_int,&(index),1L,1L,sizeof(int),
        ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
        ECPGt_int,&(result),1L,1L,sizeof(int),
        ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 147 "foo.pgc"

(這裡的對齊是我們為了增強可讀性加的, 可不是預處理器能幹的事情。)