/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.empire.db;

import java.io.Closeable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.empire.commons.ClassUtils;
import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.data.Column;
import org.apache.empire.data.ColumnExpr;
import org.apache.empire.data.DataType;
import org.apache.empire.data.EntityType;
import org.apache.empire.db.exceptions.EmpireSQLException;
import org.apache.empire.db.exceptions.NoPrimaryKeyException;
import org.apache.empire.db.exceptions.QueryNoResultException;
import org.apache.empire.db.list.DataBean;
import org.apache.empire.exceptions.BeanInstantiationException;
import org.apache.empire.exceptions.InvalidArgumentException;
import org.apache.empire.exceptions.ObjectNotValidException;
import org.apache.empire.exceptions.UnspecifiedErrorException;
import org.apache.empire.xml.XMLUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;


/**
 * <P>
 * This class is used to perform database queries from a DBCommand object and access the results.<BR>
 * In oder to perform a query call the open() function or - for single row queries - call getRecordData();<BR>
 * You can iterate through the rows using moveNext() or an iterator.<BR>
 * <P>
 * However take care: A reader must always be explicitly closed using the close() method!<BR>
 * Otherwise you may lock the JDBC connection and run out of resources.<BR>
 * Use <PRE>try { ... } finally { reader.close(); } </PRE> to make sure the reader is closed.<BR>
 * <P>
 * To access and work with the query result you can do one of the following:<BR>
 * <ul>
 *  <li>access field values directly by using one of the get... functions (see {@link DBRecordData})</li> 
 *  <li>get the rows as a list of Java Beans using by using {@link DBReader#getBeanList(Class, int)}</li> 
 *  <li>get the rows as an XML-Document using {@link DBReader#getXmlDocument()} </li> 
 *  <li>initialize a DBRecord with the current row data using {@link DBReader#initRecord(DBRowSet, DBRecordBase)}<br>
 *      This will allow you to modify and update the data. 
 *  </li> 
 * </ul>
 *
 *
 */
public class DBReader extends DBRecordData implements Closeable
{
    // *Deprecated* private static final long serialVersionUID = 1L;
  
    /**
     * DBReaderIterator
     * Base class for DBReader interators
     * @author rainer
     */
    public abstract class DBReaderIterator implements Iterator<DBRecordData>
    {
        protected int curCount = 0;
        protected int maxCount = 0;

        public DBReaderIterator(int maxCount)
        {
            if (maxCount < 0)
                maxCount = 0x7FFFFFFF; // Highest positive number
            // Set Maxcount
            this.maxCount = maxCount;
        }

        /**
         * Implements the Iterator Interface Method remove not implemented and not applicable.
         */
        @Override
        public void remove()
        {
            log.error("DBReader.remove ist not implemented!");
        }

        /**
         * Disposes the iterator.
         */
        public void dispose()
        {
            curCount = maxCount = -1;
        }
    }

    /**
     * This is an iterator for scrolling resultsets.
     * This iterator has no such limitations as the forward iterator.
     */
    public class DBReaderScrollableIterator extends DBReaderIterator
    {
        public DBReaderScrollableIterator(int maxCount)
        {
            super(maxCount);
        }

        /**
         * Implements the Iterator Interface.
         * 
         * @return true if there is another record to read
         */
        @Override
        public boolean hasNext()
        {
            try
            {   // Check position
                if (curCount >= maxCount)
                    return false;
                // Check Recordset
                if (rset == null || rset.isLast() || rset.isAfterLast())
                    return false;
                // there are more records
                return true;
            } catch (SQLException e) {
                // Error
                throw new EmpireSQLException(context.getDbms(), e);
            }
        }

        /**
         * Implements the Iterator Interface.
         * 
         * @return the current Record interface
         */
        @Override
        public DBRecordData next()
        {
            if ((curCount < maxCount && moveNext()))
            {
                curCount++;
                return DBReader.this;
            }
            // Past the end!
            return null;
        }
    }

