[pgsql-jp: 33830] Re: Java JDBCにおけるFloat 型のNaN値の扱いについて
bxcel
bxcel @ prophet.jp
2004年 8月 6日 (金) 15:06:09 JST
松本と申します。
この件について以下のようなjdbcドライバのpatchを作ってみました。
postgres-7.4.3用です。 このpatchを適用したドライバを使用すると
ps = connection.prepareStatement("INSERT INTO t1 VALUES(?);");
ps.setObject(1,new Float(Float.NaN));
というコードの時に
INSERT INTO t1 VALUES('NaN');
というSQL文になります。
単純にNaNの時にsetStringと同じ処理になるようにしただけでして
その周りの処理はあまり理解できていません。
ローカル環境では確認出来ましたが、何かご意見等ございましたら
アドバイス頂きたくよろしくお願いします。
diff -rc jdbc.orig/org/postgresql/jdbc1/AbstractJdbc1Statement.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
*** jdbc.orig/org/postgresql/jdbc1/AbstractJdbc1Statement.java 2004-05-18 05:38:56.000000000 +0900
--- jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java 2004-08-06 14:24:10.000000000 +0900
***************
*** 1066,1072 ****
*/
public void setFloat(int parameterIndex, float x) throws SQLException
{
! bind(parameterIndex, Float.toString(x), PG_FLOAT);
}
/*
--- 1066,1076 ----
*/
public void setFloat(int parameterIndex, float x) throws SQLException
{
! if ((Float.isNaN(x)) || (x == Float.POSITIVE_INFINITY) || (x == Float.NEGATIVE_INFINITY)) {
! setString(parameterIndex, Float.toString(x), PG_TEXT);
! } else {
! bind(parameterIndex, Float.toString(x), PG_FLOAT);
! }
}
/*
***************
*** 1079,1085 ****
*/
public void setDouble(int parameterIndex, double x) throws SQLException
{
! bind(parameterIndex, Double.toString(x), PG_DOUBLE);
}
/*
--- 1083,1093 ----
*/
public void setDouble(int parameterIndex, double x) throws SQLException
{
! if ((Double.isNaN(x)) || (x == Double.POSITIVE_INFINITY) || (x == Double.NEGATIVE_INFINITY)) {
! setString(parameterIndex, Double.toString(x), PG_TEXT);
! } else {
! bind(parameterIndex, Double.toString(x), PG_DOUBLE);
! }
}
/*
> 松本と申します。
>
> JDBC経由にてFloat型へデータをINSERTする処理において
> PreparedStatementを使用した場合、java.lang.Floatの値が
> Float.NaNの場合にエラーとなってしまいました。
>
> 環境
> Vine2.6 + postgres7.4.3 + pg74.214.jdbc3.jar
>
> テーブル定義
> test=# \d t1
> テーブル "public.t1"
> カラム | 型 | 修飾語
> --------+------------------+--------
> a | double precision |
>
> 再現用Javaのコード1
> ps = connection.prepareStatement("INSERT INTO t1 VALUES(?);");
> ps.setObject(1,new Float(Float.NaN));
>
> 実行されたSQL文
> INSERT INTO t1 VALUES(NaN);
>
> 実行結果
> ERROR: column "nan" does not exist
>
> 再現用Javaのコード2
> ps.setFloat(1,Float.NaN);
>
> 実行結果
> ERROR: column "nan" does not exist
>
> psqlコマンドから実行してみた所、シングルクォートすると
> うまく行きました。
> test=# INSERT INTO t1 VALUES('NaN');
> INSERT 17151 1
> test=# select * from t1;
> a
> -----
> NaN
> (1 行)
>
> Float.POSITIVE_INFINITYとFloat.NEGATIVE_INFINITY
> も同様でした。それぞれ
>
> INSERT INTO t1 VALUES(Infinity);
> ERROR: column "infinity" does not exist
>
> INSERT INTO t1 VALUES(-Infinity);
> ERROR: column "infinity" does not exist
>
> となってしまいました。
> #もっとも解決したとしてもオーバーフローのようですが....
>
> PreparedStatementの「?」を使用しなければ
> いいのですが、float型で使用できないのも不便ですし、
> 「NaN」や「Infinity」「-Infinity」の時だけ
> 別に展開するのもあまり良い方法には思えません。
>
> 他に良い回避方法など何か情報ありましたら教えてください。
>
> これとは似た別の問題ですが、「WHERE a = ?」というWHERE句にて
> 「ps.setObject(1,null)」とした場合「WHERE a = null」となって
> しまい「WHERE a is null」にはならないので、期待した結果に
> ならない問題と同様なんですかね。
> #こちらはSQL文作る方で対処しなければなりませんが....
>
>
>
pgsql-jp メーリングリストの案内