On Tue, 2006-05-09 at 09:30 -0400, Andrus Adamchik wrote:
> I think you can select files in question and then do "Team -> Add to  
> Version Control" and then do a diff.

Ah! It works. 

I didn't think to try it since I've got read-only access to the
repository.

Attached is an example using the MSAccess adapter.

-- 
Øyvind Harboe
http://www.zylin.com
Index: C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/AutoAdapter.java
===================================================================
--- C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/AutoAdapter.java	(revision 405312)
+++ C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/AutoAdapter.java	(working copy)
@@ -77,6 +77,7 @@
 import org.objectstyle.cayenne.dba.frontbase.FrontBaseSniffer;
 import org.objectstyle.cayenne.dba.hsqldb.HSQLDBSniffer;
 import org.objectstyle.cayenne.dba.ingres.IngresSniffer;
+import org.objectstyle.cayenne.dba.msaccess.MSAccessSniffer;
 import org.objectstyle.cayenne.dba.mysql.MySQLSniffer;
 import org.objectstyle.cayenne.dba.openbase.OpenBaseSniffer;
 import org.objectstyle.cayenne.dba.oracle.OracleSniffer;
@@ -105,7 +106,8 @@
             new MySQLSniffer(), new PostgresSniffer(), new OracleSniffer(),
             new SQLServerSniffer(), new HSQLDBSniffer(), new DB2Sniffer(),
             new SybaseSniffer(), new DerbySniffer(), new OpenBaseSniffer(),