    /**
     * This is an iterator for forward only resultsets.
     * There is an important limitation on this iterator: After calling
     * hasNext() the caller may not use any functions on the current item any more. i.e.
     * Example:
     *  while (i.hasNext())
     *  {
     *      DBRecordData r = i.next(); 
     *      Object o  = r.getValue(0);  // ok
     *      
     *      bool last = i.hasNext();    // ok
     *      Object o  = r.getValue(0);  // Illegal call!
     *  }
     */
    public class DBReaderForwardIterator extends DBReaderIterator
    {
        private boolean getCurrent = true;
        private boolean hasCurrent = false;

        public DBReaderForwardIterator(int maxCount)
        {
            super(maxCount);
        }

        /**
         * Implements the Iterator Interface.
         * 
         * @return true if there is another record to read
         */
        @Override
        public boolean hasNext()
        {
            // Check position
            if (curCount >= maxCount)
                return false;
            if (rset == null)
                throw new ObjectNotValidException(this);
            // Check next Record
            if (getCurrent == true)
            {
                getCurrent = false;
                hasCurrent = moveNext();
            }
            return hasCurrent;
        }

        /**
         * Implements the Iterator Interface.
         * 
         * @return the current Record interface
         */
        @Override
        public DBRecordData next()
        {
            if (hasCurrent == false)
                return null; // Past the end!
            // next called without call to hasNext ?
            if (getCurrent && !moveNext())
            { // No more records
                hasCurrent = false;
                getCurrent = false;
                return null;
            }
            // Move forward
            curCount++;
            getCurrent = true;
            return DBReader.this;
        }
    }

    // Logger
    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
     */
    private static ThreadLocal<Map<DBReader, Exception>> threadLocalOpenResultSets = new ThreadLocal<Map<DBReader, Exception>>();

    // the context
    protected final DBContext context;
    
    // Object references
    private DBDatabase     db      = null;
    private DBColumnExpr[] columns = null;
    private ResultSet      rset    = null;
    // the field index map
    private Map<ColumnExpr, Integer> fieldIndexMap = null;

    /**
     * Constructs an empty DBRecordSet object.
     * @param useFieldIndexMap 
     */
    public DBReader(DBContext context, boolean useFieldIndexMap)
    {
        this.context = context;
        if (useFieldIndexMap)
            fieldIndexMap = new HashMap<ColumnExpr, Integer>();
    }

    /**
     * Constructs a default DBReader object with the fieldIndexMap enabled.
     */
    public DBReader(DBContext context)
    {
        // Simple Constructor
        this(context, true);
    }

    /**
     * Returns the current Context
     * @return
     */
    @Override
    public DBContext getContext()
    {
        return context;
    }

    /**
     * Returns the current DBDatabase object.
     * 
     * @return the current DBDatabase object
     */
    
    @SuppressWarnings("unchecked")
    @Override
    public final DBDatabase getDatabase()
    {
        return db;
    }
    
    public boolean getScrollable()
    {
        try
        {
            // Check Resultset
            return (rset!=null && rset.getType()!=ResultSet.TYPE_FORWARD_ONLY); 
        } catch (SQLException e)
        {
            log.error("Cannot determine Resultset type", e);
            return false;
        }
    }

    /**
     * Returns the index value by a specified DBColumnExpr object.
     * 
     * @return the index value
     */
    @Override
    public int getFieldIndex(ColumnExpr column) 
    {
        if (fieldIndexMap==null)
            return findFieldIndex(column);
        // Use fieldIndexMap
        Integer index = fieldIndexMap.get(column);
        if (index==null)
        {   // add to field Index map
            index = findFieldIndex(column);
            fieldIndexMap.put(column, index);
        }
        return index;
    }
    
