KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > Library


1 /* Copyright (c) 1995-2000, The Hypersonic SQL Group.
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the Hypersonic SQL Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * This software consists of voluntary contributions made by many individuals
31  * on behalf of the Hypersonic SQL Group.
32  *
33  *
34  * For work added by the HSQL Development Group:
35  *
36  * Copyright (c) 2001-2005, The HSQL Development Group
37  * All rights reserved.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions are met:
41  *
42  * Redistributions of source code must retain the above copyright notice, this
43  * list of conditions and the following disclaimer.
44  *
45  * Redistributions in binary form must reproduce the above copyright notice,
46  * this list of conditions and the following disclaimer in the documentation
47  * and/or other materials provided with the distribution.
48  *
49  * Neither the name of the HSQL Development Group nor the names of its
50  * contributors may be used to endorse or promote products derived from this
51  * software without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
54  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
57  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
60  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
61  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64  */

65
66
67 package org.hsqldb;
68
69 import java.sql.Connection JavaDoc;
70 import java.sql.Date JavaDoc;
71 import java.sql.Time JavaDoc;
72 import java.sql.Timestamp JavaDoc;
73 import java.text.FieldPosition JavaDoc;
74 import java.text.SimpleDateFormat JavaDoc;
75 import java.util.Calendar JavaDoc;
76 import java.util.Locale JavaDoc;
77 import java.util.Random JavaDoc;
78
79 import org.hsqldb.lib.HashMap;
80 import org.hsqldb.lib.IntValueHashMap;
81 import org.hsqldb.persist.HsqlDatabaseProperties;
82 import org.hsqldb.store.ValuePool;
83
84 // fredt@users 20020210 - patch 513005 by sqlbob@users (RMP) - ABS function
85
// fredt@users 20020305 - patch 1.7.0 - change to 2D string arrays
86
// sqlbob@users 20020420- patch 1.7.0 - added HEXTORAW and RAWTOHEX.
87
// boucherb@user 20020918 - doc 1.7.2 - added JavaDoc and code comments
88
// fredt@user 20021021 - doc 1.7.2 - modified JavaDoc
89
// boucherb@users 20030201 - patch 1.7.2 - direct calls for org.hsqldb.Library
90
// fredt@users - patch 1.8.0 - new functions added
91

92 /**
93  * fredt - todo - since the introduction of SQL built-in functions and
94  * evaluation of several session-dependent methods outside this class,
95  * several methods here are dummies. These methods are still reported in
96  * system tables incorrectly as corresponding to the SQL function names.
97  */

98
99 /**
100  * Provides the HSQLDB implementation of standard Open Group SQL CLI
101  * <em>Extended Scalar Functions</em> and other public HSQLDB SQL functions.<p>
102  *
103  * All methods here that have a Connection parameter are dummies and should
104  * not be called from user supplied Java procedure or trigger code. Use real
105  * SQL functions should be called instead in these instances.
106  *
107  * Extensively rewritten and extended in successive versions of HSQLDB.
108  *
109  * @author Thomas Mueller (Hypersonic SQL Group)
110  * @version 1.8.0
111  * @since Hypersonic SQL
112  */

