query = query + " AND item.last_modified >= '" + startDate + "'";
if ("oracle".equals(ConfigurationManager.getProperty("db.name"))) { query = query + " AND item.last_modified >= " + oracleTimeStampFromIsoString(startDate); } else { query = query + " AND item.last_modified >= '" + startDate + "'"; }
    public static List harvest(Context context, Collection scope,            String startDate, String endDate, int offset, int limit,            boolean items, boolean collections, boolean withdrawn)            throws SQLException    {        // SQL to add to the list of tables after the SELECT        String scopeTableSQL = "";        // SQL to add to the WHERE clause of the query        String scopeWhereSQL = "";        if (scope != null)        {            scopeTableSQL = ", collection2item";            scopeWhereSQL = " AND collection2item.collection_id="                    + scope.getID()                    + " AND collection2item.item_id=handle.resource_id";        }        // Put together our query. Note there is no need for an        // "in_archive=true" condition, we are using the existence of        // Handles as our 'existence criterion'.        String query = "SELECT handle.handle, handle.resource_id, item.withdrawn, item.last_modified FROM handle, item"                + scopeTableSQL                + " WHERE handle.resource_type_id="                + Constants.ITEM                + " AND handle.resource_id=item.item_id"                + scopeWhereSQL;        if (startDate != null)        {            query = query + " AND item.last_modified >= '" + startDate + "'";        }        if (endDate != null)        {            /*             * If the end date has seconds precision, e.g.:             *              * 2004-04-29T13:45:43Z             *              * we need to add 999 milliseconds to this. This is because SQL             * TIMESTAMPs have millisecond precision, and so might have a value:             *              * 2004-04-29T13:45:43.952Z             *              * and so <= '2004-04-29T13:45:43Z' would not pick this up. Reading             * things out of the database, TIMESTAMPs are rounded down, so the             * above value would be read as '2004-04-29T13:45:43Z', and             * therefore a caller would expect <= '2004-04-29T13:45:43Z' to             * include that value.             *              * Got that? ;-)             */            if (endDate.length() == 20)            {                endDate = endDate.substring(0, 19) + ".999Z";            }            query = query + " AND item.last_modified <= '" + endDate + "'";        }        if (withdrawn == false)        {            // Exclude withdrawn items            if ("oracle".equals(ConfigurationManager.getProperty("db.name")))            {                query = query + " AND withdrawn=0";            }            else            {                // postgres uses booleans                query = query + " AND withdrawn=false";            }        }        // Order by item ID, so that for a given harvest the order will be        // consistent. This is so that big harvests can be broken up into        // several smaller operations (e.g. for OAI resumption tokens.)        query = query + " ORDER BY handle.resource_id";        log.debug(LogManager.getHeader(context, "harvest SQL", query));        // Execute        TableRowIterator tri = DatabaseManager.query(context, query);        List infoObjects = new LinkedList();        int index = 0;        // Process results of query into HarvestedItemInfo objects        while (tri.hasNext())        {            TableRow row = tri.next();            /*             * This conditional ensures that we only process items within any             * constraints specified by 'offset' and 'limit' parameters.             */            if ((index >= offset)                    && ((limit == 0) || (index < (offset + limit))))            {                HarvestedItemInfo itemInfo = new HarvestedItemInfo();                itemInfo.handle = row.getStringColumn("handle");                itemInfo.itemID = row.getIntColumn("resource_id");                // Put datestamp in ISO8601                itemInfo.datestamp = row.getDateColumn("last_modified");                itemInfo.withdrawn = row.getBooleanColumn("withdrawn");                if (collections)                {                    fillCollections(context, itemInfo);                }                if (items)                {                    // Get the item                    itemInfo.item = Item.find(context, itemInfo.itemID);                }                infoObjects.add(itemInfo);            }            index++;        }        return infoObjects;    }