package com.moparisthebest.jdbc; import java.sql.Connection; import java.util.*; /** * Created by mopar on 4/29/15. */ public class BindInList implements InList { private static final int defaultMaxSize = Integer.parseInt(System.getProperty("QueryMapper.BindInList.defaultMaxSize", "999")); private static final InList instance = new BindInList(); public static InList instance() { return instance; } private final int maxSize; public BindInList(final int maxSize) { this.maxSize = maxSize; } protected BindInList() { this(defaultMaxSize); } private static List> split(final List list, final int maxLength) { final int listSize = list.size(); final List> ret = new ArrayList>(); if (listSize < maxLength) ret.add(list); else for (int fromIndex = 0, toIndex = maxLength; fromIndex < listSize; fromIndex = toIndex, toIndex += maxLength) ret.add(list.subList(fromIndex, toIndex > listSize ? listSize : toIndex)); return ret; } private String toInList(final String fieldName, final Collection items) { final StringBuilder sb = new StringBuilder("("); // do it quick if it will fit in one in-list if (items.size() < maxSize) // 999 or less return buildInList(items, sb, fieldName).append(")").toString(); // else we need to split lists boolean notFirst = false; for (final List item : split(new ArrayList(items), maxSize)) { if (notFirst) sb.append(" OR "); else notFirst = true; buildInList(item, sb, fieldName); } return sb.append(")").toString(); } private static StringBuilder buildInList(Iterable list, StringBuilder sb, String fieldName) { return oracleCommaSeparatedList(list, sb.append(fieldName).append(" IN (")).append(")"); } private static StringBuilder oracleCommaSeparatedList(Iterable list, StringBuilder sb) { boolean notFirst = false; for (final T obj : list) { // DO NOT DO THIS ANYMORE: if (obj == null) continue; if (notFirst) sb.append(','); else notFirst = true; sb.append('?'); } return sb; } public InListObject inList(final Connection conn, final String columnName, final Collection values) { return values == null || values.isEmpty() ? InListObject.empty : new BindInListObject( toInList(columnName, values), values.toArray() ); } class BindInListObject extends InListObject { private final Object[] bindObjects; public BindInListObject(final String sql, final Object[] bindObjects) { super(sql); this.bindObjects = bindObjects; } public Object[] getBindObjects() { return bindObjects; } } }