001: package com.quadcap.sql.types;
002:
003: /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.Externalizable;
042: import java.io.IOException;
043: import java.io.ObjectInput;
044: import java.io.ObjectOutput;
045:
046: import java.util.Calendar;
047:
048: import java.sql.ResultSet;
049: import java.sql.SQLException;
050: import java.sql.Types;
051:
052: import com.quadcap.util.Debug;
053: import com.quadcap.util.Util;
054:
055: /**
056: * SQL <b>INTERVAL</b> types.
057: *
058: * @author Stan Bailes
059: */
060: public class TypeInterval implements Type, Externalizable {
061: public static final TypeInterval typeInterval = new TypeInterval();
062:
063: public static final int YEAR = 0;
064: public static final int MONTH = 1;
065: public static final int DAY = 2;
066: public static final int HOUR = 3;
067: public static final int MINUTE = 4;
068: public static final int SECOND = 5;
069: public static final int NANO = 6;
070:
071: static final String[] fieldNames = { "YEAR", "MONTH", "DAY",
072: "HOUR", "MINUTE", "SECOND", "NANO" };
073:
074: static final long[] fieldNanos = { 365 * 24 * 3600 * 1000000000L, // yr
075: 30 * 24 * 3600 * 1000000000L, // mon
076: 24 * 3600 * 1000000000L, // day
077: 3600 * 1000000000L, // hour
078: 60 * 1000000000L, // min
079: 1000000000L, // sec
080: 1L // nano
081: };
082:
083: static final long[] fieldMon = { 12, 1, 0, 0, 0, 0, 0 };
084:
085: static final long[] pow10 = { 1L, 10L, 100L, 1000L, 10000L,
086: 100000L, 1000000L, 10000000L, 100000000L, 1000000000L };
087:
088: int start = -1;
089: int end = -1;
090: int startPrecision = 2;
091: int secPrecision = 6;
092:
093: public static int convertCalendarField(int field)
094: throws ValueException {
095: switch (field) {
096: case Calendar.YEAR:
097: return YEAR;
098: case Calendar.MONTH:
099: return MONTH;
100: case Calendar.DAY_OF_MONTH:
101: return DAY;
102: case Calendar.HOUR_OF_DAY:
103: return HOUR;
104: case Calendar.MINUTE:
105: return MINUTE;
106: case Calendar.SECOND:
107: return SECOND;
108: }
109: throw new ValueException("Bad time component: " + field);
110: }
111:
112: public TypeInterval() {
113: }
114:
115: public TypeInterval(int start, int startPrecision, int end,
116: int secPrecision) throws antlr.RecognitionException {
117: if (start == MONTH) {
118: throw new antlr.RecognitionException(
119: "first interval field can't be MONTH");
120: }
121: this .start = start;
122: this .startPrecision = startPrecision;
123: this .end = end;
124: this .secPrecision = secPrecision;
125: }
126:
127: public TypeInterval(int start, int startPrecision, int secPrecision) {
128: this .start = start;
129: this .end = start;
130: this .startPrecision = startPrecision;
131: this .secPrecision = secPrecision;
132: }
133:
134: int getStart() {
135: return start;
136: }
137:
138: int getEnd() {
139: return end;
140: }
141:
142: int getSecPrecision() {
143: return secPrecision;
144: }
145:
146: public String fieldName(int type) {
147: return fieldNames[type];
148: }
149:
150: static final long getNanos(int type) {
151: return fieldNanos[type];
152: }
153:
154: static final long getMon(int type) {
155: return fieldMon[type];
156: }
157:
158: /**
159: * Return the number by which the interval value must be multiplied
160: * to convert it to a value in nanoseconds
161: */
162: final long getMult() {
163: if (end == NANO) {
164: return 1000000000L / pow10[secPrecision];
165: } else {
166: return getNanos(end);
167: }
168: }
169:
170: /**
171: * Return the number by which elements of field 'type' must be multiplied
172: * in order to convert them to the unit type used in this interval.
173: *
174: * units(type) * getMult() => nanoseconds per unit
175: */
176: long units(int type, boolean ym) {
177: if (ym) {
178: return getMon(type);
179: } else if (end == NANO && type == NANO) {
180: return 1;
181: } else {
182: return getNanos(type) / getMult();
183: }
184: }
185:
186: public String getTypeName() {
187: return toString();
188: }
189:
190: public int getJDBCType() {
191: return Types.OTHER;
192: }
193:
194: public String getJDBCClassName() {
195: return "java.lang.String";
196: }
197:
198: public int getPrecision() {
199: return 32;
200: }
201:
202: public int getScale() {
203: return 0;
204: }
205:
206: public int getMaxPrecision() {
207: return 32;
208: }
209:
210: public int getMinScale() {
211: return -1;
212: }
213:
214: public int getMaxScale() {
215: return -1;
216: }
217:
218: public boolean isCharType() {
219: return false;
220: }
221:
222: public boolean isCaseSensitive() {
223: return false;
224: }
225:
226: public boolean isCurrency() {
227: return false;
228: }
229:
230: public boolean isSigned() {
231: return true;
232: }
233:
234: public String toString() {
235: StringBuffer sb = new StringBuffer("INTERVAL");
236: if (start >= 0) {
237: sb.append(' ');
238: sb.append(fieldNames[start]);
239: if (start == SECOND) {
240: if (startPrecision != 2 || secPrecision != 6) {
241: sb.append('(');
242: sb.append(Integer.toString(startPrecision));
243: sb.append(',');
244: sb.append(Integer.toString(secPrecision));
245: sb.append(')');
246: }
247: } else if (startPrecision != 2) {
248: sb.append('(');
249: sb.append(Integer.toString(startPrecision));
250: sb.append(')');
251: }
252: int fld = start;
253: if (end >= 0 && end != NANO && end != start) {
254: sb.append(" TO ");
255: sb.append(fieldNames[end]);
256: fld = end;
257: }
258: }
259: // sb.append("[");
260: // sb.append(start);
261: // sb.append("-");
262: // sb.append(end);
263: // sb.append("]");
264: return sb.toString();
265: }
266:
267: public int getDisplayWidth() {
268: return 10;
269: }
270:
271: public void readExternal(ObjectInput in) throws IOException {
272: start = in.readInt();
273: end = in.readInt();
274: startPrecision = in.readInt();
275: secPrecision = in.readInt();
276: }
277:
278: public void writeExternal(ObjectOutput out) throws IOException {
279: out.writeInt(start);
280: out.writeInt(end);
281: out.writeInt(startPrecision);
282: out.writeInt(secPrecision);
283: }
284:
285: public Value convert(Value v) throws ValueException {
286: return v.convert(this );
287: }
288:
289: public String getCreateParams() {
290: return null;
291: }
292: }
|