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