You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by wi...@apache.org on 2007/04/03 21:35:00 UTC

svn commit: r525252 - in /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java

Author: wisneskid
Date: Tue Apr  3 12:34:59 2007
New Revision: 525252

URL: http://svn.apache.org/viewvc?view=rev&rev=525252
Log:
changes for JIRA OPENJPA-182

Modified:
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java?view=diff&rev=525252&r1=525251&r2=525252
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java Tue Apr  3 12:34:59 2007
@@ -52,7 +52,7 @@
         supportsLockingWithOrderClause = false;
         supportsLockingWithOuterJoin = false;
         supportsLockingWithInnerJoin = false;
-        supportsLockingWithSelectRange = false;
+        supportsLockingWithSelectRange = true;
 
         requiresAutoCommitForMetaData = true;
         requiresAliasForSubselect = true;

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java?view=diff&rev=525252&r1=525251&r2=525252
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java Tue Apr  3 12:34:59 2007
@@ -15,13 +15,15 @@
  */
 package org.apache.openjpa.jdbc.sql;
 
+import java.lang.reflect.Method;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
 import java.util.Arrays;
-
+import java.util.StringTokenizer;
 import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
 import org.apache.openjpa.jdbc.schema.Sequence;
+import org.apache.openjpa.lib.log.Log;
 
 /**
  * Dictionary for IBM DB2 database.
@@ -31,7 +33,18 @@
 
     public String optimizeClause = "optimize for";
     public String rowClause = "row";
-
+    private int db2ServerType = 0; 
+    private static final int  db2ISeriesV5R3AndEarlier = 1;
+    private static final int db2UDBV81OrEarlier = 2;
+    private static final int db2ZOSV8x = 3;
+    private static final int db2UDBV82AndLater = 4;
+    private static final int  db2ISeriesV5R4AndLater = 5;
+	private static final String  forUpdateOfClause="FOR UPDATE OF";
+    private static final String  withRSClause="WITH RS";
+    private static final String  withRRClause="WITH RR";
+    private static final String  useKeepUpdateLockClause= "USE AND KEEP UPDATE LOCKS";
+    private static final String  useKeepExclusiveLockClause="USE AND KEEP EXCLUSIVE LOCKS";
+    private static final String  forReadOnlyClause = "FOR READ ONLY";
     public DB2Dictionary() {
         platform = "DB2";
         validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
@@ -170,6 +183,18 @@
     	if (isJDBC3(metaData)) {
 			int maj = metaData.getDatabaseMajorVersion();
 	    	int min = metaData.getDatabaseMinorVersion();
+	    	
+	    	// Determine the type of DB2 database
+	    	if (isDB2ISeriesV5R3AndEarlier(metaData))
+	    	    db2ServerType =db2ISeriesV5R3AndEarlier;
+	    	else if (isDB2UDBV81OrEarlier(metaData,maj,min))
+	    	    db2ServerType =db2UDBV81OrEarlier;
+	    	else if (isDB2ZOSV8x(metaData,maj))
+	    	    db2ServerType =db2ZOSV8x;
+	    	else if (isDB2UDBV82AndLater(metaData,maj,min))
+	    	    db2ServerType=db2UDBV82AndLater;
+	    	else if (isDB2ISeriesV5R4AndLater(metaData))
+	    	    db2ServerType=db2ISeriesV5R4AndLater;
 
 	    	if (maj >= 9 || (maj == 8 && min >= 2)) {
 	    		supportsLockingWithMultipleTables = true;
@@ -198,13 +223,221 @@
         }
     }
     
+    /** Get the update clause for the query based on the 
+     * updateClause and isolationLevel hints
+     */
+    public String getForUpdateClause(JDBCFetchConfiguration fetch, boolean forUpdate) {
+        String isolationLevel = null;
+        Boolean updateClause = null;
+        DatabaseMetaData metaData = null;
+        StringBuffer forUpdateString = new StringBuffer();
+        try {
+            // Determine the update clause/isolationLevel the hint 
+            // overrides the persistence.xml value
+            if (fetch != null && fetch.getHint("openjpa.hint.updateClause")
+                !=null )
+                updateClause = (Boolean)fetch.
+                getHint("openjpa.hint.updateClause");
+            else 
+                updateClause = forUpdate;
+            if (fetch != null &&fetch.getHint("openjpa.hint.isolationLevel")
+                !=null )
+                isolationLevel = (String)fetch.
+                getHint("openjpa.hint.isolationLevel");
+            else 
+                isolationLevel = conf.getTransactionIsolation();
+            if (updateClause == false)
+                //This sql is not for update so add FOR Read Only clause
+                forUpdateString.append(" ").append(forReadOnlyClause)
+                .append(" ");
+            else if (updateClause == true){
+
+                switch(db2ServerType){
+                case db2ISeriesV5R3AndEarlier:
+                case db2UDBV81OrEarlier: 
+                    if (isolationLevel.equals("read-uncommitted"))
+                        forUpdateString.append(" ").append(withRSClause)
+                        .append(" ").append(forUpdateOfClause).append(" ");
+                    else
+                        forUpdateString.append(" ").append(forUpdateOfClause)
+                        .append(" ");
+                    break;   
+                case db2ZOSV8x:
+                case db2UDBV82AndLater: 
+                    if (isolationLevel.equals("serializable"))
+                        forUpdateString.append(" ").append(withRRClause)
+                        .append(" ").append(useKeepUpdateLockClause)
+                        .append(" ");
+                    else
+                        forUpdateString.append(" ").append(withRSClause)
+                        .append(" ").append(useKeepUpdateLockClause)
+                        .append(" ");	
+                    break;
+                case db2ISeriesV5R4AndLater:
+                    if (isolationLevel.equals("serializable"))
+                        forUpdateString.append(" ").append(withRRClause)
+                        .append(" ").append(useKeepExclusiveLockClause)
+                        .append(" ");
+                    else
+                        forUpdateString.append(" ").append(withRSClause)
+                        .append(" ").append(useKeepExclusiveLockClause)
+                        .append(" ");	
+                }
+            }
+        }    
+        catch (Exception e) {
+            if (log.isTraceEnabled())
+                log.error(e.toString(),e);
+        }
+        return forUpdateString.toString();
+    }  
+
+   
+    /** Override the DBDictionary toSelect to call getOptimizeClause and append 
+     *   to the select string
+     */   
+    public SQLBuffer toSelect(SQLBuffer selects, JDBCFetchConfiguration fetch,
+       SQLBuffer from, SQLBuffer where, SQLBuffer group,
+       SQLBuffer having, SQLBuffer order,
+       boolean distinct, boolean forUpdate, long start, long end,
+       int expectedResultCount) {
+       String forUpdateString = getForUpdateClause(fetch,forUpdate);
+       SQLBuffer selString = toOperation(getSelectOperation(fetch), 
+            selects, from, where,
+            group, having, order, distinct,
+            forUpdate, start, end,forUpdateString);
+        return selString;
+    }
+
+    public boolean isDB2UDBV82AndLater(DatabaseMetaData metadata, int maj,
+        int min) throws SQLException {
+        boolean match = false;
+        if (metadata.getDatabaseProductVersion().indexOf("SQL") != -1 
+            && ((maj ==8 && min >=2) ||(maj >=8)))
+            match = true; 
+        return match;
+    }
+
+    public boolean isDB2ZOSV8x(DatabaseMetaData metadata,int maj)
+       throws SQLException {
+       boolean match = false;
+       if (metadata.getDatabaseProductVersion().indexOf("DSN") != -1 
+           && maj ==8 )
+           match = true; 
+        return match;
+    }
+
+    public boolean isDB2ISeriesV5R3AndEarlier(DatabaseMetaData metadata)
+       throws SQLException {
+       boolean match = false;
+       if (metadata.getDatabaseProductVersion().indexOf("AS") != -1 
+           && generateVersionNumber(metadata.getDatabaseProductVersion())
+           <= 530 )
+           match = true; 
+       return match;
+    }
+
+    public boolean isDB2ISeriesV5R4AndLater(DatabaseMetaData metadata)
+       throws SQLException {
+       boolean match = false;
+       if (metadata.getDatabaseProductVersion().indexOf("AS") != -1 
+           && generateVersionNumber(metadata.getDatabaseProductVersion())
+           >= 540 )
+           match = true; 
+      return match;
+    }
+
+    public boolean isDB2UDBV81OrEarlier(DatabaseMetaData metadata,int maj, 
+        int min) throws SQLException {
+        boolean match = false;
+        if (metadata.getDatabaseProductVersion().indexOf("SQL") != -1 &&
+           ((maj ==8 && min <=1)|| maj <8 ))
+            match = true; 
+        return match;
+    }
+
+    /** Get the version number for the ISeries
+     */ 
+    protected  int generateVersionNumber(String versionString) {
+        String s = versionString.substring(versionString.indexOf('V'));
+        s = s.toUpperCase(); 
+        int i = -1;
+        StringTokenizer stringtokenizer = new StringTokenizer(s, "VRM", false);
+        if (stringtokenizer.countTokens() == 3)
+        {
+            String s1 = stringtokenizer.nextToken();
+            s1 = s1 + stringtokenizer.nextToken();
+            s1 = s1 + stringtokenizer.nextToken();
+            i = Integer.parseInt(s1);
+        }
+        return i;
+    }
+ 
+       
+    /**
+     * Override the toOperationMethod of DBDictionary to pass the 
+     * forUpdateString.
+     */
+    protected SQLBuffer toOperation(String op, SQLBuffer selects, 
+        SQLBuffer from, SQLBuffer where, SQLBuffer group, SQLBuffer having, 
+        SQLBuffer order, boolean distinct, boolean forUpdate, long start, 
+        long end,String forUpdateString) {
+        SQLBuffer buf = new SQLBuffer(this);
+        buf.append(op);
+        boolean range = start != 0 || end != Long.MAX_VALUE;
+        if (range && rangePosition == RANGE_PRE_DISTINCT)
+            appendSelectRange(buf, start, end);
+        if (distinct)
+            buf.append(" DISTINCT");
+        if (range && rangePosition == RANGE_POST_DISTINCT)
+            appendSelectRange(buf, start, end);
+        buf.append(" ").append(selects).append(" FROM ").append(from);
+
+        if (where != null && !where.isEmpty())
+            buf.append(" WHERE ").append(where);
+        if (group != null && !group.isEmpty())
+            buf.append(" GROUP BY ").append(group);
+        if (having != null && !having.isEmpty()) {
+            assertSupport(supportsHaving, "SupportsHaving");
+            buf.append(" HAVING ").append(having);
+        }
+        if (order != null && !order.isEmpty())
+            buf.append(" ORDER BY ").append(order);
+        if (range && rangePosition == RANGE_POST_SELECT)
+            appendSelectRange(buf, start, end);
+
+        if (!simulateLocking ) {
+            assertSupport(supportsSelectForUpdate, "SupportsSelectForUpdate");
+            buf.append(" ").append(forUpdateString);
+        }
+        if (range && rangePosition == RANGE_POST_LOCK)
+            appendSelectRange(buf, start, end);
+        return buf;
+    }
+
     public SQLBuffer toSelect(Select sel, boolean forUpdate,
         JDBCFetchConfiguration fetch) {
-        SQLBuffer buf = super.toSelect(sel, forUpdate, fetch); 
+        sel.addJoinClassConditions();
+        boolean update = forUpdate && sel.getFromSelect() == null;
+        SQLBuffer select = getSelects(sel, false, update);
+        SQLBuffer ordering = null;
+        if (!sel.isAggregate() || sel.getGrouping() != null)
+            ordering = sel.getOrdering();
+        SQLBuffer from;
+        if (sel.getFromSelect() != null)
+            from = getFromSelect(sel, forUpdate);
+        else
+            from = getFrom(sel, update);
+        SQLBuffer where = getWhere(sel, update);
+        String forUpdateString = getForUpdateClause(fetch,forUpdate);
+        SQLBuffer buf = toOperation(getSelectOperation(fetch), select,
+            from, where,sel.getGrouping(), sel.getHaving(),  ordering,
+            sel.isDistinct(), forUpdate, sel.getStartIndex(),
+            sel.getEndIndex(),forUpdateString);
         if (sel.getExpectedResultCount() > 0)
             buf.append(" ").append(optimizeClause).append(" ").
-                append(String.valueOf(sel.getExpectedResultCount())).
-                append(" ").append(rowClause);
+            append(String.valueOf(sel.getExpectedResultCount())).
+            append(" ").append(rowClause);
         return buf;
     }
 }



RE: API or Query hints

Posted by Patrick Linskey <pl...@bea.com>.
> Do we need this function in 0.9.7 or can it wait until 0.9.8?

I don't have a strong opinion either way. If we decide to hold it for
0.9.8, then I think that it's important for us to either remove the
current functionality, or make sure it's understood that the current API
is subject to change without backwards-compatibility.

-Patrick

-- 
Patrick Linskey
BEA Systems, Inc. 

_______________________________________________________________________
Notice:  This email message, together with any attachments, may contain
information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
entities,  that may be confidential,  proprietary,  copyrighted  and/or
legally privileged, and is intended solely for the use of the individual
or entity named in this message. If you are not the intended recipient,
and have received this message in error, please immediately return this
by email and then delete it. 

> -----Original Message-----
> From: Michael Dick [mailto:michael.d.dick@gmail.com] 
> Sent: Wednesday, April 04, 2007 6:50 PM
> To: open-jpa-dev@incubator.apache.org
> Subject: Re: API or Query hints
> 
> Do we need this function in 0.9.7 or can it wait until 0.9.8?
> 
> When we're dealing with external APIs we need to be very 
> careful that we're
> doing the right thing. I think we need some time to come to a 
> consensus on
> the correct approach and I'd rather not delay 0.9.7 in the 
> meantime. Abe
> cleaned up the code I dropped for default schemas earlier today, so I
> believe this is the last outstanding issue with 0.9.7.
> 
> FTR I'm not voting for or against either implementation - I 
> just don't want
> to commit to one path until we can agree to one of them.
> 
> If the consensus is that this function should be included in 
> 0.9.7 then I'll
> withdraw my comment and wait.
> 
> Other gratuitous opinions:
> 
> +1 to using a JIRA or the mailing list to discuss external 
> changes before
> committing.
> 
> +1 to Abe's comment regarding hint naming conventions, we 
> should try to stay
> consistent.
> 
> 
> On 4/4/07, Patrick Linskey <pl...@bea.com> wrote:
> >
> > Hi,
> >
> > In the interests of putting my money where my mouth is, I attached a
> > patch to the JIRA issue, and included a description of the 
> patch in the
> > JIRA issue. Hopefully, this will help a) make the problem 
> and different
> > solutions more concrete, and b) quell any concerns about
> > implementability of the approach that I outlined.
> >
> > -Patrick
> >
> > --
> > Patrick Linskey
> > BEA Systems, Inc.
> >
> > 
> ______________________________________________________________
> _________
> > Notice:  This email message, together with any attachments, 
> may contain
> > information  of  BEA Systems,  Inc.,  its subsidiaries  and 
>  affiliated
> > entities,  that may be confidential,  proprietary,  
> copyrighted  and/or
> > legally privileged, and is intended solely for the use of 
> the individual
> > or entity named in this message. If you are not the 
> intended recipient,
> > and have received this message in error, please immediately 
> return this
> > by email and then delete it.
> >
> > > -----Original Message-----
> > > From: Craig.Russell@Sun.COM [mailto:Craig.Russell@Sun.COM]
> > > Sent: Wednesday, April 04, 2007 3:22 PM
> > > To: open-jpa-dev@incubator.apache.org
> > > Subject: API or Query hints
> > >
> > > I think any time we make a change to the external view of the
> > > project
> > > we need to have a discussion first.
> > >
> > > IMHO The JIRA process is pretty good for this kind of 
> stuff. Someone
> > > proposes a feature with non-standardized external behavior
> > > and writes
> > > up what it should look like. Then we agree on the details and
> > > go for it.
> > >
> > > On this particular issue, I can see valid reasons for 
> having an API
> > > that modifies the behavior of the query, but also 
> understand why it
> > > might be good to mirror that behavior using query hints. But
> > > whichever way we go, we need to agree on the name and semantics of
> > > the API/property and how to pass it to the internal structures for
> > > execution.
> > >
> > > There is a danger in thinking of these as "hints". As I would
> > > like to
> > > see it, the only down side to not recognizing a query 
> hint is lower
> > > performance. But if your application doesn't behave 
> correctly if the
> > > implementation can't do anything useful with the hint, 
> then it's not
> > > a hint but an application requirement. And if the hint can only be
> > > executed in some specific databases, then we need to decide if we
> > > throw an exception if the database isn't capable.
> > >
> > > Craig
> > >
> > > On Apr 4, 2007, at 2:17 PM, Abe White wrote:
> > >
> > > >> ... for certain values of "our". I think that it's
> > > important that we
> > > >> discuss API decisions as a group, as they have significant
> > > impacts on
> > > >> the OpenJPA product moving forward. This is especially
> > > important when
> > > >> there are dissenting views on a particular API 
> decision, as is the
> > > >> case
> > > >> here.
> > > >
> > > > I agree with Patrick.  API decisions need to be better 
> thought out.
> > > > For example, even if we decide as a group to use hints 
> in this case,
> > > > the names of the hints are important.  The current hint 
> names you
> > > > chose are inconsistent with other OpenJPA hints in 
> naming style and
> > > > capitalization.
> > > >
> > > >
> > > > Notice:  This email message, together with any attachments, may
> > > > contain information  of  BEA Systems,  Inc.,  its subsidiaries
> > > > and  affiliated entities,  that may be confidential,
> > > proprietary,
> > > > copyrighted  and/or legally privileged, and is intended 
> solely for
> > > > the use of the individual or entity named in this 
> message. If you
> > > > are not the intended recipient, and have received this 
> message in
> > > > error, please immediately return this by email and then 
> delete it.
> > >
> > > Craig Russell
> > > Architect, Sun Java Enterprise System 
> http://java.sun.com/products/jdo
> > > 408 276-5638 mailto:Craig.Russell@sun.com
> > > P.S. A good JDO? O, Gasp!
> > >
> > >
> >
> > Notice:  This email message, together with any attachments, 
> may contain
> > information  of  BEA Systems,  Inc.,  its subsidiaries  and 
>  affiliated
> > entities,  that may be confidential,  proprietary,  
> copyrighted  and/or
> > legally privileged, and is intended solely for the use of 
> the individual or
> > entity named in this message. If you are not the intended 
> recipient, and
> > have received this message in error, please immediately 
> return this by email
> > and then delete it.
> >
> 
> -- 
> -Michael Dick
> 

Notice:  This email message, together with any attachments, may contain information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,  copyrighted  and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.

Re: API or Query hints

Posted by Michael Dick <mi...@gmail.com>.
Do we need this function in 0.9.7 or can it wait until 0.9.8?

When we're dealing with external APIs we need to be very careful that we're
doing the right thing. I think we need some time to come to a consensus on
the correct approach and I'd rather not delay 0.9.7 in the meantime. Abe
cleaned up the code I dropped for default schemas earlier today, so I
believe this is the last outstanding issue with 0.9.7.

FTR I'm not voting for or against either implementation - I just don't want
to commit to one path until we can agree to one of them.

If the consensus is that this function should be included in 0.9.7 then I'll
withdraw my comment and wait.

Other gratuitous opinions:

+1 to using a JIRA or the mailing list to discuss external changes before
committing.

+1 to Abe's comment regarding hint naming conventions, we should try to stay
consistent.


