[jOOQ/jOOQ#9540] SQL Server NVARCHAR literal is not rendered correctly

This includes:

- [jOOQ/jOOQ#10368] Add DataType.isNString()
This commit is contained in:
Lukas Eder 2020-07-08 13:05:46 +02:00
parent d33bac8efb
commit b244dfca54
3 changed files with 123 additions and 3 deletions

View File

@ -640,6 +640,19 @@ public interface DataType<T> extends Named {
*/
boolean isString();
/**
* Whether this data type is any national character data type.
* <p>
* This applies to any of these types:
* <ul>
* <li> {@link SQLDataType#LONGNVARCHAR}</li>
* <li> {@link SQLDataType#NCHAR}</li>
* <li> {@link SQLDataType#NCLOB}</li>
* <li> {@link SQLDataType#NVARCHAR}</li>
* </ul>
*/
boolean isNString();
/**
* Whether this data type is any date or time type.
* <p>

View File

@ -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<T> extends AbstractNamed implements DataType<T>
// 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<T> extends AbstractNamed implements DataType<T>
return tType0() == String.class;
}
@Override
public final boolean isNString() {
DataType<T> 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<T> extends AbstractNamed implements DataType<T>
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

View File

@ -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<T, U> implements Binding<T, U> {
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<T, U> implements Binding<T, U> {
}
}
static final class DefaultNStringBinding<U> extends AbstractBinding<String, U> {
/**
* Generated UID
*/
private static final long serialVersionUID = 4232459541239942932L;
DefaultNStringBinding(DataType<String> dataType, Converter<String, U> converter) {
super(dataType, converter);
}
@Override
void sqlInline0(BindingSQLContext<U> ctx, String value) throws SQLException {
ctx.render().sql('N');
super.sqlInline0(ctx, value);
}
@Override
final void set0(BindingSetStatementContext<U> ctx, String value) throws SQLException {
ctx.statement().setNString(ctx.index(), value);
}
@Override
final void set0(BindingSetSQLOutputContext<U> ctx, String value) throws SQLException {
ctx.output().writeNString(value);
}
@Override
final String get0(BindingGetResultSetContext<U> ctx) throws SQLException {
return ctx.resultSet().getNString(ctx.index());
}
@Override
final String get0(BindingGetStatementContext<U> ctx) throws SQLException {
return ctx.statement().getNString(ctx.index());
}
@Override
final String get0(BindingGetSQLInputContext<U> ctx) throws SQLException {
return ctx.input().readNString();
}
@Override
final int sqltype(Statement statement, Configuration configuration) {
return Types.NVARCHAR;
}
}
static final class DefaultTimeBinding<U> extends AbstractBinding<Time, U> {
/**