Я не могу правильно прочитать UDT из хранимой функции с
Postgres JDBC драйвер. Вот пример кода:
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;
Теперь вышесказанное прекрасно работает в postgres. Я также могу выбрать UDT
столбец t_author.address непосредственно с оператором SQL SELECT. Но когда
Я выбираю из сохраненной функции p_enhance_address2 через JDBC, я получаю
странное поведение. Я попробовал эти две схемы вызова:
connection.prepareStatement("select * from p_enhance_address2()");
connection.prepareCall("{ call p_enhance_address2(?) }");
// the latter with an output parameter registered
Обе схемы вызова вызывают одинаковое поведение (на самом деле
CallableStatement - это не что иное, как выбор из функции).
Кажется, есть две совершенно разные проблемы:
Вложенная структура 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));
}
Выход:
Кол-во столбцов: 6
("(" "Парламентский холм" ", 77)", NW31A9)
Почему там 6 столбцов? И почему UDT неправильно выбирается (многие
поля отсутствуют)
Небольшое улучшение может быть достигнуто, когда вложенный UDT
u_street_type "сплющен" к varchar, что приводит к
Предположение, что вложенные UDT плохо поддерживаются драйвером 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))
Тогда результаты будут примерно такими:
Кол-во столбцов: 6
("Парламент Хилл 77", NW31A9, Хэмпстед, Англия, 1980-01-01,)
Запись UDT теперь выглядит правильно (выбирается из результирующего набора в
позиция 1). Но в наборе результатов по-прежнему есть 6 столбцов.
Некоторые факты:
- Я не испытываю этих проблем в pgAdmin III
- Я использую PostgreSQL 9.0.1, скомпилированный Visual C ++ build 1500, 64-bit
- Я использую postgresql-9.0-801.jdbc4.jar
Кто-нибудь знает, что не так?