On 4/4/07, Patrick Linskey <pl...@bea.com> wrote:
>
> Hi,
>
> In the interests of putting my money where my mouth is, I attached a
> patch to the JIRA issue, and included a description of the patch in the
> JIRA issue. Hopefully, this will help a) make the problem and different
> solutions more concrete, and b) quell any concerns about
> implementability of the approach that I outlined.
>
> -Patrick
>
> --
> Patrick Linskey
> BEA Systems, Inc.
>
> _______________________________________________________________________
> Notice:  This email message, together with any attachments, may contain
> information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
> entities,  that may be confidential,  proprietary,  copyrighted  and/or
> legally privileged, and is intended solely for the use of the individual
> or entity named in this message. If you are not the intended recipient,
> and have received this message in error, please immediately return this
> by email and then delete it.
>
> > -----Original Message-----
> > From: Craig.Russell@Sun.COM [mailto:Craig.Russell@Sun.COM]
> > Sent: Wednesday, April 04, 2007 3:22 PM
> > To: open-jpa-dev@incubator.apache.org
> > Subject: API or Query hints
> >
> > I think any time we make a change to the external view of the
> > project
> > we need to have a discussion first.
> >
> > IMHO The JIRA process is pretty good for this kind of stuff. Someone
> > proposes a feature with non-standardized external behavior
> > and writes
> > up what it should look like. Then we agree on the details and
> > go for it.
> >
> > On this particular issue, I can see valid reasons for having an API
> > that modifies the behavior of the query, but also understand why it
> > might be good to mirror that behavior using query hints. But
> > whichever way we go, we need to agree on the name and semantics of
> > the API/property and how to pass it to the internal structures for
> > execution.
> >
> > There is a danger in thinking of these as "hints". As I would
> > like to
> > see it, the only down side to not recognizing a query hint is lower
> > performance. But if your application doesn't behave correctly if the
> > implementation can't do anything useful with the hint, then it's not
> > a hint but an application requirement. And if the hint can only be
> > executed in some specific databases, then we need to decide if we
> > throw an exception if the database isn't capable.
> >
> > Craig
> >
> > On Apr 4, 2007, at 2:17 PM, Abe White wrote:
> >
> > >> ... for certain values of "our". I think that it's
> > important that we
> > >> discuss API decisions as a group, as they have significant
> > impacts on
> > >> the OpenJPA product moving forward. This is especially
> > important when
> > >> there are dissenting views on a particular API decision, as is the
> > >> case
> > >> here.
> > >
> > > I agree with Patrick.  API decisions need to be better thought out.
> > > For example, even if we decide as a group to use hints in this case,
> > > the names of the hints are important.  The current hint names you
> > > chose are inconsistent with other OpenJPA hints in naming style and
> > > capitalization.
> > >
> > >
> > > Notice:  This email message, together with any attachments, may
> > > contain information  of  BEA Systems,  Inc.,  its subsidiaries
> > > and  affiliated entities,  that may be confidential,
> > proprietary,
> > > copyrighted  and/or legally privileged, and is intended solely for
> > > the use of the individual or entity named in this message. If you
> > > are not the intended recipient, and have received this message in
> > > error, please immediately return this by email and then delete it.
> >
> > Craig Russell
> > Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
> > 408 276-5638 mailto:Craig.Russell@sun.com
> > P.S. A good JDO? O, Gasp!
> >
> >
>
> Notice:  This email message, together with any attachments, may contain
> information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
> entities,  that may be confidential,  proprietary,  copyrighted  and/or
> legally privileged, and is intended solely for the use of the individual or
> entity named in this message. If you are not the intended recipient, and
> have received this message in error, please immediately return this by email
> and then delete it.
>

-- 
-Michael Dick

RE: API or Query hints

Posted by Patrick Linskey <pl...@bea.com>.
Hi,

In the interests of putting my money where my mouth is, I attached a
patch to the JIRA issue, and included a description of the patch in the
JIRA issue. Hopefully, this will help a) make the problem and different
solutions more concrete, and b) quell any concerns about
implementability of the approach that I outlined.

-Patrick

-- 
Patrick Linskey
BEA Systems, Inc. 

_______________________________________________________________________
Notice:  This email message, together with any attachments, may contain
information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
entities,  that may be confidential,  proprietary,  copyrighted  and/or
legally privileged, and is intended solely for the use of the individual
or entity named in this message. If you are not the intended recipient,
and have received this message in error, please immediately return this
by email and then delete it. 

> -----Original Message-----
> From: Craig.Russell@Sun.COM [mailto:Craig.Russell@Sun.COM] 
> Sent: Wednesday, April 04, 2007 3:22 PM
> To: open-jpa-dev@incubator.apache.org
> Subject: API or Query hints
> 
> I think any time we make a change to the external view of the 
> project  
> we need to have a discussion first.
> 
> IMHO The JIRA process is pretty good for this kind of stuff. Someone  
> proposes a feature with non-standardized external behavior 
> and writes  
> up what it should look like. Then we agree on the details and 
> go for it.
> 
> On this particular issue, I can see valid reasons for having an API  
> that modifies the behavior of the query, but also understand why it  
> might be good to mirror that behavior using query hints. But  
> whichever way we go, we need to agree on the name and semantics of  
> the API/property and how to pass it to the internal structures for  
> execution.
> 
> There is a danger in thinking of these as "hints". As I would 
> like to  
> see it, the only down side to not recognizing a query hint is lower  
> performance. But if your application doesn't behave correctly if the  
> implementation can't do anything useful with the hint, then it's not  
> a hint but an application requirement. And if the hint can only be  
> executed in some specific databases, then we need to decide if we  
> throw an exception if the database isn't capable.
> 
> Craig
> 
> On Apr 4, 2007, at 2:17 PM, Abe White wrote:
> 
> >> ... for certain values of "our". I think that it's 
> important that we
> >> discuss API decisions as a group, as they have significant 
> impacts on
> >> the OpenJPA product moving forward. This is especially 
> important when
> >> there are dissenting views on a particular API decision, as is the
> >> case
> >> here.
> >
> > I agree with Patrick.  API decisions need to be better thought out.
> > For example, even if we decide as a group to use hints in this case,
> > the names of the hints are important.  The current hint names you
> > chose are inconsistent with other OpenJPA hints in naming style and
> > capitalization.
> >
> >
> > Notice:  This email message, together with any attachments, may  
> > contain information  of  BEA Systems,  Inc.,  its subsidiaries   
> > and  affiliated entities,  that may be confidential,  
> proprietary,   
> > copyrighted  and/or legally privileged, and is intended solely for  
> > the use of the individual or entity named in this message. If you  
> > are not the intended recipient, and have received this message in  
> > error, please immediately return this by email and then delete it.
> 
> Craig Russell
> Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
> 408 276-5638 mailto:Craig.Russell@sun.com
> P.S. A good JDO? O, Gasp!
> 
> 

Notice:  This email message, together with any attachments, may contain information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,  copyrighted  and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.

API or Query hints

Posted by Craig L Russell <Cr...@Sun.COM>.
I think any time we make a change to the external view of the project  
we need to have a discussion first.

IMHO The JIRA process is pretty good for this kind of stuff. Someone  
proposes a feature with non-standardized external behavior and writes  
up what it should look like. Then we agree on the details and go for it.

On this particular issue, I can see valid reasons for having an API  
that modifies the behavior of the query, but also understand why it  
might be good to mirror that behavior using query hints. But  
whichever way we go, we need to agree on the name and semantics of  
the API/property and how to pass it to the internal structures for  
execution.

There is a danger in thinking of these as "hints". As I would like to  
see it, the only down side to not recognizing a query hint is lower  
performance. But if your application doesn't behave correctly if the  
implementation can't do anything useful with the hint, then it's not  
a hint but an application requirement. And if the hint can only be  
executed in some specific databases, then we need to decide if we  
throw an exception if the database isn't capable.

Craig

On Apr 4, 2007, at 2:17 PM, Abe White wrote:

>> ... for certain values of "our". I think that it's important that we
>> discuss API decisions as a group, as they have significant impacts on
>> the OpenJPA product moving forward. This is especially important when
>> there are dissenting views on a particular API decision, as is the
>> case
>> here.
>
> I agree with Patrick.  API decisions need to be better thought out.
> For example, even if we decide as a group to use hints in this case,
> the names of the hints are important.  The current hint names you
> chose are inconsistent with other OpenJPA hints in naming style and
> capitalization.
>
>
> Notice:  This email message, together with any attachments, may  
> contain information  of  BEA Systems,  Inc.,  its subsidiaries   
> and  affiliated entities,  that may be confidential,  proprietary,   
> copyrighted  and/or legally privileged, and is intended solely for  
> the use of the individual or entity named in this message. If you  
> are not the intended recipient, and have received this message in  
> error, please immediately return this by email and then delete it.

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:Craig.Russell@sun.com
P.S. A good JDO? O, Gasp!


Re: svn commit: r525252 - in /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java

Posted by Abe White <aw...@bea.com>.
> ... for certain values of "our". I think that it's important that we
> discuss API decisions as a group, as they have significant impacts on
> the OpenJPA product moving forward. This is especially important when
> there are dissenting views on a particular API decision, as is the  
> case
> here.

I agree with Patrick.  API decisions need to be better thought out.   
For example, even if we decide as a group to use hints in this case,  
the names of the hints are important.  The current hint names you  
chose are inconsistent with other OpenJPA hints in naming style and  
capitalization. 
  

Notice:  This email message, together with any attachments, may contain information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,  copyrighted  and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.

Re: svn commit: r525252 - in /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java

Posted by David Wisneski <wi...@gmail.com>.
My experience is that customers don't like and tend not to use
proprietary apis.  They tend to understand and use the standard apis.
If we can make a standard api do what we need that should be the
preferrred approach over creating proprietary apis and annotations and
then having to educate folks on how to use them.  The JPA Hint was
supposed to be a way to specify properties on a per query basis and
that is exactly what we are trying to do in this case.

