21 changed files with 1003 additions and 333 deletions
@ -0,0 +1,108 @@
@@ -0,0 +1,108 @@
|
||||
package com.moparisthebest.jdbc; |
||||
|
||||
import com.moparisthebest.jdbc.codegen.JdbcMapper; |
||||
import com.moparisthebest.jdbc.util.Bindable; |
||||
import com.moparisthebest.jdbc.util.InListUtil; |
||||
import com.moparisthebest.jdbc.util.PreparedStatementUtil; |
||||
|
||||
import java.lang.reflect.Method; |
||||
import java.sql.Connection; |
||||
import java.sql.SQLException; |
||||
import java.util.Collection; |
||||
|
||||
/** |
||||
* For a column name and a Collection, return a Object usable by QueryMapper for binding to a PreparedStatement and |
||||
* ListQueryMapper for substituting in the query |
||||
*/ |
||||
public interface InList { |
||||
|
||||
InList defaultInList = InListObject.getDefaultInListInstance(); |
||||
|
||||
/** |
||||
* Returns an InList instance for use with this connection |
||||
* @param conn connection which may be inspected to determine best InList to use |
||||
* @return InList instance |
||||
*/ |
||||
public InList instance(final Connection conn); |
||||
|
||||
/** |
||||
* Returns an Object who's .toString returns a String for a query, and QueryMapper knows how to bind to a PreparedStatement |
||||
* @param columnName Column name for query |
||||
* @param values values for in list |
||||
* @return object |
||||
*/ |
||||
public <T> InListObject inList(final Connection conn, final String columnName, final Collection<T> values) throws SQLException; |
||||
|
||||
/** |
||||
* Returns an Object who's .toString returns a String for a query, and QueryMapper knows how to bind to a PreparedStatement |
||||
* @param columnName Column name for query |
||||
* @param values values for not in list |
||||
* @return object |
||||
*/ |
||||
public <T> InListObject notInList(final Connection conn, final String columnName, final Collection<T> values) throws SQLException; |
||||
|
||||
class InListObject implements Bindable { |
||||
static final InListObject inEmpty = new InListObject(InListUtil.inEmpty, null); |
||||
static final InListObject notInEmpty = new InListObject(InListUtil.notInEmpty, null); |
||||
|
||||
public static InListObject inEmpty() { |
||||
return inEmpty; |
||||
} |
||||
|
||||
public static InListObject notInEmpty() { |
||||
return notInEmpty; |
||||
} |
||||
|
||||
private final String sql; |
||||
private final Object bindObject; |
||||
|
||||
public InListObject(final String sql, final Object bindObject) { |
||||
this.sql = sql; |
||||
this.bindObject = bindObject; |
||||
} |
||||
|
||||
@Override |
||||
public final String toString() { |
||||
return sql; |
||||
} |
||||
|
||||
@Override |
||||
public Object getBindObject() { |
||||
return bindObject; |
||||
} |
||||
|
||||
private static InList getDefaultInListInstance() { |
||||
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")); |
||||
return (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")) { |
||||
return OptimalInList.instance(); |
||||
} else { |
||||
switch (JdbcMapper.DatabaseType.valueOf(type)) { |
||||
case DEFAULT: |
||||
case BIND: |
||||
return BindInList.instance(); |
||||
case ANY: |
||||
return ArrayInList.instance(); |
||||
case ORACLE: |
||||
return OracleArrayInList.instance(); |
||||
case UNNEST: |
||||
return UnNestArrayInList.instance(); |
||||
default: |
||||
throw new RuntimeException("Invalid queryMapper.databaseType: " + type); |
||||
} |
||||
} |
||||
} |
||||
} catch (Throwable e) { |
||||
// NEVER ignore
|
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
package com.moparisthebest.jdbc.util; |
||||
|
||||
import static com.moparisthebest.jdbc.util.PreparedStatementUtil.noBind; |
||||
|
||||
public interface Bindable { |
||||
|
||||
Bindable empty = new Bindable() { |
||||
@Override |
||||
public Object getBindObject() { |
||||
return noBind; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return ""; |
||||
} |
||||
}; |
||||
|
||||
/** |
||||
* This returns raw SQL to be included in a query, can contain bind params as standard ? |
||||
* @return |
||||
*/ |
||||
String toString(); |
||||
|
||||
/** |
||||
* This returns an object (or list of objects, or list of list etc) to bind to the SQL snippet returned by toString() |
||||
* PreparedStatementUtil must know how to bind this |
||||
* @return |
||||
*/ |
||||
Object getBindObject(); |
||||
} |
@ -0,0 +1,201 @@
@@ -0,0 +1,201 @@
|
||||
package com.moparisthebest.jdbc.util; |
||||
|
||||
import com.moparisthebest.jdbc.InList; |
||||
|
||||
import java.io.*; |
||||
import java.nio.charset.Charset; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.SQLException; |
||||
import java.util.Collection; |
||||
|
||||
//IFJAVA8_START
|
||||
import java.time.*; |
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8; |
||||
//IFJAVA8_END
|
||||
|
||||
public class PreparedStatementUtil { |
||||
|
||||
public static final Object noBind = new Object(); |
||||
|
||||
public static PreparedStatement bind(final PreparedStatement ps, final Object... bindObjects) throws SQLException { |
||||
recursiveBind(ps, bindObjects); |
||||
return ps; |
||||
} |
||||
|
||||
public static void setObject(final PreparedStatement ps, final int index, final Object o) throws SQLException { |
||||
// we are going to put most common ones up top so it should execute faster normally
|
||||
if (o == null || o instanceof String || o instanceof Number) |
||||
ps.setObject(index, o); |
||||
// java.util.Date support, put it in a Timestamp
|
||||
else if (o instanceof java.util.Date) |
||||
ps.setObject(index, o.getClass().equals(java.util.Date.class) ? new java.sql.Timestamp(((java.util.Date)o).getTime()) : o); |
||||
//IFJAVA8_START// todo: other java.time types
|
||||
else if (o instanceof Instant) |
||||
ps.setObject(index, java.sql.Timestamp.from((Instant)o)); |
||||
else if (o instanceof LocalDateTime) |
||||
ps.setObject(index, java.sql.Timestamp.valueOf((LocalDateTime)o)); |
||||
else if (o instanceof LocalDate) |
||||
ps.setObject(index, java.sql.Date.valueOf((LocalDate)o)); |
||||
else if (o instanceof LocalTime) |
||||
ps.setObject(index, java.sql.Time.valueOf((LocalTime)o)); |
||||
else if (o instanceof ZonedDateTime) |
||||
ps.setObject(index, java.sql.Timestamp.from(((ZonedDateTime)o).toInstant())); |
||||
else if (o instanceof OffsetDateTime) |
||||
ps.setObject(index, java.sql.Timestamp.from(((OffsetDateTime)o).toInstant())); |
||||
else if (o instanceof OffsetTime) |
||||
ps.setObject(index, java.sql.Time.valueOf(((OffsetTime)o).toLocalTime())); // todo: no timezone?
|
||||
|
||||
//IFJAVA8_END
|
||||
// CLOB support
|
||||
else if (o instanceof Reader) |
||||
ps.setClob(index, (Reader) o); |
||||
else if (o instanceof ClobString) |
||||
ps.setClob(index, ((ClobString) o).s == null ? null : new StringReader(((ClobString) o).s)); |
||||
else if (o instanceof java.sql.Clob) |
||||
ps.setClob(index, (java.sql.Clob) o); |
||||
// BLOB support
|
||||
else if (o instanceof byte[]) |
||||
ps.setBlob(index, new ByteArrayInputStream((byte[]) o)); |
||||
else if (o instanceof InputStream) |
||||
ps.setBlob(index, (InputStream) o); |
||||
else if (o instanceof File) |
||||
try { |
||||
ps.setBlob(index, new FileInputStream((File) o)); // todo: does this close this or leak a file descriptor?
|
||||
} catch (FileNotFoundException e) { |
||||
throw new SQLException("File to Blob FileNotFoundException", e); |
||||
} |
||||
else if (o instanceof BlobString) |
||||
ps.setBlob(index, ((BlobString) o).s == null ? null : new ByteArrayInputStream(((BlobString) o).s.getBytes(((BlobString) o).charset))); |
||||
else if (o instanceof java.sql.Blob) |
||||
ps.setBlob(index, (java.sql.Blob) o); |
||||
else if (o instanceof java.sql.Array) |
||||
ps.setArray(index, (java.sql.Array) o); |
||||
else if (o instanceof Enum) |
||||
ps.setObject(index, ((Enum)o).name()); |
||||
else |
||||
ps.setObject(index, o); // probably won't get here ever, but just in case...
|
||||
/* |
||||
switch(ps.getParameterMetaData().getParameterType(index)){ // 'java.sql.SQLException: Unsupported feature', fully JDBC 3.0 compliant my ass, freaking oracle...
|
||||
case Types.CLOB: |
||||
if(o instanceof String) |
||||
ps.setObject(index, o); |
||||
else if (o instanceof Reader) |
||||
ps.setClob(index, (Reader) o); |
||||
else if (o instanceof Clob) |
||||
ps.setClob(index, (Clob) o); |
||||
return; |
||||
case Types.BLOB: |
||||
if (o instanceof byte[]) |
||||
ps.setBlob(index, new ByteArrayInputStream((byte[])o)); |
||||
else if (o instanceof InputStream) |
||||
ps.setBlob(index, (InputStream) o); |
||||
else if (o instanceof File) |
||||
try { |
||||
ps.setBlob(index, new FileInputStream((File) o)); |
||||
} catch (FileNotFoundException e) { |
||||
throw new SQLException("File to Blob FileNotFoundException", e); |
||||
} |
||||
else if (o instanceof Blob) |
||||
ps.setBlob(index, (Blob) o); |
||||
else if(o instanceof String) |
||||
try{ |
||||
ps.setBlob(index, new ByteArrayInputStream(((String) o).getBytes("UTF-8"))); |
||||
}catch(UnsupportedEncodingException e){ |
||||
throw new SQLException("String to Blob UnsupportedEncodingException", e); |
||||
} |
||||
return; |
||||
default: |
||||
ps.setObject(index, o); |
||||
} |
||||
*/ |
||||
} |
||||
|
||||
public static int recursiveBind(final PreparedStatement ps, final Object... bindObjects) throws SQLException { |
||||
return recursiveBindIndex(ps, 0, bindObjects); |
||||
} |
||||
|
||||
public static int recursiveBindIndex(final PreparedStatement ps, int index, final Object... bindObjects) throws SQLException { |
||||
if (bindObjects != null && bindObjects.length > 0) { |
||||
for (final Object o : bindObjects) { |
||||
if (o != null) { |
||||
if (o == InList.InListObject.inEmpty() || o == InList.InListObject.notInEmpty() || o == noBind) { |
||||
continue; // ignore
|
||||
} else if (o instanceof Bindable) { |
||||
index = recursiveBindIndex(ps, index, ((Bindable) o).getBindObject()); |
||||
continue; |
||||
} else if (o instanceof Object[]) { |
||||
index = recursiveBindIndex(ps, index, (Object[]) o); |
||||
continue; |
||||
} else if (o instanceof Collection) { |
||||
// is creating 1 array and doing 1 method call faster than falling through to iterator and making multiple method calls/arrays? *probably* ?
|
||||
index = recursiveBindIndex(ps, index, ((Collection) o).toArray()); |
||||
continue; |
||||
} else if(o instanceof Iterable) { |
||||
for(final Object o2 : (Iterable) o) { |
||||
index = recursiveBindIndex(ps, index, o2); |
||||
} |
||||
continue; |
||||
} |
||||
} |
||||
//System.out.printf("index: '%d' bound to '%s'\n", index+1, o);
|
||||
setObject(ps, ++index, o); |
||||
//ps.setObject(++index, o);
|
||||
} |
||||
} |
||||
return index; |
||||
} |
||||
|
||||
public static Object wrapClob(String s) { |
||||
return new ClobString(s); |
||||
} |
||||
|
||||
public static Object wrapBlob(String s) { |
||||
return new BlobString(s, UTF_8); |
||||
} |
||||
|
||||
public static Object wrapBlob(final String s, final Charset charset) { |
||||
return new BlobString(s, charset == null ? UTF_8 : charset); |
||||
} |
||||
|
||||
private static class StringWrapper { |
||||
public final String s; |
||||
|
||||
private StringWrapper(String s) { |
||||
this.s = s; |
||||
} |
||||
|
||||
public String toString() { |
||||
return s; |
||||
} |
||||
|
||||
public boolean equals(Object o) { |
||||
if (this == o) return true; |
||||
if (!(o instanceof StringWrapper)) return false; |
||||
StringWrapper that = (StringWrapper) o; |
||||
return !(s != null ? !s.equals(that.s) : that.s != null); |
||||
} |
||||
|
||||
public int hashCode() { |
||||
return s != null ? s.hashCode() : 0; |
||||
} |
||||
} |
||||
|
||||
private static class ClobString extends StringWrapper { |
||||
private ClobString(String s) { |
||||
super(s); |
||||
} |
||||
} |
||||
|
||||
private static class BlobString extends StringWrapper { |
||||
private final Charset charset; |
||||
private BlobString(final String s, final Charset charset) { |
||||
super(s); |
||||
this.charset = charset; |
||||
} |
||||
} |
||||
|
||||
/*IFJAVA6_START |
||||
private static final Charset UTF_8 = Charset.forName("UTF-8"); |
||||
IFJAVA6_END*/ |
||||
} |
@ -0,0 +1,463 @@
@@ -0,0 +1,463 @@
|
||||
package com.moparisthebest.jdbc.util; |
||||
|
||||
import com.moparisthebest.jdbc.*; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.SQLException; |
||||
import java.util.*; |
||||
|
||||
//IFJAVA8_START
|
||||
import java.util.function.Consumer; |
||||
import java.util.function.Predicate; |
||||
import java.util.stream.IntStream; |
||||
import java.util.stream.Stream; |
||||
//IFJAVA8_END
|
||||
|
||||
import static com.moparisthebest.jdbc.InList.defaultInList; |
||||
|
||||
public class SqlBuilder implements Appendable, CharSequence, Collection<Object>, Bindable { |
||||
|
||||
private final StringBuilder sb; |
||||
private final Collection<Object> bindObjects; |
||||
|
||||
private final InList inList; |
||||
private final Connection conn; |
||||
|
||||
private SqlBuilder(final Connection conn, final InList inList, final StringBuilder sb, final Collection<Object> bindObjects) { |
||||
if(sb == null || bindObjects == null || inList == null || conn == null) |
||||
throw new NullPointerException("all arguments must be non-null"); |
||||
this.sb = sb; |
||||
this.bindObjects = bindObjects; |
||||
this.inList = inList.instance(conn); |
||||
this.conn = conn; |
||||
} |
||||
|
||||
public static SqlBuilder of(final Connection conn, final InList inList, final StringBuilder sb, final Collection<Object> bindObjects) { |
||||
return new SqlBuilder(conn, inList, sb, bindObjects); |
||||
} |
||||
|
||||
public static SqlBuilder of(final Connection conn) { |
||||
return new SqlBuilder(conn, defaultInList, new StringBuilder(), new ArrayList<Object>()); |
||||
} |
||||
|
||||
public static SqlBuilder of(final Connection conn, final Collection<Object> bindObjects) { |
||||
return new SqlBuilder(conn, defaultInList, new StringBuilder(), bindObjects); |
||||
} |
||||
|
||||
public static SqlBuilder of(final Connection conn, final StringBuilder sb) { |
||||
return new SqlBuilder(conn, defaultInList, sb, new ArrayList<Object>()); |
||||
} |
||||
|
||||
public static SqlBuilder of(final Connection conn, final InList inList) { |
||||
return new SqlBuilder(conn, inList, new StringBuilder(), new ArrayList<Object>()); |
||||
} |
||||
|
||||
// start custom SqlBuilder methods
|
||||
|
||||
public SqlBuilder append(final String sql, final Object bindObject) { |
||||
sb.append(sql); |
||||
this.bindObjects.add(bindObject); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder append(final String sql, final Object... bindObjects) { |
||||
return this.append(sql, (Object) bindObjects); |
||||
} |
||||
|
||||
public <T> SqlBuilder appendInList(final String columnName, final Collection<T> values) throws SQLException { |
||||
final InList.InListObject inListObject = inList.inList(conn, columnName, values); |
||||
return this.append(inListObject.toString(), inListObject.getBindObject()); |
||||
} |
||||
|
||||
public <T> SqlBuilder appendNotInList(final String columnName, final Collection<T> values) throws SQLException { |
||||
final InList.InListObject inListObject = inList.notInList(conn, columnName, values); |
||||
return this.append(inListObject.toString(), inListObject.getBindObject()); |
||||
} |
||||
|
||||
public StringBuilder getStringBuilder() { |
||||
return sb; |
||||
} |
||||
|
||||
@Override |
||||
public Collection<Object> getBindObject() { |
||||
return bindObjects; |
||||
} |
||||
|
||||
public InList getInList() { |
||||
return inList; |
||||
} |
||||
|
||||
public Connection getConnection() { |
||||
return conn; |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object o) { |
||||
if (this == o) return true; |
||||
if (!(o instanceof SqlBuilder)) return false; |
||||
|
||||
final SqlBuilder that = (SqlBuilder) o; |
||||
|
||||
return bindObjects.equals(that.bindObjects) && sb.toString().equals(that.sb.toString()); |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
int result = sb.toString().hashCode(); |
||||
result = 31 * result + bindObjects.hashCode(); |
||||
return result; |
||||
} |
||||
|
||||
// end custom SqlBuilder methods
|
||||
// start StringBuilder delegates
|
||||
|
||||
public SqlBuilder append(Object obj) { |
||||
sb.append(obj); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder append(String str) { |
||||
sb.append(str); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder append(StringBuffer sb) { |
||||
this.sb.append(sb); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public SqlBuilder append(CharSequence s) { |
||||
sb.append(s); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public SqlBuilder append(CharSequence s, int start, int end) { |
||||
sb.append(s, start, end); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder append(char[] str) { |
||||
sb.append(str); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder append(char[] str, int offset, int len) { |
||||
sb.append(str, offset, len); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder append(boolean b) { |
||||
sb.append(b); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public SqlBuilder append(char c) { |
||||
sb.append(c); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder append(int i) { |
||||
sb.append(i); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder append(long lng) { |
||||
sb.append(lng); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder append(float f) { |
||||
sb.append(f); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder append(double d) { |
||||
sb.append(d); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder appendCodePoint(int codePoint) { |
||||
sb.appendCodePoint(codePoint); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder delete(int start, int end) { |
||||
sb.delete(start, end); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder deleteCharAt(int index) { |
||||
sb.deleteCharAt(index); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder replace(int start, int end, String str) { |
||||
sb.replace(start, end, str); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder insert(int index, char[] str, int offset, int len) { |
||||
sb.insert(index, str, offset, len); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder insert(int offset, Object obj) { |
||||
sb.insert(offset, obj); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder insert(int offset, String str) { |
||||
sb.insert(offset, str); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder insert(int offset, char[] str) { |
||||
sb.insert(offset, str); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder insert(int dstOffset, CharSequence s) { |
||||
sb.insert(dstOffset, s); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder insert(int dstOffset, CharSequence s, int start, int end) { |
||||
sb.insert(dstOffset, s, start, end); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder insert(int offset, boolean b) { |
||||
sb.insert(offset, b); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder insert(int offset, char c) { |
||||
sb.insert(offset, c); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder insert(int offset, int i) { |
||||
sb.insert(offset, i); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder insert(int offset, long l) { |
||||
sb.insert(offset, l); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder insert(int offset, float f) { |
||||
sb.insert(offset, f); |
||||
return this; |
||||
} |
||||
|
||||
public SqlBuilder insert(int offset, double d) { |
||||
sb.insert(offset, d); |
||||
return this; |
||||
} |
||||
|
||||
public int indexOf(String str) { |
||||
return sb.indexOf(str); |
||||
} |
||||
|
||||
public int indexOf(String str, int fromIndex) { |
||||
return sb.indexOf(str, fromIndex); |
||||
} |
||||
|
||||
public int lastIndexOf(String str) { |
||||
return sb.lastIndexOf(str); |
||||
} |
||||
|
||||
public int lastIndexOf(String str, int fromIndex) { |
||||
return sb.lastIndexOf(str, fromIndex); |
||||
} |
||||
|
||||
public SqlBuilder reverse() { |
||||
sb.reverse(); |
||||
return this; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return sb.toString(); |
||||
} |
||||
|
||||
@Override |
||||
public int length() { |
||||
return sb.length(); |
||||
} |
||||
|
||||
public int capacity() { |
||||
return sb.capacity(); |
||||
} |
||||
|
||||
public void ensureCapacity(int minimumCapacity) { |
||||
sb.ensureCapacity(minimumCapacity); |
||||
} |
||||
|
||||
public void trimToSize() { |
||||
sb.trimToSize(); |
||||
} |
||||
|
||||
public void setLength(int newLength) { |
||||
sb.setLength(newLength); |
||||
} |
||||
|
||||
@Override |
||||
public char charAt(int index) { |
||||
return sb.charAt(index); |
||||
} |
||||
|
||||
public int codePointAt(int index) { |
||||
return sb.codePointAt(index); |
||||
} |
||||
|
||||
public int codePointBefore(int index) { |
||||
return sb.codePointBefore(index); |
||||
} |
||||
|
||||
public int codePointCount(int beginIndex, int endIndex) { |
||||
return sb.codePointCount(beginIndex, endIndex); |
||||
} |
||||
|
||||
public int offsetByCodePoints(int index, int codePointOffset) { |
||||
return sb.offsetByCodePoints(index, codePointOffset); |
||||
} |
||||
|
||||
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { |
||||
sb.getChars(srcBegin, srcEnd, dst, dstBegin); |
||||
} |
||||
|
||||
public void setCharAt(int index, char ch) { |
||||
sb.setCharAt(index, ch); |
||||
} |
||||
|
||||
public String substring(int start) { |
||||
return sb.substring(start); |
||||
} |
||||
|
||||
@Override |
||||
public CharSequence subSequence(int start, int end) { |
||||
return sb.subSequence(start, end); |
||||
} |
||||
|
||||
public String substring(int start, int end) { |
||||
return sb.substring(start, end); |
||||
} |
||||
|
||||
//IFJAVA8_START
|
||||
|
||||
@Override |
||||
public IntStream chars() { |
||||
return sb.chars(); |
||||
} |
||||
|
||||
@Override |
||||
public IntStream codePoints() { |
||||
return sb.codePoints(); |
||||
} |
||||
|
||||
//IFJAVA8_END
|
||||
|
||||
// end StringBuilder delegates
|
||||
// start Collection delegates
|
||||
|
||||
@Override |
||||
public int size() { |
||||
return bindObjects.size(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean isEmpty() { |
||||
return bindObjects.isEmpty(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean contains(Object o) { |
||||
return bindObjects.contains(o); |
||||
} |
||||
|
||||
@Override |
||||
public Iterator<Object> iterator() { |
||||
return bindObjects.iterator(); |
||||
} |
||||
|
||||
@Override |
||||
public Object[] toArray() { |
||||
return bindObjects.toArray(); |
||||
} |
||||
|
||||
@Override |
||||
public <T> T[] toArray(T[] a) { |
||||
return bindObjects.toArray(a); |
||||
} |
||||
|
||||
@Override |
||||
public boolean add(Object e) { |
||||
return bindObjects.add(e); |
||||
} |
||||
|
||||
@Override |
||||
public boolean remove(Object o) { |
||||
return bindObjects.remove(o); |
||||
} |
||||
|
||||
@Override |
||||
public boolean containsAll(Collection<?> c) { |
||||
return bindObjects.containsAll(c); |
||||
} |
||||
|
||||
@Override |
||||
public boolean addAll(Collection<? extends Object> c) { |
||||
return bindObjects.addAll(c); |
||||
} |
||||
|
||||
@Override |
||||
public boolean removeAll(Collection<?> c) { |
||||
return bindObjects.removeAll(c); |
||||
} |
||||
|
||||
@Override |
||||
public boolean retainAll(Collection<?> c) { |
||||
return bindObjects.retainAll(c); |
||||
} |
||||
|
||||
@Override |
||||
public void clear() { |
||||
bindObjects.clear(); |
||||
} |
||||
|
||||
//IFJAVA8_START
|
||||
|
||||
@Override |
||||
public boolean removeIf(Predicate<? super Object> filter) { |
||||
return bindObjects.removeIf(filter); |
||||
} |
||||
|
||||
@Override |
||||
public Spliterator<Object> spliterator() { |
||||
return bindObjects.spliterator(); |
||||
} |
||||
|
||||
@Override |
||||
public Stream<Object> stream() { |
||||
return bindObjects.stream(); |
||||
} |
||||
|
||||
@Override |
||||
public Stream<Object> parallelStream() { |
||||
return bindObjects.parallelStream(); |
||||
} |
||||
|
||||
@Override |
||||
public void forEach(Consumer<? super Object> action) { |
||||
bindObjects.forEach(action); |
||||
} |
||||
|
||||
//IFJAVA8_END
|
||||
|
||||
// end Collection delegates
|
||||
} |
@ -1,53 +0,0 @@
@@ -1,53 +0,0 @@
|
||||
package com.moparisthebest.jdbc; |
||||
|
||||
import com.moparisthebest.jdbc.util.InListUtil; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.SQLException; |
||||
import java.util.Collection; |
||||
|
||||
/** |
||||
* For a column name and a Collection, return a Object usable by QueryMapper for binding to a PreparedStatement and |
||||
* ListQueryMapper for substituting in the query |
||||
*/ |
||||
public interface InList { |
||||
|
||||
/** |
||||
* Returns an InList instance for use with this connection |
||||
* @param conn connection which may be inspected to determine best InList to use |
||||
* @return InList instance |
||||
*/ |
||||
public InList instance(final Connection conn); |
||||
|
||||
/** |
||||
* Returns an Object who's .toString returns a String for a query, and QueryMapper knows how to bind to a PreparedStatement |
||||
* @param columnName Column name for query |
||||
* @param values values for in list |
||||
* @return object |
||||
*/ |
||||
public <T> InListObject inList(final Connection conn, final String columnName, final Collection<T> values) throws SQLException; |
||||
|
||||
/** |
||||
* Returns an Object who's .toString returns a String for a query, and QueryMapper knows how to bind to a PreparedStatement |
||||
* @param columnName Column name for query |
||||
* @param values values for not in list |
||||
* @return object |
||||
*/ |
||||
public <T> InListObject notInList(final Connection conn, final String columnName, final Collection<T> values) throws SQLException; |
||||
|
||||
class InListObject { |
||||
static final InListObject inEmpty = new InListObject(InListUtil.inEmpty); |
||||
static final InListObject notInEmpty = new InListObject(InListUtil.notInEmpty); |
||||
|
||||
private final String sql; |
||||
|
||||
public InListObject(final String sql) { |
||||
this.sql = sql; |
||||
} |
||||
|
||||
@Override |
||||
public final String toString() { |
||||
return sql; |
||||
} |
||||
} |
||||
} |