001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free Software Foundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.amber.query;
030:
031: import com.caucho.amber.expr.AmberExpr;
032: import com.caucho.util.Alarm;
033:
034: import java.lang.ref.SoftReference;
035: import java.sql.SQLException;
036: import java.util.ArrayList;
037:
038: /**
039: * The JDBC statement implementation.
040: */
041: public class ResultSetCacheChunk {
042: public static final int CACHE_CHUNK_SIZE = 64;
043:
044: private SelectQuery _query;
045:
046: private ArrayList<FromItem> _fromList;
047: private ArrayList<AmberExpr> _resultList;
048:
049: private int _startRow;
050:
051: private final ArrayList<Object[]> _results = new ArrayList<Object[]>();
052:
053: private SoftReference<ResultSetCacheChunk> _next;
054: private boolean _isLast;
055:
056: private long _expireTime;
057:
058: public ResultSetCacheChunk() {
059: }
060:
061: public ResultSetCacheChunk(ResultSetCacheChunk prev) {
062: _startRow = prev._startRow + CACHE_CHUNK_SIZE;
063: _query = prev._query;
064: _fromList = prev._fromList;
065: _resultList = prev._resultList;
066:
067: _expireTime = prev._expireTime;
068: }
069:
070: /**
071: * Sets the query.
072: */
073: public void setQuery(SelectQuery query) {
074: _query = query;
075:
076: _fromList = query.getFromList();
077: _resultList = query.getResultList();
078:
079: _expireTime = Alarm.getCurrentTime() + query.getCacheMaxAge();
080: }
081:
082: /**
083: * Gets the query.
084: */
085: public SelectQuery getQuery() {
086: return _query;
087: }
088:
089: /**
090: * Returns the expire time.
091: */
092: public long getExpireTime() {
093: return _expireTime;
094: }
095:
096: /**
097: * Return true if the chunk is still valid.
098: */
099: public boolean isValid() {
100: return Alarm.getCurrentTime() <= _expireTime;
101: }
102:
103: /**
104: * Invalidates the chunk.
105: */
106: public void invalidate() {
107: _expireTime = 0;
108: _next = null;
109: }
110:
111: /**
112: * Invalidates the chunk based on a table and key.
113: */
114: public boolean invalidate(String table, Object key) {
115: if (getQuery().invalidateTable(table)) {
116: invalidate();
117:
118: return true;
119: } else
120: return false;
121: }
122:
123: /**
124: * Returns the number of rows.
125: */
126: public int getRowCount() {
127: return _startRow + _results.size();
128: }
129:
130: /**
131: * Adds a new row.
132: */
133: public void newRow() {
134: _results.add(new Object[_resultList.size()]);
135: }
136:
137: /**
138: * Sets a row value.
139: */
140: public void setValue(int row, int column, Object value) {
141: _results.get(row % CACHE_CHUNK_SIZE)[column] = value;
142: }
143:
144: /**
145: * Gets the next chunk
146: */
147: public ResultSetCacheChunk getNext() {
148: SoftReference<ResultSetCacheChunk> nextRef = _next;
149:
150: if (nextRef != null)
151: return nextRef.get();
152: else
153: return null;
154: }
155:
156: /**
157: * Gets the next chunk
158: */
159: public void setNext(ResultSetCacheChunk next) {
160: _next = new SoftReference<ResultSetCacheChunk>(next);
161: }
162:
163: /**
164: * Sets true for the last.
165: */
166: public void setLast(boolean isLast) {
167: _isLast = isLast;
168: }
169:
170: /**
171: * True for the last.
172: */
173: public boolean isLast() {
174: return _isLast;
175: }
176:
177: /**
178: * Returns true if the last column read was null.
179: */
180: public boolean isNull(int row, int column) {
181: return getObject(row, column) == null;
182: }
183:
184: /**
185: * Returns the boolean value for the column.
186: */
187: public boolean getBoolean(int row, int column) throws SQLException {
188: Object object = getObject(row, column);
189:
190: if (object instanceof Boolean)
191: return ((Boolean) object).booleanValue();
192: else if (object instanceof Number)
193: return ((Number) object).intValue() != 0;
194: else if (object instanceof String) {
195: String s = (String) object;
196:
197: return s.startsWith("t") || s.startsWith("y");
198: } else
199: return object != null;
200: }
201:
202: /**
203: * Returns the byte value for the column.
204: */
205: public byte getByte(int row, int column) throws SQLException {
206: Object object = getObject(row, column);
207:
208: if (object instanceof Byte)
209: return ((Byte) object).byteValue();
210: else if (object instanceof String)
211: return Byte.parseByte((String) object);
212: else if (object == null)
213: return 0;
214: else
215: return Byte.parseByte(String.valueOf(object));
216: }
217:
218: /**
219: * Returns the int value for the column.
220: */
221: public int getInt(int row, int column) throws SQLException {
222: Object object = getObject(row, column);
223:
224: if (object instanceof Number)
225: return ((Number) object).intValue();
226: else if (object instanceof String)
227: return Integer.parseInt((String) object);
228: else if (object == null)
229: return 0;
230: else
231: return Integer.parseInt(String.valueOf(object));
232: }
233:
234: /**
235: * Returns the short value for the column.
236: */
237: public short getShort(int row, int column) throws SQLException {
238: Object object = getObject(row, column);
239:
240: if (object instanceof Number)
241: return ((Number) object).shortValue();
242: else if (object instanceof String)
243: return Short.parseShort((String) object);
244: else if (object == null)
245: return 0;
246: else
247: return Short.parseShort(String.valueOf(object));
248: }
249:
250: /**
251: * Returns the long value for the column.
252: */
253: public long getLong(int row, int column) throws SQLException {
254: Object object = getObject(row, column);
255:
256: if (object instanceof Number)
257: return ((Number) object).longValue();
258: else if (object instanceof String)
259: return Long.parseLong((String) object);
260: else if (object instanceof java.sql.Date)
261: return ((java.sql.Date) object).getTime();
262: else if (object == null)
263: return 0;
264: else
265: return Long.parseLong(String.valueOf(object));
266: }
267:
268: /**
269: * Returns the double value for the column.
270: */
271: public double getDouble(int row, int column) throws SQLException {
272: Object object = getObject(row, column);
273:
274: if (object instanceof Number)
275: return ((Number) object).doubleValue();
276: else if (object instanceof String)
277: return Double.parseDouble((String) object);
278: else if (object == null)
279: return 0;
280: else
281: return Double.parseDouble(String.valueOf(object));
282: }
283:
284: /**
285: * Returns the float value for the column.
286: */
287: public float getFloat(int row, int column) throws SQLException {
288: Object object = getObject(row, column);
289:
290: if (object instanceof Number)
291: return ((Number) object).floatValue();
292: else if (object instanceof String)
293: return Float.parseFloat((String) object);
294: else if (object == null)
295: return 0;
296: else
297: return Float.parseFloat(String.valueOf(object));
298: }
299:
300: /**
301: * Returns the string value for the column.
302: */
303: public String getString(int row, int column) throws SQLException {
304: Object object = getObject(row, column);
305:
306: if (object instanceof String)
307: return (String) object;
308: else if (object == null)
309: return null;
310: else
311: return String.valueOf(object);
312: }
313:
314: /**
315: * Returns the value.
316: */
317: public final Object getObject(int row, int column) {
318: return _results.get(row % CACHE_CHUNK_SIZE)[column];
319: }
320: }
|