Domanda

Non riesco a leggere un UDT correttamente da una funzione memorizzata con il il driver JDBC Postgres. Questo è un codice di esempio:

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;

Ora le opere di cui sopra perfettamente in Postgres. Posso anche selezionare l'UDT t_author.address colonna con un'istruzione SQL SELECT direttamente. Ma quando Seleziono dal p_enhance_address2 funzione memorizzata tramite JDBC, ho un strano comportamento. Ho provato questi due schemi di invocazione:

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

Entrambi i sistemi di chiamata indurre lo stesso comportamento (in realtà la CallableStatement non è altro che selezionare dalla funzione). Sembra che ci siano due problemi ben distinte:

La struttura UDT nidificato completamente le viti fino risultati fetching. Questo è quello che ottengo con 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));
}

Output:

  

Numero di colonne: 6   ( "(" "Parliament Hill" "77)", NW31A9)

Perché ci sono 6 colonne? E perché è l'UDT in modo non corretto inverosimile (molti campi mancanti)

Un po 'di miglioramento può essere raggiunto, quando l'UDT nidificato u_street_type è "appiattita" ad un varchar, che conduce ai presupposto che nidificati di UDT sono scarsamente supportati dal driver JDBC:

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

Poi i risultati saranno qualcosa di simile:

  

Numero di colonne: 6   ( "Parliament Hill 77", NW31A9, Hampstead, Inghilterra, 1980-01-01,)

Il record UDT ora sembra corretto (prelevato dalla serie di risultati a posizione 1). Ma ci sono ancora 6 colonne del set di risultati.

Alcuni fatti:

  • I non si verificano questi problemi in pgAdmin III
  • Io uso PostgreSQL 9.0.1, compilato da Visual C ++ di build 1500, a 64 bit
  • I usare PostgreSQL-9.0-801.jdbc4.jar

Qualcuno ha qualche idea di cosa c'è che non va?

È stato utile?

Soluzione

posso riprodurre questo e sembra che si tratta di un bug.

Vorrei suggerire di postare questo alla mailing list di PostgreSQL JDBC, in modo che gli sviluppatori possano risolvere il problema.

Altri suggerimenti

Se non am UDT sbagliato (utente tipo definito) non ufficialmente supportato (JDBC conformità) da parte dei conducenti postgres9.4 (postgresql-9.0-801.jdbc4.jar). Ho molto anche di fronte a problemi durante postgres chiamando la funzione codice del modulo Java. Ho usato qui di seguito i driver e risolto il mio problema.

ecco il link pilota non ufficiale, http://impossibl.github.io/pgjdbc-ng/ modulo pilota copiare il link Crea connessione come spiegato nel seguente

si prega di vedere sotto esempio di lavoro dalla mia POC Oracle10g a Postgres9.4 l'attività di migrazione vedi sotto esempio POC,

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

Funzione principale di chiamata,

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");
       }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top