Генерация JOOQ sql для того, где цитата кажется несовместимой для нескольких объектов

Я работал с JOOQ для создания моего SQL, но у меня возникли проблемы с предложением «in», я написал простой тест, который показывает, что я имею в виду:

@Test
public void testWhereInBehaviorJOOQ() {
    String expectedSingleObjectSQL = "select distinct \"Business Group\" \"Business_Group\" from \"SOME_TABLE\" where \"Business Group Process\" in ('SomeValue')";
    String expectedMultipleObjectSQL = "select distinct \"Business Group\" \"Business_Group\" from \"SOME_TABLE\" where \"Business Group Process\" in ('SomeValue','AnotherValue')";

    String actualSingleObjectSQL = generateSQLWithWhereInInline("SomeValue");
    String actualTwoObjectSQL = generateSQLWithWhereInInline("SomeValue,AnotherValue");
    String actualTwoObjectWithQuotesSQL = generateSQLWithWhereInInline("'SomeValue','AnotherValue'");
    String actualTwoObjectWithMiddleQuotesSQL = generateSQLWithWhereInInline("SomeValue','AnotherValue");


    LOGGER.info("JOOQ Generated query for single object \"someValue\" = {}",actualSingleObjectSQL );
    LOGGER.info("JOOQ Generated query for two objects without single quotes \"someValue,AnotherValue\" = {}",actualTwoObjectSQL );
    LOGGER.info("JOOQ Generated query for two objects with single quotes \"'someValue','AnotherValue'\" = {}",actualTwoObjectWithQuotesSQL);
    LOGGER.info("JOOQ Generated query for two objects with single quotes only at the middle \"someValue','AnotherValue\" = {}",actualTwoObjectWithMiddleQuotesSQL );

    Assert.assertEquals(expectedSingleObjectSQL,actualSingleObjectSQL);
    Assert.assertEquals(expectedMultipleObjectSQL,actualTwoObjectSQL);
    Assert.assertEquals(expectedMultipleObjectSQL,actualTwoObjectWithQuotesSQL);
    Assert.assertEquals(expectedMultipleObjectSQL,actualTwoObjectWithMiddleQuotesSQL);

}

private String generateSQLWithWhereInInline(String businessGroupProcess) {
    DSLContext create = DSL.using(SQLDialect.ORACLE);
    return create.
            selectDistinct(
                    DSL.fieldByName("Business Group").as("Business_Group"))
            .from(DSL.tableByName("SOME_TABLE")).where(DSL.fieldByName("Business Group Process").in(DSL.inline(businessGroupProcess))).getSQL();
}

но сгенерированные значения:

JOOQ Сгенерированный запрос для одного объекта "someValue" =

select distinct "Business Group" "Business_Group" 
from "SOME_TABLE" where "Business Group Process" in ('SomeValue')

JOOQ Сгенерированный запрос для двух объектов без одинарных кавычек "someValue,AnotherValue" =

select distinct "Business Group" "Business_Group" 
from "SOME_TABLE" where "Business Group Process" in ('SomeValue,AnotherValue')

JOOQ Сгенерированный запрос для двух объектов с одинарными кавычками "'someValue','AnotherValue'" =

select distinct "Business Group" "Business_Group" 
from "SOME_TABLE" 
where "Business Group Process" in ('''SomeValue'',''AnotherValue''')

JOOQ Сгенерированный запрос для двух объектов с одинарными кавычками только посередине "someValue','AnotherValue" =

select distinct "Business Group" "Business_Group" 
from "SOME_TABLE" 
where "Business Group Process" in ('SomeValue'',''AnotherValue')

поэтому, когда есть только один объект, он работает нормально, для двух он только добавляет кавычки в начало и конец, если я добавляю к ним кавычки до того, как он добавляет кавычки в начало, конец и каждый объект, и если я пытаюсь "обмануть ", добавляя кавычки посередине, надеясь, что он попытается заключить переменные в кавычки, чтобы все получить кавычки. Пробелы не помогают.

кто-нибудь сталкивался с этим раньше? Я хочу знать, неправильно ли я называю это или это ошибка.


person GMelo    schedule 14.08.2013    source источник


Ответы (1)


Здесь jOOQ работает, как и ожидалось. Field.in(...) Метод принимает несколько значений для предиката IN через параметр varargs. Следовательно, если вы хотите выразить предикат с несколькими значениями, вам придется предоставить метод с несколькими значениями.

Таким образом, ваш служебный метод должен выглядеть так:

// I'm assuming this static import
import static org.jooq.impl.DSL.*;

private String generateSQLWithWhereInInline(String... businessGroupProcesses) {
    Field<String>[] fields = new Field[businessGroupProcesses.length];
    for (int i = 0; i < businessGroupProcesses.length; i++)
        fields[i] = inline(businessGroupProcesses[i]);

    return DSL.using(SQLDialect.ORACLE)
              .selectDistinct(
                    field(name("Business Group")).as("Business_Group"))
              .from(table(name("SOME_TABLE")))
              .where(field(name("Business Group Process")).in(fields))
              .getSQL();
}

Более простой способ может состоять в том, чтобы предоставить DSLContext параметр, указывающий ему напрямую встраивать все значения привязки. Это задокументировано здесь:

http://www.jooq.org/doc/latest/manual/sql-building/dsl-context/custom-settings

Тогда ваш метод будет читать:

private String generateSQLWithWhereInInline(String... businessGroupProcesses) {
    Settings settings = new Settings()
        .withStatementType(StatementType.STATIC_STATEMENT);

    return DSL.using(SQLDialect.ORACLE, settings);
              .selectDistinct(
                    field(name("Business Group")).as("Business_Group"))
              .from(table(name("SOME_TABLE")))
              .where(field(name("Business Group Process"))
                    .in(businessGroupProcesses))
              .getSQL();
}
person Lukas Eder    schedule 15.08.2013
comment
Это здорово, работает отлично, спасибо, поддержка сообщества на JOOQ была превосходной! - person GMelo; 15.08.2013