From 2b8bc0c97f24aca3dfe6d098aebaa92e360cbbe0 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Fri, 31 Oct 2008 00:17:36 +0000 Subject: [PATCH] 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. --- .../samskivert/jdbc/depot/BindVisitor.java | 5 +- .../com/samskivert/jdbc/depot/KeySet.java | 11 +++- .../samskivert/jdbc/depot/MySQLBuilder.java | 8 +-- .../jdbc/depot/PostgreSQLBuilder.java | 51 ++++++++++++++----- .../com/samskivert/jdbc/depot/SQLBuilder.java | 4 +- 5 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/java/com/samskivert/jdbc/depot/BindVisitor.java b/src/java/com/samskivert/jdbc/depot/BindVisitor.java index 43d9dbd..41eea4f 100644 --- a/src/java/com/samskivert/jdbc/depot/BindVisitor.java +++ b/src/java/com/samskivert/jdbc/depot/BindVisitor.java @@ -21,6 +21,7 @@ package com.samskivert.jdbc.depot; import java.nio.ByteBuffer; +import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Map; @@ -261,9 +262,10 @@ public class BindVisitor implements ExpressionVisitor deleteClause.getWhereClause().accept(this); } - protected BindVisitor (DepotTypes types, PreparedStatement stmt) + protected BindVisitor (DepotTypes types, Connection conn, PreparedStatement stmt) { _types = types; + _conn = conn; _stmt = stmt; _argIdx = 1; } @@ -299,6 +301,7 @@ public class BindVisitor implements ExpressionVisitor } protected DepotTypes _types; + protected Connection _conn; protected PreparedStatement _stmt; protected int _argIdx; } diff --git a/src/java/com/samskivert/jdbc/depot/KeySet.java b/src/java/com/samskivert/jdbc/depot/KeySet.java index 442f0df..e5bb851 100644 --- a/src/java/com/samskivert/jdbc/depot/KeySet.java +++ b/src/java/com/samskivert/jdbc/depot/KeySet.java @@ -52,13 +52,22 @@ public class KeySet extends WhereClause _condition = new LiteralExp("false"); } 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) { throw new IllegalArgumentException("Cannot create where clause for more than " + Conditionals.In.MAX_KEYS + " at a time."); } // 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; for (Key key : keys) { keyFieldValues[ii++] = key.getValues().get(0); diff --git a/src/java/com/samskivert/jdbc/depot/MySQLBuilder.java b/src/java/com/samskivert/jdbc/depot/MySQLBuilder.java index 96d466f..21df188 100644 --- a/src/java/com/samskivert/jdbc/depot/MySQLBuilder.java +++ b/src/java/com/samskivert/jdbc/depot/MySQLBuilder.java @@ -117,8 +117,8 @@ public class MySQLBuilder public class MSBindVisitor extends BindVisitor { - protected MSBindVisitor (DepotTypes types, PreparedStatement stmt) { - super(types, stmt); + protected MSBindVisitor (DepotTypes types, Connection conn, PreparedStatement stmt) { + super(types, conn, stmt); } @Override public void visit (FullTextMatch match) { @@ -195,9 +195,9 @@ public class MySQLBuilder } @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 diff --git a/src/java/com/samskivert/jdbc/depot/PostgreSQLBuilder.java b/src/java/com/samskivert/jdbc/depot/PostgreSQLBuilder.java index 1d103a0..66e86ad 100644 --- a/src/java/com/samskivert/jdbc/depot/PostgreSQLBuilder.java +++ b/src/java/com/samskivert/jdbc/depot/PostgreSQLBuilder.java @@ -48,6 +48,7 @@ import com.samskivert.jdbc.depot.FieldMarshaller.ShortMarshaller; import com.samskivert.jdbc.depot.annotation.FullTextIndex; import com.samskivert.jdbc.depot.expression.EpochSeconds; 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.StringUtil; @@ -58,26 +59,28 @@ public class PostgreSQLBuilder { public class PGBuildVisitor extends BuildVisitor { - @Override public void visit (FullTextMatch match) - { + @Override public void visit (FullTextMatch match) { appendIdentifier("ftsCol_" + match.getName()); _builder.append(" @@ TO_TSQUERY('default', ?)"); } - public void visit (EpochSeconds epochSeconds) - { + @Override public void visit (EpochSeconds epochSeconds) { _builder.append("date_part('epoch', "); epochSeconds.getArgument().accept(this); _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); } - @Override protected void appendIdentifier (String field) - { + @Override protected void appendIdentifier (String field) { _builder.append("\"").append(field).append("\""); } } @@ -103,8 +106,32 @@ public class PostgreSQLBuilder } } - protected PGBindVisitor (DepotTypes types, PreparedStatement stmt) { - super(types, stmt); +// TODO: enable when we can require 1.6 support +// @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 - protected BindVisitor getBindVisitor (PreparedStatement stmt) + protected BindVisitor getBindVisitor (Connection conn, PreparedStatement stmt) { - return new PGBindVisitor(_types, stmt); + return new PGBindVisitor(_types, conn, stmt); } @Override diff --git a/src/java/com/samskivert/jdbc/depot/SQLBuilder.java b/src/java/com/samskivert/jdbc/depot/SQLBuilder.java index 1b71373..2683c60 100644 --- a/src/java/com/samskivert/jdbc/depot/SQLBuilder.java +++ b/src/java/com/samskivert/jdbc/depot/SQLBuilder.java @@ -78,7 +78,7 @@ public abstract class SQLBuilder } PreparedStatement stmt = conn.prepareStatement(_buildVisitor.getQuery()); - _bindVisitor = getBindVisitor(stmt); + _bindVisitor = getBindVisitor(conn, stmt); _clause.accept(_bindVisitor); if (PersistenceContext.DEBUG) { @@ -213,7 +213,7 @@ public abstract class SQLBuilder /** * 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.