On 4/3/07, Patrick Linskey <pl...@bea.com> wrote:
> > open ended setHint api.  It is our intent to make use this api so that
> > users can
> > sets these values without having to make use of OpenJPA specific apis
> > -- granted the hint name and value would be OpenJPA specific.
>
> ... for certain values of "our". I think that it's important that we
> discuss API decisions as a group, as they have significant impacts on
> the OpenJPA product moving forward. This is especially important when
> there are dissenting views on a particular API decision, as is the case
> here.
>
> Currently, most of the precedent in OpenJPA is to use OpenJPA-specific
> APIs, rather than untyped strings, whenever possible for fetch
> configuration and behavior. See the APIs for controlling the fetch batch
> size, or the lock level, or the maximum fetch depth. Personally, I much
> prefer that model of operation, since it provides strong typing where
> vendor-specific extensions are used, and thus raises the awareness of
> developers that they are using a proprietary feature. Using string
> key-value pairs is notoriously error-prone and difficult to refactor,
> and in my opinion detracts from the usability of the API.
>
> > accessed.    In the case of static SQL,  these hints would be defined
> > on a NamedQuery definition and not through runtime api.
>
> Again, I don't think that 'hint' is really the right word for describing
> lock and isolation levels.
>
> We could also create new annotations to describe the lock levels and
> isolation settings needed for the named queries; we do not need to
> constrain ourselves to what is available in the JPA annotations / XML.
> This will mean a bit more work on our part, but I think that we should
> figure out what the right decision is for our users, and work from
> there, rather than just doing whatever fits into what the JPA spec
> provides API-wise.
>
> Similarly, these facilities seem useful for regular EM.find() calls; one
> of the nice things about the FetchPlan is that an EM has a FetchPlan and
> a Query has one, so similar fetching configurations can be implemented
> in a common manner.
>
> Thoughts?
>
> -Patrick
>
> --
> Patrick Linskey
> BEA Systems, Inc.
>
> _______________________________________________________________________
> Notice:  This email message, together with any attachments, may contain
> information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
> entities,  that may be confidential,  proprietary,  copyrighted  and/or
> legally privileged, and is intended solely for the use of the individual
> or entity named in this message. If you are not the intended recipient,
> and have received this message in error, please immediately return this
> by email and then delete it.
>
> > -----Original Message-----
> > From: David Wisneski [mailto:wisneskid@gmail.com]
> > Sent: Tuesday, April 03, 2007 1:24 PM
> > To: open-jpa-dev@incubator.apache.org
> > Subject: Re: svn commit: r525252 - in
> > /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache
> > /openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java
> >
> > SQL provides capabilities for tuning of locking.  In the case of DB2
> > this involves setting the isolation level, update lock, result set
> > optimize set, etc.
> > JPA spec does not provide support for these concepts but does
> > provide a rather
> > open ended setHint api.  It is our intent to make use this api so that
> > users can
> > sets these values without having to make use of OpenJPA specific apis
> > -- granted the hint name and value would be OpenJPA specific.
> > Furthermore, we are intending to support static SQL.  Static SQL is
> > extremely important in the enterprise environment for our larger
> > customers because (1) it provides better optimization of SQL and (2)
> > auditability and security over who access the data and how it is
> > accessed.    In the case of static SQL,  these hints would be defined
> > on a NamedQuery definition and not through runtime api.
> >
> > On 4/3/07, Patrick Linskey <pl...@bea.com> wrote:
> > > I'm a little nervous about this change still. I don't like
> > it that we're
> > > adding yet another way to configure locking, especially
> > since it seems
> > > like the lock level settings should be sufficient (or nearly so) to
> > > handle per-transaction / per-query lock levels.
> > >
> > > I also still do not believe that isolationLevel should be a hint; it
> > > seems more rule-like than hint-like.
> > >
> > > To date, the OpenJPA model has not been to piggyback on the
> > > Query.setHint() facilities for vendor-specific metadata,
> > but rather to
> > > use our OpenJPA extension classes (FetchPlan, etc.) to allow us to
> > > convey more structured data to the kernel. I think that the
> > isolation
> > > level should probably be part of FetchPlan (or possibly
> > JDBCFetchPlan),
> > > and the update information should be obtainable from the FetchPlan's
> > > read- and write-lock levels.
> > >
> > > I don't think that we should rush this change in just so
> > it's in 0.9.7;
> > > we can always delay 0.9.7 if it's a must-have, or have a 0.9.8 that
> > > follows soon thereafter. Generally-speaking, my experience
> > is that once
> > > code gets committed, it tends to not get cleaned up, so the argument
> > > "let's get it in for the release and then fix it later"
> > usually ends up
> > > turning into "let's get it in for the release". This seems
> > especially
> > > true for a change like this, that is exposing new APIs (the hints).
> > >
> > > Thoughts?
> > >
> > > -Patrick
> > >
> > > --
> > > Patrick Linskey
> > > BEA Systems, Inc.
> > >
> > >
> > ______________________________________________________________
> > _________
> > > Notice:  This email message, together with any attachments,
> > may contain
> > > information  of  BEA Systems,  Inc.,  its subsidiaries  and
> >  affiliated
> > > entities,  that may be confidential,  proprietary,
> > copyrighted  and/or
> > > legally privileged, and is intended solely for the use of
> > the individual
> > > or entity named in this message. If you are not the
> > intended recipient,
> > > and have received this message in error, please immediately
> > return this
> > > by email and then delete it.
> > >
> > > > -----Original Message-----
> > > > From: wisneskid@apache.org [mailto:wisneskid@apache.org]
> > > > Sent: Tuesday, April 03, 2007 12:35 PM
> > > > To: open-jpa-commits@incubator.apache.org
> > > > Subject: svn commit: r525252 - in
> > > > /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache
> > > > /openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java
> > > >
> > > > Author: wisneskid
> > > > Date: Tue Apr  3 12:34:59 2007
> > > > New Revision: 525252
> > > >
> > > > URL: http://svn.apache.org/viewvc?view=rev&rev=525252
> > > > Log:
> > > > changes for JIRA OPENJPA-182
> > > >
> > > > Modified:
> > > >
> > > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > > openjpa/jdbc/sql/AbstractDB2Dictionary.java
> > > >
> > > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > > openjpa/jdbc/sql/DB2Dictionary.java
> > > >
> > > > Modified:
> > > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > > openjpa/jdbc/sql/AbstractDB2Dictionary.java
> > > > URL:
> > > > http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-j
> > >
> > dbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dicti
> > onary.java
> > > ?view=diff&rev=> 525252&r1=525251&r2=525252
> > > > ==============================================================
> > > > ================
> > > > ---
> > > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > > openjpa/jdbc/sql/AbstractDB2Dictionary.java (original)
> > > > +++
> > > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > > openjpa/jdbc/sql/AbstractDB2Dictionary.java Tue Apr  3 12:34:59 2007
> > > > @@ -52,7 +52,7 @@
> > > >          supportsLockingWithOrderClause = false;
> > > >          supportsLockingWithOuterJoin = false;
> > > >          supportsLockingWithInnerJoin = false;
> > > > -        supportsLockingWithSelectRange = false;
> > > > +        supportsLockingWithSelectRange = true;
> > > >
> > > >          requiresAutoCommitForMetaData = true;
> > > >          requiresAliasForSubselect = true;
> > > >
> > > > Modified:
> > > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > > openjpa/jdbc/sql/DB2Dictionary.java
> > > > URL:
> > > > http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-j
> > >
> > dbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.ja
> > va?view=di
> > > ff&rev=525252&r1=> 525251&r2=525252
> > > > ==============================================================
> > > > ================
> > > > ---
> > > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > > openjpa/jdbc/sql/DB2Dictionary.java (original)
> > > > +++
> > > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > > openjpa/jdbc/sql/DB2Dictionary.java Tue Apr  3 12:34:59 2007
> > > > @@ -15,13 +15,15 @@
> > > >   */
> > > >  package org.apache.openjpa.jdbc.sql;
> > > >
> > > > +import java.lang.reflect.Method;
> > > >  import java.sql.Connection;
> > > >  import java.sql.DatabaseMetaData;
> > > >  import java.sql.SQLException;
> > > >  import java.util.Arrays;
> > > > -
> > > > +import java.util.StringTokenizer;
> > > >  import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
> > > >  import org.apache.openjpa.jdbc.schema.Sequence;
> > > > +import org.apache.openjpa.lib.log.Log;
> > > >
> > > >  /**
> > > >   * Dictionary for IBM DB2 database.
> > > > @@ -31,7 +33,18 @@
> > > >
> > > >      public String optimizeClause = "optimize for";
> > > >      public String rowClause = "row";
> > > > -
> > > > +    private int db2ServerType = 0;
> > > > +    private static final int  db2ISeriesV5R3AndEarlier = 1;
> > > > +    private static final int db2UDBV81OrEarlier = 2;
> > > > +    private static final int db2ZOSV8x = 3;
> > > > +    private static final int db2UDBV82AndLater = 4;
> > > > +    private static final int  db2ISeriesV5R4AndLater = 5;
> > > > +     private static final String  forUpdateOfClause="FOR
> > UPDATE OF";
> > > > +    private static final String  withRSClause="WITH RS";
> > > > +    private static final String  withRRClause="WITH RR";
> > > > +    private static final String  useKeepUpdateLockClause=
> > > > "USE AND KEEP UPDATE LOCKS";
> > > > +    private static final String
> > > > useKeepExclusiveLockClause="USE AND KEEP EXCLUSIVE LOCKS";
> > > > +    private static final String  forReadOnlyClause =
> > "FOR READ ONLY";
> > > >      public DB2Dictionary() {
> > > >          platform = "DB2";
> > > >          validationSQL = "SELECT DISTINCT(CURRENT
> > TIMESTAMP) FROM "
> > > > @@ -170,6 +183,18 @@
> > > >       if (isJDBC3(metaData)) {
> > > >                       int maj =
> > metaData.getDatabaseMajorVersion();
> > > >               int min = metaData.getDatabaseMinorVersion();
> > > > +
> > > > +             // Determine the type of DB2 database
> > > > +             if (isDB2ISeriesV5R3AndEarlier(metaData))
> > > > +                 db2ServerType =db2ISeriesV5R3AndEarlier;
> > > > +             else if (isDB2UDBV81OrEarlier(metaData,maj,min))
> > > > +                 db2ServerType =db2UDBV81OrEarlier;
> > > > +             else if (isDB2ZOSV8x(metaData,maj))
> > > > +                 db2ServerType =db2ZOSV8x;
> > > > +             else if (isDB2UDBV82AndLater(metaData,maj,min))
> > > > +                 db2ServerType=db2UDBV82AndLater;
> > > > +             else if (isDB2ISeriesV5R4AndLater(metaData))
> > > > +                 db2ServerType=db2ISeriesV5R4AndLater;
> > > >
> > > >               if (maj >= 9 || (maj == 8 && min >= 2)) {
> > > >                       supportsLockingWithMultipleTables = true;
> > > > @@ -198,13 +223,221 @@
> > > >          }
> > > >      }
> > > >
> > > > +    /** Get the update clause for the query based on the
> > > > +     * updateClause and isolationLevel hints
> > > > +     */
> > > > +    public String getForUpdateClause(JDBCFetchConfiguration
> > > > fetch, boolean forUpdate) {
> > > > +        String isolationLevel = null;
> > > > +        Boolean updateClause = null;
> > > > +        DatabaseMetaData metaData = null;
> > > > +        StringBuffer forUpdateString = new StringBuffer();
> > > > +        try {
> > > > +            // Determine the update
> > clause/isolationLevel the hint
> > > > +            // overrides the persistence.xml value
> > > > +            if (fetch != null &&
> > > > fetch.getHint("openjpa.hint.updateClause")
> > > > +                !=null )
> > > > +                updateClause = (Boolean)fetch.
> > > > +                getHint("openjpa.hint.updateClause");
> > > > +            else
> > > > +                updateClause = forUpdate;
> > > > +            if (fetch != null
> > > > &&fetch.getHint("openjpa.hint.isolationLevel")
> > > > +                !=null )
> > > > +                isolationLevel = (String)fetch.
> > > > +                getHint("openjpa.hint.isolationLevel");
> > > > +            else
> > > > +                isolationLevel = conf.getTransactionIsolation();
> > > > +            if (updateClause == false)
> > > > +                //This sql is not for update so add FOR Read
> > > > Only clause
> > > > +                forUpdateString.append("
> > ").append(forReadOnlyClause)
> > > > +                .append(" ");
> > > > +            else if (updateClause == true){
> > > > +
> > > > +                switch(db2ServerType){
> > > > +                case db2ISeriesV5R3AndEarlier:
> > > > +                case db2UDBV81OrEarlier:
> > > > +                    if
> > (isolationLevel.equals("read-uncommitted"))
> > > > +                        forUpdateString.append("
> > > > ").append(withRSClause)
> > > > +                        .append("
> > > > ").append(forUpdateOfClause).append(" ");
> > > > +                    else
> > > > +                        forUpdateString.append("
> > > > ").append(forUpdateOfClause)
> > > > +                        .append(" ");
> > > > +                    break;
> > > > +                case db2ZOSV8x:
> > > > +                case db2UDBV82AndLater:
> > > > +                    if (isolationLevel.equals("serializable"))
> > > > +                        forUpdateString.append("
> > > > ").append(withRRClause)
> > > > +                        .append("
> > ").append(useKeepUpdateLockClause)
> > > > +                        .append(" ");
> > > > +                    else
> > > > +                        forUpdateString.append("
> > > > ").append(withRSClause)
> > > > +                        .append("
> > ").append(useKeepUpdateLockClause)
> > > > +                        .append(" ");
> > > > +                    break;
> > > > +                case db2ISeriesV5R4AndLater:
> > > > +                    if (isolationLevel.equals("serializable"))
> > > > +                        forUpdateString.append("
> > > > ").append(withRRClause)
> > > > +                        .append("
> > > > ").append(useKeepExclusiveLockClause)
> > > > +                        .append(" ");
> > > > +                    else
> > > > +                        forUpdateString.append("
> > > > ").append(withRSClause)
> > > > +                        .append("
> > > > ").append(useKeepExclusiveLockClause)
> > > > +                        .append(" ");
> > > > +                }
> > > > +            }
> > > > +        }
> > > > +        catch (Exception e) {
> > > > +            if (log.isTraceEnabled())
> > > > +                log.error(e.toString(),e);
> > > > +        }
> > > > +        return forUpdateString.toString();
> > > > +    }
> > > > +
> > > > +
> > > > +    /** Override the DBDictionary toSelect to call
> > > > getOptimizeClause and append
> > > > +     *   to the select string
> > > > +     */
> > > > +    public SQLBuffer toSelect(SQLBuffer selects,
> > > > JDBCFetchConfiguration fetch,
> > > > +       SQLBuffer from, SQLBuffer where, SQLBuffer group,
> > > > +       SQLBuffer having, SQLBuffer order,
> > > > +       boolean distinct, boolean forUpdate, long start, long end,
> > > > +       int expectedResultCount) {
> > > > +       String forUpdateString =
> > getForUpdateClause(fetch,forUpdate);
> > > > +       SQLBuffer selString =
> > toOperation(getSelectOperation(fetch),
> > > > +            selects, from, where,
> > > > +            group, having, order, distinct,
> > > > +            forUpdate, start, end,forUpdateString);
> > > > +        return selString;
> > > > +    }
> > > > +
> > > > +    public boolean isDB2UDBV82AndLater(DatabaseMetaData
> > > > metadata, int maj,
> > > > +        int min) throws SQLException {
> > > > +        boolean match = false;
> > > > +        if
> > > > (metadata.getDatabaseProductVersion().indexOf("SQL") != -1
> > > > +            && ((maj ==8 && min >=2) ||(maj >=8)))
> > > > +            match = true;
> > > > +        return match;
> > > > +    }
> > > > +
> > > > +    public boolean isDB2ZOSV8x(DatabaseMetaData metadata,int maj)
> > > > +       throws SQLException {
> > > > +       boolean match = false;
> > > > +       if
> > (metadata.getDatabaseProductVersion().indexOf("DSN") != -1
> > > > +           && maj ==8 )
> > > > +           match = true;
> > > > +        return match;
> > > > +    }
> > > > +
> > > > +    public boolean
> > > > isDB2ISeriesV5R3AndEarlier(DatabaseMetaData metadata)
> > > > +       throws SQLException {
> > > > +       boolean match = false;
> > > > +       if
> > (metadata.getDatabaseProductVersion().indexOf("AS") != -1
> > > > +           &&
> > > > generateVersionNumber(metadata.getDatabaseProductVersion())
> > > > +           <= 530 )
> > > > +           match = true;
> > > > +       return match;
> > > > +    }
> > > > +
> > > > +    public boolean isDB2ISeriesV5R4AndLater(DatabaseMetaData
> > > > metadata)
> > > > +       throws SQLException {
> > > > +       boolean match = false;
> > > > +       if
> > (metadata.getDatabaseProductVersion().indexOf("AS") != -1
> > > > +           &&
> > > > generateVersionNumber(metadata.getDatabaseProductVersion())
> > > > +           >= 540 )
> > > > +           match = true;
> > > > +      return match;
> > > > +    }
> > > > +
> > > > +    public boolean isDB2UDBV81OrEarlier(DatabaseMetaData
> > > > metadata,int maj,
> > > > +        int min) throws SQLException {
> > > > +        boolean match = false;
> > > > +        if
> > > > (metadata.getDatabaseProductVersion().indexOf("SQL") != -1 &&
> > > > +           ((maj ==8 && min <=1)|| maj <8 ))
> > > > +            match = true;
> > > > +        return match;
> > > > +    }
> > > > +
> > > > +    /** Get the version number for the ISeries
> > > > +     */
> > > > +    protected  int generateVersionNumber(String versionString) {
> > > > +        String s =
> > > > versionString.substring(versionString.indexOf('V'));
> > > > +        s = s.toUpperCase();
> > > > +        int i = -1;
> > > > +        StringTokenizer stringtokenizer = new
> > > > StringTokenizer(s, "VRM", false);
> > > > +        if (stringtokenizer.countTokens() == 3)
> > > > +        {
> > > > +            String s1 = stringtokenizer.nextToken();
> > > > +            s1 = s1 + stringtokenizer.nextToken();
> > > > +            s1 = s1 + stringtokenizer.nextToken();
> > > > +            i = Integer.parseInt(s1);
> > > > +        }
> > > > +        return i;
> > > > +    }
> > > > +
> > > > +
> > > > +    /**
> > > > +     * Override the toOperationMethod of DBDictionary to pass the
> > > > +     * forUpdateString.
> > > > +     */
> > > > +    protected SQLBuffer toOperation(String op, SQLBuffer selects,
> > > > +        SQLBuffer from, SQLBuffer where, SQLBuffer group,
> > > > SQLBuffer having,
> > > > +        SQLBuffer order, boolean distinct, boolean
> > > > forUpdate, long start,
> > > > +        long end,String forUpdateString) {
> > > > +        SQLBuffer buf = new SQLBuffer(this);
> > > > +        buf.append(op);
> > > > +        boolean range = start != 0 || end != Long.MAX_VALUE;
> > > > +        if (range && rangePosition == RANGE_PRE_DISTINCT)
> > > > +            appendSelectRange(buf, start, end);
> > > > +        if (distinct)
> > > > +            buf.append(" DISTINCT");
> > > > +        if (range && rangePosition == RANGE_POST_DISTINCT)
> > > > +            appendSelectRange(buf, start, end);
> > > > +        buf.append(" ").append(selects).append(" FROM
> > > > ").append(from);
> > > > +
> > > > +        if (where != null && !where.isEmpty())
> > > > +            buf.append(" WHERE ").append(where);
> > > > +        if (group != null && !group.isEmpty())
> > > > +            buf.append(" GROUP BY ").append(group);
> > > > +        if (having != null && !having.isEmpty()) {
> > > > +            assertSupport(supportsHaving, "SupportsHaving");
> > > > +            buf.append(" HAVING ").append(having);
> > > > +        }
> > > > +        if (order != null && !order.isEmpty())
> > > > +            buf.append(" ORDER BY ").append(order);
> > > > +        if (range && rangePosition == RANGE_POST_SELECT)
> > > > +            appendSelectRange(buf, start, end);
> > > > +
> > > > +        if (!simulateLocking ) {
> > > > +            assertSupport(supportsSelectForUpdate,
> > > > "SupportsSelectForUpdate");
> > > > +            buf.append(" ").append(forUpdateString);
> > > > +        }
> > > > +        if (range && rangePosition == RANGE_POST_LOCK)
> > > > +            appendSelectRange(buf, start, end);
> > > > +        return buf;
> > > > +    }
> > > > +
> > > >      public SQLBuffer toSelect(Select sel, boolean forUpdate,
> > > >          JDBCFetchConfiguration fetch) {
> > > > -        SQLBuffer buf = super.toSelect(sel, forUpdate, fetch);
> > > > +        sel.addJoinClassConditions();
> > > > +        boolean update = forUpdate &&
> > sel.getFromSelect() == null;
> > > > +        SQLBuffer select = getSelects(sel, false, update);
> > > > +        SQLBuffer ordering = null;
> > > > +        if (!sel.isAggregate() || sel.getGrouping() != null)
> > > > +            ordering = sel.getOrdering();
> > > > +        SQLBuffer from;
> > > > +        if (sel.getFromSelect() != null)
> > > > +            from = getFromSelect(sel, forUpdate);
> > > > +        else
> > > > +            from = getFrom(sel, update);
> > > > +        SQLBuffer where = getWhere(sel, update);
> > > > +        String forUpdateString =
> > getForUpdateClause(fetch,forUpdate);
> > > > +        SQLBuffer buf =
> > > > toOperation(getSelectOperation(fetch), select,
> > > > +            from, where,sel.getGrouping(), sel.getHaving(),
> > > > ordering,
> > > > +            sel.isDistinct(), forUpdate, sel.getStartIndex(),
> > > > +            sel.getEndIndex(),forUpdateString);
> > > >          if (sel.getExpectedResultCount() > 0)
> > > >              buf.append(" ").append(optimizeClause).append(" ").
> > > > -
> > append(String.valueOf(sel.getExpectedResultCount())).
> > > > -                append(" ").append(rowClause);
> > > > +            append(String.valueOf(sel.getExpectedResultCount())).
> > > > +            append(" ").append(rowClause);
> > > >          return buf;
> > > >      }
> > > >  }
> > > >
> > > >
> > > >
> > >
> > > Notice:  This email message, together with any attachments,
> > may contain information  of  BEA Systems,  Inc.,  its
> > subsidiaries  and  affiliated entities,  that may be
> > confidential,  proprietary,  copyrighted  and/or legally
> > privileged, and is intended solely for the use of the
> > individual or entity named in this message. If you are not
> > the intended recipient, and have received this message in
> > error, please immediately return this by email and then delete it.
> > >
> >
>
> Notice:  This email message, together with any attachments, may contain information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,  copyrighted  and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.
>

RE: svn commit: r525252 - in /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java

Posted by Patrick Linskey <pl...@bea.com>.
> open ended setHint api.  It is our intent to make use this api so that
> users can
> sets these values without having to make use of OpenJPA specific apis
> -- granted the hint name and value would be OpenJPA specific.

... for certain values of "our". I think that it's important that we
discuss API decisions as a group, as they have significant impacts on
the OpenJPA product moving forward. This is especially important when
there are dissenting views on a particular API decision, as is the case
here.

Currently, most of the precedent in OpenJPA is to use OpenJPA-specific
APIs, rather than untyped strings, whenever possible for fetch
configuration and behavior. See the APIs for controlling the fetch batch
size, or the lock level, or the maximum fetch depth. Personally, I much
prefer that model of operation, since it provides strong typing where
vendor-specific extensions are used, and thus raises the awareness of
developers that they are using a proprietary feature. Using string
key-value pairs is notoriously error-prone and difficult to refactor,
and in my opinion detracts from the usability of the API.

> accessed.    In the case of static SQL,  these hints would be defined
> on a NamedQuery definition and not through runtime api.

Again, I don't think that 'hint' is really the right word for describing
lock and isolation levels.

We could also create new annotations to describe the lock levels and
isolation settings needed for the named queries; we do not need to
constrain ourselves to what is available in the JPA annotations / XML.
This will mean a bit more work on our part, but I think that we should
figure out what the right decision is for our users, and work from
there, rather than just doing whatever fits into what the JPA spec
provides API-wise.

Similarly, these facilities seem useful for regular EM.find() calls; one
of the nice things about the FetchPlan is that an EM has a FetchPlan and
a Query has one, so similar fetching configurations can be implemented
in a common manner.

Thoughts?

-Patrick

-- 
Patrick Linskey
BEA Systems, Inc. 

_______________________________________________________________________
Notice:  This email message, together with any attachments, may contain
information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
entities,  that may be confidential,  proprietary,  copyrighted  and/or
legally privileged, and is intended solely for the use of the individual
or entity named in this message. If you are not the intended recipient,
and have received this message in error, please immediately return this
by email and then delete it. 

> -----Original Message-----
> From: David Wisneski [mailto:wisneskid@gmail.com] 
> Sent: Tuesday, April 03, 2007 1:24 PM
> To: open-jpa-dev@incubator.apache.org
> Subject: Re: svn commit: r525252 - in 
> /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache
> /openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java
> 
> SQL provides capabilities for tuning of locking.  In the case of DB2
> this involves setting the isolation level, update lock, result set
> optimize set, etc.
> JPA spec does not provide support for these concepts but does 
> provide a rather
> open ended setHint api.  It is our intent to make use this api so that
> users can
> sets these values without having to make use of OpenJPA specific apis
> -- granted the hint name and value would be OpenJPA specific.
> Furthermore, we are intending to support static SQL.  Static SQL is
> extremely important in the enterprise environment for our larger
> customers because (1) it provides better optimization of SQL and (2)
> auditability and security over who access the data and how it is
> accessed.    In the case of static SQL,  these hints would be defined
> on a NamedQuery definition and not through runtime api.
> 
> On 4/3/07, Patrick Linskey <pl...@bea.com> wrote:
> > I'm a little nervous about this change still. I don't like 
> it that we're
> > adding yet another way to configure locking, especially 
> since it seems
> > like the lock level settings should be sufficient (or nearly so) to
> > handle per-transaction / per-query lock levels.
> >
> > I also still do not believe that isolationLevel should be a hint; it
> > seems more rule-like than hint-like.
> >
> > To date, the OpenJPA model has not been to piggyback on the
> > Query.setHint() facilities for vendor-specific metadata, 
> but rather to
> > use our OpenJPA extension classes (FetchPlan, etc.) to allow us to
> > convey more structured data to the kernel. I think that the 
> isolation
> > level should probably be part of FetchPlan (or possibly 
> JDBCFetchPlan),
> > and the update information should be obtainable from the FetchPlan's
> > read- and write-lock levels.
> >
> > I don't think that we should rush this change in just so 
> it's in 0.9.7;
> > we can always delay 0.9.7 if it's a must-have, or have a 0.9.8 that
> > follows soon thereafter. Generally-speaking, my experience 
> is that once
> > code gets committed, it tends to not get cleaned up, so the argument
> > "let's get it in for the release and then fix it later" 
> usually ends up
> > turning into "let's get it in for the release". This seems 
> especially
> > true for a change like this, that is exposing new APIs (the hints).
> >
> > Thoughts?
> >
> > -Patrick
> >
> > --
> > Patrick Linskey
> > BEA Systems, Inc.
> >
> > 
> ______________________________________________________________
> _________
> > Notice:  This email message, together with any attachments, 
> may contain
> > information  of  BEA Systems,  Inc.,  its subsidiaries  and 
>  affiliated
> > entities,  that may be confidential,  proprietary,  
> copyrighted  and/or
> > legally privileged, and is intended solely for the use of 
> the individual
> > or entity named in this message. If you are not the 
> intended recipient,
> > and have received this message in error, please immediately 
> return this
> > by email and then delete it.
> >
> > > -----Original Message-----
> > > From: wisneskid@apache.org [mailto:wisneskid@apache.org]
> > > Sent: Tuesday, April 03, 2007 12:35 PM
> > > To: open-jpa-commits@incubator.apache.org
> > > Subject: svn commit: r525252 - in
> > > /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache
> > > /openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java
> > >
> > > Author: wisneskid
> > > Date: Tue Apr  3 12:34:59 2007
> > > New Revision: 525252
> > >
> > > URL: http://svn.apache.org/viewvc?view=rev&rev=525252
> > > Log:
> > > changes for JIRA OPENJPA-182
> > >
> > > Modified:
> > >
> > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/AbstractDB2Dictionary.java
> > >
> > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/DB2Dictionary.java
> > >
> > > Modified:
> > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/AbstractDB2Dictionary.java
> > > URL:
> > > http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-j
> > 
> dbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dicti
> onary.java
> > ?view=diff&rev=> 525252&r1=525251&r2=525252
> > > ==============================================================
> > > ================
> > > ---
> > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/AbstractDB2Dictionary.java (original)
> > > +++
> > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/AbstractDB2Dictionary.java Tue Apr  3 12:34:59 2007
> > > @@ -52,7 +52,7 @@
> > >          supportsLockingWithOrderClause = false;
> > >          supportsLockingWithOuterJoin = false;
> > >          supportsLockingWithInnerJoin = false;
> > > -        supportsLockingWithSelectRange = false;
> > > +        supportsLockingWithSelectRange = true;
> > >
> > >          requiresAutoCommitForMetaData = true;
> > >          requiresAliasForSubselect = true;
> > >
> > > Modified:
> > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/DB2Dictionary.java
> > > URL:
> > > http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-j
> > 
> dbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.ja
> va?view=di
> > ff&rev=525252&r1=> 525251&r2=525252
> > > ==============================================================
> > > ================
> > > ---
> > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/DB2Dictionary.java (original)
> > > +++
> > > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/DB2Dictionary.java Tue Apr  3 12:34:59 2007
> > > @@ -15,13 +15,15 @@
> > >   */
> > >  package org.apache.openjpa.jdbc.sql;
> > >
> > > +import java.lang.reflect.Method;
> > >  import java.sql.Connection;
> > >  import java.sql.DatabaseMetaData;
> > >  import java.sql.SQLException;
> > >  import java.util.Arrays;
> > > -
> > > +import java.util.StringTokenizer;
> > >  import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
> > >  import org.apache.openjpa.jdbc.schema.Sequence;
> > > +import org.apache.openjpa.lib.log.Log;
> > >
> > >  /**
> > >   * Dictionary for IBM DB2 database.
> > > @@ -31,7 +33,18 @@
> > >
> > >      public String optimizeClause = "optimize for";
> > >      public String rowClause = "row";
> > > -
> > > +    private int db2ServerType = 0;
> > > +    private static final int  db2ISeriesV5R3AndEarlier = 1;
> > > +    private static final int db2UDBV81OrEarlier = 2;
> > > +    private static final int db2ZOSV8x = 3;
> > > +    private static final int db2UDBV82AndLater = 4;
> > > +    private static final int  db2ISeriesV5R4AndLater = 5;
> > > +     private static final String  forUpdateOfClause="FOR 
> UPDATE OF";
> > > +    private static final String  withRSClause="WITH RS";
> > > +    private static final String  withRRClause="WITH RR";
> > > +    private static final String  useKeepUpdateLockClause=
> > > "USE AND KEEP UPDATE LOCKS";
> > > +    private static final String
> > > useKeepExclusiveLockClause="USE AND KEEP EXCLUSIVE LOCKS";
> > > +    private static final String  forReadOnlyClause = 
> "FOR READ ONLY";
> > >      public DB2Dictionary() {
> > >          platform = "DB2";
> > >          validationSQL = "SELECT DISTINCT(CURRENT 
> TIMESTAMP) FROM "
> > > @@ -170,6 +183,18 @@
> > >       if (isJDBC3(metaData)) {
> > >                       int maj = 
> metaData.getDatabaseMajorVersion();
> > >               int min = metaData.getDatabaseMinorVersion();
> > > +
> > > +             // Determine the type of DB2 database
> > > +             if (isDB2ISeriesV5R3AndEarlier(metaData))
> > > +                 db2ServerType =db2ISeriesV5R3AndEarlier;
> > > +             else if (isDB2UDBV81OrEarlier(metaData,maj,min))
> > > +                 db2ServerType =db2UDBV81OrEarlier;
> > > +             else if (isDB2ZOSV8x(metaData,maj))
> > > +                 db2ServerType =db2ZOSV8x;
> > > +             else if (isDB2UDBV82AndLater(metaData,maj,min))
> > > +                 db2ServerType=db2UDBV82AndLater;
> > > +             else if (isDB2ISeriesV5R4AndLater(metaData))
> > > +                 db2ServerType=db2ISeriesV5R4AndLater;
> > >
> > >               if (maj >= 9 || (maj == 8 && min >= 2)) {
> > >                       supportsLockingWithMultipleTables = true;
> > > @@ -198,13 +223,221 @@
> > >          }
> > >      }
> > >
> > > +    /** Get the update clause for the query based on the
> > > +     * updateClause and isolationLevel hints
> > > +     */
> > > +    public String getForUpdateClause(JDBCFetchConfiguration
> > > fetch, boolean forUpdate) {
> > > +        String isolationLevel = null;
> > > +        Boolean updateClause = null;
> > > +        DatabaseMetaData metaData = null;
> > > +        StringBuffer forUpdateString = new StringBuffer();
> > > +        try {
> > > +            // Determine the update 
> clause/isolationLevel the hint
> > > +            // overrides the persistence.xml value
> > > +            if (fetch != null &&
> > > fetch.getHint("openjpa.hint.updateClause")
> > > +                !=null )
> > > +                updateClause = (Boolean)fetch.
> > > +                getHint("openjpa.hint.updateClause");
> > > +            else
> > > +                updateClause = forUpdate;
> > > +            if (fetch != null
> > > &&fetch.getHint("openjpa.hint.isolationLevel")
> > > +                !=null )
> > > +                isolationLevel = (String)fetch.
> > > +                getHint("openjpa.hint.isolationLevel");
> > > +            else
> > > +                isolationLevel = conf.getTransactionIsolation();
> > > +            if (updateClause == false)
> > > +                //This sql is not for update so add FOR Read
> > > Only clause
> > > +                forUpdateString.append(" 
> ").append(forReadOnlyClause)
> > > +                .append(" ");
> > > +            else if (updateClause == true){
> > > +
> > > +                switch(db2ServerType){
> > > +                case db2ISeriesV5R3AndEarlier:
> > > +                case db2UDBV81OrEarlier:
> > > +                    if 
> (isolationLevel.equals("read-uncommitted"))
> > > +                        forUpdateString.append("
> > > ").append(withRSClause)
> > > +                        .append("
> > > ").append(forUpdateOfClause).append(" ");
> > > +                    else
> > > +                        forUpdateString.append("
> > > ").append(forUpdateOfClause)
> > > +                        .append(" ");
> > > +                    break;
> > > +                case db2ZOSV8x:
> > > +                case db2UDBV82AndLater:
> > > +                    if (isolationLevel.equals("serializable"))
> > > +                        forUpdateString.append("
> > > ").append(withRRClause)
> > > +                        .append(" 
> ").append(useKeepUpdateLockClause)
> > > +                        .append(" ");
> > > +                    else
> > > +                        forUpdateString.append("
> > > ").append(withRSClause)
> > > +                        .append(" 
> ").append(useKeepUpdateLockClause)
> > > +                        .append(" ");
> > > +                    break;
> > > +                case db2ISeriesV5R4AndLater:
> > > +                    if (isolationLevel.equals("serializable"))
> > > +                        forUpdateString.append("
> > > ").append(withRRClause)
> > > +                        .append("
> > > ").append(useKeepExclusiveLockClause)
> > > +                        .append(" ");
> > > +                    else
> > > +                        forUpdateString.append("
> > > ").append(withRSClause)
> > > +                        .append("
> > > ").append(useKeepExclusiveLockClause)
> > > +                        .append(" ");
> > > +                }
> > > +            }
> > > +        }
> > > +        catch (Exception e) {
> > > +            if (log.isTraceEnabled())
> > > +                log.error(e.toString(),e);
> > > +        }
> > > +        return forUpdateString.toString();
> > > +    }
> > > +
> > > +
> > > +    /** Override the DBDictionary toSelect to call
> > > getOptimizeClause and append
> > > +     *   to the select string
> > > +     */
> > > +    public SQLBuffer toSelect(SQLBuffer selects,
> > > JDBCFetchConfiguration fetch,
> > > +       SQLBuffer from, SQLBuffer where, SQLBuffer group,
> > > +       SQLBuffer having, SQLBuffer order,
> > > +       boolean distinct, boolean forUpdate, long start, long end,
> > > +       int expectedResultCount) {
> > > +       String forUpdateString = 
> getForUpdateClause(fetch,forUpdate);
> > > +       SQLBuffer selString = 
> toOperation(getSelectOperation(fetch),
> > > +            selects, from, where,
> > > +            group, having, order, distinct,
> > > +            forUpdate, start, end,forUpdateString);
> > > +        return selString;
> > > +    }
> > > +
> > > +    public boolean isDB2UDBV82AndLater(DatabaseMetaData
> > > metadata, int maj,
> > > +        int min) throws SQLException {
> > > +        boolean match = false;
> > > +        if
> > > (metadata.getDatabaseProductVersion().indexOf("SQL") != -1
> > > +            && ((maj ==8 && min >=2) ||(maj >=8)))
> > > +            match = true;
> > > +        return match;
> > > +    }
> > > +
> > > +    public boolean isDB2ZOSV8x(DatabaseMetaData metadata,int maj)
> > > +       throws SQLException {
> > > +       boolean match = false;
> > > +       if 
> (metadata.getDatabaseProductVersion().indexOf("DSN") != -1
> > > +           && maj ==8 )
> > > +           match = true;
> > > +        return match;
> > > +    }
> > > +
> > > +    public boolean
> > > isDB2ISeriesV5R3AndEarlier(DatabaseMetaData metadata)
> > > +       throws SQLException {
> > > +       boolean match = false;
> > > +       if 
> (metadata.getDatabaseProductVersion().indexOf("AS") != -1
> > > +           &&
> > > generateVersionNumber(metadata.getDatabaseProductVersion())
> > > +           <= 530 )
> > > +           match = true;
> > > +       return match;
> > > +    }
> > > +
> > > +    public boolean isDB2ISeriesV5R4AndLater(DatabaseMetaData
> > > metadata)
> > > +       throws SQLException {
> > > +       boolean match = false;
> > > +       if 
> (metadata.getDatabaseProductVersion().indexOf("AS") != -1
> > > +           &&
> > > generateVersionNumber(metadata.getDatabaseProductVersion())
> > > +           >= 540 )
> > > +           match = true;
> > > +      return match;
> > > +    }
> > > +
> > > +    public boolean isDB2UDBV81OrEarlier(DatabaseMetaData
> > > metadata,int maj,
> > > +        int min) throws SQLException {
> > > +        boolean match = false;
> > > +        if
> > > (metadata.getDatabaseProductVersion().indexOf("SQL") != -1 &&
> > > +           ((maj ==8 && min <=1)|| maj <8 ))
> > > +            match = true;
> > > +        return match;
> > > +    }
> > > +
> > > +    /** Get the version number for the ISeries
> > > +     */
> > > +    protected  int generateVersionNumber(String versionString) {
> > > +        String s =
> > > versionString.substring(versionString.indexOf('V'));
> > > +        s = s.toUpperCase();
> > > +        int i = -1;
> > > +        StringTokenizer stringtokenizer = new
> > > StringTokenizer(s, "VRM", false);
> > > +        if (stringtokenizer.countTokens() == 3)
> > > +        {
> > > +            String s1 = stringtokenizer.nextToken();
> > > +            s1 = s1 + stringtokenizer.nextToken();
> > > +            s1 = s1 + stringtokenizer.nextToken();
> > > +            i = Integer.parseInt(s1);
> > > +        }
> > > +        return i;
> > > +    }
> > > +
> > > +
> > > +    /**
> > > +     * Override the toOperationMethod of DBDictionary to pass the
> > > +     * forUpdateString.
> > > +     */
> > > +    protected SQLBuffer toOperation(String op, SQLBuffer selects,
> > > +        SQLBuffer from, SQLBuffer where, SQLBuffer group,
> > > SQLBuffer having,
> > > +        SQLBuffer order, boolean distinct, boolean
> > > forUpdate, long start,
> > > +        long end,String forUpdateString) {
> > > +        SQLBuffer buf = new SQLBuffer(this);
> > > +        buf.append(op);
> > > +        boolean range = start != 0 || end != Long.MAX_VALUE;
> > > +        if (range && rangePosition == RANGE_PRE_DISTINCT)
> > > +            appendSelectRange(buf, start, end);
> > > +        if (distinct)
> > > +            buf.append(" DISTINCT");
> > > +        if (range && rangePosition == RANGE_POST_DISTINCT)
> > > +            appendSelectRange(buf, start, end);
> > > +        buf.append(" ").append(selects).append(" FROM
> > > ").append(from);
> > > +
> > > +        if (where != null && !where.isEmpty())
> > > +            buf.append(" WHERE ").append(where);
> > > +        if (group != null && !group.isEmpty())
> > > +            buf.append(" GROUP BY ").append(group);
> > > +        if (having != null && !having.isEmpty()) {
> > > +            assertSupport(supportsHaving, "SupportsHaving");
> > > +            buf.append(" HAVING ").append(having);
> > > +        }
> > > +        if (order != null && !order.isEmpty())
> > > +            buf.append(" ORDER BY ").append(order);
> > > +        if (range && rangePosition == RANGE_POST_SELECT)
> > > +            appendSelectRange(buf, start, end);
> > > +
> > > +        if (!simulateLocking ) {
> > > +            assertSupport(supportsSelectForUpdate,
> > > "SupportsSelectForUpdate");
> > > +            buf.append(" ").append(forUpdateString);
> > > +        }
> > > +        if (range && rangePosition == RANGE_POST_LOCK)
> > > +            appendSelectRange(buf, start, end);
> > > +        return buf;
> > > +    }
> > > +
> > >      public SQLBuffer toSelect(Select sel, boolean forUpdate,
> > >          JDBCFetchConfiguration fetch) {
> > > -        SQLBuffer buf = super.toSelect(sel, forUpdate, fetch);
> > > +        sel.addJoinClassConditions();
> > > +        boolean update = forUpdate && 
> sel.getFromSelect() == null;
> > > +        SQLBuffer select = getSelects(sel, false, update);
> > > +        SQLBuffer ordering = null;
> > > +        if (!sel.isAggregate() || sel.getGrouping() != null)
> > > +            ordering = sel.getOrdering();
> > > +        SQLBuffer from;
> > > +        if (sel.getFromSelect() != null)
> > > +            from = getFromSelect(sel, forUpdate);
> > > +        else
> > > +            from = getFrom(sel, update);
> > > +        SQLBuffer where = getWhere(sel, update);
> > > +        String forUpdateString = 
> getForUpdateClause(fetch,forUpdate);
> > > +        SQLBuffer buf =
> > > toOperation(getSelectOperation(fetch), select,
> > > +            from, where,sel.getGrouping(), sel.getHaving(),
> > > ordering,
> > > +            sel.isDistinct(), forUpdate, sel.getStartIndex(),
> > > +            sel.getEndIndex(),forUpdateString);
> > >          if (sel.getExpectedResultCount() > 0)
> > >              buf.append(" ").append(optimizeClause).append(" ").
> > > -                
> append(String.valueOf(sel.getExpectedResultCount())).
> > > -                append(" ").append(rowClause);
> > > +            append(String.valueOf(sel.getExpectedResultCount())).
> > > +            append(" ").append(rowClause);
> > >          return buf;
> > >      }
> > >  }
> > >
> > >
> > >
> >
> > Notice:  This email message, together with any attachments, 
> may contain information  of  BEA Systems,  Inc.,  its 
> subsidiaries  and  affiliated entities,  that may be 
> confidential,  proprietary,  copyrighted  and/or legally 
> privileged, and is intended solely for the use of the 
> individual or entity named in this message. If you are not 
> the intended recipient, and have received this message in 
> error, please immediately return this by email and then delete it.
> >
> 

Notice:  This email message, together with any attachments, may contain information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,  copyrighted  and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.

Re: svn commit: r525252 - in /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java

Posted by David Wisneski <wi...@gmail.com>.
SQL provides capabilities for tuning of locking.  In the case of DB2
this involves setting the isolation level, update lock, result set
optimize set, etc.
JPA spec does not provide support for these concepts but does provide a rather
open ended setHint api.  It is our intent to make use this api so that
users can
sets these values without having to make use of OpenJPA specific apis
-- granted the hint name and value would be OpenJPA specific.
Furthermore, we are intending to support static SQL.  Static SQL is
extremely important in the enterprise environment for our larger
customers because (1) it provides better optimization of SQL and (2)
auditability and security over who access the data and how it is
accessed.    In the case of static SQL,  these hints would be defined
on a NamedQuery definition and not through runtime api.

On 4/3/07, Patrick Linskey <pl...@bea.com> wrote:
> I'm a little nervous about this change still. I don't like it that we're
> adding yet another way to configure locking, especially since it seems
> like the lock level settings should be sufficient (or nearly so) to
> handle per-transaction / per-query lock levels.
>
> I also still do not believe that isolationLevel should be a hint; it
> seems more rule-like than hint-like.
>
> To date, the OpenJPA model has not been to piggyback on the
> Query.setHint() facilities for vendor-specific metadata, but rather to
> use our OpenJPA extension classes (FetchPlan, etc.) to allow us to
> convey more structured data to the kernel. I think that the isolation
> level should probably be part of FetchPlan (or possibly JDBCFetchPlan),
> and the update information should be obtainable from the FetchPlan's
> read- and write-lock levels.
>
> I don't think that we should rush this change in just so it's in 0.9.7;
> we can always delay 0.9.7 if it's a must-have, or have a 0.9.8 that
> follows soon thereafter. Generally-speaking, my experience is that once
> code gets committed, it tends to not get cleaned up, so the argument
> "let's get it in for the release and then fix it later" usually ends up
> turning into "let's get it in for the release". This seems especially
> true for a change like this, that is exposing new APIs (the hints).
>
> Thoughts?
>
> -Patrick
>
> --
> Patrick Linskey
> BEA Systems, Inc.
>
> _______________________________________________________________________
> Notice:  This email message, together with any attachments, may contain
> information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
> entities,  that may be confidential,  proprietary,  copyrighted  and/or
> legally privileged, and is intended solely for the use of the individual
> or entity named in this message. If you are not the intended recipient,
> and have received this message in error, please immediately return this
> by email and then delete it.
>
> > -----Original Message-----
> > From: wisneskid@apache.org [mailto:wisneskid@apache.org]
> > Sent: Tuesday, April 03, 2007 12:35 PM
> > To: open-jpa-commits@incubator.apache.org
> > Subject: svn commit: r525252 - in
> > /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache
> > /openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java
> >
> > Author: wisneskid
> > Date: Tue Apr  3 12:34:59 2007
> > New Revision: 525252
> >
> > URL: http://svn.apache.org/viewvc?view=rev&rev=525252
> > Log:
> > changes for JIRA OPENJPA-182
> >
> > Modified:
> >
> > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> openjpa/jdbc/sql/AbstractDB2Dictionary.java
> >
> > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> openjpa/jdbc/sql/DB2Dictionary.java
> >
> > Modified:
> > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> openjpa/jdbc/sql/AbstractDB2Dictionary.java
> > URL:
> > http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-j
> dbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java
> ?view=diff&rev=> 525252&r1=525251&r2=525252
> > ==============================================================
> > ================
> > ---
> > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> openjpa/jdbc/sql/AbstractDB2Dictionary.java (original)
> > +++
> > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> openjpa/jdbc/sql/AbstractDB2Dictionary.java Tue Apr  3 12:34:59 2007
> > @@ -52,7 +52,7 @@
> >          supportsLockingWithOrderClause = false;
> >          supportsLockingWithOuterJoin = false;
> >          supportsLockingWithInnerJoin = false;
> > -        supportsLockingWithSelectRange = false;
> > +        supportsLockingWithSelectRange = true;
> >
> >          requiresAutoCommitForMetaData = true;
> >          requiresAliasForSubselect = true;
> >
> > Modified:
> > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> openjpa/jdbc/sql/DB2Dictionary.java
> > URL:
> > http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-j
> dbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java?view=di
> ff&rev=525252&r1=> 525251&r2=525252
> > ==============================================================
> > ================
> > ---
> > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> openjpa/jdbc/sql/DB2Dictionary.java (original)
> > +++
> > incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> openjpa/jdbc/sql/DB2Dictionary.java Tue Apr  3 12:34:59 2007
> > @@ -15,13 +15,15 @@
> >   */
> >  package org.apache.openjpa.jdbc.sql;
> >
> > +import java.lang.reflect.Method;
> >  import java.sql.Connection;
> >  import java.sql.DatabaseMetaData;
> >  import java.sql.SQLException;
> >  import java.util.Arrays;
> > -
> > +import java.util.StringTokenizer;
> >  import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
> >  import org.apache.openjpa.jdbc.schema.Sequence;
> > +import org.apache.openjpa.lib.log.Log;
> >
> >  /**
> >   * Dictionary for IBM DB2 database.
> > @@ -31,7 +33,18 @@
> >
> >      public String optimizeClause = "optimize for";
> >      public String rowClause = "row";
> > -
> > +    private int db2ServerType = 0;
> > +    private static final int  db2ISeriesV5R3AndEarlier = 1;
> > +    private static final int db2UDBV81OrEarlier = 2;
> > +    private static final int db2ZOSV8x = 3;
> > +    private static final int db2UDBV82AndLater = 4;
> > +    private static final int  db2ISeriesV5R4AndLater = 5;
> > +     private static final String  forUpdateOfClause="FOR UPDATE OF";
> > +    private static final String  withRSClause="WITH RS";
> > +    private static final String  withRRClause="WITH RR";
> > +    private static final String  useKeepUpdateLockClause=
> > "USE AND KEEP UPDATE LOCKS";
> > +    private static final String
> > useKeepExclusiveLockClause="USE AND KEEP EXCLUSIVE LOCKS";
> > +    private static final String  forReadOnlyClause = "FOR READ ONLY";
> >      public DB2Dictionary() {
> >          platform = "DB2";
> >          validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
> > @@ -170,6 +183,18 @@
> >       if (isJDBC3(metaData)) {
> >                       int maj = metaData.getDatabaseMajorVersion();
> >               int min = metaData.getDatabaseMinorVersion();
> > +
> > +             // Determine the type of DB2 database
> > +             if (isDB2ISeriesV5R3AndEarlier(metaData))
> > +                 db2ServerType =db2ISeriesV5R3AndEarlier;
> > +             else if (isDB2UDBV81OrEarlier(metaData,maj,min))
> > +                 db2ServerType =db2UDBV81OrEarlier;
> > +             else if (isDB2ZOSV8x(metaData,maj))
> > +                 db2ServerType =db2ZOSV8x;
> > +             else if (isDB2UDBV82AndLater(metaData,maj,min))
> > +                 db2ServerType=db2UDBV82AndLater;
> > +             else if (isDB2ISeriesV5R4AndLater(metaData))
> > +                 db2ServerType=db2ISeriesV5R4AndLater;
> >
> >               if (maj >= 9 || (maj == 8 && min >= 2)) {
> >                       supportsLockingWithMultipleTables = true;
> > @@ -198,13 +223,221 @@
> >          }
> >      }
> >
> > +    /** Get the update clause for the query based on the
> > +     * updateClause and isolationLevel hints
> > +     */
> > +    public String getForUpdateClause(JDBCFetchConfiguration
> > fetch, boolean forUpdate) {
> > +        String isolationLevel = null;
> > +        Boolean updateClause = null;
> > +        DatabaseMetaData metaData = null;
> > +        StringBuffer forUpdateString = new StringBuffer();
> > +        try {
> > +            // Determine the update clause/isolationLevel the hint
> > +            // overrides the persistence.xml value
> > +            if (fetch != null &&
> > fetch.getHint("openjpa.hint.updateClause")
> > +                !=null )
> > +                updateClause = (Boolean)fetch.
> > +                getHint("openjpa.hint.updateClause");
> > +            else
> > +                updateClause = forUpdate;
> > +            if (fetch != null
> > &&fetch.getHint("openjpa.hint.isolationLevel")
> > +                !=null )
> > +                isolationLevel = (String)fetch.
> > +                getHint("openjpa.hint.isolationLevel");
> > +            else
> > +                isolationLevel = conf.getTransactionIsolation();
> > +            if (updateClause == false)
> > +                //This sql is not for update so add FOR Read
> > Only clause
> > +                forUpdateString.append(" ").append(forReadOnlyClause)
> > +                .append(" ");
> > +            else if (updateClause == true){
> > +
> > +                switch(db2ServerType){
> > +                case db2ISeriesV5R3AndEarlier:
> > +                case db2UDBV81OrEarlier:
> > +                    if (isolationLevel.equals("read-uncommitted"))
> > +                        forUpdateString.append("
> > ").append(withRSClause)
> > +                        .append("
> > ").append(forUpdateOfClause).append(" ");
> > +                    else
> > +                        forUpdateString.append("
> > ").append(forUpdateOfClause)
> > +                        .append(" ");
> > +                    break;
> > +                case db2ZOSV8x:
> > +                case db2UDBV82AndLater:
> > +                    if (isolationLevel.equals("serializable"))
> > +                        forUpdateString.append("
> > ").append(withRRClause)
> > +                        .append(" ").append(useKeepUpdateLockClause)
> > +                        .append(" ");
> > +                    else
> > +                        forUpdateString.append("
> > ").append(withRSClause)
> > +                        .append(" ").append(useKeepUpdateLockClause)
> > +                        .append(" ");
> > +                    break;
> > +                case db2ISeriesV5R4AndLater:
> > +                    if (isolationLevel.equals("serializable"))
> > +                        forUpdateString.append("
> > ").append(withRRClause)
> > +                        .append("
> > ").append(useKeepExclusiveLockClause)
> > +                        .append(" ");
> > +                    else
> > +                        forUpdateString.append("
> > ").append(withRSClause)
> > +                        .append("
> > ").append(useKeepExclusiveLockClause)
> > +                        .append(" ");
> > +                }
> > +            }
> > +        }
> > +        catch (Exception e) {
> > +            if (log.isTraceEnabled())
> > +                log.error(e.toString(),e);
> > +        }
> > +        return forUpdateString.toString();
> > +    }
> > +
> > +
> > +    /** Override the DBDictionary toSelect to call
> > getOptimizeClause and append
> > +     *   to the select string
> > +     */
> > +    public SQLBuffer toSelect(SQLBuffer selects,
> > JDBCFetchConfiguration fetch,
> > +       SQLBuffer from, SQLBuffer where, SQLBuffer group,
> > +       SQLBuffer having, SQLBuffer order,
> > +       boolean distinct, boolean forUpdate, long start, long end,
> > +       int expectedResultCount) {
> > +       String forUpdateString = getForUpdateClause(fetch,forUpdate);
> > +       SQLBuffer selString = toOperation(getSelectOperation(fetch),
> > +            selects, from, where,
> > +            group, having, order, distinct,
> > +            forUpdate, start, end,forUpdateString);
> > +        return selString;
> > +    }
> > +
> > +    public boolean isDB2UDBV82AndLater(DatabaseMetaData
> > metadata, int maj,
> > +        int min) throws SQLException {
> > +        boolean match = false;
> > +        if
> > (metadata.getDatabaseProductVersion().indexOf("SQL") != -1
> > +            && ((maj ==8 && min >=2) ||(maj >=8)))
> > +            match = true;
> > +        return match;
> > +    }
> > +
> > +    public boolean isDB2ZOSV8x(DatabaseMetaData metadata,int maj)
> > +       throws SQLException {
> > +       boolean match = false;
> > +       if (metadata.getDatabaseProductVersion().indexOf("DSN") != -1
> > +           && maj ==8 )
> > +           match = true;
> > +        return match;
> > +    }
> > +
> > +    public boolean
> > isDB2ISeriesV5R3AndEarlier(DatabaseMetaData metadata)
> > +       throws SQLException {
> > +       boolean match = false;
> > +       if (metadata.getDatabaseProductVersion().indexOf("AS") != -1
> > +           &&
> > generateVersionNumber(metadata.getDatabaseProductVersion())
> > +           <= 530 )
> > +           match = true;
> > +       return match;
> > +    }
> > +
> > +    public boolean isDB2ISeriesV5R4AndLater(DatabaseMetaData
> > metadata)
> > +       throws SQLException {
> > +       boolean match = false;
> > +       if (metadata.getDatabaseProductVersion().indexOf("AS") != -1
> > +           &&
> > generateVersionNumber(metadata.getDatabaseProductVersion())
> > +           >= 540 )
> > +           match = true;
> > +      return match;
> > +    }
> > +
> > +    public boolean isDB2UDBV81OrEarlier(DatabaseMetaData
> > metadata,int maj,
> > +        int min) throws SQLException {
> > +        boolean match = false;
> > +        if
> > (metadata.getDatabaseProductVersion().indexOf("SQL") != -1 &&
> > +           ((maj ==8 && min <=1)|| maj <8 ))
> > +            match = true;
> > +        return match;
> > +    }
> > +
> > +    /** Get the version number for the ISeries
> > +     */
> > +    protected  int generateVersionNumber(String versionString) {
> > +        String s =
> > versionString.substring(versionString.indexOf('V'));
> > +        s = s.toUpperCase();
> > +        int i = -1;
> > +        StringTokenizer stringtokenizer = new
> > StringTokenizer(s, "VRM", false);
> > +        if (stringtokenizer.countTokens() == 3)
> > +        {
> > +            String s1 = stringtokenizer.nextToken();
> > +            s1 = s1 + stringtokenizer.nextToken();
> > +            s1 = s1 + stringtokenizer.nextToken();
> > +            i = Integer.parseInt(s1);
> > +        }
> > +        return i;
> > +    }
> > +
> > +
> > +    /**
> > +     * Override the toOperationMethod of DBDictionary to pass the
> > +     * forUpdateString.
> > +     */
> > +    protected SQLBuffer toOperation(String op, SQLBuffer selects,
> > +        SQLBuffer from, SQLBuffer where, SQLBuffer group,
> > SQLBuffer having,
> > +        SQLBuffer order, boolean distinct, boolean
> > forUpdate, long start,
> > +        long end,String forUpdateString) {
> > +        SQLBuffer buf = new SQLBuffer(this);
> > +        buf.append(op);
> > +        boolean range = start != 0 || end != Long.MAX_VALUE;
> > +        if (range && rangePosition == RANGE_PRE_DISTINCT)
> > +            appendSelectRange(buf, start, end);
> > +        if (distinct)
> > +            buf.append(" DISTINCT");
> > +        if (range && rangePosition == RANGE_POST_DISTINCT)
> > +            appendSelectRange(buf, start, end);
> > +        buf.append(" ").append(selects).append(" FROM
> > ").append(from);
> > +
> > +        if (where != null && !where.isEmpty())
> > +            buf.append(" WHERE ").append(where);
> > +        if (group != null && !group.isEmpty())
> > +            buf.append(" GROUP BY ").append(group);
> > +        if (having != null && !having.isEmpty()) {
> > +            assertSupport(supportsHaving, "SupportsHaving");
> > +            buf.append(" HAVING ").append(having);
> > +        }
> > +        if (order != null && !order.isEmpty())
> > +            buf.append(" ORDER BY ").append(order);
> > +        if (range && rangePosition == RANGE_POST_SELECT)
> > +            appendSelectRange(buf, start, end);
> > +
> > +        if (!simulateLocking ) {
> > +            assertSupport(supportsSelectForUpdate,
> > "SupportsSelectForUpdate");
> > +            buf.append(" ").append(forUpdateString);
> > +        }
> > +        if (range && rangePosition == RANGE_POST_LOCK)
> > +            appendSelectRange(buf, start, end);
> > +        return buf;
> > +    }
> > +
> >      public SQLBuffer toSelect(Select sel, boolean forUpdate,
> >          JDBCFetchConfiguration fetch) {
> > -        SQLBuffer buf = super.toSelect(sel, forUpdate, fetch);
> > +        sel.addJoinClassConditions();
> > +        boolean update = forUpdate && sel.getFromSelect() == null;
> > +        SQLBuffer select = getSelects(sel, false, update);
> > +        SQLBuffer ordering = null;
> > +        if (!sel.isAggregate() || sel.getGrouping() != null)
> > +            ordering = sel.getOrdering();
> > +        SQLBuffer from;
> > +        if (sel.getFromSelect() != null)
> > +            from = getFromSelect(sel, forUpdate);
> > +        else
> > +            from = getFrom(sel, update);
> > +        SQLBuffer where = getWhere(sel, update);
> > +        String forUpdateString = getForUpdateClause(fetch,forUpdate);
> > +        SQLBuffer buf =
> > toOperation(getSelectOperation(fetch), select,
> > +            from, where,sel.getGrouping(), sel.getHaving(),
> > ordering,
> > +            sel.isDistinct(), forUpdate, sel.getStartIndex(),
> > +            sel.getEndIndex(),forUpdateString);
> >          if (sel.getExpectedResultCount() > 0)
> >              buf.append(" ").append(optimizeClause).append(" ").
> > -                append(String.valueOf(sel.getExpectedResultCount())).
> > -                append(" ").append(rowClause);
> > +            append(String.valueOf(sel.getExpectedResultCount())).
> > +            append(" ").append(rowClause);
> >          return buf;
> >      }
> >  }
> >
> >
> >
>
> Notice:  This email message, together with any attachments, may contain information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,  copyrighted  and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.
>

RE: svn commit: r525252 - in /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java

Posted by Patrick Linskey <pl...@bea.com>.
I'm a little nervous about this change still. I don't like it that we're
adding yet another way to configure locking, especially since it seems
like the lock level settings should be sufficient (or nearly so) to
handle per-transaction / per-query lock levels.

I also still do not believe that isolationLevel should be a hint; it
seems more rule-like than hint-like.

To date, the OpenJPA model has not been to piggyback on the
Query.setHint() facilities for vendor-specific metadata, but rather to
use our OpenJPA extension classes (FetchPlan, etc.) to allow us to
convey more structured data to the kernel. I think that the isolation
level should probably be part of FetchPlan (or possibly JDBCFetchPlan),
and the update information should be obtainable from the FetchPlan's
read- and write-lock levels.

I don't think that we should rush this change in just so it's in 0.9.7;
we can always delay 0.9.7 if it's a must-have, or have a 0.9.8 that
follows soon thereafter. Generally-speaking, my experience is that once
code gets committed, it tends to not get cleaned up, so the argument
"let's get it in for the release and then fix it later" usually ends up
turning into "let's get it in for the release". This seems especially
true for a change like this, that is exposing new APIs (the hints).

Thoughts?

-Patrick

-- 
Patrick Linskey
BEA Systems, Inc. 

_______________________________________________________________________
Notice:  This email message, together with any attachments, may contain
information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
entities,  that may be confidential,  proprietary,  copyrighted  and/or
legally privileged, and is intended solely for the use of the individual
or entity named in this message. If you are not the intended recipient,
and have received this message in error, please immediately return this
by email and then delete it. 

> -----Original Message-----
> From: wisneskid@apache.org [mailto:wisneskid@apache.org] 
> Sent: Tuesday, April 03, 2007 12:35 PM
> To: open-jpa-commits@incubator.apache.org
> Subject: svn commit: r525252 - in 
> /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache
> /openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java
> 
> Author: wisneskid
> Date: Tue Apr  3 12:34:59 2007
> New Revision: 525252
> 
> URL: http://svn.apache.org/viewvc?view=rev&rev=525252
> Log:
> changes for JIRA OPENJPA-182
> 
> Modified:
>     
> incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
openjpa/jdbc/sql/AbstractDB2Dictionary.java
>     
> incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
openjpa/jdbc/sql/DB2Dictionary.java
> 
> Modified: 
> incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
openjpa/jdbc/sql/AbstractDB2Dictionary.java
> URL: 
> http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-j
dbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java
?view=diff&rev=> 525252&r1=525251&r2=525252
> ==============================================================
> ================
> --- 
> incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
openjpa/jdbc/sql/AbstractDB2Dictionary.java (original)
> +++ 
> incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
openjpa/jdbc/sql/AbstractDB2Dictionary.java Tue Apr  3 12:34:59 2007
> @@ -52,7 +52,7 @@
>          supportsLockingWithOrderClause = false;
>          supportsLockingWithOuterJoin = false;
>          supportsLockingWithInnerJoin = false;
> -        supportsLockingWithSelectRange = false;
> +        supportsLockingWithSelectRange = true;
>  
>          requiresAutoCommitForMetaData = true;
>          requiresAliasForSubselect = true;
> 
> Modified: 
> incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
openjpa/jdbc/sql/DB2Dictionary.java
> URL: 
> http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-j
dbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java?view=di
ff&rev=525252&r1=> 525251&r2=525252
> ==============================================================
> ================
> --- 
> incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
openjpa/jdbc/sql/DB2Dictionary.java (original)
> +++ 
> incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
openjpa/jdbc/sql/DB2Dictionary.java Tue Apr  3 12:34:59 2007
> @@ -15,13 +15,15 @@
>   */
>  package org.apache.openjpa.jdbc.sql;
>  
> +import java.lang.reflect.Method;
>  import java.sql.Connection;
>  import java.sql.DatabaseMetaData;
>  import java.sql.SQLException;
>  import java.util.Arrays;
> -
> +import java.util.StringTokenizer;
>  import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
>  import org.apache.openjpa.jdbc.schema.Sequence;
> +import org.apache.openjpa.lib.log.Log;
>  
>  /**
>   * Dictionary for IBM DB2 database.
> @@ -31,7 +33,18 @@
>  
>      public String optimizeClause = "optimize for";
>      public String rowClause = "row";
> -
> +    private int db2ServerType = 0; 
> +    private static final int  db2ISeriesV5R3AndEarlier = 1;
> +    private static final int db2UDBV81OrEarlier = 2;
> +    private static final int db2ZOSV8x = 3;
> +    private static final int db2UDBV82AndLater = 4;
> +    private static final int  db2ISeriesV5R4AndLater = 5;
> +	private static final String  forUpdateOfClause="FOR UPDATE OF";
> +    private static final String  withRSClause="WITH RS";
> +    private static final String  withRRClause="WITH RR";
> +    private static final String  useKeepUpdateLockClause= 
> "USE AND KEEP UPDATE LOCKS";
> +    private static final String  
> useKeepExclusiveLockClause="USE AND KEEP EXCLUSIVE LOCKS";
> +    private static final String  forReadOnlyClause = "FOR READ ONLY";
>      public DB2Dictionary() {
>          platform = "DB2";
>          validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
> @@ -170,6 +183,18 @@
>      	if (isJDBC3(metaData)) {
>  			int maj = metaData.getDatabaseMajorVersion();
>  	    	int min = metaData.getDatabaseMinorVersion();
> +	    	
> +	    	// Determine the type of DB2 database
> +	    	if (isDB2ISeriesV5R3AndEarlier(metaData))
> +	    	    db2ServerType =db2ISeriesV5R3AndEarlier;
> +	    	else if (isDB2UDBV81OrEarlier(metaData,maj,min))
> +	    	    db2ServerType =db2UDBV81OrEarlier;
> +	    	else if (isDB2ZOSV8x(metaData,maj))
> +	    	    db2ServerType =db2ZOSV8x;
> +	    	else if (isDB2UDBV82AndLater(metaData,maj,min))
> +	    	    db2ServerType=db2UDBV82AndLater;
> +	    	else if (isDB2ISeriesV5R4AndLater(metaData))
> +	    	    db2ServerType=db2ISeriesV5R4AndLater;
>  
>  	    	if (maj >= 9 || (maj == 8 && min >= 2)) {
>  	    		supportsLockingWithMultipleTables = true;
> @@ -198,13 +223,221 @@
>          }
>      }
>      
> +    /** Get the update clause for the query based on the 
> +     * updateClause and isolationLevel hints
> +     */
> +    public String getForUpdateClause(JDBCFetchConfiguration 
> fetch, boolean forUpdate) {
> +        String isolationLevel = null;
> +        Boolean updateClause = null;
> +        DatabaseMetaData metaData = null;
> +        StringBuffer forUpdateString = new StringBuffer();
> +        try {
> +            // Determine the update clause/isolationLevel the hint 
> +            // overrides the persistence.xml value
> +            if (fetch != null && 
> fetch.getHint("openjpa.hint.updateClause")
> +                !=null )
> +                updateClause = (Boolean)fetch.
> +                getHint("openjpa.hint.updateClause");
> +            else 
> +                updateClause = forUpdate;
> +            if (fetch != null 
> &&fetch.getHint("openjpa.hint.isolationLevel")
> +                !=null )
> +                isolationLevel = (String)fetch.
> +                getHint("openjpa.hint.isolationLevel");
> +            else 
> +                isolationLevel = conf.getTransactionIsolation();
> +            if (updateClause == false)
> +                //This sql is not for update so add FOR Read 
> Only clause
> +                forUpdateString.append(" ").append(forReadOnlyClause)
> +                .append(" ");
> +            else if (updateClause == true){
> +
> +                switch(db2ServerType){
> +                case db2ISeriesV5R3AndEarlier:
> +                case db2UDBV81OrEarlier: 
> +                    if (isolationLevel.equals("read-uncommitted"))
> +                        forUpdateString.append(" 
> ").append(withRSClause)
> +                        .append(" 
> ").append(forUpdateOfClause).append(" ");
> +                    else
> +                        forUpdateString.append(" 
> ").append(forUpdateOfClause)
> +                        .append(" ");
> +                    break;   
> +                case db2ZOSV8x:
> +                case db2UDBV82AndLater: 
> +                    if (isolationLevel.equals("serializable"))
> +                        forUpdateString.append(" 
> ").append(withRRClause)
> +                        .append(" ").append(useKeepUpdateLockClause)
> +                        .append(" ");
> +                    else
> +                        forUpdateString.append(" 
> ").append(withRSClause)
> +                        .append(" ").append(useKeepUpdateLockClause)
> +                        .append(" ");	
> +                    break;
> +                case db2ISeriesV5R4AndLater:
> +                    if (isolationLevel.equals("serializable"))
> +                        forUpdateString.append(" 
> ").append(withRRClause)
> +                        .append(" 
> ").append(useKeepExclusiveLockClause)
> +                        .append(" ");
> +                    else
> +                        forUpdateString.append(" 
> ").append(withRSClause)
> +                        .append(" 
> ").append(useKeepExclusiveLockClause)
> +                        .append(" ");	
> +                }
> +            }
> +        }    
> +        catch (Exception e) {
> +            if (log.isTraceEnabled())
> +                log.error(e.toString(),e);
> +        }
> +        return forUpdateString.toString();
> +    }  
> +
> +   
> +    /** Override the DBDictionary toSelect to call 
> getOptimizeClause and append 
> +     *   to the select string
> +     */   
> +    public SQLBuffer toSelect(SQLBuffer selects, 
> JDBCFetchConfiguration fetch,
> +       SQLBuffer from, SQLBuffer where, SQLBuffer group,
> +       SQLBuffer having, SQLBuffer order,
> +       boolean distinct, boolean forUpdate, long start, long end,
> +       int expectedResultCount) {
> +       String forUpdateString = getForUpdateClause(fetch,forUpdate);
> +       SQLBuffer selString = toOperation(getSelectOperation(fetch), 
> +            selects, from, where,
> +            group, having, order, distinct,
> +            forUpdate, start, end,forUpdateString);
> +        return selString;
> +    }
> +
> +    public boolean isDB2UDBV82AndLater(DatabaseMetaData 
> metadata, int maj,
> +        int min) throws SQLException {
> +        boolean match = false;
> +        if 
> (metadata.getDatabaseProductVersion().indexOf("SQL") != -1 
> +            && ((maj ==8 && min >=2) ||(maj >=8)))
> +            match = true; 
> +        return match;
> +    }
> +
> +    public boolean isDB2ZOSV8x(DatabaseMetaData metadata,int maj)
> +       throws SQLException {
> +       boolean match = false;
> +       if (metadata.getDatabaseProductVersion().indexOf("DSN") != -1 
> +           && maj ==8 )
> +           match = true; 
> +        return match;
> +    }
> +
> +    public boolean 
> isDB2ISeriesV5R3AndEarlier(DatabaseMetaData metadata)
> +       throws SQLException {
> +       boolean match = false;
> +       if (metadata.getDatabaseProductVersion().indexOf("AS") != -1 
> +           && 
> generateVersionNumber(metadata.getDatabaseProductVersion())
> +           <= 530 )
> +           match = true; 
> +       return match;
> +    }
> +
> +    public boolean isDB2ISeriesV5R4AndLater(DatabaseMetaData 
> metadata)
> +       throws SQLException {
> +       boolean match = false;
> +       if (metadata.getDatabaseProductVersion().indexOf("AS") != -1 
> +           && 
> generateVersionNumber(metadata.getDatabaseProductVersion())
> +           >= 540 )
> +           match = true; 
> +      return match;
> +    }
> +
> +    public boolean isDB2UDBV81OrEarlier(DatabaseMetaData 
> metadata,int maj, 
> +        int min) throws SQLException {
> +        boolean match = false;
> +        if 
> (metadata.getDatabaseProductVersion().indexOf("SQL") != -1 &&
> +           ((maj ==8 && min <=1)|| maj <8 ))
> +            match = true; 
> +        return match;
> +    }
> +
> +    /** Get the version number for the ISeries
> +     */ 
> +    protected  int generateVersionNumber(String versionString) {
> +        String s = 
> versionString.substring(versionString.indexOf('V'));
> +        s = s.toUpperCase(); 
> +        int i = -1;
> +        StringTokenizer stringtokenizer = new 
> StringTokenizer(s, "VRM", false);
> +        if (stringtokenizer.countTokens() == 3)
> +        {
> +            String s1 = stringtokenizer.nextToken();
> +            s1 = s1 + stringtokenizer.nextToken();
> +            s1 = s1 + stringtokenizer.nextToken();
> +            i = Integer.parseInt(s1);
> +        }
> +        return i;
> +    }
> + 
> +       
> +    /**
> +     * Override the toOperationMethod of DBDictionary to pass the 
> +     * forUpdateString.
> +     */
> +    protected SQLBuffer toOperation(String op, SQLBuffer selects, 
> +        SQLBuffer from, SQLBuffer where, SQLBuffer group, 
> SQLBuffer having, 
> +        SQLBuffer order, boolean distinct, boolean 
> forUpdate, long start, 
> +        long end,String forUpdateString) {
> +        SQLBuffer buf = new SQLBuffer(this);
> +        buf.append(op);
> +        boolean range = start != 0 || end != Long.MAX_VALUE;
> +        if (range && rangePosition == RANGE_PRE_DISTINCT)
> +            appendSelectRange(buf, start, end);
> +        if (distinct)
> +            buf.append(" DISTINCT");
> +        if (range && rangePosition == RANGE_POST_DISTINCT)
> +            appendSelectRange(buf, start, end);
> +        buf.append(" ").append(selects).append(" FROM 
> ").append(from);
> +
> +        if (where != null && !where.isEmpty())
> +            buf.append(" WHERE ").append(where);
> +        if (group != null && !group.isEmpty())
> +            buf.append(" GROUP BY ").append(group);
> +        if (having != null && !having.isEmpty()) {
> +            assertSupport(supportsHaving, "SupportsHaving");
> +            buf.append(" HAVING ").append(having);
> +        }
> +        if (order != null && !order.isEmpty())
> +            buf.append(" ORDER BY ").append(order);
> +        if (range && rangePosition == RANGE_POST_SELECT)
> +            appendSelectRange(buf, start, end);
> +
> +        if (!simulateLocking ) {
> +            assertSupport(supportsSelectForUpdate, 
> "SupportsSelectForUpdate");
> +            buf.append(" ").append(forUpdateString);
> +        }
> +        if (range && rangePosition == RANGE_POST_LOCK)
> +            appendSelectRange(buf, start, end);
> +        return buf;
> +    }
> +
>      public SQLBuffer toSelect(Select sel, boolean forUpdate,
>          JDBCFetchConfiguration fetch) {
> -        SQLBuffer buf = super.toSelect(sel, forUpdate, fetch); 
> +        sel.addJoinClassConditions();
> +        boolean update = forUpdate && sel.getFromSelect() == null;
> +        SQLBuffer select = getSelects(sel, false, update);
> +        SQLBuffer ordering = null;
> +        if (!sel.isAggregate() || sel.getGrouping() != null)
> +            ordering = sel.getOrdering();
> +        SQLBuffer from;
> +        if (sel.getFromSelect() != null)
> +            from = getFromSelect(sel, forUpdate);
> +        else
> +            from = getFrom(sel, update);
> +        SQLBuffer where = getWhere(sel, update);
> +        String forUpdateString = getForUpdateClause(fetch,forUpdate);
> +        SQLBuffer buf = 
> toOperation(getSelectOperation(fetch), select,
> +            from, where,sel.getGrouping(), sel.getHaving(),  
> ordering,
> +            sel.isDistinct(), forUpdate, sel.getStartIndex(),
> +            sel.getEndIndex(),forUpdateString);
>          if (sel.getExpectedResultCount() > 0)
>              buf.append(" ").append(optimizeClause).append(" ").
> -                append(String.valueOf(sel.getExpectedResultCount())).
> -                append(" ").append(rowClause);
> +            append(String.valueOf(sel.getExpectedResultCount())).
> +            append(" ").append(rowClause);
>          return buf;
>      }
>  }
> 
> 
> 

Notice:  This email message, together with any attachments, may contain information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,  copyrighted  and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.

Re: svn commit: r525252 - in /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java

Posted by Craig L Russell <Cr...@Sun.COM>.
Never mind. I fixed it. I guess we still need to decide whether the  
change goes in, but meantime it should compile...

Craig

On Apr 3, 2007, at 12:58 PM, Ritika Maheshwari wrote:

> yes will do that
>
> ritika
>
>
> On 4/3/07, Craig L Russell <Cr...@sun.com> wrote:
>>
>> Hi David,
>>
>> The DB2Dictionary class doesn't compile with 1.4 due to autoboxing.
>> Can you please fix this?
>>
>> Craig
>>
>>     public String getForUpdateClause(JDBCFetchConfiguration fetch,
>> boolean forUpdate) {
>>         String isolationLevel = null;
>>         Boolean updateClause = null;
>>         DatabaseMetaData metaData = null;
>>         StringBuffer forUpdateString = new StringBuffer();
>>         try {
>>             // Determine the update clause/isolationLevel the hint
>>             // overrides the persistence.xml value
>>             if (fetch != null && fetch.getHint
>> ("openjpa.hint.updateClause")
>>                 !=null )
>>                 updateClause = (Boolean)fetch.
>>                 getHint("openjpa.hint.updateClause");
>>             else
>>                 updateClause = forUpdate;
>> <=========================================== here
>>             if (fetch != null &&fetch.getHint
>> ("openjpa.hint.isolationLevel")
>>                 !=null )
>>                 isolationLevel = (String)fetch.
>>                 getHint("openjpa.hint.isolationLevel");
>>             else
>>                 isolationLevel = conf.getTransactionIsolation();
>>             if (updateClause == false)
>> <=========================================== here
>>                 //This sql is not for update so add FOR Read Only
>> clause
>>                 forUpdateString.append(" ").append(forReadOnlyClause)
>>                 .append(" ");
>>             else if (updateClause == true)
>> { <=========================================== here
>>
>>
>> On Apr 3, 2007, at 12:35 PM, wisneskid@apache.org wrote:
>>
>> > Author: wisneskid
>> > Date: Tue Apr  3 12:34:59 2007
>> > New Revision: 525252
>> >
>> > URL: http://svn.apache.org/viewvc?view=rev&rev=525252
>> > Log:
>> > changes for JIRA OPENJPA-182
>> >
>> > Modified:
>> >     incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
>> > openjpa/jdbc/sql/AbstractDB2Dictionary.java
>> >     incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
>> > openjpa/jdbc/sql/DB2Dictionary.java
>> >
>> > Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/
>> > apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java
>> > URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-
>> > jdbc/src/main/java/org/apache/openjpa/jdbc/sql/
>> > AbstractDB2Dictionary.java?view=diff&rev=525252&r1=525251&r2=525252
>> >  
>> ===================================================================== 
>> =
>> > ========
>> > --- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
>> > openjpa/jdbc/sql/AbstractDB2Dictionary.java (original)
>> > +++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
>> > openjpa/jdbc/sql/AbstractDB2Dictionary.java Tue Apr  3 12:34:59  
>> 2007
>> > @@ -52,7 +52,7 @@
>> >          supportsLockingWithOrderClause = false;
>> >          supportsLockingWithOuterJoin = false;
>> >          supportsLockingWithInnerJoin = false;
>> > -        supportsLockingWithSelectRange = false;
>> > +        supportsLockingWithSelectRange = true;
>> >
>> >          requiresAutoCommitForMetaData = true;
>> >          requiresAliasForSubselect = true;
>> >
>> > Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/
>> > apache/openjpa/jdbc/sql/DB2Dictionary.java
>> > URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-
>> > jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java?
>> > view=diff&rev=525252&r1=525251&r2=525252
>> >  
>> ===================================================================== 
>> =
>> > ========
>> > --- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
>> > openjpa/jdbc/sql/DB2Dictionary.java (original)
>> > +++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
>> > openjpa/jdbc/sql/DB2Dictionary.java Tue Apr  3 12:34:59 2007
>> > @@ -15,13 +15,15 @@
>> >   */
>> >  package org.apache.openjpa.jdbc.sql;
>> >
>> > +import java.lang.reflect.Method;
>> >  import java.sql.Connection;
>> >  import java.sql.DatabaseMetaData;
>> >  import java.sql.SQLException;
>> >  import java.util.Arrays;
>> > -
>> > +import java.util.StringTokenizer;
>> >  import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
>> >  import org.apache.openjpa.jdbc.schema.Sequence;
>> > +import org.apache.openjpa.lib.log.Log;
>> >
>> >  /**
>> >   * Dictionary for IBM DB2 database.
>> > @@ -31,7 +33,18 @@
>> >
>> >      public String optimizeClause = "optimize for";
>> >      public String rowClause = "row";
>> > -
>> > +    private int db2ServerType = 0;
>> > +    private static final int  db2ISeriesV5R3AndEarlier = 1;
>> > +    private static final int db2UDBV81OrEarlier = 2;
>> > +    private static final int db2ZOSV8x = 3;
>> > +    private static final int db2UDBV82AndLater = 4;
>> > +    private static final int  db2ISeriesV5R4AndLater = 5;
>> > +     private static final String  forUpdateOfClause="FOR UPDATE  
>> OF";
>> > +    private static final String  withRSClause="WITH RS";
>> > +    private static final String  withRRClause="WITH RR";
>> > +    private static final String  useKeepUpdateLockClause= "USE AND
>> > KEEP UPDATE LOCKS";
>> > +    private static final String  useKeepExclusiveLockClause="USE
>> > AND KEEP EXCLUSIVE LOCKS";
>> > +    private static final String  forReadOnlyClause = "FOR READ  
>> ONLY";
>> >      public DB2Dictionary() {
>> >          platform = "DB2";
>> >          validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
>> > @@ -170,6 +183,18 @@
>> >       if (isJDBC3(metaData)) {
>> >                       int maj = metaData.getDatabaseMajorVersion();
>> >               int min = metaData.getDatabaseMinorVersion();
>> > +
>> > +             // Determine the type of DB2 database
>> > +             if (isDB2ISeriesV5R3AndEarlier(metaData))
>> > +                 db2ServerType =db2ISeriesV5R3AndEarlier;
>> > +             else if (isDB2UDBV81OrEarlier(metaData,maj,min))
>> > +                 db2ServerType =db2UDBV81OrEarlier;
>> > +             else if (isDB2ZOSV8x(metaData,maj))
>> > +                 db2ServerType =db2ZOSV8x;
>> > +             else if (isDB2UDBV82AndLater(metaData,maj,min))
>> > +                 db2ServerType=db2UDBV82AndLater;
>> > +             else if (isDB2ISeriesV5R4AndLater(metaData))
>> > +                 db2ServerType=db2ISeriesV5R4AndLater;
>> >
>> >               if (maj >= 9 || (maj == 8 && min >= 2)) {
>> >                       supportsLockingWithMultipleTables = true;
>> > @@ -198,13 +223,221 @@
>> >          }
>> >      }
>> >
>> > +    /** Get the update clause for the query based on the
>> > +     * updateClause and isolationLevel hints
>> > +     */
>> > +    public String getForUpdateClause(JDBCFetchConfiguration fetch,
>> > boolean forUpdate) {
>> > +        String isolationLevel = null;
>> > +        Boolean updateClause = null;
>> > +        DatabaseMetaData metaData = null;
>> > +        StringBuffer forUpdateString = new StringBuffer();
>> > +        try {
>> > +            // Determine the update clause/isolationLevel the hint
>> > +            // overrides the persistence.xml value
>> > +            if (fetch != null && fetch.getHint
>> > ("openjpa.hint.updateClause")
>> > +                !=null )
>> > +                updateClause = (Boolean)fetch.
>> > +                getHint("openjpa.hint.updateClause");
>> > +            else
>> > +                updateClause = forUpdate;
>> > +            if (fetch != null &&fetch.getHint
>> > ("openjpa.hint.isolationLevel")
>> > +                !=null )
>> > +                isolationLevel = (String)fetch.
>> > +                getHint("openjpa.hint.isolationLevel");
>> > +            else
>> > +                isolationLevel = conf.getTransactionIsolation();
>> > +            if (updateClause == false)
>> > +                //This sql is not for update so add FOR Read Only
>> > clause
>> > +                forUpdateString.append(" ").append 
>> (forReadOnlyClause)
>> > +                .append(" ");
>> > +            else if (updateClause == true){
>> > +
>> > +                switch(db2ServerType){
>> > +                case db2ISeriesV5R3AndEarlier:
>> > +                case db2UDBV81OrEarlier:
>> > +                    if (isolationLevel.equals("read-uncommitted"))
>> > +                        forUpdateString.append(" ").append
>> > (withRSClause)
>> > +                        .append(" ").append
>> > (forUpdateOfClause).append(" ");
>> > +                    else
>> > +                        forUpdateString.append(" ").append
>> > (forUpdateOfClause)
>> > +                        .append(" ");
>> > +                    break;
>> > +                case db2ZOSV8x:
>> > +                case db2UDBV82AndLater:
>> > +                    if (isolationLevel.equals("serializable"))
>> > +                        forUpdateString.append(" ").append
>> > (withRRClause)
>> > +                        .append(" ").append 
>> (useKeepUpdateLockClause)
>> > +                        .append(" ");
>> > +                    else
>> > +                        forUpdateString.append(" ").append
>> > (withRSClause)
>> > +                        .append(" ").append 
>> (useKeepUpdateLockClause)
>> > +                        .append(" ");
>> > +                    break;
>> > +                case db2ISeriesV5R4AndLater:
>> > +                    if (isolationLevel.equals("serializable"))
>> > +                        forUpdateString.append(" ").append
>> > (withRRClause)
>> > +                        .append(" ").append
>> > (useKeepExclusiveLockClause)
>> > +                        .append(" ");
>> > +                    else
>> > +                        forUpdateString.append(" ").append
>> > (withRSClause)
>> > +                        .append(" ").append
>> > (useKeepExclusiveLockClause)
>> > +                        .append(" ");
>> > +                }
>> > +            }
>> > +        }
>> > +        catch (Exception e) {
>> > +            if (log.isTraceEnabled())
>> > +                log.error(e.toString(),e);
>> > +        }
>> > +        return forUpdateString.toString();
>> > +    }
>> > +
>> > +
>> > +    /** Override the DBDictionary toSelect to call
>> > getOptimizeClause and append
>> > +     *   to the select string
>> > +     */
>> > +    public SQLBuffer toSelect(SQLBuffer selects,
>> > JDBCFetchConfiguration fetch,
>> > +       SQLBuffer from, SQLBuffer where, SQLBuffer group,
>> > +       SQLBuffer having, SQLBuffer order,
>> > +       boolean distinct, boolean forUpdate, long start, long end,
>> > +       int expectedResultCount) {
>> > +       String forUpdateString = getForUpdateClause 
>> (fetch,forUpdate);
>> > +       SQLBuffer selString = toOperation(getSelectOperation 
>> (fetch),
>> > +            selects, from, where,
>> > +            group, having, order, distinct,
>> > +            forUpdate, start, end,forUpdateString);
>> > +        return selString;
>> > +    }
>> > +
>> > +    public boolean isDB2UDBV82AndLater(DatabaseMetaData metadata,
>> > int maj,
>> > +        int min) throws SQLException {
>> > +        boolean match = false;
>> > +        if (metadata.getDatabaseProductVersion().indexOf 
>> ("SQL") != -1
>> > +            && ((maj ==8 && min >=2) ||(maj >=8)))
>> > +            match = true;
>> > +        return match;
>> > +    }
>> > +
>> > +    public boolean isDB2ZOSV8x(DatabaseMetaData metadata,int maj)
>> > +       throws SQLException {
>> > +       boolean match = false;
>> > +       if (metadata.getDatabaseProductVersion().indexOf("DSN") ! 
>> = -1
>> > +           && maj ==8 )
>> > +           match = true;
>> > +        return match;
>> > +    }
>> > +
>> > +    public boolean isDB2ISeriesV5R3AndEarlier(DatabaseMetaData
>> > metadata)
>> > +       throws SQLException {
>> > +       boolean match = false;
>> > +       if (metadata.getDatabaseProductVersion().indexOf("AS") ! 
>> = -1
>> > +           && generateVersionNumber
>> > (metadata.getDatabaseProductVersion())
>> > +           <= 530 )
>> > +           match = true;
>> > +       return match;
>> > +    }
>> > +
>> > +    public boolean isDB2ISeriesV5R4AndLater(DatabaseMetaData
>> > metadata)
>> > +       throws SQLException {
>> > +       boolean match = false;
>> > +       if (metadata.getDatabaseProductVersion().indexOf("AS") ! 
>> = -1
>> > +           && generateVersionNumber
>> > (metadata.getDatabaseProductVersion())
>> > +           >= 540 )
>> > +           match = true;
>> > +      return match;
>> > +    }
>> > +
>> > +    public boolean isDB2UDBV81OrEarlier(DatabaseMetaData
>> > metadata,int maj,
>> > +        int min) throws SQLException {
>> > +        boolean match = false;
>> > +        if (metadata.getDatabaseProductVersion().indexOf("SQL") !=
>> > -1 &&
>> > +           ((maj ==8 && min <=1)|| maj <8 ))
>> > +            match = true;
>> > +        return match;
>> > +    }
>> > +
>> > +    /** Get the version number for the ISeries
>> > +     */
>> > +    protected  int generateVersionNumber(String versionString) {
>> > +        String s = versionString.substring(versionString.indexOf
>> > ('V'));
>> > +        s = s.toUpperCase();
>> > +        int i = -1;
>> > +        StringTokenizer stringtokenizer = new StringTokenizer(s,
>> > "VRM", false);
>> > +        if (stringtokenizer.countTokens() == 3)
>> > +        {
>> > +            String s1 = stringtokenizer.nextToken();
>> > +            s1 = s1 + stringtokenizer.nextToken();
>> > +            s1 = s1 + stringtokenizer.nextToken();
>> > +            i = Integer.parseInt(s1);
>> > +        }
>> > +        return i;
>> > +    }
>> > +
>> > +
>> > +    /**
>> > +     * Override the toOperationMethod of DBDictionary to pass the
>> > +     * forUpdateString.
>> > +     */
>> > +    protected SQLBuffer toOperation(String op, SQLBuffer selects,
>> > +        SQLBuffer from, SQLBuffer where, SQLBuffer group,
>> > SQLBuffer having,
>> > +        SQLBuffer order, boolean distinct, boolean forUpdate, long
>> > start,
>> > +        long end,String forUpdateString) {
>> > +        SQLBuffer buf = new SQLBuffer(this);
>> > +        buf.append(op);
>> > +        boolean range = start != 0 || end != Long.MAX_VALUE;
>> > +        if (range && rangePosition == RANGE_PRE_DISTINCT)
>> > +            appendSelectRange(buf, start, end);
>> > +        if (distinct)
>> > +            buf.append(" DISTINCT");
>> > +        if (range && rangePosition == RANGE_POST_DISTINCT)
>> > +            appendSelectRange(buf, start, end);
>> > +        buf.append(" ").append(selects).append(" FROM ").append
>> > (from);
>> > +
>> > +        if (where != null && !where.isEmpty())
>> > +            buf.append(" WHERE ").append(where);
>> > +        if (group != null && !group.isEmpty())
>> > +            buf.append(" GROUP BY ").append(group);
>> > +        if (having != null && !having.isEmpty()) {
>> > +            assertSupport(supportsHaving, "SupportsHaving");
>> > +            buf.append(" HAVING ").append(having);
>> > +        }
>> > +        if (order != null && !order.isEmpty())
>> > +            buf.append(" ORDER BY ").append(order);
>> > +        if (range && rangePosition == RANGE_POST_SELECT)
>> > +            appendSelectRange(buf, start, end);
>> > +
>> > +        if (!simulateLocking ) {
>> > +            assertSupport(supportsSelectForUpdate,
>> > "SupportsSelectForUpdate");
>> > +            buf.append(" ").append(forUpdateString);
>> > +        }
>> > +        if (range && rangePosition == RANGE_POST_LOCK)
>> > +            appendSelectRange(buf, start, end);
>> > +        return buf;
>> > +    }
>> > +
>> >      public SQLBuffer toSelect(Select sel, boolean forUpdate,
>> >          JDBCFetchConfiguration fetch) {
>> > -        SQLBuffer buf = super.toSelect(sel, forUpdate, fetch);
>> > +        sel.addJoinClassConditions();
>> > +        boolean update = forUpdate && sel.getFromSelect() == null;
>> > +        SQLBuffer select = getSelects(sel, false, update);
>> > +        SQLBuffer ordering = null;
>> > +        if (!sel.isAggregate() || sel.getGrouping() != null)
>> > +            ordering = sel.getOrdering();
>> > +        SQLBuffer from;
>> > +        if (sel.getFromSelect() != null)
>> > +            from = getFromSelect(sel, forUpdate);
>> > +        else
>> > +            from = getFrom(sel, update);
>> > +        SQLBuffer where = getWhere(sel, update);
>> > +        String forUpdateString = getForUpdateClause 
>> (fetch,forUpdate);
>> > +        SQLBuffer buf = toOperation(getSelectOperation(fetch),
>> > select,
>> > +            from, where,sel.getGrouping(), sel.getHaving(),
>> > ordering,
>> > +            sel.isDistinct(), forUpdate, sel.getStartIndex(),
>> > +            sel.getEndIndex(),forUpdateString);
>> >          if (sel.getExpectedResultCount() > 0)
>> >              buf.append(" ").append(optimizeClause).append(" ").
>> > -                append(String.valueOf(sel.getExpectedResultCount 
>> ())).
>> > -                append(" ").append(rowClause);
>> > +            append(String.valueOf(sel.getExpectedResultCount())).
>> > +            append(" ").append(rowClause);
>> >          return buf;
>> >      }
>> >  }
>> >
>> >
>>
>> Craig Russell
>> Architect, Sun Java Enterprise System http://java.sun.com/products/ 
>> jdo
>> 408 276-5638 mailto:Craig.Russell@sun.com
>> P.S. A good JDO? O, Gasp!
>>
>>
>>

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:Craig.Russell@sun.com
P.S. A good JDO? O, Gasp!


Re: svn commit: r525252 - in /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java

Posted by Ritika Maheshwari <ri...@gmail.com>.
yes will do that

ritika


On 4/3/07, Craig L Russell <Cr...@sun.com> wrote:
>
> Hi David,
>
> The DB2Dictionary class doesn't compile with 1.4 due to autoboxing.
> Can you please fix this?
>
> Craig
>
>     public String getForUpdateClause(JDBCFetchConfiguration fetch,
> boolean forUpdate) {
>         String isolationLevel = null;
>         Boolean updateClause = null;
>         DatabaseMetaData metaData = null;
>         StringBuffer forUpdateString = new StringBuffer();
>         try {
>             // Determine the update clause/isolationLevel the hint
>             // overrides the persistence.xml value
>             if (fetch != null && fetch.getHint
> ("openjpa.hint.updateClause")
>                 !=null )
>                 updateClause = (Boolean)fetch.
>                 getHint("openjpa.hint.updateClause");
>             else
>                 updateClause = forUpdate;
> <=========================================== here
>             if (fetch != null &&fetch.getHint
> ("openjpa.hint.isolationLevel")
>                 !=null )
>                 isolationLevel = (String)fetch.
>                 getHint("openjpa.hint.isolationLevel");
>             else
>                 isolationLevel = conf.getTransactionIsolation();
>             if (updateClause == false)
> <=========================================== here
>                 //This sql is not for update so add FOR Read Only
> clause
>                 forUpdateString.append(" ").append(forReadOnlyClause)
>                 .append(" ");
>             else if (updateClause == true)
> { <=========================================== here
>
>
> On Apr 3, 2007, at 12:35 PM, wisneskid@apache.org wrote:
>
> > Author: wisneskid
> > Date: Tue Apr  3 12:34:59 2007
> > New Revision: 525252
> >
> > URL: http://svn.apache.org/viewvc?view=rev&rev=525252
> > Log:
> > changes for JIRA OPENJPA-182
> >
> > Modified:
> >     incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/AbstractDB2Dictionary.java
> >     incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/DB2Dictionary.java
> >
> > Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/
> > apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java
> > URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-
> > jdbc/src/main/java/org/apache/openjpa/jdbc/sql/
> > AbstractDB2Dictionary.java?view=diff&rev=525252&r1=525251&r2=525252
> > ======================================================================
> > ========
> > --- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/AbstractDB2Dictionary.java (original)
> > +++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/AbstractDB2Dictionary.java Tue Apr  3 12:34:59 2007
> > @@ -52,7 +52,7 @@
> >          supportsLockingWithOrderClause = false;
> >          supportsLockingWithOuterJoin = false;
> >          supportsLockingWithInnerJoin = false;
> > -        supportsLockingWithSelectRange = false;
> > +        supportsLockingWithSelectRange = true;
> >
> >          requiresAutoCommitForMetaData = true;
> >          requiresAliasForSubselect = true;
> >
> > Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/
> > apache/openjpa/jdbc/sql/DB2Dictionary.java
> > URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-
> > jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java?
> > view=diff&rev=525252&r1=525251&r2=525252
> > ======================================================================
> > ========
> > --- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/DB2Dictionary.java (original)
> > +++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/
> > openjpa/jdbc/sql/DB2Dictionary.java Tue Apr  3 12:34:59 2007
> > @@ -15,13 +15,15 @@
> >   */
> >  package org.apache.openjpa.jdbc.sql;
> >
> > +import java.lang.reflect.Method;
> >  import java.sql.Connection;
> >  import java.sql.DatabaseMetaData;
> >  import java.sql.SQLException;
> >  import java.util.Arrays;
> > -
> > +import java.util.StringTokenizer;
> >  import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
> >  import org.apache.openjpa.jdbc.schema.Sequence;
> > +import org.apache.openjpa.lib.log.Log;
> >
> >  /**
> >   * Dictionary for IBM DB2 database.
> > @@ -31,7 +33,18 @@
> >
> >      public String optimizeClause = "optimize for";
> >      public String rowClause = "row";
> > -
> > +    private int db2ServerType = 0;
> > +    private static final int  db2ISeriesV5R3AndEarlier = 1;
> > +    private static final int db2UDBV81OrEarlier = 2;
> > +    private static final int db2ZOSV8x = 3;
> > +    private static final int db2UDBV82AndLater = 4;
> > +    private static final int  db2ISeriesV5R4AndLater = 5;
> > +     private static final String  forUpdateOfClause="FOR UPDATE OF";
> > +    private static final String  withRSClause="WITH RS";
> > +    private static final String  withRRClause="WITH RR";
> > +    private static final String  useKeepUpdateLockClause= "USE AND
> > KEEP UPDATE LOCKS";
> > +    private static final String  useKeepExclusiveLockClause="USE
> > AND KEEP EXCLUSIVE LOCKS";
> > +    private static final String  forReadOnlyClause = "FOR READ ONLY";
> >      public DB2Dictionary() {
> >          platform = "DB2";
> >          validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
> > @@ -170,6 +183,18 @@
> >       if (isJDBC3(metaData)) {
> >                       int maj = metaData.getDatabaseMajorVersion();
> >               int min = metaData.getDatabaseMinorVersion();
> > +
> > +             // Determine the type of DB2 database
> > +             if (isDB2ISeriesV5R3AndEarlier(metaData))
> > +                 db2ServerType =db2ISeriesV5R3AndEarlier;
> > +             else if (isDB2UDBV81OrEarlier(metaData,maj,min))
> > +                 db2ServerType =db2UDBV81OrEarlier;
> > +             else if (isDB2ZOSV8x(metaData,maj))
> > +                 db2ServerType =db2ZOSV8x;
> > +             else if (isDB2UDBV82AndLater(metaData,maj,min))
> > +                 db2ServerType=db2UDBV82AndLater;
> > +             else if (isDB2ISeriesV5R4AndLater(metaData))
> > +                 db2ServerType=db2ISeriesV5R4AndLater;
> >
> >               if (maj >= 9 || (maj == 8 && min >= 2)) {
> >                       supportsLockingWithMultipleTables = true;
> > @@ -198,13 +223,221 @@
> >          }
> >      }
> >
> > +    /** Get the update clause for the query based on the
> > +     * updateClause and isolationLevel hints
> > +     */
> > +    public String getForUpdateClause(JDBCFetchConfiguration fetch,
> > boolean forUpdate) {
> > +        String isolationLevel = null;
> > +        Boolean updateClause = null;
> > +        DatabaseMetaData metaData = null;
> > +        StringBuffer forUpdateString = new StringBuffer();
> > +        try {
> > +            // Determine the update clause/isolationLevel the hint
> > +            // overrides the persistence.xml value
> > +            if (fetch != null && fetch.getHint
> > ("openjpa.hint.updateClause")
> > +                !=null )
> > +                updateClause = (Boolean)fetch.
> > +                getHint("openjpa.hint.updateClause");
> > +            else
> > +                updateClause = forUpdate;
> > +            if (fetch != null &&fetch.getHint
> > ("openjpa.hint.isolationLevel")
> > +                !=null )
> > +                isolationLevel = (String)fetch.
> > +                getHint("openjpa.hint.isolationLevel");
> > +            else
> > +                isolationLevel = conf.getTransactionIsolation();
> > +            if (updateClause == false)
> > +                //This sql is not for update so add FOR Read Only
> > clause
> > +                forUpdateString.append(" ").append(forReadOnlyClause)
> > +                .append(" ");
> > +            else if (updateClause == true){
> > +
> > +                switch(db2ServerType){
> > +                case db2ISeriesV5R3AndEarlier:
> > +                case db2UDBV81OrEarlier:
> > +                    if (isolationLevel.equals("read-uncommitted"))
> > +                        forUpdateString.append(" ").append
> > (withRSClause)
> > +                        .append(" ").append
> > (forUpdateOfClause).append(" ");
> > +                    else
> > +                        forUpdateString.append(" ").append
> > (forUpdateOfClause)
> > +                        .append(" ");
> > +                    break;
> > +                case db2ZOSV8x:
> > +                case db2UDBV82AndLater:
> > +                    if (isolationLevel.equals("serializable"))
> > +                        forUpdateString.append(" ").append
> > (withRRClause)
> > +                        .append(" ").append(useKeepUpdateLockClause)
> > +                        .append(" ");
> > +                    else
> > +                        forUpdateString.append(" ").append
> > (withRSClause)
> > +                        .append(" ").append(useKeepUpdateLockClause)
> > +                        .append(" ");
> > +                    break;
> > +                case db2ISeriesV5R4AndLater:
> > +                    if (isolationLevel.equals("serializable"))
> > +                        forUpdateString.append(" ").append
> > (withRRClause)
> > +                        .append(" ").append
> > (useKeepExclusiveLockClause)
> > +                        .append(" ");
> > +                    else
> > +                        forUpdateString.append(" ").append
> > (withRSClause)
> > +                        .append(" ").append
> > (useKeepExclusiveLockClause)
> > +                        .append(" ");
> > +                }
> > +            }
> > +        }
> > +        catch (Exception e) {
> > +            if (log.isTraceEnabled())
> > +                log.error(e.toString(),e);
> > +        }
> > +        return forUpdateString.toString();
> > +    }
> > +
> > +
> > +    /** Override the DBDictionary toSelect to call
> > getOptimizeClause and append
> > +     *   to the select string
> > +     */
> > +    public SQLBuffer toSelect(SQLBuffer selects,
> > JDBCFetchConfiguration fetch,
> > +       SQLBuffer from, SQLBuffer where, SQLBuffer group,
> > +       SQLBuffer having, SQLBuffer order,
> > +       boolean distinct, boolean forUpdate, long start, long end,
> > +       int expectedResultCount) {
> > +       String forUpdateString = getForUpdateClause(fetch,forUpdate);
> > +       SQLBuffer selString = toOperation(getSelectOperation(fetch),
> > +            selects, from, where,
> > +            group, having, order, distinct,
> > +            forUpdate, start, end,forUpdateString);
> > +        return selString;
> > +    }
> > +
> > +    public boolean isDB2UDBV82AndLater(DatabaseMetaData metadata,
> > int maj,
> > +        int min) throws SQLException {
> > +        boolean match = false;
> > +        if (metadata.getDatabaseProductVersion().indexOf("SQL") != -1
> > +            && ((maj ==8 && min >=2) ||(maj >=8)))
> > +            match = true;
> > +        return match;
> > +    }
> > +
> > +    public boolean isDB2ZOSV8x(DatabaseMetaData metadata,int maj)
> > +       throws SQLException {
> > +       boolean match = false;
> > +       if (metadata.getDatabaseProductVersion().indexOf("DSN") != -1
> > +           && maj ==8 )
> > +           match = true;
> > +        return match;
> > +    }
> > +
> > +    public boolean isDB2ISeriesV5R3AndEarlier(DatabaseMetaData
> > metadata)
> > +       throws SQLException {
> > +       boolean match = false;
> > +       if (metadata.getDatabaseProductVersion().indexOf("AS") != -1
> > +           && generateVersionNumber
> > (metadata.getDatabaseProductVersion())
> > +           <= 530 )
> > +           match = true;
> > +       return match;
> > +    }
> > +
> > +    public boolean isDB2ISeriesV5R4AndLater(DatabaseMetaData
> > metadata)
> > +       throws SQLException {
> > +       boolean match = false;
> > +       if (metadata.getDatabaseProductVersion().indexOf("AS") != -1
> > +           && generateVersionNumber
> > (metadata.getDatabaseProductVersion())
> > +           >= 540 )
> > +           match = true;
> > +      return match;
> > +    }
> > +
> > +    public boolean isDB2UDBV81OrEarlier(DatabaseMetaData
> > metadata,int maj,
> > +        int min) throws SQLException {
> > +        boolean match = false;
> > +        if (metadata.getDatabaseProductVersion().indexOf("SQL") !=
> > -1 &&
> > +           ((maj ==8 && min <=1)|| maj <8 ))
> > +            match = true;
> > +        return match;
> > +    }
> > +
> > +    /** Get the version number for the ISeries
> > +     */
> > +    protected  int generateVersionNumber(String versionString) {
> > +        String s = versionString.substring(versionString.indexOf
> > ('V'));
> > +        s = s.toUpperCase();
> > +        int i = -1;
> > +        StringTokenizer stringtokenizer = new StringTokenizer(s,
> > "VRM", false);
> > +        if (stringtokenizer.countTokens() == 3)
> > +        {
> > +            String s1 = stringtokenizer.nextToken();
> > +            s1 = s1 + stringtokenizer.nextToken();
> > +            s1 = s1 + stringtokenizer.nextToken();
> > +            i = Integer.parseInt(s1);
> > +        }
> > +        return i;
> > +    }
> > +
> > +
> > +    /**
> > +     * Override the toOperationMethod of DBDictionary to pass the
> > +     * forUpdateString.
> > +     */
> > +    protected SQLBuffer toOperation(String op, SQLBuffer selects,
> > +        SQLBuffer from, SQLBuffer where, SQLBuffer group,
> > SQLBuffer having,
> > +        SQLBuffer order, boolean distinct, boolean forUpdate, long
> > start,
> > +        long end,String forUpdateString) {
> > +        SQLBuffer buf = new SQLBuffer(this);
> > +        buf.append(op);
> > +        boolean range = start != 0 || end != Long.MAX_VALUE;
> > +        if (range && rangePosition == RANGE_PRE_DISTINCT)
> > +            appendSelectRange(buf, start, end);
> > +        if (distinct)
> > +            buf.append(" DISTINCT");
> > +        if (range && rangePosition == RANGE_POST_DISTINCT)
> > +            appendSelectRange(buf, start, end);
> > +        buf.append(" ").append(selects).append(" FROM ").append
> > (from);
> > +
> > +        if (where != null && !where.isEmpty())
> > +            buf.append(" WHERE ").append(where);
> > +        if (group != null && !group.isEmpty())
> > +            buf.append(" GROUP BY ").append(group);
> > +        if (having != null && !having.isEmpty()) {
> > +            assertSupport(supportsHaving, "SupportsHaving");
> > +            buf.append(" HAVING ").append(having);
> > +        }
> > +        if (order != null && !order.isEmpty())
> > +            buf.append(" ORDER BY ").append(order);
> > +        if (range && rangePosition == RANGE_POST_SELECT)
> > +            appendSelectRange(buf, start, end);
> > +
> > +        if (!simulateLocking ) {
> > +            assertSupport(supportsSelectForUpdate,
> > "SupportsSelectForUpdate");
> > +            buf.append(" ").append(forUpdateString);
> > +        }
> > +        if (range && rangePosition == RANGE_POST_LOCK)
> > +            appendSelectRange(buf, start, end);
> > +        return buf;
> > +    }
> > +
> >      public SQLBuffer toSelect(Select sel, boolean forUpdate,
> >          JDBCFetchConfiguration fetch) {
> > -        SQLBuffer buf = super.toSelect(sel, forUpdate, fetch);
> > +        sel.addJoinClassConditions();
> > +        boolean update = forUpdate && sel.getFromSelect() == null;
> > +        SQLBuffer select = getSelects(sel, false, update);
> > +        SQLBuffer ordering = null;
> > +        if (!sel.isAggregate() || sel.getGrouping() != null)
> > +            ordering = sel.getOrdering();
> > +        SQLBuffer from;
> > +        if (sel.getFromSelect() != null)
> > +            from = getFromSelect(sel, forUpdate);
> > +        else
> > +            from = getFrom(sel, update);
> > +        SQLBuffer where = getWhere(sel, update);
> > +        String forUpdateString = getForUpdateClause(fetch,forUpdate);
> > +        SQLBuffer buf = toOperation(getSelectOperation(fetch),
> > select,
> > +            from, where,sel.getGrouping(), sel.getHaving(),
> > ordering,
> > +            sel.isDistinct(), forUpdate, sel.getStartIndex(),
> > +            sel.getEndIndex(),forUpdateString);
> >          if (sel.getExpectedResultCount() > 0)
> >              buf.append(" ").append(optimizeClause).append(" ").
> > -                append(String.valueOf(sel.getExpectedResultCount())).
> > -                append(" ").append(rowClause);
> > +            append(String.valueOf(sel.getExpectedResultCount())).
> > +            append(" ").append(rowClause);
> >          return buf;
> >      }
> >  }
> >
> >
>
> Craig Russell
> Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
> 408 276-5638 mailto:Craig.Russell@sun.com
> P.S. A good JDO? O, Gasp!
>
>
>

Re: svn commit: r525252 - in /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java

Posted by Abe White <aw...@bea.com>.
> The DB2Dictionary class doesn't compile with 1.4 due to autoboxing.  
> Can you please fix this?

And I'd like to see all those hints defined as static constants on  
the dictionary class and named for DB2 (if they're that specific) and  
capitalized while you're at it -- see OracleDictionary.SELECT_HINT  
for a template.

Notice:  This email message, together with any attachments, may contain information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,  copyrighted  and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.

Re: svn commit: r525252 - in /incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql: AbstractDB2Dictionary.java DB2Dictionary.java

Posted by Craig L Russell <Cr...@Sun.COM>.
Hi David,

The DB2Dictionary class doesn't compile with 1.4 due to autoboxing.  
Can you please fix this?

Craig

     public String getForUpdateClause(JDBCFetchConfiguration fetch,  
boolean forUpdate) {
         String isolationLevel = null;
         Boolean updateClause = null;
         DatabaseMetaData metaData = null;
         StringBuffer forUpdateString = new StringBuffer();
         try {
             // Determine the update clause/isolationLevel the hint
             // overrides the persistence.xml value
             if (fetch != null && fetch.getHint 
("openjpa.hint.updateClause")
                 !=null )
                 updateClause = (Boolean)fetch.
                 getHint("openjpa.hint.updateClause");
             else
                 updateClause = forUpdate;  
<=========================================== here
             if (fetch != null &&fetch.getHint 
("openjpa.hint.isolationLevel")
                 !=null )
                 isolationLevel = (String)fetch.
                 getHint("openjpa.hint.isolationLevel");
             else
                 isolationLevel = conf.getTransactionIsolation();
             if (updateClause == false)  
<=========================================== here
                 //This sql is not for update so add FOR Read Only  
clause
                 forUpdateString.append(" ").append(forReadOnlyClause)
                 .append(" ");
             else if (updateClause == true) 
{ <=========================================== here


On Apr 3, 2007, at 12:35 PM, wisneskid@apache.org wrote:

> Author: wisneskid
> Date: Tue Apr  3 12:34:59 2007
> New Revision: 525252
>
> URL: http://svn.apache.org/viewvc?view=rev&rev=525252
> Log:
> changes for JIRA OPENJPA-182
>
> Modified:
>     incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/ 
> openjpa/jdbc/sql/AbstractDB2Dictionary.java
>     incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/ 
> openjpa/jdbc/sql/DB2Dictionary.java
>
> Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/ 
> apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java
> URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa- 
> jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ 
> AbstractDB2Dictionary.java?view=diff&rev=525252&r1=525251&r2=525252
> ====================================================================== 
> ========
> --- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/ 
> openjpa/jdbc/sql/AbstractDB2Dictionary.java (original)
> +++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/ 
> openjpa/jdbc/sql/AbstractDB2Dictionary.java Tue Apr  3 12:34:59 2007
> @@ -52,7 +52,7 @@
>          supportsLockingWithOrderClause = false;
>          supportsLockingWithOuterJoin = false;
>          supportsLockingWithInnerJoin = false;
> -        supportsLockingWithSelectRange = false;
> +        supportsLockingWithSelectRange = true;
>
>          requiresAutoCommitForMetaData = true;
>          requiresAliasForSubselect = true;
>
> Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/ 
> apache/openjpa/jdbc/sql/DB2Dictionary.java
> URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa- 
> jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java? 
> view=diff&rev=525252&r1=525251&r2=525252
> ====================================================================== 
> ========
> --- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/ 
> openjpa/jdbc/sql/DB2Dictionary.java (original)
> +++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/ 
> openjpa/jdbc/sql/DB2Dictionary.java Tue Apr  3 12:34:59 2007
> @@ -15,13 +15,15 @@
>   */
>  package org.apache.openjpa.jdbc.sql;
>
> +import java.lang.reflect.Method;
>  import java.sql.Connection;
>  import java.sql.DatabaseMetaData;
>  import java.sql.SQLException;
>  import java.util.Arrays;
> -
> +import java.util.StringTokenizer;
>  import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
>  import org.apache.openjpa.jdbc.schema.Sequence;
> +import org.apache.openjpa.lib.log.Log;
>
>  /**
>   * Dictionary for IBM DB2 database.
> @@ -31,7 +33,18 @@
>
>      public String optimizeClause = "optimize for";
>      public String rowClause = "row";
> -
> +    private int db2ServerType = 0;
> +    private static final int  db2ISeriesV5R3AndEarlier = 1;
> +    private static final int db2UDBV81OrEarlier = 2;
> +    private static final int db2ZOSV8x = 3;
> +    private static final int db2UDBV82AndLater = 4;
> +    private static final int  db2ISeriesV5R4AndLater = 5;
> +	private static final String  forUpdateOfClause="FOR UPDATE OF";
> +    private static final String  withRSClause="WITH RS";
> +    private static final String  withRRClause="WITH RR";
> +    private static final String  useKeepUpdateLockClause= "USE AND  
> KEEP UPDATE LOCKS";
> +    private static final String  useKeepExclusiveLockClause="USE  
> AND KEEP EXCLUSIVE LOCKS";
> +    private static final String  forReadOnlyClause = "FOR READ ONLY";
>      public DB2Dictionary() {
>          platform = "DB2";
>          validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
> @@ -170,6 +183,18 @@
>      	if (isJDBC3(metaData)) {
>  			int maj = metaData.getDatabaseMajorVersion();
>  	    	int min = metaData.getDatabaseMinorVersion();
> +	    	
> +	    	// Determine the type of DB2 database
> +	    	if (isDB2ISeriesV5R3AndEarlier(metaData))
> +	    	    db2ServerType =db2ISeriesV5R3AndEarlier;
> +	    	else if (isDB2UDBV81OrEarlier(metaData,maj,min))
> +	    	    db2ServerType =db2UDBV81OrEarlier;
> +	    	else if (isDB2ZOSV8x(metaData,maj))
> +	    	    db2ServerType =db2ZOSV8x;
> +	    	else if (isDB2UDBV82AndLater(metaData,maj,min))
> +	    	    db2ServerType=db2UDBV82AndLater;
> +	    	else if (isDB2ISeriesV5R4AndLater(metaData))
> +	    	    db2ServerType=db2ISeriesV5R4AndLater;
>
>  	    	if (maj >= 9 || (maj == 8 && min >= 2)) {
>  	    		supportsLockingWithMultipleTables = true;
> @@ -198,13 +223,221 @@
>          }
>      }
>
> +    /** Get the update clause for the query based on the
> +     * updateClause and isolationLevel hints
> +     */
> +    public String getForUpdateClause(JDBCFetchConfiguration fetch,  
> boolean forUpdate) {
> +        String isolationLevel = null;
> +        Boolean updateClause = null;
> +        DatabaseMetaData metaData = null;
> +        StringBuffer forUpdateString = new StringBuffer();
> +        try {
> +            // Determine the update clause/isolationLevel the hint
> +            // overrides the persistence.xml value
> +            if (fetch != null && fetch.getHint 
> ("openjpa.hint.updateClause")
> +                !=null )
> +                updateClause = (Boolean)fetch.
> +                getHint("openjpa.hint.updateClause");
> +            else
> +                updateClause = forUpdate;
> +            if (fetch != null &&fetch.getHint 
> ("openjpa.hint.isolationLevel")
> +                !=null )
> +                isolationLevel = (String)fetch.
> +                getHint("openjpa.hint.isolationLevel");
> +            else
> +                isolationLevel = conf.getTransactionIsolation();
> +            if (updateClause == false)
> +                //This sql is not for update so add FOR Read Only  
> clause
> +                forUpdateString.append(" ").append(forReadOnlyClause)
> +                .append(" ");
> +            else if (updateClause == true){
> +
> +                switch(db2ServerType){
> +                case db2ISeriesV5R3AndEarlier:
> +                case db2UDBV81OrEarlier:
> +                    if (isolationLevel.equals("read-uncommitted"))
> +                        forUpdateString.append(" ").append 
> (withRSClause)
> +                        .append(" ").append 
> (forUpdateOfClause).append(" ");
> +                    else
> +                        forUpdateString.append(" ").append 
> (forUpdateOfClause)
> +                        .append(" ");
> +                    break;
> +                case db2ZOSV8x:
> +                case db2UDBV82AndLater:
> +                    if (isolationLevel.equals("serializable"))
> +                        forUpdateString.append(" ").append 
> (withRRClause)
> +                        .append(" ").append(useKeepUpdateLockClause)
> +                        .append(" ");
> +                    else
> +                        forUpdateString.append(" ").append 
> (withRSClause)
> +                        .append(" ").append(useKeepUpdateLockClause)
> +                        .append(" ");	
> +                    break;
> +                case db2ISeriesV5R4AndLater:
> +                    if (isolationLevel.equals("serializable"))
> +                        forUpdateString.append(" ").append 
> (withRRClause)
> +                        .append(" ").append 
> (useKeepExclusiveLockClause)
> +                        .append(" ");
> +                    else
> +                        forUpdateString.append(" ").append 
> (withRSClause)
> +                        .append(" ").append 
> (useKeepExclusiveLockClause)
> +                        .append(" ");	
> +                }
> +            }
> +        }
> +        catch (Exception e) {
> +            if (log.isTraceEnabled())
> +                log.error(e.toString(),e);
> +        }
> +        return forUpdateString.toString();
> +    }
> +
> +
> +    /** Override the DBDictionary toSelect to call  
> getOptimizeClause and append
> +     *   to the select string
> +     */
> +    public SQLBuffer toSelect(SQLBuffer selects,  
> JDBCFetchConfiguration fetch,
> +       SQLBuffer from, SQLBuffer where, SQLBuffer group,
> +       SQLBuffer having, SQLBuffer order,
> +       boolean distinct, boolean forUpdate, long start, long end,
> +       int expectedResultCount) {
> +       String forUpdateString = getForUpdateClause(fetch,forUpdate);
> +       SQLBuffer selString = toOperation(getSelectOperation(fetch),
> +            selects, from, where,
> +            group, having, order, distinct,
> +            forUpdate, start, end,forUpdateString);
> +        return selString;
> +    }
> +
> +    public boolean isDB2UDBV82AndLater(DatabaseMetaData metadata,  
> int maj,
> +        int min) throws SQLException {
> +        boolean match = false;
> +        if (metadata.getDatabaseProductVersion().indexOf("SQL") != -1
> +            && ((maj ==8 && min >=2) ||(maj >=8)))
> +            match = true;
> +        return match;
> +    }
> +
> +    public boolean isDB2ZOSV8x(DatabaseMetaData metadata,int maj)
> +       throws SQLException {
> +       boolean match = false;
> +       if (metadata.getDatabaseProductVersion().indexOf("DSN") != -1
> +           && maj ==8 )
> +           match = true;
> +        return match;
> +    }
> +
> +    public boolean isDB2ISeriesV5R3AndEarlier(DatabaseMetaData  
> metadata)
> +       throws SQLException {
> +       boolean match = false;
> +       if (metadata.getDatabaseProductVersion().indexOf("AS") != -1
> +           && generateVersionNumber 
> (metadata.getDatabaseProductVersion())
> +           <= 530 )
> +           match = true;
> +       return match;
> +    }
> +
> +    public boolean isDB2ISeriesV5R4AndLater(DatabaseMetaData  
> metadata)
> +       throws SQLException {
> +       boolean match = false;
> +       if (metadata.getDatabaseProductVersion().indexOf("AS") != -1
> +           && generateVersionNumber 
> (metadata.getDatabaseProductVersion())
> +           >= 540 )
> +           match = true;
> +      return match;
> +    }
> +
> +    public boolean isDB2UDBV81OrEarlier(DatabaseMetaData  
> metadata,int maj,
> +        int min) throws SQLException {
> +        boolean match = false;
> +        if (metadata.getDatabaseProductVersion().indexOf("SQL") !=  
> -1 &&
> +           ((maj ==8 && min <=1)|| maj <8 ))
> +            match = true;
> +        return match;
> +    }
> +
> +    /** Get the version number for the ISeries
> +     */
> +    protected  int generateVersionNumber(String versionString) {
> +        String s = versionString.substring(versionString.indexOf 
> ('V'));
> +        s = s.toUpperCase();
> +        int i = -1;
> +        StringTokenizer stringtokenizer = new StringTokenizer(s,  
> "VRM", false);
> +        if (stringtokenizer.countTokens() == 3)
> +        {
> +            String s1 = stringtokenizer.nextToken();
> +            s1 = s1 + stringtokenizer.nextToken();
> +            s1 = s1 + stringtokenizer.nextToken();
> +            i = Integer.parseInt(s1);
> +        }
> +        return i;
> +    }
> +
> +
> +    /**
> +     * Override the toOperationMethod of DBDictionary to pass the
> +     * forUpdateString.
> +     */
> +    protected SQLBuffer toOperation(String op, SQLBuffer selects,
> +        SQLBuffer from, SQLBuffer where, SQLBuffer group,  
> SQLBuffer having,
> +        SQLBuffer order, boolean distinct, boolean forUpdate, long  
> start,
> +        long end,String forUpdateString) {
> +        SQLBuffer buf = new SQLBuffer(this);
> +        buf.append(op);
> +        boolean range = start != 0 || end != Long.MAX_VALUE;
> +        if (range && rangePosition == RANGE_PRE_DISTINCT)
> +            appendSelectRange(buf, start, end);
> +        if (distinct)
> +            buf.append(" DISTINCT");
> +        if (range && rangePosition == RANGE_POST_DISTINCT)
> +            appendSelectRange(buf, start, end);
> +        buf.append(" ").append(selects).append(" FROM ").append 
> (from);
> +
> +        if (where != null && !where.isEmpty())
> +            buf.append(" WHERE ").append(where);
> +        if (group != null && !group.isEmpty())
> +            buf.append(" GROUP BY ").append(group);
> +        if (having != null && !having.isEmpty()) {
> +            assertSupport(supportsHaving, "SupportsHaving");
> +            buf.append(" HAVING ").append(having);
> +        }
> +        if (order != null && !order.isEmpty())
> +            buf.append(" ORDER BY ").append(order);
> +        if (range && rangePosition == RANGE_POST_SELECT)
> +            appendSelectRange(buf, start, end);
> +
> +        if (!simulateLocking ) {
> +            assertSupport(supportsSelectForUpdate,  
> "SupportsSelectForUpdate");
> +            buf.append(" ").append(forUpdateString);
> +        }
> +        if (range && rangePosition == RANGE_POST_LOCK)
> +            appendSelectRange(buf, start, end);
> +        return buf;
> +    }
> +
>      public SQLBuffer toSelect(Select sel, boolean forUpdate,
>          JDBCFetchConfiguration fetch) {
> -        SQLBuffer buf = super.toSelect(sel, forUpdate, fetch);
> +        sel.addJoinClassConditions();
> +        boolean update = forUpdate && sel.getFromSelect() == null;
> +        SQLBuffer select = getSelects(sel, false, update);
> +        SQLBuffer ordering = null;
> +        if (!sel.isAggregate() || sel.getGrouping() != null)
> +            ordering = sel.getOrdering();
> +        SQLBuffer from;
> +        if (sel.getFromSelect() != null)
> +            from = getFromSelect(sel, forUpdate);
> +        else
> +            from = getFrom(sel, update);
> +        SQLBuffer where = getWhere(sel, update);
> +        String forUpdateString = getForUpdateClause(fetch,forUpdate);
> +        SQLBuffer buf = toOperation(getSelectOperation(fetch),  
> select,
> +            from, where,sel.getGrouping(), sel.getHaving(),   
> ordering,
> +            sel.isDistinct(), forUpdate, sel.getStartIndex(),
> +            sel.getEndIndex(),forUpdateString);
>          if (sel.getExpectedResultCount() > 0)
>              buf.append(" ").append(optimizeClause).append(" ").
> -                append(String.valueOf(sel.getExpectedResultCount())).
> -                append(" ").append(rowClause);
> +            append(String.valueOf(sel.getExpectedResultCount())).
> +            append(" ").append(rowClause);
>          return buf;
>      }
>  }
>
>

Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:Craig.Russell@sun.com
P.S. A good JDO? O, Gasp!