From 9bb640f33410277e0c55efb392cf94183cdf9e34 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Mon, 27 Apr 2009 19:45:07 +0000 Subject: [PATCH] Detect our JDBC major version when starting Depot. If we are using JDBC4 then use JDBC4's array support when doing In() clauses for Postgres. --- .../samskivert/depot/PersistenceContext.java | 24 +++++- .../depot/impl/PostgreSQL4Builder.java | 76 +++++++++++++++++++ .../depot/impl/PostgreSQLBuilder.java | 31 +------- 3 files changed, 99 insertions(+), 32 deletions(-) create mode 100644 src/java/com/samskivert/depot/impl/PostgreSQL4Builder.java diff --git a/src/java/com/samskivert/depot/PersistenceContext.java b/src/java/com/samskivert/depot/PersistenceContext.java index 40e3fab..68c6cca 100644 --- a/src/java/com/samskivert/depot/PersistenceContext.java +++ b/src/java/com/samskivert/depot/PersistenceContext.java @@ -51,6 +51,7 @@ import com.samskivert.depot.impl.HSQLBuilder; import com.samskivert.depot.impl.Modifier; import com.samskivert.depot.impl.MySQLBuilder; import com.samskivert.depot.impl.Operation; +import com.samskivert.depot.impl.PostgreSQL4Builder; import com.samskivert.depot.impl.PostgreSQLBuilder; import com.samskivert.depot.impl.Query; import com.samskivert.depot.impl.SQLBuilder; @@ -66,7 +67,8 @@ public class PersistenceContext public static final boolean DEBUG = Boolean.getBoolean("com.samskivert.depot.debug"); /** Allow toggling of cache-related logging via a system property. */ - public static final boolean CACHE_DEBUG = Boolean.getBoolean("com.samskivert.depot.cache_debug"); + public static final boolean CACHE_DEBUG = + Boolean.getBoolean("com.samskivert.depot.cache_debug"); /** Map {@link TableGenerator} instances by name. */ public Map tableGenerators = Maps.newHashMap(); @@ -170,6 +172,19 @@ public class PersistenceContext _conprov = conprov; _liaison = LiaisonRegistry.getLiaison(conprov.getURL(ident)); _cache = adapter; + + // determine our JDBC major version + Connection conn = null; + try { + conn = _conprov.getConnection(_ident, true); + _jdbcMajorVersion = conn.getMetaData().getJDBCMajorVersion(); + } catch (Exception e) { + throw new DatabaseException("getJDBCMajorVersion failed [ident=" + ident + "].", e); + } finally { + if (conn != null) { + _conprov.releaseConnection(_ident, true, conn); + } + } } /** @@ -204,7 +219,11 @@ public class PersistenceContext public SQLBuilder getSQLBuilder (DepotTypes types) { if (_liaison instanceof PostgreSQLLiaison) { - return new PostgreSQLBuilder(types); + if (_jdbcMajorVersion >= 4) { + return new PostgreSQL4Builder(types); + } else { + return new PostgreSQLBuilder(types); + } } if (_liaison instanceof MySQLLiaison) { return new MySQLBuilder(types); @@ -603,6 +622,7 @@ public class PersistenceContext protected ConnectionProvider _conprov; protected DatabaseLiaison _liaison; protected boolean _warnOnLazyInit; + protected int _jdbcMajorVersion; /** Used to track various statistics. */ protected Stats _stats = new Stats(); diff --git a/src/java/com/samskivert/depot/impl/PostgreSQL4Builder.java b/src/java/com/samskivert/depot/impl/PostgreSQL4Builder.java new file mode 100644 index 0000000..8043de8 --- /dev/null +++ b/src/java/com/samskivert/depot/impl/PostgreSQL4Builder.java @@ -0,0 +1,76 @@ +// +// $Id$ +// +// Depot library - a Java relational persistence library +// Copyright (C) 2006-2008 Michael Bayne and Pär Winzell +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.samskivert.depot.impl; + +import java.sql.Connection; +import java.sql.PreparedStatement; + +import com.samskivert.depot.DatabaseException; +import com.samskivert.depot.operator.Conditionals.In; + +/** + * Specializes our PostgreSQL builder for JDBC4. + */ +public class PostgreSQL4Builder extends PostgreSQLBuilder +{ + public class PG4BuildVisitor extends PGBuildVisitor + { + @Override public Void visit (In in) { + in.getColumn().accept(this); + _builder.append(" = any (?)"); + final Comparable[] values = in.getValues(); + _bindables.add(new Bindable() { + public void doBind (Connection conn, PreparedStatement stmt, int argIdx) + throws Exception { + stmt.setObject(argIdx, conn.createArrayOf(getElementType(values), + (Object[])values)); + } + 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()); + } + } + }); + return null; + } + + protected PG4BuildVisitor (DepotTypes types) + { + super(types); + } + } + + public PostgreSQL4Builder (DepotTypes types) + { + super(types); + } + + @Override + protected BuildVisitor getBuildVisitor () + { + return new PG4BuildVisitor(_types); + } +} diff --git a/src/java/com/samskivert/depot/impl/PostgreSQLBuilder.java b/src/java/com/samskivert/depot/impl/PostgreSQLBuilder.java index f5ba58d..91f52c5 100644 --- a/src/java/com/samskivert/depot/impl/PostgreSQLBuilder.java +++ b/src/java/com/samskivert/depot/impl/PostgreSQLBuilder.java @@ -37,8 +37,8 @@ import com.samskivert.util.ArrayUtil; import com.samskivert.util.StringUtil; import com.samskivert.depot.PersistentRecord; -import com.samskivert.depot.annotation.FullTextIndex; import com.samskivert.depot.annotation.FullTextIndex.Configuration; +import com.samskivert.depot.annotation.FullTextIndex; import com.samskivert.depot.expression.EpochSeconds; import com.samskivert.depot.operator.Conditionals.FullText; @@ -84,35 +84,6 @@ public class PostgreSQLBuilder return null; } -// TODO: enable when we can require 1.6 support -// @Override public void visit (In in) { -// in.getColumn().accept(this); -// _builder.append(" = any (?)"); -// } - -// @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 FullTextIndex getFTIndex (FullText definition) { DepotMarshaller marsh = _types.getMarshaller(definition.getPersistentClass());