    /** Get the column Expression at position */
    @Override
    public DBColumnExpr getColumn(int iColumn)
    {
        if (columns == null || iColumn < 0 || iColumn >= columns.length)
            return null; // Index out of range
        // return column Expression
        return columns[iColumn];
    }

    /**
     * Returns the index value by a specified column name.
     * 
     * @param column the column name
     * @return the index value
     */
    @Override
    public int getFieldIndex(String column)
    {
        if (columns != null)
        {
            for (int i = 0; i < columns.length; i++)
                if (columns[i].getName().equalsIgnoreCase(column))
                    return i;
        }
        // not found
        return -1;
    }

    /**
     * Checks wehter a column value is null Unlike the base
     * class implementation, this class directly check the value fromt the
     * resultset.
     * 
     * @param index index of the column
     * @return true if the value is null or false otherwise
     */
    @Override
    public boolean isNull(int index)
    {
        if (index < 0 || index >= columns.length)
        { // Index out of range
            log.error("Index out of range: " + index);
            return true;
        }
        try
        { // Check Value on Resultset
            rset.getObject(index + 1);
            return rset.wasNull();
        } catch (Exception e)
        {
            log.error("isNullValue exception", e);
            return super.isNull(index);
        }
    }

    /**
     * Returns a data value identified by the column index.
     * 
     * @param index index of the column
     * @return the value
     */
    @Override
    public Object getValue(int index)
    {
        // Check params
        if (index < 0 || index >= columns.length)
            throw new InvalidArgumentException("index", index);
        try
        {   // Get Value from Resultset
            DataType dataType = columns[index].getDataType();
            return context.getDbms().getResultValue(rset, index + 1, dataType);

        } catch (SQLException e)
        { // Operation failed
            throw new EmpireSQLException(context.getDbms(), e);
        }
    }
    
    /**
     * Returns the record key for a type of entity
     * @param entityType the entity type or rowset for which to get key
     * @return the record key
     */
    public Object[] getRecordKey(EntityType entityType)
    {
        Column[] keyColumns = entityType.getKeyColumns();
        if (keyColumns==null || keyColumns.length==0)
            throw new NoPrimaryKeyException(entityType);
        // Collect key
        Object[] key = new Object[keyColumns.length];
        for (int i=0; i<key.length; i++)
            key[i] = this.get(keyColumns[i]);
        return key;
    }

    /**
     * Returns the record id for a type of entity which has a single numeric primary key
     * @param entityType the entity type or rowset for which to get key
     * @return the record id
     * @throws InvalidArgumentException if the entity has not a single numeric primary key
     */
    public long getRecordId(EntityType entityType)
    {
        Column[] keyColumns = entityType.getKeyColumns();
        if (keyColumns==null || keyColumns.length!=1)
            throw new InvalidArgumentException("entityType", entityType.getEntityName());
        // return id
        return this.getLong(keyColumns[0]);
    }

    /** 
     * Checks if the rowset is open
     *  
     * @return true if the rowset is open
     */
    public boolean isOpen()
    {
        return (rset != null);
    }
    
