PL/SQL IF, ELSIF, ELSE, END IFの対応表No.24812
Papageno さん 08/04/21 01:50
 
今月からインドで作られたパッケージの日本の環境へのローカライズ
を手伝っています。

PL/SQLのストアド・プログラムだけで4,000本以上あります。
ざっと見たプログラムのうち5本に1本がいっさいインデントして
ありません。とてもプログラムを追いかける気にはなれません。
秀丸エディタにはカッコの位置にカーソルがあるとペアになって
いるカッコを強調表示してカッコの入れ子の追跡を手助けして
くれる機能がありますが、
PL/SQLのIF, ELSIF, ELSE, END IFの対応についても強調表示
してIFの入れ子の追跡を手助けしてくれる機能を提供していただけ
ないでしょうか?

たまたまチェックしたプログラムで
IF VARCHAR2(1)型の変数 = 'SA' THEN ...
などと絶対に真にならない条件で書いてあったりで、プログラムの
品質が悪く、とても6月の本番リリースは無理なんですが。

[ ]
RE:24812 PL/SQL IF, ELSIF, ELSE, END IFNo.24813
秀丸担当 さん 08/04/21 11:00
 

>PL/SQLのIF, ELSIF, ELSE, END IFの対応についても強調表示
>してIFの入れ子の追跡を手助けしてくれる機能を提供していただけ
>ないでしょうか?

そのような機能があったら便利かもしれないです。
ご意見として参考にさせていただきます。

現状でやるには、対応するIF、END IF等に移動するようなマクロを作ることがで
きれば、それなりに助けになるかもしれなですが、作るとしたら少々難しいマク
ロになるかもしれません。

マクロライブラリに、マクロ作者様によるマクロがいろいろ登録されているので、
探してみるといいものが見つかるかもしれません。

 秀丸エディタのマクロライブラリ
 http://hide.maruo.co.jp/lib/macro/index.html

PL/SQLの文法に合うものがあるかどうかは、ちょっとわからないです。

[ ]
RE:24813 PL/SQL IF, ELSIF, ELSE, END IFNo.24823
Papageno さん 08/04/22 18:34
 
>そのような機能があったら便利かもしれないです。
>ご意見として参考にさせていただきます。

秀丸エディタに実装するのもかなりの時間がかかりそうです
から気長に待っています。

>現状でやるには、対応するIF、END IF等に移動するようなマクロを作ることがで
>きれば、それなりに助けになるかもしれなですが、作るとしたら少々難しいマク
>ロになるかもしれません。

とりあえず、
http://hide.maruo.co.jp/lib/macro/sqlfmt_mac.html
SQLとPL/SQLを整形するマクロ
をつかってみましたが、だめでした。

[ ]
RE:24823 PL/SQL IF, ELSIF, ELSE, END IFNo.24824
秀丸担当 さん 08/04/23 12:47
 

>秀丸エディタに実装するのもかなりの時間がかかりそうです
>から気長に待っています。

秀丸エディタで標準でやろうとすると、いろいろな言語や文法を正しく解釈する
ことを考えなければいけなさそうなので、ちょっと難しいかもしれません。

文法とかあまり考えずに適当にマクロを作ってみましたが、参考にしてみてくだ
さい。
IFのある場所で実行します。
V7.00以降でのみ使えます。
マクロ登録で、自動起動マクロのカーソル移動後タイマーに登録してもいいかも
しれません。

