2011-01-10 52 views
2

postgres JDBCドライバを使用して、ストアドファンクションからUDTを正しく読み取れないようです。これはいくつかのサンプルコードです:postgresストアドファンクションからUDTを読み取る方法

CREATE TYPE u_country AS ENUM ('Brazil', 'England', 'Germany') 

CREATE TYPE u_street_type AS (
    street VARCHAR(100), 
    no VARCHAR(30) 
) 

CREATE TYPE u_address_type AS (
    street u_street_type, 
    zip VARCHAR(50), 
    city VARCHAR(50), 
    country u_country, 
    since DATE, 
    code INTEGER 
) 

CREATE TABLE t_author (
    id INTEGER NOT NULL PRIMARY KEY, 
    first_name VARCHAR(50), 
    last_name VARCHAR(50) NOT NULL, 
    date_of_birth DATE, 
    year_of_birth INTEGER, 
    address u_address_type 
) 

INSERT INTO t_author VALUES (1, 'George', 'Orwell', 
TO_DATE('1903-06-25', 'YYYY-MM-DD'), 1903, ROW(ROW('Parliament Hill', 
'77'), 'NW31A9', 'Hampstead', 'England', '1980-01-01', null)) 
INSERT INTO t_author VALUES (2, 'Paulo', 'Coelho', 
TO_DATE('1947-08-24', 'YYYY-MM-DD'), 1947, ROW(ROW('Caixa Postal', 
'43.003'), null, 'Rio de Janeiro', 'Brazil', '1940-01-01', 2)) 

CREATE FUNCTION p_enhance_address2 (address OUT u_address_type) 
AS $$ 
BEGIN 
     SELECT t_author.address 
     INTO address 
     FROM t_author 
     WHERE first_name = 'George'; 
END; 
$$ LANGUAGE plpgsql; 

上記は完全にポストグラムで動作します。また、SQL SELECT文を使用してUDT 列t_author.addressを直接選択することもできます。しかし、 JDBC経由でストアド関数p_enhance_address2から選択すると、 という奇妙な動作が発生します。 (実際に たCallableStatementは、関数から選択するより他に何もありません)

connection.prepareStatement("select * from p_enhance_address2()"); 
connection.prepareCall("{ call p_enhance_address2(?) }"); 
// the latter with an output parameter registered 

どちらの呼び出し方式が同じ行動を誘発する:私は、これらの二つの呼び出しスキームを試してみました。 2つの非常に明確な問題があるようです。

ネストされたUDT構造は、フェッチ結果を完全に固定します。この は私がJDBCで得るものです:

PreparedStatement stmt = connection.prepareStatement(
    "select * from p_enhance_address2()"); 
ResultSet rs = stmt.executeQuery(); 

while (rs.next()) { 
    System.out.println("# of columns: " + 
    rs.getMetaData().getColumnCount()); 
    System.out.println(rs.getObject(1)); 
} 

出力:列の

NR:6 ( "(" "パーラメント" "77)"、NW31A9)

なぜ6列ありますか?そして、なぜUDTは、ネストされたUDT u_street_typeがUDTの不十分されているネストされた 前提につながるvarchar型、に「フラット化」されたときにほとんど改善は、達成することができ

を(多くの フィールドが欠落している)が誤って取り込まれ、 JDBCドライバでサポート:列の

NR:

CREATE TYPE u_address_type AS (
    street VARCHAR(80), 
    zip VARCHAR(50), 
    city VARCHAR(50), 
    country u_country, 
    since DATE, 
    code INTEGER 
) 

INSERT INTO t_author VALUES (1, 'George', 'Orwell', 
TO_DATE('1903-06-25', 'YYYY-MM-DD'), 1903, ROW('Parliament Hill 77', 
'NW31A9', 'Hampstead', 'England', '1980-01-01', null)) 
INSERT INTO t_author VALUES (2, 'Paulo', 'Coelho', 
TO_DATE('1947-08-24', 'YYYY-MM-DD'), 1947, ROW('Caixa Postal 43.003', 
null, 'Rio de Janeiro', 'Brazil', '1940-01-01', 2)) 

その後の結果はこのようになります6 ( "パーラメントヒル77"、NW31A9、ハムステッド、イングランド、1980年1月1日、)