113 public class Library {
114
115     static final SimpleDateFormat JavaDoc tocharFormat = new SimpleDateFormat JavaDoc();
116     static final SimpleDateFormat JavaDoc daynameFormat = new SimpleDateFormat JavaDoc("EEEE",
117         Locale.ENGLISH);
118     static final SimpleDateFormat JavaDoc monthnameFormat =
119         new SimpleDateFormat JavaDoc("MMMM", Locale.ENGLISH);
120     static final StringBuffer JavaDoc daynameBuffer = new StringBuffer JavaDoc();
121     static final StringBuffer JavaDoc monthnameBuffer = new StringBuffer JavaDoc();
122     static final FieldPosition JavaDoc monthPosition =
123         new FieldPosition JavaDoc(SimpleDateFormat.MONTH_FIELD);
124     static final FieldPosition JavaDoc dayPosition =
125         new FieldPosition JavaDoc(SimpleDateFormat.DAY_OF_WEEK_FIELD);
126     public static final String JavaDoc[][] sNumeric = {
127         {
128             "ABS", "org.hsqldb.Library.abs"
129         }, {
130             "ACOS", "java.lang.Math.acos"
131         }, {
132             "ASIN", "java.lang.Math.asin"
133         }, {
134             "ATAN", "java.lang.Math.atan"
135         }, {
136             "ATAN2", "java.lang.Math.atan2"
137         }, {
138             "CEILING", "java.lang.Math.ceil"
139         }, {
140             "COS", "java.lang.Math.cos"
141         }, {
142             "COT", "org.hsqldb.Library.cot"
143         }, {
144             "DEGREES", "java.lang.Math.toDegrees"
145         }, {
146             "EXP", "java.lang.Math.exp"
147         }, {
148             "FLOOR", "java.lang.Math.floor"
149         }, {
150             "LOG", "java.lang.Math.log"
151         }, {
152             "LOG10", "org.hsqldb.Library.log10"
153         }, {
154             "MOD", "org.hsqldb.Library.mod"
155         }, {
156             "PI", "org.hsqldb.Library.pi"
157         }, {
158             "POWER", "java.lang.Math.pow"
159         }, {
160             "RADIANS", "java.lang.Math.toRadians"
161         }, {
162             "RAND", "java.lang.Math.random"
163         }, {
164             "ROUND", "org.hsqldb.Library.round"
165         }, {
166             "SIGN", "org.hsqldb.Library.sign"
167         }, {
168             "SIN", "java.lang.Math.sin"
169         }, {
170             "SQRT", "java.lang.Math.sqrt"
171         }, {
172             "TAN", "java.lang.Math.tan"
173         }, {
174             "TRUNCATE", "org.hsqldb.Library.truncate"
175         }, {
176             "BITAND", "org.hsqldb.Library.bitand"
177         }, {
178             "BITOR", "org.hsqldb.Library.bitor"
179         }, {
180             "BITXOR", "org.hsqldb.Library.bitxor"
181         }, {
182             "ROUNDMAGIC", "org.hsqldb.Library.roundMagic"
183         }
184     };
185
186 // fredt@users 20010701 - patch 418023 by deforest@users
187
// the definition for SUBSTR was added
188
public static final String JavaDoc[][] sString = {
189         {
190             "ASCII", "org.hsqldb.Library.ascii"
191         }, {
192             "BIT_LENGTH", "org.hsqldb.Library.bitLength"
193         }, {
194             "CHAR", "org.hsqldb.Library.character"
195         }, {
196             "CHAR_LENGTH", "org.hsqldb.Library.length"
197         }, {
198             "CHARACTER_LENGTH", "org.hsqldb.Library.length"
199         }, {
200             "CONCAT", "org.hsqldb.Library.concat"
201         }, {
202             "DIFFERENCE", "org.hsqldb.Library.difference"
203         }, {
204             "HEXTORAW", "org.hsqldb.Library.hexToRaw"
205         }, {
206             "INSERT", "org.hsqldb.Library.insert"
207         }, {
208             "LCASE", "org.hsqldb.Library.lcase"
209         }, {
210             "LEFT", "org.hsqldb.Library.left"
211         }, {
212             "LENGTH", "org.hsqldb.Library.length"
213         }, {
214             "LOCATE", "org.hsqldb.Library.locate"
215         }, {
216             "LTRIM", "org.hsqldb.Library.ltrim"
217         }, {
218             "OCTET_LENGTH", "org.hsqldb.Library.octetLength"
219         }, {
220             "RAWTOHEX", "org.hsqldb.Library.rawToHex"
221         }, {
222             "REPEAT", "org.hsqldb.Library.repeat"
223         }, {
224             "REPLACE", "org.hsqldb.Library.replace"
225         }, {
226             "RIGHT", "org.hsqldb.Library.right"
227         }, {
228             "RTRIM", "org.hsqldb.Library.rtrim"
229         }, {
230             "SOUNDEX", "org.hsqldb.Library.soundex"
231         }, {
232             "SPACE", "org.hsqldb.Library.space"
233         }, {
234             "SUBSTR", "org.hsqldb.Library.substring"
235         }, {
236             "SUBSTRING", "org.hsqldb.Library.substring"
237         }, {
238             "UCASE", "org.hsqldb.Library.ucase"
239         }, {
240             "LOWER", "org.hsqldb.Library.lcase"
241         }, {
242             "UPPER", "org.hsqldb.Library.ucase"
243         }
244     };
245     public static final String JavaDoc[][] sTimeDate = {
246         {
247             "CURDATE", "org.hsqldb.Library.curdate"
248         }, {
249             "CURTIME", "org.hsqldb.Library.curtime"
250         }, {
251             "DATEDIFF", "org.hsqldb.Library.datediff"
252         }, {
253             "DAYNAME", "org.hsqldb.Library.dayname"
254         }, {
255             "DAY", "org.hsqldb.Library.dayofmonth"
256         }, {
257             "DAYOFMONTH", "org.hsqldb.Library.dayofmonth"
258         }, {
259             "DAYOFWEEK", "org.hsqldb.Library.dayofweek"
260         }, {
261             "DAYOFYEAR", "org.hsqldb.Library.dayofyear"
262         }, {
263             "HOUR", "org.hsqldb.Library.hour"
264         }, {
265             "MINUTE", "org.hsqldb.Library.minute"
266         }, {
267             "MONTH", "org.hsqldb.Library.month"
268         }, {
269             "MONTHNAME", "org.hsqldb.Library.monthname"
270         }, {
271             "NOW", "org.hsqldb.Library.now"
272         }, {
273             "QUARTER", "org.hsqldb.Library.quarter"
274         }, {
275             "SECOND", "org.hsqldb.Library.second"
276         }, {
277             "WEEK", "org.hsqldb.Library.week"
278         }, {
279             "YEAR", "org.hsqldb.Library.year"
280         }, {
281             "TO_CHAR", "org.hsqldb.Library.to_char"
282         }
283     };
284     public static final String JavaDoc[][] sSystem = {
285         {
286             "DATABASE", "org.hsqldb.Library.database"
287         }, {
288             "USER", "org.hsqldb.Library.user"
289         }, {
290             "IDENTITY", "org.hsqldb.Library.identity"
291         }
292     };
293
294     private Library() {}
295
296     static HashMap getAliasMap() {
297
298         HashMap h = new HashMap(83, 1);
299
300         register(h, sNumeric);
301         register(h, sString);
302         register(h, sTimeDate);
303         register(h, sSystem);
304
305         return h;
306     }
307
308     private static void register(HashMap h, String JavaDoc[][] s) {
309
310         for (int i = 0; i < s.length; i++) {
311             h.put(s[i][0], s[i][1]);
312         }
313     }
314
315     private static final Random JavaDoc rRandom = new Random JavaDoc();
316
317     // NUMERIC FUNCTIONS
318
// fredt@users 20020220 - patch 489184 by xclayl@users - thread safety
319

320     /**
321      * Returns the next pseudorandom, uniformly distributed <code>double</code> value
322      * between 0.0 and 1.0 from a single, system-wide random number generator's
323      * sequence, optionally re-seeding (and thus resetting) the generator sequence.
324      *
325      * If the seed value is <code>null</code>, then the underlying random number
326      * generator retrieves the next value in its current sequence, else the seed
327      * alters the state of the generator object so as to be in exactly the same state
328      * as if it had just been created with the seed value.
329      * @param seed an optional parameter with which to reseed the underlying
330      * pseudorandom number generator
331      * @return the next pseudorandom, uniformly distributed <code>double</code> value between
332      * 0.0 and 1.0
333      */

334     public static double rand(Integer JavaDoc seed) {
335
336         // boucherb@users 20020918
337
// CHECKME: perhaps rRandom should be a member of Session,
338
// since otherwise connections are *not* guranteed to get the
339
// same pseudorandom sequence, given the same set of calls to this
340
// SQL function. This makes comparitive analysis difficult.
341
// In fact, rRandom will be shared across multiple in-process
342
// database instances, so it is not even guaranteed that the
343
// sole connection to one instance will get the same sequence given
344
// the same set of calls to this SQL function.
345
synchronized (rRandom) {
346             if (seed != null) {
347                 rRandom.setSeed(seed.intValue());
348             }
349
350             return rRandom.nextDouble();
351         }
352     }
353
354     /**
355      * Returns the absolute value of the given <code>double</code> value.
356      * @param d the number for which to determine the absolute value
357      * @return the absolute value of <code>d</code>, as a <code>double</code>
358      */

359     public static double abs(double d) {
360         return Math.abs(d);
361     }
362
363     // this magic number works for 100000000000000; but not for 0.1 and 0.01
364
private static final double LOG10_FACTOR = 0.43429448190325183;
365
366     /**
367      * Returns the base 10 logarithm of the given <code>double</code> value.
368      * @param x the value for which to calculate the base 10 logarithm
369      * @return the base 10 logarithm of <code>x</code>, as a <code>double</code>
370      */

371     public static double log10(double x) {
372         return roundMagic(Math.log(x) * LOG10_FACTOR);
373     }
374
375     /**
376      * Retrieves a <em>magically</em> rounded </code>double</code> value produced
377      * from the given <code>double</code> value. This method provides special
378      * handling for numbers close to zero and performs rounding only for
379      * numbers within a specific range, returning precisely the given value
380      * if it does not lie in this range. <p>
381      *
382      * Special handling includes: <p>
383      *
384      * <UL>
385      * <LI> input in the interval -0.0000000000001..0.0000000000001 returns 0.0
386      * <LI> input outside the interval -1000000000000..1000000000000 returns
387      * input unchanged
388      * <LI> input is converted to String form
389      * <LI> input with a <code>String</code> form length greater than 16 returns
390      * input unchaged
391      * <LI> <code>String</code> form with last four characters of '...000x' where
392      * x != '.' is converted to '...0000'
393      * <LI> <code>String</code> form with last four characters of '...9999' is
394      * converted to '...999999'
395      * <LI> the <code>java.lang.Double.doubleValue</code> of the <code>String</code>
396      * form is returned
397      * </UL>
398      * @param d the double value for which to retrieve the <em>magically</em>
399      * rounded value
400      * @return the <em>magically</em> rounded value produced
401      */

402     public static double roundMagic(double d) {
403
404         // this function rounds numbers in a good way but slow:
405
// - special handling for numbers around 0
406
// - only numbers <= +/-1000000000000
407
// - convert to a string
408
// - check the last 4 characters:
409
// '000x' becomes '0000'
410
// '999x' becomes '999999' (this is rounded automatically)
411
if ((d < 0.0000000000001) && (d > -0.0000000000001)) {
412             return 0.0;
413         }
414
415         if ((d > 1000000000000.) || (d < -1000000000000.)) {
416             return d;
417         }
418
419         StringBuffer JavaDoc s = new StringBuffer JavaDoc();
420
421         s.append(d);
422
423         int len = s.length();
424
425         if (len < 16) {
426             return d;
427         }
428
429         char cx = s.charAt(len - 1);
430         char c1 = s.charAt(len - 2);
431         char c2 = s.charAt(len - 3);
432         char c3 = s.charAt(len - 4);
433
434         if ((c1 == '0') && (c2 == '0') && (c3 == '0') && (cx != '.')) {
435             s.setCharAt(len - 1, '0');
436         } else if ((c1 == '9') && (c2 == '9') && (c3 == '9') && (cx != '.')) {
437             s.setCharAt(len - 1, '9');
438             s.append('9');
439             s.append('9');
440         }
441
442         return Double.valueOf(s.toString()).doubleValue();
443     }
444
445     /**
446      * Returns the cotangent of the given <code>double</code> value
447      * expressed in radians.
448      * @param d the angle, expressed in radians
449      * @return the cotangent
450      */

451     public static double cot(double d) {
452         return 1. / Math.tan(d);
453     }
454
455     /**
456      * Returns the remainder (modulus) of the first given integer divided
457      * by the second. <p>
458      *
459      * @param i1 the numerator
460      * @param i2 the divisor
461      * @return <code>i1</code> % <code>i2</code>, as an <code>int</code>
462      */

463     public static int mod(int i1, int i2) {
464         return i1 % i2;
465     }
466
467     /**
468      * Returns the constant value, pi.
469      * @return pi as a <code>double</code> value
470      */

471     public static double pi() {
472         return Math.PI;
473     }
474
475     /**
476      * Returns the given <code>double</code> value, rounded to the given
477      * <code>int</code> places right of the decimal point. If
478      * the supplied rounding place value is negative, rounding is performed
479      * to the left of the decimal point, using its magnitude (absolute value).
480      * @param d the value to be rounded
481      * @param p the rounding place value
482      * @return <code>d</code> rounded
483      */

484     public static double round(double d, int p) {
485
486         double f = Math.pow(10., p);
487
488         return Math.round(d * f) / f;
489     }
490
491     /**
492      * Returns an indicator of the sign of the given <code>double</code>
493      * value. If the value is less than zero, -1 is returned. If the value
494      * equals zero, 0 is returned. If the value is greater than zero, 1 is
495      * returned.
496      * @param d the value
497      * @return the sign of <code>d</code>
498      */

499     public static int sign(double d) {
500
501         return (d < 0) ? -1
502                        : ((d > 0) ? 1
503                                   : 0);
504     }
505
506     /**
507      * Returns the given <code>double</code> value, truncated to
508      * the given <code>int</code> places right of the decimal point.
509      * If the given place value is negative, the given <code>double</code>
510      * value is truncated to the left of the decimal point, using the
511      * magnitude (aboslute value) of the place value.
512      * @param d the value to truncate
513      * @param p the places left or right of the decimal point at which to
514      * truncate
515      * @return <code>d</code>, truncated
516      */

517     public static double truncate(double d, int p) {
518
519         double f = Math.pow(10., p);
520         double g = d * f;
521
522         return ((d < 0) ? Math.ceil(g)
523                         : Math.floor(g)) / f;
524     }
525
526     /**
527      * Returns the bit-wise logical <em>and</em> of the given
528      * integer values.
529      * @param i the first value
530      * @param j the second value
531      * @return the bit-wise logical <em>and</em> of
532      * <code>i</code> and <code>j</code>
533      */

534     public static int bitand(int i, int j) {
535         return i & j;
536     }
537
538     /**
539      * Returns the bit-wise logical <em>or</em> of the given
540      * integer values.
541      *
542      * @param i the first value
543      * @param j the second value
544      * @return the bit-wise logical <em>or</em> of
545      * <code>i</code> and <code>j</code>
546      */

547     public static int bitor(int i, int j) {
548         return i | j;
549     }
550
551     /**
552      * Returns the bit-wise logical <em>xor</em> of the given
553      * integer values.
554      *
555      * @param i the first value
556      * @param j the second value
557      * @return the bit-wise logical <em>xor</em> of
558      * <code>i</code> and <code>j</code>
559      *
560      * @since 1.8.0
561      */

562     public static int bitxor(int i, int j) {
563         return i ^ j;
564     }
565
566     // STRING FUNCTIONS
567

568     /**
569      * Returns the Unicode code value of the leftmost character of
570      * <code>s</code> as an <code>int</code>. This is the same as the
571      * ASCII value if the string contains only ASCII characters.
572      * @param s the <code>String</code> to evaluate
573      * @return the integer Unicode value of the
574      * leftmost character
575      */

576     public static Integer JavaDoc ascii(String JavaDoc s) {
577
578         if ((s == null) || (s.length() == 0)) {
579             return null;
580         }
581
582         return ValuePool.getInt(s.charAt(0));
583     }
584
585     /**
586      * Returns the character string corresponding to the given ASCII
587      * (or Unicode) value.
588      *
589      * <b>Note:</b> <p>
590      *
591      * In some SQL CLI
592      * implementations, a <code>null</code> is returned if the range is outside 0..255.
593      * In HSQLDB, the corresponding Unicode character is returned
594      * unchecked.
595      * @param code the character code for which to return a String
596      * representation
597      * @return the String representation of the character
598      */

599     public static String JavaDoc character(int code) {
600         return String.valueOf((char) code);
601     }
602
603     /**
604      * Returns a <code>String</code> object that is the result of an
605      * concatenation of the given <code>String</code> objects. <p>
606      *
607      * <b>When only one string is NULL, the result is different from that
608      * returned by an (string1 || string2) expression:
609      *
610      * <UL>
611      * <LI> if both <code>String</code> objects are <code>null</code>, return
612      * <code>null</code>
613      * <LI> if only one string is <code>null</code>, return the other
614      * <LI> if both <code>String</code> objects are non-null, return as a
615      * <code>String</code> object the character sequence obtained by listing,
616      * in left to right order, the characters of the first string followed by
617      * the characters of the second
618      * </UL>
619      * @param s1 the first <code>String</code>
620      * @param s2 the second <code>String</code>
621      * @return <code>s1</code> concatentated with <code>s2</code>
622      */

623     public static String JavaDoc concat(String JavaDoc s1, String JavaDoc s2) {
624
625         if (s1 == null) {
626             if (s2 == null) {
627                 return null;
628             }
629
630             return s2;
631         }
632
633         if (s2 == null) {
634             return s1;
635         }
636
637         return s1.concat(s2);
638     }
639
640     /**
641      * Returns a count of the characters that do not match when comparing
642      * the 4 digit numeric SOUNDEX character sequences for the
643      * given <code>String</code> objects. If either <code>String</code> object is
644      * <code>null</code>, zero is returned.
645      * @param s1 the first <code>String</code>
646      * @param s2 the second <code>String</code>
647      * @return the number of differences between the <code>SOUNDEX</code> of
648      * <code>s1</code> and the <code>SOUNDEX</code> of <code>s2</code>
649      */

650
651 // fredt@users 20020305 - patch 460907 by fredt - soundex
652
public static int difference(String JavaDoc s1, String JavaDoc s2) {
653
654         // todo: check if this is the standard algorithm
655
if ((s1 == null) || (s2 == null)) {
656             return 0;
657         }
658
659         s1 = soundex(s1);
660         s2 = soundex(s2);
661
662         int e = 0;
663
664         for (int i = 0; i < 4; i++) {
665             if (s1.charAt(i) != s2.charAt(i)) {
666                 e++;
667             }
668         }
669
670         return e;
671     }
672
673     /**
674      * Converts a <code>String</code> of hexidecimal digit characters to a raw
675      * binary value, represented as a <code>String</code>.<p>
676      *
677      * The given <code>String</code> object must consist of a sequence of
678      * 4 digit hexidecimal character substrings.<p> If its length is not
679      * evenly divisible by 4, <code>null</code> is returned. If any of
680      * its 4 character subsequences cannot be parsed as a
681      * 4 digit, base 16 value, then a NumberFormatException is thrown.
682      *
683      * This conversion has the effect of reducing the character count 4:1.
684      *
685      * @param s a <code>String</code> of hexidecimal digit characters
686      * @return an equivalent raw binary value, represented as a
687      * <code>String</code>
688      */

689     public static String JavaDoc hexToRaw(String JavaDoc s) {
690
691         if (s == null) {
692             return null;
693         }
694
695         char raw;
696         StringBuffer JavaDoc to = new StringBuffer JavaDoc();
697         int len = s.length();
698
699         if (len % 4 != 0) {
700             return null;
701         }
702
703         for (int i = 0; i < len; i += 4) {
704             raw = (char) Integer.parseInt(s.substring(i, i + 4), 16);
705
706             to.append(raw);
707         }
708
709         return (to.toString());
710     }
711
712     /**
713      * Returns a character sequence which is the result of writing the
714      * first <code>length</code> number of characters from the second
715      * given <code>String</code> over the first string. The start position
716      * in the first string where the characters are overwritten is given by
717      * <code>start</code>.<p>
718      *
719      * <b>Note:</b> In order of precedence, boundry conditions are handled as
720      * follows:<p>
721      *
722      * <UL>
723      * <LI>if either supplied <code>String</code> is null, then the other is
724      * returned; the check starts with the first given <code>String</code>.
725      * <LI>if <code>start</code> is less than one, <code>s1</code> is returned
726      * <LI>if <code>length</code> is less than or equal to zero,
727      * <code>s1</code> is returned
728      * <LI>if the length of <code>s2</code> is zero, <code>s1</code> is returned
729      * <LI>if <code>start</code> is greater than the length of <code>s1</code>,
730      * <code>s1</code> is returned
731      * <LI>if <code>length</code> is such that, taken together with
732      * <code>start</code>, the indicated interval extends
733      * beyond the end of <code>s1</code>, then the insertion is performed
734      * precisely as if upon a copy of <code>s1</code> extended in length
735      * to just include the indicated interval
736      * </UL>
737      * @param s1 the <code>String</code> into which to insert <code>s2</code>
738      * @param start the position, with origin one, at which to start the insertion
739      * @param length the number of characters in <code>s1</code> to replace
740      * @param s2 the <code>String</code> to insert into <code>s1</code>
741      * @return <code>s2</code> inserted into <code>s1</code>, as indicated
742      * by <code>start</code> and <code>length</code> and adjusted for
743      * boundry conditions
744      */

745     public static String JavaDoc insert(String JavaDoc s1, int start, int length, String JavaDoc s2) {
746
747         if (s1 == null) {
748             return s2;
749         }
750
751         if (s2 == null) {
752             return s1;
753         }
754
755         int len1 = s1.length();
756         int len2 = s2.length();
757
758         start--;
759
760         if (start < 0 || length <= 0 || len2 == 0 || start > len1) {
761             return s1;
762         }
763
764         if (start + length > len1) {
765             length = len1 - start;
766         }
767
768         return s1.substring(0, start) + s2 + s1.substring(start + length);
769     }
770
771     /**
772      * Returns a copy of the given <code>String</code>, with all upper case
773      * characters converted to lower case. This uses the default Java String
774      * conversion.
775      * @param s the <code>String</code> from which to produce a lower case
776      * version
777      * @return a lower case version of <code>s</code>
778      */

779     public static String JavaDoc lcase(String JavaDoc s) {
780         return (s == null) ? null
781                            : s.toLowerCase();
782     }
783
784     /**
785      * Returns the leftmost <code>count</code> characters from the given
786      * <code>String</code>. <p>
787      *
788      * <b>Note:</b> boundry conditions are handled in the following order of
789      * precedence:
790      *
791      * <UL>
792      * <LI> if <code>s</code> is <code>null</code>, then <code>null</code>
793      * is returned
794      * <LI> if <code>count</code> is less than 1, then a zero-length
795      * <code>String</code> is returned
796      * <LI> if <code>count</code> is greater than the length of <code>s</code>,
797      * then a copy of <code>s</code> is returned
798      * </UL>
799      * @param s the <code>String</code> from which to retrieve the leftmost
800      * characters
801      * @param count the count of leftmost characters to retrieve
802      * @return the leftmost <code>count</code> characters of <code>s</code>
803      */

804     public static String JavaDoc left(String JavaDoc s, int count) {
805
806         if (s == null) {
807             return null;
808         }
809
810         return s.substring(0, ((count < 0) ? 0
811                                            : (count < s.length()) ? count
812                                                                   : s.length()));
813     }
814
815 // fredt@users - 20020819 - patch 595854 by thomasm@users
816

817     /**
818      * Returns the number of characters in the given <code>String</code>.
819      * This includes trailing blanks.
820      *
821      * @param s the <code>String</code> for which to determine length
822      * @return the length of <code>s</code>, including trailing blanks
823      */

824     public static Integer JavaDoc length(String JavaDoc s) {
825         return s == null ? null
826                          : ValuePool.getInt(s.length());
827     }
828
829     /**
830      * Returns the number of bytes in the given <code>String</code>.
831      * This includes trailing blanks.
832      *
833      * @param s the <code>String</code> for which to determine the octet length
834      * @return the octet length of <code>s</code>, including trailing blanks
835      * @since 1.7.2
836      */

837     public static Integer JavaDoc octetLength(String JavaDoc s) {
838         return s == null ? null
839                          : ValuePool.getInt(s.length() * 2);
840     }
841
842     /**
843      * Returns the number of bits in the given <code>String</code>.
844      * This includes trailing blanks.
845      *
846      * @param s the <code>String</code> for which to determine the bit length
847      * @return the bit length of <code>s</code>, including trailing blanks
848      * @since 1.7.2
849      */

850     public static Integer JavaDoc bitLength(String JavaDoc s) {
851         return s == null ? null
852                          : ValuePool.getInt(s.length() * 16);
853     }
854
855     /**
856      * Returns the starting position of the first occurrence of
857      * the given <code>search</code> <code>String</code> object within
858      * the given <code>String</code> object, <code>s</code>.
859      *
860      * The search for the first occurrence of <code>search</code> begins with
861      * the first character position in <code>s</code>, unless the optional
862      * argument, <code>start</code>, is specified (non-null). If
863      * <code>start</code> is specified, the search begins with the character
864      * position indicated by the value of <code>start</code>, where the
865      * first character position in <code>s</code> is indicated by the value 1.
866      * If <code>search</code> is not found within <code>s</code>, the
867      * value 0 is returned.
868      * @param search the <code>String</code> occurence to find in <code>s</code>
869      * @param s the <code>String</code> within which to find the first
870      * occurence of <code>search</code>
871      * @param start the optional character position from which to start
872      * looking in <code>s</code>
873      * @return the one-based starting position of the first occurrence of
874      * <code>search</code> within <code>s</code>, or 0 if not found
875      */

876     public static int locate(String JavaDoc search, String JavaDoc s, Integer JavaDoc start) {
877
878         if (s == null || search == null) {
879             return 0;
880         }
881
882         int i = (start == null) ? 0
883                                 : start.intValue() - 1;
884
885         return s.indexOf(search, (i < 0) ? 0
886                                          : i) + 1;
887     }
888
889     /**
890      * As locate but from start position l. <p>
891      *
892      * @param search the <code>String</code> occurence to find in <code>s</code>
893      * @param s the <code>String</code> within which to find the first
894      * occurence of <code>search</code>
895      * @return the one-based starting position of the first occurrence of
896      * <code>search</code> within <code>s</code>, or 0 if not found
897      */

898     public static int position(String JavaDoc search, String JavaDoc s) {
899         return locate(search, s, null);
900     }
901
902     /**
903      * Returns the characters of the given <code>String</code>, with the
904      * leading spaces removed. Characters such as TAB are not removed.
905      *
906      * @param s the <code>String</code> from which to remove the leading blanks
907      * @return the characters of the given <code>String</code>, with the leading
908      * spaces removed
909      */

910     public static String JavaDoc ltrim(String JavaDoc s) {
911
912         if (s == null) {
913             return s;
914         }
915
916         int len = s.length(),
917             i = 0;
918
919         while (i < len && s.charAt(i) <= ' ') {
920             i++;
921         }
922
923         return (i == 0) ? s
924                         : s.substring(i);
925     }
926
927     /**
928      * Converts a raw binary value, as represented by the given
929      * <code>String</code>, to the equivalent <code>String</code>
930      * of hexidecimal digit characters. <p>
931      *
932      * This conversion has the effect of expanding the character count 1:4.
933      *
934      * @param s the raw binary value, as a <code>String</code>
935      * @return an equivalent <code>String</code> of hexidecimal digit characters
936      */

937     public static String JavaDoc rawToHex(String JavaDoc s) {
938
939         if (s == null) {
940             return null;
941         }
942
943         char[] from = s.toCharArray();
944         String JavaDoc hex;
945         StringBuffer JavaDoc to = new StringBuffer JavaDoc(4 * s.length());
946
947         for (int i = 0; i < from.length; i++) {
948             hex = Integer.toHexString(from[i] & 0xffff);
949
950             for (int j = hex.length(); j < 4; j++) {
951                 to.append('0');
952             }
953
954             to.append(hex);
955         }
956
957         return (to.toString());
958     }
959
960     /**
961      * Returns a <code>String</code> composed of the given <code>String</code>,
962      * repeated <code>count</code> times.
963      *
964      * @param s the <code>String</code> to repeat
965      * @param count the number of repetitions
966      * @return the given <code>String</code>, repeated <code>count</code> times
967      */

968     public static String JavaDoc repeat(String JavaDoc s, Integer JavaDoc count) {
969
970         if (s == null || count == null || count.intValue() < 0) {
971             return null;
972         }
973
974         int i = count.intValue();
975         StringBuffer JavaDoc b = new StringBuffer JavaDoc(s.length() * i);
976
977         while (i-- > 0) {
978             b.append(s);
979         }
980
981         return b.toString();
982     }
983
984 // fredt@users - 20020903 - patch 1.7.1 - bug fix to allow multiple replaces
985

986     /**
987      * Replaces all occurrences of <code>replace</code> in <code>s</code>
988      * with the <code>String</code> object: <code>with</code>
989      * @param s the target for replacement
990      * @param replace the substring(s), if any, in <code>s</code> to replace
991      * @param with the value to substitute for <code>replace</code>
992      * @return <code>s</code>, with all occurences of <code>replace</code>
993      * replaced by <code>with</code>
994      */

995     public static String JavaDoc replace(String JavaDoc s, String JavaDoc replace, String JavaDoc with) {
996
997         if (s == null || replace == null) {
998             return s;
999         }
1000
1001        if (with == null) {
1002            with = "";
1003        }
1004
1005        StringBuffer JavaDoc b = new StringBuffer JavaDoc();
1006        int start = 0;
1007        int lenreplace = replace.length();
1008
1009        while (true) {
1010            int i = s.indexOf(replace, start);
1011
1012            if (i == -1) {
1013                b.append(s.substring(start));
1014
1015                break;
1016            }
1017
1018            b.append(s.substring(start, i));
1019            b.append(with);
1020
1021            start = i + lenreplace;
1022        }
1023
1024        return b.toString();
1025    }
1026
1027    /**
1028     * Returns the rightmost <code>count</code> characters of the given
1029     * <code>String</code>, <code>s</code>. <p>
1030     *
1031     * <b>Note:</b> boundry conditions are handled in the following order of
1032     * precedence: <p>
1033     *
1034     * <UL>
1035     * <LI> if <code>s</code> is <code>null</code>, <code>null</code> is returned
1036     * <LI> if <code>count</code> is less than one, a zero-length
1037     * <code>String</code> is returned
1038     * <LI> if <code>count</code> is greater than the length of <code>s</code>,
1039     * a copy of <code>s</code> is returned
1040     * </UL>
1041     * @param s the <code>String</code> from which to retrieve the rightmost
1042     * <code>count</code> characters
1043     * @param count the number of rightmost characters to retrieve
1044     * @return the rightmost <code>count</code> characters of <code>s</code>
1045     */

1046    public static String JavaDoc right(String JavaDoc s, int count) {
1047
1048        if (s == null) {
1049            return null;
1050        }
1051
1052        count = s.length() - count;
1053
1054        return s.substring((count < 0) ? 0
1055                                       : (count < s.length()) ? count
1056                                                              : s.length());
1057    }
1058
1059// fredt@users 20020530 - patch 1.7.0 fredt - trim only the space character
1060

1061    /**
1062     * Returns the characters of the given <code>String</code>, with trailing
1063     * spaces removed.
1064     * @param s the <code>String</code> from which to remove the trailing blanks
1065     * @return the characters of the given <code>String</code>, with the
1066     * trailing spaces removed
1067     */

1068    public static String JavaDoc rtrim(String JavaDoc s) {
1069
1070        if (s == null) {
1071            return s;
1072        }
1073
1074        int endindex = s.length() - 1;
1075        int i = endindex;
1076
1077        for (; i >= 0 && s.charAt(i) == ' '; i--) {}
1078
1079        return i == endindex ? s
1080                             : s.substring(0, i + 1);
1081    }
1082
1083    /**
1084     * Returns the character sequence <code>s</code>, with the leading,
1085     * trailing or both the leading and trailing occurences of the first
1086     * character of the character sequence <code>trimstr</code> removed. <p>
1087     *
1088     * This method is in support of the standard SQL String function TRIM.
1089     * Ordinarily, the functionality of this method is accessed from SQL using
1090     * the following syntax: <p>
1091     *
1092     * <pre class="SqlCodeExample">
1093     * &lt;trim function&gt; ::= TRIM &lt;left paren&gt; &lt;trim operands&gt; &lt;right paren&gt;
1094     * &lt;trim operands&gt; ::= [ [ &lt;trim specification&gt; ] [ &lt;trim character&gt; ] FROM ] &lt;trim source&gt;
1095     * &lt;trim source&gt; ::= &lt;character value expression&gt;
1096     * &lt;trim specification&gt; ::= LEADING | TRAILING | BOTH
1097     * &lt;trim character&gt; ::= &lt;character value expression&gt;
1098     * </pre>
1099     *
1100     * @param s the string to trim
1101     * @param trimstr the character whose occurences will be removed
1102     * @param leading if true, remove leading occurences
1103     * @param trailing if true, remove trailing occurences
1104     * @return s, with the leading, trailing or both the leading and trailing
1105     * occurences of the first character of <code>trimstr</code> removed
1106     * @since 1.7.2
1107     */

1108    public static String JavaDoc trim(String JavaDoc s, String JavaDoc trimstr, boolean leading,
1109                              boolean trailing) {
1110
1111        if (s == null) {
1112            return s;
1113        }
1114
1115        int trim = trimstr.charAt(0);
1116        int endindex = s.length();
1117
1118        if (trailing) {
1119            for (--endindex; endindex >= 0 && s.charAt(endindex) == trim;
1120                    endindex--) {}
1121
1122            endindex++;
1123        }
1124
1125        if (endindex == 0) {
1126            return "";
1127        }
1128
1129        int startindex = 0;
1130
1131        if (leading) {
1132            while (startindex < endindex && s.charAt(startindex) == trim) {
1133                startindex++;
1134            }
1135        }
1136
1137        if (startindex == 0 && endindex == s.length()) {
1138            return s;
1139        } else {
1140            return s.substring(startindex, endindex);
1141        }
1142    }
1143
1144// fredt@users 20011010 - patch 460907 by fredt - soundex
1145

1146    /**
1147     * Returns a four character code representing the sound of the given
1148     * <code>String</code>. Non-ASCCI characters in the
1149     * input <code>String</code> are ignored. <p>
1150     *
1151     * This method was
1152     * rewritten for HSQLDB by fredt@users to comply with the description at
1153     * <a HREF="http://www.nara.gov/genealogy/coding.html">
1154     * http://www.nara.gov/genealogy/coding.html</a>.<p>
1155     * @param s the <code>String</code> for which to calculate the 4 character
1156     * <code>SOUNDEX</code> value
1157     * @return the 4 character <code>SOUNDEX</code> value for the given
1158     * <code>String</code>
1159     */

1160    public static String JavaDoc soundex(String JavaDoc s) {
1161
1162        if (s == null) {
1163            return s;
1164        }
1165
1166        s = s.toUpperCase(Locale.ENGLISH);
1167
1168        int len = s.length();
1169        char[] b = new char[] {
1170            '0', '0', '0', '0'
1171        };
1172        char lastdigit = '0';
1173
1174        for (int i = 0, j = 0; i < len && j < 4; i++) {
1175            char c = s.charAt(i);
1176            char newdigit;
1177
1178            if ("AEIOUY".indexOf(c) != -1) {
1179                newdigit = '7';
1180            } else if (c == 'H' || c == 'W') {
1181                newdigit = '8';
1182            } else if ("BFPV".indexOf(c) != -1) {
1183                newdigit = '1';
1184            } else if ("CGJKQSXZ".indexOf(c) != -1) {
1185                newdigit = '2';
1186            } else if (c == 'D' || c == 'T') {
1187                newdigit = '3';
1188            } else if (c == 'L') {
1189                newdigit = '4';
1190            } else if (c == 'M' || c == 'N') {
1191                newdigit = '5';
1192            } else if (c == 'R') {
1193                newdigit = '6';
1194            } else {
1195                continue;
1196            }
1197
1198            if (j == 0) {
1199                b[j++] = c;
1200                lastdigit = newdigit;
1201            } else if (newdigit <= '6') {
1202                if (newdigit != lastdigit) {
1203                    b[j++] = newdigit;
1204                    lastdigit = newdigit;
1205                }
1206            } else if (newdigit == '7') {
1207                lastdigit = newdigit;
1208            }
1209        }
1210
1211        return new String JavaDoc(b, 0, 4);
1212    }
1213
1214    /**
1215     * Returns a <code>String</code> consisting of <code>count</code> spaces, or
1216     * <code>null</code> if <code>count</code> is less than zero. <p>
1217     *
1218     * @param count the number of spaces to produce
1219     * @return a <code>String</code> of <code>count</code> spaces
1220     */

1221    public static String JavaDoc space(int count) {
1222
1223        if (count < 0) {
1224            return null;
1225        }
1226
1227        char[] c = new char[count];
1228
1229        while (count > 0) {
1230            c[--count] = ' ';
1231        }
1232
1233        return new String JavaDoc(c);
1234    }
1235
1236    /**
1237     * Returns the characters from the given <code>String</code>, starting at
1238     * the indicated one-based <code>start</code> position and extending the
1239     * (optional) indicated <code>length</code>. If <code>length</code> is not
1240     * specified (is <code>null</code>), the remainder of <code>s</code> is
1241     * implied.
1242     *
1243     * The rules for boundary conditions on s, start and length are,
1244     * in order of precedence: <p>
1245     *
1246     * 1.) if s is null, return null
1247     *
1248     * 2.) If length is less than 1, return null.
1249     *
1250     * 3.) If start is 0, it is treated as 1.
1251     *
1252     * 4.) If start is positive, count from the beginning of s to find
1253     * the first character postion.
1254     *
1255     * 5.) If start is negative, count backwards from the end of s
1256     * to find the first character.
1257     *
1258     * 6.) If, after applying 2.) or 3.), the start position lies outside s,
1259     * then return null
1260     *
1261     * 7.) if length is ommited or is greated than the number of characters
1262     * from the start position to the end of s, return the remaineder of s,
1263     * starting with the start position.
1264     *
1265     * @param s the <code>String</code> from which to produce the indicated
1266     * substring
1267     * @param start the starting position of the desired substring
1268     * @param length the length of the desired substring
1269     * @return the indicted substring of <code>s</code>.
1270     */

1271
1272// fredt@users 20020210 - patch 500767 by adjbirch@users - modified
1273
// boucherb@users 20050205 - patch to correct bug 1107477
1274
public static String JavaDoc substring(final String JavaDoc s, int start,
1275                                   final Integer JavaDoc length) {
1276
1277        if (s == null) {
1278            return null;
1279        }
1280
1281        int sl = s.length();
1282        int ol = (length == null) ? sl
1283                                  : length.intValue();
1284
1285        if (ol < 1) {
1286            return null;
1287        }
1288
1289        if (start < 0) {
1290            start = sl + start;
1291        } else if (start > 0) {
1292            start--;
1293        }
1294
1295        if (start < 0 || start >= sl) {
1296            return null;
1297        } else if (start > sl - ol) {
1298            ol = sl - start;
1299        }
1300
1301        return s.substring(start, start + ol);
1302    }
1303
1304    /**
1305     * Returns a copy of the given <code>String</code>, with all lower case
1306     * characters converted to upper case using the default Java method.
1307     * @param s the <code>String</code> from which to produce an upper case
1308     * version
1309     * @return an upper case version of <code>s</code>
1310     */

1311    public static String JavaDoc ucase(String JavaDoc s) {
1312        return (s == null) ? null
1313                           : s.toUpperCase();
1314    }
1315
1316    // TIME AND DATE
1317

1318    /**
1319     * Returns the current date as a date value. <p>
1320     *
1321     * Dummy mehtod.<p>
1322     *
1323     * @return a date value representing the current date
1324     */

1325    public static Date JavaDoc curdate(Connection JavaDoc c) {
1326        return null;
1327    }
1328
1329    /**
1330     * Returns the current local time as a time value. <p>
1331     *
1332     * Dummy mehtod.<p>
1333     *
1334     * @return a time value representing the current local time
1335     */

1336    public static Time JavaDoc curtime(Connection JavaDoc c) {
1337        return null;
1338    }
1339
1340    /**
1341     * Returns a character string containing the name of the day
1342     * (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday )
1343     * for the day portion of the given <code>java.sql.Date</code>.
1344     * @param d the date value from which to extract the day name
1345     * @return the name of the day corresponding to the given
1346     * <code>java.sql.Date</code>
1347     */

1348    public static String JavaDoc dayname(Date JavaDoc d) {
1349
1350        if (d == null) {
1351            return null;
1352        }
1353
1354        synchronized (daynameBuffer) {
1355            daynameBuffer.setLength(0);
1356
1357            return daynameFormat.format(d, daynameBuffer,
1358                                        dayPosition).toString();
1359        }
1360    }
1361
1362    /**
1363     * Returns the day of the month from the given date value, as an integer
1364     * value in the range of 1-31.
1365     *
1366     * @param d the date value from which to extract the day of month
1367     * @return the day of the month from the given date value
1368     */

1369    public static Integer JavaDoc dayofmonth(Date JavaDoc d) {
1370
1371        if (d == null) {
1372            return null;
1373        }
1374
1375        return ValuePool.getInt(HsqlDateTime.getDateTimePart(d,
1376                Calendar.DAY_OF_MONTH));
1377    }
1378
1379    /**
1380     * Returns the day of the week from the given date value, as an integer
1381     * value in the range 1-7, where 1 represents Sunday.
1382     *
1383     * @param d the date value from which to extract the day of week
1384     * @return the day of the week from the given date value
1385     */

1386    public static Integer JavaDoc dayofweek(Date JavaDoc d) {
1387
1388        if (d == null) {
1389            return null;
1390        }
1391
1392        return ValuePool.getInt(HsqlDateTime.getDateTimePart(d,
1393                Calendar.DAY_OF_WEEK));
1394    }
1395
1396    /**
1397     * Returns the day of the year from the given date value, as an integer
1398     * value in the range 1-366.
1399     *
1400     * @param d the date value from which to extract the day of year
1401     * @return the day of the year from the given date value
1402     */

1403    public static Integer JavaDoc dayofyear(Date JavaDoc d) {
1404
1405        if (d == null) {
1406            return null;
1407        }
1408
1409        return ValuePool.getInt(HsqlDateTime.getDateTimePart(d,
1410                Calendar.DAY_OF_YEAR));
1411    }
1412
1413    /**
1414     * Returns the hour from the given time value, as an integer value in
1415     * the range of 0-23.
1416     *
1417     * @param t the time value from which to extract the hour of day
1418     * @return the hour of day from the given time value
1419     */

1420
1421// fredt@users 20020210 - patch 513005 by sqlbob@users (RMP) - hour
1422
public static Integer JavaDoc hour(Time JavaDoc t) {
1423
1424        if (t == null) {
1425            return null;
1426        }
1427
1428        return ValuePool.getInt(HsqlDateTime.getDateTimePart(t,
1429                Calendar.HOUR_OF_DAY));
1430    }
1431
1432    /**
1433     * Returns the minute from the given time value, as integer value in
1434     * the range of 0-59.
1435     *
1436     * @param t the time value from which to extract the minute value
1437     * @return the minute value from the given time value
1438     */

1439    public static Integer JavaDoc minute(Time JavaDoc t) {
1440
1441        if (t == null) {
1442            return null;
1443        }
1444
1445        return ValuePool.getInt(HsqlDateTime.getDateTimePart(t,
1446                Calendar.MINUTE));
1447    }
1448
1449    /**
1450     * Returns the month from the given date value, as an integer value in the
1451     * range of 1-12. <p>
1452     *
1453     * The sql_month database property is now obsolete.
1454     * The function always returns the SQL (1-12) value for month.
1455     *
1456     * @param d the date value from which to extract the month value
1457     * @return the month value from the given date value
1458     */

1459    public static Integer JavaDoc month(Date JavaDoc d) {
1460
1461        if (d == null) {
1462            return null;
1463        }
1464
1465        return ValuePool.getInt(
1466            HsqlDateTime.getDateTimePart(d, Calendar.MONTH) + 1);
1467    }
1468
1469    /**
1470     * Returns a character string containing the name of month
1471     * (January, February, March, April, May, June, July, August,
1472     * September, October, November, December) for the month portion of
1473     * the given date value.
1474     *
1475     * @param d the date value from which to extract the month name
1476     * @return a String representing the month name from the given date value
1477     */

1478    public static String JavaDoc monthname(Date JavaDoc d) {
1479
1480        if (d == null) {
1481            return null;
1482        }
1483
1484        synchronized (monthnameBuffer) {
1485            monthnameBuffer.setLength(0);
1486
1487            return monthnameFormat.format(d, monthnameBuffer,
1488                                          monthPosition).toString();
1489        }
1490    }
1491
1492    /**
1493     * Returns the current date and time as a timestamp value. <p>
1494     *
1495     * Dummy mehtod.<p>
1496     *
1497     * @return a timestamp value representing the current date and time
1498     */

1499    public static Timestamp JavaDoc now(Connection JavaDoc c) {
1500        return null;
1501    }
1502
1503    /**
1504     * Returns the quarter of the year in the given date value, as an integer
1505     * value in the range of 1-4. <p>
1506     *
1507     * @param d the date value from which to extract the quarter of the year
1508     * @return an integer representing the quater of the year from the given
1509     * date value
1510     */

1511    public static Integer JavaDoc quarter(Date JavaDoc d) {
1512
1513        if (d == null) {
1514            return null;
1515        }
1516
1517        return ValuePool.getInt(
1518            (HsqlDateTime.getDateTimePart(d, Calendar.MONTH) / 3) + 1);
1519    }
1520
1521    /**
1522     * Returns the second of the given time value, as an integer value in
1523     * the range of 0-59.
1524     *
1525     * @param d the date value from which to extract the second of the hour
1526     * @return an integer representing the second of the hour from the
1527     * given time value
1528     */

1529    public static Integer JavaDoc second(Time JavaDoc d) {
1530
1531        if (d == null) {
1532            return null;
1533        }
1534
1535        return ValuePool.getInt(HsqlDateTime.getDateTimePart(d,
1536                Calendar.SECOND));
1537    }
1538
1539    /**
1540     * Returns the week of the year from the given date value, as an integer
1541     * value in the range of 1-53. <p>
1542     *
1543     * @param d the date value from which to extract the week of the year
1544     * @return an integer representing the week of the year from the given
1545     * date value
1546     */

1547    public static Integer JavaDoc week(Date JavaDoc d) {
1548
1549        if (d == null) {
1550            return null;
1551        }
1552
1553        return ValuePool.getInt(HsqlDateTime.getDateTimePart(d,
1554                Calendar.WEEK_OF_YEAR));
1555    }
1556
1557    /**
1558     * Returns the year from the given date value, as an integer value in
1559     * the range of 1-9999. <p>
1560     *
1561     * @param d the date value from which to extract the year
1562     * @return an integer value representing the year from the given
1563     * date value
1564     */

1565    public static Integer JavaDoc year(Date JavaDoc d) {
1566
1567        if (d == null) {
1568            return null;
1569        }
1570
1571        return ValuePool.getInt(HsqlDateTime.getDateTimePart(d,
1572                Calendar.YEAR));
1573    }
1574
1575    /**
1576     * @since 1.8.0
1577     */

1578    public static String JavaDoc to_char(java.util.Date JavaDoc d, String JavaDoc format) {
1579
1580        if (d == null || format == null) {
1581            return null;
1582        }
1583
1584        synchronized (tocharFormat) {
1585            tocharFormat.applyPattern(HsqlDateTime.toJavaDatePattern(format));
1586
1587            return tocharFormat.format(d);
1588        }
1589    }
1590
1591    // date calculations.
1592

1593    /**
1594     * Returns the number of units elapsed between two dates.<p>
1595     * The datapart parameter indicates the part to be used for computing the
1596     * difference. Supported types include: 'year', 'yy', 'month', 'mm'
1597     * 'day', 'dd', 'hour', 'hh', 'minute', 'mi', 'second', 'ss', 'millisecond',
1598     * 'ms'.
1599     *
1600     * Contributed by Michael Landon<p>
1601     *
1602     * @param datepart Specifies the unit in which the interval is to be measured.
1603     * @param d1 The starting datetime value for the interval. This value is
1604     * subtracted from d2 to return the number of
1605     * date-parts between the two arguments.
1606     * @param d2 The ending datetime for the interval. d1 is subtracted
1607     * from this value to return the number of date-parts
1608     * between the two arguments.
1609     *
1610     * since 1.7.3
1611     */

1612    public static Long JavaDoc datediff(String JavaDoc datepart, Timestamp JavaDoc d1,
1613                                Timestamp JavaDoc d2) throws HsqlException {
1614
1615        // make sure we've got valid data
1616
if (d1 == null || d2 == null) {
1617            return null;
1618        }
1619
1620        if ("yy".equalsIgnoreCase(datepart)
1621                || "year".equalsIgnoreCase(datepart)) {
1622            return ValuePool.getLong(getElapsed(Calendar.YEAR, d1, d2));
1623        } else if ("mm".equalsIgnoreCase(datepart)
1624                   || "month".equalsIgnoreCase(datepart)) {
1625            return ValuePool.getLong(getElapsed(Calendar.MONTH, d1, d2));
1626        } else if ("dd".equalsIgnoreCase(datepart)
1627                   || "day".equalsIgnoreCase(datepart)) {
1628            return ValuePool.getLong(getElapsed(Calendar.DATE, d1, d2));
1629        } else if ("hh".equalsIgnoreCase(datepart)
1630                   || "hour".equalsIgnoreCase(datepart)) {
1631            return ValuePool.getLong(getElapsed(Calendar.HOUR, d1, d2));
1632        } else if ("mi".equalsIgnoreCase(datepart)
1633                   || "minute".equalsIgnoreCase(datepart)) {
1634            return ValuePool.getLong(getElapsed(Calendar.MINUTE, d1, d2));
1635        } else if ("ss".equalsIgnoreCase(datepart)
1636                   || "second".equalsIgnoreCase(datepart)) {
1637            return ValuePool.getLong(getElapsed(Calendar.SECOND, d1, d2));
1638        } else if ("ms".equalsIgnoreCase(datepart)
1639                   || "millisecond".equalsIgnoreCase(datepart)) {
1640            return ValuePool.getLong(getElapsed(Calendar.MILLISECOND, d1,
1641                                                d2));
1642        } else {
1643            throw Trace.error(Trace.INVALID_CONVERSION);
1644        }
1645    }
1646
1647    /**
1648     * Private method used to do actual calculation units elapsed between
1649     * two given dates. <p>
1650     *
1651     * @param field Calendar field to use to calculate elapsed time
1652     * @param d1 The starting date for the interval. This value is
1653     * subtracted from d2 to return the number of
1654     * date-parts between the two arguments.
1655     * @param d2 The ending date for the interval. d1 is subtracted
1656     * from this value to return the number of date-parts
1657     * between the two arguments.
1658     */

1659    private static long getElapsed(int field, java.util.Date JavaDoc d1,
1660                                   java.util.Date JavaDoc d2) {
1661
1662        // can we do this very simply?
1663
if (field == Calendar.MILLISECOND) {
1664            return d2.getTime() - d1.getTime();
1665        }
1666
1667        // ok, let's work a little harder:
1668
Calendar JavaDoc g1 = Calendar.getInstance(),
1669                 g2 = Calendar.getInstance();
1670
1671        g1.setTime(d1);
1672        g2.setTime(d2);
1673        g1.set(Calendar.MILLISECOND, 0);
1674        g2.set(Calendar.MILLISECOND, 0);
1675
1676        if (field == Calendar.SECOND) {
1677            return (g2.getTime().getTime() - g1.getTime().getTime()) / 1000;
1678        }
1679
1680        g1.set(Calendar.SECOND, 0);
1681        g2.set(Calendar.SECOND, 0);
1682
1683        if (field == Calendar.MINUTE) {
1684            return (g2.getTime().getTime() - g1.getTime().getTime())
1685                   / (1000 * 60);
1686        }
1687
1688        g1.set(Calendar.MINUTE, 0);
1689        g2.set(Calendar.MINUTE, 0);
1690
1691        if (field == Calendar.HOUR) {
1692            return (g2.getTime().getTime() - g1.getTime().getTime())
1693                   / (1000 * 60 * 60);
1694        } // end if-else
1695

1696        // if we got here, then we really need to work:
1697
long elapsed = 0;
1698        short sign = 1;
1699
1700        if (g2.before(g1)) {
1701            sign = -1;
1702
1703            Calendar JavaDoc tmp = g1;
1704
1705            g1 = g2;
1706            g2 = tmp;
1707        } // end if
1708

1709        g1.set(Calendar.HOUR_OF_DAY, 0);
1710        g2.set(Calendar.HOUR_OF_DAY, 0);
1711
1712        if (field == Calendar.MONTH || field == Calendar.YEAR) {
1713            g1.set(Calendar.DATE, 1);
1714            g2.set(Calendar.DATE, 1);
1715        }
1716
1717        if (field == Calendar.YEAR) {
1718            g1.set(Calendar.MONTH, 1);
1719            g2.set(Calendar.MONTH, 1);
1720        } // end if-else
1721

1722        // then calculate elapsed units
1723
while (g1.before(g2)) {
1724            g1.add(field, 1);
1725
1726            elapsed++;
1727        }
1728
1729        return sign * elapsed;
1730    } // end getElapsed
1731

1732    // SYSTEM
1733
/*
1734     * All system functions that return Session dependent information are
1735     * dummies here.
1736     */

1737
1738    /**
1739     * Returns the name of the database corresponding to this connection.
1740     *
1741     * @param conn the connection for which to retrieve the database name
1742     * @return the name of the database for the given connection
1743     * @throws HsqlException if a database access error occurs
1744     */

1745    public static String JavaDoc database(Connection JavaDoc conn) throws HsqlException {
1746        return null;
1747    }
1748
1749    /**
1750     * Returns the user's authorization name (the user's name as known to this
1751     * database).
1752     *
1753     * @param conn the connection for which to retrieve the user name
1754     * @return the user's name as known to the database
1755     * @throws HsqlException if a database access error occurs
1756     */

1757    public static String JavaDoc user(Connection JavaDoc conn) throws HsqlException {
1758        return null;
1759    }
1760
1761    /**
1762     * Retrieves the last auto-generated integer indentity value
1763     * used by this connection. <p>
1764     *
1765     * Dummy mehtod.<p>
1766     *
1767     * @return the connection's the last generated integer identity value
1768     * @throws HsqlException if a database access error occurs
1769     */

1770    public static int identity() throws HsqlException {
1771        return 0;
1772    }
1773
1774    // JDBC SYSTEM
1775

1776    /**
1777     * Retrieves the autocommit status of this connection. <p>
1778     *
1779     * @param conn the <code>Connection</code> object for which to retrieve
1780     * the current autocommit status
1781     * @return a boolean value representing the connection's autocommit status
1782     * @since 1.7.0
1783     */

1784    public static boolean getAutoCommit(Connection JavaDoc conn) {
1785        return false;
1786    }
1787
1788    /**
1789     * Retrieves the full version number of this database product. <p>
1790     *
1791     * @return database version number as a <code>String</code> object
1792     * @since 1.8.0.4
1793     */

1794    public static String JavaDoc getDatabaseFullProductVersion() {
1795        return HsqlDatabaseProperties.THIS_FULL_VERSION;
1796    }
1797
1798    /**
1799     * Retrieves the name of this database product. <p>
1800     *
1801     * @return database product name as a <code>String</code> object
1802     * @since 1.7.2
1803     */

1804    public static String JavaDoc getDatabaseProductName() {
1805        return HsqlDatabaseProperties.PRODUCT_NAME;
1806    }
1807
1808    /**
1809     * Retrieves the version number of this database product. <p>
1810     *
1811     * @return database version number as a <code>String</code> object
1812     * @since 1.7.2
1813     */

1814    public static String JavaDoc getDatabaseProductVersion() {
1815        return HsqlDatabaseProperties.THIS_VERSION;
1816    }
1817
1818    /**
1819     * Retrieves the major version number of this database. <p>
1820     *
1821     * @return the database's major version as an <code>int</code> value
1822     * @since 1.7.2
1823     */

1824    public static int getDatabaseMajorVersion() {
1825        return HsqlDatabaseProperties.MAJOR;
1826    }
1827
1828    /**
1829     * Retrieves the major version number of this database. <p>
1830     *
1831     * @return the database's major version as an <code>int</code> value
1832     * @since 1.7.2
1833     */

1834    public static int getDatabaseMinorVersion() {
1835        return HsqlDatabaseProperties.MINOR;
1836    }
1837
1838    /**
1839     * Retrieves whether this connection is in read-only mode. <p>
1840     *
1841     * Dummy mehtod.<p>
1842     *
1843     * @param conn the <code>Connection</code> object for which to retrieve
1844     * the current read-only status
1845     * @return <code>true</code> if connection is read-only and
1846     * <code>false</code> otherwise
1847     * @since 1.7.2
1848     */

1849    public static boolean isReadOnlyConnection(Connection JavaDoc conn) {
1850        return false;
1851    }
1852
1853    /**
1854     * Dummy method. Retrieves whether this database is in read-only mode. <p>
1855     *
1856     * @param c the <code>Connection</code> object for which to retrieve
1857     * the current database read-only status
1858     * @return <code>true</code> if so; <code>false</code> otherwise
1859     * @since 1.7.2
1860     */

1861    public static boolean isReadOnlyDatabase(Connection JavaDoc c) {
1862        return false;
1863    }
1864
1865    /**
1866     * Retrieves whether the files of this database are in read-only mode. <p>
1867     *
1868     * Dummy mehtod.<p>
1869     *
1870     * @param c the <code>Connection</code> object for which to retrieve
1871     * the current database files read-only status
1872     * @return <code>true</code> if so; <code>false</code> otherwise
1873     * @since 1.7.2
1874     */

1875    public static boolean isReadOnlyDatabaseFiles(Connection JavaDoc c) {
1876        return false;
1877    }
1878
1879    static final int abs = 0;
1880    static final int ascii = 1;
1881    static final int bitand = 2;
1882    static final int bitLength = 3;
1883    static final int bitor = 4;
1884    static final int bitxor = 5;
1885    static final int character = 6;
1886    static final int concat = 7;
1887    static final int cot = 8;
1888    static final int curdate = 9;
1889    static final int curtime = 10;
1890    static final int database = 11;
1891    static final int datediff = 12;
1892    static final int day = 13;
1893    static final int dayname = 14;
1894    static final int dayofmonth = 15;
1895    static final int dayofweek = 16;
1896    static final int dayofyear = 17;
1897    static final int difference = 18;
1898    static final int getAutoCommit = 19;
1899    static final int getDatabaseFullProductVersion = 20;
1900    static final int getDatabaseMajorVersion = 21;
1901    static final int getDatabaseMinorVersion = 22;
1902    static final int getDatabaseProductName = 23;
1903    static final int getDatabaseProductVersion = 24;
1904    static final int hexToRaw = 25;
1905    static final int hour = 26;
1906    static final int identity = 27;
1907    static final int insert = 28;
1908    static final int isReadOnlyConnection = 29;
1909    static final int isReadOnlyDatabase = 30;
1910    static final int isReadOnlyDatabaseFiles = 31;
1911    static final int lcase = 32;
1912    static final int left = 33;
1913    static final int length = 34;
1914    static final int locate = 35;
1915    static final int log10 = 36;
1916    static final int ltrim = 37;
1917    static final int minute = 38;
1918    static final int mod = 39;
1919    static final int month = 40;
1920    static final int monthname = 41;
1921    static final int now = 42;
1922    static final int octetLength = 43;
1923    static final int pi = 44;
1924    static final int position = 45;
1925    static final int quarter = 46;
1926    static final int rand = 47;
1927    static final int rawToHex = 48;
1928    static final int repeat = 49;
1929    static final int replace = 50;
1930    static final int right = 51;
1931    static final int round = 52;
1932    static final int roundMagic = 53;
1933    static final int rtrim = 54;
1934    static final int second = 55;
1935    static final int sign = 56;
1936    static final int soundex = 57;
1937    static final int space = 58;
1938    static final int substring = 59;
1939    static final int to_char = 60;
1940    static final int trim = 61;
1941    static final int truncate = 62;
1942    static final int ucase = 63;
1943    static final int user = 64;
1944    static final int week = 65;
1945    static final int year = 66;
1946
1947/** @todo see bitxor and datediff numbering */
1948
1949    //
1950
private static final IntValueHashMap functionMap =
1951        new IntValueHashMap(67);
1952    static final Double JavaDoc piValue = new Double JavaDoc(Library.pi());
1953
1954    static {
1955        functionMap.put("abs", abs);
1956        functionMap.put("ascii", ascii);
1957        functionMap.put("bitand", bitand);
1958        functionMap.put("bitlength", bitLength);
1959        functionMap.put("bitor", bitor);
1960        functionMap.put("bitxor", bitor);
1961        functionMap.put("character", character);
1962        functionMap.put("concat", concat);
1963        functionMap.put("cot", cot);
1964        functionMap.put("curdate", curdate);
1965        functionMap.put("curtime", curtime);
1966        functionMap.put("database", database);
1967        functionMap.put("datediff", datediff);
1968        functionMap.put("dayname", dayname);
1969        functionMap.put("day", day);
1970        functionMap.put("dayofmonth", dayofmonth);
1971        functionMap.put("dayofweek", dayofweek);
1972        functionMap.put("dayofyear", dayofyear);
1973        functionMap.put("difference", difference);
1974        functionMap.put("getAutoCommit", getAutoCommit);
1975        functionMap.put("getDatabaseFullProductVersion",
1976                        getDatabaseFullProductVersion);
1977        functionMap.put("getDatabaseMajorVersion", getDatabaseMajorVersion);
1978        functionMap.put("getDatabaseMinorVersion", getDatabaseMinorVersion);
1979        functionMap.put("getDatabaseProductName", getDatabaseProductName);
1980        functionMap.put("getDatabaseProductVersion",
1981                        getDatabaseProductVersion);
1982        functionMap.put("hexToRaw", hexToRaw);
1983        functionMap.put("hour", hour);
1984        functionMap.put("identity", identity);
1985        functionMap.put("insert", insert);
1986        functionMap.put("isReadOnlyConnection", isReadOnlyConnection);
1987        functionMap.put("isReadOnlyDatabase", isReadOnlyDatabase);
1988        functionMap.put("isReadOnlyDatabaseFiles", isReadOnlyDatabaseFiles);
1989        functionMap.put("lcase", lcase);
1990        functionMap.put("left", left);
1991        functionMap.put("length", length);
1992        functionMap.put("locate", locate);
1993        functionMap.put("log10", log10);
1994        functionMap.put("ltrim", ltrim);
1995        functionMap.put("minute", minute);
1996        functionMap.put("mod", mod);
1997        functionMap.put("month", month);
1998        functionMap.put("monthname", monthname);
1999        functionMap.put("now", now);
2000        functionMap.put("octetLength", octetLength);
2001        functionMap.put("pi", pi);
2002        functionMap.put("position", position);
2003        functionMap.put("quarter", quarter);
2004        functionMap.put("rand", rand);
2005        functionMap.put("rawToHex", rawToHex);
2006        functionMap.put("repeat", repeat);
2007        functionMap.put("replace", replace);
2008        functionMap.put("right", right);
2009        functionMap.put("round", round);
2010        functionMap.put("roundMagic", roundMagic);
2011        functionMap.put("rtrim", rtrim);
2012        functionMap.put("second", second);
2013        functionMap.put("sign", sign);
2014        functionMap.put("soundex", soundex);
2015        functionMap.put("space", space);
2016        functionMap.put("substring", substring);
2017        functionMap.put("to_char", to_char);
2018        functionMap.put("trim", trim);
2019        functionMap.put("truncate", truncate);
2020        functionMap.put("ucase", ucase);
2021        functionMap.put("user", user);
2022        functionMap.put("week", week);
2023        functionMap.put("year", year);
2024    }
2025
2026    static Object JavaDoc invoke(int fID, Object JavaDoc[] params) throws HsqlException {
2027
2028        try {
2029            switch (fID) {
2030
2031                case abs : {
2032                    return new Double JavaDoc(
2033                        Library.abs(((Number JavaDoc) params[0]).doubleValue()));
2034                }
2035                case ascii : {
2036                    return ascii((String JavaDoc) params[0]);
2037                }
2038                case bitand : {
2039                    return ValuePool.getInt(
2040                        bitand(((Number JavaDoc) params[0]).intValue(),
2041                               ((Number JavaDoc) params[1]).intValue()));
2042                }
2043                case bitLength : {
2044                    return bitLength((String JavaDoc) params[0]);
2045                }
2046                case bitor : {
2047                    return ValuePool.getInt(
2048                        bitor(((Number JavaDoc) params[0]).intValue(),
2049                              ((Number JavaDoc) params[1]).intValue()));
2050                }
2051                case bitxor : {
2052                    return ValuePool.getInt(
2053                        bitxor(((Number JavaDoc) params[0]).intValue(),
2054                               ((Number JavaDoc) params[1]).intValue()));
2055                }
2056                case character : {
2057                    return character(((Number JavaDoc) params[0]).intValue());
2058                }
2059                case concat : {
2060                    return concat((String JavaDoc) params[0], (String JavaDoc) params[1]);
2061                }
2062                case cot : {
2063                    return new Double JavaDoc(
2064                        cot(((Number JavaDoc) params[0]).doubleValue()));
2065                }
2066                case curdate : {
2067                    return null;
2068                }
2069                case curtime : {
2070                    return null;
2071                }
2072                case database : {
2073                    return null;
2074                }
2075                case datediff : {
2076                    return datediff((String JavaDoc) params[0],
2077                                    (Timestamp JavaDoc) params[1],
2078                                    (Timestamp JavaDoc) params[2]);
2079                }
2080                case dayname : {
2081                    return dayname((Date JavaDoc) params[0]);
2082                }
2083                case dayofmonth :
2084                case day : {
2085                    return dayofmonth((Date JavaDoc) params[0]);
2086                }
2087                case dayofweek : {
2088                    return dayofweek((Date JavaDoc) params[0]);
2089                }
2090                case dayofyear : {
2091                    return dayofyear((Date JavaDoc) params[0]);
2092                }
2093                case difference : {
2094                    return ValuePool.getInt(difference((String JavaDoc) params[0],
2095                                                       (String JavaDoc) params[1]));
2096                }
2097                case getAutoCommit : {
2098                    return null;
2099                }
2100                case getDatabaseFullProductVersion : {
2101                    return getDatabaseFullProductVersion();
2102                }
2103                case getDatabaseMajorVersion : {
2104                    return ValuePool.getInt(getDatabaseMajorVersion());
2105                }
2106                case getDatabaseMinorVersion : {
2107                    return ValuePool.getInt(getDatabaseMinorVersion());
2108                }
2109                case getDatabaseProductName : {
2110                    return getDatabaseProductName();
2111                }
2112                case getDatabaseProductVersion : {
2113                    return getDatabaseProductVersion();
2114                }
2115                case hexToRaw : {
2116                    return hexToRaw((String JavaDoc) params[0]);
2117                }
2118                case hour : {
2119                    return hour((Time JavaDoc) params[0]);
2120                }
2121                case identity : {
2122                    return null;
2123                }
2124                case insert : {
2125                    return insert((String JavaDoc) params[0],
2126                                  ((Number JavaDoc) params[1]).intValue(),
2127                                  ((Number JavaDoc) params[2]).intValue(),
2128                                  (String JavaDoc) params[3]);
2129                }
2130                case isReadOnlyConnection : {
2131                    return null;
2132                }
2133                case isReadOnlyDatabase : {
2134                    return null;
2135                }
2136                case lcase : {
2137                    return lcase((String JavaDoc) params[0]);
2138                }
2139                case left : {
2140                    return left((String JavaDoc) params[0],
2141                                ((Number JavaDoc) params[1]).intValue());
2142                }
2143                case length : {
2144                    return length((String JavaDoc) params[0]);
2145                }
2146                case locate : {
2147                    return ValuePool.getInt(locate((String JavaDoc) params[0],
2148                                                   (String JavaDoc) params[1],
2149                                                   (Integer JavaDoc) params[2]));
2150                }
2151                case log10 : {
2152                    return new Double JavaDoc(
2153                        log10(((Number JavaDoc) params[0]).doubleValue()));
2154                }
2155                case ltrim : {
2156                    return ltrim((String JavaDoc) params[0]);
2157                }
2158                case minute : {
2159                    return minute((Time JavaDoc) params[0]);
2160                }
2161                case mod : {
2162                    return ValuePool.getInt(
2163                        mod(
2164                        ((Number JavaDoc) params[0]).intValue(),
2165                        ((Number JavaDoc) params[1]).intValue()));
2166                }
2167                case month : {
2168                    return month((Date JavaDoc) params[0]);
2169                }
2170                case monthname : {
2171                    return ValuePool.getString(monthname((Date JavaDoc) params[0]));
2172                }
2173                case now : {
2174                    return null;
2175                }
2176                case octetLength : {
2177                    return octetLength((String JavaDoc) params[0]);
2178                }
2179                case position : {
2180                    return ValuePool.getInt(position((String JavaDoc) params[0],
2181                                                     (String JavaDoc) params[1]));
2182                }
2183                case pi : {
2184                    return piValue;
2185                }
2186                case quarter : {
2187                    return quarter((Date JavaDoc) params[0]);
2188                }
2189                case rand : {
2190                    return new Double JavaDoc(rand((Integer JavaDoc) params[0]));
2191                }
2192                case rawToHex : {
2193                    return rawToHex((String JavaDoc) params[0]);
2194                }
2195                case repeat : {
2196                    return repeat((String JavaDoc) params[0], (Integer JavaDoc) params[1]);
2197                }
2198                case replace : {
2199                    return replace((String JavaDoc) params[0], (String JavaDoc) params[1],
2200                                   (String JavaDoc) params[2]);
2201                }
2202                case right : {
2203                    return right((String JavaDoc) params[0],
2204                                 ((Number JavaDoc) params[1]).intValue());
2205                }
2206                case round : {
2207                    return new Double JavaDoc(
2208                        round(((Number JavaDoc) params[0]).doubleValue(),
2209                              ((Number JavaDoc) params[1]).intValue()));
2210                }
2211                case roundMagic : {
2212                    return new Double JavaDoc(
2213                        roundMagic(((Number JavaDoc) params[0]).doubleValue()));
2214                }
2215                case rtrim : {
2216                    return rtrim((String JavaDoc) params[0]);
2217                }
2218                case second : {
2219                    return second((Time JavaDoc) params[0]);
2220                }
2221                case sign : {
2222                    return ValuePool.getInt(
2223                        sign(((Number JavaDoc) params[0]).doubleValue()));
2224                }
2225                case soundex : {
2226                    return soundex((String JavaDoc) params[0]);
2227                }
2228                case space : {
2229                    return space(((Number JavaDoc) params[0]).intValue());
2230                }
2231                case substring : {
2232                    return substring((String JavaDoc) params[0],
2233                                     ((Number JavaDoc) params[1]).intValue(),
2234                                     (Integer JavaDoc) params[2]);
2235                }
2236                case trim : {
2237                    return trim((String JavaDoc) params[0], (String JavaDoc) params[1],
2238                                ((Boolean JavaDoc) params[2]).booleanValue(),
2239                                ((Boolean JavaDoc) params[3]).booleanValue());
2240                }
2241                case truncate : {
2242                    return new Double JavaDoc(
2243                        truncate(
2244                            ((Number JavaDoc) params[0]).doubleValue(),
2245                            ((Number JavaDoc) params[1]).intValue()));
2246                }
2247                case ucase : {
2248                    return ucase((String JavaDoc) params[0]);
2249                }
2250                case user : {
2251                    return null;
2252                }
2253                case week : {
2254                    return week((Date JavaDoc) params[0]);
2255                }
2256                case year : {
2257                    return year((Date JavaDoc) params[0]);
2258                }
2259                case to_char : {
2260                    return to_char((java.util.Date JavaDoc) params[0],
2261                                   (String JavaDoc) params[1]);
2262                }
2263                case isReadOnlyDatabaseFiles : {
2264                    return null;
2265                }
2266                default : {
2267
2268                    // coding error
2269
Trace.doAssert(false);
2270
2271                    return null;
2272                }
2273            }
2274        } catch (Exception JavaDoc e) {
2275            throw Trace.error(Trace.FUNCTION_CALL_ERROR, e.toString());
2276        }
2277    }
2278
2279    static final String JavaDoc prefix = "org.hsqldb.Library.";
2280    static final int prefixLength = prefix.length();
2281
2282    static int functionID(String JavaDoc fname) {
2283
2284        return fname.startsWith(prefix)
2285               ? functionMap.get(fname.substring(prefixLength), -1)
2286               : -1;
2287    }
2288}
2289
Popular Tags