[pgsql-jp: 33190] PostgrsSQL7.4.2 ecpgのprepare,executeでnull値が渡せない

aya shigeto_aya_za @ mail.toyota.co.jp
2004年 6月 10日 (木) 13:51:38 JST


綾 重人と申します。

PostgreSQL7.3.3で正常に動いていたecpgプログラムを
PostgreSQL7.4.2にしてコンパイルしたところエラーとなります。

具体的にはprepareでinsert文を宣言し、動的にnull値を含む変数を
insertするためのexecute文で、
コンパイルエラー(syntaxエラー)となります。

エラーとなる行は以下です。
61 EXEC SQL execute ins_cur using :indata:ind_indata;

7.3.3では正常に動きます。
実際のアプリケーションではテーブル名が
動的にかわるためどうしても動的SQLで
null値をinsertする必要があります。

対応方法ご存知の方いらっしゃいましたら
ご教授ください。

わかりにくいと思うので、
サンプルソースより重要な部分を抜粋したものをのせます。

    38      /* テーブル作成 */
    39      EXEC SQL create table tmptable ( row1 integer );
    40

    48      /* 動的にinsertする準備 */
    49      memset(sqlstring,'\0',sizeof(sqlstring));
    50      strcpy( sqlstring , "insert into tmptable values (?)");
    51      EXEC SQL prepare ins_cur from :sqlstring;
    52
    53      /* 動的に通常のデータ登録 これはOK */
    54      indata=44;
    55      EXEC SQL execute ins_cur using :indata;
    56
    57      /* 動的にNULL値のデータ登録 */
    58      ind_indata=-1;
    59      indata=0;
    60      /* 本当はこのように書きたい が、コンパイルエラー */
    61         EXEC SQL execute ins_cur using :indata:ind_indata;


サンプル全ソースをのせます。(長文すみません。)

ここから ------------------------------------
     1  #include <stdio.h>
     2  /* #include
</usr/local/src/postgresql-7.4.2/src/interfaces/ecpg/include/sqlca.h> */
     3
     4  #include <sqlca.h>
     5
     6  void dbclose(void);
     7  void dbopen(void);
     8  void error_exit(void);
     9
    10  int main(int argc, char* argv[]){
    11
    12      /* ホスト変数 */
    13      exec sql begin declare section;
    14
    15          char sqlstring[1000];
    16
    17          int indata;
    18          int ind_indata;
    19
    20          int *indata_p;
    21
    22          int host_row1;
    23          int ind_row1;
    24
    25      exec sql end declare section;
    26
    27      /* データベースopen */
    28      dbopen();
    29
    30      /* トランザクションレベル */
    31      exec sql set transaction isolation level read committed;
    32
    33      exec sql whenever sqlerror continue;
    34
    35      /* テーブル削除 */
    36      EXEC SQL drop table tmptable;
    37
    38      /* テーブル作成 */
    39      EXEC SQL create table tmptable ( row1 integer );
    40
    41      /* 静的に通常のデータinsert */
    42      EXEC SQL insert into tmptable values (33);
    43          printf("insert sqlcode %d\n",sqlca.sqlcode);
    44      /* 静的にNULL値のデータinsert */
    45      EXEC SQL insert into tmptable values (NULL);
    46          printf("insert sqlcode %d\n",sqlca.sqlcode);
    47
    48      /* 動的にinsertする準備 */
    49      memset(sqlstring,'\0',sizeof(sqlstring));
    50      strcpy( sqlstring , "insert into tmptable values (?)");
    51      EXEC SQL prepare ins_cur from :sqlstring;
    52
    53      /* 動的に通常のデータ登録 */
    54      indata=44;
    55      EXEC SQL execute ins_cur using :indata;
    56
    57      /* 動的にNULL値のデータ登録 */
    58      ind_indata=-1;
    59      indata=0;
    60      /* 本当はこのように書きたい が、コンパイルエラー */
    61         EXEC SQL execute ins_cur using :indata:ind_indata;
    62         EXEC SQL execute ins_cur using :indata:ind_indata;
    63         EXEC SQL execute ins_cur using :indata:ind_indata;
    64         EXEC SQL execute ins_cur using :indata:ind_indata;
    65         EXEC SQL execute ins_cur using :indata:ind_indata;
    66         EXEC SQL execute ins_cur using :indata:ind_indata;
    67
    68      /* これだと0が登録されてしまう */
    69      EXEC SQL execute ins_cur using :indata;
    70
    71      /* これだとSegmentation fault
    72      indata_p=NULL;
    73      EXEC SQL execute ins_cur using :indata_p;  */
    74
    75      /* これだとコンパイルエラー
    76         ERROR: syntax error at or near ":indata_p"
    77      indata_p=NULL;
    78      EXEC SQL execute ins_cur using :indata:indata_p; */
    79
    80      EXEC SQL declare aya_cur cursor for select * from tmptable;
    81          printf("declare sqlcode %d\n",sqlca.sqlcode);
    82
    83      EXEC SQL open aya_cur ;
    84          printf("open sqlcode %d\n",sqlca.sqlcode);
    85
    86      while(1){
    87          host_row1=0;
    88          ind_row1=0;
    89          EXEC SQL fetch in aya_cur into :host_row1:ind_row1;
    90              printf("fetch sqlcode=%d error_msg=%s\n",sqlca.sqlcode,
    91
sqlca.sqlerrm.sqlerrmc);
    92          /* printf("fetch sqlcode=%d error_msg=%s\n",
        */
    93          /*                        (*ECPGget_sqlca()).sqlcode,
        */
    94          /*
(*ECPGget_sqlca()).sqlerrm.sqlerrmc); */
    95
    96          if (sqlca.sqlcode == 100 ) {
    97              break;
    98          }
    99
   100          if (ind_row1 == -1 ){
   101              printf("row1 is null\n");
   102          } else {
   103              printf("row1 %d\n",host_row1);
   104          }
   105      }
   106
   107      exec sql commit work;
   108
   109      dbclose();
   110
   111      exit(0);
   112
   113  }
   114
   115  /* エラー処理 */
   116  void error_exit(void){
   117      fprintf(stderr, "PostgreSQL error : %d[%.*s]\n",
   118              sqlca.sqlcode, sqlca.sqlerrm.sqlerrml,
sqlca.sqlerrm.sqlerrmc);
   119
   120      exec sql whenever sqlerror continue;
   121      exec sql rollback;
   122      exec sql disconnect;
   123
   124      exit(1);
   125  }
   126
   127  void dbopen(void){
   128      /* データベースに接続 */
   129      /* 何らかのエラーが発生した場合は関数 error_exit() をコール
する */
   130      exec sql whenever sqlerror do error_exit();
   131      /* データベース bookmark へユーザ dbuser として接続する */
   132      exec sql connect to aya user aya;
   133  }
   134
   135  void dbclose(void){
   136      /* データベース切り離し postgres_sqlca*/
   137      exec sql disconnect;
   138  }




pgsql-jp メーリングリストの案内