001: /*
002: * tsColumn.java - Column Object for tinySQL.
003: *
004: * Copyright 1996, Brian C. Jepson
005: * (bjepson@ids.net)
006: * $Author: davis $
007: * $Date: 2004/12/18 21:25:35 $
008: * $Revision: 1.1 $
009: *
010: * This library is free software; you can redistribute it and/or
011: * modify it under the terms of the GNU Lesser General Public
012: * License as published by the Free Software Foundation; either
013: * version 2.1 of the License, or (at your option) any later version.
014: *
015: * This library is distributed in the hope that it will be useful,
016: * but WITHOUT ANY WARRANTY; without even the implied warranty of
017: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
018: * Lesser General Public License for more details.
019: *
020: * You should have received a copy of the GNU Lesser General Public
021: * License along with this library; if not, write to the Free Software
022: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
023: *
024: */
025:
026: package com.sqlmagic.tinysql;
027:
028: import java.util.*;
029: import java.lang.*;
030: import java.io.*;
031: import java.text.*;
032: import java.sql.Types;
033:
034: /*
035: * Object to hold column metadata and value
036: * Example for a column_def entity:
037: * phone CHAR(30) DEFAULT '-' NOT NULL
038: *
039: * @author Thomas Morgner <mgs@sherito.org> type is now integer
040: * and contains one of the java.sql.Types Values
041: */
042: class tsColumn implements Cloneable {
043: public String name = null; // the column's name
044: public String alias = null; // the column's definition
045: public String longName = null; // the column's long name ( > 11 chars)
046: public Vector contextList; // the columns context (SELECT,ORDER,etc.)
047: public int type = -1; // the column's type
048: // dBase types:
049: // 'C' Char (max 254 bytes)
050: // 'N' '-.0123456789' (max 19 bytes)
051: // 'L' 'YyNnTtFf?' (1 byte)
052: // 'M' 10 digit .DBT block number
053: // 'D' 8 digit YMD
054: public int size = 0; // the column's size
055: public int decimalPlaces = 0; // decimal places in numeric column
056: public String defaultVal = null;// not yet supported
057: public int position = 0; // internal use
058: public String tableName = ""; // the table which "owns" the column
059: public tinySQLTable columnTable = null;
060: public String newLine = System.getProperty("line.separator");
061: String functionName = (String) null; // Function name
062: String functionArgString = (String) null; // Function arguments
063: Vector functionArgs = (Vector) null; // Function arguments as columns
064: boolean notNull = false;
065: boolean valueSet = false;
066: String stringValue = (String) null;
067: int intValue = Integer.MIN_VALUE;
068: float floatValue = Float.MIN_VALUE;
069: SimpleDateFormat fmtyyyyMMdd = new SimpleDateFormat("yyyy-MM-dd");
070: Calendar today = Calendar.getInstance();
071: boolean isConstant = false;
072: boolean groupedColumn = false;
073:
074: /*
075: * The constructor creates a column object using recursion if this is a
076: * function.
077: */
078: tsColumn(String s) throws tinySQLException {
079: this (s, (Hashtable) null, "SELECT");
080: }
081:
082: tsColumn(String s, Hashtable tableDefs, String inputContext)
083: throws tinySQLException {
084: FieldTokenizer ft, ftArgs;
085: int i, j, numericType, nameLength, dotAt, argIndex;
086: String upperName, checkName, nextArg;
087: tinySQLTable jtbl;
088: tsColumn tcol;
089: Vector t;
090: Enumeration col_keys;
091: name = s;
092: longName = name;
093: nameLength = name.length();
094: contextList = new Vector();
095: contextList.addElement(inputContext);
096: ft = new FieldTokenizer(name, '(', false);
097: if (ft.countFields() == 2) {
098: /*
099: * This is a function rather than a simple column or constant
100: */
101: functionName = ft.getField(0).toUpperCase();
102: if (functionName.equals("COUNT")) {
103: type = Types.INTEGER;
104: size = 10;
105: intValue = Integer.MIN_VALUE;
106: groupedColumn = true;
107: } else if (functionName.equals("SUM")) {
108: type = Types.FLOAT;
109: size = 10;
110: groupedColumn = true;
111: } else if (functionName.equals("TO_DATE")) {
112: type = Types.DATE;
113: size = 10;
114: } else if (functionName.equals("CONCAT")
115: | functionName.equals("UPPER")
116: | functionName.equals("SUBSTR")
117: | functionName.equals("TRIM")) {
118: type = Types.CHAR;
119: }
120: functionArgString = ft.getField(1);
121: ftArgs = new FieldTokenizer(functionArgString, ',', false);
122: functionArgs = new Vector();
123: argIndex = 0;
124: while (ftArgs.hasMoreFields()) {
125: nextArg = ftArgs.nextField();
126: tcol = new tsColumn(nextArg, tableDefs, inputContext);
127: if (tcol.isGroupedColumn())
128: groupedColumn = true;
129: /*
130: * MAX and MIN functions can be either FLOAT or CHAR types
131: * depending upon the type of the argument.
132: */
133: if (functionName.equals("MAX")
134: | functionName.equals("MIN")) {
135: if (argIndex > 0)
136: throw new tinySQLException(
137: "Function can only have 1 argument");
138: groupedColumn = true;
139: type = tcol.type;
140: size = tcol.size;
141: } else if (functionName.equals("CONCAT")) {
142: type = Types.CHAR;
143: size += tcol.size;
144: } else if (functionName.equals("UPPER")) {
145: type = Types.CHAR;
146: size = tcol.size;
147: } else if (functionName.equals("TO_DATE")) {
148: type = Types.DATE;
149: size = 10;
150: } else if (functionName.equals("TRIM")) {
151: type = Types.CHAR;
152: size = tcol.size;
153: } else if (functionName.equals("SUBSTR")) {
154: type = Types.CHAR;
155: if (argIndex == 0 & tcol.type != Types.CHAR) {
156: throw new tinySQLException(
157: "SUBSTR first argument must be character");
158: } else if (argIndex == 1) {
159: if (tcol.type != Types.INTEGER
160: | tcol.intValue < 1)
161: throw new tinySQLException(
162: "SUBSTR second argument "
163: + tcol.getString()
164: + " must be integer > 0");
165: } else if (argIndex == 2) {
166: if (tcol.type != Types.INTEGER
167: | tcol.intValue < 1)
168: throw new tinySQLException(
169: "SUBSTR third argument "
170: + tcol.getString()
171: + " must be integer > 0");
172: size = tcol.intValue;
173: }
174: }
175: argIndex++;
176: functionArgs.addElement(tcol);
177: }
178: } else {
179: /*
180: * Check for SYSDATE
181: */
182: if (name.toUpperCase().equals("SYSDATE")) {
183: isConstant = true;
184: type = Types.DATE;
185: size = 10;
186: notNull = true;
187: valueSet = true;
188: stringValue = fmtyyyyMMdd.format(today.getTime());
189: /*
190: * Check for a quoted string
191: */
192: } else if (UtilString.isQuotedString(name)) {
193: isConstant = true;
194: type = Types.CHAR;
195: stringValue = UtilString.removeQuotes(name);
196: if (stringValue != (String) null) {
197: size = stringValue.length();
198: notNull = true;
199: valueSet = true;
200: }
201: } else {
202: /*
203: * Check for a numeric constant
204: */
205: numericType = UtilString.getValueType(name);
206: if (numericType == Types.INTEGER) {
207: intValue = Integer.valueOf(name).intValue();
208: size = 10;
209: type = numericType;
210: isConstant = true;
211: notNull = true;
212: valueSet = true;
213: } else if (numericType == Types.FLOAT) {
214: floatValue = Float.valueOf(name).floatValue();
215: size = 10;
216: type = numericType;
217: isConstant = true;
218: notNull = true;
219: valueSet = true;
220: } else {
221: /*
222: * This should be a column name.
223: */
224: columnTable = (tinySQLTable) null;
225: upperName = name.toUpperCase();
226: if (tinySQLGlobals.DEBUG)
227: System.out.println("Trying to find table for "
228: + upperName);
229: dotAt = upperName.indexOf(".");
230: if (dotAt > -1) {
231: tableName = upperName.substring(0, dotAt);
232: if (tableDefs != (Hashtable) null
233: & tableName.indexOf("->") < 0) {
234: t = (Vector) tableDefs
235: .get("TABLE_SELECT_ORDER");
236: tableName = UtilString.findTableAlias(
237: tableName, t);
238: }
239: upperName = upperName.substring(dotAt + 1);
240: /*
241: * Check to see if this column name has a short equivalent.
242: */
243: if (upperName.length() > 11) {
244: longName = name;
245: upperName = tinySQLGlobals
246: .getShortName(upperName);
247: }
248: columnTable = (tinySQLTable) tableDefs
249: .get(tableName);
250: } else if (tableDefs != (Hashtable) null) {
251: /*
252: * Check to see if this column name has a short equivalent.
253: */
254: if (upperName.length() > 11) {
255: longName = name;
256: upperName = tinySQLGlobals
257: .getShortName(upperName);
258: }
259: /*
260: * Use an enumeration to go through all of the tables to find
261: * this column.
262: */
263: t = (Vector) tableDefs
264: .get("TABLE_SELECT_ORDER");
265: for (j = 0; j < t.size(); j++) {
266: tableName = (String) t.elementAt(j);
267: jtbl = (tinySQLTable) tableDefs
268: .get(tableName);
269: col_keys = jtbl.column_info.keys();
270: /*
271: * Check all columns.
272: */
273: while (col_keys.hasMoreElements()) {
274: checkName = (String) col_keys
275: .nextElement();
276: if (checkName.equals(upperName)) {
277: upperName = checkName;
278: columnTable = jtbl;
279: break;
280: }
281: }
282: if (columnTable != (tinySQLTable) null)
283: break;
284: }
285: } else {
286: if (tinySQLGlobals.DEBUG)
287: System.out.println("No table definitions.");
288: }
289: if (columnTable != (tinySQLTable) null) {
290: name = columnTable.table + "->"
291: + columnTable.tableAlias + "."
292: + upperName;
293: type = columnTable.ColType(upperName);
294: size = columnTable.ColSize(upperName);
295: decimalPlaces = columnTable.ColDec(upperName);
296: tableName = columnTable.table + "->"
297: + columnTable.tableAlias;
298: }
299: }
300: }
301: }
302: }
303:
304: /*
305: * This function sets the column to a null value if the column belongs
306: * to the input table, or the column is a function which has an
307: * argument which belongs to the input table and whose value is null
308: * if any argument is null.
309: */
310: public boolean clear() {
311: return clear((String) null);
312: }
313:
314: public boolean clear(String inputTableName) {
315: int i;
316: tsColumn argColumn;
317: boolean argClear;
318: if (functionName == (String) null) {
319: if (!isConstant) {
320: if (inputTableName == (String) null) {
321: notNull = false;
322: valueSet = false;
323: } else if (tableName == (String) null) {
324: notNull = false;
325: valueSet = false;
326: } else if (tableName.equals(inputTableName)) {
327: notNull = false;
328: valueSet = false;
329: }
330: }
331: } else {
332: for (i = 0; i < functionArgs.size(); i++) {
333: argColumn = (tsColumn) functionArgs.elementAt(i);
334: argClear = argColumn.clear(inputTableName);
335: if (argClear & Utils.clearFunction(functionName)) {
336: notNull = false;
337: valueSet = false;
338: }
339: }
340: }
341: return isNull();
342: }
343:
344: /*
345: * This method updates the value of the column. In the case of a function
346: * only the argument values are updated, not the function as a whole. Functions
347: * must be done using updateFunctions because of the requirement
348: * to evaluate summary functions only once per row.
349: */
350: public void update(String inputColumnName, String inputColumnValue)
351: throws tinySQLException {
352: int i;
353: tsColumn argColumn;
354: if (isConstant | inputColumnName == (String) null)
355: return;
356: if (inputColumnName.trim().length() == 0)
357: return;
358: if (functionName == (String) null) {
359: /*
360: * Only update the * column once per row.
361: */
362: if (name.equals("*") & valueSet)
363: return;
364: if (inputColumnName.equals(name) | name.equals("*")) {
365: if (tinySQLGlobals.DEBUG)
366: System.out.println("Set " + contextToString()
367: + " column " + name + " = "
368: + inputColumnValue.trim());
369: /*
370: * If this is a simple column value, reset to null before
371: * trying to interpret the inputColumnValue.
372: */
373: valueSet = true;
374: notNull = false;
375: stringValue = (String) null;
376: intValue = Integer.MIN_VALUE;
377: floatValue = Float.MIN_VALUE;
378: /*
379: * Empty string will be interpreted as nulls
380: */
381: if (inputColumnValue == (String) null)
382: return;
383: if (inputColumnValue.trim().length() == 0)
384: return;
385: notNull = true;
386: if (type == Types.CHAR | type == Types.DATE
387: | type == -1) {
388: stringValue = inputColumnValue;
389: } else if (type == Types.INTEGER & notNull) {
390: try {
391: intValue = Integer.parseInt(inputColumnValue
392: .trim());
393: } catch (Exception ex) {
394: throw new tinySQLException(inputColumnValue
395: + " is not an integer.");
396: }
397: } else if (type == Types.FLOAT & notNull) {
398: try {
399: floatValue = Float.valueOf(
400: inputColumnValue.trim()).floatValue();
401: } catch (Exception ex) {
402: throw new tinySQLException(inputColumnValue
403: + " is not a Float.");
404: }
405: }
406: }
407: } else {
408: /*
409: * Update the function arguments.
410: */
411: for (i = 0; i < functionArgs.size(); i++) {
412: argColumn = (tsColumn) functionArgs.elementAt(i);
413: argColumn.update(inputColumnName, inputColumnValue);
414: }
415: }
416: }
417:
418: /*
419: * This method evaluates the value of functions. This step must be kept
420: * separate from the update of individual columns to prevent evaluation
421: * of summary functions such as COUNT and SUM more than once, or when
422: * the row being processed will ultimately fail a where clause condition.
423: */
424: public void updateFunctions() throws tinySQLException {
425: int i, startAt, charCount, day, monthAt, month, year;
426: tsColumn argColumn;
427: StringBuffer concatBuffer;
428: FieldTokenizer ft;
429: String[] ftFields;
430: String months = "-JAN-FEB-MAR-APR-MAY-JUN-JUL-AUG-SEP-OCT-NOV-DEC-", monthName, dayField, monthField, yearField;
431: if (isConstant)
432: return;
433: if (functionName == (String) null)
434: return;
435: if (functionName.equals("CONCAT")) {
436: concatBuffer = new StringBuffer();
437: for (i = 0; i < functionArgs.size(); i++) {
438: argColumn = (tsColumn) functionArgs.elementAt(i);
439: argColumn.updateFunctions();
440: if (argColumn.isValueSet())
441: valueSet = true;
442: if (argColumn.notNull) {
443: concatBuffer.append(argColumn.getString());
444: notNull = true;
445: }
446: }
447: stringValue = concatBuffer.toString();
448: } else if (functionName.equals("UPPER")) {
449: argColumn = (tsColumn) functionArgs.elementAt(0);
450: argColumn.updateFunctions();
451: if (argColumn.isValueSet())
452: valueSet = true;
453: if (argColumn.notNull) {
454: stringValue = argColumn.getString().toUpperCase();
455: notNull = true;
456: }
457: } else if (functionName.equals("TRIM")) {
458: argColumn = (tsColumn) functionArgs.elementAt(0);
459: argColumn.updateFunctions();
460: if (argColumn.isValueSet())
461: valueSet = true;
462: if (argColumn.notNull) {
463: stringValue = argColumn.getString().trim();
464: notNull = true;
465: }
466: } else if (functionName.equals("SUBSTR")) {
467: if (functionArgs.size() != 3)
468: throw new tinySQLException(
469: "Wrong number of arguments for SUBSTR");
470: argColumn = (tsColumn) functionArgs.elementAt(1);
471: startAt = argColumn.intValue;
472: argColumn = (tsColumn) functionArgs.elementAt(2);
473: charCount = argColumn.intValue;
474: argColumn = (tsColumn) functionArgs.elementAt(0);
475: argColumn.updateFunctions();
476: if (argColumn.isValueSet())
477: valueSet = true;
478: if (argColumn.notNull) {
479: stringValue = argColumn.stringValue;
480: if (startAt < stringValue.length() - 1 & charCount > 0) {
481: stringValue = stringValue.substring(startAt - 1,
482: startAt + charCount - 1);
483: notNull = true;
484: } else {
485: stringValue = (String) null;
486: }
487: }
488: } else if (functionName.equals("COUNT")) {
489: argColumn = (tsColumn) functionArgs.elementAt(0);
490: argColumn.updateFunctions();
491: /*
492: * The COUNT function always returns a not null value
493: */
494: notNull = true;
495: valueSet = true;
496: if (intValue == Integer.MIN_VALUE) {
497: intValue = 0;
498: } else {
499: intValue = intValue + 1;
500: }
501: } else if (functionName.equals("TO_DATE")) {
502: /*
503: * Validate the TO_DATE argument
504: */
505: argColumn = (tsColumn) functionArgs.elementAt(0);
506: argColumn.updateFunctions();
507: if (argColumn.isValueSet())
508: valueSet = true;
509: type = Types.DATE;
510: size = 10;
511: if (argColumn.notNull) {
512: stringValue = argColumn.getString().trim();
513: ft = new FieldTokenizer(stringValue, '-', false);
514: ftFields = ft.getFields();
515: if (ftFields.length < 3) {
516: throw new tinySQLException(stringValue
517: + " is not a date with "
518: + "format DD-MON-YY!");
519: } else {
520: try {
521: day = Integer.parseInt(ftFields[0]);
522: if (day < 1 | day > 31)
523: throw new tinySQLException(stringValue
524: + " day not " + "between 1 and 31.");
525: monthName = ftFields[1].toUpperCase();
526: monthAt = months.indexOf("-" + monthName + "-");
527: if (monthAt == -1)
528: throw new tinySQLException(stringValue
529: + " month not " + "recognized.");
530: month = (monthAt + 4) / 4;
531: year = Integer.parseInt(ftFields[2]);
532: if (year < 0 | year > 2100)
533: throw new tinySQLException(stringValue
534: + " year not " + "recognized.");
535: /*
536: * Assume that years < 50 are in the 21st century, otherwise
537: * the 20th.
538: */
539: if (year < 50) {
540: year = 2000 + year;
541: } else if (year < 100) {
542: year = 1900 + year;
543: }
544: dayField = Integer.toString(day);
545: if (dayField.length() < 2)
546: dayField = "0" + dayField;
547: monthField = Integer.toString(month);
548: if (monthField.length() < 2)
549: monthField = "0" + monthField;
550: yearField = Integer.toString(year);
551: stringValue = yearField + "-" + monthField
552: + "-" + dayField;
553: } catch (Exception dayEx) {
554: throw new tinySQLException(stringValue
555: + " exception " + dayEx.getMessage());
556: }
557: }
558: notNull = true;
559: }
560: } else if (functionName.equals("SUM")) {
561: argColumn = (tsColumn) functionArgs.elementAt(0);
562: argColumn.updateFunctions();
563: if (argColumn.isValueSet())
564: valueSet = true;
565: if (argColumn.type == Types.CHAR
566: | argColumn.type == Types.DATE)
567: throw new tinySQLException(argColumn.name
568: + " is not numeric!");
569: if (argColumn.notNull) {
570: notNull = true;
571: if (floatValue == Float.MIN_VALUE) {
572: floatValue = (float) 0.0;
573: } else {
574: if (argColumn.type == Types.INTEGER)
575: floatValue += new Integer(argColumn.intValue)
576: .floatValue();
577: else
578: floatValue += argColumn.floatValue;
579: }
580: }
581: } else if (functionName.equals("MAX")
582: | functionName.equals("MIN")) {
583: argColumn = (tsColumn) functionArgs.elementAt(0);
584: argColumn.updateFunctions();
585: if (argColumn.isValueSet())
586: valueSet = true;
587: if (argColumn.notNull) {
588: notNull = true;
589: if (argColumn.type == Types.CHAR
590: | argColumn.type == Types.DATE) {
591: if (stringValue == null) {
592: stringValue = argColumn.stringValue;
593: } else {
594: /*
595: * Update the max and min based upon string comparisions.
596: */
597: if (functionName.equals("MAX")
598: & (argColumn.stringValue
599: .compareTo(stringValue) > 0)) {
600: stringValue = argColumn.stringValue;
601: } else if (functionName.equals("MIN")
602: & (argColumn.stringValue
603: .compareTo(stringValue) < 0)) {
604: stringValue = argColumn.stringValue;
605: }
606: }
607: } else if (argColumn.type == Types.INTEGER) {
608: /*
609: * Update max and min based upon numeric values.
610: */
611: if (intValue == Integer.MIN_VALUE) {
612: intValue = argColumn.intValue;
613: } else {
614: if (functionName.equals("MIN")
615: & argColumn.intValue < intValue)
616: intValue = argColumn.intValue;
617: else if (functionName.equals("MAX")
618: & argColumn.intValue > intValue)
619: intValue = argColumn.intValue;
620: }
621: } else if (argColumn.type == Types.FLOAT) {
622: if (floatValue == Float.MIN_VALUE) {
623: floatValue = argColumn.floatValue;
624: } else {
625: if (functionName.equals("MIN")
626: & argColumn.floatValue < floatValue)
627: floatValue = argColumn.floatValue;
628: else if (functionName.equals("MAX")
629: & argColumn.floatValue > floatValue)
630: floatValue = argColumn.floatValue;
631: }
632: }
633: }
634: }
635: }
636:
637: public boolean isGroupedColumn() {
638: return groupedColumn;
639: }
640:
641: public boolean isValueSet() {
642: return valueSet;
643: }
644:
645: public boolean isNotNull() {
646: return notNull;
647: }
648:
649: public boolean isNull() {
650: return !notNull;
651: }
652:
653: /*
654: * The following function compares this column to the input using
655: * a "like" comparison using % as the wildcard.
656: */
657: public boolean like(tsColumn inputColumn) throws tinySQLException {
658: FieldTokenizer ft;
659: String nextField, firstField, lastField;
660: boolean like;
661: int foundAt;
662: if (!Utils.isCharColumn(type)
663: | !Utils.isCharColumn(inputColumn.type))
664: throw new tinySQLException("Column " + name + " or "
665: + inputColumn.name + " is not character.");
666: ft = new FieldTokenizer(inputColumn.stringValue, '%', true);
667: like = true;
668: foundAt = 0;
669: firstField = (String) null;
670: lastField = (String) null;
671: while (ft.hasMoreFields()) {
672: nextField = ft.nextField();
673: lastField = nextField;
674: /*
675: * If the first matching field is not the wildcare character
676: * then the test field must start with this string.
677: */
678: if (firstField == (String) null) {
679: firstField = nextField;
680: if (!firstField.equals("%")
681: & !stringValue.startsWith(firstField)) {
682: like = false;
683: break;
684: }
685: }
686: if (!nextField.equals("%")) {
687: if (stringValue.indexOf(nextField, foundAt) < 0) {
688: like = false;
689: break;
690: }
691: foundAt = stringValue.indexOf(nextField, foundAt) + 1;
692: }
693: }
694: if (!lastField.equals("%") & !stringValue.endsWith(lastField))
695: like = false;
696: if (tinySQLGlobals.DEBUG)
697: System.out.println("Is " + getString() + " like "
698: + inputColumn.getString() + " ? " + like);
699: return like;
700: }
701:
702: public Object clone() throws CloneNotSupportedException {
703: return super .clone();
704: }
705:
706: public int compareTo(Object inputObj) throws tinySQLException {
707: String this String, inputString, this YMD, inputYMD;
708: tsColumn inputColumn;
709: tsRow inputRow;
710: int i, inputType, returnValue;
711: double this Value, inputValue;
712: inputColumn = (tsColumn) inputObj;
713: inputType = inputColumn.type;
714: this Value = Double.MIN_VALUE;
715: inputValue = Double.MIN_VALUE;
716: returnValue = 0;
717: if (Utils.isCharColumn(type)) {
718: /*
719: * Compare character types.
720: */
721: if (!Utils.isCharColumn(inputType)) {
722: throw new tinySQLException("Type mismatch between "
723: + getString() + " and "
724: + inputColumn.getString());
725: } else if (stringValue == (String) null
726: | inputColumn.stringValue == (String) null) {
727: throw new tinySQLException("One of the values is NULL");
728: } else {
729: returnValue = stringValue
730: .compareTo(inputColumn.stringValue);
731: }
732: } else if (Utils.isDateColumn(type)) {
733: /*
734: * Compare date types.
735: */
736: if (!Utils.isDateColumn(inputType)) {
737: throw new tinySQLException("Type mismatch between "
738: + getString() + " and "
739: + inputColumn.getString());
740: } else if (stringValue == (String) null
741: | inputColumn.stringValue == (String) null) {
742: throw new tinySQLException("One of the values is NULL");
743: } else {
744: inputYMD = UtilString
745: .toStandardDate(inputColumn.stringValue);
746: this YMD = UtilString.toStandardDate(stringValue);
747: returnValue = this YMD.compareTo(inputYMD);
748: }
749: } else if (Utils.isNumberColumn(type)) {
750: if (type == Types.INTEGER)
751: this Value = (double) intValue;
752: else if (type == Types.FLOAT)
753: this Value = (double) floatValue;
754: if (inputType == Types.INTEGER)
755: inputValue = (double) inputColumn.intValue;
756: else if (inputType == Types.FLOAT)
757: inputValue = (double) inputColumn.floatValue;
758: if (this Value > inputValue)
759: returnValue = 1;
760: else if (this Value < inputValue)
761: returnValue = -1;
762: } else {
763: System.out.println("Cannot sort unknown type");
764: }
765: if (tinySQLGlobals.DEBUG)
766: System.out.println("Comparing " + getString() + " to "
767: + inputColumn.getString() + " gave " + returnValue);
768: return returnValue;
769: }
770:
771: public void addContext(String inputContext) {
772: if (inputContext != (String) null) {
773: contextList.addElement(inputContext);
774: }
775: }
776:
777: /*
778: * This method checks to see if the column has the specified context.
779: */
780: public String contextToString() {
781: StringBuffer outputBuffer = new StringBuffer();
782: int i;
783: for (i = 0; i < contextList.size(); i++) {
784: if (i > 0)
785: outputBuffer.append(",");
786: outputBuffer.append((String) contextList.elementAt(i));
787: }
788: return outputBuffer.toString();
789: }
790:
791: /*
792: * This method returns the list of contexts as a string
793: */
794: public boolean getContext(String inputContext) {
795: String nextContext;
796: int i;
797: for (i = 0; i < contextList.size(); i++) {
798: nextContext = (String) contextList.elementAt(i);
799: if (nextContext == (String) null)
800: continue;
801: if (nextContext.equals(inputContext))
802: return true;
803: }
804: return false;
805: }
806:
807: /*
808: * This method returns the value of the column as a string
809: */
810: public String getString() {
811: if (!notNull)
812: return "null";
813: if (type == Types.CHAR | type == Types.DATE | type == -1) {
814: return stringValue;
815: } else if (type == Types.INTEGER) {
816: if (intValue == Integer.MIN_VALUE)
817: return (String) null;
818: return Integer.toString(intValue);
819: } else if (type == Types.FLOAT) {
820: if (floatValue == Float.MIN_VALUE)
821: return (String) null;
822: return Float.toString(floatValue);
823: }
824: return (String) null;
825: }
826:
827: public String toString() {
828: int i;
829: StringBuffer outputBuffer = new StringBuffer();
830: if (functionName == (String) null) {
831: outputBuffer.append("-----------------------------------"
832: + newLine + "Column Name: " + name + newLine
833: + "Table: " + tableName + newLine + "IsNotNull: "
834: + notNull + newLine + "valueSet: " + valueSet
835: + newLine + "IsConstant: " + isConstant + newLine
836: + "Type: " + type + newLine + "Size: " + size
837: + newLine + "Context: " + contextToString()
838: + newLine + "Value: " + getString());
839: } else {
840: outputBuffer.append("Function: " + functionName + newLine
841: + "IsNotNull: " + notNull + newLine + "Type: "
842: + type + newLine + "Size: " + size + newLine
843: + "Value: " + getString());
844: for (i = 0; i < functionArgs.size(); i++) {
845: outputBuffer.append(newLine
846: + "Argument "
847: + i
848: + " follows"
849: + newLine
850: + ((tsColumn) functionArgs.elementAt(i))
851: .toString() + newLine);
852: }
853: }
854: return outputBuffer.toString();
855: }
856: }
|