From a01a8d52ceccf78231e8a418c16107195fff6753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Westk=C3=A4mper?= Date: Sun, 17 Aug 2014 23:56:21 +0300 Subject: [PATCH] Add typename mappings --- .../com/mysema/query/sql/Configuration.java | 58 +++++----- .../com/mysema/query/sql/DerbyTemplates.java | 13 ++- .../mysema/query/sql/FirebirdTemplates.java | 11 +- .../com/mysema/query/sql/H2Templates.java | 8 ++ .../com/mysema/query/sql/HSQLDBTemplates.java | 16 ++- .../com/mysema/query/sql/MySQLTemplates.java | 52 +++++++-- .../com/mysema/query/sql/OracleTemplates.java | 31 ++++-- .../mysema/query/sql/PostgresTemplates.java | 22 +++- .../com/mysema/query/sql/SQLSerializer.java | 4 +- .../mysema/query/sql/SQLServerTemplates.java | 29 ++++- .../com/mysema/query/sql/SQLTemplates.java | 102 +++++++++++------- .../com/mysema/query/sql/SQLiteTemplates.java | 6 +- .../mysema/query/sql/TeradataTemplates.java | 4 - .../java/com/mysema/query/Connections.java | 4 +- .../mysema/query/ddl/CreateTableClause.java | 16 +-- .../com/mysema/query/ddl/DropTableClause.java | 6 +- .../java/com/mysema/query/sql/TypesDump.java | 48 +++++++++ 17 files changed, 313 insertions(+), 117 deletions(-) create mode 100644 querydsl-sql/src/test/java/com/mysema/query/sql/TypesDump.java diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/Configuration.java b/querydsl-sql/src/main/java/com/mysema/query/sql/Configuration.java index 3baf596aa..b2f54d639 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/Configuration.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/Configuration.java @@ -13,8 +13,8 @@ */ package com.mysema.query.sql; +import javax.annotation.Nullable; import java.lang.reflect.Array; -import java.lang.reflect.Field; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -23,8 +23,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.annotation.Nullable; - import com.google.common.collect.Maps; import com.mysema.query.sql.types.Null; import com.mysema.query.sql.types.Type; @@ -40,22 +38,6 @@ public final class Configuration { public static final Configuration DEFAULT = new Configuration(SQLTemplates.DEFAULT); - private static final Map typeConstants = Maps.newHashMap(); - - static { - try { - for (Field field : java.sql.Types.class.getDeclaredFields()) { - if (field.getType().equals(Integer.TYPE)) { - typeConstants.put(field.getName().toLowerCase(), field.getInt(null)); - } - } - typeConstants.put("int4", Types.INTEGER); - typeConstants.put("int8", Types.BIGINT); - } catch (IllegalAccessException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - private final JDBCTypeMapping jdbcTypeMapping = new JDBCTypeMapping(); private final JavaTypeMapping javaTypeMapping = new JavaTypeMapping(); @@ -154,12 +136,14 @@ public final class Configuration { return clazz; } if (sqlType == Types.ARRAY) { - for (Map.Entry entry : typeConstants.entrySet()) { - if (typeName.toLowerCase().contains(entry.getKey())) { - Class componentType = jdbcTypeMapping.get(entry.getValue(), size, digits); - return Array.newInstance(componentType, 0).getClass(); - } + if (typeName.startsWith("_")) { + typeName = typeName.substring(1); + } else if (typeName.endsWith(" array")) { + typeName = typeName.substring(0, typeName.length() - 6); } + int sqlComponentType = templates.getCodeForTypeName(typeName); + Class componentType = jdbcTypeMapping.get(sqlComponentType, size, digits); + return Array.newInstance(componentType, 0).getClass(); } } // sql type mapped class @@ -206,8 +190,7 @@ public final class Configuration { /** * Get the schema/table override * - * @param schema - * @param table + * @param key * @return */ @Nullable @@ -290,6 +273,27 @@ public final class Configuration { return javaTypeMapping.getType(clazz); } + /** + * Get the SQL type name for the given java type + * + * @param type + * @return + */ + public String getTypeName(Class type) { + int jdbcType = jdbcTypeMapping.get(type); + return templates.getTypeNameForCode(jdbcType); + } + + /** + * + * @param type + * @return + */ + public String getTypeNameForCast(Class type) { + int jdbcType = jdbcTypeMapping.get(type); + return templates.getCastTypeNameForCode(jdbcType); + } + /** * Register a schema override * @@ -478,7 +482,7 @@ public final class Configuration { } /** - * @param listeners + * @param listener */ public void addListener(SQLListener listener) { listeners.add(listener); diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/DerbyTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/DerbyTemplates.java index 17c53fd73..30bdb54a0 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/DerbyTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/DerbyTemplates.java @@ -13,12 +13,12 @@ */ package com.mysema.query.sql; +import java.sql.Types; + import com.mysema.query.QueryMetadata; import com.mysema.query.QueryModifiers; import com.mysema.query.types.Ops; -import java.sql.Types; - /** * DerbyTemplates is an SQL dialect for Derby * @@ -53,7 +53,6 @@ public class DerbyTemplates extends SQLTemplates { public DerbyTemplates(char escape, boolean quote) { super("\"", escape, quote); setDummyTable("sysibm.sysdummy1"); - addClass2TypeMappings("smallint", Byte.class); setAutoIncrement(" generated always as identity"); setFunctionJoinsWrapped(true); setDefaultValues("\nvalues (default)"); @@ -106,6 +105,14 @@ public class DerbyTemplates extends SQLTemplates { // left via substr add(Ops.StringOps.LEFT, "substr({0},1,{1})"); + + addTypeNameToCode("smallint", Types.TINYINT, true); + addTypeNameToCode("long varchar for bit data", Types.LONGVARBINARY); + addTypeNameToCode("varchar () for bit data", Types.VARBINARY); + addTypeNameToCode("char () for bit data", Types.BINARY); + addTypeNameToCode("long varchar", Types.LONGVARCHAR, true); + addTypeNameToCode("object", Types.JAVA_OBJECT, true); + addTypeNameToCode("xml", Types.SQLXML,true); } @Override diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/FirebirdTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/FirebirdTemplates.java index e3f6201a5..56c1c830a 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/FirebirdTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/FirebirdTemplates.java @@ -1,5 +1,7 @@ package com.mysema.query.sql; +import java.sql.Types; + import com.mysema.query.QueryMetadata; import com.mysema.query.QueryModifiers; import com.mysema.query.types.Ops; @@ -34,9 +36,6 @@ public class FirebirdTemplates extends SQLTemplates { setDummyTable("RDB$DATABASE"); setUnionsWrapped(false); setWrapSelectParameters(true); - addClass2TypeMappings("smallint", Boolean.class, Byte.class); - addClass2TypeMappings("varchar(256)", String.class); - addClass2TypeMappings("double precision", Double.class); // string add(Ops.CHAR_AT, "cast(substring({0} from {1s}+1 for 1) as char)"); @@ -86,6 +85,12 @@ public class FirebirdTemplates extends SQLTemplates { add(Ops.DateTimeOps.DIFF_HOURS, "datediff(hour,{0},{1})"); add(Ops.DateTimeOps.DIFF_MINUTES, "datediff(minute,{0},{1})"); add(Ops.DateTimeOps.DIFF_SECONDS, "datediff(second,{0},{1})"); + + addTypeNameToCode("blob sub_type 0", Types.LONGVARBINARY); + addTypeNameToCode("blob sub_type 1", Types.LONGVARCHAR); + addTypeNameToCode("double precision", Types.DOUBLE); + addTypeNameToCode("array", Types.OTHER); + addTypeNameToCode("blob sub_type <0 ", Types.BLOB); } @Override diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/H2Templates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/H2Templates.java index 9e72a896f..39e2bfece 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/H2Templates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/H2Templates.java @@ -13,6 +13,8 @@ */ package com.mysema.query.sql; +import java.sql.Types; + import com.mysema.query.types.Ops; /** @@ -56,6 +58,12 @@ public class H2Templates extends SQLTemplates { add(Ops.MathOps.COTH, "(cosh({0}) / sinh({0}))"); add(Ops.DateTimeOps.DATE, "convert({0}, date)"); + + addTypeNameToCode("result_set", -10); + addTypeNameToCode("identity", Types.BIGINT); + addTypeNameToCode("uuid", Types.BINARY); + addTypeNameToCode("serial", Types.INTEGER); + addTypeNameToCode("varchar_ignorecase", Types.VARCHAR); } } diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/HSQLDBTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/HSQLDBTemplates.java index c164e75f0..e71bb0a51 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/HSQLDBTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/HSQLDBTemplates.java @@ -13,6 +13,8 @@ */ package com.mysema.query.sql; +import java.sql.Types; + import com.mysema.query.types.Ops; /** @@ -78,11 +80,19 @@ public class HSQLDBTemplates extends SQLTemplates { add(Ops.DateTimeOps.DIFF_SECONDS, "datediff('ss', {0}, {1})"); add(Ops.DateTimeOps.DATE, "convert({0}, date)"); + + addTypeNameToCode("character", Types.CHAR, true); + addTypeNameToCode("float", Types.DOUBLE, true); + addTypeNameToCode("real", Types.DOUBLE); + addTypeNameToCode("nvarchar", Types.VARCHAR); } - @Override - public String getTypeForCast(Class cl) { - return (cl.equals(String.class)) ? "varchar(10)" : getTypeForClass(cl); + public String getCastTypeNameForCode(int code) { + if (code == Types.VARCHAR) { + return "varchar(10)"; + } else { + return super.getCastTypeNameForCode(code); + } } } diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/MySQLTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/MySQLTemplates.java index c16652b37..509e89de2 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/MySQLTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/MySQLTemplates.java @@ -13,7 +13,7 @@ */ package com.mysema.query.sql; -import java.math.BigDecimal; +import java.sql.Types; import com.mysema.query.types.Ops; @@ -51,14 +51,6 @@ public class MySQLTemplates extends SQLTemplates { setNullsFirst(null); setNullsLast(null); - addClass2TypeMappings("bool", Boolean.class); - addClass2TypeMappings("signed", - Byte.class, Short.class, Integer.class, Long.class); - - addClass2TypeMappings("decimal", - Double.class, Float.class, BigDecimal.class); - addClass2TypeMappings("char", String.class); - add(Ops.CONCAT, "concat({0}, {1})",0); add(Ops.StringOps.LPAD, "lpad({0},{1},' ')"); @@ -104,6 +96,32 @@ public class MySQLTemplates extends SQLTemplates { add(Ops.DateTimeOps.DIFF_HOURS, "timestampdiff(hour,{0},{1})"); add(Ops.DateTimeOps.DIFF_MINUTES, "timestampdiff(minute,{0},{1})"); add(Ops.DateTimeOps.DIFF_SECONDS, "timestampdiff(second,{0},{1})"); + + addTypeNameToCode("bool", Types.BIT, true); + addTypeNameToCode("tinyint unsigned", Types.TINYINT); + addTypeNameToCode("bigint unsigned", Types.BIGINT); + addTypeNameToCode("long varbinary", Types.LONGVARBINARY, true); + addTypeNameToCode("mediumblob", Types.LONGVARBINARY); + addTypeNameToCode("longblob", Types.LONGVARBINARY); + addTypeNameToCode("blob", Types.LONGVARBINARY); + addTypeNameToCode("tinyblob", Types.LONGVARBINARY); + addTypeNameToCode("long varchar", Types.LONGVARCHAR, true); + addTypeNameToCode("mediumtext", Types.LONGVARCHAR); + addTypeNameToCode("longtext", Types.LONGVARCHAR); + addTypeNameToCode("text", Types.LONGVARCHAR); + addTypeNameToCode("tinytext", Types.LONGVARCHAR); + addTypeNameToCode("integer unsigned", Types.INTEGER); + addTypeNameToCode("int", Types.INTEGER); + addTypeNameToCode("int unsigned", Types.INTEGER); + addTypeNameToCode("mediumint", Types.INTEGER); + addTypeNameToCode("mediumint unsigned", Types.INTEGER); + addTypeNameToCode("smallint unsigned", Types.SMALLINT); + addTypeNameToCode("float", Types.REAL, true); + addTypeNameToCode("double precision", Types.DOUBLE, true); + addTypeNameToCode("real", Types.DOUBLE); + addTypeNameToCode("enum", Types.VARCHAR); + addTypeNameToCode("set", Types.VARCHAR); + addTypeNameToCode("datetime", Types.TIMESTAMP, true); } @Override @@ -118,4 +136,20 @@ public class MySQLTemplates extends SQLTemplates { return builder.toString(); } + + public String getCastTypeNameForCode(int code) { + switch (code) { + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + case Types.BIGINT: return "signed"; + case Types.FLOAT: + case Types.DOUBLE: + case Types.REAL: + case Types.DECIMAL: return "decimal"; + case Types.VARCHAR: return "char"; + default: return super.getCastTypeNameForCode(code); + } + } + } diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/OracleTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/OracleTemplates.java index 693b8813f..8007246f0 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/OracleTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/OracleTemplates.java @@ -13,7 +13,6 @@ */ package com.mysema.query.sql; -import java.math.BigInteger; import java.sql.Types; import java.util.List; @@ -70,15 +69,6 @@ public class OracleTemplates extends SQLTemplates { setWithRecursive("with "); setCountViaAnalytics(true); - // type mappings - addClass2TypeMappings("number(3,0)", Byte.class); - addClass2TypeMappings("number(1,0)", Boolean.class); - addClass2TypeMappings("number(19,0)", BigInteger.class, Long.class); - addClass2TypeMappings("number(5,0)", Short.class); - addClass2TypeMappings("number(10,0)", Integer.class); - addClass2TypeMappings("double precision", Double.class); - addClass2TypeMappings("varchar(4000 char)", String.class); - add(Ops.ALIAS, "{0} {1}"); add(SQLOps.NEXTVAL, "{0s}.nextval"); @@ -132,6 +122,27 @@ public class OracleTemplates extends SQLTemplates { add(Ops.DateTimeOps.TRUNC_HOUR, "trunc({0}, 'hh')"); add(Ops.DateTimeOps.TRUNC_MINUTE, "trunc({0}, 'mi')"); add(Ops.DateTimeOps.TRUNC_SECOND, "{0}"); // not truncated + + addTypeNameToCode("intervalds", -104); + addTypeNameToCode("intervalym", -103); + addTypeNameToCode("timestamp with local time zone", -102); + addTypeNameToCode("timestamp with time zone", -101); + addTypeNameToCode("long raw", Types.LONGVARBINARY); + addTypeNameToCode("raw", Types.VARBINARY); + addTypeNameToCode("long", Types.LONGVARCHAR); + addTypeNameToCode("varchar2", Types.VARCHAR); + } + + public String getCastTypeNameForCode(int code) { + switch (code) { + case Types.TINYINT: return "number(3,0)"; + case Types.SMALLINT: return "number(5,0)"; + case Types.INTEGER: return "number(10,0)"; + case Types.BIGINT: return "number(19,0)"; + case Types.DOUBLE: return "double precision"; + case Types.VARCHAR: return "varchar(4000 char)"; + default: return super.getCastTypeNameForCode(code); + } } @Override diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/PostgresTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/PostgresTemplates.java index 2c06685ae..9c0ec661b 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/PostgresTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/PostgresTemplates.java @@ -13,6 +13,8 @@ */ package com.mysema.query.sql; +import java.sql.Types; + import com.mysema.query.types.Ops; /** @@ -49,9 +51,6 @@ public class PostgresTemplates extends SQLTemplates { setCountViaAnalytics(true); setDefaultValues("\ndefault values"); - addClass2TypeMappings("numeric(3,0)", Byte.class); - addClass2TypeMappings("double precision", Double.class); - // String add(Ops.MATCHES, "{0} ~ {1}"); add(Ops.INDEX_OF, "strpos({0},{1})-1"); @@ -110,6 +109,23 @@ public class PostgresTemplates extends SQLTemplates { add(Ops.DateTimeOps.DIFF_HOURS, hoursDiff); add(Ops.DateTimeOps.DIFF_MINUTES, minutesDiff); add(Ops.DateTimeOps.DIFF_SECONDS, secondsDiff); + + addTypeNameToCode("bool", Types.BIT, true); + addTypeNameToCode("bytea", Types.BINARY); + addTypeNameToCode("name", Types.VARCHAR); + addTypeNameToCode("int8", Types.BIGINT, true); + addTypeNameToCode("bigserial", Types.BIGINT); + addTypeNameToCode("int2", Types.TINYINT, true); + addTypeNameToCode("int2", Types.SMALLINT, true); + addTypeNameToCode("int4", Types.INTEGER, true); + addTypeNameToCode("serial", Types.INTEGER); + addTypeNameToCode("text", Types.VARCHAR); + addTypeNameToCode("oid", Types.BIGINT); + addTypeNameToCode("xml", Types.SQLXML, true); + addTypeNameToCode("float4", Types.REAL, true); + addTypeNameToCode("float8", Types.DOUBLE, true); + addTypeNameToCode("bpchar", Types.CHAR); + addTypeNameToCode("timestamptz", Types.TIMESTAMP); } } diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLSerializer.java b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLSerializer.java index e1e59f136..1fa3e1b41 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLSerializer.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLSerializer.java @@ -853,13 +853,13 @@ public class SQLSerializer extends SerializerBase { ImmutableList.of(args.get(0), ConstantImpl.create(escaped))); } else if (operator == Ops.STRING_CAST) { - final String typeName = templates.getTypeForCast(String.class); + final String typeName = configuration.getTypeNameForCast(String.class); super.visitOperation(String.class, SQLOps.CAST, ImmutableList.of(args.get(0), ConstantImpl.create(typeName))); } else if (operator == Ops.NUMCAST) { final Class targetType = (Class) ((Constant) args.get(1)).getConstant(); - final String typeName = templates.getTypeForCast(targetType); + final String typeName = configuration.getTypeNameForCast(targetType); super.visitOperation(targetType, SQLOps.CAST, ImmutableList.of(args.get(0), ConstantImpl.create(typeName))); diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLServerTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLServerTemplates.java index c18577a67..9bafdc99a 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLServerTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLServerTemplates.java @@ -51,7 +51,6 @@ public class SQLServerTemplates extends SQLTemplates { public SQLServerTemplates(char escape, boolean quote) { super("\"", escape, quote); - addClass2TypeMappings("decimal", Double.class); setDummyTable(""); setNullsFirst(null); setNullsLast(null); @@ -114,6 +113,34 @@ public class SQLServerTemplates extends SQLTemplates { add(Ops.DateTimeOps.DATE, "cast({0} as date)"); add(Ops.DateTimeOps.CURRENT_DATE, "cast(getdate() as date)"); + + addTypeNameToCode("decimal", Types.DOUBLE, true); + addTypeNameToCode("tinyint identity", Types.TINYINT); + addTypeNameToCode("bigint identity", Types.BIGINT); + addTypeNameToCode("timestamp", Types.BINARY); + addTypeNameToCode("nchar", Types.CHAR); + addTypeNameToCode("uniqueidentifier", Types.CHAR); + addTypeNameToCode("numeric() identity", Types.NUMERIC); + addTypeNameToCode("money", Types.DECIMAL); + addTypeNameToCode("smallmoney", Types.DECIMAL); + addTypeNameToCode("decimal() identity", Types.DECIMAL); + addTypeNameToCode("int", Types.INTEGER); + addTypeNameToCode("int identity", Types.INTEGER); + addTypeNameToCode("smallint identity", Types.SMALLINT); + addTypeNameToCode("float", Types.DOUBLE); + addTypeNameToCode("nvarchar", Types.VARCHAR); + addTypeNameToCode("date", Types.VARCHAR); + addTypeNameToCode("time", Types.VARCHAR); + addTypeNameToCode("datetime2", Types.VARCHAR); + addTypeNameToCode("datetimeoffset", Types.VARCHAR); + addTypeNameToCode("sysname", Types.VARCHAR); + addTypeNameToCode("sql_variant", Types.VARCHAR); + addTypeNameToCode("datetime", Types.TIMESTAMP); + addTypeNameToCode("smalldatetime", Types.TIMESTAMP); + addTypeNameToCode("image", Types.BLOB); + addTypeNameToCode("ntext", Types.CLOB); + addTypeNameToCode("xml", Types.CLOB); + addTypeNameToCode("text", Types.CLOB); } @Override diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLTemplates.java index 9605c2052..c53a2c4b2 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLTemplates.java @@ -14,17 +14,13 @@ package com.mysema.query.sql; import java.lang.reflect.Field; -import java.math.BigDecimal; -import java.math.BigInteger; import java.sql.Types; import java.util.Arrays; import java.util.List; -import java.util.Locale; import java.util.Map; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.primitives.Primitives; import com.mysema.commons.lang.Pair; import com.mysema.query.JoinType; import com.mysema.query.QueryException; @@ -33,10 +29,6 @@ import com.mysema.query.QueryMetadata; import com.mysema.query.QueryModifiers; import com.mysema.query.sql.types.Type; import com.mysema.query.types.*; -import org.joda.time.DateTime; -import org.joda.time.LocalDate; -import org.joda.time.LocalDateTime; -import org.joda.time.LocalTime; /** * SQLTemplates extends Templates to provides SQL specific extensions @@ -89,7 +81,9 @@ public class SQLTemplates extends Templates { } - private final Map, String> class2type = Maps.newHashMap(); + private final Map typeNameToCode = Maps.newHashMap(); + + private final Map codeToTypeName = Maps.newHashMap(); private final Map tableOverrides = Maps.newHashMap(); @@ -342,27 +336,43 @@ public class SQLTemplates extends Templates { add(Ops.AggOps.BOOLEAN_ANY, "some({0})"); add(Ops.AggOps.BOOLEAN_ALL, "every({0})"); - for (Class cl : new Class[] { Boolean.class, Byte.class, - Double.class, Float.class, Integer.class, Long.class, - Short.class, String.class }) { - class2type.put(cl, cl.getSimpleName().toLowerCase(Locale.ENGLISH)); - } - - class2type.put(Boolean.class, "bit"); - class2type.put(Byte.class, "tinyint"); - class2type.put(Long.class, "bigint"); - class2type.put(BigInteger.class, "bigint"); - class2type.put(BigDecimal.class, "decimal"); - class2type.put(Short.class, "smallint"); - class2type.put(String.class, "varchar"); - class2type.put(java.sql.Date.class, "date"); - class2type.put(java.sql.Time.class, "time"); - class2type.put(java.sql.Timestamp.class, "timestamp"); - - class2type.put(LocalDateTime.class, "timestamp"); - class2type.put(LocalDate.class, "date"); - class2type.put(LocalTime.class, "time"); - class2type.put(DateTime.class, "timestamp"); + // default type names + addTypeNameToCode("null", Types.NULL); + addTypeNameToCode("char", Types.CHAR); + addTypeNameToCode("datalink", Types.DATALINK); + addTypeNameToCode("numeric", Types.NUMERIC); + addTypeNameToCode("decimal", Types.DECIMAL); + addTypeNameToCode("integer", Types.INTEGER); + addTypeNameToCode("smallint", Types.SMALLINT); + addTypeNameToCode("float", Types.FLOAT); + addTypeNameToCode("real", Types.REAL); + addTypeNameToCode("double", Types.DOUBLE); + addTypeNameToCode("varchar", Types.VARCHAR); + addTypeNameToCode("longnvarchar", Types.LONGNVARCHAR); + addTypeNameToCode("nchar", Types.NCHAR); + addTypeNameToCode("boolean", Types.BOOLEAN); + addTypeNameToCode("nvarchar", Types.NVARCHAR); + addTypeNameToCode("rowid", Types.ROWID); + addTypeNameToCode("timestamp", Types.TIMESTAMP); + addTypeNameToCode("bit", Types.BIT); + addTypeNameToCode("time", Types.TIME); + addTypeNameToCode("tinyint", Types.TINYINT); + addTypeNameToCode("other", Types.OTHER); + addTypeNameToCode("bigint", Types.BIGINT); + addTypeNameToCode("longvarbinary", Types.LONGVARBINARY); + addTypeNameToCode("varbinary", Types.VARBINARY); + addTypeNameToCode("date", Types.DATE); + addTypeNameToCode("binary", Types.BINARY); + addTypeNameToCode("longvarchar", Types.LONGVARCHAR); + addTypeNameToCode("struct", Types.STRUCT); + addTypeNameToCode("array", Types.ARRAY); + addTypeNameToCode("java_object", Types.JAVA_OBJECT); + addTypeNameToCode("distinct", Types.DISTINCT); + addTypeNameToCode("ref", Types.REF); + addTypeNameToCode("blob", Types.BLOB); + addTypeNameToCode("clob", Types.CLOB); + addTypeNameToCode("nclob", Types.NCLOB); + addTypeNameToCode("sqlxml", Types.SQLXML); } public String serialize(String literal, int jdbcType) { @@ -405,12 +415,17 @@ public class SQLTemplates extends Templates { return builder.toString(); } - protected void addClass2TypeMappings(String type, Class... classes) { - for (Class cl : classes) { - class2type.put(cl, type); + protected void addTypeNameToCode(String type, int code, boolean override) { + typeNameToCode.put(type, code); + if (override || !codeToTypeName.containsKey(code)) { + codeToTypeName.put(code, type); } } + protected void addTypeNameToCode(String type, int code) { + addTypeNameToCode(type, code, false); + } + protected void add(Map, String> ops) { for (Map.Entry, String> entry : ops.entrySet()) { add(entry.getKey(), entry.getValue()); @@ -568,17 +583,26 @@ public class SQLTemplates extends Templates { return tableOverrides; } + @Deprecated public String getTypeForCast(Class cl) { return getTypeForClass(cl); } + @Deprecated public String getTypeForClass(Class cl) { - Class clazz = Primitives.wrap(cl); - if (class2type.containsKey(clazz)) { - return class2type.get(clazz); - } else { - throw new IllegalArgumentException("Got no type for " + clazz.getName()); - } + throw new UnsupportedOperationException(); + } + + public String getTypeNameForCode(int code) { + return codeToTypeName.get(code); + } + + public String getCastTypeNameForCode(int code) { + return getTypeNameForCode(code); + } + + public int getCodeForTypeName(String type) { + return typeNameToCode.get(type); } public final String getUpdate() { diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLiteTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLiteTemplates.java index 9c612a0ae..40e035dcc 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLiteTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLiteTemplates.java @@ -13,13 +13,13 @@ */ package com.mysema.query.sql; +import java.sql.Types; + import com.mysema.query.sql.types.BigDecimalAsDoubleType; import com.mysema.query.types.Ops; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; -import java.sql.Types; - /** * SQLiteTemplates is a SQL dialect for SQLite * @@ -94,6 +94,8 @@ public class SQLiteTemplates extends SQLTemplates { add(Ops.MathOps.RANDOM2, "random({0})"); add(Ops.MathOps.LN, "log({0})"); add(Ops.MathOps.LOG, "(log({0}) / log({1}))"); + + addTypeNameToCode("text", Types.VARCHAR); } @Override diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/TeradataTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/TeradataTemplates.java index 17217e9fe..19938823b 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/TeradataTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/TeradataTemplates.java @@ -59,10 +59,6 @@ public class TeradataTemplates extends SQLTemplates { setCountViaAnalytics(true); setDefaultValues("\ndefault values"); - addClass2TypeMappings("byteint", Byte.class); - addClass2TypeMappings("double precision", Double.class); - addClass2TypeMappings("varchar(4000)", String.class); - add(Ops.NE, "{0} <> {1}"); // String diff --git a/querydsl-sql/src/test/java/com/mysema/query/Connections.java b/querydsl-sql/src/test/java/com/mysema/query/Connections.java index 28055ce18..0c8a3f12a 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/Connections.java +++ b/querydsl-sql/src/test/java/com/mysema/query/Connections.java @@ -157,11 +157,11 @@ public final class Connections { } private static CreateTableClause createTable(SQLTemplates templates, String table) { - return new CreateTableClause(connHolder.get(), templates, table); + return new CreateTableClause(connHolder.get(), new Configuration(templates), table); } public static void dropTable(SQLTemplates templates, String table) throws SQLException{ - new DropTableClause(connHolder.get(), templates, table).execute(); + new DropTableClause(connHolder.get(), new Configuration(templates), table).execute(); } public static void dropType(Statement stmt, String type) throws SQLException { diff --git a/querydsl-sql/src/test/java/com/mysema/query/ddl/CreateTableClause.java b/querydsl-sql/src/test/java/com/mysema/query/ddl/CreateTableClause.java index 1a7844b9f..05f00f176 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/ddl/CreateTableClause.java +++ b/querydsl-sql/src/test/java/com/mysema/query/ddl/CreateTableClause.java @@ -11,12 +11,12 @@ import java.sql.Statement; import java.util.ArrayList; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.google.common.base.Joiner; import com.mysema.query.QueryException; +import com.mysema.query.sql.Configuration; import com.mysema.query.sql.SQLTemplates; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * CreateTableClause defines a CREATE TABLE clause @@ -32,6 +32,8 @@ public class CreateTableClause { private final Connection connection; + private final Configuration configuration; + private final SQLTemplates templates; private final String table; @@ -44,9 +46,10 @@ public class CreateTableClause { private final List foreignKeys = new ArrayList(); - public CreateTableClause(Connection conn, SQLTemplates templates, String table) { + public CreateTableClause(Connection conn, Configuration c, String table) { this.connection = conn; - this.templates = templates; + this.configuration = c; + this.templates = c.getTemplates(); this.table = templates.quoteIdentifier(table); } @@ -58,7 +61,8 @@ public class CreateTableClause { * @return */ public CreateTableClause column(String name, Class type) { - columns.add(new ColumnData(templates.quoteIdentifier(name), templates.getTypeForClass(type))); + String typeName = configuration.getTypeName(type); + columns.add(new ColumnData(templates.quoteIdentifier(name), typeName)); return this; } diff --git a/querydsl-sql/src/test/java/com/mysema/query/ddl/DropTableClause.java b/querydsl-sql/src/test/java/com/mysema/query/ddl/DropTableClause.java index e7f8d1c34..746f882c5 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/ddl/DropTableClause.java +++ b/querydsl-sql/src/test/java/com/mysema/query/ddl/DropTableClause.java @@ -10,7 +10,7 @@ import java.sql.SQLException; import java.sql.Statement; import com.mysema.query.QueryException; -import com.mysema.query.sql.SQLTemplates; +import com.mysema.query.sql.Configuration; /** * DropTableClause defines a DROP TABLE clause @@ -24,9 +24,9 @@ public class DropTableClause { private final String table; - public DropTableClause(Connection conn, SQLTemplates templates, String table) { + public DropTableClause(Connection conn, Configuration c, String table) { this.connection = conn; - this.table = templates.quoteIdentifier(table); + this.table = c.getTemplates().quoteIdentifier(table); } @SuppressWarnings("SQL_NONCONSTANT_STRING_PASSED_TO_EXECUTE") diff --git a/querydsl-sql/src/test/java/com/mysema/query/sql/TypesDump.java b/querydsl-sql/src/test/java/com/mysema/query/sql/TypesDump.java new file mode 100644 index 000000000..6225dda9e --- /dev/null +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/TypesDump.java @@ -0,0 +1,48 @@ +package com.mysema.query.sql; + +import java.lang.reflect.Field; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.util.Map; + +import com.google.common.collect.Maps; +import com.mysema.query.Connections; + +public class TypesDump { + + public static void main(String[] args) throws Exception { + Map typeConstants = Maps.newHashMap(); + for (Field field : java.sql.Types.class.getDeclaredFields()) { + if (field.getType().equals(Integer.TYPE)) { + typeConstants.put(field.getInt(null), field.getName()); + } + } + + Connections.initSQLServer(); + try { + Connection c = Connections.getConnection(); + DatabaseMetaData m = c.getMetaData(); + ResultSet rs = m.getTypeInfo(); + try { + while (rs.next()) { + String name = rs.getString("TYPE_NAME"); + int jdbcType = rs.getInt("DATA_TYPE"); + String jdbcTypeField = typeConstants.get(jdbcType); + if (jdbcTypeField == null || !jdbcTypeField.equalsIgnoreCase(name)) { + String prefix = rs.getString("LITERAL_PREFIX"); + String suffix = rs.getString("LITERAL_SUFFIX"); + String jdbcTypeStr = jdbcTypeField != null ? ("Types." + jdbcTypeField) : String.valueOf(jdbcType); + System.out.println("addTypeNameToCode(\"" + name.toLowerCase() + "\", " + jdbcTypeStr + ");"); + } + } + } finally { + rs.close(); + } + } finally { + Connections.close(); + } + + } + +}