Hitachi

ノンストップデータベース HiRDB Version 10 UAP開発ガイド


7.2.2 プログラム例題

C言語による埋込み型UAPのプログラム例題を示します。

なお,SQLの文法の詳細については,マニュアル「HiRDB SQLリファレンス」を参照してください。

〈この項の構成〉

(1) 基本的な操作の例

(a) PADチャート

プログラム例題1のPADチャートを次の図に示します。

図7‒2 プログラム例題1のPADチャート(1/2)

[図データ]

図7‒3 プログラム例題1のPADチャート(2/2)

[図データ]

(b) コーディング例

プログラム例題1のコーディング例を次に示します。

    1  #include <string.h>
    2  #include <stdlib.h>
    3  
    4  #define MAXCOLUMN 80           /* max column in one line */
    5  #define INFILE   "inputf1"     /* input data file name   */
    6  
    7  /* declare functions */
    8  void abnormalend();
    9  void connecterror();
   10  
   11  FILE *input = NULL;
   12  
   13  main()
   14  {
   15    /* input data */
   16    char indata[MAXCOLUMN + 1];
   17  
   18    char in_userid[31];
   19    char in_passwd[31];
   20    char in_kubun;
   21    char in_scode[5];
   22    char in_sname[17];
   23    char in_col[3];
   24    int in_tanka;
   25    int in_gryo;
   26    char in_okubun;
   27  
   28    /* variables for SQL */
   29    EXEC SQL BEGIN DECLARE SECTION;                               1
   30      char xuserid[31];                                           1
   31      char xpasswd[31];                                           1
   32      char xscode[5];                                             1
   33      char xsname[17];                                            1
   34      char xcol[3];                                               1
   35      long xtanka;                                                1
   36      long xgryo;                                                 1
   37    EXEC SQL END DECLARE SECTION;                                 1
   38  
   39    /* input file open */                                         2
   40    input = fopen(INFILE, "r");                                   2
   41    if (input == NULL) {                                          2
   42      /* input file open error */                                 2
   43      fprintf(stderr, "can't open %s.", INFILE);                  2
   44      goto FIN;                                                   2
   45    }                                                             2
   46                                                                  2
   47    /* get userid/passwd */                                       2
   48    fgets(indata, 81, input);                                     2
   49    sscanf(indata, "%30s %30s", xuserid, xpasswd);                2
   50    if (feof(input)) {                                            2
   51      fprintf(stderr, "*** error *** no data for connect ***");   2
   52      goto FIN;                                                   2
   53    }                                                             2
   54    printf("connect start,\n");                                   2
   55    EXEC SQL WHENEVER SQLERROR PERFORM connecterror;         (a)  2
   56    EXEC SQL CONNECT USER :xuserid USING :xpasswd;           (b)  2
   57    printf("connected,\n");                                       2
   58  
   59    /* read data from inputfile */
   60    EXEC SQL WHENEVER SQLERROR PERFORM abnormalend;
   61    fgets(indata, MAXCOLUMN, input);
   62  
   63    while (!feof(input)) {
   64      sscanf(indata, "%c %4s %16s %2s %8d %8d %c",
   65        &in_kubun, in_scode, in_sname, in_col,
   66        &in_tanka, &in_gryo, &in_okubun);
   67      switch (in_kubun) {
   68      case 'I':
   69        strncpy(xscode, in_scode, 4);
   70        strncpy(xsname, in_sname, 8);
   71        strncpy(xcol, in_col, 2);
   72        xtanka = in_tanka;
   73        xgryo = in_gryo;
   74        EXEC SQL                                                  3
   75          INSERT INTO ZAIKO(SCODE,SNAME,COL,TANKA,ZSURYO)         3
   76            VALUES(:xscode,:xsname,:xcol,:xtanka,:xgryo);         3
   77        break;
   78      case 'U':
   79        strncpy(xscode, in_scode, 4);                             4
   80        xgryo = in_gryo;                                          4
   81        if (in_okubun == '1') {                                   4
   82          EXEC SQL                                           (a)  4
   83            UPDATE ZAIKO SET ZSURYO=ZSURYO+:xgryo            (a)  4
   84              WHERE SCODE=:xscode;                           (a)  4
   88        } else {                                                  4
   86          EXEC SQL                                           (b)  4
   87            UPDATE ZAIKO SET ZSURYO=ZSURYO-:xgryo            (b)  4
   88              WHERE SCODE=:xscode;                           (b)  4
   89        }
   90        break;
   91      case 'D':
   92        strncpy(xscode, in_scode, 4);
   93        EXEC SQL                                                  5
   94          DELETE FROM ZAIKO WHERE SCODE=:xscode;                  5
   95        break;
   96      }
   97      fgets(indata, MAXCOLUMN, input);
   98    }
   99  
  100    /* print zaiko list */
  101    EXEC SQL                                                      6
  102      DECLARE CR1 CURSOR FOR                                      6
  103          SELECT SCODE,SNAME,COL,TANKA,ZSURYO FROM ZAIKO;         6
  104    EXEC SQL OPEN CR1;                                            7
  105  
  106    /* print midashi */
  107    printf("\n\n");
  108    printf("  ***** 在庫表 リスト *****\n\n");
  109    printf("  商品コート゛ 商品名      色 単価   現在庫量\n");
  110    printf("  ----   ---------------- -- -------- --------\n");
  111  
  112    /* FETCH */
  113    SQLCODE = 0;
  114    while (SQLCODE <= 100) {
  115      EXEC SQL WHENEVER NOT FOUND GO TO OWARI;
  116      EXEC SQL                                                    8
  117        FETCH CR1 INTO :xscode,:xsname,:xcol,:xtanka,:xgryo;      8
  118      EXEC SQL WHENEVER NOT FOUND CONTINUE;
  119      printf("  %4s   %-16s %2s %8d %8d\n",
  120          xscode, xsname, xcol, xtanka, xgryo);
  121    }
  122  
  123  OWARI:
  124    /* finish */
  125    EXEC SQL CLOSE CR1;                                      (a)  9
  126    EXEC SQL COMMIT;                                         (b)  9
  127    printf(" *** normal ended ***\n");
  128  
  129  FIN:
  130    if (input != NULL) {
  131      fclose(input);
  132    }
  133    EXEC SQL WHENEVER SQLERROR  CONTINUE;
  134    EXEC SQL WHENEVER NOT FOUND CONTINUE;
  135    EXEC SQL WHENEVER SQLWARNING CONTINUE;
  136    EXEC SQL DISCONNECT;                                         10
  137    return(0);
  138  }
  139  
  140  
  141  void connecterror()
  142  {
  143  
  144    printf("\n************ error *** cannot connect ***\n");
  145    fclose(input);
  146    EXEC SQL DISCONNECT;
  147    exit(1);
  148  }
  149  
  150  
  151  void abnormalend()
  152  {
  153    int  wsqlcode;
  154  
  155    wsqlcode = -SQLCODE;
  156    printf("\n*** HiRDB SQL ERROR SQLCODE = %d \n", wsqlcode);
  157    printf("SQLERRMC = %s\n", SQLERRMC);
  158  
  159    EXEC SQL ROLLBACK;                                       (a)  11
  160    EXEC SQL DISCONNECT;                                     (b)  11
  161    exit(2);
  162  }

<説明>

  1. 埋込みSQL宣言節の始まりと終わり

    UAP中で使用する変数をBEGIN DECLARE SECTIONとEND DECLARE SECTIONとで囲んで,埋込みSQL宣言節の始まりと終わりを示します。

  2. HiRDBとの接続

    (a) 特異状態発生時の指定

    以下のSQLの実行後に,エラー(SQLERROR)が発生した場合の処理として,分岐先(connecterror)を指定します。

    (b) 接続

    HiRDBに認可識別子及びパスワードを連絡して,UAPがHiRDBを使用できる状態にします。

  3. 在庫表への行の挿入

    在庫表の各列に,埋込み変数に読み込まれた値を挿入します。

  4. 在庫表の行の更新

    (a) 入庫

    在庫表から,埋込み変数(:xgno)に読み込んだ品番をキーとして,更新する行を検索します。検索した行の数量(SURYO)の値に,埋込み変数(:xsuryo)に読み込んだ値を加算して,行を更新します。

    (b) 在庫

    在庫表から,埋込み変数(:xgno)に読み込んだ品番をキーとして,更新する行を検索します。検索した行の数量(SURYO)の値に,埋込み変数(:xsuryo)に読み込んだ値を減算して,行を更新します。

  5. 在庫表の行の削除

    在庫表から,埋込み変数(:xgno)に読み込んだ品番をキーとして,それと等しいキーを持つ行を削除します。

  6. カーソルCR1の宣言

    在庫表(ZAIKO)の行を検索するために,カーソルCR1を宣言します。

  7. カーソルCR1のオープン

    在庫表(ZAIKO)の検索行の直前にカーソルを位置づけて,行を取り出せる状態にします。

  8. 在庫表の行の取り出し

    在庫表(ZAIKO)から,カーソルCR1の示す行を1行取り出し,各埋込み変数に設定します。

  9. カーソルCR1のクローズとトランザクションの終了

    (a) カーソルCR1のクローズ

    カーソルCR1を閉じます。

    (b) トランザクションの終了

    現在のトランザクションを正常終了させて,そのトランザクションによるデータベースへの追加,更新,削除の結果を有効にします。

  10. HiRDBの切り離し

    UAPをHiRDBから切り離します。

  11. トランザクションの取り消し

    (a) トランザクションの無効化

    現在のトランザクションを取り消して,そのトランザクションによるデータベースへの追加,更新,削除の結果を無効にします。

    (b) HiRDBの切り離し

    UAPをHiRDBから切り離します。

(2) ユーザ定義のSQL記述領域を使用した例

(a) PADチャート

プログラム例題2のPADチャートを次の図に示します。

図7‒4 プログラム例題2のPADチャート(1/4)

[図データ]

図7‒5 プログラム例題2のPADチャート(2/4)

[図データ]

図7‒6 プログラム例題2のPADチャート(3/4)

[図データ]

図7‒7 プログラム例題2のPADチャート(4/4)

[図データ]

(b) コーディング例

プログラム例題2のコーディング例を次に示します。

    1  /******************************************************/
    2  /*                                                    */
    3  /* ALL RIGHTS RESERVED,COPYRIGHT (C)1997,HITACHI,LTD. */
    4  /* LICENSED MATERIAL OF HITACHI,LTD.                  */
    5  /*                                                    */
    6  /* SQLDAを使用したFETCHのサンプル                    */
    7  /*                                                    */
    8  /******************************************************/
    9
   10
   11  #include <stdio.h>
   12  #include <stdlib.h>
   13  #include <string.h>
   14  #include "pdbsqlda.h"                                          1
   15
   16
   17  static void Describe();
   18  static void Fetch();
   19  static void ClearSqlda(short);
   20  static void errmsg();
   21
   22  /***********************************************************/
   23  /*  GLOBAL VARIABLE                                        */
   24  /***********************************************************/
   25  short ErrFlg;
   26
   27  /***********************************************************/
   28  /*  GLOBAL VARIABLE                                        */
   29  /***********************************************************/
   30
   31  /* sqlda */
   32  PDUSRSQLDA(10) xsqlda;                                         2
   33
   34  /* sqlcnda */                                                  3
   35  struct {                                                       3
   36      short    sqlnz;                                            3
   37      struct {                                                   3
   38           short    sqlnamel;                                    3
   39           char     sqlnamec[30];                                3
   40      } SQLNAME[10];                                             3
   41  } ucnda;                                                       3
   42
   43
   44  /***********************************************************/
   45  /*                                                         */
   46  /*  MAIN ROUTINE                                           */
   47  /*                                                         */
   48  /***********************************************************/
   49  int main(
   50  int   argc,
   51  char  *argv[]) 
   52  {
   53
   54  /***********************************************************/
   55  /*  CONNECT                                                */
   56  /***********************************************************/
   57      EXEC SQL
   58        WHENEVER SQLERROR  GOTO :ERR_EXIT;
   59
   60      printf("***** connect start \n");
   61      EXEC SQL
   62         CONNECT;                                                4
   63      printf("***** connect : END\n");
   64
   65  /***********************************************************/
   66  /*  DESCRIBE                                               */
   67  /***********************************************************/
   68      Describe();                                                5
   69      if(ErrFlg < 0){                                            5
   70          goto ERR_EXIT;                                         5
   71      }                                                          5
   72                                                                 5
   73  /***********************************************************/  5
   74  /*  FETCH                                                  */  5
   75  /***********************************************************/  5
   76      Fetch();                                                   5
   77      if(ErrFlg < 0){                                            5
   78          goto ERR_EXIT;                                         5
   79      }                                                          5
   80
   81  /***********************************************************/
   82  /*  END OF ALL                                             */
   83  /***********************************************************/
   84  ERR_EXIT:
   85      if(SQLCODE < 0){
   86          errmsg();
   87          ErrFlg = -1;
   88      }
   89
   90      EXEC SQL
   91        WHENEVER SQLERROR  CONTINUE;
   92      EXEC SQL
   93        WHENEVER NOT FOUND CONTINUE;
   94      EXEC SQL
   95        WHENEVER SQLWARNING CONTINUE;
   96
   97      EXEC SQL
   98        DISCONNECT;                                              6
   99
  100      return(ErrFlg);
  101  }
  102
  103
  104  /***********************************************************/
  105  /*                                                         */
  106  /*  DYNAMIC CURSOR                                         */
  107  /*                                                         */
  108  /***********************************************************/
  109  static void Fetch()
  110  {
  111      EXEC SQL BEGIN DECLARE SECTION;
  112      char XCUSTOM_CD[6];
  113      char XCUSTOM_NAME[31];
  114      char XTELNO[13];
  115      char XZIPCD[4];
  116      char XADDRESS[31];
  117      EXEC SQL END DECLARE SECTION;
  118
  119      EXEC SQL
  120        WHENEVER SQLERROR  GOTO :Exit_Fetch;
  121
  122      EXEC SQL
  123         DECLARE CUR2 CURSOR FOR SEL1;                           7
  124
  125  /***********************************************************/
  126  /*  OPEN CURSOR                                            */
  127  /***********************************************************/
  128      printf("***** DYNAMIC CURSOR open start\n");
  129      EXEC SQL
  130        OPEN CUR2;                                               8
  131      printf("***** DYNAMIC CURSOR open : END\n");
  132
  133
  134  /***********************************************************/
  135  /*  FETCH                                                  */
  136  /***********************************************************/
  137      printf("***** fetch (use sqlda) start\n");
  138
  139
  140      EXEC SQL
  141        WHENEVER NOT FOUND GOTO FETCH2_END;
  142
  143      for(;;) {
  144          ClearSqlda(5);                                         9
  145          PDSQLDATA(xsqlda, 0) = (void *)XCUSTOM_CD;        (a)  9
  146          PDSQLCOD(xsqlda, 0) = PDSQL_CHAR;                 (a)  9
  147          PDSQLLEN(xsqlda, 0) = sizeof(XCUSTOM_CD)-1;       (a)  9
  148          PDSQLDATA(xsqlda, 1) = (void *)XCUSTOM_NAME;      (b)  9
  149          PDSQLCOD(xsqlda, 1) = PDSQL_CHAR;                 (b)  9
  150          PDSQLLEN(xsqlda, 1) = sizeof(XCUSTOM_NAME)-1;     (b)  9
  151          PDSQLDATA(xsqlda, 2) = (void *)XTELNO;            (c)  9
  152          PDSQLCOD(xsqlda, 2) = PDSQL_CHAR;                 (c)  9
  153          PDSQLLEN(xsqlda, 2) = sizeof(XTELNO)-1;           (c)  9
  154          PDSQLDATA(xsqlda, 3) = (void *)XZIPCD;            (d)  9
  155          PDSQLCOD(xsqlda, 3) = PDSQL_CHAR;                 (d)  9
  156          PDSQLLEN(xsqlda, 3) = sizeof(XZIPCD)-1;           (d)  9
  157          PDSQLDATA(xsqlda, 4) = (void *)XADDRESS;          (e)  9
  158          PDSQLCOD(xsqlda, 4) = PDSQL_CHAR;                 (e)  9
  159          PDSQLLEN(xsqlda, 4) = sizeof(XADDRESS)-1;         (e)  9
  160
  161          memset(XCUSTOM_CD, 0, sizeof(XCUSTOM_CD));
  162          memset(XCUSTOM_NAME, 0, sizeof(XCUSTOM_NAME));
  163          memset(XTELNO, 0, sizeof(XTELNO));
  164          memset(XZIPCD, 0, sizeof(XZIPCD));
  165          memset(XADDRESS, 0, sizeof(XADDRESS));
  166
  167          EXEC SQL FETCH CUR2
  168            USING DESCRIPTOR :xsqlda;                            10
  169
  170          printf("%s ", XCUSTOM_CD);
  171          printf("%s ", XCUSTOM_NAME);
  172          printf("%s ", XTELNO);
  173          printf("%s ", XZIPCD);
  174          printf("%s\n", XADDRESS);
  175      }
  176  FETCH2_END:
  177      printf("***** fetch : END\n");
  178
  179  /***********************************************************/
  180  /*  CLOSE CURSOR                                           */
  181  /***********************************************************/
  182      printf("*****  close start\n");
  183      EXEC SQL
  184        WHENEVER NOT FOUND  CONTINUE;
  185      EXEC SQL
  186        CLOSE CUR2;                                              11
  187      printf("*****  close : END\n");
  188
  189  /***********************************************************/
  190  /*                                                         */
  191  /***********************************************************/
  192  Exit_Fetch:   
  193      if(SQLCODE < 0){
  194          errmsg(); 
  195          ErrFlg = -1;
  196      }
  197      return;
  198  }
  199
  200
  201  /***********************************************************/
  202  /*  DESCRIBE                                               */
  203  /***********************************************************/
  204  static void Describe()
  205  {
  206      short  i;
  207
  208      EXEC SQL
  209        WHENEVER SQLERROR  GOTO :Exit_Describe;  
  210
  211  /***********************************************************/
  212  /*  PREPARE                                                */
  213  /***********************************************************/
  214      printf("***** prepare start\n");
  215      EXEC SQL                                                   12
  216        PREPARE SEL1                                             12
  217          FROM 'SELECT * FROM CUSTOM'                            12
  218          WITH SQLNAME OPTION;                                   12
  219      printf("***** prepare  : END\n");
  220
  221  /***********************************************************/
  222  /*  DESCRIBE                                               */
  223  /***********************************************************/
  224      PDSQLN(xsqlda) = 10;
  225      printf("***** describe start\n");
  226      EXEC SQL
  227         DESCRIBE SEL1 INTO :xsqlda :ucnda;                      13
  228      printf("***** describe : END\n");
  229
  230      printf(" describe result\n");
  231      printf("  NUMBER OF DATA = %d\n", PDSQLD(xsqlda));
  232      printf("  NUMBER OF COLUMN NAME = %d\n", ucnda.sqlnz);
  233      for (i = 0 ; i < ucnda.sqlnz ; i++ ) {
  234          printf(" [%d]", i );
  235          printf(" DATA TYPE(%d)", PDSQLCOD(xsqlda, i));
  236          printf(" DATA LENGTH(%d)", PDSQLLEN(xsqlda, i));
  237          printf(" COLUMN NAME(%s)\n", ucnda.SQLNAME[i].sqlnamec);
  238      }
  239
  240  /***********************************************************/
  241  /*                                                         */
  242  /***********************************************************/
  243  Exit_Describe:  
  244      if(SQLCODE < 0){
  245          errmsg();
  246          ErrFlg = -1;
  247      }
  248      return;
  249  }
  250
  251
  252  /***********************************************************/
  253  /*  Clear SQLDA                                            */
  254  /***********************************************************/
  255  static void ClearSqlda(
  256  short num)
  257  {
  258      PDSQLN(xsqlda) = num;                                      14
  259      PDSQLD(xsqlda) = num;                                      14
  260      while(num-->0){
  261          PDSQLDATA(xsqlda, num) = NULL;                         15
  262          PDSQLIND(xsqlda, num)  = NULL;                         15
  263          PDSQLDIM(xsqlda, num) = 0;                             15
  264          PDSQLXDIM(xsqlda, num) = 1;                            15
  265          PDSQLSYS(xsqlda, num) = 0;                             15
  266          PDSQLCOD(xsqlda, num) = 0;                             15
  267          PDSQLLEN(xsqlda, num) = 0;                             15
  268      }
  269      return;
  270  }
  271
  272
  273  /**********************************************************/
  274  /*                                                         */
  275  /*  WARNING                                                */
  276  /*                                                         */
  277  /***********************************************************/
  278  static void errmsg()
  279  {
  280      int wsqlcode;
  281
  282      if(SQLCODE > 0){
  283          printf(">>>警告\n");
  284      }
  285      if(SQLCODE < 0){
  286          printf(">>> 異常発生\n");
  287      }  
  288      wsqlcode = SQLCODE;
  289      printf(">>> sqlcode = %d\n", SQLCODE);
  290      printf(">>> sqlwarn = %c", SQLWARN0);
  291      printf("%c", SQLWARN1);
  292      printf("%c", SQLWARN2);
  293      printf("%c", SQLWARN3);
  294      printf("%c", SQLWARN4);
  295      printf("%c", SQLWARN5);
  296      printf("%c", SQLWARN6);
  297      printf("%c", SQLWARN7);
  298      printf("%c", SQLWARN8);
  299      printf("%c", SQLWARN9);
  300      printf("%c", SQLWARNA);
  301      printf("%c", SQLWARNB);
  302      printf("%c\n", SQLWARNC);
  303
  304  #if defined(HIUXWE2) || defined(WIN32)
  305      printf(">>> message = %s\n", SQLERRMC);
  306  #else
  307      printf(">>> message = %Fs\n", SQLERRMC);
  308  #endif
  309      return;
  310  }

