Search in sources :

Example 6 with SQLDialect

use of org.jooq.SQLDialect in project jOOQ by jOOQ.

the class DefaultBinding method toSQL.

/**
     * Inlining abstraction
     */
@SuppressWarnings({ "unchecked", "rawtypes" })
private final void toSQL(BindingSQLContext<U> ctx, Object val) {
    SQLDialect family = ctx.family();
    RenderContext render = ctx.render();
    if (render.paramType() == INLINED) {
        if (val == null) {
            render.keyword("null");
        } else if (type == Boolean.class) {
            // [#1153] Some dialects don't support boolean literals TRUE and FALSE
            if (asList(FIREBIRD, SQLITE).contains(family)) {
                render.sql(((Boolean) val) ? "1" : "0");
            } else {
                render.keyword(((Boolean) val).toString());
            }
        } else // [#1154] Binary data cannot always be inlined
        if (type == byte[].class) {
            byte[] binary = (byte[]) val;
            if (asList().contains(family)) {
                render.sql("0x").sql(convertBytesToHex(binary));
            } else if (asList(DERBY, H2, HSQLDB, MARIADB, MYSQL, SQLITE).contains(family)) {
                render.sql("X'").sql(convertBytesToHex(binary)).sql('\'');
            } else if (asList().contains(family)) {
                render.keyword("hextoraw('").sql(convertBytesToHex(binary)).sql("')");
            } else if (family == POSTGRES) {
                render.sql("E'").sql(PostgresUtils.toPGString(binary)).keyword("'::bytea");
            } else // This default behaviour is used in debug logging for dialects
            // that do not support inlining binary data
            {
                render.sql("X'").sql(convertBytesToHex(binary)).sql('\'');
            }
        } else // Interval extends Number, so let Interval come first!
        if (Interval.class.isAssignableFrom(type)) {
            render.sql('\'').sql(escape(val, render)).sql('\'');
        } else // [#5249] Special inlining of special floating point values
        if (Double.class.isAssignableFrom(type) && ((Double) val).isNaN()) {
            if (POSTGRES == family)
                render.visit(inline("NaN")).sql("::").keyword("float8");
            else
                render.sql(((Number) val).toString());
        } else // [#5249] Special inlining of special floating point values
        if (Float.class.isAssignableFrom(type) && ((Float) val).isNaN()) {
            if (POSTGRES == family)
                render.visit(inline("NaN")).sql("::").keyword("float4");
            else
                render.sql(((Number) val).toString());
        } else if (Number.class.isAssignableFrom(type)) {
            render.sql(((Number) val).toString());
        } else // [#1156] DATE / TIME inlining is very vendor-specific
        if (Tools.isDate(type)) {
            Date date = getDate(type, val);
            // [#1253] SQL Server and Sybase do not implement date literals
            if (asList(SQLITE).contains(family)) {
                render.sql('\'').sql(escape(date, render)).sql('\'');
            } else // [#1253] Derby doesn't support the standard literal
            if (family == DERBY) {
                render.keyword("date('").sql(escape(date, render)).sql("')");
            } else // [#3648] Circumvent a MySQL bug related to date literals
            if (family == MYSQL) {
                render.keyword("{d '").sql(escape(date, render)).sql("'}");
            } else // Most dialects implement SQL standard date literals
            {
                render.keyword("date '").sql(escape(date, render)).sql('\'');
            }
        } else if (Tools.isTimestamp(type)) {
            Timestamp ts = getTimestamp(type, val);
            // [#1253] SQL Server and Sybase do not implement timestamp literals
            if (asList(SQLITE).contains(family)) {
                render.sql('\'').sql(escape(ts, render)).sql('\'');
            } else // [#1253] Derby doesn't support the standard literal
            if (family == DERBY) {
                render.keyword("timestamp('").sql(escape(ts, render)).sql("')");
            } else // CUBRID timestamps have no fractional seconds
            if (family == CUBRID) {
                render.keyword("datetime '").sql(escape(ts, render)).sql('\'');
            } else // [#3648] Circumvent a MySQL bug related to date literals
            if (family == MYSQL) {
                render.keyword("{ts '").sql(escape(ts, render)).sql("'}");
            } else // Most dialects implement SQL standard timestamp literals
            {
                render.keyword("timestamp '").sql(escape(ts, render)).sql('\'');
            }
        } else if (Tools.isTime(type)) {
            Time time = getTime(type, val);
            // [#1253] SQL Server and Sybase do not implement time literals
            if (asList(SQLITE).contains(family)) {
                render.sql('\'').sql(new SimpleDateFormat("HH:mm:ss").format(time)).sql('\'');
            } else // [#1253] Derby doesn't support the standard literal
            if (family == DERBY) {
                render.keyword("time").sql("('").sql(escape(time, render)).sql("')");
            } else // [#3648] Circumvent a MySQL bug related to date literals
            if (family == MYSQL) {
                render.keyword("{t '").sql(escape(time, render)).sql("'}");
            } else // Most dialects implement SQL standard time literals
            {
                render.keyword("time").sql(" '").sql(escape(time, render)).sql('\'');
            }
        } else if (type == OffsetDateTime.class) {
            String string = format((OffsetDateTime) val);
            // Some dialects implement SQL standard time literals
            {
                render.keyword("timestamp with time zone").sql(" '").sql(escape(string, render)).sql('\'');
            }
        } else if (type == OffsetTime.class) {
            String string = format((OffsetTime) val);
            // Some dialects implement SQL standard time literals
            {
                render.keyword("time with time zone").sql(" '").sql(escape(string, render)).sql('\'');
            }
        } else if (type.isArray()) {
            String separator = "";
            // H2 renders arrays as rows
            if (family == H2) {
                render.sql('(');
                for (Object o : ((Object[]) val)) {
                    render.sql(separator);
                    new DefaultBinding<Object, Object>(Converters.identity((Class) type.getComponentType()), isLob).sql(new DefaultBindingSQLContext<Object>(ctx.configuration(), ctx.data(), ctx.render(), o));
                    separator = ", ";
                }
                render.sql(')');
            } else if (family == POSTGRES) {
                render.visit(cast(inline(PostgresUtils.toPGArrayString((Object[]) val)), type));
            } else // By default, render HSQLDB / POSTGRES syntax
            {
                render.keyword("ARRAY");
                render.sql('[');
                for (Object o : ((Object[]) val)) {
                    render.sql(separator);
                    new DefaultBinding<Object, Object>(Converters.identity((Class) type.getComponentType()), isLob).sql(new DefaultBindingSQLContext<Object>(ctx.configuration(), ctx.data(), ctx.render(), o));
                    separator = ", ";
                }
                render.sql(']');
                // [#3214] Some PostgreSQL array type literals need explicit casting
                if (family == POSTGRES && EnumType.class.isAssignableFrom(type.getComponentType())) {
                    pgRenderEnumCast(render, type);
                }
            }
        } else if (EnumType.class.isAssignableFrom(type)) {
            String literal = ((EnumType) val).getLiteral();
            if (literal == null) {
                new DefaultBinding<Object, Object>(Converters.identity((Class) String.class), isLob).sql(new DefaultBindingSQLContext<Object>(ctx.configuration(), ctx.data(), ctx.render(), literal));
            } else {
                new DefaultBinding<Object, Object>(Converters.identity((Class) String.class), isLob).sql(new DefaultBindingSQLContext<Object>(ctx.configuration(), ctx.data(), ctx.render(), literal));
            }
        } else if (UDTRecord.class.isAssignableFrom(type)) {
            render.sql("[UDT]");
        } else // Known fall-through types:
        // - Blob, Clob (both not supported by jOOQ)
        // - String
        // - UUID
        {
            render.sql('\'').sql(escape(val, render), true).sql('\'');
        }
    } else // In Postgres, some additional casting must be done in some cases...
    if (family == SQLDialect.POSTGRES) {
        // Postgres needs explicit casting for enum (array) types
        if (EnumType.class.isAssignableFrom(type) || (type.isArray() && EnumType.class.isAssignableFrom(type.getComponentType()))) {
            render.sql(ctx.variable());
            pgRenderEnumCast(render, type);
        } else // ... and also for other array types
        if (type.isArray() && byte[].class != type) {
            render.sql(ctx.variable());
            render.sql("::");
            render.keyword(DefaultDataType.getDataType(family, type).getCastTypeName(render.configuration()));
        } else {
            render.sql(ctx.variable());
        }
    } else {
        render.sql(ctx.variable());
    }
}
Also used : RenderContext(org.jooq.RenderContext) Time(java.sql.Time) LocalTime(java.time.LocalTime) OffsetTime(java.time.OffsetTime) OffsetDateTime(java.time.OffsetDateTime) LocalDateTime(java.time.LocalDateTime) PostgresUtils.toPGArrayString(org.jooq.util.postgres.PostgresUtils.toPGArrayString) Timestamp(java.sql.Timestamp) LocalDate(java.time.LocalDate) Date(java.sql.Date) UNumber(org.jooq.types.UNumber) SQLDialect(org.jooq.SQLDialect) OffsetTime(java.time.OffsetTime) EnumType(org.jooq.EnumType) SimpleDateFormat(java.text.SimpleDateFormat) PostgresUtils.toPGInterval(org.jooq.util.postgres.PostgresUtils.toPGInterval) Interval(org.jooq.types.Interval)

