From c24bb0bbfd3817d4bbd31f3f51622fd28b340dd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Westk=C3=A4mper?= Date: Wed, 17 Dec 2014 19:55:51 +0200 Subject: [PATCH] Stubs for DB2 support --- .../test/java/com/mysema/query/Target.java | 4 + querydsl-sql/pom.xml | 10 +- .../com/mysema/query/sql/DB2Templates.java | 143 ++++++++++++++++++ .../java/com/mysema/query/Connections.java | 70 ++++++++- 4 files changed, 224 insertions(+), 3 deletions(-) create mode 100644 querydsl-sql/src/main/java/com/mysema/query/sql/DB2Templates.java diff --git a/querydsl-core/src/test/java/com/mysema/query/Target.java b/querydsl-core/src/test/java/com/mysema/query/Target.java index e727f6436..a6e485d2c 100644 --- a/querydsl-core/src/test/java/com/mysema/query/Target.java +++ b/querydsl-core/src/test/java/com/mysema/query/Target.java @@ -22,6 +22,10 @@ public enum Target{ * CUBRID */ CUBRID, + /** + * DB2 + */ + DB2, /** * Derby */ diff --git a/querydsl-sql/pom.xml b/querydsl-sql/pom.xml index ef6ab8a77..0ef454805 100644 --- a/querydsl-sql/pom.xml +++ b/querydsl-sql/pom.xml @@ -1,4 +1,4 @@ - + 4.0.0 @@ -192,6 +192,12 @@ true + + com.ibm.db2 + db2-jdbc + 1.0 + + @@ -318,4 +324,4 @@ - + diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/DB2Templates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/DB2Templates.java new file mode 100644 index 000000000..241561af0 --- /dev/null +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/DB2Templates.java @@ -0,0 +1,143 @@ +/* + * Copyright 2011, Mysema Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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; + +/** + * DB2Templates is an SQL dialect for DB2 + * + * @author tiwe + * + */ +public class DB2Templates extends SQLTemplates { + + private String limitOffsetTemplate = "\noffset {1s} rows fetch next {0s} rows only"; + + private String limitTemplate = "\nfetch first {0s} rows only"; + + private String offsetTemplate = "\noffset {0s} rows"; + + public static Builder builder() { + return new Builder() { + @Override + protected SQLTemplates build(char escape, boolean quote) { + return new DB2Templates(escape, quote); + } + }; + } + + public DB2Templates() { + this('\\',false); + } + + public DB2Templates(boolean quote) { + this('\\',quote); + } + + public DB2Templates(char escape, boolean quote) { + super("\"", escape, quote); + setDummyTable("sysibm.sysdummy1"); + setAutoIncrement(" generated always as identity"); + setFunctionJoinsWrapped(true); + setDefaultValues("\nvalues (default)"); + + add(Ops.CONCAT, "varchar({0} || {1})"); + add(Ops.DateTimeOps.DAY_OF_MONTH, "day({0})"); + + add(SQLOps.NEXTVAL, "next value for {0s}"); + + // case for eq + add(Ops.CASE_EQ, "case {1} end"); + add(Ops.CASE_EQ_WHEN, "when {0} = {1} then {2} {3}"); + add(Ops.CASE_EQ_ELSE, "else {0}"); + + add(Ops.MathOps.RANDOM, "random()"); + add(Ops.MathOps.ROUND, "floor({0})"); // FIXME + add(Ops.MathOps.POWER, "exp({1} * log({0}))"); + add(Ops.MathOps.LN, "log({0})"); + add(Ops.MathOps.LOG, "(log({0}) / log({1}))"); + add(Ops.MathOps.COTH, "(exp({0} * 2) + 1) / (exp({0} * 2) - 1)"); + + // overrides of the SQL standard functions + add(Ops.DateTimeOps.SECOND, "second({0})"); + add(Ops.DateTimeOps.MINUTE, "minute({0})"); + add(Ops.DateTimeOps.HOUR, "hour({0})"); + add(Ops.DateTimeOps.WEEK, "week({0})"); + add(Ops.DateTimeOps.MONTH, "month({0})"); + add(Ops.DateTimeOps.YEAR, "year({0})"); + add(Ops.DateTimeOps.YEAR_MONTH, "(year({0}) * 100 + month({0}))"); + add(Ops.DateTimeOps.YEAR_WEEK, "(year({0}) * 100 + week({0}))"); + add(Ops.DateTimeOps.DAY_OF_WEEK, "dayofweek({0})"); + add(Ops.DateTimeOps.DAY_OF_MONTH, "day({0})"); + add(Ops.DateTimeOps.DAY_OF_YEAR, "dayofyear({0})"); + + add(Ops.DateTimeOps.ADD_YEARS, "{fn timestampadd(SQL_TSI_YEAR, {1}, {0})}"); + add(Ops.DateTimeOps.ADD_MONTHS, "{fn timestampadd(SQL_TSI_MONTH, {1}, {0})}"); + add(Ops.DateTimeOps.ADD_WEEKS, "{fn timestampadd(SQL_TSI_WEEK, {1}, {0})}"); + add(Ops.DateTimeOps.ADD_DAYS, "{fn timestampadd(SQL_TSI_DAY, {1}, {0})}"); + add(Ops.DateTimeOps.ADD_HOURS, "{fn timestampadd(SQL_TSI_HOUR, {1}, {0})}"); + add(Ops.DateTimeOps.ADD_MINUTES, "{fn timestampadd(SQL_TSI_MINUTE, {1}, {0})}"); + add(Ops.DateTimeOps.ADD_SECONDS, "{fn timestampadd(SQL_TSI_SECOND, {1}, {0})}"); + + add(Ops.DateTimeOps.DIFF_YEARS, "{fn timestampdiff(SQL_TSI_YEAR, {0}, {1})}"); + add(Ops.DateTimeOps.DIFF_MONTHS, "{fn timestampdiff(SQL_TSI_MONTH, {0}, {1})}"); + add(Ops.DateTimeOps.DIFF_WEEKS, "{fn timestampdiff(SQL_TSI_WEEK, {0}, {1})}"); + add(Ops.DateTimeOps.DIFF_DAYS, "{fn timestampdiff(SQL_TSI_DAY, {0}, {1})}"); + add(Ops.DateTimeOps.DIFF_HOURS, "{fn timestampdiff(SQL_TSI_HOUR, {0}, {1})}"); + add(Ops.DateTimeOps.DIFF_MINUTES, "{fn timestampdiff(SQL_TSI_MINUTE, {0}, {1})}"); + add(Ops.DateTimeOps.DIFF_SECONDS, "{fn timestampdiff(SQL_TSI_SECOND, {0}, {1})}"); + + // 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 + public String serialize(String literal, int jdbcType) { + if (jdbcType == Types.TIMESTAMP) { + return "{ts '" + literal + "'}"; + } else if (jdbcType == Types.DATE) { + return "{d '" + literal + "'}"; + } else if (jdbcType == Types.TIME) { + return "{t '" + literal + "'}"; + } else { + return super.serialize(literal, jdbcType); + } + } + + @Override + protected void serializeModifiers(QueryMetadata metadata, SQLSerializer context) { + QueryModifiers mod = metadata.getModifiers(); + if (mod.getLimit() == null) { + context.handle(offsetTemplate, mod.getOffset()); + } else if (mod.getOffset() == null) { + context.handle(limitTemplate, mod.getLimit()); + } else { + context.handle(limitOffsetTemplate, mod.getLimit(), mod.getOffset()); + } + } + +} 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 97b3e405f..66198a00e 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/Connections.java +++ b/querydsl-sql/src/test/java/com/mysema/query/Connections.java @@ -17,11 +17,12 @@ import java.sql.*; import java.util.Map; import java.util.Properties; +import org.hsqldb.types.Types; + import com.google.common.collect.Maps; import com.mysema.query.ddl.CreateTableClause; import com.mysema.query.ddl.DropTableClause; import com.mysema.query.sql.*; -import org.hsqldb.types.Types; /** * @author tiwe @@ -86,6 +87,12 @@ public final class Connections { templatesHolder.set(templates); } + private static Connection getDB2() throws SQLException, ClassNotFoundException { + Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); + String url = "jdbc:derby:target/demoDB;create=true"; + return DriverManager.getConnection(url, "", ""); + } + private static Connection getDerby() throws SQLException, ClassNotFoundException { Class.forName("org.apache.derby.jdbc.EmbeddedDriver"); String url = "jdbc:derby:target/demoDB;create=true"; @@ -294,6 +301,67 @@ public final class Connections { cubridInited = true; } + public static void initDB2() throws SQLException, ClassNotFoundException { + targetHolder.set(Target.DERBY); + SQLTemplates templates = new DerbyTemplates(); + Connection c = getDerby(); + connHolder.set(c); + Statement stmt = c.createStatement(); + stmtHolder.set(stmt); + + if (derbyInited) { + return; + } + + // types + dropType(stmt, "price restrict"); + stmt.execute("create type price external name 'com.example.Price' language java"); + + // survey + dropTable(templates, "SURVEY"); + stmt.execute("create table SURVEY(" + + "ID int generated by default as identity(start with 1, increment by 1), " + + "NAME varchar(30)," + + "NAME2 varchar(30))"); + stmt.execute("insert into SURVEY values (1,'Hello World','Hello')"); + + // test + dropTable(templates, "TEST"); + stmt.execute(CREATE_TABLE_TEST); + stmt.execute("create index test_name on test(name)"); + PreparedStatement pstmt = c.prepareStatement(INSERT_INTO_TEST_VALUES); + try{ + for (int i = 0; i < TEST_ROW_COUNT; i++) { + pstmt.setString(1, "name" + i); + pstmt.addBatch(); + } + pstmt.executeBatch(); + }finally{ + pstmt.close(); + } + + // employee + dropTable(templates, "EMPLOYEE"); + + createEmployeeTable(templates); + + addEmployees(INSERT_INTO_EMPLOYEE); + + // date_test and time_test + dropTable(templates, "TIME_TEST"); + stmt.execute(CREATE_TABLE_TIMETEST); + + dropTable(templates, "DATE_TEST"); + stmt.execute(CREATE_TABLE_DATETEST); + + // xml + dropTable(templates, "XML_TEST"); + stmt.execute("create table XML_TEST(COL varchar(128))"); + + derbyInited = true; + } + + public static void initDerby() throws SQLException, ClassNotFoundException { targetHolder.set(Target.DERBY); SQLTemplates templates = new DerbyTemplates();