You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by an...@apache.org on 2009/06/03 17:23:23 UTC

svn commit: r781429 - in /cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src: main/java/org/apache/cayenne/access/ main/java/org/apache/cayenne/access/jdbc/ main/java/org/apache/cayenne/access/trans/ main/java/org/apache/cayenne/map/ test/java...

Author: andrey
Date: Wed Jun  3 15:23:22 2009
New Revision: 781429

URL: http://svn.apache.org/viewvc?rev=781429&view=rev
Log:
CAY-1236 Allow providing custom INSERT, UPDATE, DELETE query builders

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainActionBuilder.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainBatchAction.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainDeleteQuery.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainInsertQuery.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainUpdateQuery.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BatchQueryBuilderFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/DefaultBatchQueryBuilderFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SoftDeleteBatchQueryBuilder.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SoftDeleteQueryBuilderFactory.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/jdbc/SoftDeleteBatchQueryBuilderTest.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/Locking.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/SoftTest.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/auto/_Locking.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/auto/_SoftTest.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomain.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainDeleteBucket.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainInsertBucket.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainUpdateBucket.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/DeleteBatchQueryBuilder.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DataMap.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/locking.map.xml

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomain.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomain.java?rev=781429&r1=781428&r2=781429&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomain.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomain.java Wed Jun  3 15:23:22 2009
@@ -30,6 +30,7 @@
 import org.apache.cayenne.DataChannel;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.QueryResponse;
+import org.apache.cayenne.access.jdbc.BatchQueryBuilderFactory;
 import org.apache.cayenne.cache.MapQueryCacheFactory;
 import org.apache.cayenne.cache.QueryCache;
 import org.apache.cayenne.cache.QueryCacheFactory;
@@ -117,6 +118,12 @@
     protected QueryCache queryCache;
 
     protected boolean stopped;
