
com.blazebit.persistence.impl.dialect.DefaultDbmsDialect Maven / Gradle / Ivy
The newest version!
package com.blazebit.persistence.impl.dialect;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.*;
import java.util.*;
import com.blazebit.persistence.impl.util.SqlUtils;
import com.blazebit.persistence.spi.*;
public class DefaultDbmsDialect implements DbmsDialect {
private final Map, String> sqlTypes;
public DefaultDbmsDialect() {
this(Collections.EMPTY_MAP);
}
public DefaultDbmsDialect(Map, String> childSqlTypes) {
Map, String> types = new HashMap, String>();
types.put(Boolean.class, "boolean");
types.put(Boolean.TYPE, "boolean");
types.put(Byte.class, "tinyint");
types.put(Byte.TYPE, "tinyint");
types.put(Short.class, "smallint");
types.put(Short.TYPE, "smallint");
types.put(Integer.class, "integer");
types.put(Integer.TYPE, "integer");
types.put(Long.class, "bigint");
types.put(Long.TYPE, "bigint");
types.put(Float.class, "float");
types.put(Float.TYPE, "float");
types.put(Double.class, "double precision");
types.put(Double.TYPE, "double precision");
types.put(Character.class, "char");
types.put(Character.TYPE, "char");
types.put(String.class, "varchar");
types.put(BigInteger.class, "bigint");
types.put(BigDecimal.class, "decimal");
types.put(Time.class, "time");
types.put(java.sql.Date.class, "date");
types.put(Timestamp.class, "timestamp");
types.put(java.util.Date.class, "timestamp");
types.put(java.util.Calendar.class, "timestamp");
types.putAll(childSqlTypes);
sqlTypes = Collections.unmodifiableMap(types);
}
@Override
public boolean supportsTupleDistinctCounts() {
return true;
}
@Override
public boolean supportsWithClause() {
return true;
}
@Override
public boolean supportsNonRecursiveWithClause() {
return true;
}
@Override
public boolean supportsJoinsInRecursiveCte() {
return true;
}
@Override
public String getSqlType(Class> castType) {
return sqlTypes.get(castType);
}
@Override
public String getWithClause(boolean recursive) {
if (recursive) {
return "with recursive";
} else {
return "with";
}
}
@Override
public Map appendExtendedSql(StringBuilder sqlSb, DbmsStatementType statementType, boolean isSubquery, boolean isEmbedded, StringBuilder withClause, String limit, String offset, String[] returningColumns, Map includedModificationStates) {
if (isSubquery) {
sqlSb.insert(0, '(');
}
if (withClause != null) {
sqlSb.insert(0, withClause);
}
if (limit != null) {
appendLimit(sqlSb, isSubquery, limit, offset);
}
if (isSubquery && !supportsReturningColumns() && returningColumns != null) {
throw new IllegalArgumentException("Returning columns in a subquery is not possible for this dbms!");
}
if (isSubquery) {
sqlSb.append(')');
}
return null;
}
@Override
public void appendSet(StringBuilder sqlSb, SetOperationType setType, boolean isSubquery, List operands, List extends OrderByElement> orderByElements, String limit, String offset) {
if (isSubquery) {
sqlSb.insert(0, '(');
}
if (operands.size() > 0) {
String operator = getOperator(setType);
boolean hasLimit = limit != null;
boolean hasOrderBy = orderByElements.size() > 0;
boolean hasOuterClause = hasLimit || hasOrderBy;
appendSetOperands(sqlSb, operator, isSubquery, operands, hasOuterClause);
appendOrderBy(sqlSb, orderByElements);
if (limit != null) {
appendLimit(sqlSb, isSubquery, limit, offset);
}
}
if (isSubquery) {
sqlSb.append(')');
}
}
@Override
public DbmsLimitHandler createLimitHandler() {
return new DefaultDbmsLimitHandler();
}
protected void appendSetOperands(StringBuilder sqlSb, String operator, boolean isSubquery, List operands, boolean hasOuterClause) {
boolean first = true;
for (String operand : operands) {
if (first) {
first = false;
} else {
sqlSb.append("\n");
sqlSb.append(operator);
sqlSb.append("\n");
}
sqlSb.append(operand);
}
}
protected void appendOrderBy(StringBuilder sqlSb, List extends OrderByElement> orderByElements) {
if (orderByElements.isEmpty()) {
return;
}
sqlSb.append(" order by ");
boolean first = true;
for (OrderByElement element : orderByElements) {
if (first) {
first = false;
} else {
sqlSb.append(',');
}
appendOrderByElement(sqlSb, element);
}
}
protected void appendOrderByElement(StringBuilder sqlSb, OrderByElement element) {
sqlSb.append(element.getPosition());
if (element.isAscending()) {
sqlSb.append(" asc");
} else {
sqlSb.append(" desc");
}
if (element.isNullsFirst()) {
sqlSb.append(" nulls first");
} else {
sqlSb.append(" nulls last");
}
}
protected void appendEmulatedOrderByElementWithNulls(StringBuilder sqlSb, OrderByElement element) {
sqlSb.append("case when ");
sqlSb.append(element.getPosition());
sqlSb.append(" is null then ");
sqlSb.append(element.isNullsFirst() ? 0 : 1);
sqlSb.append(" else ");
sqlSb.append(element.isNullsFirst() ? 1 : 0);
sqlSb.append(" end, ");
sqlSb.append(element.getPosition());
sqlSb.append(element.isAscending() ? " asc" : " desc");
}
protected String getOperator(SetOperationType type) {
if (type == null) {
return null;
}
switch (type) {
case UNION: return "UNION";
case UNION_ALL: return "UNION ALL";
case INTERSECT: return "INTERSECT";
case INTERSECT_ALL: return "INTERSECT ALL";
case EXCEPT: return "EXCEPT";
case EXCEPT_ALL: return "EXCEPT ALL";
}
return null;
}
@Override
public boolean supportsUnion(boolean all) {
return true;
}
@Override
public boolean supportsIntersect(boolean all) {
// Most dbms don't support intersect all
return !all;
}
@Override
public boolean supportsExcept(boolean all) {
// Most dbms don't support except all
return !all;
}
@Override
public boolean supportsWithClauseInModificationQuery() {
return true;
}
@Override
public boolean supportsModificationQueryInWithClause() {
return false;
}
@Override
public boolean usesExecuteUpdateWhenWithClauseInModificationQuery() {
return true;
}
@Override
public boolean supportsReturningGeneratedKeys() {
return true;
}
@Override
public boolean supportsReturningAllGeneratedKeys() {
return true;
}
@Override
public boolean supportsReturningColumns() {
return false;
}
@Override
public boolean supportsComplexGroupBy() {
return true;
}
@Override
public boolean supportsComplexJoinOn() {
return true;
}
@Override
public ValuesStrategy getValuesStrategy() {
return ValuesStrategy.VALUES;
}
@Override
public boolean needsCastParameters() {
return true;
}
@Override
public String getDummyTable() {
return null;
}
@Override
public String cast(String expression, String sqlType) {
return "cast(" + expression + " as " + sqlType + ")";
}
public void appendLimit(StringBuilder sqlSb, boolean isSubquery, String limit, String offset) {
createLimitHandler().applySql(sqlSb, isSubquery, limit, offset);
}
protected static int indexOfIgnoreCase(StringBuilder haystack, String needle) {
final int endLimit = haystack.length() - needle.length() + 1;
for (int i = 0; i < endLimit; i++) {
if (regionMatchesIgnoreCase(haystack, i, needle, 0, needle.length())) {
return i;
}
}
return -1;
}
protected static boolean regionMatchesIgnoreCase(StringBuilder haystack, int thisStart, String substring, int start, int length) {
int index1 = thisStart;
int index2 = start;
int tmpLen = length;
while (tmpLen-- > 0) {
final char c1 = haystack.charAt(index1++);
final char c2 = substring.charAt(index2++);
if (c1 != c2 && Character.toUpperCase(c1) != Character.toUpperCase(c2) && Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
return false;
}
}
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy