From ed5fec9b659bed5087dc91a84cdcbc91c82e3bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Westk=C3=A4mper?= Date: Sun, 17 Jun 2012 12:15:44 +0300 Subject: [PATCH] #169 fixed UNION and date/time handling for SQLite --- .../java/com/mysema/query/FilterFactory.java | 1 + .../mysema/query/MatchingFiltersFactory.java | 1 + .../com/mysema/query/sql/SQLSerializer.java | 29 +++++++++++-- .../com/mysema/query/sql/SQLiteTemplates.java | 26 +++++------ .../java/com/mysema/query/Connections.java | 4 +- .../query/_sqlite/DeleteSQLiteTest.java | 43 +++++++++++++++++++ .../query/_sqlite/InsertSQLiteTest.java | 43 +++++++++++++++++++ .../query/_sqlite/LikeEscapeSQLiteTest.java | 43 +++++++++++++++++++ .../mysema/query/_sqlite/MergeSQLiteTest.java | 42 ++++++++++++++++++ .../query/_sqlite/SelectSQLiteTest.java | 2 - .../mysema/query/_sqlite/TypesSQLiteTest.java | 20 +++++++++ .../query/_sqlite/UpdateSQLiteTest.java | 43 +++++++++++++++++++ .../query/sql/AbstractSQLTemplatesTest.java | 6 +-- .../mysema/query/sql/OracleTemplatesTest.java | 6 +-- .../query/sql/SQLServerTemplatesTest.java | 6 +-- 15 files changed, 287 insertions(+), 28 deletions(-) create mode 100644 querydsl-sql/src/test/java/com/mysema/query/_sqlite/DeleteSQLiteTest.java create mode 100644 querydsl-sql/src/test/java/com/mysema/query/_sqlite/InsertSQLiteTest.java create mode 100644 querydsl-sql/src/test/java/com/mysema/query/_sqlite/LikeEscapeSQLiteTest.java create mode 100644 querydsl-sql/src/test/java/com/mysema/query/_sqlite/MergeSQLiteTest.java create mode 100644 querydsl-sql/src/test/java/com/mysema/query/_sqlite/TypesSQLiteTest.java create mode 100644 querydsl-sql/src/test/java/com/mysema/query/_sqlite/UpdateSQLiteTest.java diff --git a/querydsl-core/src/test/java/com/mysema/query/FilterFactory.java b/querydsl-core/src/test/java/com/mysema/query/FilterFactory.java index bd94ae3f8..d4620aac6 100644 --- a/querydsl-core/src/test/java/com/mysema/query/FilterFactory.java +++ b/querydsl-core/src/test/java/com/mysema/query/FilterFactory.java @@ -297,6 +297,7 @@ public class FilterFactory { if (!target.equals(Target.DERBY) && !target.equals(Target.HSQLDB) && !target.equals(Target.H2) + && !target.equals(Target.SQLITE) && !target.equals(Target.SQLSERVER)){ rv.add(expr.matches(knownValue.substring(0,1)+".*")); rv.add(expr.matches(".*"+knownValue.substring(1))); diff --git a/querydsl-core/src/test/java/com/mysema/query/MatchingFiltersFactory.java b/querydsl-core/src/test/java/com/mysema/query/MatchingFiltersFactory.java index 0a98670dc..3e5fbb4db 100644 --- a/querydsl-core/src/test/java/com/mysema/query/MatchingFiltersFactory.java +++ b/querydsl-core/src/test/java/com/mysema/query/MatchingFiltersFactory.java @@ -259,6 +259,7 @@ public class MatchingFiltersFactory { || (!target.equals(Target.HSQLDB) && !target.equals(Target.H2) && !target.equals(Target.DERBY) + && !target.equals(Target.SQLITE) && !target.equals(Target.SQLSERVER))){ rv.add(expr.matches(other)); 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 dbdec2e02..a6df1fe5e 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 @@ -43,6 +43,7 @@ import com.mysema.query.types.ParamExpression; import com.mysema.query.types.Path; import com.mysema.query.types.Predicate; import com.mysema.query.types.SubQueryExpression; +import com.mysema.query.types.TemplateExpression; import com.mysema.query.types.TemplateExpressionImpl; /** @@ -97,6 +98,8 @@ public class SQLSerializer extends SerializerBase { private final SQLTemplates templates; + private boolean inUnion = false; + public SQLSerializer(SQLTemplates templates) { this(templates, false, false); } @@ -457,7 +460,10 @@ public class SQLSerializer extends SerializerBase { @SuppressWarnings("unchecked") public void serializeUnion(SubQueryExpression[] sqs, QueryMetadata metadata, boolean unionAll) { // union + boolean oldInUnion = inUnion; + inUnion = true; handle(unionAll ? templates.getUnionAll() : templates.getUnion(), Arrays.asList(sqs)); + inUnion = oldInUnion; // order by if (!metadata.getOrderBy().isEmpty()) { @@ -547,9 +553,26 @@ public class SQLSerializer extends SerializerBase { @Override public Void visit(SubQueryExpression query, Void context) { - append("("); - serialize(query.getMetadata(), false); - append(")"); + if (inUnion) { + serialize(query.getMetadata(), false); + } else { + append("("); + serialize(query.getMetadata(), false); + append(")"); + } + return null; + } + + @Override + public Void visit(TemplateExpression expr, Void context) { + if (expr.getTemplate().toString().toLowerCase().contains("union")) { + boolean oldInUnion = inUnion; + inUnion = true; + super.visit(expr, context); + inUnion = oldInUnion; + } else { + super.visit(expr, context); + } return null; } 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 1fbbb19aa..028e0cd9d 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 @@ -15,7 +15,6 @@ package com.mysema.query.sql; import com.mysema.query.types.Ops; -//work in progress /** * @author tiwe * @@ -38,17 +37,20 @@ public class SQLiteTemplates extends SQLTemplates { add(Ops.INDEX_OF, "charindex({1},{0},1)-1"); add(Ops.INDEX_OF_2ARGS, "charindex({1},{0},{2s}+1)-1"); + + add(Ops.CONCAT, "{0} || {1}"); - add(Ops.DateTimeOps.YEAR, "cast(strftime('%Y',{0},'unixepoch') as integer)"); - add(Ops.DateTimeOps.YEAR_MONTH, "strftime('%Y',{0}) * 100 + strftime('%m',{0})"); - add(Ops.DateTimeOps.MONTH, "cast(strftime('%m',{0},'unixepoch') as integer)"); - add(Ops.DateTimeOps.WEEK, "cast(strftime('%W',{0},'unixepoch') as integer) + 1"); - add(Ops.DateTimeOps.DAY_OF_MONTH, "cast(strftime('%d',{0}) as integer) + 1"); - add(Ops.DateTimeOps.DAY_OF_WEEK, "cast(strftime('%w',{0}) as integer) "); - add(Ops.DateTimeOps.DAY_OF_YEAR, "cast(strftime('%j',{0}) as integer)"); - add(Ops.DateTimeOps.HOUR, "cast(strftime('%H',{0}) as integer)"); - add(Ops.DateTimeOps.MINUTE, "cast(strftime('%M',{0}) as integer)"); - add(Ops.DateTimeOps.SECOND, "cast(strftime('%S',{0}) as integer)"); + // TODO : optimize + add(Ops.DateTimeOps.YEAR, "cast(strftime('%Y',{0} / 1000, 'unixepoch', 'localtime') as integer)"); + add(Ops.DateTimeOps.YEAR_MONTH, "strftime('%Y',{0} / 1000, 'unixepoch', 'localtime') * 100 + strftime('%m',{0} / 1000, 'unixepoch', 'localtime')"); + add(Ops.DateTimeOps.MONTH, "cast(strftime('%m',{0} / 1000, 'unixepoch', 'localtime') as integer)"); + add(Ops.DateTimeOps.WEEK, "cast(strftime('%W',{0} / 1000, 'unixepoch', 'localtime') as integer) + 1"); + add(Ops.DateTimeOps.DAY_OF_MONTH, "cast(strftime('%d',{0} / 1000, 'unixepoch', 'localtime') as integer)"); + add(Ops.DateTimeOps.DAY_OF_WEEK, "cast(strftime('%w',{0} / 1000, 'unixepoch', 'localtime') as integer) + 1"); + add(Ops.DateTimeOps.DAY_OF_YEAR, "cast(strftime('%j',{0} / 1000, 'unixepoch', 'localtime') as integer)"); + add(Ops.DateTimeOps.HOUR, "cast(strftime('%H',{0} / 1000, 'unixepoch', 'localtime') as integer)"); + add(Ops.DateTimeOps.MINUTE, "cast(strftime('%M',{0} / 1000, 'unixepoch', 'localtime') as integer)"); + add(Ops.DateTimeOps.SECOND, "cast(strftime('%S',{0} / 1000, 'unixepoch', 'localtime') as integer)"); } - + } 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 bcb24e6ea..a3cfda4c1 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/Connections.java +++ b/querydsl-sql/src/test/java/com/mysema/query/Connections.java @@ -129,9 +129,9 @@ public final class Connections { } private static Connection getSQLite() throws SQLException, ClassNotFoundException { - System.setProperty("sqlite.purejava", "true"); + //System.setProperty("sqlite.purejava", "true"); Class.forName("org.sqlite.JDBC"); - return DriverManager.getConnection("jdbc:sqlite:"); + return DriverManager.getConnection("jdbc:sqlite:target/sample.db"); } private static CreateTableClause createTable(SQLTemplates templates, String table){ diff --git a/querydsl-sql/src/test/java/com/mysema/query/_sqlite/DeleteSQLiteTest.java b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/DeleteSQLiteTest.java new file mode 100644 index 000000000..0c352df2f --- /dev/null +++ b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/DeleteSQLiteTest.java @@ -0,0 +1,43 @@ +/* + * 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._sqlite; + +import java.sql.SQLException; + +import org.junit.Before; +import org.junit.BeforeClass; + +import com.mysema.query.Connections; +import com.mysema.query.DeleteBaseTest; +import com.mysema.query.Target; +import com.mysema.query.sql.SQLiteTemplates; +import com.mysema.testutil.Label; + +@Label(Target.SQLITE) +public class DeleteSQLiteTest extends DeleteBaseTest{ + + @BeforeClass + public static void setUpClass() throws Exception { + Connections.initSQLite(); + } + + @Before + public void setUp() throws SQLException { + templates = new SQLiteTemplates(){{ + newLineToSingleSpace(); + }}; + super.setUp(); + } + +} diff --git a/querydsl-sql/src/test/java/com/mysema/query/_sqlite/InsertSQLiteTest.java b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/InsertSQLiteTest.java new file mode 100644 index 000000000..f4cf1e527 --- /dev/null +++ b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/InsertSQLiteTest.java @@ -0,0 +1,43 @@ +/* + * 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._sqlite; + +import java.sql.SQLException; + +import org.junit.Before; +import org.junit.BeforeClass; + +import com.mysema.query.Connections; +import com.mysema.query.InsertBaseTest; +import com.mysema.query.Target; +import com.mysema.query.sql.SQLiteTemplates; +import com.mysema.testutil.Label; + +@Label(Target.SQLITE) +public class InsertSQLiteTest extends InsertBaseTest{ + + @BeforeClass + public static void setUpClass() throws Exception { + Connections.initSQLite(); + } + + @Before + public void setUp() throws SQLException { + templates = new SQLiteTemplates(){{ + newLineToSingleSpace(); + }}; + super.setUp(); + } + +} diff --git a/querydsl-sql/src/test/java/com/mysema/query/_sqlite/LikeEscapeSQLiteTest.java b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/LikeEscapeSQLiteTest.java new file mode 100644 index 000000000..f85c6eb68 --- /dev/null +++ b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/LikeEscapeSQLiteTest.java @@ -0,0 +1,43 @@ +/* + * 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._sqlite; + +import java.sql.SQLException; + +import org.junit.Before; +import org.junit.BeforeClass; + +import com.mysema.query.Connections; +import com.mysema.query.LikeEscapeBaseTest; +import com.mysema.query.Target; +import com.mysema.query.sql.SQLiteTemplates; +import com.mysema.testutil.Label; + +@Label(Target.SQLITE) +public class LikeEscapeSQLiteTest extends LikeEscapeBaseTest{ + + @BeforeClass + public static void setUpClass() throws Exception { + Connections.initSQLite(); + } + + @Before + public void setUp() throws SQLException { + templates = new SQLiteTemplates('!', false){{ + newLineToSingleSpace(); + }}; + super.setUp(); + } + +} diff --git a/querydsl-sql/src/test/java/com/mysema/query/_sqlite/MergeSQLiteTest.java b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/MergeSQLiteTest.java new file mode 100644 index 000000000..f0aa2a963 --- /dev/null +++ b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/MergeSQLiteTest.java @@ -0,0 +1,42 @@ +/* + * 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._sqlite; + +import java.sql.SQLException; + +import org.junit.Before; +import org.junit.BeforeClass; + +import com.mysema.query.Connections; +import com.mysema.query.MergeBaseTest; +import com.mysema.query.Target; +import com.mysema.query.sql.SQLiteTemplates; +import com.mysema.testutil.Label; + +@Label(Target.SQLITE) +public class MergeSQLiteTest extends MergeBaseTest{ + + @BeforeClass + public static void setUpClass() throws Exception { + Connections.initSQLite(); + } + + @Before + public void setUp() throws SQLException { + templates = new SQLiteTemplates(){{ + newLineToSingleSpace(); + }}; + super.setUp(); + } +} diff --git a/querydsl-sql/src/test/java/com/mysema/query/_sqlite/SelectSQLiteTest.java b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/SelectSQLiteTest.java index 972d1b45e..356291e1b 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/_sqlite/SelectSQLiteTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/SelectSQLiteTest.java @@ -17,7 +17,6 @@ import static com.mysema.query.Constants.employee; import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import com.mysema.query.Connections; @@ -27,7 +26,6 @@ import com.mysema.query.sql.SQLQuery; import com.mysema.query.sql.SQLiteTemplates; import com.mysema.testutil.Label; -@Ignore // work in progress @Label(Target.SQLITE) public class SelectSQLiteTest extends SelectBaseTest { diff --git a/querydsl-sql/src/test/java/com/mysema/query/_sqlite/TypesSQLiteTest.java b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/TypesSQLiteTest.java new file mode 100644 index 000000000..8484da1cc --- /dev/null +++ b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/TypesSQLiteTest.java @@ -0,0 +1,20 @@ +package com.mysema.query._sqlite; + +import org.junit.BeforeClass; + +import com.mysema.query.Connections; +import com.mysema.query.Target; +import com.mysema.query.TypesBaseTest; +import com.mysema.testutil.Label; + +@Label(Target.SQLITE) +public class TypesSQLiteTest extends TypesBaseTest { + + // not supported + + @BeforeClass + public static void setUpClass() throws Exception { + Connections.initSQLite(); + } + +} diff --git a/querydsl-sql/src/test/java/com/mysema/query/_sqlite/UpdateSQLiteTest.java b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/UpdateSQLiteTest.java new file mode 100644 index 000000000..5ea1f3f5c --- /dev/null +++ b/querydsl-sql/src/test/java/com/mysema/query/_sqlite/UpdateSQLiteTest.java @@ -0,0 +1,43 @@ +/* + * 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._sqlite; + +import java.sql.SQLException; + +import org.junit.Before; +import org.junit.BeforeClass; + +import com.mysema.query.Connections; +import com.mysema.query.Target; +import com.mysema.query.UpdateBaseTest; +import com.mysema.query.sql.SQLiteTemplates; +import com.mysema.testutil.Label; + +@Label(Target.SQLITE) +public class UpdateSQLiteTest extends UpdateBaseTest{ + + @BeforeClass + public static void setUpClass() throws Exception { + Connections.initSQLite(); + } + + @Before + public void setUp() throws SQLException { + templates = new SQLiteTemplates(){{ + newLineToSingleSpace(); + }}; + super.setUp(); + } + +} diff --git a/querydsl-sql/src/test/java/com/mysema/query/sql/AbstractSQLTemplatesTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/AbstractSQLTemplatesTest.java index 0f9073248..269e207fe 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/sql/AbstractSQLTemplatesTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/AbstractSQLTemplatesTest.java @@ -59,11 +59,11 @@ public abstract class AbstractSQLTemplatesTest { sq().unique(two), sq().unique(three)); assertEquals( - "(select 1 as col1 from dual) " + + "select 1 as col1 from dual " + "union " + - "(select 2 from dual) " + + "select 2 from dual " + "union " + - "(select 3 from dual)", union.toString()); + "select 3 from dual", union.toString()); } @Test diff --git a/querydsl-sql/src/test/java/com/mysema/query/sql/OracleTemplatesTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/OracleTemplatesTest.java index 4acacb32f..4c1611985 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/sql/OracleTemplatesTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/OracleTemplatesTest.java @@ -45,11 +45,11 @@ public class OracleTemplatesTest extends AbstractSQLTemplatesTest{ sq().unique(two), sq().unique(three)); assertEquals( - "(select 1 col1 from dual) " + + "select 1 col1 from dual " + "union " + - "(select 2 from dual) " + + "select 2 from dual " + "union " + - "(select 3 from dual)", union.toString()); + "select 3 from dual", union.toString()); } @Test diff --git a/querydsl-sql/src/test/java/com/mysema/query/sql/SQLServerTemplatesTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/SQLServerTemplatesTest.java index 3425ef5bf..57d329de5 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/sql/SQLServerTemplatesTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/SQLServerTemplatesTest.java @@ -53,11 +53,11 @@ public class SQLServerTemplatesTest extends AbstractSQLTemplatesTest{ sq().unique(two), sq().unique(three)); assertEquals( - "(select 1 as col1) " + + "select 1 as col1 " + "union " + - "(select 2) " + + "select 2 " + "union " + - "(select 3)", union.toString()); + "select 3", union.toString()); } @Test