You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2007/03/02 02:33:47 UTC
svn commit: r513577 [1/3] - in /db/ojb/trunk/src:
java/org/apache/ojb/broker/ java/org/apache/ojb/broker/accesslayer/
java/org/apache/ojb/broker/accesslayer/sql/
java/org/apache/ojb/broker/core/ java/org/apache/ojb/broker/metadata/
java/org/apache/ojb/...
Author: arminw
Date: Thu Mar 1 17:33:44 2007
New Revision: 513577
URL: http://svn.apache.org/viewvc?view=rev&rev=513577
Log:
merge trunk with 1.0.x branch
Added:
db/ojb/trunk/src/test/org/apache/ojb/broker/PaginationTest.java
db/ojb/trunk/src/test/org/apache/ojb/repository_junit_pagination.xml
Modified:
db/ojb/trunk/src/java/org/apache/ojb/broker/PersistenceBroker.java
db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/ChainingIterator.java
db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/OJBIterator.java
db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/PagingIterator.java
db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java
db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java
db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java
db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/JdbcConnectionDescriptor.java
db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/Platform.java
db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDb2Impl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformFirebirdImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformHsqldbImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMckoiImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMsSQLServerImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMySQLImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformOracleImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformPostgreSQLImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformSapdbImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/query/AbstractQueryImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/query/Query.java
db/ojb/trunk/src/java/org/apache/ojb/broker/query/QueryByCriteria.java
db/ojb/trunk/src/java/org/apache/ojb/broker/query/QueryByCriteriaImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/query/QueryByExampleImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/query/ReportQueryByCriteriaImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/util/BrokerHelper.java
db/ojb/trunk/src/java/org/apache/ojb/broker/util/ExceptionHelper.java
db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/AbstractSequenceManager.java
db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/PerFieldManager.java
db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/SequenceManager.java
db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/SequenceManagerHighLowImpl.java
db/ojb/trunk/src/java/org/apache/ojb/broker/util/sequence/SequenceManagerIdentityImpl.java
db/ojb/trunk/src/samples/org/apache/ojb/tutorials/PBExample.java
db/ojb/trunk/src/schema/ojbtest-schema.xml
db/ojb/trunk/src/test/org/apache/ojb/broker/AbstractArticle.java
db/ojb/trunk/src/test/org/apache/ojb/broker/AllTests.java
db/ojb/trunk/src/test/org/apache/ojb/broker/PersistenceBrokerTest.java
db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityHsqlTest.java
db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityMaxDBTest.java
db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityMySqlTest.java
db/ojb/trunk/src/test/org/apache/ojb/broker/sequence/DatabaseIdentityTest.java
db/ojb/trunk/src/test/org/apache/ojb/odmg/DListTest.java
db/ojb/trunk/src/test/org/apache/ojb/odmg/ObjectImageTest.java
db/ojb/trunk/src/test/org/apache/ojb/repository.xml
db/ojb/trunk/src/test/org/apache/ojb/repository_database.xml
db/ojb/trunk/src/test/org/apache/ojb/repository_junit_meta_seq.xml
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/PersistenceBroker.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/PersistenceBroker.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/PersistenceBroker.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/PersistenceBroker.java Thu Mar 1 17:33:44 2007
@@ -37,11 +37,7 @@
* PersistenceBroker declares a protocol for persisting arbitrary objects.
* A typical implementation might wrap an RDBMS access layer.
*
- * @see org.apache.ojb.broker.core.PersistenceBrokerImpl
- *
- * @author <a href="mailto:thomas.mahler@itellium.com">Thomas Mahler<a>
* @version $Id$
- *
*/
public interface PersistenceBroker extends ObjectContainer
{
@@ -116,6 +112,7 @@
/**
* Return the {@link IdentityFactory} instance associated with this broker.
+ *
* @return service to create {@link Identity} objects.
*/
public IdentityFactory serviceIdentity();
@@ -147,7 +144,7 @@
public void fireBrokerEvent(PBStateEvent event);
/**
- * Removes all temporary listeners from this PersistenceBroker instance
+ * Removes all temporary listeners from this broker.
* <b>NOTE:</b> Use with care, because some internals rely on this mechanism.
*
* @see #removeListener(PBListener)
@@ -155,15 +152,12 @@
public void removeAllListeners() throws PersistenceBrokerException;
/**
- * If parameter <code>permanet</code> was <code>true</code> all permanent and temporary listeners
- * will be removed from this PersistenceBroker instance.
- * <br/>
+ * Removes all temporary and, if desired, permanent listeners from this broker.
* <b>NOTE:</b> Use with care, because some internals rely on this mechanism.
*
* @param permanent If <em>false</em> all temporary listener will be removed. If
* <em>true</em> temporaray and permanent listern will be removed from this instance.
* @see #removeListener(PBListener)
- * @see #removeListener(PBListener listener)
*/
public void removeAllListeners(boolean permanent) throws PersistenceBrokerException;
@@ -174,23 +168,21 @@
* it to the pool).
*
* @param listener The listener to add
- * @see #addListener(org.apache.ojb.broker.PBListener listener, boolean permanent)
+ * @see #addListener(PBListener, boolean)
*/
public void addListener(PBListener listener) throws PersistenceBrokerException;
/**
- * Adds a permanent {@link org.apache.ojb.broker.PBListener}
- * to this PersistenceBroker instance if parameter <code>permanent</code>
- * was <code>true</code>. This means the listener will be
- * hold the whole life time of the broker.
+ * Adds a temporary or permanent {@link org.apache.ojb.broker.PBListener} to this broker,
+ * depending on the parameter value. Note that temporary listeners will be removed upon
+ * closing a broker (returning it to the pool).
* <br/>
* <b>NOTE:</b> Handle carefully when using this method, keep in mind you don't
- * know which instance was returned next time from the pool, with a permanent
- * listener or without! To garantee that any pooled broker instance use the permanent
- * listener, best way is to implement your own
+ * know which broker instance will be returned next time from the pool! To guarantee that
+ * a listener is connect to every broker, the best way is to define your own implementation of
* {@link org.apache.ojb.broker.core.PersistenceBrokerFactoryIF} or extend the default
- * implementation {@link org.apache.ojb.broker.core.PersistenceBrokerFactoryDefaultImpl}
- * and add the listener at creation of the {@link org.apache.ojb.broker.PersistenceBroker}
+ * one, {@link org.apache.ojb.broker.core.PersistenceBrokerFactoryDefaultImpl}. There you
+ * can add the listener at creation of the {@link org.apache.ojb.broker.PersistenceBroker}
* instances.
*
* @param listener The listener to add
@@ -343,7 +335,18 @@
/**
* Makes the given object persistent in the underlying persistence system.
* This is usually done by issuing an INSERT ... or UPDATE ... in an RDBMS.
- * The ObjectModification parameter can be used to generate optimized SQL code
+ *
+ * @param obj The object to store
+ * @param modification Specifies what operation to perform (for generating optimized SQL)
+ * @param ignoreReferences If set <em>true</em> OJB will ignore all referenced objects
+ * and only insert/update the fields of the object.
+ */
+ public void store(Object obj,
+ ObjectModification modification, boolean ignoreReferences) throws PersistenceBrokerException;
+
+ /**
+ * Makes the given object persistent in the underlying persistence system.
+ * This is usually done by issuing an INSERT ... or UPDATE ... in an RDBMS.
*
* @param obj The object to store
* @param modification Specifies what operation to perform (for generating optimized SQL)
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/ChainingIterator.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/ChainingIterator.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/ChainingIterator.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/ChainingIterator.java Thu Mar 1 17:33:44 2007
@@ -1,6 +1,6 @@
package org.apache.ojb.broker.accesslayer;
-/* Copyright 2002-2004 The Apache Software Foundation
+/* Copyright 2002-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Collection;
import org.apache.ojb.broker.PersistenceBrokerException;
@@ -34,7 +35,6 @@
* The ChainingIterator cannot return sorted results as the iterator is a
* collection of query results across different tables.
*
- * @author matthew.baird (mattbaird@yahoo.com)
* @version $Id$
*/
public class ChainingIterator implements OJBIterator
@@ -64,9 +64,9 @@
/**
* Constructor for ChainingIterator.
*/
- public ChainingIterator(List iterators)
+ public ChainingIterator(Collection ojbIterators)
{
- Iterator checkIterator = iterators.iterator();
+ Iterator checkIterator = ojbIterators.iterator();
OJBIterator temp;
/**
@@ -156,6 +156,65 @@
return size();
}
+ protected OJBIterator getActiveIterator()
+ {
+ OJBIterator result;
+ if(m_activeIterator == null)
+ {
+ if(m_rsIterators.size() > 0)
+ {
+ result = (OJBIterator) m_rsIterators.get(0);
+ }
+ else
+ {
+ result = OJBIterator.EMPTY_ITERATOR;
+ }
+ }
+ else
+ {
+ result = m_activeIterator;
+ }
+ return result;
+ }
+
+ protected OJBIterator getIterator(int index)
+ {
+ return (OJBIterator) m_rsIterators.get(index);
+ }
+
+ protected OJBIterator setActiveIterator(int iteratorNumber)
+ {
+ m_activeIterator = getIterator(iteratorNumber);
+ m_activeIteratorIndex = iteratorNumber;
+ return m_activeIterator;
+ }
+
+ protected boolean setActiveAbsolute(int row)
+ {
+ OJBIterator it = getActiveIterator();
+ boolean result = it.absolute(row);
+ if(result)
+ {
+ if(row > 0) m_currentCursorPosition = row;
+ else
+ {
+ m_currentCursorPosition = it.size() + 1 + row;
+ }
+ }
+ return result;
+ }
+
+ protected boolean setActiveRelative(int row)
+ {
+ OJBIterator it = getActiveIterator();
+ boolean result = it.relative(row);
+ if(result)
+ {
+ m_currentCursorPosition += row;
+ }
+ return result;
+ }
+
/**
* the absolute and relative calls are the trickiest parts. We have to
* move across cursor boundaries potentially.
@@ -169,74 +228,65 @@
public boolean absolute(int row) throws PersistenceBrokerException
{
checkOpen();
- // 1. handle the special cases first.
+ // 1. handle the special cases first
if (row == 0)
{
return true;
}
-
if (row == 1)
{
- m_activeIteratorIndex = 0;
- m_activeIterator = (OJBIterator) m_rsIterators.get(m_activeIteratorIndex);
- m_activeIterator.absolute(1);
- return true;
+ setActiveIterator(0);
+ return setActiveAbsolute(1);
}
if (row == -1)
{
- m_activeIteratorIndex = m_rsIterators.size();
- m_activeIterator = (OJBIterator) m_rsIterators.get(m_activeIteratorIndex);
- m_activeIterator.absolute(-1);
- return true;
+ setActiveIterator(m_rsIterators.size() - 1);
+ return setActiveAbsolute(-1);
}
-
- // now do the real work.
- boolean movedToAbsolute = false;
+ // 2. now do the real work
boolean retval = false;
- setNextIterator();
-
// row is positive, so index from beginning.
if (row > 0)
{
int sizeCount = 0;
- Iterator it = m_rsIterators.iterator();
OJBIterator temp;
- while (it.hasNext() && !movedToAbsolute)
+ for(int i = 0; i < m_rsIterators.size(); i++)
+ //while (it.hasNext() && !movedToAbsolute)
{
- temp = (OJBIterator) it.next();
- if (temp.size() < row)
+ temp = getIterator(i);
+ int tempMax = temp.size();
+ if(sizeCount + tempMax < row)
{
- sizeCount += temp.size();
+ sizeCount += tempMax;
}
else
{
- // move to the offset - sizecount
- m_currentCursorPosition = row - sizeCount;
- retval = temp.absolute(m_currentCursorPosition);
- movedToAbsolute = true;
+ setActiveIterator(i);
+ retval = setActiveAbsolute(row - sizeCount);
+ break;
}
}
}
-
// row is negative, so index from end
else if (row < 0)
{
int sizeCount = 0;
+ int rowAbs = Math.abs(row);
OJBIterator temp;
- for (int i = m_rsIterators.size(); ((i >= 0) && !movedToAbsolute); i--)
+ for (int i = m_rsIterators.size() - 1; i >= 0; i--)
{
- temp = (OJBIterator) m_rsIterators.get(i);
- if (temp.size() < row)
+ temp = getIterator(i);
+ int tempMax = temp.size();
+ if (sizeCount + tempMax < rowAbs)
{
sizeCount += temp.size();
}
else
{
- // move to the offset - sizecount
- m_currentCursorPosition = row + sizeCount;
- retval = temp.absolute(m_currentCursorPosition);
- movedToAbsolute = true;
+ setActiveIterator(i);
+ retval = setActiveAbsolute(row + sizeCount);
+ break;
}
}
}
@@ -262,45 +312,79 @@
public boolean relative(int row) throws PersistenceBrokerException
{
checkOpen();
+ // 1. handle the special cases first.
if (row == 0)
{
return true;
}
-
- boolean movedToRelative = false;
+ // 2. now do the real work.
boolean retval = false;
- setNextIterator();
-
+ OJBIterator it = getActiveIterator();
+ // positive shift
if (row > 0)
{
// special case checking for the iterator we're currently in
// (since it isn't positioned on the boundary potentially)
- if (row > (m_activeIterator.size() - m_currentCursorPosition))
+ if (row > (it.size() - m_currentCursorPosition))
{
// the relative position lies over the border of the
// current iterator.
// starting position counter should be set to whatever we have left in
// active iterator.
- int positionCounter = m_activeIterator.size() - m_currentCursorPosition;
- for (int i = m_activeIteratorIndex + 1; ((i < m_rsIterators.size()) && !movedToRelative); i++)
+ int positionCounter = it.size() - m_currentCursorPosition;
+ for (int i = m_activeIteratorIndex + 1; i < m_rsIterators.size(); i++)
{
- m_activeIteratorIndex = i;
- m_currentCursorPosition = 0;
- m_activeIterator = (OJBIterator) m_rsIterators.get(m_activeIteratorIndex);
- if (!((row - positionCounter) > m_activeIterator.size()))
+ OJBIterator temp = getIterator(i);
+ if ((row - positionCounter) > temp.size())
+ {
+ positionCounter += temp.size();
+ }
+ else
{
// the relative position requested is within this iterator.
- m_currentCursorPosition = row - positionCounter;
- retval = m_activeIterator.relative(m_currentCursorPosition);
- movedToRelative = true;
+ setActiveIterator(i);
+ retval = setActiveRelative(row - positionCounter);
+ break;
}
}
}
else
{
// the relative position lays within the current iterator.
- retval = m_activeIterator.relative(row);
+ retval = setActiveRelative(row);
+ }
+ }
+ else // negative shift
+ {
+ int rowAbs = Math.abs(row);
+ if(m_currentCursorPosition < rowAbs)
+ {
+ // the relative position lies over the border of the
+ // current iterator.
+
+ // starting position counter should be set to whatever we have left in
+ // active iterator.
+ int positionCounter = m_currentCursorPosition;
+ for (int i = m_activeIteratorIndex - 1; i > -1; i--)
+ {
+ OJBIterator temp = getIterator(i);
+ if ((rowAbs - positionCounter) > temp.size())
+ {
+ positionCounter += temp.size();
+ }
+ else
+ {
+ // the relative position requested is within this iterator.
+ setActiveIterator(i);
+ retval = setActiveRelative(row + positionCounter);
+ break;
+ }
+ }
+ }
+ else
+ {
+ retval = setActiveRelative(row);
}
}
@@ -437,4 +521,5 @@
iter.disableLifeCycleEvents();
}
}
+
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java Thu Mar 1 17:33:44 2007
@@ -59,6 +59,7 @@
import org.apache.ojb.broker.query.NullCriteria;
import org.apache.ojb.broker.query.FieldCriteria;
import org.apache.ojb.broker.query.SqlCriteria;
+import org.apache.ojb.broker.query.AbstractQueryImpl;
import org.apache.ojb.broker.util.BrokerHelper;
import org.apache.ojb.broker.util.ExceptionHelper;
import org.apache.ojb.broker.util.SqlHelper;
@@ -80,7 +81,7 @@
/** The broker in use. */
protected PersistenceBrokerInternal broker;
protected BatchManager batchManager;
- protected Platform platform;
+ protected Platform m_platform;
protected BrokerHelper helper;
/**
@@ -91,7 +92,7 @@
{
this.broker = broker;
this.helper = broker.serviceBrokerHelper();
- this.platform = broker.serviceConnectionManager().getSupportedPlatform();
+ this.m_platform = broker.serviceConnectionManager().getSupportedPlatform();
this.batchManager = broker.serviceBatchManager();
}
@@ -255,7 +256,7 @@
try
{
batchManager.add(batcher, values, 1);
- postSequenceProcess(cld, obj);
+ postSequenceProcess(null, cld, obj);
}
catch(SQLException e)
{
@@ -285,7 +286,7 @@
// TODO: return execution result int value in method
stmt.executeUpdate();
// perform identity column based autoincrement
- postSequenceProcess(cld, obj);
+ postSequenceProcess(stmt, cld, obj);
// Harvest any return values.
if(isStoredProcedure) harvestReturnValues(cld.getInsertProcedure(), obj, (CallableStatement) stmt);
@@ -647,6 +648,16 @@
{
if(log.isDebugEnabled()) log.debug("executeQuery: " + query);
+ /*
+ arminw:
+ we need platform dependent information below, so we have to pre-process the
+ query object, this can cause twice invocation of method Query.preprocess
+ because in class PersistencebrokerImpl#getRsIteratorFromQuery this method
+ is called too
+ TODO: fix twice call of method Query.preprocess if possible
+ */
+ query.preprocess(broker);
+
final StatementManager stmtManager = broker.serviceStatementManager();
final boolean scrollable = isScrollable(query);
SelectStatement sql = null;
@@ -670,7 +681,7 @@
{
// Query implemented as a stored procedure, which must return a result set.
// Query sytax is: { ?= call PROCEDURE_NAME(?,...,?)}
- platform.registerOutResultSet((CallableStatement) stmt, 1);
+ m_platform.registerOutResultSet((CallableStatement) stmt, 1);
bindStatement(stmt, query, cld, 2);
stmt.execute();
rs = (ResultSet) ((CallableStatement) stmt).getObject(1);
@@ -727,7 +738,7 @@
{
// Query implemented as a stored procedure, which must return a result set.
// Query sytax is: { ?= call PROCEDURE_NAME(?,...,?)}
- platform.registerOutResultSet((CallableStatement) stmt, 1);
+ m_platform.registerOutResultSet((CallableStatement) stmt, 1);
bindValues((CallableStatement) stmt, values, 2, null);
stmt.execute();
rs = (ResultSet) ((CallableStatement) stmt).getObject(1);
@@ -881,7 +892,7 @@
boolean useResultSet = procedure.hasReturnValue();
if(useResultSet)
{
- platform.registerOutResultSet(cs, index);
+ m_platform.registerOutResultSet(cs, index);
if(log.isDebugEnabled()) log.debug("[SP] Register OUT ResultSet a index " + index);
++index;
}
@@ -1204,11 +1215,11 @@
/**
* Perform assignment of database identity column based autoincrement values
*/
- protected void postSequenceProcess(ClassDescriptor cld, Object target) throws SequenceManagerException
+ protected void postSequenceProcess(Statement stmt, ClassDescriptor cld, Object target) throws SequenceManagerException
{
// post insert sequence manager call, e.g. to lookup identity column PK value
// from DB and set PK in persistent object
- broker.serviceSequenceManager().afterStore(broker, this, cld, target);
+ broker.serviceSequenceManager().afterStore(broker, this, stmt, cld, target);
}
/**
@@ -1264,7 +1275,7 @@
{
if(index == 1 && descriptor.hasReturnValue())
{
- platform.registerOutResultSet(cs, index);
+ m_platform.registerOutResultSet(cs, index);
if(log.isDebugEnabled()) log.debug("[SP] Register OUT ResultSet a index " + index);
++index;
}
@@ -1325,11 +1336,11 @@
{
if(value == null)
{
- platform.setNullForStatement(stmt, index, sqlType);
+ m_platform.setNullForStatement(stmt, index, sqlType);
}
else
{
- platform.setObjectForStatement(stmt, index, value, sqlType);
+ m_platform.setObjectForStatement(stmt, index, value, sqlType);
}
}
@@ -1432,11 +1443,11 @@
// BRJ: use field conversions and platform
if(value != null)
{
- platform.setObjectForStatement(stmt, index, fld.getFieldConversion().javaToSql(value), fld.getJdbcType().getType());
+ m_platform.setObjectForStatement(stmt, index, fld.getFieldConversion().javaToSql(value), fld.getJdbcType().getType());
}
else
{
- platform.setNullForStatement(stmt, index, fld.getJdbcType().getType());
+ m_platform.setNullForStatement(stmt, index, fld.getJdbcType().getType());
}
}
else
@@ -1517,18 +1528,51 @@
public int bindStatement(final PreparedStatement stmt, final Query query,
final ClassDescriptor cld, int param) throws SQLException
{
- int index;
+ int result = param;
+ //TODO: rework limit/offset support, avoid this cast
+ int[] limitValues = ((AbstractQueryImpl) query).getLimitValues();
+ boolean limitOrOffset = query.usePaging() && limitValues.length > 0;
+ if(limitOrOffset)
+ {
+ if(m_platform.limitAfterSelect())
+ {
+ for(int i = 0; i < limitValues.length; i++)
+ {
+ int limitValue = limitValues[i];
+ m_platform.setObjectForStatement(stmt, result, new Integer(limitValue), Types.INTEGER);
+ ++result;
+ }
+ }
- // check type of subquery
- if (query instanceof QueryByCriteria)
+ // check type of subquery
+ if (query instanceof QueryByCriteria)
+ {
+ QueryByCriteria qbq = (QueryByCriteria) query;
+ result = bindStatement(stmt, qbq.getCriteria(), cld, param);
+ result = bindStatement(stmt, qbq.getHavingCriteria(), cld, result);
+ }
+
+ if(!m_platform.limitAfterSelect())
+ {
+ for(int i = 0; i < limitValues.length; i++)
+ {
+ int limitValue = limitValues[i];
+ m_platform.setObjectForStatement(stmt, result, new Integer(limitValue), Types.INTEGER);
+ ++result;
+ }
+ }
+ }
+ else
{
- QueryByCriteria qbq = (QueryByCriteria) query;
- index = bindStatement(stmt, qbq.getCriteria(), cld, param);
- index = bindStatement(stmt, qbq.getHavingCriteria(), cld, index);
- return index;
+ // check type of subquery
+ if (query instanceof QueryByCriteria)
+ {
+ QueryByCriteria qbq = (QueryByCriteria) query;
+ result = bindStatement(stmt, qbq.getCriteria(), cld, param);
+ result = bindStatement(stmt, qbq.getHavingCriteria(), cld, result);
+ }
}
-
- return param;
+ return result;
}
/** bind a Query based Select Statement */
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/OJBIterator.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/OJBIterator.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/OJBIterator.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/OJBIterator.java Thu Mar 1 17:33:44 2007
@@ -21,8 +21,8 @@
/**
* A {@link Iterator} extension internaly used by OJB to handle query results.
- * <p/>
- * <p/>
+ *
+ * <p>
* NOTE: OJB is very strict in handling <em>OJBIterator</em> instances. The <em>OJBIterator</em> is
* bound very closely to the used {@link org.apache.ojb.broker.PersistenceBroker} instance.
* Thus if you do a
@@ -33,7 +33,7 @@
* call, the current <em>OJBIterator</em> instance resources will be cleaned up automatic
* and invalidate current instance by implicit {@link #releaseDbResources()} call.
* </p>
- * <p/>
+ * <p>
* Except user explicitly call {@link #setAutoRelease(boolean) setAutoRelease(false)}, then the
* user is responsible for release resource call.
* </p>
@@ -43,13 +43,27 @@
public interface OJBIterator extends Iterator
{
/**
+ * Returns the size of the iterator in consideration of limit-seetings
+ * (see {@link org.apache.ojb.broker.query.Query#setStartAtIndex(int)}
+ * and {@link org.apache.ojb.broker.query.Query#setEndAtIndex(int)}) of the
+ * underlying {@link org.apache.ojb.broker.query.Query}.
+ * <br/>
+ * This may differ from the result of method {@link #fullSize()}.
+ *
* @return the size of the iterator, aka the number of rows in this iterator.
*/
int size() throws PersistenceBrokerException;
/**
- * @return the unlimited size of the iterator,
- * fullSize() may differ from size() for PagingIterator
+ * Returns the full size of the iterator.
+ *
+ * @return the unlimited size of the iterator, this may differ from {@link #size()}
+ * dependent of the used implementation - e.g. if
+ * {@link org.apache.ojb.broker.query.Query#setStartAtIndex(int)}
+ * and {@link org.apache.ojb.broker.query.Query#setEndAtIndex(int)} is used in the
+ * underlying {@link org.apache.ojb.broker.query.Query} but the used database does not
+ * support native LIMIT/OFFSET, thus {@link #fullSize()} will return the full iterator size and
+ * {@link #size()} take care of limit boundaries.
*/
int fullSize() throws PersistenceBrokerException;
@@ -63,8 +77,9 @@
boolean absolute(int row) throws PersistenceBrokerException;
/**
- * Moves the cursor a relative number of rows, either positive or negative. Attempting to move beyond the first/last
- * row in the iterator positions the cursor before/after the the first/last row. Calling relative(0) is valid,
+ * Moves the cursor a relative number of rows, either positive or negative.
+ * Attempting to move beyond the first/last row in the iterator positions the
+ * cursor before/after the first/last row. Calling relative(0) is valid,
* but does not change the cursor position.
*
* @param row the row to move to in this iterator, by relative number
@@ -113,4 +128,60 @@
* Do not fire any PBLifeCycleEvent when reading next item.
*/
public void disableLifeCycleEvents();
+
+ /**
+ * A NOOP implementation of this interface.
+ */
+ public static final OJBIterator EMPTY_ITERATOR = new OJBIterator(){
+ public boolean absolute(int row) throws PersistenceBrokerException
+ {
+ return false;
+ }
+
+ public void disableLifeCycleEvents()
+ {
+ }
+
+ public int fullSize() throws PersistenceBrokerException
+ {
+ return 0;
+ }
+
+ public boolean relative(int row) throws PersistenceBrokerException
+ {
+ return false;
+ }
+
+ public void releaseDbResources()
+ {
+ }
+
+ public int size() throws PersistenceBrokerException
+ {
+ return 0;
+ }
+
+ public boolean hasNext()
+ {
+ return false;
+ }
+
+ public Object next()
+ {
+ return null;
+ }
+
+ public void remove()
+ {
+ }
+
+ public boolean isClosed()
+ {
+ return false;
+ }
+
+ public void setAutoRelease(boolean autoRelease)
+ {
+ }
+ };
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/PagingIterator.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/PagingIterator.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/PagingIterator.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/PagingIterator.java Thu Mar 1 17:33:44 2007
@@ -1,6 +1,6 @@
package org.apache.ojb.broker.accesslayer;
-/* Copyright 2003-2004 The Apache Software Foundation
+/* Copyright 2003-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
*/
import org.apache.ojb.broker.PersistenceBrokerException;
+import org.apache.ojb.broker.util.logging.Logger;
+import org.apache.ojb.broker.util.logging.LoggerFactory;
import org.apache.ojb.broker.query.Query;
/**
@@ -26,18 +28,18 @@
* startAt = 1, endAt = 11 returns rows 1 to 11 if available
* if endAt == Query.NO_END_AT_INDEX endAt is set to the last available row
*
- * @author <a href="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
* @version $Id$
*/
public class PagingIterator implements OJBIterator
{
-
+ private Logger log = LoggerFactory.getLogger(PagingIterator.class);
private final OJBIterator m_iterator;
private int m_startAt;
private int m_endAt;
- private int m_rowLimit;
+ private int m_rowLimitSize;
private int m_fullSize;
- private int m_currentCursorPosition; // position of the wrapped iterator
+ // position of the wrapped iterator
+ private int m_currentCursorPosition;
/**
* Constructor
@@ -48,36 +50,29 @@
public PagingIterator(OJBIterator anIterator, int startAt, int endAt)
{
super();
-
- if (endAt != Query.NO_START_AT_INDEX && startAt > endAt)
+ if (endAt != Query.NO_END_AT_INDEX && startAt > endAt)
{
throw new PersistenceBrokerException("startAt must be less than endAt.");
}
- m_iterator = anIterator;
- m_fullSize = m_iterator.size();
-
- if (startAt == Query.NO_START_AT_INDEX)
- {
- m_startAt = 1;
- }
- else
- {
- m_startAt = startAt;
- }
-
- if (endAt == Query.NO_END_AT_INDEX)
- {
- m_endAt = m_fullSize;
+ m_fullSize = anIterator.size();
+ m_startAt = (startAt == Query.NO_START_AT_INDEX ? 1 : startAt);
+ m_endAt = (endAt == Query.NO_END_AT_INDEX || endAt > m_fullSize ? m_fullSize : endAt);
+ m_rowLimitSize = Math.max(0, m_endAt - m_startAt + 1);
+ m_currentCursorPosition = m_startAt;
+ if(m_startAt > m_endAt || m_startAt > m_fullSize)
+ {
+ log.warn("Index out of bound, Query.startAt=" + m_startAt
+ + " and Query.endAt=" + m_endAt + " doesn't match results");
+ m_iterator = OJBIterator.EMPTY_ITERATOR;
+ m_rowLimitSize = 0;
+ m_fullSize = 0;
+ anIterator.releaseDbResources();
}
else
{
- m_endAt = Math.min(endAt, m_fullSize);
+ m_iterator = anIterator;
}
-
- m_rowLimit = Math.max(0, m_endAt - m_startAt + 1);
- m_currentCursorPosition = m_startAt - 1;
-
m_iterator.absolute(m_currentCursorPosition);
}
@@ -99,13 +94,13 @@
*/
public int size() throws PersistenceBrokerException
{
- if (m_fullSize < m_rowLimit)
+ if (m_fullSize < m_rowLimitSize)
{
return m_fullSize;
}
else
{
- return m_rowLimit;
+ return m_rowLimitSize;
}
}
@@ -122,20 +117,23 @@
*/
public boolean absolute(int row) throws PersistenceBrokerException
{
- int newPosition = (m_startAt - 1) + row;
-
- if (newPosition < m_startAt)
+ boolean result = false;
+ int newPosition = 0;
+ if(row > 0)
+ {
+ newPosition = m_startAt - 1 + row;
+ result = m_iterator.absolute(newPosition);
+ }
+ else if(row < 0)
{
- newPosition = Math.max(m_endAt + row, m_startAt - 1);
+ newPosition = m_endAt + 1 + row;
+ result = m_iterator.absolute(newPosition);
}
-
- if (newPosition > m_endAt)
+ if(result)
{
- newPosition = m_endAt;
+ m_currentCursorPosition = newPosition;
}
-
- m_currentCursorPosition = newPosition;
- return m_iterator.absolute(newPosition);
+ return result;
}
/**
@@ -143,7 +141,30 @@
*/
public boolean relative(int row) throws PersistenceBrokerException
{
- return absolute(m_currentCursorPosition - (m_startAt - 1) + row);
+ boolean result = false;
+ if(row > 0)
+ {
+ if(row <= m_endAt - m_currentCursorPosition)
+ {
+ result = m_iterator.relative(row);
+ if(result)
+ {
+ m_currentCursorPosition += row;
+ }
+ }
+ }
+ else if(row < 0)
+ {
+ if(Math.abs(row) <= m_currentCursorPosition - m_startAt)
+ {
+ result = m_iterator.relative(row);
+ if(result)
+ {
+ m_currentCursorPosition += row;
+ }
+ }
+ }
+ return result;
}
/**
@@ -167,16 +188,12 @@
*/
public boolean hasNext()
{
- if (m_currentCursorPosition < m_endAt)
- {
- return true;
- }
- else
+ boolean result = m_currentCursorPosition <= m_endAt && m_iterator.hasNext();
+ if(!result)
{
releaseDbResources();
- return false;
}
-
+ return result;
}
/**
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/RsIterator.java Thu Mar 1 17:33:44 2007
@@ -69,17 +69,12 @@
* It will NOT work with JDBC 1.0 Drivers (e.g. SUN's JdbcOdbcDriver) If you
* are forced to use such a driver, you can use code from the 0.1.30 release.
* </p>
- * @author <a href="mailto:thma@apache.org">Thomas Mahler <a>
- * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird <a>- added the
- * support for extents mapped to single table - added the .size
- * functionality - added cursor control
*
* @version $Id$
*/
public class RsIterator implements OJBIterator
{
protected Logger logger = LoggerFactory.getLogger(this.getClass());
-
private static final String INFO_MSG = "Resources already cleaned up, recommend to set" +
" this flag before first use of the iterator";
/*
@@ -215,6 +210,7 @@
{
setHasCalledCheck(true);
setHasNext(getRsAndStmt().m_rs.next());
+ m_current_row++;
if (!getHasNext())
{
autoReleaseDbResources();
@@ -260,7 +256,7 @@
if (getHasNext())
{
Object obj = getObjectFromResultSet();
- m_current_row++;
+ //m_current_row++;
// Invoke events on PersistenceBrokerAware instances and listeners
// set target object
@@ -507,8 +503,7 @@
{
if (!JDBCSupportAssessed)
{
- if (getConnectionDescriptor().getJdbcLevel() >= 2.0)
- advancedJDBCSupport = true;
+ advancedJDBCSupport = getConnectionDescriptor().getJdbcLevel() >= 2.0;
JDBCSupportAssessed = true;
}
return advancedJDBCSupport;
@@ -667,38 +662,47 @@
private boolean absoluteBasic(int row)
{
boolean retval = false;
-
- if (row > m_current_row)
+ if(row == -1)
{
- try
+ int size = size();
+ if(getQueryObject().usePaging())
{
- while (m_current_row < row && getRsAndStmt().m_rs.next())
+ int span = getQueryObject().getEndIndex() + 1 - getQueryObject().getStartIndex();
+ if(span < size)
{
- m_current_row++;
+ size = span;
}
- if (m_current_row == row)
- {
- retval = true;
- }
- else
+ }
+ row = size;
+ }
+ if (row > m_current_row)
+ {
+ try
+ {
+ retval = true;
+ while (m_current_row < row && retval)
{
- setHasCalledCheck(true);
- setHasNext(false);
- retval = false;
- autoReleaseDbResources();
+ retval = getRsAndStmt().m_rs.next();
+ if(retval) m_current_row++;
+ else break;
}
+ setHasCalledCheck(true);
+ setHasNext(retval);
+ if(!retval) autoReleaseDbResources();
+ System.out.println("result: " + getRsAndStmt().m_rs.getString(1) +", "+ getRsAndStmt().m_rs.getString("Lagerbestand"));
}
catch (Exception ex)
{
setHasCalledCheck(true);
setHasNext(false);
retval = false;
+ autoReleaseDbResources();
}
}
else
{
- logger.info("Your driver does not support advanced JDBC Functionality, " +
- "you cannot call absolute() with a position < current");
+ logger.warn("Your driver does not support advanced JDBC Functionality, " +
+ "you cannot call absolute() with a 'position' < 'current'");
}
return retval;
}
@@ -709,21 +713,26 @@
private boolean absoluteAdvanced(int row)
{
boolean retval = false;
-
try
{
if (getRsAndStmt().m_rs != null)
{
- if (row == 0)
+ if(row == 1 || row == 0)
+ {
+ retval = getRsAndStmt().m_rs.first();
+ //retval = getRsAndStmt().m_rs.absolute(1);
+ }
+ else if (row == -1)
{
- getRsAndStmt().m_rs.beforeFirst();
+ retval = getRsAndStmt().m_rs.last();
}
else
{
- retval = getRsAndStmt().m_rs.absolute(row);
+ retval = getRsAndStmt().m_rs.absolute(row);
}
- m_current_row = row;
- setHasCalledCheck(false);
+ if(retval) m_current_row = row;
+ setHasCalledCheck(retval);
+ setHasNext(retval);
}
}
catch (SQLException e)
@@ -768,7 +777,8 @@
}
else
{
- logger.info("Your driver does not support advanced JDBC Functionality, you cannot call relative() with a negative value");
+ logger.warn("Your driver does not support advanced JDBC Functionality, you cannot call" +
+ " relative() with a negative value");
}
}
return retval;
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/accesslayer/sql/SqlSelectStatement.java Thu Mar 1 17:33:44 2007
@@ -15,12 +15,12 @@
* limitations under the License.
*/
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.lang.ref.WeakReference;
import org.apache.commons.collections.set.ListOrderedSet;
import org.apache.ojb.broker.accesslayer.sql.TableAliasHandler.TableAlias;
@@ -33,6 +33,7 @@
import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.query.QueryByCriteria;
import org.apache.ojb.broker.query.ReportQueryByCriteria;
+import org.apache.ojb.broker.query.AbstractQueryImpl;
import org.apache.ojb.broker.util.SqlHelper;
import org.apache.ojb.broker.util.logging.Logger;
@@ -356,10 +357,10 @@
((ReportQueryByCriteria) query).setAttributeFieldDescriptors(getAttributesToFieldDescriptors());
}
- if(query.isSelectForUpdate())
- {
- stmt.append(getPlatform().getSelectForUpdateClause());
- }
+ stmt = prepareLimitAndOffset(stmt);
+
+ appendSelectForUpdate(stmt);
+
if(query.getQueryAffix() != null)
{
stmt.append(" ").append(query.getQueryAffix());
@@ -368,17 +369,25 @@
return stmt.toString();
}
- /**
- * @see org.apache.ojb.broker.accesslayer.sql.SelectStatement#getQueryInstance()
- */
+ protected StringBuffer prepareLimitAndOffset(StringBuffer stmt)
+ {
+ //TODO: Rework this section
+ return ((AbstractQueryImpl) getQuery()).prepareLimitAndOffset(stmt);
+ }
+
+ protected void appendSelectForUpdate(StringBuffer stmt)
+ {
+ if(getQuery().isSelectForUpdate())
+ {
+ stmt.append(getPlatform().getSelectForUpdateClause());
+ }
+ }
+
public Query getQueryInstance()
{
return getQuery();
}
- /**
- * @see org.apache.ojb.broker.accesslayer.sql.SelectStatement#getColumnIndex(org.apache.ojb.broker.metadata.FieldDescriptor)
- */
public int getColumnIndex(FieldDescriptor fld)
{
int index = JdbcType.MIN_INT;
@@ -397,9 +406,6 @@
return index;
}
- /**
- * @see org.apache.ojb.broker.accesslayer.sql.SelectStatement#isUseOjbClassColumn()
- */
public boolean isUseOjbClassColumn()
{
// BRJ: force generation of sql-string.
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/DelegatingPersistenceBroker.java Thu Mar 1 17:33:44 2007
@@ -277,7 +277,12 @@
getBroker().store(obj, modification);
}
- public PBKey getPBKey()
+ public void store(Object obj, ObjectModification modification, boolean ignoreReferences) throws PersistenceBrokerException
+ {
+ getBroker().store(obj, modification, ignoreReferences);
+ }
+
+ public PBKey getPBKey()
{
return getBroker().getPBKey();
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/core/PersistenceBrokerImpl.java Thu Mar 1 17:33:44 2007
@@ -42,6 +42,7 @@
import org.apache.ojb.broker.TransactionInProgressException;
import org.apache.ojb.broker.TransactionNotInProgressException;
import org.apache.ojb.broker.TransientObjectException;
+import org.apache.ojb.broker.platforms.Platform;
import org.apache.ojb.broker.accesslayer.ChainingIterator;
import org.apache.ojb.broker.accesslayer.CollectionCreationContext;
import org.apache.ojb.broker.accesslayer.ConnectionManagerIF;
@@ -57,7 +58,6 @@
import org.apache.ojb.broker.accesslayer.batch.BatchStrategy;
import org.apache.ojb.broker.accesslayer.batch.ReturnValueValidator;
import org.apache.ojb.broker.accesslayer.sql.SqlGenerator;
-import org.apache.ojb.broker.cache.ObjectCache;
import org.apache.ojb.broker.cache.SessionCache;
import org.apache.ojb.broker.core.configuration.ComponentContainer;
import org.apache.ojb.broker.core.proxy.CollectionProxy;
@@ -1152,25 +1152,6 @@
link(obj, cld, rds, ref, insert);
}
- private void afterStore(TrackingCollection tc, CollectionDescriptor cod)
- {
- if (cod.getCascadingStore() == ObjectReferenceDescriptor.CASCADE_OBJECT)
- {
- Iterator iter = tc.getDeletedObjects().iterator();
- while (iter.hasNext())
- {
- Object obj = iter.next();
- ClassDescriptor cld = getClassDescriptor(obj.getClass());
- if (serviceBrokerHelper().assertValidPkForDelete(cld, obj))
- {
- delete(obj);
- }
- }
- tc.clearDeletedObjects();
- tc.clearNewObjects();
- }
- }
-
/**
* Store/Link collections of objects poiting to <b>obj</b>.
* More info please see comments in source.
@@ -1213,6 +1194,25 @@
}
}
+ private void afterStore(TrackingCollection tc, CollectionDescriptor cod)
+ {
+ if (cod.getCascadingStore() == ObjectReferenceDescriptor.CASCADE_OBJECT)
+ {
+ Iterator iter = tc.getDeletedObjects().iterator();
+ while (iter.hasNext())
+ {
+ Object obj = iter.next();
+ ClassDescriptor cld = getClassDescriptor(obj.getClass());
+ if (serviceBrokerHelper().assertValidPkForDelete(cld, obj))
+ {
+ delete(obj);
+ }
+ }
+ tc.clearDeletedObjects();
+ tc.clearNewObjects();
+ }
+ }
+
/**
* Store/Link m:n collection references.
*
@@ -1940,23 +1940,23 @@
return getIteratorFromQuery(query, cld);
}
- /**
- * Get an extent aware Iterator based on the Query
- *
- * @param query
- * @param cld the ClassDescriptor
- * @return OJBIterator
- */
- protected OJBIterator getIteratorFromQuery(Query query, ClassDescriptor cld) throws PersistenceBrokerException
- {
- OJBIterator result = getRsIteratorFromQuery(query, cld, RsIteratorFactoryFactory.getRsIteratorFactory());
-
- if (query.usePaging())
- {
- result = new PagingIterator(result, query.getStartAtIndex(), query.getEndAtIndex());
- }
- return result;
- }
+// /**
+// * Get an extent aware Iterator based on the Query
+// *
+// * @param query
+// * @param cld the ClassDescriptor
+// * @return OJBIterator
+// */
+// protected OJBIterator getIteratorFromQuery(Query query, ClassDescriptor cld) throws PersistenceBrokerException
+// {
+// OJBIterator result = getRsIteratorFromQuery(query, cld, RsIteratorFactoryFactory.getRsIteratorFactory());
+//
+// if (query.usePaging())
+// {
+// result = new PagingIterator(result, query.getStartAtIndex(), query.getEndAtIndex());
+// }
+// return result;
+// }
public Object getObjectByIdentity(Identity id) throws PersistenceBrokerException
{
@@ -2277,16 +2277,13 @@
return result;
}
- /**
- * Makes object obj persistent in the underlying persistence system.
- * E.G. by INSERT INTO ... or UPDATE ... in an RDBMS.
- * The ObjectModification parameter can be used to determine whether INSERT or update is to be used.
- * This functionality is typically called from transaction managers, that
- * track which objects have to be stored. If the object is an unmaterialized
- * proxy the method return immediately.
- */
public void store(Object obj, ObjectModification mod) throws PersistenceBrokerException
{
+ store(obj, mod, false);
+ }
+
+ public void store(Object obj, ObjectModification mod, boolean ignoreReferences) throws PersistenceBrokerException
+ {
obj = extractObjectToStore(obj);
// null for unmaterialized Proxy
if (obj == null)
@@ -2300,11 +2297,11 @@
// select flag for insert / update selection by checking the ObjectModification
if (mod.needsInsert())
{
- store(obj, oid, cld, true);
+ store(obj, oid, cld, true, ignoreReferences);
}
else if (mod.needsUpdate())
{
- store(obj, oid, cld, false);
+ store(obj, oid, cld, false, ignoreReferences);
}
/*
arminw
@@ -2516,6 +2513,32 @@
}
/**
+ * Get an extent aware Iterator based on the ReportQuery
+ *
+ * @param query
+ * @param cld
+ * @return OJBIterator
+ */
+ protected OJBIterator getReportQueryIteratorFromQuery(Query query, ClassDescriptor cld) throws PersistenceBrokerException
+ {
+ RsIteratorFactory factory = RsIteratorFactoryFactory.getReportRsIteratorFactory();
+ return getRsIteratorFromQuery(query, cld, factory);
+ }
+
+ /**
+ * Get an extent aware Iterator based on the Query
+ *
+ * @param query
+ * @param cld the ClassDescriptor
+ * @return OJBIterator
+ */
+ protected OJBIterator getIteratorFromQuery(Query query, ClassDescriptor cld) throws PersistenceBrokerException
+ {
+ RsIteratorFactory factory = RsIteratorFactoryFactory.getRsIteratorFactory();
+ return getRsIteratorFromQuery(query, cld, factory);
+ }
+
+ /**
* Get an extent aware RsIterator based on the Query
*
* @param query
@@ -2526,60 +2549,90 @@
private OJBIterator getRsIteratorFromQuery(Query query, ClassDescriptor cld, RsIteratorFactory factory)
throws PersistenceBrokerException
{
- query.setFetchSize(1);
+ // arminw: we use iterator for all kind of query, so I think
+ // this setting doesn't make sense and will override user settings
+ //query.setFetchSize(1);
+ /*
+ arminw:
+ we need platform dependent information below, so we have to pre-process the
+ query object, this will cause twice invocation of method Query.preprocess
+ because in class JdbcAccess this method is called too
+ TODO: fix twice call of method Query.preprocess if possible
+ */
query.preprocess(this);
+ OJBIterator result;
if (query instanceof QueryBySQL)
{
if(logger.isDebugEnabled()) logger.debug("Creating SQL-RsIterator for class ["+cld.getClassNameOfObject()+"]");
- return factory.createRsIterator((QueryBySQL) query, cld, this);
+ result = factory.createRsIterator((QueryBySQL) query, cld, this);
+ result = wrapWithPagingIteratorIfNeeded(result, query);
}
-
- if (!cld.isExtent() || !query.getWithExtents())
+ else if (!cld.isExtent() || !query.getWithExtents())
{
// no extents just use the plain vanilla RsIterator
if(logger.isDebugEnabled()) logger.debug("Creating RsIterator for class ["+cld.getClassNameOfObject()+"]");
Query theQuery = serviceBrokerHelper().setConcreteClassCriteria(this, (QueryByCriteria)query, cld);
- return factory.createRsIterator(theQuery, cld, this);
+ result = factory.createRsIterator(theQuery, cld, this);
+ result = wrapWithPagingIteratorIfNeeded(result, query);
}
-
- if(logger.isDebugEnabled()) logger.debug("Creating ChainingIterator for class ["+cld.getClassNameOfObject()+"]");
-
- ChainingIterator chainingIter = new ChainingIterator();
- Collection cldInfos = serviceBrokerHelper().getExtentsDescriptors(cld);
- Iterator extents = cldInfos.iterator();
-
- while (extents.hasNext())
+ else
{
- BrokerHelper.CldInfo cldInfo = (BrokerHelper.CldInfo) extents.next();
- Query theQuery = serviceBrokerHelper().setConcreteClassCriteria(this, (QueryByCriteria)query, cldInfo);
+ if(logger.isDebugEnabled()) logger.debug("Creating ChainingIterator for class ["+cld.getClassNameOfObject()+"]");
- if(logger.isDebugEnabled()) logger.debug("Adding RsIterator of class ["+ cldInfo.cld.getClassNameOfObject()+"] to ChainingIterator");
+ ChainingIterator chainingIter = new ChainingIterator();
+ Collection cldInfos = serviceBrokerHelper().getExtentsDescriptors(cld);
+ Iterator extents = cldInfos.iterator();
- // add the iterator to the chaining iterator.
- chainingIter.addIterator(factory.createRsIterator(theQuery, cldInfo.cld, this));
- }
+ while (extents.hasNext())
+ {
+ BrokerHelper.CldInfo cldInfo = (BrokerHelper.CldInfo) extents.next();
+ if(logger.isDebugEnabled()) logger.debug("Adding RsIterator of class ["+ cldInfo.cld.getClassNameOfObject()+"] to ChainingIterator");
+ Query theQuery = serviceBrokerHelper().setConcreteClassCriteria(this, (QueryByCriteria)query, cldInfo);
+ OJBIterator tmp = wrapWithPagingIteratorIfNeeded(factory.createRsIterator(theQuery, cldInfo.cld, this), theQuery);
+ // add the iterator to the chaining iterator.
+ chainingIter.addIterator(tmp);
+ }
- return chainingIter;
+ result = chainingIter;
+ }
+ return result;
}
/**
- * Get an extent aware Iterator based on the ReportQuery
+ * If native paging (LIMIT and/or LIMIT OFFSET) is not supported by the current
+ * database, wrap the current OJBIterator with a paging wrapper.
*
- * @param query
- * @param cld
- * @return OJBIterator
+ * @param iter The normal iterator.
+ * @param query The query.
+ * @return A paging capable iterator or the specified iterator if native paging
+ * is supported.
*/
- private OJBIterator getReportQueryIteratorFromQuery(Query query, ClassDescriptor cld) throws PersistenceBrokerException
+ protected OJBIterator wrapWithPagingIteratorIfNeeded(OJBIterator iter, Query query)
{
- OJBIterator result = getRsIteratorFromQuery(query, cld, RsIteratorFactoryFactory.getReportRsIteratorFactory());
-
- if (query.usePaging())
+ OJBIterator result = iter;
+ boolean isNativeLimitOffset = serviceConnectionManager().getConnectionDescriptor().isNativeLimitOffset();
+ if(query.usePaging())
{
- result = new PagingIterator(result, query.getStartAtIndex(), query.getEndAtIndex());
+ Platform platform = serviceConnectionManager().getSupportedPlatform();
+ // limit offset needed, full paging
+ if(query.hasOffset())
+ {
+ if(!isNativeLimitOffset || !platform.supportsOffset())
+ {
+ result = new PagingIterator(iter, query.getStartAtIndex(), query.getEndAtIndex());
+ }
+ }
+ // only limit
+ else if (query.hasLimit())
+ {
+ if(!isNativeLimitOffset || !platform.supportsLimit())
+ {
+ result = new PagingIterator(iter, query.getStartAtIndex(), query.getEndAtIndex());
+ }
+ }
}
-
return result;
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/JdbcConnectionDescriptor.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/JdbcConnectionDescriptor.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/JdbcConnectionDescriptor.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/JdbcConnectionDescriptor.java Thu Mar 1 17:33:44 2007
@@ -28,6 +28,7 @@
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
import org.apache.ojb.broker.util.XmlHelper;
+import org.apache.ojb.broker.util.ConvertHelper;
/**
* JdbcConnectionDescriptor describes all relevant parameters of
@@ -43,6 +44,7 @@
public static final int AUTO_COMMIT_IGNORE_STATE = 0;
public static final int AUTO_COMMIT_SET_TRUE_AND_TEMPORARY_FALSE = 1;
public static final int AUTO_COMMIT_SET_FALSE = 2;
+ protected static final String ATTRIBUTE_NATIVE_LIMIT_OFFSET = "nativeLimitOffset";
private String m_jcdAlias;
private String m_Dbms;
@@ -58,6 +60,7 @@
private boolean defaultConnection = false;
private int useAutoCommit = AUTO_COMMIT_SET_TRUE_AND_TEMPORARY_FALSE;
private boolean ignoreAutoCommitExceptions = false;
+ private Boolean nativeLimitOffset;
private PBKey pbKey;
private ConnectionFactoryDescriptor cpd;
private SequenceDescriptor sequenceDescriptor;
@@ -418,6 +421,42 @@
m_batchMode = flag;
}
+ /**
+ * Get the query limit/offset mode. If set <em>true</em> OJB use the native database specific
+ * LIMIT and OFFSET arguments for limit and paging queries (if it's supported by the DB and
+ * OJB's {@link Platform} implementation class). If set <em>false</em> OJB simulate limit
+ * and paging by a specific result set iterator (this can result in bad performance on big
+ * result sets).
+ *
+ * @return The current used limit and paging mode.
+ */
+ public boolean isNativeLimitOffset()
+ {
+ if(nativeLimitOffset == null)
+ {
+ nativeLimitOffset = ConvertHelper.toBoolean(getAttribute(ATTRIBUTE_NATIVE_LIMIT_OFFSET));
+ // by default we support native limit/paging
+ if(nativeLimitOffset == null)
+ {
+ nativeLimitOffset = Boolean.TRUE;
+ }
+ }
+ return nativeLimitOffset.booleanValue();
+ }
+
+ /**
+ * Sets the query limit/paging mode - see {@link #isNativeLimitOffset()}.
+ *
+ * @param nativeLimitOffset The limit paging mode.
+ */
+ public void setNativeLimitOffset(boolean nativeLimitOffset)
+ {
+ this.nativeLimitOffset = nativeLimitOffset ? Boolean.TRUE : Boolean.FALSE;
+ }
+
+ /**
+ * Returns the associated {@link org.apache.ojb.broker.platforms.Platform}.
+ */
public Platform getPlatform()
{
// no need to synchronize, dosen't matter if we use different instances
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/Platform.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/Platform.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/Platform.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/Platform.java Thu Mar 1 17:33:44 2007
@@ -25,6 +25,7 @@
import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.query.LikeCriteria;
+import org.apache.ojb.broker.query.Query;
/**
* This interface provides callbacks that allow to perform
@@ -51,7 +52,7 @@
/**
* Called by {@link org.apache.ojb.broker.accesslayer.StatementManager} implementation
* after invoking <tt>stmt.close()</tt> method.
- * @see #beforeStatementClose(java.sql.Statement, java.sql.ResultSet)
+ * @see #beforeStatementClose(java.sql.Statement, java.sql.ResultSet)
*/
public void afterStatementClose(Statement stmt, ResultSet rs) throws PlatformException;
@@ -161,15 +162,6 @@
String createSequenceQuery(String sequenceName, Properties prop);
/**
- * Returns a query to create a sequence entry.
- *
- * @param sequenceName The name of the sequence to create.
- * @return a sql string to create a sequence
- * @deprecated use {@link #createSequenceQuery(String)} instead.
- */
- String createSequenceQuery(String sequenceName);
-
- /**
* Returns a query to obtain the next sequence key.
* @return a sql string to get next sequence value
*/
@@ -205,33 +197,80 @@
*/
public String getLastInsertIdentityQuery(String tableName);
+
+ //===================================================================
+ // Limit and paging methods
+ //===================================================================
+
/**
- * Answer true if LIMIT or equivalent is supported
- * <b> SQL-Paging is not yet supported </b>
+ * Answer <em>true</em> if LIMIT or equivalent is supported.
*/
- public boolean supportsPaging();
+ boolean supportsLimit();
/**
- * Add the LIMIT or equivalent to the SQL
- * <b> SQL-Paging is not yet supported </b>
+ * Add the LIMIT to the SQL.
*/
- public void addPagingSql(StringBuffer anSqlString);
+ StringBuffer addLimitSql(Query query, StringBuffer anSqlString);
/**
- * Answer true if the LIMIT parameters are bound before the query parameters
- * <b> SQL-Paging is not yet supported </b>
+ * Answer <em>true</em> if LIMIT OFFSET or equivalent is supported.
*/
- public boolean bindPagingParametersFirst();
+ boolean supportsOffset();
/**
- * Bind the Paging Parameters
- * <b> SQL-Paging is not yet supported </b>
- * @param ps
- * @param index parameter index
- * @param startAt
- * @param endAt
+ * Add the LIMIT with LIMIT OFFSET to the SQL.
*/
- public int bindPagingParameters(PreparedStatement ps, int index, int startAt, int endAt) throws SQLException;
+ StringBuffer addPagingSql(Query query, StringBuffer anSqlString);
+
+ /**
+ * Builds the platform dependend LIMIT OFFSET value of the
+ * {@link org.apache.ojb.broker.query.Query#getStartAtIndex()} value
+ * (Note: take care of include/exclude boundary conditions).
+ *
+ * @param query The query.
+ * @return The platform dependend limit offset value.
+ */
+ int buildOffset(Query query);
+
+ /**
+ * Builds the platform dependend LIMIT value of the
+ * {@link org.apache.ojb.broker.query.Query#getEndAtIndex()} value
+ * (Note: take care of include/exclude boundary conditions).
+ *
+ * @param query The query.
+ * @return The platform dependend limit value.
+ */
+ int buildLimit(Query query);
+
+ /**
+ * Returns the order of the LIMIT and OFFSET value setting
+ * in the LIMIT/OFFSET clause (e.g. in "LIMIT ?, ?").
+ * If <em>true</em> the limit argument have to be set before the offset
+ * argument. If <em>false</em> the reverse order is mandatory.
+ *
+ * @return The order of the LIMIT/OFFSET values.
+ */
+ boolean limitBeforeOffset();
+
+ /**
+ * Returns <em>true</em> if the LIMIT/OFFSET clause is added after the
+ * SELECT-expression (e.g. "SELECT TOP n ..."). If <em>false</em> the
+ * LIMIT/OFFSET clause is added after the ORDER BY clause (e.g. "SELECT ... ORDER BY 1 LIMIT n,m").
+ */
+ boolean limitAfterSelect();
+
+ /**
+ * If <em>true</em> the LIMIT/OFFSET values will be embedded in
+ * the limit/paging SQL-query when calling {@link #addLimitSql(org.apache.ojb.broker.query.Query, StringBuffer)}
+ * or {@link #addPagingSql(org.apache.ojb.broker.query.Query, StringBuffer)}. If <em>false</em> prepared statement
+ * paceholder "?" are used in these methods and OJB have bind the values.
+ *
+ * @return Whether or not the LIMIT/OFFSET values will be embedded in the SQL-query.
+ */
+ boolean limitOffsetValuesEmbedded();
+
+ //===================================================================
+
/**
* Whether the platform supports a COUNT DISTINCT across multiple columns.
@@ -308,4 +347,20 @@
* @return The post prepared column value.
*/
public Object postPrepareReadInValue(FieldDescriptor fld, Object value);
+
+ /**
+ * If <em>true</em> auto-generated keys can be retrieved after a statement
+ * has been executed.
+ */
+ boolean supportsGetGeneratedKeys();
+
+ /**
+ * Show same behavior as <em>Statement.getGeneratedKeys()</em> - JDBC quotation:
+ * <br/>
+ * "Retrieves any auto-generated keys created as a result of executing this Statement object.
+ * If this Statement object did not generate any keys, an empty ResultSet object is returned."
+ * @param stmt
+ * @return The generated keys.
+ */
+ ResultSet getGeneratedKeys(Statement stmt) throws SQLException;
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDb2Impl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDb2Impl.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDb2Impl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDb2Impl.java Thu Mar 1 17:33:44 2007
@@ -22,6 +22,7 @@
import org.apache.ojb.broker.util.sequence.SequenceManagerHelper;
import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
+import org.apache.ojb.broker.query.Query;
/**
* This class extends <code>PlatformDefaultImpl</code> and defines specific
@@ -141,11 +142,6 @@
}
}
- public String createSequenceQuery(String sequenceName)
- {
- return "create sequence " + sequenceName;
- }
-
public String createSequenceQuery(String sequenceName, Properties prop)
{
/*
@@ -253,4 +249,76 @@
//
return "select IDENTITY_VAL_LOCAL() from sysibm.sysdummy1";
}
+
+
+
+ public boolean supportsLimit()
+ {
+ return true;
+}
+
+ public StringBuffer addLimitSql(Query query, StringBuffer anSqlString)
+ {
+ /*
+ see http://troels.arvin.dk/db/rdbms/
+ "When doing casual work, it's often easier to use DB2's non-standard
+ SELECT ... FETCH FIRST n ROWS ONLY construct."
+ Seems parameter marker '?' are not allowed.
+ */
+ return anSqlString
+ .append(" FETCH FIRST ")
+ .append(buildLimit(query))
+ .append(" ROWS ONLY");
+ }
+
+ public boolean supportsOffset()
+ {
+ return false;
+ }
+
+ public StringBuffer addPagingSql(Query query, StringBuffer anSqlString)
+ {
+ // TODO: native paging support
+ // not supported
+ throw new UnsupportedOperationException("OFFSET is not supported by this platform" +
+ " implementation class (" + this.getClass().getName() +
+ "), please disable the native limit/offset flag in the" +
+ " connection metadata mapping file using attribute 'nativeLimitOffset'" +
+ " then OJB will use specific paging/limit result set iterator to simulate it!");
+ }
+
+ public int buildLimit(Query query)
+ {
+ int result = 0;
+ if(query.hasLimit())
+ {
+ return query.getEndAtIndex();
+ }
+ else if(query.hasOffset())
+ {
+ return MAX_LIMIT_VALUE;
+ }
+ return result;
+ }
+
+ public int buildOffset(Query query)
+ {
+ return query.getStartAtIndex();
+ }
+
+ public boolean limitOffsetValuesEmbedded()
+ {
+ // parameter marker '?' are not allowed, we embed limit/offset values
+ return true;
+ }
+
+ public boolean limitBeforeOffset()
+ {
+ return false;
+ }
+
+ public boolean limitAfterSelect()
+ {
+ return false;
+ }
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java Thu Mar 1 17:33:44 2007
@@ -36,6 +36,7 @@
import org.apache.ojb.broker.metadata.FieldDescriptor;
import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
import org.apache.ojb.broker.query.LikeCriteria;
+import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.util.SqlHelper;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
@@ -54,9 +55,17 @@
private static final String INITIALIZATION_CHECK_AUTOCOMMIT = "initializationCheck";
private static final String FALSE_STR = "false";
+ /**
+ * Doesn't make sense to use the maximal possible integer as maximal limit value,
+ * thus OJB use '900000000'. Don't use Integer.MAX because not all DB INTEGER
+ * data type support it.
+ */
+ protected static final int MAX_LIMIT_VALUE = 900000000;
+
protected boolean m_batchUpdatesChecked = false;
protected boolean m_supportsBatchUpdates = false;
- protected Boolean locatorsUpdateCopy;
+ private Boolean locatorsUpdateCopy;
+ private Boolean supportsGetGeneratedKeys;
protected JdbcConnectionDescriptor jcd;
public PlatformDefaultImpl(JdbcConnectionDescriptor jcd)
@@ -98,6 +107,40 @@
}
}
+ /**
+ * Sets platform information for if the jdbc driver/db combo support
+ * get auto-generated keys. Will only be checked once.
+ *
+ * @param conn
+ */
+ protected void checkForGetGeneratedKeys(Connection conn)
+ {
+ if(supportsGetGeneratedKeys == null)
+ {
+ try
+ {
+//#ifdef JDBC30
+
+ DatabaseMetaData meta = conn.getMetaData();
+ boolean result = meta.supportsGetGeneratedKeys();
+
+//#else
+
+/*
+ boolean result = false;
+*/
+
+//#endif
+ supportsGetGeneratedKeys = result ? Boolean.TRUE : Boolean.FALSE;
+ }
+ catch(Exception e)
+ {
+ log.warn("Get auto-generated keys support check failed", e);
+ supportsGetGeneratedKeys = Boolean.FALSE;
+ }
+ }
+ }
+
public void afterStatementCreate(Statement stmt) throws PlatformException
{
//noop
@@ -159,6 +202,7 @@
public void initializeJdbcConnection(Connection conn) throws PlatformException
{
if (jcd.getBatchMode()) checkForBatchSupport(conn);
+ checkForGetGeneratedKeys(conn);
switch (jcd.getUseAutoCommit())
{
@@ -446,14 +490,6 @@
public String createSequenceQuery(String sequenceName, Properties prop)
{
- return createSequenceQuery(sequenceName);
- }
-
- /**
- * Override this method to enable database based sequence generation
- */
- public String createSequenceQuery(String sequenceName)
- {
/*default implementation does not support this*/
throw new UnsupportedOperationException("This feature is not supported by this implementation");
}
@@ -489,42 +525,77 @@
throw new UnsupportedOperationException("This feature is not supported by this implementation");
}
- /**
- * @see org.apache.ojb.broker.platforms.Platform#addPagingSql(java.lang.StringBuffer)
- */
- public void addPagingSql(StringBuffer anSqlString)
+
+
+ public boolean supportsLimit()
{
- // do nothing
+ return false;
}
- /**
- * @see org.apache.ojb.broker.platforms.Platform#bindPagingParametersFirst()
- */
- public boolean bindPagingParametersFirst()
+ public StringBuffer addLimitSql(Query query, StringBuffer anSqlString)
+ {
+ // not supported
+ throw new UnsupportedOperationException("LIMIT/OFFSET is not supported by this platform" +
+ " implementation class (" + this.getClass().getName() +
+ "), please disable the native limit/offset flag in the" +
+ " connection metadata mapping file using attribute 'nativeLimitOffset'" +
+ " then OJB will use specific paging/limit result set iterator to simulate it!");
+ }
+
+ public boolean supportsOffset()
{
return false;
}
- /**
- * @see org.apache.ojb.broker.platforms.Platform#supportsPaging()
- */
- public boolean supportsPaging()
+ public StringBuffer addPagingSql(Query query, StringBuffer anSqlString)
+ {
+ // not supported
+ throw new UnsupportedOperationException("LIMIT/OFFSET is not supported by this platform" +
+ " implementation class (" + this.getClass().getName() +
+ "), please disable the native limit/offset flag in the" +
+ " connection metadata mapping file using attribute 'nativeLimitOffset'" +
+ " then OJB will use specific paging/limit result set iterator to simulate it!");
+ }
+
+ public int buildOffset(Query query)
+ {
+ // if start index not set return 0
+ return query.hasOffset() ? query.getStartAtIndex() - 1 : 0;
+ }
+
+ public int buildLimit(Query query)
+ {
+ if(query.hasLimit())
+ {
+ return query.getEndAtIndex() - (query.getStartAtIndex() > 0 ? query.getStartAtIndex() - 1 : 0);
+ } // offset set without limit, we return all rows starting with the offset
+ else if(query.hasOffset())
+ {
+ return MAX_LIMIT_VALUE;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ public boolean limitBeforeOffset()
{
return false;
}
- /**
- * @see org.apache.ojb.broker.platforms.Platform#bindPagingParameters(java.sql.PreparedStatement, int, int, int)
- */
- public int bindPagingParameters(PreparedStatement ps, int index, int startAt, int endAt) throws SQLException
+ public boolean limitAfterSelect()
{
- ps.setInt(index, startAt - 1); // zero based start
- index++;
- ps.setInt(index, endAt - (startAt - 1)); // number of rows to fetch
- index++;
- return index;
+ return false;
}
+ public boolean limitOffsetValuesEmbedded()
+ {
+ return false;
+ }
+
+
+
/**
* Answer the Character for Concatenation
*/
@@ -691,5 +762,39 @@
public Object postPrepareReadInValue(final FieldDescriptor fld, final Object value)
{
return value;
+ }
+
+ public boolean supportsGetGeneratedKeys()
+ {
+ return supportsGetGeneratedKeys != null && supportsGetGeneratedKeys.booleanValue();
+ }
+
+ public ResultSet getGeneratedKeys(Statement stmt) throws SQLException
+ {
+
+//#ifdef JDBC30
+
+ return stmt.getGeneratedKeys();
+
+//#else
+
+/*
+ // not supported
+ throw new UnsupportedOperationException("Not supported in used JDBC-specification version");
+*/
+
+//#endif
+
+ }
+
+ /**
+ * Build the default query to create a database sequence.
+ *
+ * @param sequenceName The name of the sequence.
+ * @return The create-sequence query.
+ */
+ protected String createSequenceQuery(String sequenceName)
+ {
+ return "create sequence " + sequenceName;
}
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformFirebirdImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformFirebirdImpl.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformFirebirdImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformFirebirdImpl.java Thu Mar 1 17:33:44 2007
@@ -1,5 +1,7 @@
package org.apache.ojb.broker.platforms;
+import java.util.Properties;
+
import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
/* Copyright 2003-2004 The Apache Software Foundation
@@ -33,7 +35,7 @@
super(jcd);
}
- public String createSequenceQuery(String sequenceName)
+ public String createSequenceQuery(String sequenceName, Properties prop)
{
return "create generator " + sequenceName;
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformHsqldbImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformHsqldbImpl.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformHsqldbImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformHsqldbImpl.java Thu Mar 1 17:33:44 2007
@@ -19,6 +19,7 @@
import org.apache.ojb.broker.util.sequence.SequenceManagerHelper;
import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
+import org.apache.ojb.broker.query.Query;
/**
* This class extends <code>PlatformDefaultImpl</code> and defines specific
@@ -88,26 +89,29 @@
return LAST_INSERT;
}
- /**
- * @see org.apache.ojb.broker.platforms.Platform#addPagingSql(java.lang.StringBuffer)
- */
- public void addPagingSql(StringBuffer anSqlString)
+
+
+ public boolean supportsLimit()
{
- anSqlString.insert(6, " LIMIT ? ? ");
+ return true;
}
- /**
- * @see org.apache.ojb.broker.platforms.Platform#bindPagingParametersFirst()
- */
- public boolean bindPagingParametersFirst()
+ public StringBuffer addLimitSql(Query query, StringBuffer anSqlString)
+ {
+ return anSqlString.append(" LIMIT ?");
+ }
+
+ public boolean supportsOffset()
{
return true;
}
- /**
- * @see org.apache.ojb.broker.platforms.Platform#supportsPaging()
- */
- public boolean supportsPaging()
+ public StringBuffer addPagingSql(Query query, StringBuffer anSqlString)
+ {
+ return anSqlString.append(" LIMIT ? OFFSET ?");
+ }
+
+ public boolean limitBeforeOffset()
{
return true;
}
@@ -117,6 +121,8 @@
return false;
}
+
+
public String createSequenceQuery(String sequenceName, Properties prop)
{
// CREATE SEQUENCE <sequencename> [AS {INTEGER | BIGINT}]
@@ -146,14 +152,6 @@
}
}
return query.toString();
- }
-
- /**
- * @see org.apache.ojb.broker.platforms.Platform#createSequenceQuery(java.lang.String)
- */
- public String createSequenceQuery(String sequenceName)
- {
- return "CREATE SEQUENCE " + sequenceName;
}
/**
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMckoiImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMckoiImpl.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMckoiImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMckoiImpl.java Thu Mar 1 17:33:44 2007
@@ -22,6 +22,7 @@
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
+import java.util.Properties;
import org.apache.ojb.broker.query.LikeCriteria;
import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
@@ -92,7 +93,7 @@
/* (non-Javadoc)
* @see org.apache.ojb.broker.platforms.Platform#createSequenceQuery(String)
*/
- public String createSequenceQuery(String sequenceName)
+ public String createSequenceQuery(String sequenceName, Properties prop)
{
return "create sequence " + sequenceName;
}
Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMsSQLServerImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMsSQLServerImpl.java?view=diff&rev=513577&r1=513576&r2=513577
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMsSQLServerImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMsSQLServerImpl.java Thu Mar 1 17:33:44 2007
@@ -21,6 +21,8 @@
import java.sql.SQLException;
import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
+import org.apache.ojb.broker.query.Query;
+import org.apache.commons.lang.StringUtils;
/**
* This class extends <code>PlatformDefaultImpl</code> and defines specific behavior for the
@@ -93,5 +95,71 @@
protected String getQuotedName(String aString)
{
return '[' + aString + ']';
+ }
+
+
+
+ public boolean supportsLimit()
+ {
+ return true;
+ }
+
+ public StringBuffer addLimitSql(Query query, StringBuffer anSqlString)
+ {
+ /*
+ See http://troels.arvin.dk/db/rdbms/#select-top-n-standard
+ SELECT TOP 3 WITH TIES * FROM person ORDER BY age ASC
+ */
+ return new StringBuffer(StringUtils.replace(anSqlString.toString(), "SELECT", "SELECT TOP ?", 1));
+ }
+
+ public boolean supportsOffset()
+ {
+ return true;
+ }
+
+ public StringBuffer addPagingSql(Query query, StringBuffer anSqlString)
+ {
+ /*
+ See http://troels.arvin.dk/db/rdbms/#select-top-n-standard
+ SELECT * FROM (
+ SELECT TOP n * FROM (
+ SELECT TOP z columns -- (z=n+skip)
+ FROM tablename ORDER BY key ASC)
+ AS FOO ORDER BY key DESC -- ('FOO' may be anything)
+ ) AS BAR ORDER BY key ASC -- ('BAR' may be anything)
+ */
+ StringBuffer tmp = new StringBuffer(StringUtils.replace(
+ anSqlString.toString(), "SELECT", "SELECT * FROM ( SELECT TOP ? * FROM ( SELECT TOP ?", 1));
+ return tmp.append(") AS FOO ORDER BY key DESC ) AS BAR ORDER BY key ASC");
+ }
+
+ public int buildLimit(Query query)
+ {
+ int result = 0;
+ if(query.hasLimit())
+ {
+ return query.getEndAtIndex();
+ }
+ else if(query.hasOffset())
+ {
+ return MAX_LIMIT_VALUE;
+ }
+ return result;
+ }
+
+ public int buildOffset(Query query)
+ {
+ return super.buildOffset(query);
+ }
+
+ public boolean limitBeforeOffset()
+ {
+ return false;
+ }
+
+ public boolean limitAfterSelect()
+ {
+ return true;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org