    /**
     * Opens the reader by executing the given SQL command.<BR>
     * After the reader is open, the reader's position is before the first record.<BR>
     * Use moveNext or iterator() to step through the rows.<BR>
     * Data of the current row can be accessed through the functions on the RecordData interface.<BR>
     * <P>
     * ATTENTION: After using the reader it must be closed using the close() method!<BR>
     * Use <PRE>try { ... } finally { reader.close(); } </PRE> to make sure the reader is closed.<BR>
     * <P>
     * @param cmd the SQL-Command with cmd.getSelect()
     * @param scrollable true if the reader should be scrollable or false if not
     * @param conn a valid JDBC connection.
     */
    public void open(DBCommandExpr cmd, boolean scrollable)
    {
        if (isOpen())
            close();
        // Get the query statement
        String sqlCmd = cmd.getSelect();
        Object[] paramValues = cmd.getParamValues();
        // Collect the query parameters
        /*
        List<Object> subqueryParamValues = (cmd instanceof DBCommand) ? findSubQueryParams((DBCommand)cmd) : null;
        if (subqueryParamValues!=null && !subqueryParamValues.isEmpty())
        {   // Check Count
            if (paramValues==null)
            {   // use subquery params
                paramValues = subqueryParamValues.toArray();
            }
            else if (paramValues.length!=subqueryParamValues.size())
            {   // number of params do not match
                String msg = MessageFormat.format("Invalid number of parameters query: provided={0}, required={1}; query="+cmd.getSelect(), paramValues.length, subqueryParamValues.size());
                throw new UnspecifiedErrorException(msg);
            }
        }
        */
        // Execute the query
        DBUtils utils = context.getUtils();
        ResultSet queryRset = utils.executeQuery(sqlCmd, paramValues, scrollable);
        if (queryRset==null)
            throw new QueryNoResultException(sqlCmd);
        // init
        init(cmd.getDatabase(), cmd.getSelectExprList(), queryRset);
    }

    /**
     * Opens the reader by executing the given SQL command.<BR>
     * <P>
     * see {@link DBReader#open(DBCommandExpr, boolean, Connection)}
     * </P>
     * @param cmd the SQL-Command with cmd.getSelect()
     * @param conn a valid JDBC connection.
     */
    public final void open(DBCommandExpr cmd)
    {
        open(cmd, false);
    }

    /**
     * <P>
     * Opens the reader by executing the given SQL command and moves to the first row.<BR>
     * If true is returned data of the row can be accessed through the functions on the RecordData interface.<BR>
     * This function is intended for single row queries and provided for convenience.<BR>
     * However it behaves exacly as calling reader.open() and reader.moveNext()<BR>
     * <P>
     * ATTENTION: After using the reader it must be closed using the close() method!<BR>
     * Use <PRE>try { ... } finally { reader.close(); } </PRE> to make sure the reader is closed.<BR>
     * <P>
     * @param cmd the SQL-Command with cmd.getSelect()
     * @param conn a valid JDBC connection.
     */
    public void getRecordData(DBCommandExpr cmd)
    { // Open the record
        open(cmd);
        // Get First Record
        if (!moveNext())
        { // Close
            throw new QueryNoResultException(cmd.getSelect());
        }
    }

    /**
     * Closes the DBRecordSet object, the Statement object and detach the columns.<BR>
     * A reader must always be closed immediately after using it.
     */
    @Override
    public void close()
    {
        try
        { // Dispose iterator
            if (iterator != null)
            {   iterator.dispose();
                iterator = null;
            }
            // Close JDBC-Resultset
            if (rset != null)
            {   // call dbms
                context.getDbms().closeResultSet(rset);
                // remove from tracking-list
                endTrackingThisResultSet();
            }
            // Detach columns
            columns = null;
            rset = null;
            // clear FieldIndexMap
            if (fieldIndexMap!=null)
                fieldIndexMap.clear();
            // Done
        } catch (Exception e)
        { // What's wrong here?
            log.warn(e.toString());
        }
    }

    /**
     * Moves the cursor down the given number of rows.
     * 
     * @param count the number of rows to skip 
     * 
     * @return true if the reader is on a valid record or false otherwise
     */
    public boolean skipRows(int count)
    {
        try
        {   // Check Recordset
            if (rset == null)
                throw new ObjectNotValidException(this);
            // Forward only cursor?
            int type = rset.getType();
            if (type == ResultSet.TYPE_FORWARD_ONLY)
            {
                if (count < 0)
                    throw new InvalidArgumentException("count", count);
                // Move
                for (; count > 0; count--)
                {
                    if (!moveNext())
                        return false;
                }
                return true;
            }
            // Scrollable Cursor
            if (count > 0)
            { // Move a single record first
                if (rset.next() == false)
                    return false;
                // Move relative
                if (count > 1)
                    return rset.relative(count - 1);
            } 
            else if (count < 0)
            { // Move a single record first
                if (rset.previous() == false)
                    return false;
                // Move relative
                if (count < -1)
                    return rset.relative(count + 1);
            }
            return true;

        } catch (SQLException e) {
            // an error occurred
            throw new EmpireSQLException(context.getDbms(), e);
        }
    }

