When we can switch entirely to 1.6 we can use Postgres's value = any(?::int[])

form to pass as many damned keys we want in a giant array. At that time we can
nix all the >32,768 key fiddly business.
This commit is contained in:
Michael Bayne
2008-10-31 00:17:36 +00:00
parent ec76d4d29f
commit 2b8bc0c97f
5 changed files with 59 additions and 20 deletions
@@ -21,6 +21,7 @@
package com.samskivert.jdbc.depot; package com.samskivert.jdbc.depot;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Map; import java.util.Map;
@@ -261,9 +262,10 @@ public class BindVisitor implements ExpressionVisitor
deleteClause.getWhereClause().accept(this); deleteClause.getWhereClause().accept(this);
} }
protected BindVisitor (DepotTypes types, PreparedStatement stmt) protected BindVisitor (DepotTypes types, Connection conn, PreparedStatement stmt)
{ {
_types = types; _types = types;
_conn = conn;
_stmt = stmt; _stmt = stmt;
_argIdx = 1; _argIdx = 1;
} }
@@ -299,6 +301,7 @@ public class BindVisitor implements ExpressionVisitor
} }
protected DepotTypes _types; protected DepotTypes _types;
protected Connection _conn;
protected PreparedStatement _stmt; protected PreparedStatement _stmt;
protected int _argIdx; protected int _argIdx;
} }
+10 -1
View File
@@ -52,13 +52,22 @@ public class KeySet<T extends PersistentRecord> extends WhereClause
_condition = new LiteralExp("false"); _condition = new LiteralExp("false");
} else if (keyFields.length == 1) { } else if (keyFields.length == 1) {
// TODO: remove when we update to 1.6 and change Postgres In handling
if (keys.size() > Conditionals.In.MAX_KEYS) { if (keys.size() > Conditionals.In.MAX_KEYS) {
throw new IllegalArgumentException("Cannot create where clause for more than " + throw new IllegalArgumentException("Cannot create where clause for more than " +
Conditionals.In.MAX_KEYS + " at a time."); Conditionals.In.MAX_KEYS + " at a time.");
} }
// Single-column keys result in the compact IN(keyVal1, keyVal2, ...) // Single-column keys result in the compact IN(keyVal1, keyVal2, ...)
Comparable<?>[] keyFieldValues = new Comparable<?>[keys.size()]; Comparable<?> first = keys.iterator().next().getValues().get(0);
Comparable<?>[] keyFieldValues;
if (first instanceof Integer) {
keyFieldValues = new Integer[keys.size()];
} else if (first instanceof Integer) {
keyFieldValues = new String[keys.size()];
} else {
keyFieldValues = new Comparable<?>[keys.size()];
}
int ii = 0; int ii = 0;
for (Key<T> key : keys) { for (Key<T> key : keys) {
keyFieldValues[ii++] = key.getValues().get(0); keyFieldValues[ii++] = key.getValues().get(0);
@@ -117,8 +117,8 @@ public class MySQLBuilder
public class MSBindVisitor extends BindVisitor public class MSBindVisitor extends BindVisitor
{ {
protected MSBindVisitor (DepotTypes types, PreparedStatement stmt) { protected MSBindVisitor (DepotTypes types, Connection conn, PreparedStatement stmt) {
super(types, stmt); super(types, conn, stmt);
} }
@Override public void visit (FullTextMatch match) { @Override public void visit (FullTextMatch match) {
@@ -195,9 +195,9 @@ public class MySQLBuilder
} }
@Override @Override
protected BindVisitor getBindVisitor (PreparedStatement stmt) protected BindVisitor getBindVisitor (Connection conn, PreparedStatement stmt)
{ {
return new MSBindVisitor(_types, stmt); return new MSBindVisitor(_types, conn, stmt);
} }
@Override @Override
@@ -48,6 +48,7 @@ import com.samskivert.jdbc.depot.FieldMarshaller.ShortMarshaller;
import com.samskivert.jdbc.depot.annotation.FullTextIndex; import com.samskivert.jdbc.depot.annotation.FullTextIndex;
import com.samskivert.jdbc.depot.expression.EpochSeconds; import com.samskivert.jdbc.depot.expression.EpochSeconds;
import com.samskivert.jdbc.depot.operator.Conditionals.FullTextMatch; import com.samskivert.jdbc.depot.operator.Conditionals.FullTextMatch;
import com.samskivert.jdbc.depot.operator.Conditionals.In;
import com.samskivert.util.ArrayUtil; import com.samskivert.util.ArrayUtil;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
@@ -58,26 +59,28 @@ public class PostgreSQLBuilder
{ {
public class PGBuildVisitor extends BuildVisitor public class PGBuildVisitor extends BuildVisitor
{ {
@Override public void visit (FullTextMatch match) @Override public void visit (FullTextMatch match) {
{
appendIdentifier("ftsCol_" + match.getName()); appendIdentifier("ftsCol_" + match.getName());
_builder.append(" @@ TO_TSQUERY('default', ?)"); _builder.append(" @@ TO_TSQUERY('default', ?)");
} }
public void visit (EpochSeconds epochSeconds) @Override public void visit (EpochSeconds epochSeconds) {
{
_builder.append("date_part('epoch', "); _builder.append("date_part('epoch', ");
epochSeconds.getArgument().accept(this); epochSeconds.getArgument().accept(this);
_builder.append(")"); _builder.append(")");
} }
protected PGBuildVisitor (DepotTypes types) // TODO: enable when we can require 1.6 support
{ // @Override public void visit (In in) {
// in.getColumn().accept(this);
// _builder.append(" = any (?)");
// }
protected PGBuildVisitor (DepotTypes types) {
super(types); super(types);
} }
@Override protected void appendIdentifier (String field) @Override protected void appendIdentifier (String field) {
{
_builder.append("\"").append(field).append("\""); _builder.append("\"").append(field).append("\"");
} }
} }
@@ -103,8 +106,32 @@ public class PostgreSQLBuilder
} }
} }
protected PGBindVisitor (DepotTypes types, PreparedStatement stmt) { // TODO: enable when we can require 1.6 support
super(types, stmt); // @Override public void visit (In in) {
// Comparable<?>[] values = in.getValues();
// try {
// _stmt.setObject(
// _argIdx++, _conn.createArrayOf(getElementType(values), (Object[])values));
// } catch (SQLException sqe) {
// throw new DatabaseException(
// "Failed to write value to statement [idx=" + (_argIdx-1) +
// ", values=" + StringUtil.safeToString(values) + "]", sqe);
// }
// }
// protected String getElementType (Comparable<?>[] values) {
// if (values instanceof Integer[]) {
// return "integer";
// } else if (values instanceof String[]) {
// return "character varying";
// } else {
// throw new DatabaseException(
// "Don't know how to make Postgres array for " + values.getClass());
// }
// }
protected PGBindVisitor (DepotTypes types, Connection conn, PreparedStatement stmt) {
super(types, conn, stmt);
} }
} }
@@ -203,9 +230,9 @@ public class PostgreSQLBuilder
} }
@Override @Override
protected BindVisitor getBindVisitor (PreparedStatement stmt) protected BindVisitor getBindVisitor (Connection conn, PreparedStatement stmt)
{ {
return new PGBindVisitor(_types, stmt); return new PGBindVisitor(_types, conn, stmt);
} }
@Override @Override
@@ -78,7 +78,7 @@ public abstract class SQLBuilder
} }
PreparedStatement stmt = conn.prepareStatement(_buildVisitor.getQuery()); PreparedStatement stmt = conn.prepareStatement(_buildVisitor.getQuery());
_bindVisitor = getBindVisitor(stmt); _bindVisitor = getBindVisitor(conn, stmt);
_clause.accept(_bindVisitor); _clause.accept(_bindVisitor);
if (PersistenceContext.DEBUG) { if (PersistenceContext.DEBUG) {
@@ -213,7 +213,7 @@ public abstract class SQLBuilder
/** /**
* Overridden by subclasses to create a dialect-specific {@link BindVisitor}. * Overridden by subclasses to create a dialect-specific {@link BindVisitor}.
*/ */
protected abstract BindVisitor getBindVisitor (PreparedStatement stmt); protected abstract BindVisitor getBindVisitor (Connection conn, PreparedStatement stmt);
/** /**
* Overridden by subclasses to figure the dialect-specific SQL type of the given field. * Overridden by subclasses to figure the dialect-specific SQL type of the given field.