Determine ansinull setting for Sybase ASE and implement proper comparison handling when it is off
This commit is contained in:
parent
c71171a762
commit
9e4e9ce0d5
|
@ -3103,6 +3103,10 @@ public abstract class Dialect implements ConversionContext {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAnsiNullOn() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders an ordering fragment
|
* Renders an ordering fragment
|
||||||
*
|
*
|
||||||
|
|
|
@ -16,6 +16,6 @@ package org.hibernate.dialect;
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class Sybase11Dialect extends SybaseASEDialect {
|
public class Sybase11Dialect extends SybaseASEDialect {
|
||||||
public Sybase11Dialect() {
|
public Sybase11Dialect() {
|
||||||
super( 1100, false );
|
super( 1100, false, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ package org.hibernate.dialect;
|
||||||
public class SybaseASE157Dialect extends SybaseASEDialect {
|
public class SybaseASE157Dialect extends SybaseASEDialect {
|
||||||
|
|
||||||
public SybaseASE157Dialect() {
|
public SybaseASE157Dialect() {
|
||||||
super( 1570, false );
|
super( 1570, false, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ package org.hibernate.dialect;
|
||||||
public class SybaseASE15Dialect extends SybaseASEDialect {
|
public class SybaseASE15Dialect extends SybaseASEDialect {
|
||||||
|
|
||||||
public SybaseASE15Dialect() {
|
public SybaseASE15Dialect() {
|
||||||
super( 1500, false );
|
super( 1500, false, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -48,21 +51,23 @@ import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtract
|
||||||
public class SybaseASEDialect extends SybaseDialect {
|
public class SybaseASEDialect extends SybaseDialect {
|
||||||
|
|
||||||
private final SizeStrategy sizeStrategy;
|
private final SizeStrategy sizeStrategy;
|
||||||
|
private final boolean ansiNull;
|
||||||
|
|
||||||
public SybaseASEDialect() {
|
public SybaseASEDialect() {
|
||||||
this( 1100, false );
|
this( 1100, false, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
public SybaseASEDialect(DialectResolutionInfo info) {
|
public SybaseASEDialect(DialectResolutionInfo info) {
|
||||||
this(
|
this(
|
||||||
info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10,
|
info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10,
|
||||||
info.getDriverName() != null && info.getDriverName().contains( "jTDS" )
|
info.getDriverName() != null && info.getDriverName().contains( "jTDS" ),
|
||||||
|
isAnsiNull( info.unwrap( DatabaseMetaData.class ) )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SybaseASEDialect(int version, boolean jtdsDriver) {
|
public SybaseASEDialect(int version, boolean jtdsDriver, boolean ansiNull) {
|
||||||
super( version, jtdsDriver );
|
super( version, jtdsDriver );
|
||||||
|
this.ansiNull = ansiNull;
|
||||||
//On Sybase ASE, the 'bit' type cannot be null,
|
//On Sybase ASE, the 'bit' type cannot be null,
|
||||||
//and cannot have indexes (while we don't use
|
//and cannot have indexes (while we don't use
|
||||||
//tinyint to store signed bytes, we can use it
|
//tinyint to store signed bytes, we can use it
|
||||||
|
@ -121,6 +126,28 @@ public class SybaseASEDialect extends SybaseDialect {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isAnsiNull(DatabaseMetaData databaseMetaData) {
|
||||||
|
if ( databaseMetaData != null ) {
|
||||||
|
try (java.sql.Statement s = databaseMetaData.getConnection().createStatement() ) {
|
||||||
|
final ResultSet rs = s.executeQuery( "SELECT @@options" );
|
||||||
|
if ( rs.next() ) {
|
||||||
|
final byte[] optionBytes = rs.getBytes( 1 );
|
||||||
|
// By trial and error, enabling and disabling ansinull revealed that this bit is the indicator
|
||||||
|
return ( optionBytes[4] & 2 ) == 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SQLException ex) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAnsiNullOn() {
|
||||||
|
return ansiNull;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDoublePrecision() {
|
public int getDoublePrecision() {
|
||||||
return 48;
|
return 48;
|
||||||
|
|
|
@ -19,7 +19,9 @@ import org.hibernate.sql.ast.tree.Statement;
|
||||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||||
|
import org.hibernate.sql.ast.tree.expression.NullnessLiteral;
|
||||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
@ -152,11 +154,28 @@ public class SybaseASESqlAstTranslator<T extends JdbcOperation> extends Abstract
|
||||||
@Override
|
@Override
|
||||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||||
// I think intersect is only supported in 16.0 SP3
|
// I think intersect is only supported in 16.0 SP3
|
||||||
// renderComparisonEmulateIntersect( lhs, operator, rhs );
|
if ( getDialect().isAnsiNullOn() ) {
|
||||||
|
if ( getDialect().getVersion() >= 1630 ) {
|
||||||
|
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
renderComparisonEmulateCase( lhs, operator, rhs );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// The ansinull setting only matters if using a parameter or literal and the eq operator according to the docs
|
||||||
|
// http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc32300.1570/html/sqlug/sqlug89.htm
|
||||||
|
boolean rhsNotNullPredicate =
|
||||||
|
lhs instanceof NullnessLiteral
|
||||||
|
|| lhs instanceof Literal
|
||||||
|
|| lhs instanceof JdbcParameter;
|
||||||
|
boolean lhsNotNullPredicate =
|
||||||
|
rhs instanceof NullnessLiteral
|
||||||
|
|| rhs instanceof Literal
|
||||||
|
|| rhs instanceof JdbcParameter;
|
||||||
|
if ( rhsNotNullPredicate || lhsNotNullPredicate ) {
|
||||||
lhs.accept( this );
|
lhs.accept( this );
|
||||||
appendSql( " " );
|
appendSql( " " );
|
||||||
// This relies on the fact that Sybase usually is configured with ANSINULLS OFF
|
|
||||||
switch ( operator ) {
|
switch ( operator ) {
|
||||||
case DISTINCT_FROM:
|
case DISTINCT_FROM:
|
||||||
appendSql( "<>" );
|
appendSql( "<>" );
|
||||||
|
@ -164,12 +183,39 @@ public class SybaseASESqlAstTranslator<T extends JdbcOperation> extends Abstract
|
||||||
case NOT_DISTINCT_FROM:
|
case NOT_DISTINCT_FROM:
|
||||||
appendSql( '=' );
|
appendSql( '=' );
|
||||||
break;
|
break;
|
||||||
|
case LESS_THAN:
|
||||||
|
case GREATER_THAN:
|
||||||
|
case LESS_THAN_OR_EQUAL:
|
||||||
|
case GREATER_THAN_OR_EQUAL:
|
||||||
|
// These operators are not affected by ansinull=off
|
||||||
|
lhsNotNullPredicate = false;
|
||||||
|
rhsNotNullPredicate = false;
|
||||||
default:
|
default:
|
||||||
appendSql( operator.sqlText() );
|
appendSql( operator.sqlText() );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
appendSql( " " );
|
appendSql( " " );
|
||||||
rhs.accept( this );
|
rhs.accept( this );
|
||||||
|
if ( lhsNotNullPredicate ) {
|
||||||
|
appendSql( " and " );
|
||||||
|
lhs.accept( this );
|
||||||
|
appendSql( " is not null" );
|
||||||
|
}
|
||||||
|
if ( rhsNotNullPredicate ) {
|
||||||
|
appendSql( " and " );
|
||||||
|
rhs.accept( this );
|
||||||
|
appendSql( " is not null" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( getDialect().getVersion() >= 1630 ) {
|
||||||
|
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
renderComparisonEmulateCase( lhs, operator, rhs );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1994,6 +1994,40 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void renderComparisonEmulateCase(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||||
|
switch ( operator ) {
|
||||||
|
case DISTINCT_FROM:
|
||||||
|
appendSql( "case when " );
|
||||||
|
lhs.accept( this );
|
||||||
|
appendSql( " = " );
|
||||||
|
rhs.accept( this );
|
||||||
|
appendSql( " or " );
|
||||||
|
lhs.accept( this );
|
||||||
|
appendSql( " is null and " );
|
||||||
|
rhs.accept( this );
|
||||||
|
appendSql( " is null then 0 else 1 end = 1" );
|
||||||
|
break;
|
||||||
|
case NOT_DISTINCT_FROM:
|
||||||
|
appendSql( "case when " );
|
||||||
|
lhs.accept( this );
|
||||||
|
appendSql( " = " );
|
||||||
|
rhs.accept( this );
|
||||||
|
appendSql( " or " );
|
||||||
|
lhs.accept( this );
|
||||||
|
appendSql( " is null and " );
|
||||||
|
rhs.accept( this );
|
||||||
|
appendSql( " is null then 0 else 1 end = 0" );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
lhs.accept( this );
|
||||||
|
appendSql( ' ' );
|
||||||
|
appendSql( operator.sqlText() );
|
||||||
|
appendSql( ' ' );
|
||||||
|
rhs.accept( this );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void renderComparisonEmulateIntersect(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
protected void renderComparisonEmulateIntersect(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||||
switch ( operator ) {
|
switch ( operator ) {
|
||||||
case DISTINCT_FROM:
|
case DISTINCT_FROM:
|
||||||
|
|
Loading…
Reference in New Issue