diff --git a/lib/taskana-core/pom.xml b/lib/taskana-core/pom.xml index d28c367f8..b74117d62 100644 --- a/lib/taskana-core/pom.xml +++ b/lib/taskana-core/pom.xml @@ -1,5 +1,5 @@ - + 4.0.0 pro.taskana taskana-core @@ -18,10 +18,10 @@ - Holger Hagen - holger.hagen@novatec-gmbh.de - NovaTec Consulting GmbH - https://www.novatec-gmbh.de + Holger Hagen + holger.hagen@novatec-gmbh.de + NovaTec Consulting GmbH + https://www.novatec-gmbh.de @@ -128,11 +128,11 @@ slf4j-api 1.7.25 - - org.json - json - 20180130 - + + org.json + json + 20180130 + junit @@ -146,30 +146,36 @@ 2.8.47 test - - org.powermock - powermock-module-junit4 - ${powermock.version} - test - - - org.powermock - powermock-api-mockito2 - ${powermock.version} - test - + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito2 + ${powermock.version} + test + com.h2database h2 1.4.196 test - - com.ibm.db2.jcc - db2jcc4 - 11.1.1.1 - test - + + org.postgresql + postgresql + 42.2.2 + test + + + com.ibm.db2.jcc + db2jcc4 + 11.1.1.1 + test + org.apache.logging.log4j log4j-slf4j-impl @@ -246,15 +252,15 @@ - - - - novatec public - novatec-repository - https://repository.novatec-gmbh.de/content/repositories/novatec/ - - - + + + + novatec public + novatec-repository + https://repository.novatec-gmbh.de/content/repositories/novatec/ + + + diff --git a/lib/taskana-core/src/main/java/pro/taskana/TaskanaEngine.java b/lib/taskana-core/src/main/java/pro/taskana/TaskanaEngine.java index e562e4280..d08d2442b 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/TaskanaEngine.java +++ b/lib/taskana-core/src/main/java/pro/taskana/TaskanaEngine.java @@ -60,7 +60,7 @@ public interface TaskanaEngine { * @param connection * - The java.sql.Connection that is controlled by the client */ - void setConnection(java.sql.Connection connection); + void setConnection(java.sql.Connection connection) throws java.sql.SQLException; /** * Closes the client's connection, sets it to null and switches to mode PARTICIPATE. Only applicable in mode @@ -68,20 +68,6 @@ public interface TaskanaEngine { */ void closeConnection(); - /** - * Connection management mode. Controls the connection handling of taskana - * - */ - enum ConnectionManagementMode { - PARTICIPATE, - AUTOCOMMIT, - EXPLICIT - } - /** * check whether the current user is member of one of the roles specified. * @@ -100,4 +86,18 @@ public interface TaskanaEngine { * If the current user is not member of any specified role */ void checkRoleMembership(TaskanaRole... roles) throws NotAuthorizedException; + + /** + * Connection management mode. Controls the connection handling of taskana + * + */ + enum ConnectionManagementMode { + PARTICIPATE, + AUTOCOMMIT, + EXPLICIT + } } diff --git a/lib/taskana-core/src/main/java/pro/taskana/configuration/DbSchemaCreator.java b/lib/taskana-core/src/main/java/pro/taskana/configuration/DbSchemaCreator.java index 6dd7814c9..dfe039744 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/configuration/DbSchemaCreator.java +++ b/lib/taskana-core/src/main/java/pro/taskana/configuration/DbSchemaCreator.java @@ -20,6 +20,7 @@ public class DbSchemaCreator { private static final Logger LOGGER = LoggerFactory.getLogger(DbSchemaCreator.class); private static final String SQL = "/sql"; private static final String DB_SCHEMA = SQL + "/taskana-schema.sql"; + private static final String DB_SCHEMA_POSTGRES = SQL + "/taskana-schema-postgres.sql"; private static final String DB_SCHEMA_DETECTION = SQL + "/schema-detection.sql"; private DataSource dataSource; private StringWriter outWriter = new StringWriter(); @@ -32,6 +33,10 @@ public class DbSchemaCreator { this.dataSource = dataSource; } + private static String selectDbScriptFileName(String dbProductName) { + return "PostgreSQL".equals(dbProductName) ? DB_SCHEMA_POSTGRES : DB_SCHEMA; + } + /** * Run all db scripts. * @@ -48,7 +53,8 @@ public class DbSchemaCreator { runner.setErrorLogWriter(errorLogWriter); try { if (!isSchemaPreexisting(runner)) { - runner.runScript(new InputStreamReader(this.getClass().getResourceAsStream(DB_SCHEMA))); + runner.runScript(new InputStreamReader(this.getClass() + .getResourceAsStream(selectDbScriptFileName(connection.getMetaData().getDatabaseProductName())))); } } finally { runner.closeConnection(); diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationServiceImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationServiceImpl.java index bc2c4774e..c700664b1 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationServiceImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/ClassificationServiceImpl.java @@ -1,5 +1,6 @@ package pro.taskana.impl; +import java.sql.SQLException; import java.sql.SQLIntegrityConstraintViolationException; import java.time.Duration; import java.time.Instant; @@ -395,10 +396,8 @@ public class ClassificationServiceImpl implements ClassificationService { } private boolean isReferentialIntegrityConstraintViolation(PersistenceException e) { - return ((e.getCause().getClass().getName().equals("org.h2.jdbc.JdbcSQLException") - && e.getMessage().contains("23503")) - || (e.getCause() instanceof SQLIntegrityConstraintViolationException - && e.getMessage().contains("-532"))); + return e.getCause() instanceof SQLException && ((SQLException) e.getCause()).getSQLState().equals("23503") + || e.getCause() instanceof SQLIntegrityConstraintViolationException && e.getMessage().contains("-532"); } } diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskanaEngineImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskanaEngineImpl.java index 5f279a415..8655c489a 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskanaEngineImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskanaEngineImpl.java @@ -62,16 +62,56 @@ public class TaskanaEngineImpl implements TaskanaEngine { protected ConnectionManagementMode mode = ConnectionManagementMode.PARTICIPATE; protected java.sql.Connection connection = null; - public static TaskanaEngine createTaskanaEngine(TaskanaEngineConfiguration taskanaEngineConfiguration) { - return new TaskanaEngineImpl(taskanaEngineConfiguration); - } - protected TaskanaEngineImpl(TaskanaEngineConfiguration taskanaEngineConfiguration) { this.taskanaEngineConfiguration = taskanaEngineConfiguration; createTransactionFactory(taskanaEngineConfiguration.getUseManagedTransactions()); this.sessionManager = createSqlSessionManager(); } + public static TaskanaEngine createTaskanaEngine(TaskanaEngineConfiguration taskanaEngineConfiguration) { + return new TaskanaEngineImpl(taskanaEngineConfiguration); + } + + /** + * With sessionStack, we maintain a Stack of SqlSessionManager objects on a per thread basis. SqlSessionManager is + * the MyBatis object that wraps database connections. The purpose of this stack is to keep track of nested calls. + * Each external API call is wrapped into taskanaEngineImpl.openConnection(); ..... + * taskanaEngineImpl.returnConnection(); calls. In order to avoid duplicate opening / closing of connections, we use + * the sessionStack in the following way: Each time, an openConnection call is received, we push the current + * sessionManager onto the stack. On the first call to openConnection, we call sessionManager.startManagedSession() + * to open a database connection. On each call to returnConnection() we pop one instance of sessionManager from the + * stack. When the stack becomes empty, we close the database connection by calling sessionManager.close() + * + * @return Stack of SqlSessionManager + */ + protected static Deque getSessionStack() { + Deque stack = sessionStack.get(); + if (stack == null) { + stack = new ArrayDeque<>(); + sessionStack.set(stack); + } + return stack; + } + + protected static SqlSessionManager getSessionFromStack() { + Deque stack = getSessionStack(); + if (stack.isEmpty()) { + return null; + } + return stack.peek(); + } + + protected static void pushSessionToStack(SqlSessionManager session) { + getSessionStack().push(session); + } + + protected static void popSessionFromStack() { + Deque stack = getSessionStack(); + if (!stack.isEmpty()) { + stack.pop(); + } + } + @Override public TaskService getTaskService() { SqlSession session = this.sessionManager; @@ -140,17 +180,15 @@ public class TaskanaEngineImpl implements TaskanaEngine { * The connection that passed into TaskanaEngine */ @Override - public void setConnection(java.sql.Connection connection) { + public void setConnection(java.sql.Connection connection) throws SQLException { if (connection != null) { this.connection = connection; + // disabling auto commit for passed connection in order to gain full control over the connection management + connection.setAutoCommit(false); mode = ConnectionManagementMode.EXPLICIT; sessionManager.startManagedSession(connection); } else if (this.connection != null) { - this.connection = null; - if (sessionManager.isManagedSessionStarted()) { - sessionManager.close(); - } - mode = ConnectionManagementMode.PARTICIPATE; + closeConnection(); } } @@ -291,6 +329,8 @@ public class TaskanaEngineImpl implements TaskanaEngine { configuration.setDatabaseId("db2"); } else if (databaseProductName.contains("H2")) { configuration.setDatabaseId("h2"); + } else if (databaseProductName.equals("PostgreSQL")) { + configuration.setDatabaseId("postgres"); } else { LOGGER.error( "Method createSqlSessionManager() didn't find database with name {}. Throwing UnsupportedDatabaseException", @@ -335,46 +375,6 @@ public class TaskanaEngineImpl implements TaskanaEngine { } } - /** - * With sessionStack, we maintain a Stack of SqlSessionManager objects on a per thread basis. SqlSessionManager is - * the MyBatis object that wraps database connections. The purpose of this stack is to keep track of nested calls. - * Each external API call is wrapped into taskanaEngineImpl.openConnection(); ..... - * taskanaEngineImpl.returnConnection(); calls. In order to avoid duplicate opening / closing of connections, we use - * the sessionStack in the following way: Each time, an openConnection call is received, we push the current - * sessionManager onto the stack. On the first call to openConnection, we call sessionManager.startManagedSession() - * to open a database connection. On each call to returnConnection() we pop one instance of sessionManager from the - * stack. When the stack becomes empty, we close the database connection by calling sessionManager.close() - * - * @return Stack of SqlSessionManager - */ - protected static Deque getSessionStack() { - Deque stack = sessionStack.get(); - if (stack == null) { - stack = new ArrayDeque<>(); - sessionStack.set(stack); - } - return stack; - } - - protected static SqlSessionManager getSessionFromStack() { - Deque stack = getSessionStack(); - if (stack.isEmpty()) { - return null; - } - return stack.peek(); - } - - protected static void pushSessionToStack(SqlSessionManager session) { - getSessionStack().push(session); - } - - protected static void popSessionFromStack() { - Deque stack = getSessionStack(); - if (!stack.isEmpty()) { - stack.pop(); - } - } - /** * Returns true if the given domain does exist in the configuration. * diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/MapTypeHandler.java b/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/MapTypeHandler.java index 3c58bdef2..0a8f46dc8 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/MapTypeHandler.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/persistence/MapTypeHandler.java @@ -1,7 +1,6 @@ package pro.taskana.impl.persistence; import java.sql.CallableStatement; -import java.sql.Clob; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -30,9 +29,7 @@ public class MapTypeHandler extends BaseTypeHandler { LOGGER.debug("Input-Map before serializing: ", parameter); // Convert Map to JSON string JSONObject jsonObj = new JSONObject(parameter); - Clob content = ps.getConnection().createClob(); - content.setString(1, jsonObj.toString()); - ps.setClob(i, content); + ps.setString(i, jsonObj.toString()); } else { ps.setNull(i, Types.BLOB); } @@ -40,36 +37,34 @@ public class MapTypeHandler extends BaseTypeHandler { @Override public Map getNullableResult(ResultSet rs, String columnName) throws SQLException { - Clob fieldValue = rs.getClob(columnName); + String fieldValue = rs.getString(columnName); if (fieldValue != null) { - return convertClobToMap(fieldValue); + return convertToMap(fieldValue); } return null; } @Override public Map getNullableResult(ResultSet rs, int columnIndex) throws SQLException { - Clob fieldValue = rs.getClob(columnIndex); + String fieldValue = rs.getString(columnIndex); if (fieldValue != null) { - return convertClobToMap(fieldValue); + return convertToMap(fieldValue); } return null; } @Override public Map getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { - Clob fieldValue = cs.getClob(columnIndex); + String fieldValue = cs.getString(columnIndex); if (fieldValue != null) { - return convertClobToMap(fieldValue); + return convertToMap(fieldValue); } return null; } - private Map convertClobToMap(Clob fieldValue) throws SQLException { - String content = fieldValue.getSubString(1L, (int) fieldValue.length()); - JSONObject jsonObj = new JSONObject(content); - Map result = jsonObj.toMap(); - return result; + private Map convertToMap(String fieldValue) throws SQLException { + JSONObject jsonObj = new JSONObject(fieldValue); + return jsonObj.toMap(); } } diff --git a/lib/taskana-core/src/main/java/pro/taskana/mappings/AttachmentMapper.java b/lib/taskana-core/src/main/java/pro/taskana/mappings/AttachmentMapper.java index 62f952901..50a614617 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/mappings/AttachmentMapper.java +++ b/lib/taskana-core/src/main/java/pro/taskana/mappings/AttachmentMapper.java @@ -11,7 +11,6 @@ import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import org.apache.ibatis.type.ClobTypeHandler; -import org.apache.ibatis.type.JdbcType; import pro.taskana.impl.AttachmentImpl; import pro.taskana.impl.AttachmentSummaryImpl; @@ -46,7 +45,7 @@ public interface AttachmentMapper { @Result(property = "objectReference.value", column = "REF_VALUE"), @Result(property = "channel", column = "CHANNEL"), @Result(property = "received", column = "RECEIVED"), - @Result(property = "customAttributes", column = "CUSTOM_ATTRIBUTES", jdbcType = JdbcType.CLOB, + @Result(property = "customAttributes", column = "CUSTOM_ATTRIBUTES", javaType = Map.class, typeHandler = MapTypeHandler.class) }) List findAttachmentsByTaskId(@Param("taskId") String taskId); @@ -70,7 +69,7 @@ public interface AttachmentMapper { @Result(property = "objectReference.value", column = "REF_VALUE"), @Result(property = "channel", column = "CHANNEL"), @Result(property = "received", column = "RECEIVED"), - @Result(property = "customAttributes", column = "CUSTOM_ATTRIBUTES", jdbcType = JdbcType.CLOB, + @Result(property = "customAttributes", column = "CUSTOM_ATTRIBUTES", javaType = Map.class, typeHandler = MapTypeHandler.class) }) AttachmentImpl getAttachment(@Param("attachmentId") String attachmentId); @@ -107,7 +106,7 @@ public interface AttachmentMapper { + "with UR " + "") @Results(value = { - @Result(property = "customAttributes", column = "CUSTOM_ATTRIBUTES", jdbcType = JdbcType.CLOB, + @Result(property = "customAttributes", column = "CUSTOM_ATTRIBUTES", javaType = String.class, typeHandler = ClobTypeHandler.class) }) String getCustomAttributesAsString(@Param("attachmentId") String attachmentId); diff --git a/lib/taskana-core/src/main/java/pro/taskana/mappings/JobMapper.java b/lib/taskana-core/src/main/java/pro/taskana/mappings/JobMapper.java index 50f41f488..0e323eb24 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/mappings/JobMapper.java +++ b/lib/taskana-core/src/main/java/pro/taskana/mappings/JobMapper.java @@ -9,7 +9,6 @@ import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; -import org.apache.ibatis.type.JdbcType; import pro.taskana.impl.Job; import pro.taskana.impl.persistence.MapTypeHandler; @@ -19,8 +18,19 @@ import pro.taskana.impl.persistence.MapTypeHandler; */ public interface JobMapper { - @Insert("INSERT INTO TASKANA.JOB (JOB_ID, CREATED, STARTED, COMPLETED, STATE, EXECUTOR, ARGUMENTS) " - + "VALUES (NEXT VALUE FOR TASKANA.JOB_SEQ, #{job.created}, #{job.started}, #{job.completed}, #{job.state}, #{job.executor}, #{job.arguments,jdbcType=CLOB, javaType=java.util.Map,typeHandler=pro.taskana.impl.persistence.MapTypeHandler} )") + @Insert("") void insertJob(@Param("job") Job job); @Select("SELECT JOB_ID, CREATED, STARTED, COMPLETED, STATE, EXECUTOR, ARGUMENTS " @@ -34,7 +44,7 @@ public interface JobMapper { @Result(property = "completed", column = "COMPLETED"), @Result(property = "state", column = "STATE"), @Result(property = "executor", column = "EXECUTOR"), - @Result(property = "arguments", column = "ARGUMENTS", jdbcType = JdbcType.CLOB, + @Result(property = "arguments", column = "ARGUMENTS", javaType = Map.class, typeHandler = MapTypeHandler.class) }) List findJobsToRun(); diff --git a/lib/taskana-core/src/main/java/pro/taskana/mappings/QueryMapper.java b/lib/taskana-core/src/main/java/pro/taskana/mappings/QueryMapper.java index f372760cd..bb10d0ed8 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/mappings/QueryMapper.java +++ b/lib/taskana-core/src/main/java/pro/taskana/mappings/QueryMapper.java @@ -32,9 +32,9 @@ public interface QueryMapper { + "" + " " + "AND t.WORKBASKET_ID IN ( " - + "select WID from (select WORKBASKET_ID as WID, max(PERM_READ) as MAX_READ FROM TASKANA.WORKBASKET_ACCESS_LIST where " + + "SELECT WID from (SELECT WORKBASKET_ID as WID, MAX(PERM_READ::int) as MAX_READ FROM TASKANA.WORKBASKET_ACCESS_LIST AS s where " + "ACCESS_ID IN (#{item}) " - + "group by WORKBASKET_ID ) where max_read = 1 ) " + + "group by WORKBASKET_ID ) AS f where max_read = 1 ) " + " " + "AND t.ID IN(#{item}) " + " AND ( ( t.CREATED >= #{item.begin} AND t.CREATED <=#{item.end} )) " @@ -234,10 +234,10 @@ public interface QueryMapper { + "SELECT DISTINCT " + "w.ID, w.KEY, w.NAME, w.DOMAIN, W.TYPE, w.DESCRIPTION, w.OWNER, w.ORG_LEVEL_1, w.ORG_LEVEL_2, w.ORG_LEVEL_3, w.ORG_LEVEL_4 from TASKANA.WORKBASKET w " + " " - + "LEFT OUTER JOIN (select WORKBASKET_ID as WID, max(PERM_READ) as MAX_READ, max(PERM_OPEN) as MAX_OPEN, " - + "MAX(PERM_APPEND) as MAX_APPEND, MAX(PERM_TRANSFER) as MAX_TRANSFER, MAX(PERM_DISTRIBUTE) as MAX_DISTRIBUTE, MAX(PERM_CUSTOM_1) as MAX_CUSTOM_1, MAX(PERM_CUSTOM_2) as MAX_CUSTOM_2, " - + "MAX(PERM_CUSTOM_3) as MAX_CUSTOM_3, MAX(PERM_CUSTOM_4) as MAX_CUSTOM_4, MAX(PERM_CUSTOM_5) as MAX_CUSTOM_5, MAX(PERM_CUSTOM_6) as MAX_CUSTOM_6, MAX(PERM_CUSTOM_7) as MAX_CUSTOM_7, " - + "MAX(PERM_CUSTOM_8) as MAX_CUSTOM_8, MAX(PERM_CUSTOM_9) as MAX_CUSTOM_9, MAX(PERM_CUSTOM_10) as MAX_CUSTOM_10, MAX(PERM_CUSTOM_11) as MAX_CUSTOM_11, MAX(PERM_CUSTOM_12) as MAX_CUSTOM_12 " + + "LEFT OUTER JOIN (select WORKBASKET_ID as WID, MAX(PERM_READ::int) as MAX_READ, MAX(PERM_OPEN::int) as MAX_OPEN, " + + "MAX(PERM_APPEND::int) as MAX_APPEND, MAX(PERM_TRANSFER::int) as MAX_TRANSFER, MAX(PERM_DISTRIBUTE::int) as MAX_DISTRIBUTE, MAX(PERM_CUSTOM_1::int) as MAX_CUSTOM_1, MAX(PERM_CUSTOM_2::int) as MAX_CUSTOM_2, " + + "MAX(PERM_CUSTOM_3::int) as MAX_CUSTOM_3, MAX(PERM_CUSTOM_4::int) as MAX_CUSTOM_4, MAX(PERM_CUSTOM_5::int) as MAX_CUSTOM_5, MAX(PERM_CUSTOM_6::int) as MAX_CUSTOM_6, MAX(PERM_CUSTOM_7::int) as MAX_CUSTOM_7, " + + "MAX(PERM_CUSTOM_8::int) as MAX_CUSTOM_8, MAX(PERM_CUSTOM_9::int) as MAX_CUSTOM_9, MAX(PERM_CUSTOM_10::int) as MAX_CUSTOM_10, MAX(PERM_CUSTOM_11::int) as MAX_CUSTOM_11, MAX(PERM_CUSTOM_12::int) as MAX_CUSTOM_12 " + "FROM TASKANA.WORKBASKET_ACCESS_LIST where ACCESS_ID IN (#{item}) group by WORKBASKET_ID ) a " + "on (w.ID = a.WID)" + " " @@ -357,9 +357,9 @@ public interface QueryMapper { + "" + " " + "AND t.WORKBASKET_ID IN ( " - + "select WID from (select WORKBASKET_ID as WID, max(PERM_READ) as MAX_READ FROM TASKANA.WORKBASKET_ACCESS_LIST where " + + "select WID from (select WORKBASKET_ID as WID, MAX(PERM_READ::int) as MAX_READ FROM TASKANA.WORKBASKET_ACCESS_LIST AS s where " + "ACCESS_ID IN (#{item}) " - + "group by WORKBASKET_ID ) where max_read = 1 ) " + + "group by WORKBASKET_ID ) AS f where max_read = 1 ) " + " " + "AND t.ID IN(#{item}) " + " AND ( ( t.CREATED >= #{item.begin} AND t.CREATED <=#{item.end} )) " @@ -493,10 +493,10 @@ public interface QueryMapper { @Select("") @Results(value = { diff --git a/lib/taskana-core/src/main/java/pro/taskana/mappings/TaskMonitorMapper.java b/lib/taskana-core/src/main/java/pro/taskana/mappings/TaskMonitorMapper.java index 24b12852f..0357a2085 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/mappings/TaskMonitorMapper.java +++ b/lib/taskana-core/src/main/java/pro/taskana/mappings/TaskMonitorMapper.java @@ -23,6 +23,7 @@ public interface TaskMonitorMapper { @Select("") @Results({ @@ -60,6 +62,7 @@ public interface TaskMonitorMapper { @Select("") @Results({ @@ -97,6 +101,7 @@ public interface TaskMonitorMapper { @Select("") @Results({ @@ -134,6 +140,7 @@ public interface TaskMonitorMapper { @Select("") @Results({ @@ -173,6 +181,7 @@ public interface TaskMonitorMapper { @Select("") @Results({ @@ -248,6 +258,10 @@ public interface TaskMonitorMapper { + "#{selectedItem.upperAgeLimit} >= DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) AND " + "#{selectedItem.lowerAgeLimit} <= DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) " + " " + + "" + + "#{selectedItem.upperAgeLimit} >= DATE_PART('day', DUE - CURRENT_TIMESTAMP ) AND " + + "#{selectedItem.lowerAgeLimit} <= DATE_PART('day', DUE - CURRENT_TIMESTAMP ) " + + " " + ") " + "" + "with UR " diff --git a/lib/taskana-core/src/main/java/pro/taskana/mappings/WorkbasketAccessMapper.java b/lib/taskana-core/src/main/java/pro/taskana/mappings/WorkbasketAccessMapper.java index c72055dd6..b209e6957 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/mappings/WorkbasketAccessMapper.java +++ b/lib/taskana-core/src/main/java/pro/taskana/mappings/WorkbasketAccessMapper.java @@ -90,7 +90,8 @@ public interface WorkbasketAccessMapper { @Delete("DELETE FROM TASKANA.WORKBASKET_ACCESS_LIST where ACCESS_ID = #{accessId}") void deleteAccessItemsForAccessId(@Param("accessId") String accessId); - @Select("