    /**
     * Moves the cursor down one row from its current position.
     * 
     * @return true if the reader is on a valid record or false otherwise
     */
    public boolean moveNext()
    {
        try
        {   // Check Recordset
            if (rset == null)
                throw new ObjectNotValidException(this);
            // Move Next
            if (rset.next() == false)
            { // Close recordset automatically after last record
                close();
                return false;
            }
            return true;

        } catch (SQLException e) {
            // an error occurred
            throw new EmpireSQLException(context.getDbms(), e);
        }
    }

    private DBReaderIterator iterator = null; // there can only be one!

    /**
     * Returns an row iterator for this reader.<BR>
     * There can only be one iterator at a time.
     * <P>
     * @param maxCount the maximum number of item that should be returned by this iterator
     * @return the row iterator
     */
    public Iterator<DBRecordData> iterator(int maxCount)
    {
        if (iterator == null && rset != null)
        {
            if (getScrollable())
                iterator = new DBReaderScrollableIterator(maxCount);
            else
                iterator = new DBReaderForwardIterator(maxCount);
        }
        return iterator;
    }

    /**
     * <PRE>
     * Returns an row iterator for this reader.
     * There can only be one iterator at a time.
     * </PRE>
     * @return the row iterator
     */
    public final Iterator<DBRecordData> iterator()
    {
        return iterator(-1);
    }

    /**
     * <PRE>
     * initializes a DBRecord object with the values of the current row.
     * At least all primary key columns of the target rowset must be provided by this reader.
     * This function is equivalent to calling rowset.initRecord(rec, reader) 
     * set also {@link DBRowSet#initRecord(DBRecordBase, DBRecordData)});
     * </PRE>
     * @param rowset the rowset to which to attach
     * @param rec the record which to initialize
     */
    public void initRecord(DBRecordBase rec)
    {
        // init Record
        DBRowSet rowset = rec.getRowSet();
    	rowset.initRecord(rec, this);
    }
    
    /**
     * Returns the result of a query as a list of objects restricted
     * to a maximum number of objects (unless maxCount is -1).
     * 
     * @param list the collection to add the objects to
     * @param t the class type of the objects in the list
     * @param maxCount the maximum number of objects
     * 
     * @return the list of T
     */
    @SuppressWarnings("unchecked")
    public <L extends List<T>, T> L getBeanList(L list, Class<T> t, Object parent, int maxCount)
    {
        // Check Recordset
        if (rset == null)
        {   // Resultset not available
            throw new ObjectNotValidException(this);
        }
        // Query List
        try
        {   // Find Constructor
            Constructor<?> ctor = findBeanConstructor(t);
            Object[] args = (ctor!=null) ? new Object[getFieldCount()] : null; 
            Class<?>[] ctorParamTypes = (ctor!=null) ? ctor.getParameterTypes() : null;
            
            // Create a list of beans
            int rownum = 0;
            while (moveNext() && maxCount != 0)
            {   // Create bean an init
                T bean;
                if (ctor!=null)
                {   // Use Constructor
                    for (int i = 0; i < getFieldCount(); i++)
                        args[i] = ObjectUtils.convert(ctorParamTypes[i], getValue(i));
                    bean = (T)ctor.newInstance(args);
                }
                else
                {   // Use Property Setters
                    bean = t.newInstance();
                    setBeanProperties(bean);
                }
                // add
                list.add(bean);
                rownum++;
                // post processing
                if (bean instanceof DataBean<?>)
                    ((DataBean<?>)bean).initialize(((DBObject)this).getDatabase(), context, rownum, parent);
                // Decrease count
                if (maxCount > 0)
                    maxCount--;
            }
            // done
            return list;
        } catch (InvocationTargetException e) {
            throw new BeanInstantiationException(t, e);
        } catch (IllegalAccessException e) {
            throw new BeanInstantiationException(t, e);
        } catch (InstantiationException e) {
            throw new BeanInstantiationException(t, e);
        }
    }
    