<説明>

  1. 提供ヘッダファイルのインクルード

    SQL記述領域に設定・参照するとき用いるデータコードの定数宣言や,SQL記述領域自体のデータ型を宣言します。

  2. SQL記述領域の宣言

    UAPでユーザが独自に使用するSQL記述領域を定義します。データ型は提供ヘッダファイルの中で定義されているものです。

  3. 列名記述領域の宣言

    列名をDESCRIBE文で取得するときに用いる,変数を定義します。

  4. HiRDBへの接続

    環境変数PDUSERに定義されている認可識別子とパスワードを使用してサーバに接続します。

  5. 顧客表(CUSTOM)の検索

    顧客表(CUSTOM)の各列の列名を取得し,表に格納されているすべての行をユーザ定義のSQL記述領域を用いて検索して表示します。

  6. HiRDBの切り離し

    UAPをサーバから切り離します。

  7. カーソルCUR2の宣言

    顧客表(CUSTOM)の行を検索するために,カーソルCUR2を宣言します。

  8. カーソルCUR2のオープン

    顧客表(CUSTOM)の検索行の直前にカーソルを位置づけて,行を取り出せる状態にします。

  9. ユーザ定義のSQL記述領域の設定

    FETCH文実行時に指定する,ユーザ定義のSQL記述領域の設定をします。

    (a) 1列目のデータを格納する領域のアドレスとデータコード,データ長を設定します。

    (b) 2列目のデータを格納する領域のアドレスとデータコード,データ長を設定します。

    (c) 3列目のデータを格納する領域のアドレスとデータコード,データ長を設定します。

    (d) 4列目のデータを格納する領域のアドレスとデータコード,データ長を設定します。

    (e) 5列目のデータを格納する領域のアドレスとデータコード,データ長を設定します。

  10. 顧客表の行の取り出し

    顧客表(CUSTOM)から,カーソルCUR2の示す行を1行取り出し,ユーザ定義のSQL記述領域が示す領域に設定します。

  11. カーソルCUR2のクローズ

    カーソルCUR2を閉じます。

  12. SQLの動的実行の用意

    DESCRIBE文で顧客表(CUSTOM)の各列の列名とデータ型,データ長を取得するために,表を検索するSELECT文を用意します。

  13. 列名とデータ型の取得

    顧客表(CUSTOM)の各列のデータ型,データ長を取り出して,ユーザ定義のSQL記述領域に設定します。また,各列の列名を取り出して,ユーザ列名記述領域に設定します。

  14. ユーザ定義のSQL記述領域の列数の設定

    ユーザ定義のSQL記述領域に,SQL記述領域の大きさと取得する列の個数を設定します。

  15. ユーザ定義のSQL記述領域のクリア

    ユーザ定義のSQL記述領域の中の,各列に対応した領域をクリアします。

