From 5a71283b5e73b257aa5df12a21f76e84bff83f36 Mon Sep 17 00:00:00 2001 From: samskivert 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. git-svn-id: https://samskivert.googlecode.com/svn/trunk@2465 6335cc39-0255-0410-8fd6-9bcaacd3b74c --- .../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 +- .../jdbc/depot/tests/TestRepository.java | 16 ++++-- 6 files changed, 72 insertions(+), 23 deletions(-) diff --git a/src/java/com/samskivert/jdbc/depot/BindVisitor.java b/src/java/com/samskivert/jdbc/depot/BindVisitor.java index 43d9dbda..41eea4fe 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 442f0dfe..e5bb8517 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 96d466f4..21df1883 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 1d103a06..66e86ad8 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 1b713732..2683c60c 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. diff --git a/src/java/com/samskivert/jdbc/depot/tests/TestRepository.java b/src/java/com/samskivert/jdbc/depot/tests/TestRepository.java index 1491b8d9..fe291234 100644 --- a/src/java/com/samskivert/jdbc/depot/tests/TestRepository.java +++ b/src/java/com/samskivert/jdbc/depot/tests/TestRepository.java @@ -22,17 +22,21 @@ package com.samskivert.jdbc.depot.tests; import java.sql.Date; import java.sql.Timestamp; +import java.util.HashSet; import java.util.Set; -import com.samskivert.jdbc.StaticConnectionProvider; import com.samskivert.util.RandomUtil; + +import com.samskivert.jdbc.StaticConnectionProvider; import com.samskivert.jdbc.depot.DepotRepository; -import com.samskivert.jdbc.depot.SchemaMigration; +import com.samskivert.jdbc.depot.Key; +import com.samskivert.jdbc.depot.KeySet; import com.samskivert.jdbc.depot.PersistenceContext; import com.samskivert.jdbc.depot.PersistentRecord; +import com.samskivert.jdbc.depot.SchemaMigration; +import com.samskivert.jdbc.depot.clause.Where; import com.samskivert.jdbc.depot.expression.LiteralExp; import com.samskivert.jdbc.depot.operator.Conditionals; -import com.samskivert.jdbc.depot.clause.Where; /** * A test tool for the Depot repository services. @@ -98,6 +102,12 @@ public class TestRepository extends DepotRepository TestRecord.RECORD_ID_C, CREATE_RECORDS/2))); System.out.println("Now have " + repo.findAll(TestRecord.class).size() + " records."); repo.deleteAll(TestRecord.class, new Where(new LiteralExp("true"))); +// // TODO: try to break our In() clause +// Set> ids = new HashSet>(); +// for (int ii = 1; ii <= Conditionals.In.MAX_KEYS*2+3; ii++) { +// ids.add(TestRecord.getKey(ii)); +// } +// repo.deleteAll(TestRecord.class, new KeySet(TestRecord.class, ids)); System.out.println("Now have " + repo.findAll(TestRecord.class).size() + " records."); }