mirror of
https://github.com/moparisthebest/JdbcMapper
synced 2024-11-30 20:52:22 -05:00
Refactor BindInList, split out to InListUtil, add unit tests
This commit is contained in:
parent
ad7dc13dab
commit
2f8f293ed2
@ -8,6 +8,13 @@
|
|||||||
</parent>
|
</parent>
|
||||||
<artifactId>common</artifactId>
|
<artifactId>common</artifactId>
|
||||||
<name>${project.artifactId}</name>
|
<name>${project.artifactId}</name>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<finalName>${project.artifactId}</finalName>
|
<finalName>${project.artifactId}</finalName>
|
||||||
</build>
|
</build>
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.moparisthebest.jdbc.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class InListUtil {
|
||||||
|
|
||||||
|
private static <T> List<List<T>> split(final List<T> list, final int maxLength) {
|
||||||
|
final int listSize = list.size();
|
||||||
|
final List<List<T>> ret = new ArrayList<List<T>>();
|
||||||
|
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 static <T> StringBuilder buildCommaSeparatedList(final Iterable<T> list, final StringBuilder sb) {
|
||||||
|
boolean notFirst = false;
|
||||||
|
for (final T obj : list) {
|
||||||
|
if (notFirst) sb.append(',');
|
||||||
|
else notFirst = true;
|
||||||
|
sb.append('?');
|
||||||
|
}
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> StringBuilder buildInList(final Iterable<T> list, final StringBuilder sb, final String fieldName, final String listPrefix) {
|
||||||
|
return buildCommaSeparatedList(list, sb.append(fieldName).append(listPrefix)).append(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> String toInList(final String fieldName, final Collection<T> items, final int maxSize, final String listPrefix, final String listCombine) {
|
||||||
|
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, listPrefix).append(")").toString();
|
||||||
|
|
||||||
|
// else we need to split lists
|
||||||
|
boolean notFirst = false;
|
||||||
|
for (final List<T> item : split(items instanceof List ? (List<T>) items : new ArrayList<T>(items), maxSize)) {
|
||||||
|
if (notFirst) sb.append(listCombine);
|
||||||
|
else notFirst = true;
|
||||||
|
buildInList(item, sb, fieldName, listPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.append(")").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> String toInList(final String fieldName, final Collection<T> items, final int maxSize) {
|
||||||
|
return toInList(fieldName, items, maxSize, " IN (", " OR ");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> String toNotInList(final String fieldName, final Collection<T> items, final int maxSize) {
|
||||||
|
return toInList(fieldName, items, maxSize, " NOT IN (", " AND ");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
package com.moparisthebest.jdbc.util;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static com.moparisthebest.jdbc.util.InListUtil.toInList;
|
||||||
|
import static com.moparisthebest.jdbc.util.InListUtil.toNotInList;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class InListUtilTest {
|
||||||
|
|
||||||
|
private static Collection<Long> makeCollection(final int length) {
|
||||||
|
final Collection<Long> ret = new ArrayList<Long>(length);
|
||||||
|
final int loopLength = length + 1;
|
||||||
|
for(int x = 1; x < loopLength; ++x)
|
||||||
|
ret.add((long) x);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMakeCollection() {
|
||||||
|
assertEquals(new ArrayList<Long>(Arrays.asList(1L, 2L, 3L)), makeCollection(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShortInList() {
|
||||||
|
assertEquals("(column_name IN (?,?,?,?,?))", toInList("column_name", makeCollection(5), 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShortNotInList() {
|
||||||
|
assertEquals("(column_name NOT IN (?,?,?,?,?))", toNotInList("column_name", makeCollection(5), 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExactInList() {
|
||||||
|
assertEquals("(column_name IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?))",
|
||||||
|
toInList("column_name", makeCollection(20), 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExactNotInList() {
|
||||||
|
assertEquals("(column_name NOT IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?))",
|
||||||
|
toNotInList("column_name", makeCollection(20), 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneOverInList() {
|
||||||
|
assertEquals("(column_name IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) OR column_name IN (?))",
|
||||||
|
toInList("column_name", makeCollection(21), 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneOverNotInList() {
|
||||||
|
assertEquals("(column_name NOT IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) AND column_name NOT IN (?))",
|
||||||
|
toNotInList("column_name", makeCollection(21), 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneUnderInList() {
|
||||||
|
assertEquals("(column_name IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?))",
|
||||||
|
toInList("column_name", makeCollection(19), 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneUnderNotInList() {
|
||||||
|
assertEquals("(column_name NOT IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?))",
|
||||||
|
toNotInList("column_name", makeCollection(19), 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneOver3InList() {
|
||||||
|
assertEquals("(column_name IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) OR column_name IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) " +
|
||||||
|
"OR column_name IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) OR column_name IN (?))",
|
||||||
|
toInList("column_name", makeCollection(61), 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneOver3NotInList() {
|
||||||
|
assertEquals("(column_name NOT IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) AND column_name NOT IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) " +
|
||||||
|
"AND column_name NOT IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) AND column_name NOT IN (?))",
|
||||||
|
toNotInList("column_name", makeCollection(61), 20));
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,8 @@ package com.moparisthebest.jdbc;
|
|||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static com.moparisthebest.jdbc.util.InListUtil.toInList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mopar on 4/29/15.
|
* Created by mopar on 4/29/15.
|
||||||
*/
|
*/
|
||||||
@ -26,53 +28,9 @@ public class BindInList implements InList {
|
|||||||
this(defaultMaxSize);
|
this(defaultMaxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> List<List<T>> split(final List<T> list, final int maxLength) {
|
|
||||||
final int listSize = list.size();
|
|
||||||
final List<List<T>> ret = new ArrayList<List<T>>();
|
|
||||||
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 <T> String toInList(final String fieldName, final Collection<T> 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<T> item : split(new ArrayList<T>(items), maxSize)) {
|
|
||||||
if (notFirst) sb.append(" OR ");
|
|
||||||
else notFirst = true;
|
|
||||||
buildInList(item, sb, fieldName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.append(")").toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> StringBuilder buildInList(Iterable<T> list, StringBuilder sb, String fieldName) {
|
|
||||||
return oracleCommaSeparatedList(list, sb.append(fieldName).append(" IN (")).append(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> StringBuilder oracleCommaSeparatedList(Iterable<T> 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 <T> InListObject inList(final Connection conn, final String columnName, final Collection<T> values) {
|
public <T> InListObject inList(final Connection conn, final String columnName, final Collection<T> values) {
|
||||||
return values == null || values.isEmpty() ? InListObject.empty : new BindInListObject(
|
return values == null || values.isEmpty() ? InListObject.empty : new BindInListObject(
|
||||||
toInList(columnName, values),
|
toInList(columnName, values, this.maxSize),
|
||||||
values.toArray()
|
values.toArray()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user