From: <ssk...@vh...> - 2005-09-01 06:51:52
|
Author: sskracic Date: 2005-09-01 08:42:59 +0200 (Thu, 01 Sep 2005) New Revision: 733 Modified: ccm-core/trunk/src/com/redhat/persistence/engine/rdbms/SQLWriter.java ccm-core/trunk/src/com/redhat/persistence/metadata/Adapter.java ccm-core/trunk/src/com/redhat/persistence/oql/Literal.java ccm-core/trunk/src/com/redhat/persistence/pdl/adapters/BooleanAd.java ccm-core/trunk/src/com/redhat/persistence/pdl/adapters/SimpleAdapter.java Log: Short story: added support for Postgres 8 JDBC driver. Long story: Postgres 8 JDBC driver does not tolerate our completely broken and incosistent management of Boolean values. Sometimes they're being treated as boolean, sometimes the SQL code assumes that '0' or '1' will be returned etc. Long term, this all should be fixed, for example by killing the idea of genuine Boolean altogether (since Oracle does not support it). In the meantime, this change implements a hack which prevents Boolean values to be provided via JDBC bind parameters for Postgres database driver. Instead their literal values are provided in text of SQL statement as either '0' or '1'. This had to be done to avoid errors thrown by PG 8 JDBC driver: "no such operator: boolean == varchar" etc. Those errors seem to be generated from (PG 8) JDBC client code, when bind parameters where booleans are expected are filled with setString(). If boolean values are provided as literal values '0' and '1', PG backend provides necessary casts automatically. Modified: ccm-core/trunk/src/com/redhat/persistence/engine/rdbms/SQLWriter.java =================================================================== --- ccm-core/trunk/src/com/redhat/persistence/engine/rdbms/SQLWriter.java 2005-08-29 12:21:39 UTC (rev 732) +++ ccm-core/trunk/src/com/redhat/persistence/engine/rdbms/SQLWriter.java 2005-09-01 06:42:59 UTC (rev 733) @@ -160,9 +160,21 @@ } void writeBind(Object value, int jdbcType) { - m_sql.append("?"); - m_bindings.add(value); - m_types.add(new Integer(jdbcType)); + boolean shouldBind = true; + Adapter ad = null; + if (value != null) { + Root root = m_engine.getSession().getRoot(); + ad = root.getAdapter(value.getClass()); + shouldBind = ad.isBindable(); + } + if (shouldBind) { + m_sql.append("?"); + m_bindings.add(value); + m_types.add(new Integer(jdbcType)); + } else { + m_sql.append(ad.getLiteralCode(value)); + } + } void write(Code code) { Modified: ccm-core/trunk/src/com/redhat/persistence/metadata/Adapter.java =================================================================== --- ccm-core/trunk/src/com/redhat/persistence/metadata/Adapter.java 2005-08-29 12:21:39 UTC (rev 732) +++ ccm-core/trunk/src/com/redhat/persistence/metadata/Adapter.java 2005-09-01 06:42:59 UTC (rev 733) @@ -93,6 +93,33 @@ ("not a bindable adapter: " + getClass().getName()); } + /** + * Determines whether the values can be provided via JDBC + * bind variables. It's normally set to 'true', unless we + * have some non-tolerant JDBC drivers (for example Postgres 8) + * which don't tolerate our completely broken and inconsistent + * management of Boolean values. If 'false', then the Adapter + * is responsible for providing the properly escaped String + * which will be a part of SQL statement text. + * + * @see getLiteralCode(Object) + */ + public boolean isBindable() { + throw new UnsupportedOperationException + ("not a bindable adapter: " + getClass().getName()); + } + + /** + * Inserts literal value of passed object in SQL statement text. + * This method must be overridden if isBindable() is false. + * + * @see isBindable() + */ + public String getLiteralCode(Object o) { + throw new UnsupportedOperationException + ("not a bindable adapter: " + getClass().getName()); + } + public void mutate(ResultSet rs, String column, Object obj, int type) throws SQLException { throw new UnsupportedOperationException Modified: ccm-core/trunk/src/com/redhat/persistence/oql/Literal.java =================================================================== --- ccm-core/trunk/src/com/redhat/persistence/oql/Literal.java 2005-08-29 12:21:39 UTC (rev 732) +++ ccm-core/trunk/src/com/redhat/persistence/oql/Literal.java 2005-09-01 06:42:59 UTC (rev 733) @@ -18,14 +18,10 @@ */ package com.redhat.persistence.oql; -// XXX: dependency on c.a.db.DbHelper -import com.arsdigita.db.DbHelper; import com.redhat.persistence.*; import com.redhat.persistence.common.*; import com.redhat.persistence.metadata.*; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.*; /** @@ -119,12 +115,16 @@ if (pmap.getObjectType().isCompound()) { bindcount = convert(pmap, result, root, key, bindcount); } else { - Object k = key == null ? null : - new CompoundKey(key, new Integer(bindcount)); - Code.Binding b = new Code.Binding - (k, value, ad.defaultJDBCType()); - result.add(new Code("?", Collections.singletonList(b))); - bindcount++; + if (ad.isBindable()) { + Object k = key == null ? null : + new CompoundKey(key, new Integer(bindcount)); + Code.Binding b = new Code.Binding + (k, value, ad.defaultJDBCType()); + result.add(new Code("?", Collections.singletonList(b))); + bindcount++; + } else { + result.add(new Code(ad.getLiteralCode(value))); + } } } Modified: ccm-core/trunk/src/com/redhat/persistence/pdl/adapters/BooleanAd.java =================================================================== --- ccm-core/trunk/src/com/redhat/persistence/pdl/adapters/BooleanAd.java 2005-08-29 12:21:39 UTC (rev 732) +++ ccm-core/trunk/src/com/redhat/persistence/pdl/adapters/BooleanAd.java 2005-09-01 06:42:59 UTC (rev 733) @@ -18,6 +18,7 @@ */ package com.redhat.persistence.pdl.adapters; +import com.arsdigita.db.DbHelper; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -51,6 +52,14 @@ } } + public boolean isBindable() { + return DbHelper.getDatabase() != DbHelper.DB_POSTGRES; + } + + public String getLiteralCode(Object o) { + return Boolean.TRUE.equals(o) ? "'1'" : "'0'"; + } + public Object fetch(ResultSet rs, String column) throws SQLException { boolean bool = rs.getBoolean(column); if (rs.wasNull()) { Modified: ccm-core/trunk/src/com/redhat/persistence/pdl/adapters/SimpleAdapter.java =================================================================== --- ccm-core/trunk/src/com/redhat/persistence/pdl/adapters/SimpleAdapter.java 2005-08-29 12:21:39 UTC (rev 732) +++ ccm-core/trunk/src/com/redhat/persistence/pdl/adapters/SimpleAdapter.java 2005-09-01 06:42:59 UTC (rev 733) @@ -57,4 +57,8 @@ return false; } + public boolean isBindable() { + return true; + } + } |