package com.moparisthebest.jdbc; import com.moparisthebest.jdbc.codegen.JdbcMapper; import com.moparisthebest.jdbc.util.ResultSetIterable; import java.lang.reflect.Method; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; //IFJAVA8_START import java.util.stream.Stream; //IFJAVA8_END public class ListQueryMapper extends QueryMapper { private static final InList defaultInList; static { InList def; try { final String inListClassName = System.getProperty("QueryMapper.defaultInList.class"); if(inListClassName != null) { final Class inListClass = Class.forName(inListClassName); final Method method = inListClass.getMethod(System.getProperty("QueryMapper.defaultInList.method", "instance")); def = (InList) method.invoke(null); } else { // todo: change default to OPTIMAL ? final String type = System.getProperty("queryMapper.databaseType", System.getProperty("jdbcMapper.databaseType", "BIND")); if(type.equals("OPTIMAL")) { def = OptimalInList.instance(); } else { switch (JdbcMapper.DatabaseType.valueOf(type)) { case DEFAULT: case BIND: def = BindInList.instance(); break; case ANY: def = ArrayInList.instance(); break; case ORACLE: def = OracleArrayInList.instance(); break; case UNNEST: def = UnNestArrayInList.instance(); break; default: throw new RuntimeException("Invalid queryMapper.databaseType: " + type); } } } } catch (Throwable e) { // NEVER ignore throw new RuntimeException(e); } defaultInList = def; } protected final QueryMapper delegate; protected final InList inList; public static final String inListReplace = "{inList}"; private ListQueryMapper(Connection conn, String jndiName, Factory factory, QueryMapper delegate, ResultSetMapper cm, InList inList) { this.inList = inList.instance(conn); this.delegate = delegate == null ? new QueryMapper(conn, jndiName, factory, cm) : (delegate instanceof ListQueryMapper ? ((ListQueryMapper)delegate).delegate : delegate); } public ListQueryMapper(QueryMapper delegate, InList inList) { this(null, null, null, delegate, null, inList); } public ListQueryMapper(QueryMapper delegate) { this(null, null, null, delegate, null, defaultInList); } public ListQueryMapper(Connection conn, InList inList) { this(conn, null, null, null, null, inList); } public ListQueryMapper(Connection conn, ResultSetMapper cm, InList inList) { this(conn, null, null, null, cm, inList); } public ListQueryMapper(Connection conn) { this(conn, defaultInList); } public ListQueryMapper(Connection conn, ResultSetMapper cm) { this(conn, cm, defaultInList); } public ListQueryMapper(String jndiName, InList inList) { this(null, jndiName, null, null, null, inList); } public ListQueryMapper(String jndiName, ResultSetMapper cm, InList inList) { this(null, jndiName, null, null, cm, inList); } public ListQueryMapper(String jndiName) { this(jndiName, defaultInList); } public ListQueryMapper(String jndiName, ResultSetMapper cm) { this(jndiName, cm, defaultInList); } public ListQueryMapper(Factory factory, InList inList) { this(null, null, factory, null, null, inList); } public ListQueryMapper(Factory factory, ResultSetMapper cm, InList inList) { this(null, null, factory, null, cm, inList); } public ListQueryMapper(Factory factory) { this(factory, defaultInList); } public ListQueryMapper(Factory factory, ResultSetMapper cm) { this(factory, cm, defaultInList); } // todo: get rid of wrap, cause, how do you know to close it or not? :'( public static ListQueryMapper wrap(final QueryMapper qm){ return qm instanceof ListQueryMapper ? (ListQueryMapper)qm : new ListQueryMapper(qm); } public static ListQueryMapper wrap(final QueryMapper qm, final InList inList){ return qm instanceof ListQueryMapper && ((ListQueryMapper)qm).inList == inList ? (ListQueryMapper)qm : new ListQueryMapper(qm, inList); } public InList.InListObject inList(final String columnName, final Collection values) throws SQLException { return this.inList.inList(delegate.conn, columnName, values); } public InList.InListObject notInList(final String columnName, final Collection values) throws SQLException { return this.inList.notInList(delegate.conn, columnName, values); } // these update the database @Override public int executeUpdate(final PreparedStatement ps, final Object... bindObjects) throws SQLException { return delegate.executeUpdate(ps, bindObjects); } @Override public boolean executeUpdateSuccess(final PreparedStatement ps, final Object... bindObjects) throws SQLException { return delegate.executeUpdateSuccess(ps, bindObjects); } // these update the database using UpdateableDTOs @Override public int updateRows(final UpdateableDTO dto) throws SQLException { return delegate.updateRows(dto); } @Override public int updateRows(final Collection dtos) throws SQLException { return delegate.updateRows(dtos); } @Override public int updateRows(final UpdateableDTO[] dtos) throws SQLException { return delegate.updateRows(dtos); } @Override public int insertRows(final UpdateableDTO dto) throws SQLException { return delegate.insertRows(dto); } @Override public int insertRows(final Collection dtos) throws SQLException { return delegate.insertRows(dtos); } @Override public int insertRows(final UpdateableDTO[] dtos) throws SQLException { return delegate.insertRows(dtos); } // these grab ResultSets from the database @Override public ResultSet toResultSet(PreparedStatement ps, Object... bindObjects) throws SQLException { return delegate.toResultSet(ps, bindObjects); } // these are standard getters @Override public ResultSetMapper getCustomResultSetMapper() { return delegate.getCustomResultSetMapper(); } @Override public Connection getConnection() { return delegate.getConnection(); } // these just delegate and change no functionality @Override public void close() { delegate.close(); } // and these are standard @Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final ListQueryMapper that = (ListQueryMapper) o; if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) return false; if (inList != null ? !inList.equals(that.inList) : that.inList != null) return false; return true; } @Override public int hashCode() { int result = delegate != null ? delegate.hashCode() : 0; result = 31 * result + (inList != null ? inList.hashCode() : 0); return result; } @Override public String toString() { return "ListQueryMapper{" + "delegate=" + delegate + ", inList=" + inList + "} " + super.toString(); } // begin of ListQueryMapper specific methods private static StringBuilder recursiveReplace(final StringBuilder sb, final Object... bindObjects) { if (bindObjects != null && bindObjects.length > 0) { for (Object o : bindObjects) { if (o != null && o != QueryMapper.noBind) { if (o instanceof InList.InListObject) { final int startIndex = sb.indexOf(inListReplace); if (startIndex < -1) return sb; // we've replaced all, maybe an error? meh sb.replace(startIndex, startIndex + inListReplace.length(), o.toString()); } else if (o instanceof Object[]) { recursiveReplace(sb, (Object[]) o); } else if (o instanceof Collection) { recursiveReplace(sb, ((Collection) o).toArray()); } } } } return sb; } protected String prepareSql(final String sql, final Object... bindObjects) { return !sql.contains(inListReplace) ? sql : recursiveReplace(new StringBuilder(sql), bindObjects).toString(); } @Override public int executeUpdate(final String sql, final Object... bindObjects) throws SQLException { return delegate.executeUpdate(prepareSql(sql, bindObjects), bindObjects); } @Override public boolean executeUpdateSuccess(final String sql, final Object... bindObjects) throws SQLException { return delegate.executeUpdateSuccess(prepareSql(sql, bindObjects), bindObjects); } @Override public ResultSet toResultSet(String sql, Object... bindObjects) throws SQLException { return delegate.toResultSet(prepareSql(sql, bindObjects), bindObjects); } // DO NOT EDIT BELOW THIS LINE, OR CHANGE THIS COMMENT, CODE AUTOMATICALLY GENERATED BY genQueryMapper.sh @Override public T toObject(PreparedStatement ps, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toObject(ps, componentType, bindObjects); } @Override public T toObject(String sql, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toObject(prepareSql(sql, bindObjects), componentType, bindObjects); } @Override public ResultSetIterable toResultSetIterable(PreparedStatement ps, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toResultSetIterable(ps, componentType, bindObjects); } @Override public ResultSetIterable toResultSetIterable(String sql, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toResultSetIterable(prepareSql(sql, bindObjects), componentType, bindObjects); } @Override public , V> ResultSetIterable> toResultSetIterable(PreparedStatement ps, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toResultSetIterable(ps, componentType, mapValType, bindObjects); } @Override public , V> ResultSetIterable> toResultSetIterable(String sql, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toResultSetIterable(prepareSql(sql, bindObjects), componentType, mapValType, bindObjects); } //IFJAVA8_START @Override public Stream toStream(PreparedStatement ps, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toStream(ps, componentType, bindObjects); } @Override public Stream toStream(String sql, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toStream(prepareSql(sql, bindObjects), componentType, bindObjects); } //IFJAVA8_END //IFJAVA8_START @Override public , V> Stream> toStream(PreparedStatement ps, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toStream(ps, componentType, mapValType, bindObjects); } @Override public , V> Stream> toStream(String sql, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toStream(prepareSql(sql, bindObjects), componentType, mapValType, bindObjects); } //IFJAVA8_END @Override public , V> Map toSingleMap(PreparedStatement ps, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toSingleMap(ps, componentType, mapValType, bindObjects); } @Override public , V> Map toSingleMap(String sql, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toSingleMap(prepareSql(sql, bindObjects), componentType, mapValType, bindObjects); } @Override public Map toSingleMap(PreparedStatement ps, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toSingleMap(ps, mapValType, bindObjects); } @Override public Map toSingleMap(String sql, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toSingleMap(prepareSql(sql, bindObjects), mapValType, bindObjects); } @Override public T toType(PreparedStatement ps, TypeReference typeReference, final Object... bindObjects) throws SQLException { return delegate.toType(ps, typeReference, bindObjects); } @Override public T toType(String sql, TypeReference typeReference, final Object... bindObjects) throws SQLException { return delegate.toType(prepareSql(sql, bindObjects), typeReference, bindObjects); } @Override public , E> T toCollection(PreparedStatement ps, final Class collectionType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toCollection(ps, collectionType, componentType, bindObjects); } @Override public , E> T toCollection(String sql, final Class collectionType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toCollection(prepareSql(sql, bindObjects), collectionType, componentType, bindObjects); } @Override public , E> T toCollection(PreparedStatement ps, T list, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toCollection(ps, list, componentType, bindObjects); } @Override public , E> T toCollection(String sql, T list, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toCollection(prepareSql(sql, bindObjects), list, componentType, bindObjects); } @Override public , K, E> T toMap(PreparedStatement ps, T map, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMap(ps, map, mapKeyType, componentType, bindObjects); } @Override public , K, E> T toMap(String sql, T map, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMap(prepareSql(sql, bindObjects), map, mapKeyType, componentType, bindObjects); } @Override public , K, E extends Collection, C> T toMapCollection(PreparedStatement ps, final Class returnType, Class mapKeyType, Class collectionType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMapCollection(ps, returnType, mapKeyType, collectionType, componentType, bindObjects); } @Override public , K, E extends Collection, C> T toMapCollection(String sql, final Class returnType, Class mapKeyType, Class collectionType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMapCollection(prepareSql(sql, bindObjects), returnType, mapKeyType, collectionType, componentType, bindObjects); } @Override public , K, E extends Collection, C> T toMapCollection(PreparedStatement ps, T map, Class mapKeyType, Class collectionType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMapCollection(ps, map, mapKeyType, collectionType, componentType, bindObjects); } @Override public , K, E extends Collection, C> T toMapCollection(String sql, T map, Class mapKeyType, Class collectionType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMapCollection(prepareSql(sql, bindObjects), map, mapKeyType, collectionType, componentType, bindObjects); } @Override public ListIterator toListIterator(PreparedStatement ps, final Class type, final Object... bindObjects) throws SQLException { return delegate.toListIterator(ps, type, bindObjects); } @Override public ListIterator toListIterator(String sql, final Class type, final Object... bindObjects) throws SQLException { return delegate.toListIterator(prepareSql(sql, bindObjects), type, bindObjects); } @Override public Iterator toIterator(PreparedStatement ps, final Class type, final Object... bindObjects) throws SQLException { return delegate.toIterator(ps, type, bindObjects); } @Override public Iterator toIterator(String sql, final Class type, final Object... bindObjects) throws SQLException { return delegate.toIterator(prepareSql(sql, bindObjects), type, bindObjects); } @Override public T[] toArray(PreparedStatement ps, final Class type, final Object... bindObjects) throws SQLException { return delegate.toArray(ps, type, bindObjects); } @Override public T[] toArray(String sql, final Class type, final Object... bindObjects) throws SQLException { return delegate.toArray(prepareSql(sql, bindObjects), type, bindObjects); } @Override public List toList(PreparedStatement ps, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toList(ps, componentType, bindObjects); } @Override public List toList(String sql, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toList(prepareSql(sql, bindObjects), componentType, bindObjects); } @Override public Map toMap(PreparedStatement ps, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMap(ps, mapKeyType, componentType, bindObjects); } @Override public Map toMap(String sql, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMap(prepareSql(sql, bindObjects), mapKeyType, componentType, bindObjects); } @Override public , C> Map toMapList(PreparedStatement ps, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMapList(ps, mapKeyType, componentType, bindObjects); } @Override public , C> Map toMapList(String sql, Class mapKeyType, Class componentType, final Object... bindObjects) throws SQLException { return delegate.toMapList(prepareSql(sql, bindObjects), mapKeyType, componentType, bindObjects); } @Override public , E extends Map, V> T toCollectionMap(PreparedStatement ps, final Class collectionType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toCollectionMap(ps, collectionType, componentType, mapValType, bindObjects); } @Override public , E extends Map, V> T toCollectionMap(String sql, final Class collectionType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toCollectionMap(prepareSql(sql, bindObjects), collectionType, componentType, mapValType, bindObjects); } @Override public , E extends Map, V> T toCollectionMap(PreparedStatement ps, T list, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toCollectionMap(ps, list, componentType, mapValType, bindObjects); } @Override public , E extends Map, V> T toCollectionMap(String sql, T list, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toCollectionMap(prepareSql(sql, bindObjects), list, componentType, mapValType, bindObjects); } @Override public , K, E extends Map, V> T toMapMap(PreparedStatement ps, final Class returnType, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(ps, returnType, mapKeyType, componentType, mapValType, bindObjects); } @Override public , K, E extends Map, V> T toMapMap(String sql, final Class returnType, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(prepareSql(sql, bindObjects), returnType, mapKeyType, componentType, mapValType, bindObjects); } @Override public , K, E extends Map, V> T toMapMap(PreparedStatement ps, T map, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(ps, map, mapKeyType, componentType, mapValType, bindObjects); } @Override public , K, E extends Map, V> T toMapMap(String sql, T map, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(prepareSql(sql, bindObjects), map, mapKeyType, componentType, mapValType, bindObjects); } @Override public , K, C extends Collection, E extends Map, V> T toMapCollectionMap(PreparedStatement ps, final Class returnType, Class mapKeyType, Class collectionType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapCollectionMap(ps, returnType, mapKeyType, collectionType, componentType, mapValType, bindObjects); } @Override public , K, C extends Collection, E extends Map, V> T toMapCollectionMap(String sql, final Class returnType, Class mapKeyType, Class collectionType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapCollectionMap(prepareSql(sql, bindObjects), returnType, mapKeyType, collectionType, componentType, mapValType, bindObjects); } @Override public , K, C extends Collection, E extends Map, V> T toMapCollectionMap(PreparedStatement ps, T map, Class mapKeyType, Class collectionType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapCollectionMap(ps, map, mapKeyType, collectionType, componentType, mapValType, bindObjects); } @Override public , K, C extends Collection, E extends Map, V> T toMapCollectionMap(String sql, T map, Class mapKeyType, Class collectionType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapCollectionMap(prepareSql(sql, bindObjects), map, mapKeyType, collectionType, componentType, mapValType, bindObjects); } @Override public , V> ListIterator> toListIteratorMap(PreparedStatement ps, final Class type, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListIteratorMap(ps, type, mapValType, bindObjects); } @Override public , V> ListIterator> toListIteratorMap(String sql, final Class type, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListIteratorMap(prepareSql(sql, bindObjects), type, mapValType, bindObjects); } @Override public , V> Iterator> toIteratorMap(PreparedStatement ps, final Class type, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toIteratorMap(ps, type, mapValType, bindObjects); } @Override public , V> Iterator> toIteratorMap(String sql, final Class type, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toIteratorMap(prepareSql(sql, bindObjects), type, mapValType, bindObjects); } @Override public , V> Map[] toArrayMap(PreparedStatement ps, final Class type, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toArrayMap(ps, type, mapValType, bindObjects); } @Override public , V> Map[] toArrayMap(String sql, final Class type, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toArrayMap(prepareSql(sql, bindObjects), type, mapValType, bindObjects); } @Override public , V> List> toListMap(PreparedStatement ps, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListMap(ps, componentType, mapValType, bindObjects); } @Override public , V> List> toListMap(String sql, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListMap(prepareSql(sql, bindObjects), componentType, mapValType, bindObjects); } @Override public , V> Map> toMapMap(PreparedStatement ps, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(ps, mapKeyType, componentType, mapValType, bindObjects); } @Override public , V> Map> toMapMap(String sql, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(prepareSql(sql, bindObjects), mapKeyType, componentType, mapValType, bindObjects); } @Override public , V> Map>> toMapListMap(PreparedStatement ps, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapListMap(ps, mapKeyType, componentType, mapValType, bindObjects); } @Override public , V> Map>> toMapListMap(String sql, Class mapKeyType, Class componentType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapListMap(prepareSql(sql, bindObjects), mapKeyType, componentType, mapValType, bindObjects); } @Override public ListIterator> toListIteratorMap(PreparedStatement ps, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListIteratorMap(ps, mapValType, bindObjects); } @Override public ListIterator> toListIteratorMap(String sql, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListIteratorMap(prepareSql(sql, bindObjects), mapValType, bindObjects); } @Override public Iterator> toIteratorMap(PreparedStatement ps, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toIteratorMap(ps, mapValType, bindObjects); } @Override public Iterator> toIteratorMap(String sql, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toIteratorMap(prepareSql(sql, bindObjects), mapValType, bindObjects); } @Override public List> toListMap(PreparedStatement ps, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListMap(ps, mapValType, bindObjects); } @Override public List> toListMap(String sql, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toListMap(prepareSql(sql, bindObjects), mapValType, bindObjects); } @Override public Map> toMapMap(PreparedStatement ps, Class mapKeyType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(ps, mapKeyType, mapValType, bindObjects); } @Override public Map> toMapMap(String sql, Class mapKeyType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapMap(prepareSql(sql, bindObjects), mapKeyType, mapValType, bindObjects); } @Override public Map>> toMapListMap(PreparedStatement ps, Class mapKeyType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapListMap(ps, mapKeyType, mapValType, bindObjects); } @Override public Map>> toMapListMap(String sql, Class mapKeyType, Class mapValType, final Object... bindObjects) throws SQLException { return delegate.toMapListMap(prepareSql(sql, bindObjects), mapKeyType, mapValType, bindObjects); } }