Repository: cayenne Updated Branches: refs/heads/master e56a93f4f -> 05a772502
http://git-wip-us.apache.org/repos/asf/cayenne/blob/05a77250/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTCurrentTimestampTest.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTCurrentTimestampTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTCurrentTimestampTest.java new file mode 100644 index 0000000..7b5fd0d --- /dev/null +++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTCurrentTimestampTest.java @@ -0,0 +1,54 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.cayenne.exp.parser; + +import java.util.Date; + +import org.apache.cayenne.exp.Expression; +import org.apache.cayenne.exp.ExpressionFactory; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @since 4.0 + */ +public class ASTCurrentTimestampTest { + + @Test + public void testParse() { + Expression exp2 = ExpressionFactory.exp("currentTimestamp()"); + assertTrue(exp2 instanceof ASTCurrentTimestamp); + + Expression exp3 = ExpressionFactory.exp("now()"); + assertTrue(exp3 instanceof ASTCurrentTimestamp); + + assertEquals("currentTimestamp()", exp2.toString()); + assertEquals("currentTimestamp()", exp3.toString()); + } + + @Test + public void testEvaluate() { + Expression exp = new ASTCurrentTimestamp(); + Object result = exp.evaluate(new Object()); + assertTrue(result instanceof Date); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/05a77250/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTExtractIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTExtractIT.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTExtractIT.java new file mode 100644 index 0000000..7ebbfba --- /dev/null +++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTExtractIT.java @@ -0,0 +1,240 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.cayenne.exp.parser; + +import java.util.Calendar; +import java.util.List; + +import org.apache.cayenne.CayenneRuntimeException; +import org.apache.cayenne.ObjectContext; +import org.apache.cayenne.di.Inject; +import org.apache.cayenne.exp.Expression; +import org.apache.cayenne.exp.ExpressionFactory; +import org.apache.cayenne.exp.FunctionExpressionFactory; +import org.apache.cayenne.exp.Property; +import org.apache.cayenne.query.ObjectSelect; +import org.apache.cayenne.test.jdbc.DBHelper; +import org.apache.cayenne.testdo.date_time.DateTestEntity; +import org.apache.cayenne.unit.UnitDbAdapter; +import org.apache.cayenne.unit.di.server.CayenneProjects; +import org.apache.cayenne.unit.di.server.ServerCase; +import org.apache.cayenne.unit.di.server.UseServerRuntime; +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @since 4.0 + */ +@UseServerRuntime(CayenneProjects.DATE_TIME_PROJECT) +public class ASTExtractIT extends ServerCase { + + @Inject + private ObjectContext context; + + @Inject + private DBHelper dbHelper; + + @Inject + private UnitDbAdapter unitDbAdapter; + + @Before + public void createDataSet() throws Exception { + Calendar cal = Calendar.getInstance(); + cal.set(Calendar.MILLISECOND, 0); + + DateTestEntity o1 = context.newObject(DateTestEntity.class); + cal.set(2015, Calendar.FEBRUARY, 28, + 0, 0, 0); + o1.setDateColumn(cal.getTime()); + + cal.set(2017, Calendar.MARCH, 30, + 0, 0, 0); + o1.setTimeColumn(cal.getTime()); + + cal.set(Calendar.DAY_OF_MONTH, 29); + o1.setTimestampColumn(cal.getTime()); + + DateTestEntity o2 = context.newObject(DateTestEntity.class); + cal.set(2016, Calendar.MARCH, 29, + 0, 0, 0); + o2.setDateColumn(cal.getTime()); + + cal.set(2017, Calendar.APRIL, 1, + 23, 59, 39); + o2.setTimeColumn(cal.getTime()); + + cal.set(Calendar.DAY_OF_MONTH, 2); + o2.setTimestampColumn(cal.getTime()); + + context.commitChanges(); + } + + + @Test + public void testYear() { + Expression exp = ExpressionFactory.exp("year(dateColumn) = 2015"); + + try { + long res = ObjectSelect.query(DateTestEntity.class, exp).selectCount(context); + assertEquals(1, res); + } catch (CayenneRuntimeException e) { + if(unitDbAdapter.supportsExtractPart(ASTExtract.DateTimePart.YEAR)) { + throw e; + } // else ok + } + } + + @Test + public void testMonth() { + Expression exp = ExpressionFactory.exp("month(dateColumn) = 3"); + + try { + long res = ObjectSelect.query(DateTestEntity.class, exp).selectCount(context); + assertEquals(1, res); + } catch (CayenneRuntimeException e) { + if(unitDbAdapter.supportsExtractPart(ASTExtract.DateTimePart.MONTH)) { + throw e; + } // else ok + } + } + + @Test + public void testWeek() { + // 13 or 14 depends of first day in week in current db + Expression exp = ExpressionFactory.exp("week(dateColumn) in (13, 14)"); + try { + long res = ObjectSelect.query(DateTestEntity.class, exp).selectCount(context); + assertEquals(1, res); + } catch (CayenneRuntimeException e) { + if(unitDbAdapter.supportsExtractPart(ASTExtract.DateTimePart.WEEK)) { + throw e; + } // else ok + } + } + + @Test + public void testDayOfYear() { + // day can start from 0 + Expression exp = ExpressionFactory.exp("dayOfYear(dateColumn) in (59, 58)"); + try { + long res = ObjectSelect.query(DateTestEntity.class, exp).selectCount(context); + assertEquals(1, res); + } catch (CayenneRuntimeException e) { + if(unitDbAdapter.supportsExtractPart(ASTExtract.DateTimePart.DAY_OF_YEAR)) { + throw e; + } // else ok + } + } + + @Test + public void testDayOfYearSelect() { + Property<Integer> dayOfYear = Property.create( + FunctionExpressionFactory.yearExp(DateTestEntity.DATE_COLUMN.path()), Integer.class); + + try { + List<Integer> res = ObjectSelect.query(DateTestEntity.class).column(dayOfYear).select(context); + assertEquals(2, res.size()); + } catch (CayenneRuntimeException e) { + if(unitDbAdapter.supportsExtractPart(ASTExtract.DateTimePart.DAY_OF_YEAR)) { + throw e; + } // else ok + } + } + + @Test + public void testDay() { + Expression exp = ExpressionFactory.exp("day(dateColumn) = 28"); + try { + long res = ObjectSelect.query(DateTestEntity.class, exp).selectCount(context); + assertEquals(1, res); + } catch (CayenneRuntimeException e) { + if(unitDbAdapter.supportsExtractPart(ASTExtract.DateTimePart.DAY)) { + throw e; + } // else ok + } + } + + @Test + public void testDayOfMonth() { + Expression exp = ExpressionFactory.exp("dayOfMonth(dateColumn) = 28"); + try { + long res = ObjectSelect.query(DateTestEntity.class, exp).selectCount(context); + assertEquals(1, res); + } catch (CayenneRuntimeException e) { + if(unitDbAdapter.supportsExtractPart(ASTExtract.DateTimePart.DAY_OF_MONTH)) { + throw e; + } // else ok + } + } + + @Test + public void testDayOfWeek() { + Expression exp = ExpressionFactory.exp("dayOfWeek(dateColumn) in (2, 3)"); + try { + long res = ObjectSelect.query(DateTestEntity.class, exp).selectCount(context); + assertEquals(1, res); + } catch (CayenneRuntimeException e) { + if(unitDbAdapter.supportsExtractPart(ASTExtract.DateTimePart.DAY_OF_WEEK)) { + throw e; + } + } + } + + @Test + public void testHour() { + Expression exp = ExpressionFactory.exp("hour(timestampColumn) = 23"); + try { + long res = ObjectSelect.query(DateTestEntity.class, exp).selectCount(context); + assertEquals(1, res); + } catch (CayenneRuntimeException e) { + if(unitDbAdapter.supportsExtractPart(ASTExtract.DateTimePart.HOUR)) { + throw e; + } // else ok + } + } + + @Test + public void testMinute() { + Expression exp = ExpressionFactory.exp("minute(timestampColumn) = 59"); + try { + long res = ObjectSelect.query(DateTestEntity.class, exp).selectCount(context); + assertEquals(1, res); + } catch (CayenneRuntimeException e) { + if(unitDbAdapter.supportsExtractPart(ASTExtract.DateTimePart.MINUTE)) { + throw e; + } + } + } + + @Test + public void testSecond() { + Expression exp = ExpressionFactory.exp("second(timestampColumn) = 39"); + try { + long res = ObjectSelect.query(DateTestEntity.class, exp).selectCount(context); + assertEquals(1, res); + } catch (CayenneRuntimeException e) { + if(unitDbAdapter.supportsExtractPart(ASTExtract.DateTimePart.SECOND)) { + throw e; + } + } + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/05a77250/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTExtractTest.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTExtractTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTExtractTest.java new file mode 100644 index 0000000..1787636 --- /dev/null +++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTExtractTest.java @@ -0,0 +1,162 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.cayenne.exp.parser; + +import org.apache.cayenne.exp.Expression; +import org.apache.cayenne.exp.ExpressionFactory; +import org.apache.cayenne.exp.FunctionExpressionFactory; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * @since 4.0 + */ +public class ASTExtractTest { + + @Test + public void testYear() { + String expStr = "year(dateColumn)"; + Expression expParsed = ExpressionFactory.exp(expStr); + Expression expFromFactory = FunctionExpressionFactory.yearExp("dateColumn"); + + assertTrue(expParsed instanceof ASTExtract); + assertTrue(expFromFactory instanceof ASTExtract); + + assertEquals(expStr, expParsed.toString()); + assertEquals(expStr, expFromFactory.toString()); + } + + @Test + public void testMonth() { + String expStr = "month(dateColumn)"; + Expression expParsed = ExpressionFactory.exp(expStr); + Expression expFromFactory = FunctionExpressionFactory.monthExp("dateColumn"); + + assertTrue(expParsed instanceof ASTExtract); + assertTrue(expFromFactory instanceof ASTExtract); + + assertEquals(expStr, expParsed.toString()); + assertEquals(expStr, expFromFactory.toString()); + } + + @Test + public void testWeek() { + String expStr = "week(dateColumn)"; + Expression expParsed = ExpressionFactory.exp(expStr); + Expression expFromFactory = FunctionExpressionFactory.weekExp("dateColumn"); + + assertTrue(expParsed instanceof ASTExtract); + assertTrue(expFromFactory instanceof ASTExtract); + + assertEquals(expStr, expParsed.toString()); + assertEquals(expStr, expFromFactory.toString()); + } + + @Test + public void testDayOfYear() { + String expStr = "dayOfYear(dateColumn)"; + Expression expParsed = ExpressionFactory.exp(expStr); + Expression expFromFactory = FunctionExpressionFactory.dayOfYearExp("dateColumn"); + + assertTrue(expParsed instanceof ASTExtract); + assertTrue(expFromFactory instanceof ASTExtract); + + assertEquals(expStr, expParsed.toString()); + assertEquals(expStr, expFromFactory.toString()); + } + + @Test + public void testDay() { + String expStr = "day(dateColumn)"; + Expression expParsed = ExpressionFactory.exp(expStr); + + assertTrue(expParsed instanceof ASTExtract); + + assertEquals(expStr, expParsed.toString()); + } + + @Test + public void testDayOfMonth() { + String expStr = "dayOfMonth(dateColumn)"; + Expression expParsed = ExpressionFactory.exp(expStr); + Expression expFromFactory = FunctionExpressionFactory.dayOfMonthExp("dateColumn"); + + assertTrue(expParsed instanceof ASTExtract); + assertTrue(expFromFactory instanceof ASTExtract); + + assertEquals(expStr, expParsed.toString()); + assertEquals(expStr, expFromFactory.toString()); + } + + @Test + public void testDayOfWeek() { + String expStr = "dayOfWeek(dateColumn)"; + Expression expParsed = ExpressionFactory.exp(expStr); + Expression expFromFactory = FunctionExpressionFactory.dayOfWeekExp("dateColumn"); + + assertTrue(expParsed instanceof ASTExtract); + assertTrue(expFromFactory instanceof ASTExtract); + + assertEquals(expStr, expParsed.toString()); + assertEquals(expStr, expFromFactory.toString()); + } + + @Test + public void testHour() { + String expStr = "hour(dateColumn)"; + Expression expParsed = ExpressionFactory.exp(expStr); + Expression expFromFactory = FunctionExpressionFactory.hourExp("dateColumn"); + + assertTrue(expParsed instanceof ASTExtract); + assertTrue(expFromFactory instanceof ASTExtract); + + assertEquals(expStr, expParsed.toString()); + assertEquals(expStr, expFromFactory.toString()); + } + + @Test + public void testMinute() { + String expStr = "minute(dateColumn)"; + Expression expParsed = ExpressionFactory.exp(expStr); + Expression expFromFactory = FunctionExpressionFactory.minuteExp("dateColumn"); + + assertTrue(expParsed instanceof ASTExtract); + assertTrue(expFromFactory instanceof ASTExtract); + + assertEquals(expStr, expParsed.toString()); + assertEquals(expStr, expFromFactory.toString()); + } + + @Test + public void testSecond() { + String expStr = "second(dateColumn)"; + Expression expParsed = ExpressionFactory.exp(expStr); + Expression expFromFactory = FunctionExpressionFactory.secondExp("dateColumn"); + + assertTrue(expParsed instanceof ASTExtract); + assertTrue(expFromFactory instanceof ASTExtract); + + assertEquals(expStr, expParsed.toString()); + assertEquals(expStr, expFromFactory.toString()); + } + +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/05a77250/cayenne-server/src/test/java/org/apache/cayenne/unit/DerbyUnitDbAdapter.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/DerbyUnitDbAdapter.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/DerbyUnitDbAdapter.java index c64f1b2..409c861 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/unit/DerbyUnitDbAdapter.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/DerbyUnitDbAdapter.java @@ -20,6 +20,7 @@ package org.apache.cayenne.unit; import org.apache.cayenne.dba.DbAdapter; +import org.apache.cayenne.exp.parser.ASTExtract; /** * @@ -55,4 +56,15 @@ public class DerbyUnitDbAdapter extends UnitDbAdapter { public boolean supportsExpressionInHaving() { return false; } + + @Override + public boolean supportsExtractPart(ASTExtract.DateTimePart part) { + switch (part) { + case DAY_OF_YEAR: + case DAY_OF_WEEK: + case WEEK: + return false; + } + return true; + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/05a77250/cayenne-server/src/test/java/org/apache/cayenne/unit/FrontBaseUnitDbAdapter.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/FrontBaseUnitDbAdapter.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/FrontBaseUnitDbAdapter.java index eb987f4..123ff8d 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/unit/FrontBaseUnitDbAdapter.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/FrontBaseUnitDbAdapter.java @@ -23,6 +23,7 @@ import java.sql.Connection; import java.util.Collection; import org.apache.cayenne.dba.DbAdapter; +import org.apache.cayenne.exp.parser.ASTExtract; import org.apache.cayenne.map.DataMap; /** @@ -86,4 +87,14 @@ public class FrontBaseUnitDbAdapter extends UnitDbAdapter { public boolean supportsExpressionInHaving() { return false; } + + public boolean supportsExtractPart(ASTExtract.DateTimePart part) { + switch (part) { + case WEEK: + case DAY_OF_YEAR: + case DAY_OF_WEEK: + return false; + } + return true; + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/05a77250/cayenne-server/src/test/java/org/apache/cayenne/unit/UnitDbAdapter.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/UnitDbAdapter.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/UnitDbAdapter.java index 87ca60c..a4f22f7 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/unit/UnitDbAdapter.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/UnitDbAdapter.java @@ -25,6 +25,7 @@ import org.apache.cayenne.configuration.RuntimeProperties; import org.apache.cayenne.dba.DbAdapter; import org.apache.cayenne.dba.QuotingStrategy; import org.apache.cayenne.di.Inject; +import org.apache.cayenne.exp.parser.ASTExtract; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.Procedure; @@ -398,4 +399,8 @@ public class UnitDbAdapter { public boolean supportsSelectBooleanExpression() { return true; } + + public boolean supportsExtractPart(ASTExtract.DateTimePart part) { + return true; + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/05a77250/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceInfoProvider.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceInfoProvider.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceInfoProvider.java index 94a2708..5864b77 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceInfoProvider.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceInfoProvider.java @@ -97,7 +97,7 @@ public class ServerCaseDataSourceInfoProvider implements Provider<DataSourceInfo sqlite.setAdapterClassName(SQLiteAdapter.class.getName()); sqlite.setUserName("sa"); sqlite.setPassword(""); - sqlite.setDataSourceUrl("jdbc:sqlite:file:memdb?mode=memory&cache=shared"); + sqlite.setDataSourceUrl("jdbc:sqlite:file:memdb?mode=memory&cache=shared&date_class=text"); sqlite.setJdbcDriver("org.sqlite.JDBC"); sqlite.setMinConnections(ConnectionProperties.MIN_CONNECTIONS); sqlite.setMaxConnections(ConnectionProperties.MAX_CONNECTIONS); http://git-wip-us.apache.org/repos/asf/cayenne/blob/05a77250/docs/doc/src/main/resources/RELEASE-NOTES.txt ---------------------------------------------------------------------- diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt index 9f5e3c3..ebe1207 100644 --- a/docs/doc/src/main/resources/RELEASE-NOTES.txt +++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt @@ -18,6 +18,7 @@ CAY-2258 DI: type-safe binding of List and Map CAY-2266 Move EventBridge implementations into autoloadable modules CAY-2267 Contribute lifecycle events listeners via DI CAY-2259 QueryCache: support for referencing type-safe caches +CAY-2269 Add support for date/time components extraction in expression functions CAY-2270 Update function support in expression parser Bug Fixes:
