Author: mikedd
Date: Mon Oct 18 22:07:41 2010
New Revision: 1024039

URL: http://svn.apache.org/viewvc?rev=1024039&view=rev
Log:
OPENJPA-1841: Allow DBDictionary to override IS NULL / IS NOT NULL clause for 
specific column types. 

Added:
    
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/
    
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/BlobEntity.java
   (with props)
    
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/TestBlobs.java
   (with props)
Modified:
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
    
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SybaseDictionary.java

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java?rev=1024039&r1=1024038&r2=1024039&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerFieldStrategy.java
 Mon Oct 18 22:07:41 2010
@@ -30,6 +30,7 @@ import org.apache.openjpa.jdbc.schema.Co
 import org.apache.openjpa.jdbc.schema.ColumnIO;
 import org.apache.openjpa.jdbc.schema.ForeignKey;
 import org.apache.openjpa.jdbc.schema.PrimaryKey;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
 import org.apache.openjpa.jdbc.sql.Joins;
 import org.apache.openjpa.jdbc.sql.Result;
 import org.apache.openjpa.jdbc.sql.Row;
@@ -243,22 +244,27 @@ public class HandlerFieldStrategy
     public void appendIsNull(SQLBuffer sql, Select sel, Joins joins) {
         joins = join(joins, false);
         for (int i = 0; i < _cols.length; i++) {
-            if (i > 0)
+            if (i > 0) {
                 sql.append(" AND ");
-            sql.append(sel.getColumnAlias(_cols[i], joins)).append(" IS ").
-                appendValue(null, _cols[i]);
+            }
+            // Some databases do not allow IS NULL for every column type - let 
the DBDictionary decide.
+            DBDictionary dict = sel.getDictionary();
+            sql.append(dict.getIsNullSQL(sel.getColumnAlias(_cols[i], joins), 
_cols[i].getType()));
         }
     }
 
     public void appendIsNotNull(SQLBuffer sql, Select sel, Joins joins) {
         joins = join(joins, false);
-        if (_cols.length > 1)
+        if (_cols.length > 1) {
             sql.append("(");
+        }
         for (int i = 0; i < _cols.length; i++) {
-            if (i > 0)
-                sql.append(" OR ");
-            sql.append(sel.getColumnAlias(_cols[i], joins)).
-                append(" IS NOT ").appendValue(null, _cols[i]);
+            if (i > 0) { 
+                sql.append(" OR "); 
+            }
+            // Some databases do not allow IS NOT NULL for every column type - 
let the DBDictionary decide.
+            DBDictionary dict = sel.getDictionary();
+            sql.append(dict.getIsNotNullSQL(sel.getColumnAlias(_cols[i], 
joins), _cols[i].getType()));
         }
         if (_cols.length > 1)
             sql.append(")");

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?rev=1024039&r1=1024038&r2=1024039&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
 Mon Oct 18 22:07:41 2010
@@ -5452,4 +5452,12 @@ public class DBDictionary
     public String getMarkerForInsertUpdate(Column col, Object val) {
         return "?";
     }
+
+    public String getIsNullSQL(String colAlias, int colType)  {
+        return String.format("%s IS NULL", colAlias); 
+    }
+    
+    public String getIsNotNullSQL(String colAlias, int colType) { 
+        return String.format("%s IS NOT NULL", colAlias);
+    }
 }

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java?rev=1024039&r1=1024038&r2=1024039&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
 Mon Oct 18 22:07:41 2010
@@ -927,6 +927,10 @@ public class LogicalUnion
         public List getExcludedJoinedTableClassMeta() {
             return sel.getExcludedJoinedTableClassMeta();
         }
+        
+        public DBDictionary getDictionary() { 
+            return dict; 
+        }
     }
 
     /**

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java?rev=1024039&r1=1024038&r2=1024039&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
 Mon Oct 18 22:07:41 2010
@@ -767,4 +767,6 @@ public interface Select
      * get joined table metadatas excluded for polymorphic queries
      */
     public List getExcludedJoinedTableClassMeta();
+    
+    public DBDictionary getDictionary() ; 
 }

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java?rev=1024039&r1=1024038&r2=1024039&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
 Mon Oct 18 22:07:41 2010
@@ -3032,6 +3032,10 @@ public class SelectImpl
     protected Selects newSelects() {
         return new Selects();
     }
