You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@empire-db.apache.org by do...@apache.org on 2016/02/24 18:20:12 UTC
empire-db git commit: EMPIREDB-238 allow overrides in DBReader
Repository: empire-db
Updated Branches:
refs/heads/master 9fd060de8 -> a09f6084a
EMPIREDB-238
allow overrides in DBReader
Project: http://git-wip-us.apache.org/repos/asf/empire-db/repo
Commit: http://git-wip-us.apache.org/repos/asf/empire-db/commit/a09f6084
Tree: http://git-wip-us.apache.org/repos/asf/empire-db/tree/a09f6084
Diff: http://git-wip-us.apache.org/repos/asf/empire-db/diff/a09f6084
Branch: refs/heads/master
Commit: a09f6084a7716dbf21c6000bd9127583676f9ffd
Parents: 9fd060d
Author: Rainer Döbele <do...@esteam.de>
Authored: Wed Feb 24 18:20:07 2016 +0100
Committer: Rainer Döbele <do...@esteam.de>
Committed: Wed Feb 24 18:20:07 2016 +0100
----------------------------------------------------------------------
.../java/org/apache/empire/db/DBReader.java | 156 +++++++++++++++----
1 file changed, 127 insertions(+), 29 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/empire-db/blob/a09f6084/empire-db/src/main/java/org/apache/empire/db/DBReader.java
----------------------------------------------------------------------
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBReader.java b/empire-db/src/main/java/org/apache/empire/db/DBReader.java
index 6037639..10c80a3 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBReader.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBReader.java
@@ -18,9 +18,6 @@
*/
package org.apache.empire.db;
-import java.io.IOException;
-import java.io.NotSerializableException;
-import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
@@ -30,6 +27,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.ConstructorUtils;
@@ -38,8 +36,11 @@ import org.apache.empire.data.ColumnExpr;
import org.apache.empire.data.DataType;
import org.apache.empire.db.exceptions.EmpireSQLException;
import org.apache.empire.db.exceptions.QueryNoResultException;
+import org.apache.empire.db.expr.join.DBJoinExpr;
import org.apache.empire.exceptions.BeanInstantiationException;
import org.apache.empire.exceptions.InvalidArgumentException;
+import org.apache.empire.exceptions.MiscellaneousErrorException;
+import org.apache.empire.exceptions.NotSupportedException;
import org.apache.empire.exceptions.ObjectNotValidException;
import org.apache.empire.xml.XMLUtil;
import org.slf4j.Logger;
@@ -90,6 +91,7 @@ public class DBReader extends DBRecordData
/**
* Implements the Iterator Interface Method remove not implemented and not applicable.
*/
+ @Override
public void remove()
{
log.error("DBReader.remove ist not implemented!");
@@ -120,6 +122,7 @@ public class DBReader extends DBRecordData
*
* @return true if there is another record to read
*/
+ @Override
public boolean hasNext()
{
try
@@ -142,6 +145,7 @@ public class DBReader extends DBRecordData
*
* @return the current Record interface
*/
+ @Override
public DBRecordData next()
{
if ((curCount < maxCount && moveNext()))
@@ -183,6 +187,7 @@ public class DBReader extends DBRecordData
*
* @return true if there is another record to read
*/
+ @Override
public boolean hasNext()
{
// Check position
@@ -204,6 +209,7 @@ public class DBReader extends DBRecordData
*
* @return the current Record interface
*/
+ @Override
public DBRecordData next()
{
if (hasCurrent == false)
@@ -223,7 +229,9 @@ public class DBReader extends DBRecordData
}
// Logger
- protected static final Logger log = LoggerFactory.getLogger(DBReader.class);
+ protected static final Logger log = LoggerFactory.getLogger(DBReader.class);
+
+ private static boolean trackOpenResultSets = false;
/**
* Support for finding code errors where a DBRecordSet is opened but not closed
@@ -231,11 +239,11 @@ public class DBReader extends DBRecordData
private static ThreadLocal<Map<DBReader, Exception>> threadLocalOpenResultSets = new ThreadLocal<Map<DBReader, Exception>>();
// Object references
- private DBDatabase db = null;
- private DBColumnExpr[] colList = null;
+ protected DBDatabase db = null;
+ protected DBColumnExpr[] colList = null;
// Direct column access
- protected ResultSet rset = null;
+ protected ResultSet rset = null;
/**
* Constructs an empty DBRecordSet object.
@@ -405,16 +413,27 @@ public class DBReader extends DBRecordData
{
if (isOpen())
close();
- // SQL Command
+ // Get the query statement
String sqlCmd = cmd.getSelect();
- // Create Statement
+ // Collect the query parameters
+ Object[] paramValues = cmd.getParamValues();
+ List<Object[]> subqueryParamValues = (cmd instanceof DBCommand) ? findSubQueryParams((DBCommand)cmd) : null;
+ if (subqueryParamValues!=null && !subqueryParamValues.isEmpty())
+ { // Check Count
+ if (paramValues!=null || subqueryParamValues.size()>1)
+ throw new MiscellaneousErrorException("More than one (sub)query is a parameterized query. Currently one one query is allowed to be parameterized!");
+ // Use subquery params
+ paramValues = subqueryParamValues.get(0);
+ }
+ // Execute the query
db = cmd.getDatabase();
- rset = db.executeQuery(sqlCmd, cmd.getParamValues(), scrollable, conn);
+ rset = db.executeQuery(sqlCmd, paramValues, scrollable, conn);
if (rset==null)
throw new QueryNoResultException(sqlCmd);
// successfully opened
colList = cmd.getSelectExprList();
- addOpenResultSet();
+ // add to tracking list (if enabled)
+ trackThisResultSet();
}
/**
@@ -471,7 +490,8 @@ public class DBReader extends DBRecordData
if (rset != null)
{
getDatabase().closeResultSet(rset);
- removeOpenResultSet();
+ // remove from tracking-list
+ endTrackingThisResultSet();
}
// Detach columns
colList = null;
@@ -633,11 +653,11 @@ public class DBReader extends DBRecordData
try
{
// Check whether we can use a constructor
- Class[] paramTypes = new Class[getFieldCount()];
+ Class<T>[] paramTypes = new Class[getFieldCount()];
for (int i = 0; i < colList.length; i++)
paramTypes[i] = DBExpr.getValueClass(colList[i].getDataType());
// Find Constructor
- Constructor ctor = findMatchingAccessibleConstructor(t, paramTypes);
+ Constructor<?> ctor = findMatchingAccessibleConstructor(t, paramTypes);
Object[] args = (ctor!=null) ? new Object[getFieldCount()] : null;
// Create a list of beans
@@ -803,12 +823,74 @@ public class DBReader extends DBRecordData
}
/**
+ * internal helper function to find parameterized subqueries
+ * @param cmd the command
+ * @return a list of parameter arrays, one for each subquery
+ */
+ protected List<Object[]> findSubQueryParams(DBCommand cmd)
+ {
+ List<Object[]> subQueryParams = null;
+ List<DBJoinExpr> joins = cmd.getJoins();
+ if (joins==null)
+ return null; // no joins
+ // check the joins
+ for (DBJoinExpr j : joins)
+ {
+ DBRowSet rsl = j.getLeft().getUpdateColumn().getRowSet();
+ DBRowSet rsr = j.getRight().getUpdateColumn().getRowSet();
+ if (rsl instanceof DBQuery)
+ { // the left join is a query
+ subQueryParams = addSubQueryParams((DBQuery)rsl, subQueryParams);
+ }
+ if (rsr instanceof DBQuery)
+ { // the right join is a query
+ subQueryParams = addSubQueryParams((DBQuery)rsr, subQueryParams);
+ }
+ }
+ return subQueryParams;
+ }
+
+ /**
+ * Adds any subquery params to the supplied list
+ * @param query the subquery
+ * @param list the current list of parameters
+ * @return the new list of parameters
+ */
+ private List<Object[]> addSubQueryParams(DBQuery query, List<Object[]> list)
+ {
+ DBCommandExpr sqcmd = query.getCommandExpr();
+ Object[] params = query.getCommandExpr().getParamValues();
+ if (params!=null && params.length>0)
+ { // add params
+ if (list== null)
+ list = new ArrayList<Object[]>();
+ list.add(params);
+ }
+ // recurse
+ if (sqcmd instanceof DBCommand)
+ { // check this command too
+ List<Object[]> sqlist = findSubQueryParams((DBCommand)sqcmd);
+ if (sqlist!=null && !sqlist.isEmpty())
+ { // make one list
+ if (list!= null)
+ list.addAll(sqlist);
+ else
+ list = sqlist;
+ }
+ }
+ return list;
+ }
+
+ /**
* Support for finding code errors where a DBRecordSet is opened but not closed.
*
* @author bond
*/
- private synchronized void addOpenResultSet()
+ protected synchronized void trackThisResultSet()
{
+ // check if enabled
+ if (trackOpenResultSets==false)
+ return;
// add this to the vector of open resultsets on this thread
Map<DBReader, Exception> openResultSets = threadLocalOpenResultSets.get();
if (openResultSets == null)
@@ -821,10 +903,7 @@ public class DBReader extends DBRecordData
Exception stackException = openResultSets.get(this);
if (stackException != null)
{
- log
- .error(
- "DBRecordSet.addOpenResultSet called for an object which is already in the open list. This is the stack of the method opening the object which was not previously closed.",
- stackException);
+ log.error("DBRecordSet.addOpenResultSet called for an object which is already in the open list. This is the stack of the method opening the object which was not previously closed.", stackException);
// the code continues and overwrites the logged object with the new one
}
// get the current stack trace
@@ -836,15 +915,16 @@ public class DBReader extends DBRecordData
*
* @author bond
*/
- private synchronized void removeOpenResultSet()
+ protected synchronized void endTrackingThisResultSet()
{
+ // check if enabled
+ if (trackOpenResultSets==false)
+ return;
+ // remove
Map<DBReader, Exception> openResultSets = threadLocalOpenResultSets.get();
if (openResultSets.containsKey(this) == false)
{
- log
- .error(
- "DBRecordSet.removeOpenResultSet called for an object which is not in the open list. Here is the current stack.",
- new Exception());
+ log.error("DBRecordSet.removeOpenResultSet called for an object which is not in the open list. Here is the current stack.", new Exception());
}
else
{
@@ -852,17 +932,18 @@ public class DBReader extends DBRecordData
}
}
+ /*
private void writeObject(ObjectOutputStream stream) throws IOException {
if (rset != null) {
throw new NotSerializableException(DBReader.class.getName() + " (due to attached ResultSet)");
}
}
+ */
/**
* copied from org.apache.commons.beanutils.ConstructorUtils since it's private there
*/
- @SuppressWarnings("unchecked")
- private static Constructor findMatchingAccessibleConstructor(Class clazz, Class[] parameterTypes)
+ protected static Constructor<?> findMatchingAccessibleConstructor(Class<?> clazz, Class<?>[] parameterTypes)
{
// See if we can find the method directly
// probably faster if it works
@@ -878,10 +959,10 @@ public class DBReader extends DBRecordData
// search through all constructors
int paramSize = parameterTypes.length;
- Constructor[] ctors = clazz.getConstructors();
+ Constructor<?>[] ctors = clazz.getConstructors();
for (int i = 0, size = ctors.length; i < size; i++)
{ // compare parameters
- Class[] ctorParams = ctors[i].getParameterTypes();
+ Class<?>[] ctorParams = ctors[i].getParameterTypes();
int ctorParamSize = ctorParams.length;
if (ctorParamSize == paramSize)
{ // Param Size matches
@@ -896,7 +977,7 @@ public class DBReader extends DBRecordData
}
if (match) {
// get accessible version of method
- Constructor ctor = ConstructorUtils.getAccessibleConstructor(ctors[i]);
+ Constructor<?> ctor = ConstructorUtils.getAccessibleConstructor(ctors[i]);
if (ctor != null) {
try {
ctor.setAccessible(true);
@@ -908,6 +989,18 @@ public class DBReader extends DBRecordData
}
return null;
}
+
+ /**
+ * Enables or disabled tracking of open ResultSets
+ * @param enable true to enable or false otherwise
+ * @return the previous state of the trackOpenResultSets
+ */
+ public static synchronized boolean enableOpenResultSetTracking(boolean enable)
+ {
+ boolean prev = trackOpenResultSets;
+ trackOpenResultSets = enable;
+ return prev;
+ }
/**
* <PRE>
@@ -918,6 +1011,10 @@ public class DBReader extends DBRecordData
*/
public static synchronized void checkOpenResultSets()
{
+ // check if enabled
+ if (trackOpenResultSets==false)
+ throw new MiscellaneousErrorException("Open-ResultSet-Tracking has not been enabled. Use DBReader.enableOpenResultSetTracking() to enable or disable.");
+ // Check map
Map<DBReader, Exception> openResultSets = threadLocalOpenResultSets.get();
if (openResultSets != null && openResultSets.isEmpty() == false)
{
@@ -931,4 +1028,5 @@ public class DBReader extends DBRecordData
openResultSets.clear();
}
}
+
}
\ No newline at end of file