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: *
023: * Free SoftwareFoundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.db.table;
031:
032: import com.caucho.db.index.BTree;
033: import com.caucho.db.sql.Expr;
034: import com.caucho.db.sql.QueryContext;
035: import com.caucho.db.sql.SelectResult;
036: import com.caucho.db.store.Transaction;
037: import com.caucho.sql.SQLExceptionWrapper;
038: import com.caucho.util.QDate;
039:
040: import java.sql.SQLException;
041:
042: /**
043: * Represents a 64-bit long date column.
044: */
045: class DateColumn extends Column {
046: private static QDate _gmtDate = new QDate();
047:
048: /**
049: * Creates a date column.
050: *
051: * @param row the row the column is being added to
052: * @param name the column's name
053: */
054: DateColumn(Row row, String name) {
055: super (row, name);
056: }
057:
058: /**
059: * Returns the column's type code.
060: */
061: public int getTypeCode() {
062: return DATE;
063: }
064:
065: /**
066: * Returns the column's Java type.
067: */
068: public Class getJavaType() {
069: return java.sql.Date.class;
070: }
071:
072: /**
073: * Returns the column's declaration size.
074: */
075: public int getDeclarationSize() {
076: return 8;
077: }
078:
079: /**
080: * Returns the column's length
081: */
082: public int getLength() {
083: return 8;
084: }
085:
086: /**
087: * Sets a string value in the column.
088: *
089: * @param block the block's buffer
090: * @param rowOffset the offset of the row in the block
091: * @param value the value to store
092: */
093: void setString(Transaction xa, byte[] block, int rowOffset,
094: String str) throws SQLException {
095: if (str == null)
096: setNull(block, rowOffset);
097: else {
098: long date = 0;
099:
100: try {
101: synchronized (_gmtDate) {
102: date = _gmtDate.parseDate(str);
103: }
104: } catch (Exception e) {
105: throw new SQLExceptionWrapper(e);
106: }
107:
108: setDate(xa, block, rowOffset, date);
109: }
110: }
111:
112: /**
113: * Gets a string value from the column.
114: *
115: * @param block the block's buffer
116: * @param rowOffset the offset of the row in the block
117: */
118: public String getString(byte[] block, int rowOffset) {
119: if (isNull(block, rowOffset))
120: return null;
121: else
122: return QDate.formatISO8601(getDate(block, rowOffset));
123: }
124:
125: /**
126: * Sets a date value in the column.
127: *
128: * @param block the block's buffer
129: * @param rowOffset the offset of the row in the block
130: * @param value the value to store
131: */
132: void setDate(Transaction xa, byte[] block, int rowOffset, long value) {
133: int offset = rowOffset + _columnOffset;
134:
135: block[offset++] = (byte) (value >> 56);
136: block[offset++] = (byte) (value >> 48);
137: block[offset++] = (byte) (value >> 40);
138: block[offset++] = (byte) (value >> 32);
139: block[offset++] = (byte) (value >> 24);
140: block[offset++] = (byte) (value >> 16);
141: block[offset++] = (byte) (value >> 8);
142: block[offset++] = (byte) (value);
143:
144: setNonNull(block, rowOffset);
145: }
146:
147: /**
148: * Gets a date value from the column.
149: *
150: * @param block the block's buffer
151: * @param rowOffset the offset of the row in the block
152: */
153: public long getDate(byte[] block, int rowOffset) {
154: if (isNull(block, rowOffset))
155: return 0;
156:
157: int offset = rowOffset + _columnOffset;
158: long value = 0;
159:
160: value = (block[offset++] & 0xffL) << 56;
161: value |= (block[offset++] & 0xffL) << 48;
162: value |= (block[offset++] & 0xffL) << 40;
163: value |= (block[offset++] & 0xffL) << 32;
164: value |= (block[offset++] & 0xffL) << 24;
165: value |= (block[offset++] & 0xffL) << 16;
166: value |= (block[offset++] & 0xffL) << 8;
167: value |= (block[offset++] & 0xffL);
168:
169: return value;
170: }
171:
172: /**
173: * Sets a long value in the column.
174: *
175: * @param block the block's buffer
176: * @param rowOffset the offset of the row in the block
177: * @param value the value to store
178: */
179: void setLong(Transaction xa, byte[] block, int rowOffset, long value) {
180: setDate(xa, block, rowOffset, value);
181: }
182:
183: /**
184: * Gets a long value in the column.
185: *
186: * @param block the block's buffer
187: * @param rowOffset the offset of the row in the block
188: */
189: public long getLong(byte[] block, int rowOffset) {
190: return getDate(block, rowOffset);
191: }
192:
193: /**
194: * Sets a long value in the column.
195: *
196: * @param block the block's buffer
197: * @param rowOffset the offset of the row in the block
198: * @param value the value to store
199: */
200: void setInteger(Transaction xa, byte[] block, int rowOffset,
201: int value) {
202: setDate(xa, block, rowOffset, value);
203: }
204:
205: /**
206: * Sets a long value in the column.
207: *
208: * @param block the block's buffer
209: * @param rowOffset the offset of the row in the block
210: * @param value the value to store
211: */
212: public int getInteger(byte[] block, int rowOffset) {
213: return (int) getDate(block, rowOffset);
214: }
215:
216: /**
217: * Evaluates the column to a stream.
218: */
219: public void evalToResult(byte[] block, int rowOffset,
220: SelectResult result) {
221: if (isNull(block, rowOffset)) {
222: result.writeNull();
223: return;
224: }
225:
226: result.writeDate(getDate(block, rowOffset));
227: }
228:
229: /**
230: * Evaluate to a buffer.
231: *
232: * @param block the block's buffer
233: * @param rowOffset the offset of the row in the block
234: * @param buffer the result buffer
235: * @param buffer the result buffer offset
236: *
237: * @return the length of the value
238: */
239: int evalToBuffer(byte[] block, int rowOffset, byte[] buffer,
240: int bufferOffset) throws SQLException {
241: if (isNull(block, rowOffset))
242: return 0;
243:
244: int startOffset = rowOffset + _columnOffset;
245: int len = 8;
246:
247: System.arraycopy(block, startOffset, buffer, bufferOffset, len);
248:
249: return len;
250: }
251:
252: /**
253: * Sets the column based on an expression.
254: *
255: * @param block the block's buffer
256: * @param rowOffset the offset of the row in the block
257: * @param expr the expression to store
258: */
259: void setExpr(Transaction xa, byte[] block, int rowOffset,
260: Expr expr, QueryContext context) throws SQLException {
261: if (expr.isNull(null))
262: setNull(block, rowOffset);
263: else
264: setDate(xa, block, rowOffset, expr.evalDate(context));
265: }
266:
267: /**
268: * Returns true if the items in the given rows match.
269: */
270: public boolean isEqual(byte[] block1, int rowOffset1,
271: byte[] block2, int rowOffset2) {
272: //System.out.println("EQ:");
273: if (isNull(block1, rowOffset1) != isNull(block2, rowOffset2))
274: return false;
275:
276: int startOffset1 = rowOffset1 + _columnOffset;
277: int startOffset2 = rowOffset2 + _columnOffset;
278:
279: return (block1[startOffset1 + 0] == block2[startOffset2 + 0]
280: && block1[startOffset1 + 1] == block2[startOffset2 + 1]
281: && block1[startOffset1 + 2] == block2[startOffset2 + 2]
282: && block1[startOffset1 + 3] == block2[startOffset2 + 3]
283: && block1[startOffset1 + 4] == block2[startOffset2 + 4]
284: && block1[startOffset1 + 5] == block2[startOffset2 + 5]
285: && block1[startOffset1 + 6] == block2[startOffset2 + 6] && block1[startOffset1 + 7] == block2[startOffset2 + 7]);
286: }
287:
288: /**
289: * Sets any index for the column.
290: *
291: * @param block the block's buffer
292: * @param rowOffset the offset of the row in the block
293: * @param rowAddr the address of the row
294: */
295: void setIndex(Transaction xa, byte[] block, int rowOffset,
296: long rowAddr, QueryContext context) throws SQLException {
297: BTree index = getIndex();
298:
299: if (index == null)
300: return;
301:
302: index.insert(block, rowOffset + _columnOffset, 8, rowAddr, xa,
303: false);
304: }
305:
306: /**
307: * Sets based on an iterator.
308: */
309: public void set(TableIterator iter, Expr expr, QueryContext context)
310: throws SQLException {
311: iter.setDirty();
312: setDate(iter.getTransaction(), iter.getBuffer(), iter
313: .getRowOffset(), expr.evalDate(context));
314: }
315:
316: /**
317: * Deleting the row, based on the column.
318: *
319: * @param block the block's buffer
320: * @param rowOffset the offset of the row in the block
321: * @param expr the expression to store
322: */
323: void delete(Transaction xa, byte[] block, int rowOffset)
324: throws SQLException {
325: BTree index = getIndex();
326:
327: if (index != null)
328: index.remove(block, rowOffset + _columnOffset, 8, xa);
329: }
330: }
|