    /**
     * Returns the result of a query as a list of objects.
     * 
     * @param t the class type of the objects in the list
     * @param maxItems the maximum number of objects
     * 
     * @return the list of T
     */
    public final <T> List<T> getBeanList(Class<T> t, int maxItems) 
    {
        return getBeanList(new ArrayList<T>(), t, null, maxItems);
    }
    
    /**
     * Returns the result of a query as a list of objects.
     * 
     * @param t the class type of the objects in the list
     * 
     * @return the list of T
     */
    public final <T> List<T> getBeanList(Class<T> t) 
    {
        return getBeanList(t, -1);
    }
    
    /**
     * Moves the cursor down one row from its current position.
     * 
     * @return the number of column descriptions added to the Element
     */
    @Override
    public int addXmlMeta(Element parent)
    {
        if (columns == null)
            throw new ObjectNotValidException(this);
        // Add Field Description
        for (int i = 0; i < columns.length; i++)
            columns[i].addXml(parent, 0);
        // return count
        return columns.length; 
    }

    /**
     * Adds all children to a parent.
     * 
     * @param parent the parent element below which to search the child
     * @return the number of row values added to the element
     */
    @Override
    public int addXmlData(Element parent)
    {
        if (rset == null)
            throw new ObjectNotValidException(this);
        // Add all children
        for (int i = 0; i < columns.length; i++)
        { // Read all
            String name = columns[i].getName();
            String idColumnAttr = getXmlDictionary().getRowIdColumnAttribute();
            if (name.equalsIgnoreCase("id"))
            { // Add Attribute
                parent.setAttribute(idColumnAttr, getString(i));
            } 
            else
            { // Add Element
                String value = getString(i);
                Element elem = XMLUtil.addElement(parent, name, value);
                if (value == null)
                    elem.setAttribute("null", "yes"); // Null-Value
            }
        }
        // return count
        return columns.length; 
    }

    /**
     * Adds all children to a parent.
     * 
     * @param parent the parent element below which to search the child
     * @return the number of rows added to the element
     */
    public int addRows(Element parent)
    {
        int count = 0;
        if (rset == null)
            return 0;
        // Add all rows
        String rowElementName = getXmlDictionary().getRowElementName();
        while (moveNext())
        {
            addXmlData(XMLUtil.addElement(parent, rowElementName));
            count++;
        }
        return count;
    }
    
    /**
     * returns the DBXmlDictionary that should used to generate XMLDocuments<BR>
     * @return the DBXmlDictionary
     */
    protected DBXmlDictionary getXmlDictionary()
    {
        return DBXmlDictionary.getInstance();
    }

    /**
     * Returns a XML document with the field description an values of this record.
     * 
     * @return the new XML Document object
     */
    @Override
    public Document getXmlDocument()
    {
        if (rset == null)
            return null;
        // Create Document
        String rowsetElementName = getXmlDictionary().getRowSetElementName();
        Element root = XMLUtil.createDocument(rowsetElementName);
        // Add Field Description
        addXmlMeta(root);
        // Add row rset
        addRows(root);
        // return Document
        return root.getOwnerDocument();
    }

    /** returns the number of the elements of the colList array */
    @Override
    public int getFieldCount()
    {
        return (columns != null) ? columns.length : 0;
    }