(3) LOBデータを操作する例

(a) PADチャート

プログラム例題3のPADチャートを次の図に示します。

図7‒8 プログラム例題3のPADチャート(1/3)

[図データ]

図7‒9 プログラム例題3のPADチャート(2/3)

[図データ]

図7‒10 プログラム例題3のPADチャート(3/3)

[図データ]

(b) コーディング例

プログラム例題3のコーディング例を次に示します。

    1  /******************************************************/
    2  /*                                                    */
    3  /* ALL RIGHTS RESERVED,COPYRIGHT (C)1997,HITACHI,LTD. */
    4  /* LICENSED MATERIAL OF HITACHI,LTD.                  */
    5  /*                                                    */
    6  /******************************************************/
    7
    8
    9  #include <stdio.h>
   10  #include <stdlib.h>
   11  #include <stddef.h>
   12  #include <ctype.h>
   13  #include <string.h>
   14
   15  static void InitTable();
   16  static void TestBlob();
   17  static void warning();
   18
   19
   20  /***********************************************************/
   21  /*  GLOBAL VARIABLE                                        */
   22  /***********************************************************/
   23  short ErrFlg;
   24
   25  EXEC SQL BEGIN DECLARE SECTION;
   26     short XSINT_IN;     
   27     short XSINT_OUT;     
   28     long  XINT_IN;
   29     long  XINT_OUT;
   30     SQL TYPE IS BLOB(16K) XBLOB_IN;                             1
   31     SQL TYPE IS BLOB(16K) XBLOB_OUT;                            1
   32  EXEC SQL END DECLARE SECTION;
   33
   34  /*
   35   *   name = MAIN
   36   *   func =  SAMPLE
   37   *   io   =  argc : i :
   38   *           argv : i :
   39   *   return = 0,-1
   40   *   note   =  This program needs "RDUSER02" rdarea on Server.
   41   *   date =  98.04.24 by matsushiba
   42   */
   43  int main(
   44  int   argc,
   45  char  *argv[])
   46  {
   47      ErrFlg = 0;
   48
   49  /*************************************************************/
   50  /*                                                           */
   51  /*************************************************************/
   52      EXEC SQL
   53        WHENEVER SQLERROR goto ERREXIT;
   54
   55      EXEC SQL
   56        WHENEVER SQLWARNING PERFORM :warning;
   57
   58      EXEC SQL CONNECT;                                          2
   59
   60
   61  /***********************************************************/
   62  /*  INIT                                                   */
   63  /***********************************************************/
   64      InitTable();                                               3
   65      if(ErrFlg < 0){                                            3
   66          goto ERREXIT;                                          3
   67      }                                                          3
   68
   69  /**************************************************/
   70  /*                                                */
   71  /**************************************************/
   72      TestBlob();                                                4
   73      if(ErrFlg < 0){                                            4
   74          goto ERREXIT;                                          4
   75      }                                                          4
   76
   77  /*************************************************************/
   78  /*                                                           */
   79  /*************************************************************/
   80  ERREXIT:
   81      if(SQLCODE < 0){
   82          printf(":> ERROR HAPPENED!!\n");
   83          warning();
   84          ErrFlg = -1;
   85      }
   86
   87      EXEC SQL
   88        WHENEVER SQLERROR  CONTINUE;
   89      EXEC SQL
   90        WHENEVER NOT FOUND CONTINUE;
   91      EXEC SQL
   92        WHENEVER SQLWARNING CONTINUE;
   93
   94      EXEC SQL DISCONNECT;                                       5
   95
   96      return(ErrFlg);
   97  }
   98  
   99
  100  /***********************************************************/
  101  /*  INIT                                                   */
  102  /***********************************************************/
  103  static void InitTable()
  104  {
  105
  106  /************************************************************/
  107  /*                                                          */
  108  /************************************************************/
  109      EXEC SQL
  110        WHENEVER SQLERROR  CONTINUE;
  111
  112      EXEC SQL                                                   6
  113       DROP TABLE SMPTBL;                                        6
  114                                                                 6
  115      EXEC SQL                                                   6
  116        CREATE SCHEMA;                                           6
  117
  118      printf("## CREATE TABLE\n");
  119
  120      EXEC SQL
  121        WHENEVER SQLERROR  GOTO INIT_ERROR;
  122
  123      printf("## CREATE SMPTBL\n");
  124      EXEC SQL                                                   7
  125        CREATE TABLE SMPTBL(CLM1  BLOB(30K) IN RDUSER02,         7
  126                            CLM2  SMALLINT,                      7
  127                            CLM3  INTEGER);                      7
  128
  129      return;
  130
  131  INIT_ERROR:
  132      warning();
  133      ErrFlg = -1;
  134      return;
  135  }
  136
  137
  138
  139  /**********************************************************/
  140  /*  TEST BLOB                                             */
  141  /**********************************************************/
  142  static void TestBlob()
  143  {
  144      short cnt;
  145
  146      EXEC SQL
  147        WHENEVER  SQLERROR goto :ExitTestBlob;
  148
  149      EXEC SQL
  150        WHENEVER  SQLWARNING PERFORM :warning;
  151
  152  /**********************************************************/
  153  /*  INSERT                                                */
  154  /**********************************************************/
  155      memset(XBLOB_IN.XBLOB_IN_data,
  156             0x55,
  157             sizeof(XBLOB_IN.XBLOB_IN_data));
  158      XBLOB_IN.XBLOB_IN_length = sizeof(XBLOB_IN.XBLOB_IN_data);
  159
  160      printf("## INSERT \n");
  161      for(cnt=1; cnt<5; cnt++){
  162          XSINT_IN = cnt;
  163          XINT_IN = 100+cnt;
  164          EXEC SQL                                               8
  165            INSERT INTO SMPTBL                                   8
  166                VALUES(:XBLOB_IN, :XSINT_IN, :XINT_IN);          8
  167      }
  168      EXEC SQL COMMIT;
  169  
  170  /**********************************************************/
  171  /*  FETCH                                                 */
  172  /**********************************************************/
  173      printf("## FETCH \n");
  174
  175      EXEC SQL                                                   9
  176        DECLARE CUR_BLOB CURSOR FOR                              9
  177           SELECT * FROM SMPTBL;                                 9
  178
  179      EXEC SQL
  180        OPEN CUR_BLOB;                                           10
  181
  182      EXEC SQL
  183        WHENEVER NOT FOUND GOTO FETCH_END;
  184
  185      for(;;){
  186          memset(XBLOB_OUT.XBLOB_OUT_data,
  187                 0,
  188                 sizeof(XBLOB_OUT.XBLOB_OUT_data));
  189          XBLOB_OUT.XBLOB_OUT_length = 0;
  190          EXEC SQL                                               11
  191            FETCH CUR_BLOB INTO :XBLOB_OUT,                      11
  192                                :XSINT_OUT,                      11
  193                                :XINT_OUT;                       11
  194
  195              printf("CLM1 XBLOB_length == %d\n",
  196                      XBLOB_OUT.XBLOB_OUT_length);
  197              printf("CLM2 = %d\n", XSINT_OUT);
  198              printf("CLM3 = %ld\n", XINT_OUT);
  199      }
  200  FETCH_END:
  201      EXEC SQL
  202        WHENEVER NOT FOUND CONTINUE;
  203
  204      EXEC SQL
  205        CLOSE CUR_BLOB;                                          12
  206
  207  /**********************************************************/
  208  /*  UPDATE                                                */
  209  /**********************************************************/
  210      memset(XBLOB_IN.XBLOB_IN_data,
  211             0x38,
  212             sizeof(XBLOB_IN.XBLOB_IN_data));
  213      XBLOB_IN.XBLOB_IN_length = sizeof(XBLOB_IN.XBLOB_IN_data);
  214
  215      printf("## UPDATE\n");
  216      EXEC SQL
  217        UPDATE SMPTBL SET CLM1=:XBLOB_IN;                        13
  218
  219      EXEC SQL COMMIT;
  220
  221  /***********************************************************/
  222  /*                                                         */
  223  /***********************************************************/
  224  ExitTestBlob:
  225      if(SQLCODE < 0){
  226          warning();
  227          ErrFlg = -1;
  228      }
  229      return;
  230  }
  231
  232 
  233  /***********************************************************/
  234  /*  WARNING                                                */
  235  /***********************************************************/
  236  static void warning()
  237  {
  238      if(SQLCODE < 0){
  239          printf(">>>ERROR\n");
  240          printf(">>> sqlcode = %d\n", SQLCODE);
  241  #if defined(HIUXWE2) || defined(WIN32)
  242          printf(":> message = %s\n", SQLERRMC);
  243  #else    
  244          printf(":> message = %Fs\n", SQLERRMC);
  245  #endif
  246      }
  247      else{
  248          printf(">>>WARNING\n");
  249          printf(">>> sqlwarn = %c", SQLWARN0);
  250          printf("%c", SQLWARN1);
  251          printf("%c", SQLWARN2);
  252          printf("%c", SQLWARN3);
  253          printf("%c", SQLWARN4);
  254          printf("%c", SQLWARN5);
  255          printf("%c", SQLWARN6);
  256          printf("%c", SQLWARN7);
  257          printf("%c", SQLWARN8);
  258          printf("%c", SQLWARN9);
  259          printf("%c", SQLWARNA);
  260          printf("%c", SQLWARNB);
  261          printf("%c\n", SQLWARNC);
  262      }
  263      return;
  264  }

