简体   繁体   中英

JOOQ sql generation for where in quotation seems inconsistent for multiple Objects

I have been working with JOOQ to generate my SQL, but I have been having trouble with the "in" clause, I wrote a simple Test that shows what I mean:

@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();
}

but the generated values are:

JOOQ Generated query for single object "someValue" =

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

JOOQ Generated query for two objects without single quotes "someValue,AnotherValue" =

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

JOOQ Generated query for two objects with single quotes "'someValue','AnotherValue'" =

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

JOOQ Generated query for two objects with single quotes only at the middle "someValue','AnotherValue" =

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

so when there is only one object it works fine, for two it only appends quotes to the beginning and the end, if i add quotes to them before it adds quotes to the beginning, end and each object, and if i try and "trick" it by adding quotes in the middle hoping it will try to wrap the variables in quotes everything get quotes. Spaces do not seem to help.

has anyone encountered this before? I want to know if I am calling it wrong or if its a bug.

jOOQ works as expected, here. The Field.in(...) method accepts several values for the IN predicate through a varargs parameter. Hence, if you want to express a predicate with several values, you will have to provide the method with several values.

Your utility method should thus read:

// 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();
}

An easier method might be to provide the DSLContext with a setting to tell it to inline all bind values directly. This is documented here:

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

Your method would then read:

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM