「表示用SQL」の日付フォーマントについて

478 views
Skip to first unread message

awaawa

unread,
Oct 26, 2009, 3:10:53 PM10/26/09
to DBFluteユーザの集い
awaawaです。

jfluteさん
たびたびの要望で申し訳ないのですが、以下ご確認いただけないでしょうか。

1.「表示用SQL」の日付フォーマット指定
  「表示用SQL」の日付フォーマットを明示的かつ詳細に指定することで、
  timestampが条件に入っている「表示用SQL」でもオブジェクトブラウザ等で意識せず実行したいと思っています。
  もし可能であれば対応いただけないでしょうか。

  ・関連ドキュメント
   http://dbflute.sandbox.seasar.org/contents/setup/logging.html
   「表示用SQL」に関して補足

  現状でも、フォーマットの指定をDBFluteConfig.setLogXxxFormat()でできると思いますが、
  Oracleの場合、以下のフォーマットにしたいので拡張していただけるとうれしいです。
  (もしくはほかに方法ありますでしょうか。)
  「XXX_DATETIME = TO_TIMESTAMP('2009-01-01 12:34:56.000000', 'YYYY-MM-
DD HH24:MI:SS.ssssss')」
   or
  「XXX_DATETIME = timestamp '2009-01-01 12:34:56.000000'」

・リファクタリング(?)
 上記の表示用SQLのロジックを追っている際に気づいたのですが、
 AbstractConditionBeanに宣言されているgetLogXxxFormat()は不要な気がしました。
 XxxCBでオーバーライドしても「表示用SQL」には反映されなかったからです。
 ただし明示的にXxxCB.toDisplaySql()をコールした場合は反映されました。
 おそらくこれは意図した動きではないと思うのですがどうでしょうか。

以上、ご確認よろしくお願いします。

jflute

unread,
Oct 27, 2009, 12:51:53 AM10/27/09
to DBFluteユーザの集い
jfluteです。

日付の四つのマントの話ですが、
DBFluteConfigでも実現出来るけど、
Oracleだったらデフォルトで、
「timestamp '2009-01-01 12:34:56.000000'」
とかやっちゃった方が良いんじゃないの!?
って話でOKでしょうか?

あと、AbstractConditionBeanのgetLogXxxFormat()は
もともとtoDisplaySql()用のものですね。
ちなみに実行時はcb.toDisplaySql()が呼ばれているわけではないです。
(名前をxgetLogXxxFormat()とかにしちゃった方がよかったかな!?)

jflute

unread,
Oct 27, 2009, 2:34:12 AM10/27/09
to DBFluteユーザの集い
jfluteです。

わかった。
今のDBFluteConfigのsetLogDateFormat()だと、
本当にフォーマットだけしか操作できないので
実現できないですね。どうちらかというと、
フォーマットした後の文字列を豪快にフィルタする
拡張ができた方が良いって感じですかね。

jflute

unread,
Oct 27, 2009, 3:47:08 AM10/27/09
to DBFluteユーザの集い
jfluteです。

DBFluteConfig.getInstance().unlock();
String dateFormat = "date $df:{yyyy-MM-dd}";
DBFluteConfig.getInstance().setLogDateFormat(dateFormat);
String timestampFormat = "timestamp $df:{yyyy-MM-dd HH:mm:ss}";
DBFluteConfig.getInstance().setLogTimestampFormat(timestampFormat);

とやると、実現できるようにしました。
SimpleDateFormatに与えるフォーマット文字列を
「$df:{」と「}」で囲むとその周りの文字列は、
quoteした後にドッキングします。
「$df:{」と「}」が存在しなければ今まで通りです。

DBFluteモジュール:DBFlute-0.9.6-SNAPSHOT
DBFluteランタイム:DBFlute-0.9.6-10-SNAPSHOT

で、反映されています。

Oracleの場合はデフォルトで
「timestamp $df:{yyyy-MM-dd HH:mm:ss}」
にしちゃっても良いのかなぁ...

jflute

unread,
Oct 27, 2009, 12:36:18 PM10/27/09
to DBFluteユーザの集い
jfluteです。

影響範囲がとても軽い修正で、
まだRC1のダウンロードが極小(涙)なので、
RC1に上書きしました。
(Maven経由でDBFluteランタイムを利用している場合は、
お手数ですがローカルのMavenリポジトリから古いのを
一旦削除して下さい)

awaawa

unread,
Oct 27, 2009, 1:22:46 PM10/27/09
to DBFluteユーザの集い
awaawaです。

jfluteさん
SQLログ出力と、toDisplaySql()のロジックは厳密には別物なんですね。
アプリでSQLを取得して何かする時に、toDisplaySql()を利用って考えていいでしょうか。
(SqlRegistryに近いイメージ)

> フォーマットした後の文字列を豪快にフィルタする拡張ができた方が良いって感じですかね
言葉足らずですいません。ずばりそのとおりです。
対応していただいた内容確認しました。
これで、timestampがあってもログコピペ→オブジェクトブラウザ実行ができるようになりました!!
ありがとうございます。

> Oracleの場合はデフォルトで
> 「timestamp $df:{yyyy-MM-dd HH:mm:ss}」
> にしちゃっても良いのかなぁ...
ほかのRDBはわかりませんが、oracleは常にエラーになるので、
対応していただけるとありがたいです。

もちろん、対応の有無にかかわらず、ドキュメントの注意書きのとおり、
「実際に発行したSQLと表示用SQLの日付のフォーマットは無関係であることを認識しておいて下さい。」
の前提は忘れないようにしないとですね。

jflute

unread,
Oct 29, 2009, 2:48:49 AM10/29/09
to DBFluteユーザの集い
jfluteです。

DBFluteモジュール:最新の0.9.6-SNAPSHOT
DBFluteランタイム:0.9.6-15-SNAPSHOT

で、Oracleの日付フォーマットのデフォルトで、
Oracle独特の日付リテラルが付与されるようにしました。
DBFluteConfigの設定を外しても大丈夫なはずです。
(他のDBでは、なにも指定しなくてもパースしてくれました)
あと関連した細かい修正で、ミリ秒も表示するようにしました。

#
# しかし、Oracleで2Way-SQLを実現しようとすると、
# /*pmb.date*/date'2008-12-12'
# というように空白を空けないようにテスト値を
# 指定しないといけないんですねぇ...
# もしくは割り切ってsysdateにしちゃうか。
# /*pmb.date*/sysdate
#

jflute

unread,
Oct 29, 2009, 8:14:05 AM10/29/09
to DBFluteユーザの集い
jfluteです。

http://d.hatena.ne.jp/jflute/20091026/1256569726

DBFluteモジュール:0.9.6-RC2
DBFluteランタイム:0.9.6-RC2

にて、

/*pmb.date*/date '2008-12-12'
/*pmb.timestamp*/timestamp '2008-12-12 12:34:56.147'

というように空白を一個空けて記述しても、
テスト値として認識するようにしました。
テスト値上のdateもしくはtimestampの後の
シングルクォーテーションで囲まれた
日付フォーマットだけ特別な処理しています。
Oracleで日付型のテスト値はこれで決まり!
(もちろん別にsysdateでも良いけどね)

awaawa

unread,
Oct 29, 2009, 1:17:47 PM10/29/09
to DBFluteユーザの集い
awaawaです。

一気に日付型の問題がスッキリですね~さすがです!!

> 「表示用SQL」の日付フォーマントについて
> 日付の四つのマントの話ですが、
今気づきましたが、自分タイトル間違ってましたね(笑)
いまさらって感じですが・・・

jflute

unread,
Oct 30, 2009, 3:21:08 AM10/30/09
to DBFluteユーザの集い
jfluteです。

> 今気づきましたが、自分タイトル間違ってましたね(笑)
> いまさらって感じですが・・・
基本的に自分はボケ続けます。

あと、ひとつ悩むのが、
Oracleは時分秒を持たない日付型ってないので、
java.util.Dateのデフォルトのマントのための日付を
「yyyy-MM-dd」じゃなく「yyyy-MM-dd HH:mm:ss」
にした方がいいのかなって。。。

jflute

unread,
Oct 30, 2009, 8:44:59 AM10/30/09
to DBFluteユーザの集い
jfluteです。

> java.util.Dateのデフォルトのマントのための日付を
> 「yyyy-MM-dd」じゃなく「yyyy-MM-dd HH:mm:ss」
> にした方がいいのかなって。。。

結局、java.util.Dateのフォーマットを
「date yyyy-MM-dd」じゃなくて
「timestamp yyyy-MM-dd HH:mm:ss」にしました。
ここまで来たら、そのDBに対しての最適化ってことで。

よし

unread,
Mar 31, 2016, 10:26:50 PM3/31/16
to DBFluteユーザの集い
よしと申します。

 OracleのDATE型へ条件を設定したSQLの処理が遅く、調べていてこのスレッドを見つけました。

 外出しSQLでDate型のパラメータを設定した場合以下の様なWhere句になるかと思いますが、
この形ですとDT_HOGEに設定されているインデックスが使用されず、フル検索になってしまっています。

  DT_HOGE >= timestamp '2016-04-01 00:00:00'

 これを以下のようしてみると、インデックスが使用されます。

  DT_HOGE >= date '2016-04-01'

 実行計画を見るとtimestampの場合は以下
    INTERNAL_FUNCTION(DT_HOGE)>=TIMESTAMP' 2016-04-01 00:00:00.000000000' 
 Dateの場合は以下
    DT_HOGE>=TO_DATE(' 2016-04-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') 

 となっており、timestampの場合は項目に内部的に関数が使われているようで、その為インデックスが使用されていないようです。

 ご確認いただけますでしょうか?

 オラクルのバーションは11gR2
 Dbfluteのバーションは1.0.5N

 です。

kubo

unread,
Mar 31, 2016, 11:17:47 PM3/31/16
to DBFluteユーザの集い
jfluteです

よしさん、こんにちは

取り急ぎで申し訳ないですが、こちら参考にしてみてください。
http://dbflute.seasar.org/ja/manual/reference/dbway/oracle/#oracledate



※外だしSQLだと逆にうまくいかないとかあるかも...

よし

unread,
Apr 1, 2016, 12:46:26 AM4/1/16
to DBFluteユーザの集い
よしです。

jfluteさん、ありがとうございます。

ただ、試してみましたが、変化がありませんでした。
※DT_HOGE >= timestamp '2016-04-01 00:00:00'のまま、検索も遅い状態

試した内容
 littleAdjustmentMap.dfprop に 以下を設定

     ; isAvailableDatabaseNativeJDBC = ture

 manage.batで

 2:regenerateを実行

 以上です。
 
すみません、よろしくお願いします。

kubo

unread,
Apr 1, 2016, 12:59:23 AM4/1/16
to DBFluteユーザの集い
jfluteです

> ただ、試してみましたが、変化がありませんでした。

ふむぅ、そうですか…
試しに、シンプルな検索でいいので、
isAvailableDatabaseNativeJDBCを使った状態で、
ConditionBeanで検索してみて頂けないでしょうか?
oracle.sql.DATEさえ利用されれば速いのか、違う問題なのか、
の切り分けのために。

ちなみに、isAvailableDatabaseNativeJDBCでregenerateすると、
DBFluteConfigで ImplementedOracleDateType が設定されているはずです。

https://github.com/dbflute-test/dbflute-test-dbms-oracle/blob/master/src/main/java/org/docksidestage/oracle/dbflute/allcommon/DBFluteConfig.java#L132

> 外出しSQLでDate型のパラメータを設定した場合

いまって、ParameterBeanのプロパティ型が java.util.Date になっていて、
DT_HOGE > /*pmb.dtHoge*/...
っていう状態でしょうか?
その場合、isAvailableDatabaseNativeJDBC=trueなら
内部的にはoracle.sql.DATEに変換されると思うんですけどね…
(そこまでいくと、CBと外だしSQLで差がないので)

もし、oracle.sql.DATEを使えば解決する問題であれば、
外だしSQLのParameterBeanのプロパティ型を oracle.sql.DATE に
すれば速くなるかもしれないかなぁとも。
(ちょっと、やったことないですけど...)

しゃってん

unread,
Apr 1, 2016, 1:51:36 AM4/1/16
to DBFluteユーザの集い
しゃってんです。


表示用のSQLとConditionBeanで発行されるSQLで若干差があるかと思いますが・・・?

OracleのDateの場合、JDBC経由でSQLを発行する際にバインドパラメータの型にOracleDateを利用することでインデックスが利用されます。
表示用SQLはログをそのまま張り付けて実行できる形式で出力されているため、インデックスが利用されていないだけかもしれません。

※Oracleの日付型の最適化を設定することで内部的にDate型の値をバインドパラメータに設定するときにOracleDateが利用される仕組みがあるはずです。
 java.sql.Dateだと時刻部分が削除され、インデックスは効かなかった気がしました。

以前同じような問題があったときは、FromToOptionクラスを利用する場所でOracleDateを返却する独自のクラスを作成して対応していました。
現在はその仕組みを取り込んで isAvailableDatabaseNativeJDBC=true に追加されている認識です。

2016年4月1日金曜日 13時59分23秒 UTC+9 jflute:

よし

unread,
Apr 1, 2016, 2:13:34 AM4/1/16
to DBFluteユーザの集い
よしです。

jfluteさん、ごめんなさい。

 littleAdjustmentMap.dfprop の 設定を間違っていました。

    誤) ; isAvailableDatabaseNativeJDBC = ture

    正) ; isAvailableDatabaseNativeJDBC = true
 
正しく、設定しなおしてregenerateしたら、検索が早くなりました。

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

ちなみに、ログで出力される内容は以下のまま変わらないで正しいんですよね?

kubo

unread,
Apr 1, 2016, 2:28:04 AM4/1/16
to DBFluteユーザの集い
jfluteです

おおぉぉ、速くなってよかったです。
本当は、ツールなりでエラーになる方がいいですね…。

> ちなみに、ログで出力される内容は以下のまま変わらないで正しいんですよね?
これはその通りです。
あくまで表示用SQLで、かつ、
できるだけそのまま実行できる状態を作っているだけなので



しゃってんさん、詳しいフォローありがとう。

よし

unread,
Apr 3, 2016, 10:52:36 PM4/3/16
to DBFluteユーザの集い
よしです。

 jfluteさん、しゃってんさん

 フォローありがとうございました。

 Oracleで時刻情報も必要な場合は、Timestamp型を使用したほうが、無難ですね。

 今後の開発ではTimestamp型の使用を検討しようと思います。

Reply all
Reply to author
Forward
0 new messages