UDTレコードは今 位置1)で結果セットからフェッチされた(正しく見えます。しかし、結果セットにはまだ6列あります。

いくつかの事実:

  • 私はpgAdminでIII
  • で、これらの問題を経験していない私は、PostgreSQL 9.0.1を使用して、ビジュアルCでコンパイル
  • 、64ビットの1500を構築++は私は、PostgreSQL-9.0を使用します-801.jdbc4.jar

何が悪いと思いますか?

+0

Pythonでは、私は常にトンを持っていますoカスタムは、行をネストしようとするときに型をマップします。 - またはちょうどそれをしないでください:-( –

+0

はい、多分これらのことをしないほうがずっと簡単です。なぜなら、彼らのサポートは多くのRDBMSやJDBCドライバ(またはPython - 私はそれについてはわかりません)です。私は、データベース・インターフェース・ライブラリjOOQ:http://jooq.sourceforge.netを通して、ベンダー固有の高度なSQL機能へのアクセスを「標準化」しようとしています。そして、jOOQでは、期待していたのでネストされたUDTを使用できるようにしたい私のユーザーは、その機能を使用するために –

答えて

1

これを再現できますが、これはバグであるようです。

これをPostgreSQL JDBCメーリングリストに投稿することをお勧めします。これにより、開発者はこれを修正できます。

+0

フィードバックをいただきありがとうございます。私はこれがバグか間違って何かをしているかどうかわかりませんでした... –

+0

ユーザーグループのバグのように見える... http://groups.google .com/group/pgsql.interfaces.jdbc/browse_thread/thread/58568fd0699b246f/142aa7fec27cac44 –

2

間違っていない場合は、postgres9.4ドライバ(postgresql-9.0-801.jdbc4.jar)によって正式にサポートされていないUDT(ユーザー定義型)(JDBC準拠)。私はpostgres関数の形式のJavaコードを呼び出している間、多くの問題に直面しています。 以下のドライバを使用して問題を解決しました。ここ

が非公式ドライバリンク、 http://impossibl.github.io/pgjdbc-ng/ コピードライバが

の下で説明するように、リンク接続を作成形成され、例えば、POC下記参照私のPOCでOracle10gからPostgres9.4遊走活性に作業例の下に参照してください。

-- Function: fn_test_t(text) 

-- DROP FUNCTION fn_test_t(text); 

CREATE OR REPLACE FUNCTION fn_test_t(
    IN txt text, 
    OUT a typ_address[], 
    OUT b typ_address[]) 
    RETURNS record AS 
$BODY$ 
DECLARE 
address typ_address[]; 
BEGIN 
RAISE INFO '@@ inside fn_test:(%)',111; 
address[1] := ROW('Amravati', 'Mahalaxmi', ROW('Test1')); 
address[2] := ROW('Pune', 'NICMAR',ROW('Test2')); 
address[3] := ROW('', '',ROW('Test3')); 
RAISE INFO 'array of address:(%)',address; 
--a := ROW(address); 
--b := ROW(address); 
a := address; 
b := address; 
RAISE INFO 'typ_address_t a:(%)',a; 
RAISE INFO 'typ_address_t b:(%)',b; 
    -- RETURN address; 
END; 
$BODY$ 
    LANGUAGE plpgsql VOLATILE 
    COST 100; 
ALTER FUNCTION fn_test_t(text) 
    OWNER TO postgres; 

========================= 
-- Type: typ_address 

-- DROP TYPE typ_address; 

CREATE TYPE typ_address AS 
    (add1 character varying, 
    add2 character varying, 
    t typ_test); 
ALTER TYPE typ_address 
    OWNER TO postgres; 
========================== 
-- Type: typ_test 

-- DROP TYPE typ_test; 

CREATE TYPE typ_test AS 
    (t1 character varying); 
ALTER TYPE typ_test 
    OWNER TO postgres; 
========================== 

メイン関数呼び出し、

public static void oracleToPosgresUDTCall() { 
     System.out.println("@@@ inside oracleToPosgresUDTCall..."); 
      Connection c = null; 
      try { 
      Class.forName("com.impossibl.postgres.jdbc.PGDriver"); 
      c = DriverManager 
       .getConnection("jdbc:pgsql://localhost:5433/orapg", "postgres", "root"); 
      System.out.println(c.getMetaData().getDriverVersion()); 

      //you can map your UDT to pojo here Great !!! 
      Map<String, Class<?>> m = c.getTypeMap(); 
      m.put("typ_address", Address.class); 
      m.put("typ_test", AddressTypeTest.class); 
      c.setTypeMap(m); 

      // Procedure call 
      CallableStatement cstmt = c.prepareCall("{call fn_test_t(?,?,?)}"); 

      cstmt.setString(1, "791000252423"); 

      cstmt.registerOutParameter(2, Types.ARRAY); 
      cstmt.registerOutParameter(3, Types.ARRAY); 


       boolean b = cstmt.execute(); 

      Array arr = cstmt.getArray(1); //output array starts from index 1 

      System.out.println("arr:" + arr.getBaseTypeName()); 
      Object obj = arr.getArray(); 

      System.out.println("Address obj:" + obj); 
      Address[] a = (Address[])obj; 
      System.out.println("Address obj:" + a[0].getAdd1()); 
      System.out.println("Address obj:" + a[0].getTypeTest().getT1()); 

      System.out.println("======================================================="); 
      //MORE 

      List<Address> list = Arrays.asList(a); 

      for(Address aa: list){ 
       System.out.println(aa.getAdd1()); 
       System.out.println(aa.getAdd2()); 
       System.out.println("t1:" + aa.getTypeTest().getT1()); 
      } 



      cstmt.close(); 

      } catch (Exception e) { 
      e.printStackTrace(); 
      System.err.println(e.getClass().getName()+": "+e.getMessage()); 
      System.exit(0); 
      } 
      System.out.println("Opened database successfully"); 
     } 
関連する問題