+    
+    public DBDictionary getDictionary() { 
+        return _dict;
+    }
 
     /**
      * Helper class to track selected columns, with fast contains method.

Modified: 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SybaseDictionary.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SybaseDictionary.java?rev=1024039&r1=1024038&r2=1024039&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SybaseDictionary.java
 (original)
+++ 
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SybaseDictionary.java
 Mon Oct 18 22:07:41 2010
@@ -459,4 +459,24 @@ public class SybaseDictionary
             }
         }
     }
+    
+    @Override
+    public String getIsNullSQL(String colAlias, int colType)  {
+        switch(colType) {
+            case Types.BLOB:
+            case Types.CLOB:
+                return String.format("datalength(%s) = 0", colAlias);
+        }
+        return super.getIsNullSQL(colAlias, colType);
+    }
+    
+    @Override
+    public String getIsNotNullSQL(String colAlias, int colType) { 
+        switch(colType) { 
+            case Types.BLOB: 
+            case Types.CLOB:
+                return String.format("datalength(%s) != 0", colAlias);
+        }
+        return super.getIsNotNullSQL(colAlias, colType);
+    }
 }

Added: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/BlobEntity.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/BlobEntity.java?rev=1024039&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/BlobEntity.java
 (added)
+++ 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/BlobEntity.java
 Mon Oct 18 22:07:41 2010
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+ package org.apache.openjpa.persistence.blob;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Lob;
+import javax.persistence.Version;
+
+...@entity
+public class BlobEntity {
+    @Id
+    private int id;
+
+    @Version
+    private int version;
+
+    @Lob
+    protected String lobField;
+    @Lob
+    protected byte[] blobField;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getVersion() {
+        return version;
+    }
+
+    public void setVersion(int version) {
+        this.version = version;
+    }
+
+    public String getLobField() {
+        return lobField;
+    }
+
+    public void setLobField(String lobField) {
+        this.lobField = lobField;
+    }
+
+    public byte[] getBlobField() {
+        return blobField;
+    }
+
+    public void setBlobField(byte[] blobField) {
+        this.blobField = blobField;
+    }
+}

Propchange: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/BlobEntity.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/TestBlobs.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/TestBlobs.java?rev=1024039&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/TestBlobs.java
 (added)
+++ 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/TestBlobs.java
 Mon Oct 18 22:07:41 2010
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+ package org.apache.openjpa.persistence.blob;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+import javax.persistence.TypedQuery;
+
+import org.apache.openjpa.persistence.query.QueryBuilder;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+public class TestBlobs extends SingleEMFTestCase {
+
+    private int _populatedId = 1;
+    private int _nullLobId = 2;
+    private int _nullBlobId = 3;
+    private int _nullBothId = 4;
+
+    QueryBuilder qb = null;
+
+    public void setUp() {
+        super.setUp(BlobEntity.class, RETAIN_DATA);
+        cleanup();
+        populate();
+        qb = emf.getDynamicQueryBuilder();
+    }
+
+    protected void cleanup() {
+        EntityManager em = emf.createEntityManager();
+        em.getTransaction().begin();
+        em.createQuery("DELETE from BlobEntity").executeUpdate();
+        em.getTransaction().commit();
+        em.close();
+    }
+
+    protected void populate() {
+        EntityManager em = emf.createEntityManager();
+        EntityTransaction tran = em.getTransaction();
+        tran.begin();
+
+        BlobEntity be = new BlobEntity();
+        be.setId(_populatedId);
+        be.setLobField("abcdef");
+        be.setBlobField("abcdef".getBytes());
+        em.persist(be);
+
+        be = new BlobEntity();
+        be.setId(_nullLobId);
+        be.setLobField(null);
+        be.setBlobField("abcdef".getBytes());
+        em.persist(be);
+
+        be = new BlobEntity();
+        be.setId(_nullBlobId);
+        be.setLobField("abcdef");
+        be.setBlobField(null);
+        em.persist(be);
+
+        be = new BlobEntity();
+        be.setId(_nullBothId);
+        be.setLobField(null);
+        be.setBlobField(null);
+        em.persist(be);
+
+        tran.commit();
+        em.close();
+    }
+
+    public void testNotNullBlobQuery() {
+        EntityManager em = emf.createEntityManager();
+        TypedQuery<Integer> q =
+            em.createQuery("SELECT e.id FROM BlobEntity e where e.blobField IS 
NOT NULL", Integer.class);
+
+        List<Integer> ids = q.getResultList();
+        assertTrue(ids.contains(_populatedId));
+        assertTrue(ids.contains(_nullLobId));
+        assertFalse(ids.contains(_nullBlobId));
+        assertFalse(ids.contains(_nullBothId));
+        
+        em.close();
+    }
+
+    public void testNullBlobQuery() {
+        EntityManager em = emf.createEntityManager();
+        TypedQuery<Integer> q =
+            em.createQuery("SELECT e.id FROM BlobEntity e where e.blobField IS 
NULL", Integer.class);
+
+        List<Integer> ids = q.getResultList();
+        assertFalse(ids.contains(_populatedId));
+        assertFalse(ids.contains(_nullLobId));
+        assertTrue(ids.contains(_nullBlobId));
+        assertTrue(ids.contains(_nullBothId));
+        
+        em.close();
+    }
+
+    public void testNotNullLobQuery() {
+        EntityManager em = emf.createEntityManager();
+        TypedQuery<Integer> q =
+            em.createQuery("SELECT e.id FROM BlobEntity e where e.lobField IS 
NOT NULL", Integer.class);
+
+        List<Integer> ids = q.getResultList();
+        assertTrue(ids.contains(_populatedId));
+        assertFalse(ids.contains(_nullLobId));
+        assertTrue(ids.contains(_nullBlobId));
+        assertFalse(ids.contains(_nullBothId));
+        
+        em.close();
+    }
+
+    public void testNullLobQuery() {
+        EntityManager em = emf.createEntityManager();
+        TypedQuery<Integer> q =
+            em.createQuery("SELECT e.id FROM BlobEntity e where e.lobField IS 
NULL", Integer.class);
+
+        List<Integer> ids = q.getResultList();
+        assertFalse(ids.contains(_populatedId));
+        assertTrue(ids.contains(_nullLobId));
+        assertFalse(ids.contains(_nullBlobId));
+        assertTrue(ids.contains(_nullBothId));
+        
+        em.close();
+    }
+}

Propchange: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/blob/TestBlobs.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to