    /**
     * Initialize the reader from an open JDBC-ResultSet 
     * @param db the database
     * @param columns the query column expressions
     * @param rset the JDBC-ResultSet
     */
    protected void init(DBDatabase db, DBColumnExpr[] columns, ResultSet rset)
    {
        this.db = db;
        this.columns = columns;
        this.rset = rset;
        // clear fieldIndexMap         
        if (fieldIndexMap!=null)
            fieldIndexMap.clear();
        // add to tracking list (if enabled)
        trackThisResultSet();
    }

    /**
     * Access the column expression list
     * @return the column expression list
     */
    protected final DBColumnExpr[] getColumnExprList()
    {
        return columns;
    }

    /**
     * Access the JDBC-ResultSet
     * @return the JDBC-ResultSet
     */
    protected final ResultSet getResultSet()
    {
        return rset;
    }

    /**
     * finds the field Index of a given column expression
     * Internally used as helper for getFieldIndex()
     * @return the index value
     */
    protected int findFieldIndex(ColumnExpr column)
    {
        if (columns == null)
            return -1;
        // First chance: Try to find an expression match
        int index = ObjectUtils.indexOf(columns, column);
        if (index>= 0)
            return index;
        // Second chance: Try Update Column
        if (column instanceof DBColumn)
        {
            for (int i = 0; i < columns.length; i++)
            {
                DBColumn updColumn = columns[i].getUpdateColumn();                    
                if (updColumn!=null && updColumn.equals(column))
                    return i;
                 // Query Expression?
                if (updColumn instanceof DBQueryColumn)
                {   updColumn = ((DBQueryColumn)updColumn).getExpr().getUpdateColumn();
                    if (updColumn!=null && updColumn.equals(column))
                        return i;
                }
            }
        }
        // not found!
        return -1;
    }

    /**
     * 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.getLeftTable();
            DBRowSet rsr = j.getRightTable();
            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>();
            for (Object p : params)
                list.add(p);    
        }
        // 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;
    }
     */

    /**
     * Returns a constructor for a bean class for the set of parameters or null if no suitable constructor is found
     * @param clazz the bean class
     * @param parameterTypes
     * @return a constructor for the readers columns or null if not suitable constructor is available
     */
    protected Constructor<?> findBeanConstructor(Class<?> beanClass)
    {
        // Check whether we can use a constructor
        Class<?>[] paramTypes = new Class[getFieldCount()];
        for (int i = 0; i < columns.length; i++)
            paramTypes[i] = columns[i].getJavaType(); 
        // Find Constructor
        Constructor<?> ctor = ClassUtils.findMatchingConstructor(beanClass, -1, paramTypes);
        return ctor;
    }

    /**
     * Support for finding code errors where a DBRecordSet is opened but not closed.
     * 
     * @author bond
     */
    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)
        {
            // Lazy initialization of the
            openResultSets = new HashMap<DBReader, Exception>(2);
            threadLocalOpenResultSets.set(openResultSets);
        }

        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);
            // the code continues and overwrites the logged object with the new one
        }
        // get the current stack trace
        openResultSets.put(this, new Exception());
    }

    /**
     * Support for finding code errors where a DBRecordSet is opened but not closed.
     * 
     * @author bond
     */
    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());
        } 
        else
        {
            openResultSets.remove(this);
        }
    }

    /**
     * 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>
     * Call this if you want to check whether there are any unclosed resultsets
     * It logs stack traces to help find piece of code 
     * where a DBReader was opened but not closed.
     * </PRE>
     */
    public static synchronized void checkOpenResultSets()
    {
        // check if enabled
        if (trackOpenResultSets==false)
            throw new UnspecifiedErrorException("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)
        {
            // we have found a(n) open result set(s). Now show the stack trace(s)
            Object keySet[] = openResultSets.keySet().toArray();
            for (int i = 0; i < keySet.length; i++)
            {
                Exception stackException = openResultSets.get(keySet[i]);
                log.error("A DBReader was not closed. Stack of opening code is ", stackException);
            }
            openResultSets.clear();
        }
    }
     
}