Example 7 with SQLDialect

use of org.jooq.SQLDialect in project jOOQ by jOOQ.

the class DefaultBinding method set.

@SuppressWarnings("unchecked")
@Override
public void set(BindingSetStatementContext<U> ctx) throws SQLException {
    Configuration configuration = ctx.configuration();
    SQLDialect dialect = ctx.dialect();
    T value = converter.to(ctx.value());
    if (log.isTraceEnabled())
        if (value != null && value.getClass().isArray() && value.getClass() != byte[].class)
            log.trace("Binding variable " + ctx.index(), Arrays.asList((Object[]) value) + " (" + type + ")");
        else
            log.trace("Binding variable " + ctx.index(), value + " (" + type + ")");
    // SQL dialect. See the following section for details
    if (value == null) {
        int sqlType = DefaultDataType.getDataType(dialect, type).getSQLType(configuration);
        // [#1126] Oracle's UDTs need to be bound with their type name
        if (UDTRecord.class.isAssignableFrom(type)) {
            ctx.statement().setNull(ctx.index(), sqlType, Tools.getMappedUDTName(configuration, (Class<UDTRecord<?>>) type));
        } else // Some dialects have trouble binding binary data as BLOB
        if (asList(POSTGRES).contains(configuration.family()) && sqlType == Types.BLOB) {
            ctx.statement().setNull(ctx.index(), Types.BINARY);
        } else // All other types can be set to null if the JDBC type is known
        if (sqlType != Types.OTHER) {
            ctx.statement().setNull(ctx.index(), sqlType);
        } else // [#729] In the absence of the correct JDBC type, try setObject
        {
            ctx.statement().setObject(ctx.index(), null);
        }
    } else {
        Class<?> actualType = type;
        // Try to infer the bind value type from the actual bind value if possible.
        if (actualType == Object.class) {
            actualType = value.getClass();
        }
        if (actualType == Blob.class) {
            ctx.statement().setBlob(ctx.index(), (Blob) value);
        } else if (actualType == Boolean.class) {
            ctx.statement().setBoolean(ctx.index(), (Boolean) value);
        } else if (actualType == BigDecimal.class) {
            if (asList(SQLITE).contains(dialect.family())) {
                ctx.statement().setString(ctx.index(), value.toString());
            } else {
                ctx.statement().setBigDecimal(ctx.index(), (BigDecimal) value);
            }
        } else if (actualType == BigInteger.class) {
            if (asList(SQLITE).contains(dialect.family())) {
                ctx.statement().setString(ctx.index(), value.toString());
            } else {
                ctx.statement().setBigDecimal(ctx.index(), new BigDecimal((BigInteger) value));
            }
        } else if (actualType == Byte.class) {
            ctx.statement().setByte(ctx.index(), (Byte) value);
        } else if (actualType == byte[].class) {
            ctx.statement().setBytes(ctx.index(), (byte[]) value);
        } else if (actualType == Clob.class) {
            ctx.statement().setClob(ctx.index(), (Clob) value);
        } else if (actualType == Double.class) {
            ctx.statement().setDouble(ctx.index(), (Double) value);
        } else if (actualType == Float.class) {
            ctx.statement().setFloat(ctx.index(), (Float) value);
        } else if (actualType == Integer.class) {
            ctx.statement().setInt(ctx.index(), (Integer) value);
        } else if (actualType == Long.class) {
            ctx.statement().setLong(ctx.index(), (Long) value);
        } else if (actualType == Short.class) {
            ctx.statement().setShort(ctx.index(), (Short) value);
        } else if (actualType == String.class) {
            ctx.statement().setString(ctx.index(), (String) value);
        } else // -------------------------------------------------------------
        if (Tools.isDate(actualType)) {
            Date date = getDate(actualType, value);
            if (dialect == SQLITE) {
                ctx.statement().setString(ctx.index(), date.toString());
            } else {
                ctx.statement().setDate(ctx.index(), date);
            }
        } else if (Tools.isTime(actualType)) {
            Time time = getTime(actualType, value);
            if (dialect == SQLITE) {
                ctx.statement().setString(ctx.index(), time.toString());
            } else {
                ctx.statement().setTime(ctx.index(), time);
            }
        } else if (Tools.isTimestamp(actualType)) {
            Timestamp timestamp = getTimestamp(actualType, value);
            if (dialect == SQLITE) {
                ctx.statement().setString(ctx.index(), timestamp.toString());
            } else {
                ctx.statement().setTimestamp(ctx.index(), timestamp);
            }
        } else if (actualType == OffsetTime.class) {
            String string = format((OffsetTime) value);
            ctx.statement().setString(ctx.index(), string);
        } else if (actualType == OffsetDateTime.class) {
            ctx.statement().setString(ctx.index(), format((OffsetDateTime) value));
        } else // [#566] Interval data types are best bound as Strings
        if (actualType == YearToMonth.class) {
            if (dialect.family() == POSTGRES) {
                ctx.statement().setObject(ctx.index(), toPGInterval((YearToMonth) value));
            } else {
                ctx.statement().setString(ctx.index(), value.toString());
            }
        } else if (actualType == DayToSecond.class) {
            if (dialect.family() == POSTGRES) {
                ctx.statement().setObject(ctx.index(), toPGInterval((DayToSecond) value));
            } else {
                ctx.statement().setString(ctx.index(), value.toString());
            }
        } else if (actualType == UByte.class) {
            ctx.statement().setShort(ctx.index(), ((UByte) value).shortValue());
        } else if (actualType == UShort.class) {
            ctx.statement().setInt(ctx.index(), ((UShort) value).intValue());
        } else if (actualType == UInteger.class) {
            ctx.statement().setLong(ctx.index(), ((UInteger) value).longValue());
        } else if (actualType == ULong.class) {
            ctx.statement().setBigDecimal(ctx.index(), new BigDecimal(value.toString()));
        } else if (actualType == UUID.class) {
            switch(dialect.family()) {
                // java.util.UUID data type
                case H2:
                case POSTGRES:
                    {
                        ctx.statement().setObject(ctx.index(), value);
                        break;
                    }
                // emulates the type
                default:
                    {
                        ctx.statement().setString(ctx.index(), value.toString());
                        break;
                    }
            }
        } else // The type byte[] is handled earlier. byte[][] can be handled here
        if (actualType.isArray()) {
            switch(dialect.family()) {
                case POSTGRES:
                    {
                        ctx.statement().setString(ctx.index(), toPGArrayString((Object[]) value));
                        break;
                    }
                case HSQLDB:
                    {
                        Object[] a = (Object[]) value;
                        Class<?> t = actualType;
                        // See also: https://sourceforge.net/p/hsqldb/bugs/1466
                        if (actualType == UUID[].class) {
                            a = Convert.convertArray(a, byte[][].class);
                            t = byte[][].class;
                        }
                        ctx.statement().setArray(ctx.index(), new MockArray(dialect, a, t));
                        break;
                    }
                case H2:
                    {
                        ctx.statement().setObject(ctx.index(), value);
                        break;
                    }
                default:
                    throw new SQLDialectNotSupportedException("Cannot bind ARRAY types in dialect " + dialect);
            }
        } else if (EnumType.class.isAssignableFrom(actualType)) {
            ctx.statement().setString(ctx.index(), ((EnumType) value).getLiteral());
        } else {
            ctx.statement().setObject(ctx.index(), value);
        }
    }
}
Also used : Configuration(org.jooq.Configuration) Time(java.sql.Time) LocalTime(java.time.LocalTime) OffsetTime(java.time.OffsetTime) OffsetDateTime(java.time.OffsetDateTime) LocalDateTime(java.time.LocalDateTime) PostgresUtils.toPGArrayString(org.jooq.util.postgres.PostgresUtils.toPGArrayString) Timestamp(java.sql.Timestamp) UUID(java.util.UUID) UShort(org.jooq.types.UShort) SQLDialectNotSupportedException(org.jooq.exception.SQLDialectNotSupportedException) ULong(org.jooq.types.ULong) DayToSecond(org.jooq.types.DayToSecond) UShort(org.jooq.types.UShort) BigDecimal(java.math.BigDecimal) LocalDate(java.time.LocalDate) Date(java.sql.Date) MockArray(org.jooq.tools.jdbc.MockArray) UInteger(org.jooq.types.UInteger) BigInteger(java.math.BigInteger) OffsetDateTime(java.time.OffsetDateTime) SQLDialect(org.jooq.SQLDialect) BigInteger(java.math.BigInteger) YearToMonth(org.jooq.types.YearToMonth)