if(selecting)endmacro;
if(code!='I'&&code!='F'&&code!='i'&&code!='f') endmacro;
disabledraw;
#yTop=screentopy;
#xOrg=x;
#yOrg=y;
gowordtop;
#x1=x; #y1=y;
wordrightsalnen;
#x2=x; #y2=y;
$word=toupper(gettext(#x1,#y1,#x2,#y2));
if($word=="IF"){
  wordleft;
  $wordleft=toupper(gettext(x,y,#x1,#y1));
  if($wordleft=="ELS")goto Exit;
  wordleft;
  $wordleft=toupper(gettext(x,y,#x1,#y1));
  if($wordleft=="END ")goto Exit;
  selectall;
  colormarker;
  escape;
  #cNest = 1;
  call ColorMark #x1,#y1,#x2,#y2;
  while(1){
    searchdown "IF|ELSIF|ELSE|END IF",
      regular, word, nocasesense;
    if( !result ) break;
    #x1=foundtopx; #y1=foundtopy;
    #x2=foundendx; #y2=foundendy;
    $found=toupper(gettext(#x1,#y1,#x2,#y2));
    if($found=="IF") {
      #cNest = #cNest + 1;
    } else if($found=="ELSIF"||$found=="ELSE") {
      if(#cNest==1){
        call ColorMark #x1,#y1,#x2,#y2;
      }
    } else if($found=="END IF") {
      #cNest = #cNest - 1;
      if(#cNest==0){
        call ColorMark #x1,#y1,#x2,#y2;
        break;
      }
    }
    moveto #x2, #y2;
  }
}
Exit:
moveto #xOrg,#yOrg;
enabledraw #yTop;
endmacro;

ColorMark:
moveto ##1,##2;
beginsel;
moveto ##3,##4;
colormarker -1, 0x0000ff,11,2;
escape;
return;

[ ]
RE:24824 PL/SQL IF, ELSIF, ELSE, END IFNo.24825
秀丸担当 さん 08/04/23 13:03
 

このままでは検索文字列と検索オプションが変わったままになってしまうので、

最初のdisabledrawの前に、

$s=searchbuffer;
#s=searchoption;
disabledraw;

最後付近のenabledrawの後に、

enabledraw #yTop;
setsearch $s, #s;

というふうにしたほうがよかったです。

[ ]
RE:24825 PL/SQL IF, ELSIF, ELSE, END IFNo.24826
Papageno さん 08/04/23 15:05
 
簡単なPL/SQLでチェックしただけですが、
IF の位置にカーソルを持っていき、マクロを起動すると
IF, ELSIF, ELSE, END IFの背景が赤く変わります。

これだけでも十分助かります。
ありがとうございます。

[ ]
RE:24826 PL/SQL IF, ELSIF, ELSE, END IFNo.24871
Papageno さん 08/05/06 15:10
 
http://hide.maruo.co.jp/lib/macro/sqlfmt_mac.html
かなり整形できますが、整形に失敗すると

文の整形に失敗しました。(戻り値=24)
[OK]

その後コピペすると、

クリップ・ボードのオープンに失敗しました。
[再試行(R)][キャンセル]

整形したファイル以外でも同じエラーになるので、
秀丸を全終了、常駐も終了してから秀丸を再起動する
必要があります。


[ ]
RE:24871 PL/SQL IF, ELSIF, ELSE, END IFNo.24880
秀丸担当 さん 08/05/07 10:57
 

>http://hide.maruo.co.jp/lib/macro/sqlfmt_mac.html
>かなり整形できますが、整形に失敗すると
>
>文の整形に失敗しました。(戻り値=24)
>[OK]
>
>その後コピペすると、

試しにやってみようとしましたが、うまくできませんでした。
どういうときにこのエラーが出るのでしょうか。
if
if
と書いた二行でやってみたら異常終了してしまいました。異常終了してしまうの
で、sqlfmt.dllの中のようです。

おそらく、sqlfmt.dllの中でクリップボードを開いたままにしているのではない
かと推測します。
プラムシックスさんのほうに問い合わせてみたほうがいいかもしれません。

[ ]
RE:24880 PL/SQL IF, ELSIF, ELSE, END IFNo.24890
Papageno さん 08/05/08 18:18
 
>どういうときにこのエラーが出るのでしょうか。

整形のため
declare, begin, exception, end
if, elsif, else, end if
loop, end loop
など一連の対になっているキーワードでネストされているもの
を含めて解析してインデントしているはずですので、
かなり高度な検索をしているはずです。

何かの拍子に解析がうまくできずにエラーになるようです。

>プラムシックスさんのほうに問い合わせてみたほうがいいかもしれません。

Mailしましたが、1週間経っても返事がありません。
フリーソフトですから、サポートを期待するのは無理かもしれません。

[ ]
RE:24890 PL/SQL IF, ELSIF, ELSE, END IFNo.24894
秀丸担当 さん 08/05/09 09:54
 

>整形のため
>declare, begin, exception, end
>if, elsif, else, end if
>loop, end loop
>など一連の対になっているキーワードでネストされているもの
>を含めて解析してインデントしているはずですので、
>かなり高度な検索をしているはずです。

もし必ず問題が起きるような具体的なサンプルがあれば、教えていただけるとこ
ちらでも再現させることができるかもしれないです。
再現できたとしても、sqlfmt.dllの中での問題は分からないかもしれないですが。

[ ]
RE:24894 PL/SQL IF, ELSIF, ELSE, END IFNo.24896
Papageno さん 08/05/09 10:54
 
>もし必ず問題が起きるような具体的なサンプルがあれば、教えていただけるとこ
>ちらでも再現させることができるかもしれないです。

個人的には整形が必要なむごいプログラムは作りません。
派遣先のプログラムなので、サンプルにしても持ち出しは
難しいです。
不便な世の中になりました。

[ ]
RE:24896 PL/SQL IF, ELSIF, ELSE, END IFNo.25004
Papageno さん 08/06/05 14:31
 
CREATE OR REPLACE PACKAGE "PACKAGE_NAME1"
IS
...

とPACKAGE_NAME1がダブルクォーティングされると上記エラーに
なるようです。

DBMS_METADATAでDDLを取得すると
CREATE OR REPLACE PACKAGE "USERNAME1"."PACKAGE_NAME1"
...
って取得できるので、ダブルクォーティングされた程度で
エラーになってほしくないです。

http://www.shift-the-oracle.com/plsql/dbms_metadata/

[ ]
RE:25004 PL/SQL IF, ELSIF, ELSE, END IFNo.25006
秀丸担当 さん 08/06/05 15:18
 

>CREATE OR REPLACE PACKAGE "PACKAGE_NAME1"
>IS
>...
>
>とPACKAGE_NAME1がダブルクォーティングされると上記エラーに
>なるようです。

この二行を選択してやってみたところ、再現させることができました。
sqlfmt.dllは、文字列のやりとりにクリップボードを使用しているようですが、
エラーメッセージが出たとき、クリップボードを開いたままに終わってしまって
いるようです。

秀丸エディタでクリップボードを開くのに失敗したときは、「クリップボードの
オープンに失敗しました」というメッセージが出ますが、再試行するときに、本
体側でクリップボードを閉じてから再試行するように修正してみようと思います。
V7.09β6で修正します。
これでとりあえずエラーが出た後の修復はできるようになると思います。


>DBMS_METADATAでDDLを取得すると
>CREATE OR REPLACE PACKAGE "USERNAME1"."PACKAGE_NAME1"
>...
>って取得できるので、ダブルクォーティングされた程度で
>エラーになってほしくないです。

そもそもエラーになるのは、こちらではわかりませんので、プラムシックスさん
のほうにお願いするしかありません。
一応こちらからもメールしておこうと思います。

[ ]
RE:25004 PL/SQL IF, ELSIF, ELSE, END IFNo.25015
GAMACHAN さん 08/06/07 09:00
 
Papageno 様
秀丸担当様

いつもお世話になっております。GAMACHAN@プラムシックスです。
このたびは SqlFmt に関しまして貴重なご意見を頂戴いたしまして
誠に有難うございました。また、このスレッドに気付かず適切な
時期にコメントを差し上げられなかったことを申し訳なく思います。

弊社でもご指摘どおりの不具合が製品に含まれている事実を認識しており、
今後リリースされる版で改善するよう検討いたしております。

リリースまでの間、ご不便をお掛けいたしますが何卒ご容赦下さいますよう
お願い申し上げます。

[ ]
RE:25004 PL/SQL IF, ELSIF, ELSE, END IFNo.25016
GAMACHAN さん 08/06/07 10:13
 
Papageno 様

いつもお世話になっております。GAMACHAN@プラムシックスです。
戻り値=24
は、下記のような開始と終了のシンボルの対を形成している式または文に
おいて、終了のシンボルが整形対象範囲内に見つからなかった場合に
報告される戻り値となっております。

    開き丸括弧 引数リスト 閉じ丸括弧
    BEGIN ... EXCEPTION WHEN TEHN ... END;
    DECLARE ... BEGIN ... EXCEPTION WHEN TEHN ... END;
    IF THEN ... ELSIF THEN ... ELSE ... END IF;
    LOOP ... END LOOP;

上記のケース以外でも、CASE 式が含まれる SQL 文において正当な
式であるにも係らず解析が不十分なため、戻り値=24でクラッシュする
事例を確認しております。

整形を試みられたPL/SQLがこのような事例に当たっているかどうか
ご確認いただくことは可能でしょうか。

なおご確認に当たりましては秀丸エディタのマクロとして実行せず
整形対象をクリップボードへコピーした状態でコマンドプロンプトから
sqlfmt.exe を実行する方法をお試し頂けないでしょうか。
(sqlfmt.exe は sqlfmt.dll の含まれるディレクトリにございます)

こちらの場合ですと秀丸エディタとは別なプロセスとして動作しますので
仮にクラッシュいたしましてもプロセスの終了過程でクリップボードが
閉じられ、秀丸エディタに影響を与えることはございません。

[ ]
RE:25006 PL/SQL IF, ELSIF, ELSE, END IFNo.25032
Papageno さん 08/06/12 18:49
 
>V7.09β6で修正します。
>これでとりあえずエラーが出た後の修復はできるようになると思います。

ありがとうございます。
V7.09β6のアップを待っています。

[ ]
RE:25016 PL/SQL IF, ELSIF, ELSE, END IFNo.25033
Papageno さん 08/06/12 19:12
 
>整形を試みられたPL/SQLがこのような事例に当たっているかどうか
>ご確認いただくことは可能でしょうか。

偶然見つけたJavaを呼んでいるPACKAGEで

CREATE OR REPLACE PACKAGE BODY PACKAGE_NAME1 IS
    FUNCTION FUNCTION_NAME1
        (
        IN_STRING IN VARCHAR2
      , IN_KEY    IN VARCHAR2
        )
    RETURN VARCHAR2 AS
    Language Java Name '..... java.lang.String';

    FUNCTION FUNCTION_NAME1
        (
        IN_STRING IN VARCHAR2
        )
        RETURN VARCHAR2
    AS
    ...
と最初のFUNCTION_NAME1の
END;
の記述のないものがありました。


>なおご確認に当たりましては秀丸エディタのマクロとして実行せず
>整形対象をクリップボードへコピーした状態でコマンドプロンプトから
>sqlfmt.exe を実行する方法をお試し頂けないでしょうか。

sqlfmt.dll, sqlfmt.mac が置いてある
C:\Program Files\Hidemaru\Mac
へsqlfmt.exeを置き、クリップボードへコピーした状態で
コマンドプロンプトからsqlfmt.exeを実行した結果です。

C:\Program Files\Hidemaru\Mac>sqlfmt.exe
SqlFmt version 1.12
Copyright (c) 2003 - 2008 Plumsix Co.,Ltd. All rights reserved.
Error - 対応する閉じ括弧がありません。iIdt = 2, iOrgIdt = 0
関数 rcFmtStmt() が異常終了しました。(rcFmtStmt.c-1472)
ssSrc の前方 128 バイトから後方 0 バイトまでをダンプします。
前方 128 バイト:
;EXCEPTION WHEN OTHERS THEN RAISE_APPLICATION_ERROR(-20004, 'There was probl
em while doing
 decryption', TRUE);END;END pkg_ede;/

後方 0 バイト:

関数 rcFmtOnClipBoard() が異常終了しました。(rcFmtOnClipBoard.c-84)
異常終了しました。(sqlfmt.c-190)

わたしが調べることができえるパッケージの一部だけで
テーブルが3,500以上、ストアド・プログラムが5,000以上あるので、
テーブル名でgrepしたときテーブル名といっしょに
INSERT|DELETE|MERGE|SELECT|FROM|UPDATEができるだけ同じ行に
あったほうがとっても助かります。

sqlfmtでの整形時の編集ですが
DELETE
FROM TABLE_NAME1
とDELETEで改行されます。

INSERT
INTO TABLE_NAME1
とINSERTで改行されます。

このDELETEやINSERTの次の改行を止めていただけるでしょうか。

[ ]