($title_img_alt)

こちらからの投稿は、先頭に表示されているコメントへの返信になります。
サブプロシージャ内で定義したSQLカーソルのスコープについて T.K さん [ 6月3日(水) 19時34分 ]
お世話になっております。

どなたかご存知の方があればご教示ください。

現在、再帰呼出しするサブプロシージャを作成中なのですが、
そのサブプロシージャ内で定義したSQLのカーソルは、
その呼出し階層に対応したローカル変数として新しく定義されるのでしょうか?

現在V5.4(古いOSです)で動かしている限り、
SQLカーソルを定義したサブプロシージャ(たとえば、'SP'(Level-0))の中で、
CALLP 'SP' (Level-1)
と再帰的に呼出し、Level-1からLevel-0へReturnした後で、
Level-0のNextRecordをFetchしようとするとエラーになりますので、
こちらの期待通りに呼出しの都度新しくカーソルが作られる(新しく割付けられる?)
わけではないと思っています。

古い記事ですが、以下、
*ttps://www.e-bellnet.com/special/tec/tec_0806.html
にi5における不具合のような話が載っていましたので、
変数の定義については疑わしい部分があると読めますが、
SQLのカーソルについてはどうなのか判然としません。

記事にある不具合についてはV6.1で修正されているのだと思いますが、
SQLカーソルについても再帰呼出時に特に考慮する必要がないように
コンパイルされるのでしょうか?

それとも、そもそもSQLのカーソルを上記のように使うこと自体が
だめなのでしょうか?

以上、お分かりの方がおられましたらよろしくお願いいたします。
RE:サブプロシージャ内で定義したSQLカーソルのスコープについて IKD さん [ 6月7日(日) 8時46分 ]
興味深い高度な話だと思います。

再帰呼び出しの手法は意図的に使用されているのであれば無限再帰(スタック・オーバーフロー)に
ならない限り、問題はありません。
再帰呼び出しもテクニックとして利用することもありますので。

さてプロシージャー内に定義したSQLカーソルは、一見するとローカル変数として
定義されているので、再帰呼び出しでもそれぞれ独立してプロシージャー内で
定義されているはず、というのも妥当な推論です。

ところで SQLカーソルは変数なのでしょうか ?
SQLのコンパイル・リストおよび QTEMP/QSQLTEMP のRPGソースを調べてみてください。
SQLのコンパイルはコンパイラーによって QTEMP/QSQLTEMP に展開されてから
これを最終的にコンパイルする仕組みをとっています。

展開されたコンパイル・リストまたは QTEMP/QSQLTEMP を精査してみると
定義したはずの SQLカーソルは、どこにも見当たりません。
( SQL カーソルはコメント・アウトされています。)
SQL カーソルは式として展開されていますがローカル変数として
保護する仕組みもないようです。

つまり SQLカーソルとは概念であって変数ではないのです。
従ってローカル変数として他から保護されているものではありません。
グローバル変数として理解するしかありません。

結論として SQLカーソルはローカル変数とはなりません。

-- SQLバインドは OPM のときに開発された手法ですので ILE化によって SQL展開を変更する
  のは従来のソフトウェア資産と矛盾することになると IBM は考えたのでしょう。
  System i は、そうそう通常の使用では不具合はありません。
   元々これは変数ではないので不具合ではありません。
  簡単にバグだと決めつける記事のほうが論拠に欠けるものです。
RE:サブプロシージャ内で定義したSQLカーソルのスコープについて T.K さん [ 5月9日(月) 20時8分 ]
> 興味深い高度な話だと思います。
> 
> 再帰呼び出しの手法は意図的に使用されているのであれば無限再帰(スタック・オーバーフロー)

> ならない限り、問題はありません。
> 再帰呼び出しもテクニックとして利用することもありますので。
> 
> さてプロシージャー内に定義したSQLカーソルは、一見するとローカル変数として
> 定義されているので、再帰呼び出しでもそれぞれ独立してプロシージャー内で
> 定義されているはず、というのも妥当な推論です。
> 
> ところで SQLカーソルは変数なのでしょうか ?
> SQLのコンパイル・リストおよび QTEMP/QSQLTEMP のRPGソースを調べてみてください。
> SQLのコンパイルはコンパイラーによって QTEMP/QSQLTEMP に展開されてから
> これを最終的にコンパイルする仕組みをとっています。
> 
> 展開されたコンパイル・リストまたは QTEMP/QSQLTEMP を精査してみると
> 定義したはずの SQLカーソルは、どこにも見当たりません。
> ( SQL カーソルはコメント・アウトされています。)
> SQL カーソルは式として展開されていますがローカル変数として
> 保護する仕組みもないようです。
> 
> つまり SQLカーソルとは概念であって変数ではないのです。
> 従ってローカル変数として他から保護されているものではありません。
> グローバル変数として理解するしかありません。
> 
> 結論として SQLカーソルはローカル変数とはなりません。
> 
> -- SQLバインドは OPM のときに開発された手法ですので ILE化によって SQL展開を変更
する
>   のは従来のソフトウェア資産と矛盾することになると IBM は考えたのでしょう。
>   System i は、そうそう通常の使用では不具合はありません。
>    元々これは変数ではないので不具合ではありません。
>   簡単にバグだと決めつける記事のほうが論拠に欠けるものです。
> 

すみません。回答をいただいている事を今まで気づいていませんでした。

SQLカーソルは変数ではないということなんですね。

お客様の仕様としてはスタックがオーバーフローするような無限階層の呼び出しではなく、
呼び出し階層の最大値を限定することがOKでしたので、最大の階層分のカーソルを定義して
階層に応じたカーソルを使用するようなプログラムに変更したところ、
それはそれで正しく動作したのですが、やはりイマイチです。

結局、SQLで読むことをやめて、
各階層で下位呼び出しの直前に現在の読み込み位置を保存しておき、
下位層からリターンしたときに次の読み込み開始位置を再度設定する、
ということにしました。

実質的には変わりない内容ですが、ソースコードが短くなるのでこちらを採用しました。

ご回答ありがとうございました。

お名前

パスワード

メールアドレス

タイトル

ホームページ

アドレス

項目