Postgresql array_agg из нескольких столбцов с JDBC

Я пытаюсь присоединиться к таблице, которая может иметь несколько записей для данного идентификатора, и объединить строки, соответствующие этому идентификатору, в массиве. В SQL-запросе это выглядит следующим образом:

SELECT * from data
LEFT JOIN (select id, array_agg(row(foo, bar)) AS foo_bar_data from foo_bar_table group by id) AS temp using(id)

Это работает по назначению, но у меня возникают проблемы с чтением результата в JDBC.

ResultSet rs = st.executeQuery(...)
Array a = rs.getArray("foo_bar_data")
// Now I want to iterate over the array, reading the values foo and bar of each item.

Мои усилия до сих пор всегда заканчивались исключением Method org.postgresql.jdbc4.Jdbc4Array.getArrayImpl(long,int,Map) is not yet implemented.. Как я могу перебрать a, получая значения foo и bar?

Изменить: я должен также упомянуть, что foo и bar не имеют одного и того же типа.


person panmari    schedule 14.08.2015    source источник
comment
Какие версии сервера pg и драйвера?   -  person Radek Postołowicz    schedule 14.08.2015
comment
Сервер на 8.4.9 и в качестве драйвера я использую postgresql-9.4-1201.jdbc41.jar   -  person panmari    schedule 14.08.2015
comment
Не могли бы вы опубликовать полный запрос, который вы используете (или, по крайней мере, часть SELECT, что отражает ResultSet).   -  person Mick Mnemonic    schedule 15.08.2015


Ответы (1)


Драйвер Postgres JDBC не поддерживает ничего, кроме базовых типов (числа, дата/временная метка, строка) в качестве массива JDBC. Вы можете вызвать array_agg дважды и получить два массива в каждой строке:

    try (Connection db = DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgres", "postgres", "postgres");
                 ResultSet rs = db.createStatement().executeQuery("select array_agg(i), array_agg(s) from (select 1 i, 'a' s union select 2 i, 'b' s) t")) {
        rs.next();
        System.out.println(Arrays.toString((Object[]) rs.getArray(1).getArray()));
        System.out.println(Arrays.toString((Object[]) rs.getArray(2).getArray()));
    }
person sibnick    schedule 15.08.2015
comment
Я не понимаю, как этот запрос должен работать. Не могли бы вы немного объяснить и, возможно, использовать те же имена столбцов, что и я? Кроме того, я упомянул в своем ответе, что foo и bar не имеют одного и того же типа, например. г. строка соотв. целое число. Будет ли это все еще работать, поскольку я вижу, что вы все переводите в массив Integer? - person panmari; 15.08.2015
comment
В порядке. Я понимаю вашу проблему. postgres JDBC не поддерживает смешанный массив. Вы можете выбрать два столбца: массив чисел и массив строк. - person sibnick; 15.08.2015
comment
Итак, как я смогу это сделать, если я приведу все к строке в запросе? - person panmari; 15.08.2015
comment
Вы можете написать: SELECT * from data LEFT JOIN (select id, array_agg(row(foo, bar)::text) AS foo_bar_data и вы получите String[] вроде [(1,a), (2,b)], где (1,a) — одна строка. Но почему вы не хотите использовать два столбца/массива? - person sibnick; 15.08.2015
comment
Это решение, которое я сейчас использую, затем анализирую строку в java (очень уродливо). Да, я бы предпочел получить эти два значения по отдельности. Что вы подразумеваете под выбором двух столбцов? Вызывать array_agg дважды, один раз со строковым столбцом и один раз с столбцом int? - person panmari; 15.08.2015
comment
Да, вызвать array_agg дважды - person sibnick; 15.08.2015
comment
Хорошо, согласно этому ответу, соответствующие значения будут упорядочены одинаково в обоих массивах, что было бы достаточно для моего использования. Не могли бы вы немного отредактировать свой ответ, тогда я приму его. - person panmari; 15.08.2015