/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.amber.query; import com.caucho.amber.expr.AmberExpr; import com.caucho.util.Alarm; import java.lang.ref.SoftReference; import java.sql.SQLException; import java.util.ArrayList; /** * The JDBC statement implementation. */ public class ResultSetCacheChunk { public static final int CACHE_CHUNK_SIZE = 64; private AmberSelectQuery _query; private ArrayList<FromItem> _fromList; private ArrayList<AmberExpr> _resultList; private int _startRow; private final ArrayList<Object[]> _results = new ArrayList<Object[]>(); private SoftReference<ResultSetCacheChunk> _next; private boolean _isLast; private long _expireTime; public ResultSetCacheChunk() { } public ResultSetCacheChunk(ResultSetCacheChunk prev) { _startRow = prev._startRow + CACHE_CHUNK_SIZE; _query = prev._query; _fromList = prev._fromList; _resultList = prev._resultList; _expireTime = prev._expireTime; } /** * Sets the query. */ public void setQuery(AmberSelectQuery query) { _query = query; _fromList = query.getFromList(); _resultList = query.getResultList(); _expireTime = Alarm.getCurrentTime() + query.getCacheMaxAge(); } /** * Gets the query. */ public AmberSelectQuery getQuery() { return _query; } /** * Returns the expire time. */ public long getExpireTime() { return _expireTime; } /** * Return true if the chunk is still valid. */ public boolean isValid() { return Alarm.getCurrentTime() <= _expireTime; } /** * Invalidates the chunk. */ public void invalidate() { _expireTime = 0; _next = null; } /** * Invalidates the chunk based on a table and key. */ public boolean invalidate(String table, Object key) { if (getQuery().invalidateTable(table)) { invalidate(); return true; } else return false; } /** * Returns the number of rows. */ public int getRowCount() { return _startRow + _results.size(); } /** * Adds a new row. */ public void newRow() { _results.add(new Object[_resultList.size()]); } /** * Sets a row value. */ public void setValue(int row, int column, Object value) { _results.get(row % CACHE_CHUNK_SIZE)[column] = value; } /** * Gets the next chunk */ public ResultSetCacheChunk getNext() { SoftReference<ResultSetCacheChunk> nextRef = _next; if (nextRef != null) return nextRef.get(); else return null; } /** * Gets the next chunk */ public void setNext(ResultSetCacheChunk next) { _next = new SoftReference<ResultSetCacheChunk>(next); } /** * Sets true for the last. */ public void setLast(boolean isLast) { _isLast = isLast; } /** * True for the last. */ public boolean isLast() { return _isLast; } /** * Returns true if the last column read was null. */ public boolean isNull(int row, int column) { return getObject(row, column) == null; } /** * Returns the boolean value for the column. */ public boolean getBoolean(int row, int column) throws SQLException { Object object = getObject(row, column); if (object instanceof Boolean) return ((Boolean) object).booleanValue(); else if (object instanceof Number) return ((Number) object).intValue() != 0; else if (object instanceof String) { String s = (String) object; return s.startsWith("t") || s.startsWith("y"); } else return object != null; } /** * Returns the byte value for the column. */ public byte getByte(int row, int column) throws SQLException { Object object = getObject(row, column); if (object instanceof Byte) return ((Byte) object).byteValue(); else if (object instanceof String) return Byte.parseByte((String) object); else if (object == null) return 0; else return Byte.parseByte(String.valueOf(object)); } /** * Returns the int value for the column. */ public int getInt(int row, int column) throws SQLException { Object object = getObject(row, column); if (object instanceof Number) return ((Number) object).intValue(); else if (object instanceof String) return Integer.parseInt((String) object); else if (object == null) return 0; else return Integer.parseInt(String.valueOf(object)); } /** * Returns the short value for the column. */ public short getShort(int row, int column) throws SQLException { Object object = getObject(row, column); if (object instanceof Number) return ((Number) object).shortValue(); else if (object instanceof String) return Short.parseShort((String) object); else if (object == null) return 0; else return Short.parseShort(String.valueOf(object)); } /** * Returns the long value for the column. */ public long getLong(int row, int column) throws SQLException { Object object = getObject(row, column); if (object instanceof Number) return ((Number) object).longValue(); else if (object instanceof String) return Long.parseLong((String) object); else if (object instanceof java.sql.Date) return ((java.sql.Date) object).getTime(); else if (object == null) return 0; else return Long.parseLong(String.valueOf(object)); } /** * Returns the double value for the column. */ public double getDouble(int row, int column) throws SQLException { Object object = getObject(row, column); if (object instanceof Number) return ((Number) object).doubleValue(); else if (object instanceof String) return Double.parseDouble((String) object); else if (object == null) return 0; else return Double.parseDouble(String.valueOf(object)); } /** * Returns the float value for the column. */ public float getFloat(int row, int column) throws SQLException { Object object = getObject(row, column); if (object instanceof Number) return ((Number) object).floatValue(); else if (object instanceof String) return Float.parseFloat((String) object); else if (object == null) return 0; else return Float.parseFloat(String.valueOf(object)); } /** * Returns the string value for the column. */ public String getString(int row, int column) throws SQLException { Object object = getObject(row, column); if (object instanceof String) return (String) object; else if (object == null) return null; else return String.valueOf(object); } /** * Returns the value. */ public final Object getObject(int row, int column) { return _results.get(row % CACHE_CHUNK_SIZE)[column]; } }