diff --git a/jOOQ/src/main/java/org/jooq/DataType.java b/jOOQ/src/main/java/org/jooq/DataType.java index 45c4e5ed0e..c8dea96d32 100644 --- a/jOOQ/src/main/java/org/jooq/DataType.java +++ b/jOOQ/src/main/java/org/jooq/DataType.java @@ -640,6 +640,19 @@ public interface DataType extends Named { */ boolean isString(); + /** + * Whether this data type is any national character data type. + *

+ * This applies to any of these types: + *

+ */ + boolean isNString(); + /** * Whether this data type is any date or time type. *

diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java index 74cdc760c0..195a33a534 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java @@ -42,7 +42,9 @@ import static org.jooq.SQLDialect.DERBY; import static org.jooq.impl.DSL.unquotedName; import static org.jooq.impl.SQLDataType.BLOB; import static org.jooq.impl.SQLDataType.CLOB; +import static org.jooq.impl.SQLDataType.NCHAR; import static org.jooq.impl.SQLDataType.NCLOB; +import static org.jooq.impl.SQLDataType.NVARCHAR; import java.lang.reflect.Array; import java.math.BigDecimal; @@ -445,7 +447,7 @@ abstract class AbstractDataType extends AbstractNamed implements DataType // precision support in DDL. if (isTimestamp() && NO_SUPPORT_TIMESTAMP_PRECISION.contains(dialect)) return castTypePrefix0() + castTypeSuffix0(); - else if (scaleDefined()) + else if (scaleDefined() && scale() > 0) return castTypePrefix0() + "(" + precision() + ", " + scale() + ")" + castTypeSuffix0(); else return castTypePrefix0() + "(" + precision() + ")" + castTypeSuffix0(); @@ -553,6 +555,19 @@ abstract class AbstractDataType extends AbstractNamed implements DataType return tType0() == String.class; } + @Override + public final boolean isNString() { + DataType t = getSQLDataType(); + return t == NCHAR + || t == NCLOB + || t == NVARCHAR + + // [#9540] [#10368] In case the constant literals haven't been initialised yet + || NCHAR == null && "nchar".equals(t.getTypeName()) + || NCLOB == null && "nclob".equals(t.getTypeName()) + || NVARCHAR == null && "nvarchar".equals(t.getTypeName()); + } + @Override public final boolean isDateTime() { Class tType = tType0(); @@ -610,7 +625,14 @@ abstract class AbstractDataType extends AbstractNamed implements DataType if (t == this) return getTypeName().endsWith("lob"); else - return (t == BLOB || t == CLOB || t == NCLOB); + return t == BLOB + || t == CLOB + || t == NCLOB + + // [#9540] [#10368] In case the constant literals haven't been initialised yet + || BLOB == null && "blob".equals(t.getTypeName()) + || CLOB == null && "clob".equals(t.getTypeName()) + || NCLOB == null && "nclob".equals(t.getTypeName()); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index 2fb5066a60..1f29362d8e 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java @@ -130,6 +130,7 @@ import java.sql.Blob; import java.sql.Clob; import java.sql.Connection; import java.sql.Date; +import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -308,7 +309,10 @@ public class DefaultBinding implements Binding { else if (type == Short.class || type == short.class) return new DefaultShortBinding(dataType, converter); else if (type == String.class) - return new DefaultStringBinding(dataType, converter); + if (dataType.isNString()) + return new DefaultNStringBinding(dataType, converter); + else + return new DefaultStringBinding(dataType, converter); else if (type == Time.class) return new DefaultTimeBinding(dataType, converter); else if (type == Timestamp.class) @@ -3743,6 +3747,87 @@ public class DefaultBinding implements Binding { } } + static final class DefaultNStringBinding extends AbstractBinding { + + /** + * Generated UID + */ + private static final long serialVersionUID = 4232459541239942932L; + + DefaultNStringBinding(DataType dataType, Converter converter) { + super(dataType, converter); + } + + @Override + void sqlInline0(BindingSQLContext ctx, String value) throws SQLException { + ctx.render().sql('N'); + + super.sqlInline0(ctx, value); + } + + @Override + final void set0(BindingSetStatementContext ctx, String value) throws SQLException { + ctx.statement().setNString(ctx.index(), value); + } + + @Override + final void set0(BindingSetSQLOutputContext ctx, String value) throws SQLException { + + + + + + + + + + + + + + + + + + + + + + + + + + ctx.output().writeNString(value); + } + + @Override + final String get0(BindingGetResultSetContext ctx) throws SQLException { + return ctx.resultSet().getNString(ctx.index()); + } + + @Override + final String get0(BindingGetStatementContext ctx) throws SQLException { + return ctx.statement().getNString(ctx.index()); + } + + @Override + final String get0(BindingGetSQLInputContext ctx) throws SQLException { + return ctx.input().readNString(); + } + + @Override + final int sqltype(Statement statement, Configuration configuration) { + + + + + + + + return Types.NVARCHAR; + } + } + static final class DefaultTimeBinding extends AbstractBinding { /**