Example 8 with SQLDialect

use of org.jooq.SQLDialect in project jOOQ by jOOQ.

the class DefaultRenderContext method literal.

@Override
public final RenderContext literal(String literal) {
    // be null for CustomTable et al.
    if (literal == null)
        return this;
    SQLDialect family = family();
    // Quoting is needed when explicitly requested...
    boolean needsQuote = // http://www.sqlite.org/lang_keywords.html for details ...
    (family != SQLITE && QUOTED == cachedRenderNameStyle) || // [#2367] ... yet, do quote when an identifier is a SQLite keyword
    (family == SQLITE && SQLITE_KEYWORDS.contains(literal.toUpperCase())) || // [#1982] [#3360] ... yet, do quote when an identifier contains special characters
    (family == SQLITE && !IDENTIFIER_PATTERN.matcher(literal).matches());
    if (!needsQuote) {
        if (LOWER == cachedRenderNameStyle)
            literal = literal.toLowerCase();
        else if (UPPER == cachedRenderNameStyle)
            literal = literal.toUpperCase();
        sql(literal, true);
    } else {
        String[][] quotes = QUOTES.get(family);
        char start = quotes[QUOTE_START_DELIMITER][0].charAt(0);
        char end = quotes[QUOTE_END_DELIMITER][0].charAt(0);
        sql(start);
        //         situations
        if (literal.indexOf(end) > -1)
            sql(StringUtils.replace(literal, quotes[QUOTE_END_DELIMITER][0], quotes[QUOTE_END_DELIMITER_ESCAPED][0]), true);
        else
            sql(literal, true);
        sql(end);
    }
    return this;
}
Also used : SQLDialect(org.jooq.SQLDialect)