<説明>

  1. LOB型の埋込み変数の宣言

    書き込み用のLOB型の埋込み変数(:XBLOB_IN)と,読み取り用のLOB型の埋込み変数(:XBLOB_OUT)を宣言します。

  2. HiRDBへの接続

    環境変数PDUSERに定義されている認可識別子とパスワードを使用してサーバに接続します。

  3. 表の初期化

    LOB型の列を持つ表(SMPTBL)を定義します。

  4. LOBデータの挿入・検索・更新

    空の表(SMPTBL)にLOB型の列を含む行を挿入し,すべての行を検索した後,LOB型の列の内容を新しいLOBデータに更新します。

  5. HiRDBの切り離し

    UAPをサーバから切り離します。

  6. 表(SMPTBL)を作成するための準備

    LOB型の列を含む表(SMPTBL)を作成するため,同名の表があった場合は削除し,スキーマがないときのためにスキーマを生成します。

  7. LOB型の列を含む表(SMPTBL)を作成する

    LOB型の列を含む表(SMPTBL)を作成します。LOBデータはLOB専用のRDエリア(RDUSER02)に格納するように定義するので,サーバにユーザLOB用RDエリアを作成しておかなければなりません。ユーザLOB用RDエリアがない場合はエラーとなります。

  8. LOBデータの追加

    LOB型の列を持つ表(SMPTBL)に,埋込み変数(:XBLOB_IN,:XINT_IN,:XSINT_IN)に設定した値を追加します。

  9. カーソルCUR_BLOBの宣言

    LOB型の列を含む表(SMPTBL)を検索するために,カーソルCUR_BLOBを宣言します。

  10. カーソルCUR_BLOBのオープン

    LOB型の列を含む表(SMPTBL)の検索行の直前にカーソルを位置づけて,各行を取り出せる状態にします。

  11. LOB型データの取り出し

    LOB型の列を含む表(SMPTBL)のカーソルCUR_BLOBの示す行を1行取り出し,埋込み変数(:XBLOB_OUT,:XINT_OUT,:XSINT_OUT)に設定します。

  12. カーソルCUR_BLOBのクローズ

    カーソルCUR_BLOBを閉じます。

  13. LOBデータの更新

    表(SMPTBL)のLOB型の列の値を,埋込み変数(:XBLOB_IN)の値で更新します。