При дублировании ключа с помощью hstore merge с использованием jooq - PullRequest
0 голосов
/ 07 апреля 2020

В настоящее время я пытаюсь реализовать следующий запрос sql в jooq:

INSERT INTO table as t (id, hstore_data) 
VALUES ('test', '"key1" => "val1"') 
ON CONFLICT (id) 
DO UPDATE SET hstore_data = add(t.hstore_data, '"keyX" => "valX"');

add () - это пользовательская функция:

CREATE FUNCTION add(hstore, hstore) RETURNS hstore
AS 'select $1 || $2;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;

До сих пор мне удалось запустить и запустить это:

return DSL.using(configuration)
            .insertInto(TABLE)
            .columns(TABLE.ID, TABLE.HSTORE_DATA)
            .values(table.getId(), table.getHstoreData())
            .onDuplicateKeyUpdate()
            .set(TABLE.HSTORE_DATA,
                            merge(
                                    DSL.using(configuration).select(TABLE.HSTORE_DATA).from(TABLE).where(TABLE.ID.eq(table.getId())).fetchAnyInto(HashMap.class)
                                    , table.getHstoreData()

                            )
                    )
            .execute();

merge () - простая JAVA функция, объединяющая две карты.

This подход работает. Однако я хотел бы выполнить всю обработку на сервере базы данных, как предполагает первый запрос.

Я попытался использовать подпрограмму, сгенерированную jooq для add () . Но похоже, что jooq не использует привязку hstore. Привязка определяется в ConfigGenerator следующим образом:

types.add(new ForcedType()
            .withUserType("java.util.Map<String, String>")
            .withBinding("HStoreStringBinding")
            .withIncludeExpression(".*_data")
            .withIncludeTypes(".*"));
types.add(new ForcedType()
            .withUserType("java.util.Map<String, Long>")
            .withBinding("HStoreLongBinding")
            .withIncludeExpression(".*_counts")
            .withIncludeTypes(".*"));

Привязка работает для hstores, только не для пользовательской функции.

  1. Существуют ли более умные подходы?
  2. В чем может быть причина того, что add () введен неправильно?
  3. Как я могу сказать jooq использовать исходное значение в слиянии, как в необработанном запросе SQL с t.hstore_data?

1 Ответ

1 голос
/ 07 апреля 2020

В чем может быть причина того, что add () введен неправильно?

Попробуйте назвать параметры вашей функции, иначе вы не сможете сопоставить их со свойством includeExpression. Чтобы соответствовать возвращаемому значению функции, используйте само имя функции как includeExpression. Конечно, вы можете просто оставить свойство и сопоставить все hstore типы с более обобщенной c привязкой:

types.add(new ForcedType()
            .withUserType("java.util.Map<String, String>")
            .withBinding("HStoreStringBinding")
            .withIncludeTypes("hstore"));

Как я могу сказать jooq использовать оригинальное значение в объединить, как я делаю в необработанном SQL запросе с t.hstore_data?

Как только генерируется код, вы просто используете свою функцию добавления, как в SQL версии вашего оператора:

set(TABLE.HSTORE_DATA, Routines.add(TABLE.HSTORE_DATA, table.getHstoreData()))
...