Frage

Ich kann keine UDT richtig aus einer gespeicherten Funktion mit dem zu lesen scheinen Postgres JDBC-Treiber. Dies ist ein Beispielcode:

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;

Nun werden die oben funktioniert perfekt in Postgres. Ich kann auch die UDT wählen Spalte t_author.address mit einer direkt SQL-Anweisung SELECT. Aber wenn Ich wähle aus der gespeicherten Funktion p_enhance_address2 über JDBC, erhalte ich eine seltsames Verhalten. Ich habe versucht, diese beiden Aufrufsysteme:

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

induzieren Beide Aufruf Systeme das gleiche Verhalten (eigentlich die Callablestatement ist nichts anderes als von der Auswahl der Funktion). Es scheint zwei sehr unterschiedliche Probleme zu sein:

Die verschachtelte UDT Struktur komplett vermasselt fetching Ergebnisse. Dies Ich mit JDBC ist, was bekommen:

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));
}

Ausgabe:

nr der Spalten: 6 ( "(" "Parliament Hill" "77)", NW31A9)

Warum gibt es 6 Spalten? Und warum ist das UDT falsch abgerufen (viele Felder fehlen)

Eine kleine Verbesserung erreicht werden kann, wenn die verschachtelte UDT u_street_type wird „abgeflachte“ auf eine VARCHAR was dazu führt, Annahme, dass verschachtelte UDT sind schlecht vom JDBC-Treiber unterstützt:

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))

Dann werden die Ergebnisse so etwas wie diese:

nr der Spalten: 6 ( "Parliament Hill 77", NW31A9, Hampstead, England, 1980-01-01,)

Der UDT Datensatz sieht nun korrekt (wird aus der Ergebnismenge an Position 1). Aber es gibt noch 6 Spalten in der Ergebnismenge.

Einige Fakten:

  • Ich erlebe diese Probleme nicht in pgAdmin III
  • verwende ich PostgreSQL 9.0.1, zusammengestellt von Visual C ++ Build 1500, 64-Bit
  • Ich benutze postgresql-9.0-801.jdbc4.jar

Hat jemand eine Ahnung, was falsch ist?

War es hilfreich?

Lösung

Das kann ich reproduzieren und es scheint, dass dies ein Fehler ist.

Ich würde vorschlagen, dass Sie diesen Beitrag zu der PostgreSQL JDBC Mailing-Liste, so dass die Entwickler dieses Problem beheben können.

Andere Tipps

Wenn am nicht falsch UDT (User Defined Type) nicht offiziell unterstützt (JDBC-Konformität) von postgres9.4 Treiber (postgresql-9.0-801.jdbc4.jar). Ich auch Gesicht Menge Probleme beim Aufruf Postgres funktioniert Form von Java-Code. Früher habe ich unter Treiber und mein Problem gelöst.

Hier ist der nicht offizielle Treiber Link, http://impossibl.github.io/pgjdbc-ng/ Kopie Treiber Formular erstellen die Link-Verbindung wie im Abschnitt unter

siehe Beispiel aus meiner POC Oracle10g zu Postgres9.4 Migrationsaktivität siehe unten Beispiel POC unten arbeiten,

-- 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;
==========================

Hauptfunktionsaufruf,

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");
       }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top