-            new FirebirdSniffer(), new FrontBaseSniffer(), new IngresSniffer()
+            new FirebirdSniffer(), new FrontBaseSniffer(), new IngresSniffer(),
+            new MSAccessSniffer()
     };
 
     /**
Index: C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/MSAccessActionBuilder.java
===================================================================
--- C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/MSAccessActionBuilder.java	(revision 0)
+++ C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/MSAccessActionBuilder.java	(revision 0)
@@ -0,0 +1,31 @@
+package org.objectstyle.cayenne.dba.msaccess;
+
+import org.objectstyle.cayenne.access.jdbc.BatchAction;
+import org.objectstyle.cayenne.dba.DbAdapter;
+import org.objectstyle.cayenne.dba.JdbcActionBuilder;
+import org.objectstyle.cayenne.map.EntityResolver;
+import org.objectstyle.cayenne.query.BatchQuery;
+import org.objectstyle.cayenne.query.SQLAction;
+
+public class MSAccessActionBuilder extends JdbcActionBuilder
+{
+
+    public MSAccessActionBuilder(DbAdapter adapter, EntityResolver resolver)
+	{
+		super(adapter, resolver);
+	}
+
+
+    public SQLAction batchAction(BatchQuery query) {
+        // check run strategy...
+
+        // optimistic locking is not supported in batches due to JDBC driver limitations
+        boolean useOptimisticLock = query.isUsingOptimisticLocking();
+
+        boolean runningAsBatch = !useOptimisticLock && adapter.supportsBatchUpdates();
+        BatchAction action = new MSAccessBatchAction(query, adapter, entityResolver);
+        action.setBatch(runningAsBatch);
+        return action;
+    }
+
+}
Index: C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/MSAccessAdapter.java
===================================================================
--- C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/MSAccessAdapter.java	(revision 0)
+++ C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/MSAccessAdapter.java	(revision 0)
@@ -0,0 +1,22 @@
+package org.objectstyle.cayenne.dba.msaccess;
+
+import org.objectstyle.cayenne.access.DataNode;
+import org.objectstyle.cayenne.dba.JdbcAdapter;
+import org.objectstyle.cayenne.query.Query;
+import org.objectstyle.cayenne.query.SQLAction;
+
+/**
+ **/
+public class MSAccessAdapter extends JdbcAdapter {
+
+
+    public MSAccessAdapter()
+    {
+    	setSupportsGeneratedKeys(true);
+    }
+    public SQLAction getAction(Query query, DataNode node) {
+        return query.createSQLAction(new MSAccessActionBuilder(this, node
+                .getEntityResolver()));
+    }    
+
+ }
\ No newline at end of file
Index: C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/MSAccessBatchAction.java
===================================================================
--- C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/MSAccessBatchAction.java	(revision 0)
+++ C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/MSAccessBatchAction.java	(revision 0)
@@ -0,0 +1,143 @@
+package org.objectstyle.cayenne.dba.msaccess;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Collections;
+import java.util.Map;
+
+import org.objectstyle.cayenne.CayenneException;
+import org.objectstyle.cayenne.access.OperationObserver;
+import org.objectstyle.cayenne.access.OptimisticLockException;
+import org.objectstyle.cayenne.access.QueryLogger;
+import org.objectstyle.cayenne.access.ResultIterator;
+import org.objectstyle.cayenne.access.jdbc.BatchAction;
+import org.objectstyle.cayenne.access.jdbc.JDBCResultIterator;
+import org.objectstyle.cayenne.access.jdbc.RowDescriptor;
+import org.objectstyle.cayenne.access.trans.BatchQueryBuilder;
+import org.objectstyle.cayenne.dba.DbAdapter;
+import org.objectstyle.cayenne.map.EntityResolver;
+import org.objectstyle.cayenne.query.BatchQuery;
+import org.objectstyle.cayenne.query.DeleteBatchQuery;
+import org.objectstyle.cayenne.query.UpdateBatchQuery;
+
+/**
+ * Extracts generated primary key for MS Access databases. Note that only a single
+ * generated column is supported.
+ * 
+ */
+public class MSAccessBatchAction extends BatchAction {
+
+	public MSAccessBatchAction(BatchQuery batchQuery, DbAdapter adapter,
+           EntityResolver entityResolver) 
+   {
+       super(batchQuery, adapter, entityResolver);
+   }
+
+	protected void runAsIndividualQueries(Connection connection, BatchQueryBuilder queryBuilder, OperationObserver delegate, boolean generatesKeys) throws SQLException, Exception
+	{
+
+        boolean isLoggable = QueryLogger.isLoggable();
+        boolean useOptimisticLock = query.isUsingOptimisticLocking();
+
+        String queryStr = queryBuilder.createSqlString(query);
+
+        // log batch SQL execution
+        QueryLogger.logQuery(queryStr, Collections.EMPTY_LIST);
+
+        // run batch queries one by one
+        query.reset();
+        
+        // here a bit of woodoo to support generated keys....
+        PreparedStatement statement = connection.prepareStatement(queryStr);
+        try {
+            while (query.next()) {
+                if (isLoggable) {
+                    QueryLogger.logQueryParameters("bind", queryBuilder
+                            .getParameterValues(query));
+                }
+
+                queryBuilder.bindParameters(statement, query);
+
+                int updated = statement.executeUpdate();
+                if (useOptimisticLock && updated != 1) {
+
+                    Map snapshot = Collections.EMPTY_MAP;
+                    if (query instanceof UpdateBatchQuery) {
+                        snapshot = ((UpdateBatchQuery) query).getCurrentQualifier();
+                    }
+                    else if (query instanceof DeleteBatchQuery) {
+                        snapshot = ((DeleteBatchQuery) query).getCurrentQualifier();
+                    }
+
+                    throw new OptimisticLockException(
+                            query.getDbEntity(),
+                            queryStr,
+                            snapshot);
+                }
+
+                delegate.nextCount(query, updated);
+
+                if (generatesKeys) 
+                {
+                	String findPrimKey = "SELECT @@IDENTITY";
+                    QueryLogger.logQuery(findPrimKey, Collections.EMPTY_LIST);
+                    
+                	Statement fetchPrimKey = connection.createStatement();
+                	try
+                	{
+                		fetchPrimKey.executeQuery(findPrimKey);
+                		processGeneratedKeys(fetchPrimKey, delegate);
+                	} finally
+                	{
+                		try
+                		{
+                			fetchPrimKey.close();
+                		} catch (Throwable e)
+                		{
+                		}
+                	}
+                }
+
+                if (isLoggable) {
+                    QueryLogger.logUpdateCount(updated);
+                }
+            }
+        }
+        finally {
+            try {
+                statement.close();
+            }
+            catch (Exception e) {
+            }
+        }
+	}
+	
+    /**
+     * Implements generated keys extraction supported by MS Access
+     * 
+     */
+    protected void processGeneratedKeys(Statement statement, OperationObserver observer)
+            throws SQLException, CayenneException {
+
+        /* 
+         * The only difference between JDBC 3.0 & MS Access extraction for this fn.
+         * is that we invoke getResultSet() here on the query that found the
+         * latest primary key insterted.
+         */
+        ResultSet keysRS = statement.getResultSet();
+        RowDescriptor descriptor = new RowDescriptor(keysRS, getAdapter()
+                .getExtendedTypes());
+        ResultIterator iterator = new JDBCResultIterator(
+                null,
+                null,
+                keysRS,
+                descriptor,
+                0);
+
+        observer.nextGeneratedDataRows(query, iterator);
+    }
+
+}
Index: C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/MSAccessSniffer.java
===================================================================
--- C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/MSAccessSniffer.java	(revision 0)
+++ C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/MSAccessSniffer.java	(revision 0)
@@ -0,0 +1,22 @@
+package org.objectstyle.cayenne.dba.msaccess;
+
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+import org.objectstyle.cayenne.dba.DbAdapter;
+import org.objectstyle.cayenne.dba.DbAdapterFactory;
+
+public class MSAccessSniffer implements DbAdapterFactory {
+
+    public DbAdapter createAdapter(DatabaseMetaData md) throws SQLException {
+        String dbName = md.getDatabaseProductName();
+        if (dbName == null || dbName.toUpperCase().indexOf("ACCESS") < 0) {
+            return null;
+        }
+
+        MSAccessAdapter adapter = new MSAccessAdapter();
+
+        adapter.setSupportsGeneratedKeys(true);
+        return adapter;
+    }
+}
Index: C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/package.html
===================================================================
--- C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/package.html	(revision 0)
+++ C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/package.html	(revision 0)
@@ -0,0 +1,5 @@
+<html>
+<body>
+Microsoft Access DbAdapter.
+</body>
+</html>
\ No newline at end of file
Index: C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/types.xml
===================================================================
--- C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/types.xml	(revision 0)
+++ C:/workspace/cayenne-java/src/cayenne/java/org/objectstyle/cayenne/dba/msaccess/types.xml	(revision 0)
@@ -0,0 +1,78 @@
+<?xml version="1.0"?>
+
+<!-- MS SQL Server types mapping. -->
+
+<types>
+   <jdbc-type name="ARRAY"/>
+   <jdbc-type name="BIGINT">
+       <db-type name="int"/>
+   </jdbc-type>
+   <jdbc-type name="BINARY">
+       <db-type name="binary"/>
+   </jdbc-type>
+   <jdbc-type name="BIT">
+       <db-type name="bit"/>
+   </jdbc-type>
+   <jdbc-type name="BLOB">
+       <db-type name="image"/>
+   </jdbc-type>
+   <jdbc-type name="BOOLEAN">
+       <db-type name="bit"/>
+   </jdbc-type>
+   <jdbc-type name="CHAR">
+       <db-type name="char"/>
+   </jdbc-type>
+   <jdbc-type name="CLOB">
+       <db-type name="text"/>
+   </jdbc-type>
+   <jdbc-type name="DATALINK"/>
+   <jdbc-type name="DATE">
+       <db-type name="datetime"/>
+   </jdbc-type>
+   <jdbc-type name="DECIMAL">
+       <db-type name="decimal"/>
+   </jdbc-type>
+   <jdbc-type name="DOUBLE">
+       <db-type name="double precision"/>
+   </jdbc-type>
+   <jdbc-type name="FLOAT">
+       <db-type name="float"/>
+   </jdbc-type>
+   <jdbc-type name="INTEGER">
+       <db-type name="int"/>
+   </jdbc-type>
+   <jdbc-type name="JAVA_OBJECT"/>
+   <jdbc-type name="LONGVARBINARY">
+       <db-type name="image"/>
+   </jdbc-type>
+   <jdbc-type name="LONGVARCHAR">
+       <db-type name="text"/>
+   </jdbc-type>
+   <jdbc-type name="NUMERIC">
+       <db-type name="numeric"/>
+   </jdbc-type>
+   <jdbc-type name="OTHER"/>
+   <jdbc-type name="REAL">
+       <db-type name="real"/>
+   </jdbc-type>
+   <jdbc-type name="REF"/>
+   <jdbc-type name="SMALLINT">
+       <db-type name="smallint"/>
+   </jdbc-type>
+   <jdbc-type name="STRUCT"/>
+   <jdbc-type name="TIME">
+       <db-type name="datetime"/>
+   </jdbc-type>
+   <jdbc-type name="TIMESTAMP">
+       <db-type name="datetime"/>
+   </jdbc-type>
+   <jdbc-type name="TINYINT">
+       <db-type name="tinyint"/>
+   </jdbc-type>
+   <jdbc-type name="VARBINARY">
+       <db-type name="varbinary"/>
+   </jdbc-type>
+   <jdbc-type name="VARCHAR">
+       <db-type name="varchar"/>
+   </jdbc-type>
+</types>

Reply via email to