Example 9 with SQLDialect

use of org.jooq.SQLDialect in project jOOQ by jOOQ.

the class CompareCondition method accept.

@Override
public final void accept(Context<?> ctx) {
    SQLDialect family = ctx.family();
    Field<?> lhs = field1;
    Field<?> rhs = field2;
    Comparator op = comparator;
    // [#293] TODO: This could apply to other operators, too
    if ((op == LIKE || op == NOT_LIKE) && field1.getType() != String.class && asList(DERBY, POSTGRES).contains(family)) {
        lhs = lhs.cast(String.class);
    } else // need to emulate this as LOWER(lhs) LIKE LOWER(rhs)
    if ((op == LIKE_IGNORE_CASE || op == NOT_LIKE_IGNORE_CASE) && POSTGRES != family) {
        lhs = lhs.lower();
        rhs = rhs.lower();
        op = (op == LIKE_IGNORE_CASE ? LIKE : NOT_LIKE);
    }
    ctx.visit(lhs).sql(' ');
    boolean castRhs = false;
    ParamType previousParamType = ctx.paramType();
    ParamType forcedParamType = previousParamType;
    ctx.keyword(op.toSQL()).sql(' ');
    if (castRhs)
        ctx.keyword("cast").sql('(');
    ctx.paramType(forcedParamType).visit(rhs).paramType(previousParamType);
    if (castRhs)
        ctx.sql(' ').keyword("as").sql(' ').keyword("varchar").sql("(4000))");
    if (escape != null) {
        ctx.sql(' ').keyword("escape").sql(' ').visit(inline(escape));
    }
}
Also used : SQLDialect(org.jooq.SQLDialect) ParamType(org.jooq.conf.ParamType) Comparator(org.jooq.Comparator)

