以前、
「データベースをOracleからPostgresに変更するにあたっての対応方法」
について、質問させていただ、杉本です。
長文になります、すみません。
利用しているDataBase:Postgres 9.2
利用しているDBFlute:0.9.6.9
Postgresのテーブルのカラムの型がInteger(int4)のカラムに対し
自動生成された In句指定を行うと、In句に渡すパラメータの型はCollection<Integer>に
なっていますが、SQLのプリペアステートメント?では
colum1 In ('1','2')
のように、文字列型となって実行され、Integer型に対し文字列を指定しているためcastエラーが発生します。
DBFlute Runtimeで、0.9.6、1.0.5Nどちらで試しても同じ挙動でした。
どちらのバージョンにおいても、jdbc.bat、generate.bat、sql2entity.batを実行し自動生成し直してます。
エラー内容は、後述参照。
実行するSQLの条件は、SQLファイルに記述せず、ConditionBeanで組み立ています。
DB管理ツールのPgAdminにおいてSQLバインドせずに、colum1 In ('1','2')のようにしても
SQLエラーにならず正常通りSQLが実行されるため、プリペアステートメントだと発生するのでは?と思います。
また、PostgresではVer8.2と8.3の間で型を厳密に扱うよう暗黙の型変換が廃止されています。
を参考に、
-- 数値 <-> 文字列変換
CREATE CAST (int4 AS text) WITH INOUT AS IMPLICIT;
CREATE CAST (text as numeric) WITH INOUT AS IMPLICIT;
を、postgresのDBインスタンス(databaseでなくインスタンス単位)に実行すると
数値型のカラム対し、文字列型のIn句がバインド指定されてもSQLエラーは発生せず
正常に実行できるようになります。
DBFlute側で、シングルクォート''を補完している動きだと思うのですが、
その挙動を数値型ならば、シングルクォートで囲まないといった動きにする設定は
ありますでしょうか? もしくは、私の利用方法が間違っていますでしょうか?
なお、Oralce10gでは、暗黙の型変換され問題のSQLは正常に実行されます。
■In句に指定しているバインド変数用にセットする際のメソッド
public void setXxxId_InScope(Collection<Integer> xxxList) {
doSetXxxId_InScope(xxxList);
}
■DBのテーブル定義
[r_テーブル].[カラム1] :integer の定義です
■エラーログ、一部テーブル名やクラス名は加工しています
Throwable:org.seasar.dbflute.exception.SQLFailureException: Look! Read the message below.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
The SQL failed to execute!
[Advice]
Please confirm the SQLException message.
[SQLState]
42883
[ErrorCode]
0
[SQLException]
org.seasar.framework.exception.SSQLException
[ESSR0072]SQLで例外(SQL=[select count(*)
from m_テーブル dflocal
left outer join m_スタッフテーブル dfrelation_0 on dflocal.xxxx = dfrelation_0.xxxx
where exists (select dfsublocal_0.xxxx
from r_テーブル dfsublocal_0
where dfsublocal_0.xxx = dflocal.xxx
and dfsublocal_0.カラム1 in (?)
)
and exists (select dfsublocal_0.xxx
from r_テーブル dfsublocal_0
where dfsublocal_0.xxx = dflocal.xxx
and dfsublocal_0.カラム1 in (?)
)
and dflocal.delete_date is null
and dflocal.status = ?], Message=[0], ErrorCode=42883, SQLState={3})が発生しました
[NextException]
org.postgresql.util.PSQLException
ERROR: operator does not exist: integer = character varying
ヒント: No operator matches the given name and argument type(s). You might need to add explicit type casts.
ポジション: 390
[Behavior]
XxxBhv.selectPage():count()...
[ConditionBean]
MXxxCB
[Statement]
org.seasar.extension.jdbc.impl.PreparedStatementWrapper
[Display SQL]
select count(*)
from m_テーブル dflocal
left outer join m_スタッフテーブル dfrelation_0 on dflocal.create_user = dfrelation_0.STAFF_ID
where exists (select dfsublocal_0.favorite_comment_id
from r_テーブル dfsublocal_0
where dfsublocal_0.xxx = dflocal.xxx
and dfsublocal_0.カラム1 in ('1')
)
and exists (select dfsublocal_0.favorite_comment_id
from r_テーブル dfsublocal_0
where dfsublocal_0.xxx = dflocal.xxx
and dfsublocal_0.カラム1 in ('15')
)
and dflocal.delete_date is null
and dflocal.status = 1