+    
+    /**
+     * Factory for creating QueryBuilders. Might be null, then default one will be used. 
+     * Server-only.
+     */
+    private BatchQueryBuilderFactory queryBuilderFactory;
 
     /**
      * Creates a DataDomain and assigns it a name.
@@ -919,4 +926,18 @@
     QueryCache getQueryCacheInternal() {
         return queryCache;
     }
+    
+    /**
+     * Sets factory for creating QueryBuilders
+     */
+    public void setQueryBuilderFactory(BatchQueryBuilderFactory queryBuilderFactory) {
+        this.queryBuilderFactory = queryBuilderFactory;
+    }
+    
+    /**
+     * @return factory for creating QueryBuilders. Might be null
+     */
+    public BatchQueryBuilderFactory getQueryBuilderFactory() {
+        return queryBuilderFactory;
+    }
 }

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainActionBuilder.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainActionBuilder.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainActionBuilder.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainActionBuilder.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,71 @@
+/*****************************************************************
+ *   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.cayenne.access;
+
+import org.apache.cayenne.access.jdbc.BatchAction;
+import org.apache.cayenne.query.BatchQuery;
+import org.apache.cayenne.query.EJBQLQuery;
+import org.apache.cayenne.query.ProcedureQuery;
+import org.apache.cayenne.query.Query;
+import org.apache.cayenne.query.SQLAction;
+import org.apache.cayenne.query.SQLActionVisitor;
+import org.apache.cayenne.query.SQLTemplate;
+import org.apache.cayenne.query.SelectQuery;
+
+/**
+ * Class for creating DataDomain-specific actions
+ */
+class DataDomainActionBuilder implements SQLActionVisitor {
+    DataDomain domain;
+    
+    SQLActionVisitor delegate;
+    
+    public DataDomainActionBuilder(DataDomain domain, SQLActionVisitor delegate) {
+        this.domain = domain;
+        this.delegate = delegate;
+    }
+    
+    public DataDomain getDomain() {
+        return domain;
+    }
+
+    public SQLAction batchAction(BatchQuery query) { 
+        return new DataDomainBatchAction(domain, (BatchAction) delegate.batchAction(query));
+    }
+
+    public SQLAction ejbqlAction(EJBQLQuery query) {
+        return delegate.ejbqlAction(query);
+    }
+
+    public SQLAction objectSelectAction(SelectQuery query) {
+        return delegate.objectSelectAction(query);
+    }
+
+    public SQLAction procedureAction(ProcedureQuery query) {
+        return delegate.procedureAction(query);
+    }
+
+    public SQLAction sqlAction(SQLTemplate query) {
+        return delegate.sqlAction(query);
+    }
+
+    public SQLAction updateAction(Query query) {
+        return delegate.updateAction(query);
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainBatchAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainBatchAction.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainBatchAction.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainBatchAction.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,40 @@
+/*****************************************************************
+ *   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.cayenne.access;
+
+import org.apache.cayenne.access.jdbc.BatchAction;
+import org.apache.cayenne.access.jdbc.BatchQueryBuilderFactory;
+
+/**
+ * Batch action, which contains information about DataDomain
+ */
+class DataDomainBatchAction extends BatchAction {
+    DataDomain domain;
+    
+    public DataDomainBatchAction(DataDomain domain, BatchAction prototype) {
+        super(prototype.getQuery(), prototype.getAdapter(), prototype.getEntityResolver());
+        setBatch(prototype.isBatch());
+        this.domain = domain;
+    }
+
+    @Override
+    protected BatchQueryBuilderFactory getBatchQueryBuilderFactory() {
+        return domain.getQueryBuilderFactory();
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainDeleteBucket.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainDeleteBucket.java?rev=781429&r1=781428&r2=781429&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainDeleteBucket.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainDeleteBucket.java Wed Jun  3 15:23:22 2009
@@ -108,8 +108,9 @@
 
                     DeleteBatchQuery batch = (DeleteBatchQuery) batches.get(batchKey);
                     if (batch == null) {
-                        batch = new DeleteBatchQuery(dbEntity, qualifierBuilder
-                                .getAttributes(), nullQualifierNames, 27);
+                        batch = new DataDomainDeleteQuery(parent.getDomain(),
+                                dbEntity, qualifierBuilder.getAttributes(), 
+                                nullQualifierNames, 27);
                         batch.setUsingOptimisticLocking(qualifierBuilder
                                 .isUsingOptimisticLocking());
                         batches.put(batchKey, batch);

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainDeleteQuery.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainDeleteQuery.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainDeleteQuery.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainDeleteQuery.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,55 @@
+/*****************************************************************
+ *   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.cayenne.access;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.query.DeleteBatchQuery;
+import org.apache.cayenne.query.SQLAction;
+import org.apache.cayenne.query.SQLActionVisitor;
+
+/**
+ * Delete query which contains information about DataDomain and creates special SQLAction
+ */
+class DataDomainDeleteQuery extends DeleteBatchQuery {
+    DataDomain domain;
+    
+    public DataDomainDeleteQuery(DataDomain domain, DbEntity dbEntity, int batchCapacity) {
+        this(domain, dbEntity, dbEntity.getPrimaryKeys(), Collections.EMPTY_SET, batchCapacity);
+    }
+
+    public DataDomainDeleteQuery(DataDomain domain, DbEntity dbEntity,
+            Collection<DbAttribute> qualifierAttributes, Collection<String> nullQualifierNames,
+            int batchCapacity) {
+        super(dbEntity, qualifierAttributes, nullQualifierNames, batchCapacity);
+        this.domain = domain; 
+    }   
+    
+    public DataDomain getDomain() {
+        return domain;
+    }
+    
+    @Override
+    public SQLAction createSQLAction(SQLActionVisitor visitor) {
+        return new DataDomainActionBuilder(domain, visitor).batchAction(this);
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainInsertBucket.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainInsertBucket.java?rev=781429&r1=781428&r2=781429&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainInsertBucket.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainInsertBucket.java Wed Jun  3 15:23:22 2009
@@ -60,7 +60,8 @@
             Collection<DbEntityClassDescriptor> descriptors = descriptorsByDbEntity
                     .get(dbEntity);
 
-            InsertBatchQuery batch = new InsertBatchQuery(dbEntity, 27);
+            InsertBatchQuery batch = 
+                new DataDomainInsertQuery(parent.getDomain(), dbEntity, 27);
             for (DbEntityClassDescriptor descriptor : descriptors) {
 
                 diffBuilder.reset(descriptor);

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainInsertQuery.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainInsertQuery.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainInsertQuery.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainInsertQuery.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,45 @@
+/*****************************************************************
+ *   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.cayenne.access;
+
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.query.InsertBatchQuery;
+import org.apache.cayenne.query.SQLAction;
+import org.apache.cayenne.query.SQLActionVisitor;
+
+/**
+ * Insert query which contains information about DataDomain and creates special SQLAction
+ */
+class DataDomainInsertQuery extends InsertBatchQuery {
+    DataDomain domain;
+
+    public DataDomainInsertQuery(DataDomain domain, DbEntity entity, int batchCapacity) {
+        super(entity, batchCapacity);
+        this.domain = domain;
+    }
+
+    public DataDomain getDomain() {
+        return domain;
+    }
+    
+    @Override
+    public SQLAction createSQLAction(SQLActionVisitor visitor) {
+        return new DataDomainActionBuilder(domain, visitor).batchAction(this);
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainUpdateBucket.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainUpdateBucket.java?rev=781429&r1=781428&r2=781429&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainUpdateBucket.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainUpdateBucket.java Wed Jun  3 15:23:22 2009
@@ -107,7 +107,8 @@
 
                     UpdateBatchQuery batch = (UpdateBatchQuery) batches.get(batchKey);
                     if (batch == null) {
-                        batch = new UpdateBatchQuery(
+                        batch = new DataDomainUpdateQuery(
+                                parent.getDomain(),
                                 dbEntity,
                                 qualifierBuilder.getAttributes(),
                                 updatedAttributes(dbEntity, snapshot),

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainUpdateQuery.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainUpdateQuery.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainUpdateQuery.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainUpdateQuery.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,51 @@
+/*****************************************************************
+ *   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.cayenne.access;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.query.SQLAction;
+import org.apache.cayenne.query.SQLActionVisitor;
+import org.apache.cayenne.query.UpdateBatchQuery;
+
+/**
+ * Update query which contains information about DataDomain and creates special SQLAction
+ */
+class DataDomainUpdateQuery extends UpdateBatchQuery {
+    DataDomain domain;
+
+    public DataDomainUpdateQuery(DataDomain domain, DbEntity dbEntity,
+            List<DbAttribute> qualifierAttributes, List<DbAttribute> updatedAttribute,
+            Collection<String> nullQualifierNames, int batchCapacity) {
+        super(dbEntity, qualifierAttributes, updatedAttribute, nullQualifierNames, batchCapacity);
+        this.domain = domain;
+    }
+
+    public DataDomain getDomain() {
+        return domain;
+    }
+    
+    @Override
+    public SQLAction createSQLAction(SQLActionVisitor visitor) {
+        return new DataDomainActionBuilder(domain, visitor).batchAction(this);
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java?rev=781429&r1=781428&r2=781429&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BatchAction.java Wed Jun  3 15:23:22 2009
@@ -34,9 +34,6 @@
 import org.apache.cayenne.access.QueryLogger;
 import org.apache.cayenne.access.ResultIterator;
 import org.apache.cayenne.access.trans.BatchQueryBuilder;
-import org.apache.cayenne.access.trans.DeleteBatchQueryBuilder;
-import org.apache.cayenne.access.trans.InsertBatchQueryBuilder;
-import org.apache.cayenne.access.trans.UpdateBatchQueryBuilder;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dba.TypesMapping;
 import org.apache.cayenne.map.DbAttribute;
@@ -60,6 +57,13 @@
         super(adapter, entityResolver);
         this.query = batchQuery;
     }
+    
+    /**
+     * @return Query which originated this action
+     */
+    public BatchQuery getQuery() {
+        return query;
+    }
 
     public boolean isBatch() {
         return batch;
@@ -82,16 +86,29 @@
             runAsIndividualQueries(connection, queryBuilder, observer, generatesKeys);
         }
     }
+    
+    /**
+     * @return factory that creates BatchQueryBuilders
+     */
+    protected BatchQueryBuilderFactory getBatchQueryBuilderFactory() {
+        return null;
+    }
 
     protected BatchQueryBuilder createBuilder() throws CayenneException {
+        BatchQueryBuilderFactory factory = getBatchQueryBuilderFactory();
+           
+        if (factory == null) {
+            factory = new DefaultBatchQueryBuilderFactory();
+        }
+        
         if (query instanceof InsertBatchQuery) {
-            return new InsertBatchQueryBuilder(getAdapter());
+            return factory.createInsertQueryBuilder(adapter);
         }
         else if (query instanceof UpdateBatchQuery) {
-            return new UpdateBatchQueryBuilder(getAdapter());
+            return factory.createUpdateQueryBuilder(adapter);
         }
         else if (query instanceof DeleteBatchQuery) {
-            return new DeleteBatchQueryBuilder(getAdapter());
+            return factory.createDeleteQueryBuilder(adapter);
         }
         else {
             throw new CayenneException("Unsupported batch query: " + query);

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BatchQueryBuilderFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BatchQueryBuilderFactory.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BatchQueryBuilderFactory.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/BatchQueryBuilderFactory.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,43 @@
+/*****************************************************************
+ *   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.cayenne.access.jdbc;
+
+import org.apache.cayenne.access.trans.BatchQueryBuilder;
+import org.apache.cayenne.dba.DbAdapter;
+
+/**
+ * Factory which creates BatchQueryBuilders for different types of queries,
+ * which, in their turn, create SQL strings
+ */
+public interface BatchQueryBuilderFactory {
+    /**
+     * Creates query builder for INSERT queries
+     */
+    public BatchQueryBuilder createInsertQueryBuilder(DbAdapter adapter);
+    
+    /**
+     * Creates query builder for UPDATE queries
+     */
+    public BatchQueryBuilder createUpdateQueryBuilder(DbAdapter adapter);
+    
+    /**
+     * Creates query builder for DELETE queries
+     */
+    public BatchQueryBuilder createDeleteQueryBuilder(DbAdapter adapter);
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/DefaultBatchQueryBuilderFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/DefaultBatchQueryBuilderFactory.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/DefaultBatchQueryBuilderFactory.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/DefaultBatchQueryBuilderFactory.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,44 @@
+/*****************************************************************
+ *   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.cayenne.access.jdbc;
+
+import org.apache.cayenne.access.trans.BatchQueryBuilder;
+import org.apache.cayenne.access.trans.DeleteBatchQueryBuilder;
+import org.apache.cayenne.access.trans.InsertBatchQueryBuilder;
+import org.apache.cayenne.access.trans.UpdateBatchQueryBuilder;
+import org.apache.cayenne.dba.DbAdapter;
+
+/**
+ * Default implementation of {@link #BatchQueryBuilderFactory}
+ */
+public class DefaultBatchQueryBuilderFactory implements BatchQueryBuilderFactory {
+
+    public BatchQueryBuilder createDeleteQueryBuilder(DbAdapter adapter) {
+        return new DeleteBatchQueryBuilder(adapter);
+    }
+
+    public BatchQueryBuilder createInsertQueryBuilder(DbAdapter adapter) {
+        return new InsertBatchQueryBuilder(adapter);
+    }
+
+    public BatchQueryBuilder createUpdateQueryBuilder(DbAdapter adapter) {
+        return new UpdateBatchQueryBuilder(adapter);
+    }
+    
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SoftDeleteBatchQueryBuilder.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SoftDeleteBatchQueryBuilder.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SoftDeleteBatchQueryBuilder.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SoftDeleteBatchQueryBuilder.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,92 @@
+/*****************************************************************
+ *   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.cayenne.access.jdbc;
+
+import java.io.IOException;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import org.apache.cayenne.access.trans.DeleteBatchQueryBuilder;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.query.BatchQuery;
+
+/**
+ * Implementation of {@link #DeleteBatchQueryBuilder}, which uses 'soft' delete
+ * (runs UPDATE and sets 'deleted' field to true instead-of running SQL DELETE)
+ */
+public class SoftDeleteBatchQueryBuilder extends DeleteBatchQueryBuilder {
+    private String deletedFieldName;
+
+    public SoftDeleteBatchQueryBuilder(DbAdapter adapter, String deletedFieldName) {
+        super(adapter);
+        this.deletedFieldName = deletedFieldName;
+    }
+    
+    @Override
+    public String createSqlString(BatchQuery batch) throws IOException {
+        if (!needSoftDelete(batch)) {
+            return super.createSqlString(batch);
+        }
+        
+        boolean status = batch.getDbEntity().getDataMap() != null 
+            && batch.getDbEntity().getDataMap().isQuotingSQLIdentifiers();
+        
+        QuotingStrategy strategy = getAdapter().getQuotingStrategy(status);
+       
+        StringBuffer query = new StringBuffer("UPDATE ");
+        query.append(strategy.quoteFullyQualifiedName(batch.getDbEntity()));
+        query.append(" SET ").append(strategy.quoteString(deletedFieldName)).append(" = ?");
+
+        applyQualifier(query, batch);
+
+        return query.toString();
+    }
+
+    @Override
+    protected int getFirstParameterIndex(BatchQuery query) {
+        return needSoftDelete(query) ? 2 : 1;
+    }
+    
+    @Override
+    public void bindParameters(PreparedStatement statement, BatchQuery query)
+            throws SQLException, Exception {
+        if (needSoftDelete(query)) {
+            //binding first parameter (which is 'deleted') as true
+            adapter.bindParameter(
+                    statement,
+                    true,
+                    1,
+                    Types.BOOLEAN,
+                    -1);
+        }
+        
+        super.bindParameters(statement, query);
+    }
+    
+    /**
+     * @return whether 'soft' deletion should be used
+     */
+    protected boolean needSoftDelete(BatchQuery query) {
+        DbAttribute attr = (DbAttribute) query.getDbEntity().getAttribute(deletedFieldName);
+        return attr != null && attr.getType() == Types.BOOLEAN;
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SoftDeleteQueryBuilderFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SoftDeleteQueryBuilderFactory.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SoftDeleteQueryBuilderFactory.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/jdbc/SoftDeleteQueryBuilderFactory.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,58 @@
+/*****************************************************************
+ *   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.cayenne.access.jdbc;
+
+import org.apache.cayenne.access.trans.BatchQueryBuilder;
+import org.apache.cayenne.dba.DbAdapter;
+
+/**
+ * Implementation of {@link #BatchQueryBuilderFactory}, which uses 'soft' delete
+ * (runs UPDATE and sets 'deleted' field to true instead-of running SQL DELETE)
+ */
+public class SoftDeleteQueryBuilderFactory extends DefaultBatchQueryBuilderFactory {
+    /**
+     * Default name of 'deleted' field
+     */
+    public static final String DEFAULT_DELETED_FIELD_NAME = "DELETED";
+    
+    /**
+     * Name of 'deleted' field
+     */
+    private String deletedFieldName;
+    
+    public SoftDeleteQueryBuilderFactory() {
+        this(DEFAULT_DELETED_FIELD_NAME);
+    }
+    
+    public SoftDeleteQueryBuilderFactory(String deletedFieldName) {
+        this.deletedFieldName = deletedFieldName;
+    }
+    
+    @Override
+    public BatchQueryBuilder createDeleteQueryBuilder(DbAdapter adapter) {
+        return new SoftDeleteBatchQueryBuilder(adapter, deletedFieldName);
+    }
+    
+    /**
+     * @return name of 'deleted' field
+     */
+    public String getDeletedFieldName() {
+        return deletedFieldName;
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/DeleteBatchQueryBuilder.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/DeleteBatchQueryBuilder.java?rev=781429&r1=781428&r2=781429&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/DeleteBatchQueryBuilder.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/DeleteBatchQueryBuilder.java Wed Jun  3 15:23:22 2009
@@ -42,21 +42,26 @@
 
     @Override
     public String createSqlString(BatchQuery batch) throws IOException {
-
-        DeleteBatchQuery deleteBatch = (DeleteBatchQuery) batch;
-
-        boolean status;
-        if(batch.getDbEntity().getDataMap()!=null && batch.getDbEntity().getDataMap().isQuotingSQLIdentifiers()){ 
-            status= true;
-        } else {
-            status = false;
-        }
+        boolean status = batch.getDbEntity().getDataMap() != null 
+            && batch.getDbEntity().getDataMap().isQuotingSQLIdentifiers();
+        
         QuotingStrategy strategy =  getAdapter().getQuotingStrategy(status);
        
         StringBuffer query = new StringBuffer("DELETE FROM ");
         query.append(strategy.quoteFullyQualifiedName(batch.getDbEntity()));
-        query.append(" WHERE ");
 
+        applyQualifier(query, batch);
+
+        return query.toString();
+    }
+    
+    /**
+     * Appends WHERE clause to SQL string
+     */
+    protected void applyQualifier(StringBuffer query, BatchQuery batch) {
+        query.append(" WHERE ");
+        
+        DeleteBatchQuery deleteBatch = (DeleteBatchQuery) batch;
         Iterator<DbAttribute> i = deleteBatch.getQualifierAttributes().iterator();
         while (i.hasNext()) {
             DbAttribute attribute = i.next();
@@ -67,8 +72,6 @@
                 query.append(" AND ");
             }
         }
-
-        return query.toString();
     }
 
     /**
@@ -80,7 +83,7 @@
 
         DeleteBatchQuery deleteBatch = (DeleteBatchQuery) query;
 
-        int parameterIndex = 1;
+        int parameterIndex = getFirstParameterIndex(query);
         int i = 0;
 
         for (DbAttribute attribute : deleteBatch.getQualifierAttributes()) {
@@ -99,5 +102,12 @@
                     attribute.getScale());
         }
     }
+    
+    /**
+     * @return index of first parameter in delete clause 
+     */
+    protected int getFirstParameterIndex(BatchQuery query) {
+        return 1;
+    }
 
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DataMap.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DataMap.java?rev=781429&r1=781428&r2=781429&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DataMap.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DataMap.java Wed Jun  3 15:23:22 2009
@@ -101,7 +101,7 @@
     public static final String DEFAULT_LOCK_TYPE_PROPERTY = "defaultLockType";
     
     public static final String DEFAULT_QUOTE_SQL_IDENTIFIERS_PROPERTY = "quoteSqlIdentifiers";
-
+    
     /**
      * The namespace in which the data map XML file will be created. This is also the URI to locate a copy of the schema document.
      */
@@ -1180,6 +1180,7 @@
      * 
      * @deprecated since 3.0 DataMap no longer implements DbAttributeListener
      */
+    @Deprecated
     public void dbAttributeChanged(AttributeEvent e) {
         Entity entity = e.getEntity();
         if (entity instanceof DbEntity) {
@@ -1192,6 +1193,7 @@
      * 
      * @deprecated since 3.0 DataMap no longer implements DbAttributeListener
      */
+    @Deprecated
     public void dbAttributeAdded(AttributeEvent e) {
         // does nothing currently
     }
@@ -1201,6 +1203,7 @@
      * 
      * @deprecated since 3.0 DataMap no longer implements DbAttributeListener
      */
+    @Deprecated
     public void dbAttributeRemoved(AttributeEvent e) {
         // does nothing currently
     }
@@ -1210,6 +1213,7 @@
      * 
      * @deprecated since 3.0 DataMap no longer implements DbRelationshipListener
      */
+    @Deprecated
     public void dbRelationshipChanged(RelationshipEvent e) {
         Entity entity = e.getEntity();
         if (entity instanceof DbEntity) {
@@ -1222,6 +1226,7 @@
      * 
      * @deprecated since 3.0 DataMap no longer implements DbRelationshipListener
      */
+    @Deprecated
     public void dbRelationshipAdded(RelationshipEvent e) {
         // does nothing currently
     }
@@ -1231,6 +1236,7 @@
      * 
      * @deprecated since 3.0 DataMap no longer implements DbRelationshipListener
      */
+    @Deprecated
     public void dbRelationshipRemoved(RelationshipEvent e) {
         // does nothing currently
     }
@@ -1282,6 +1288,7 @@
      * 
      * @deprecated since 3.0 DataMap no longer implements ObjAttributeListener
      */
+    @Deprecated
     public void objAttributeChanged(AttributeEvent e) {
         // does nothing currently
     }
@@ -1291,6 +1298,7 @@
      * 
      * @deprecated since 3.0 DataMap no longer implements ObjAttributeListener
      */
+    @Deprecated
     public void objAttributeAdded(AttributeEvent e) {
         // does nothing currently
     }
@@ -1300,6 +1308,7 @@
      * 
      * @deprecated since 3.0 DataMap no longer implements ObjAttributeListener
      */
+    @Deprecated
     public void objAttributeRemoved(AttributeEvent e) {
         // does nothing currently
     }
@@ -1309,6 +1318,7 @@
      * 
      * @deprecated since 3.0 DataMap no longer implements ObjRelationshipListener
      */
+    @Deprecated
     public void objRelationshipChanged(RelationshipEvent e) {
         // does nothing currently
     }
@@ -1318,6 +1328,7 @@
      * 
      * @deprecated since 3.0 DataMap no longer implements ObjRelationshipListener
      */
+    @Deprecated
     public void objRelationshipAdded(RelationshipEvent e) {
         // does nothing currently
     }
@@ -1327,6 +1338,7 @@
      * 
      * @deprecated since 3.0 DataMap no longer implements ObjRelationshipListener
      */
+    @Deprecated
     public void objRelationshipRemoved(RelationshipEvent e) {
         // does nothing currently
     }

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/jdbc/SoftDeleteBatchQueryBuilderTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/jdbc/SoftDeleteBatchQueryBuilderTest.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/jdbc/SoftDeleteBatchQueryBuilderTest.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/jdbc/SoftDeleteBatchQueryBuilderTest.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,175 @@
+/*****************************************************************
+ *   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.cayenne.access.jdbc;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cayenne.PersistenceState;
+import org.apache.cayenne.access.DataContext;
+import org.apache.cayenne.access.trans.DeleteBatchQueryBuilder;
+import org.apache.cayenne.dba.JdbcAdapter;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.query.DeleteBatchQuery;
+import org.apache.cayenne.query.SQLTemplate;
+import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.testdo.locking.SoftTest;
+import org.apache.cayenne.unit.LockingCase;
+import org.apache.cayenne.unit.util.ThreadedTestHelper;
+
+public class SoftDeleteBatchQueryBuilderTest extends LockingCase {
+    private DeleteBatchQueryBuilder createBuilder() {
+        return createBuilder(new JdbcAdapter());
+    }
+    
+    private DeleteBatchQueryBuilder createBuilder(JdbcAdapter adapter) {
+        return (DeleteBatchQueryBuilder) new SoftDeleteQueryBuilderFactory().
+            createDeleteQueryBuilder(adapter);
+    }
+
+    public void testCreateSqlString() throws Exception {
+        DbEntity entity = getDomain().getEntityResolver().lookupObjEntity(
+                SoftTest.class).getDbEntity();
+
+        List idAttributes = Collections.singletonList(entity
+                .getAttribute("SOFT_TEST_ID"));
+
+        DeleteBatchQuery deleteQuery = new DeleteBatchQuery(entity, idAttributes, null, 1);
+        DeleteBatchQueryBuilder builder = createBuilder();
+        String generatedSql = builder.createSqlString(deleteQuery);
+        assertNotNull(generatedSql);
+        assertEquals(
+                "UPDATE " + entity.getName() + " SET DELETED = ? WHERE SOFT_TEST_ID = ?",
+                generatedSql);
+    }
+
+    public void testCreateSqlStringWithNulls() throws Exception {
+        DbEntity entity = getDomain().getEntityResolver().lookupObjEntity(
+                SoftTest.class).getDbEntity();
+
+        List idAttributes = Arrays.asList(entity.getAttribute("SOFT_TEST_ID"), entity
+                .getAttribute("NAME"));
+
+        Collection nullAttributes = Collections.singleton("NAME");
+
+        DeleteBatchQuery deleteQuery = new DeleteBatchQuery(
+                entity,
+                idAttributes,
+                nullAttributes,
+                1);
+        DeleteBatchQueryBuilder builder = createBuilder();
+        String generatedSql = builder.createSqlString(deleteQuery);
+        assertNotNull(generatedSql);
+        assertEquals("UPDATE "
+                + entity.getName()
+                + " SET DELETED = ? WHERE SOFT_TEST_ID = ? AND NAME IS NULL", generatedSql);
+    }
+
+    public void testCreateSqlStringWithIdentifiersQuote() throws Exception {
+        DbEntity entity = getDomain().getEntityResolver().lookupObjEntity(
+                SoftTest.class).getDbEntity();
+        try {
+
+            entity.getDataMap().setQuotingSQLIdentifiers(true);
+            List idAttributes = Collections.singletonList(entity
+                    .getAttribute("SOFT_TEST_ID"));
+
+            DeleteBatchQuery deleteQuery = new DeleteBatchQuery(
+                    entity,
+                    idAttributes,
+                    null,
+                    1);
+            JdbcAdapter adapter = (JdbcAdapter) getAccessStackAdapter().getAdapter();
+            DeleteBatchQueryBuilder builder = createBuilder(adapter);
+            String generatedSql = builder.createSqlString(deleteQuery);
+            
+            String charStart = adapter.getIdentifiersStartQuote();
+            String charEnd = adapter.getIdentifiersEndQuote();
+
+            assertNotNull(generatedSql);
+            assertEquals("UPDATE "
+                    + charStart
+                    + entity.getName()
+                    + charEnd
+                    + " SET "
+                    + charStart
+                    + "DELETED"
+                    + charEnd
+                    + " = ? WHERE "
+                    + charStart
+                    + "SOFT_TEST_ID"
+                    + charEnd
+                    + " = ?", generatedSql);
+        }
+        finally {
+            entity.getDataMap().setQuotingSQLIdentifiers(false);
+        }
+
+    }
+    
+    public void testUpdate() throws Exception {
+        final DataContext context = createDataContext();
+        final DbEntity entity = context.getEntityResolver().lookupObjEntity(
+                SoftTest.class).getDbEntity();
+        
+        try {
+            context.getParentDataDomain().setQueryBuilderFactory(new SoftDeleteQueryBuilderFactory());
+            
+            final SoftTest test = context.newObject(SoftTest.class);
+            test.setName("SoftDeleteBatchQueryBuilderTest");
+            context.commitChanges();
+            
+            final SelectQuery query = new SelectQuery(SoftTest.class);
+            
+            new ThreadedTestHelper() {
+                @Override
+                protected void assertResult() throws Exception {
+                    query.setQualifier(ExpressionFactory.matchExp("name", test.getName()));
+                    assertEquals(1, context.performQuery(query).size());
+                    
+                    query.andQualifier(ExpressionFactory.matchDbExp("DELETED", true));
+                    assertEquals(0, context.performQuery(query).size());
+                }
+            }.assertWithTimeout(200);
+            
+            context.deleteObject(test);
+            assertEquals(test.getPersistenceState(), PersistenceState.DELETED);
+            context.commitChanges();
+            
+            new ThreadedTestHelper() {
+                @Override
+                protected void assertResult() throws Exception {
+                    query.setQualifier(ExpressionFactory.matchExp("name", test.getName()));
+                    assertEquals(1, context.performQuery(query).size());
+                    
+                    query.andQualifier(ExpressionFactory.matchDbExp("DELETED", true));
+                    assertEquals(1, context.performQuery(query).size());
+                }
+            }.assertWithTimeout(200);
+        }
+        finally {
+            context.performQuery(new SQLTemplate(entity, "DELETE FROM SOFT_TEST"));
+            context.getParentDataDomain().setQueryBuilderFactory(null);
+        }
+    }
+
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/Locking.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/Locking.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/Locking.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/Locking.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,18 @@
+package org.apache.cayenne.testdo.locking;
+
+import org.apache.cayenne.testdo.locking.auto._Locking;
+
+public class Locking extends _Locking {
+
+    private static Locking instance;
+
+    private Locking() {}
+
+    public static Locking getInstance() {
+        if(instance == null) {
+            instance = new Locking();
+        }
+
+        return instance;
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/SoftTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/SoftTest.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/SoftTest.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/SoftTest.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,7 @@
+package org.apache.cayenne.testdo.locking;
+
+import org.apache.cayenne.testdo.locking.auto._SoftTest;
+
+public class SoftTest extends _SoftTest {
+
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/auto/_Locking.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/auto/_Locking.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/auto/_Locking.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/auto/_Locking.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,12 @@
+package org.apache.cayenne.testdo.locking.auto;
+
+
+
+/**
+ * This class was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public class _Locking {
+}
\ No newline at end of file

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/auto/_SoftTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/auto/_SoftTest.java?rev=781429&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/auto/_SoftTest.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/testdo/locking/auto/_SoftTest.java Wed Jun  3 15:23:22 2009
@@ -0,0 +1,24 @@
+package org.apache.cayenne.testdo.locking.auto;
+
+import org.apache.cayenne.CayenneDataObject;
+
+/**
+ * Class _SoftTest was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _SoftTest extends CayenneDataObject {
+
+    public static final String NAME_PROPERTY = "name";
+
+    public static final String SOFT_TEST_ID_PK_COLUMN = "SOFT_TEST_ID";
+
+    public void setName(String name) {
+        writeProperty("name", name);
+    }
+    public String getName() {
+        return (String)readProperty("name");
+    }
+
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/locking.map.xml
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/locking.map.xml?rev=781429&r1=781428&r2=781429&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/locking.map.xml (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/resources/locking.map.xml Wed Jun  3 15:23:22 2009
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <data-map xmlns="http://cayenne.apache.org/schema/3.0/modelMap"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://cayenne.apache.org/schema/3.0/modelMap ../../main/resources/org/apache/cayenne/schema/3.0/modelMap.xsd"
-	project-version="3.0">
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://cayenne.apache.org/schema/3.0/modelMap http://cayenne.apache.org/schema/3.0/modelMap"
+  project-version="3.0">
 	<property name="defaultPackage" value="org.apache.cayenne.testdo.locking"/>
 	<db-entity name="DATE_LOCKING_TEST">
 		<db-attribute name="DATE_LOCK" type="DATE"/>
@@ -24,6 +24,11 @@
 		<db-attribute name="LOCKING_TEST_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 		<db-attribute name="NAME" type="VARCHAR" length="100"/>
 	</db-entity>
+	<db-entity name="SOFT_TEST">
+		<db-attribute name="DELETED" type="BOOLEAN"/>
+		<db-attribute name="NAME" type="VARCHAR" length="100"/>
+		<db-attribute name="SOFT_TEST_ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
 	<db-entity name="TIME_LOCKING_TEST">
 		<db-attribute name="NAME" type="VARCHAR" length="100"/>
 		<db-attribute name="TIME_LOCK" type="TIMESTAMP"/>
@@ -43,6 +48,9 @@
 		<obj-attribute name="description" type="java.lang.String" db-attribute-path="DESCRIPTION"/>
 		<obj-attribute name="name" type="java.lang.String" lock="true" db-attribute-path="NAME"/>
 	</obj-entity>
+	<obj-entity name="SoftTest" className="org.apache.cayenne.testdo.locking.SoftTest" dbEntityName="SOFT_TEST">
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
+	</obj-entity>
 	<obj-entity name="TimeLockingTestEntity" className="org.apache.cayenne.testdo.locking.TimeLockingTestEntity" lock-type="optimistic" dbEntityName="TIME_LOCKING_TEST">
 		<obj-attribute name="name" type="java.lang.String" db-attribute-path="NAME"/>
 		<obj-attribute name="timeLock" type="java.util.Date" lock="true" db-attribute-path="TIME_LOCK"/>