Question

Je ne peux pas sembler lire correctement un UDT à partir d'une fonction stockée avec le pilote JDBC postgres. Ceci est un exemple de code:

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;

Maintenant, les travaux ci-dessus parfaitement dans Postgres. Je peux aussi choisir la UDT colonne t_author.address avec une instruction SQL SELECT directement. Mais quand Je choisis de la fonction stockée p_enhance_address2 via JDBC, je reçois un comportement bizarre. J'ai essayé ces deux régimes d'invocation:

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

Les deux systèmes d'appel induisent le même comportement (en fait la CallableStatement est rien d'autre que la sélection de la fonction). Il semble y avoir deux problèmes bien distincts:

La structure UDT imbriqué vis complètement vers le haut des résultats FETCH. Cette est ce que je reçois avec 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));
}

Sortie:

  

nr de colonnes: 6   ( "(" "Colline du Parlement" "77)", NW31A9)

Pourquoi y at-il 6 colonnes? Et pourquoi est l'UDT mal tiré par les cheveux (beaucoup champs manquent)

peut être atteint un peu d'amélioration, lorsque l'UDT imbriqué u_street_type est « aplaties » à un varchar, ce qui conduit à la hypothèse que de UDT imbriquées sont mal pris en charge par le pilote 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))

Ensuite, les résultats seront quelque chose comme ceci:

  

nr de colonnes: 6   ( "La Colline du Parlement 77", NW31A9, Hampstead, Angleterre, 1980-01-01,)

L'enregistrement UDT semble correcte (extraite du jeu de résultats à position 1). Mais il y a encore 6 colonnes dans le jeu de résultats.

Quelques faits:

  • Je ne connaît pas ces problèmes dans pgAdmin III
  • J'utilise PostgreSQL 9.0.1, compilé par Visual C ++ build 1500, 64 bits
  • J'utilise postgresql-9.0-801.jdbc4.jar

Est-ce que quelqu'un a une idée de ce qui ne va pas?

Était-ce utile?

La solution

Je peux reproduire ce et il semble que ce soit un bug.

Je vous suggère de publier ce à la liste de diffusion PostgreSQL JDBC, les développeurs peuvent donc résoudre ce problème.

Autres conseils

Si je ne suis pas mal UDT (type défini par l'utilisateur) pas officiellement pris en charge (conformité JDBC) par les pilotes de postgres9.4 (postgresql-9.0-801.jdbc4.jar). J'ai aussi beaucoup face problème alors que la fonction postgres appelant forme de code java. Je les pilotes ci-dessous et résolu mon problème.

voici le lien du pilote non officiel, http://impossibl.github.io/pgjdbc-ng/ sous forme de pilote de copie le lien à créer une connexion, comme expliqué ci-dessous en

S'il vous plaît voir ci-dessous exemple de travail de mon POC Oracle10g à l'activité de migration Postgres9.4 voir exemple ci-dessous 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;
==========================

appel de fonction principale,

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");
       }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top