Example 10 with SQLDialect

use of org.jooq.SQLDialect in project jOOQ by jOOQ.

the class Alias method accept.

@Override
public final void accept(Context<?> context) {
    if (context.declareAliases() && (context.declareFields() || context.declareTables())) {
        context.declareAliases(false);
        SQLDialect family = context.family();
        boolean emulatedDerivedColumnList = false;
        // Hence, wrap the table reference in a subselect
        if (fieldAliases != null && asList(CUBRID, FIREBIRD).contains(family) && (wrapped instanceof TableImpl || wrapped instanceof CommonTableExpressionImpl)) {
            Select<Record> select = select(list(field("*"))).from(((Table<?>) wrapped).as(alias));
            context.sql('(').formatIndentStart().formatNewLine().visit(select).formatIndentEnd().formatNewLine().sql(')');
        } else // results using UNION ALL
        if (fieldAliases != null && asList(H2, MARIADB, MYSQL, SQLITE).contains(family)) {
            emulatedDerivedColumnList = true;
            SelectFieldList fields = new SelectFieldList();
            for (String fieldAlias : fieldAliases) {
                switch(family) {
                    default:
                        {
                            fields.add(field("null").as(fieldAlias));
                            break;
                        }
                }
            }
            Select<Record> select = select(fields).where(falseCondition()).unionAll(// in those derived tables
            wrapped instanceof Select ? (Select<?>) wrapped : wrapped instanceof DerivedTable ? ((DerivedTable<?>) wrapped).query() : select(field("*")).from(((Table<?>) wrapped).as(alias)));
            context.sql('(').formatIndentStart().formatNewLine().visit(select).formatIndentEnd().formatNewLine().sql(')');
        } else // The default behaviour
        {
            toSQLWrapped(context);
        }
        // [#291] some aliases cause trouble, if they are not explicitly marked using "as"
        toSQLAs(context);
        context.sql(' ');
        context.literal(alias);
        // [#1801] Add field aliases to the table alias, if applicable
        if (fieldAliases != null && !emulatedDerivedColumnList) {
            toSQLDerivedColumnList(context);
        } else {
            // TODO: Is this still needed?
            switch(family) {
                case HSQLDB:
                case POSTGRES:
                    {
                        // The javac compiler doesn't like casting of generics
                        Object o = wrapped;
                        if (context.declareTables() && o instanceof ArrayTable) {
                            ArrayTable table = (ArrayTable) o;
                            context.sql('(');
                            Tools.fieldNames(context, table.fields());
                            context.sql(')');
                        }
                        break;
                    }
            }
        }
        context.declareAliases(true);
    } else {
        context.literal(alias);
    }
}
Also used : SQLDialect(org.jooq.SQLDialect) Select(org.jooq.Select) Record(org.jooq.Record)

Aggregations

SQLDialect (org.jooq.SQLDialect)18 Condition (org.jooq.Condition)3 RenderContext (org.jooq.RenderContext)3 PostgresUtils.toPGArrayString (org.jooq.util.postgres.PostgresUtils.toPGArrayString)3 BigDecimal (java.math.BigDecimal)2 Date (java.sql.Date)2 Time (java.sql.Time)2 Timestamp (java.sql.Timestamp)2 LocalDate (java.time.LocalDate)2 LocalDateTime (java.time.LocalDateTime)2 LocalTime (java.time.LocalTime)2 OffsetDateTime (java.time.OffsetDateTime)2 OffsetTime (java.time.OffsetTime)2 ArrayList (java.util.ArrayList)2 Arrays.asList (java.util.Arrays.asList)2 List (java.util.List)2 Comparator (org.jooq.Comparator)2 Configuration (org.jooq.Configuration)2 Select (org.jooq.Select)2 JooqContainer (com.intel.mtwilson.jooq.util.JooqContainer)1