S2DaoにおけるIFコメント、BEGINコメントの挙動
s2daoの「AND」文字列を消すタイミングというか消す条件がわからない。
なんとなくわかった。(2009-02-02の追記参照)
SELECT ・・・ TABLE3 T3 WHERE ・・・ /*BEGIN*/----行(1) /*IF dto.xxx1=="1"*/ T3.XXX='1' /*END*/ /*IF dto.xxx1=="1"*/ or T3.XXX='2' /*END*/ not exists ( select * from VIEW1 V1 inner join VIEW2 V2 on V1.XX_SEQ = V2.XX_SEQ where V1.XX_CD ='9999' AND V1.XX_SEQ = T3.XX_SEQ /*BEGIN*/----行A AND /*IF dto.xxCode !=null*/ AND V1.XXNO = /*dto.xxCode*/'10000' /*END*/ /*IF dto.xxDate1 != '' || dto.xxDate2 != ''*/ AND to_char(V2.HOGE_DATE,'YYYY/MM/DD') /*IF dto.xxDate1 != '' && dto.xxDate2 != '' */between /*dto.xxDate1*/'1999/01/01' and /*dto.xxDate2*/'2009/01/30' -- ELSE /*IF dto.xxDate1 == '' && dto.xxDate2 !='' */ <=/*dto.xxDate2*/'2009/01/30' /*END*/ /*IF dto.xxDate1 != '' && dto.xxDate2 =='' */ >=/*dto.xxDate1*/'1999/01/0' /*END*/ /*END*/ /*END*/ /*END*/----行B ) /*END*/----行(2)
上記だと、問題なく実行できるけど
行A、行Bの
/*BEGIN*/ /*END*/
を付与しないで、以下のように記述すると
(略) where V1.XX_CD ='9999' AND V1.XX_SEQ = T3.XX_SEQ /*IF dto.xxCode !=null*/ AND V1.XXNO = /*dto.xxCode*/'10000' ----行C /*END*/ /*IF dto.xxDate1 != '' || dto.xxDate2 != ''*/ AND to_char(V2.HOGE_DATE,'YYYY/MM/DD') ----行D /*IF dto.xxDate1 != '' && dto.xxDate2 != '' */between /*dto.xxDate1*/'1999/01/01' and /*dto.xxDate2*/'2009/01/30' -- ELSE /*IF dto.xxDate1 == '' && dto.xxDate2 !='' */ <=/*dto.xxDate2*/'2009/01/30' /*END*/ /*IF dto.xxDate1 != '' && dto.xxDate2 =='' */ >=/*dto.xxDate1*/'1999/01/0' /*END*/ /*END*/ /*END*/ )
行Cの最初の「AND」もしくは、行Dの最初の「AND」が削除されてしまう
/*IF〜*/ /*END*/ がひとつ1もtrueを返さない場合は、ANDを削除している模様。
(略) where /*IF "A"=="A"*/ V1.XX_CD ='9999' /*END* AND V1.XX_SEQ = T3.XX_SEQ /*IF dto.xxCode !=null*/ AND V1.XXNO = /*dto.xxCode*/'10000' ----行C /*END*/ /*IF dto.xxDate1 != '' || dto.xxDate2 != ''*/ AND to_char(V2.HOGE_DATE,'YYYY/MM/DD') ----行D /*IF dto.xxDate1 != '' && dto.xxDate2 != '' */between /*dto.xxDate1*/'1999/01/01' and /*dto.xxDate2*/'2009/01/30' -- ELSE /*IF dto.xxDate1 == '' && dto.xxDate2 !='' */ <=/*dto.xxDate2*/'2009/01/30' /*END*/ /*IF dto.xxDate1 != '' && dto.xxDate2 =='' */ >=/*dto.xxDate1*/'1999/01/0' /*END*/ /*END*/ /*END*/
と記述すると、行C、Dともに ANDが付与されたままのSQLで実行できる。
どう回避すべきなんだろ。 /*IF "A"=="A"*/〜/*END*/で 回避するのがわかりやすいのか・・・
2009-01-31 AM1:50追記
行(1)の /*BEGIN*/ 〜 /*END*/
で 不要な OR が存在する場合(WHERE or A=1のように、orが入りSQLが
成立しなくなるの)を回避する際のときの動作の影響を受けるみたいだ。
ネストしすぎてるから、判断できないのか。。。
2009-02-02 12:50追記
ちょっと再考してみた。
BEGIN〜END と ELSE
コメントの勘違いから始まった。
/*BEGIN*/ [あああ(ANDとかもあり)] SQL文1 /*IF 条件2 */ SQL文2 /*END*/ /*IF 条件3 */ SQL文3 /*END*/ /*END*/
とあるとき、条件2、条件3ともにみたさない(trueでない)ときに
[あああ]、SQL文1、SQL文2、SQL文3 すべて解釈されなくなる。
BEGIN〜ENDは、
ELSE コメントを含まない複数の条件コメントにおいて
すべての条件をみたさない場合に
BEGIN〜ENDの中にあるSQLを解釈しないようにする機能
別の表現だと
WHERE句とか関係なく、BEGIN〜END内にあるものがSQLを解釈するか
しないかの対象となり、IFが1つでも成立していればBEGIN〜END内は
解釈される。
よって、ELSEがあるのに関わらず ELSEでSQL文が出力されない
のがよくない。
ELSEは、IF〜ENDがみたさない場合に、
必ずELSE内のSQLがみたされるようにしておくべきなんだろう
で、SQLがよくない。というか書き方がよくない
to_charを複数回記述したくない&&Betweenで見た目をわかりやすく
と思って、ELSEを入れたけど
where V1.XX_CD ='9999' AND V1.XX_SEQ = T3.XX_SEQ /*BEGIN*/----行A AND /*IF dto.xxCode !=null*/ AND V1.XXNO = /*dto.xxCode*/'10000' /*END*/ /*IF dto.xxDate1 == '' && dto.xxDate2 !='' */ AND to_char(V2.HOGE_DATE,'YYYY/MM/DD') <=/*dto.xxDate2*/'2009/01/30' /*END*/ /*IF dto.xxDate1 != '' && dto.xxDate2 =='' */ AND to_char(V2.HOGE_DATE,'YYYY/MM/DD') >=/*dto.xxDate1*/'1999/01/0' /*END*/ /*END*/ /*END*/----行B
となるように、すべきか。
なので、行A、BのBEGIN〜END は、あってよい。行Aの後のANDも必要ってこと。
ELSEがあるのに、ELSE内でSQLが置き換わらない(出力されない、SQLが成立していない)ような
書き方をしたことが間違いだった。