From 7cc5af55fbf0ae662fa509089737cdf854898d3e Mon Sep 17 00:00:00 2001 From: moparisthebest Date: Tue, 15 May 2018 23:32:00 -0400 Subject: [PATCH] Implement UnNestArrayInList for hsqldb --- .../jdbc/codegen/JdbcMapper.java | 1 + .../jdbc/codegen/JdbcMapperProcessor.java | 14 +++++++--- .../jdbc/UnNestArrayInList.java | 26 +++++++++++++++++++ .../jdbc/codegen/QueryMapperQmDao.java | 22 ++++++++++++++-- 4 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 querymapper/src/main/java/com/moparisthebest/jdbc/UnNestArrayInList.java diff --git a/common/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapper.java b/common/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapper.java index 9c9a1af..5913af5 100644 --- a/common/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapper.java +++ b/common/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapper.java @@ -129,6 +129,7 @@ public interface JdbcMapper extends Closeable { public enum DatabaseType { DEFAULT(null, null), STANDARD("numeric", "text"), + UNNEST("numeric", "text"), ORACLE("ARRAY_NUM_TYPE", "ARRAY_STR_TYPE"); public final String arrayNumberTypeName, arrayStringTypeName; diff --git a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java index 3814a8e..035d902 100644 --- a/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java +++ b/jdbcmapper/src/main/java/com/moparisthebest/jdbc/codegen/JdbcMapperProcessor.java @@ -1,9 +1,6 @@ package com.moparisthebest.jdbc.codegen; -import com.moparisthebest.jdbc.ArrayInList; -import com.moparisthebest.jdbc.Cleaner; -import com.moparisthebest.jdbc.MapperException; -import com.moparisthebest.jdbc.OracleArrayInList; +import com.moparisthebest.jdbc.*; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; @@ -194,6 +191,9 @@ public class JdbcMapperProcessor extends AbstractProcessor { case STANDARD: arrayInList = new ArrayInList(arrayNumberTypeName, arrayStringTypeName); break; + case UNNEST: + arrayInList = new UnNestArrayInList(arrayNumberTypeName, arrayStringTypeName); + break; default: // no support arrayInList = null; @@ -403,6 +403,11 @@ public class JdbcMapperProcessor extends AbstractProcessor { "(" + inColumnName + " != ANY(?))" : "(" + inColumnName + " = ANY(?))"; break; + case UNNEST: + replacement = not ? + "(" + inColumnName + " NOT IN(UNNEST(?)))" : + "(" + inColumnName + " IN(UNNEST(?)))"; + break; default: processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "default DatabaseType? should never happen!!", bindParam); return false; @@ -749,6 +754,7 @@ public class JdbcMapperProcessor extends AbstractProcessor { //w.write("(Array) createArray.invoke(conn.unwrap(oracleConnection), \""); break; case STANDARD: + case UNNEST: w.write("conn.createArrayOf(\""); break; default: diff --git a/querymapper/src/main/java/com/moparisthebest/jdbc/UnNestArrayInList.java b/querymapper/src/main/java/com/moparisthebest/jdbc/UnNestArrayInList.java new file mode 100644 index 0000000..c8877bf --- /dev/null +++ b/querymapper/src/main/java/com/moparisthebest/jdbc/UnNestArrayInList.java @@ -0,0 +1,26 @@ +package com.moparisthebest.jdbc; + +/** + * HSQLDB requires array in lists to be implemented this way: + * https://stackoverflow.com/questions/35939489/createarrayof-string-in-hsqldb-jdbc-returns-abstractmethoderror/35964424#35964424 + */ +public class UnNestArrayInList extends ArrayInList { + + private static final InList instance = new UnNestArrayInList(); + + public static InList instance() { + return instance; + } + + public UnNestArrayInList(final String numberType, final String otherType) { + super(numberType, otherType); + } + + public UnNestArrayInList() { + super(); + } + + protected String columnAppend(final String columnName) { + return "(" + columnName + " IN(UNNEST(?)))"; + } +} diff --git a/test/src/main/java/com/moparisthebest/jdbc/codegen/QueryMapperQmDao.java b/test/src/main/java/com/moparisthebest/jdbc/codegen/QueryMapperQmDao.java index 83278be..12ff88b 100644 --- a/test/src/main/java/com/moparisthebest/jdbc/codegen/QueryMapperQmDao.java +++ b/test/src/main/java/com/moparisthebest/jdbc/codegen/QueryMapperQmDao.java @@ -54,12 +54,13 @@ public class QueryMapperQmDao implements QmDao { public static final String selectStrVal = "SELECT str_val FROM val WHERE val_no = ?"; private static final Collection> noArrayInListSupport; + private static final Class hsqlConnection; static { Collection> no = new ArrayList>(); for(final String connectionClassName : new String[]{ "org.apache.derby.impl.jdbc.EmbedConnection" - , "org.hsqldb.jdbc.JDBCConnection" + , "org.hsqldb.jdbc.JDBCConnection" // does not support ArrayInList but *does* support UnNestArrayInList , "org.sqlite.jdbc3.JDBC3Connection" , "org.mariadb.jdbc.MariaDbConnection" // h2 doesn't support this with java6 either... @@ -73,6 +74,13 @@ public class QueryMapperQmDao implements QmDao { // ignore } noArrayInListSupport = Collections.unmodifiableCollection(no); + Class hsql = null; + try { + hsql = Class.forName("org.hsqldb.jdbc.JDBCConnection"); + } catch(Exception e) { + // ignore + } + hsqlConnection = hsql; } public static boolean supportsArrayInList(final Connection conn) { @@ -89,7 +97,17 @@ public class QueryMapperQmDao implements QmDao { } public static InList getBestInList(final Connection conn) { - return supportsArrayInList(conn) ? ArrayInList.instance() : BindInList.instance(); + if(supportsArrayInList(conn)) + return ArrayInList.instance(); + if(hsqlConnection != null) + try { + if(conn.isWrapperFor(hsqlConnection)) + return UnNestArrayInList.instance(); + } catch (SQLException e) { + // ignore + } + // works for everything + return BindInList.instance(); } protected final QueryMapper qm;