The HSQLDB Library.java source code
/*
* For work developed by the HSQL Development Group:
*
* Copyright (c) 2001-2010, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
*
* For work originally developed by the Hypersonic SQL Group:
*
* Copyright (c) 1995-2000, The Hypersonic SQL Group.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the Hypersonic SQL Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* on behalf of the Hypersonic SQL Group.
*/
package org.hsqldb;
import java.sql.Connection;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.FieldPosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.Random;
import org.hsqldb.lib.HashMap;
import org.hsqldb.lib.IntValueHashMap;
import org.hsqldb.persist.HsqlDatabaseProperties;
import org.hsqldb.store.ValuePool;
// fredt@users 20020210 - patch 513005 by sqlbob@users (RMP) - ABS function
// fredt@users 20020305 - patch 1.7.0 - change to 2D string arrays
// sqlbob@users 20020420- patch 1.7.0 - added HEXTORAW and RAWTOHEX.
// boucherb@user 20020918 - doc 1.7.2 - added JavaDoc and code comments
// fredt@user 20021021 - doc 1.7.2 - modified JavaDoc
// boucherb@users 20030201 - patch 1.7.2 - direct calls for org.hsqldb.Library
// fredt@users - patch 1.8.0 - new functions added
/**
* fredt - todo - since the introduction of SQL built-in functions and
* evaluation of several session-dependent methods outside this class,
* several methods here are dummies. These methods are still reported in
* system tables incorrectly as corresponding to the SQL function names.
*/
/**
* Provides the HSQLDB implementation of standard Open Group SQL CLI
* <em>Extended Scalar Functions and other public HSQLDB SQL functions.
*
* All methods here that have a Connection parameter are dummies and should
* not be called from user supplied Java procedure or trigger code. Use real
* SQL functions should be called instead in these instances.
*
* Extensively rewritten and extended in successive versions of HSQLDB.
*
* @author Thomas Mueller (Hypersonic SQL Group)
* @version 1.8.0
* @since Hypersonic SQL
*/
public class Library {
static final SimpleDateFormat tocharFormat = new SimpleDateFormat();
static final SimpleDateFormat daynameFormat = new SimpleDateFormat("EEEE",
Locale.ENGLISH);
static final SimpleDateFormat monthnameFormat =
new SimpleDateFormat("MMMM", Locale.ENGLISH);
static final StringBuffer daynameBuffer = new StringBuffer();
static final StringBuffer monthnameBuffer = new StringBuffer();
static final FieldPosition monthPosition =
new FieldPosition(SimpleDateFormat.MONTH_FIELD);
static final FieldPosition dayPosition =
new FieldPosition(SimpleDateFormat.DAY_OF_WEEK_FIELD);
public static final String[][] sNumeric = {
{
"ABS", "org.hsqldb.Library.abs"
}, {
"ACOS", "java.lang.Math.acos"
}, {
"ASIN", "java.lang.Math.asin"
}, {
"ATAN", "java.lang.Math.atan"
}, {
"ATAN2", "java.lang.Math.atan2"
}, {
"CEILING", "java.lang.Math.ceil"
}, {
"COS", "java.lang.Math.cos"
}, {
"COT", "org.hsqldb.Library.cot"
}, {
"DEGREES", "java.lang.Math.toDegrees"
}, {
"EXP", "java.lang.Math.exp"
}, {
"FLOOR", "java.lang.Math.floor"
}, {
"LOG", "java.lang.Math.log"
}, {
"LOG10", "org.hsqldb.Library.log10"
}, {
"MOD", "org.hsqldb.Library.mod"
}, {
"PI", "org.hsqldb.Library.pi"
}, {
"POWER", "java.lang.Math.pow"
}, {
"RADIANS", "java.lang.Math.toRadians"
}, {
"RAND", "java.lang.Math.random"
}, {
"ROUND", "org.hsqldb.Library.round"
}, {
"SIGN", "org.hsqldb.Library.sign"
}, {
"SIN", "java.lang.Math.sin"
}, {
"SQRT", "java.lang.Math.sqrt"
}, {
"TAN", "java.lang.Math.tan"
}, {
"TRUNCATE", "org.hsqldb.Library.truncate"
}, {
"BITAND", "org.hsqldb.Library.bitand"
}, {
"BITOR", "org.hsqldb.Library.bitor"
}, {
"BITXOR", "org.hsqldb.Library.bitxor"
}, {
"ROUNDMAGIC", "org.hsqldb.Library.roundMagic"
}
};
// fredt@users 20010701 - patch 418023 by deforest@users
// the definition for SUBSTR was added
public static final String[][] sString = {
{
"ASCII", "org.hsqldb.Library.ascii"
}, {
"BIT_LENGTH", "org.hsqldb.Library.bitLength"
}, {
"CHAR", "org.hsqldb.Library.character"
}, {
"CHAR_LENGTH", "org.hsqldb.Library.length"
}, {
"CHARACTER_LENGTH", "org.hsqldb.Library.length"
}, {
"CONCAT", "org.hsqldb.Library.concat"
}, {
"DIFFERENCE", "org.hsqldb.Library.difference"
}, {
"HEXTORAW", "org.hsqldb.Library.hexToRaw"
}, {
"INSERT", "org.hsqldb.Library.insert"
}, {
"LCASE", "org.hsqldb.Library.lcase"
}, {
"LEFT", "org.hsqldb.Library.left"
}, {
"LENGTH", "org.hsqldb.Library.length"
}, {
"LOCATE", "org.hsqldb.Library.locate"
}, {
"LTRIM", "org.hsqldb.Library.ltrim"
}, {
"OCTET_LENGTH", "org.hsqldb.Library.octetLength"
}, {
"RAWTOHEX", "org.hsqldb.Library.rawToHex"
}, {
"REPEAT", "org.hsqldb.Library.repeat"
}, {
"REPLACE", "org.hsqldb.Library.replace"
}, {
"RIGHT", "org.hsqldb.Library.right"
}, {
"RTRIM", "org.hsqldb.Library.rtrim"
}, {
"SOUNDEX", "org.hsqldb.Library.soundex"
}, {
"SPACE", "org.hsqldb.Library.space"
}, {
"SUBSTR", "org.hsqldb.Library.substring"
}, {
"SUBSTRING", "org.hsqldb.Library.substring"
}, {
"UCASE", "org.hsqldb.Library.ucase"
}, {
"LOWER", "org.hsqldb.Library.lcase"
}, {
"UPPER", "org.hsqldb.Library.ucase"
}
};
public static final String[][] sTimeDate = {
{
"CURDATE", "org.hsqldb.Library.curdate"
}, {
"CURTIME", "org.hsqldb.Library.curtime"
}, {
"DATEDIFF", "org.hsqldb.Library.datediff"
}, {
"DAYNAME", "org.hsqldb.Library.dayname"
}, {
"DAY", "org.hsqldb.Library.dayofmonth"
}, {
"DAYOFMONTH", "org.hsqldb.Library.dayofmonth"
}, {
"DAYOFWEEK", "org.hsqldb.Library.dayofweek"
}, {
"DAYOFYEAR", "org.hsqldb.Library.dayofyear"
}, {
"HOUR", "org.hsqldb.Library.hour"
}, {
"MINUTE", "org.hsqldb.Library.minute"
}, {
"MONTH", "org.hsqldb.Library.month"
}, {
"MONTHNAME", "org.hsqldb.Library.monthname"
}, {
"NOW", "org.hsqldb.Library.now"
}, {
"QUARTER", "org.hsqldb.Library.quarter"
}, {
"SECOND", "org.hsqldb.Library.second"
}, {
"WEEK", "org.hsqldb.Library.week"
}, {
"YEAR", "org.hsqldb.Library.year"
}, {
"TO_CHAR", "org.hsqldb.Library.to_char"
}
};
public static final String[][] sSystem = {
{
"DATABASE", "org.hsqldb.Library.database"
}, {
"USER", "org.hsqldb.Library.user"
}, {
"IDENTITY", "org.hsqldb.Library.identity"
}
};
private Library() {}
static HashMap getAliasMap() {
HashMap h = new HashMap(83, 1);
register(h, sNumeric);
register(h, sString);
register(h, sTimeDate);
register(h, sSystem);
return h;
}
private static void register(HashMap h, String[][] s) {
for (int i = 0; i < s.length; i++) {
h.put(s[i][0], s[i][1]);
}
}
private static final Random rRandom = new Random();
// NUMERIC FUNCTIONS
// fredt@users 20020220 - patch 489184 by xclayl@users - thread safety
/**
* Returns the next pseudorandom, uniformly distributed <code>double value
* between 0.0 and 1.0 from a single, system-wide random number generator's
* sequence, optionally re-seeding (and thus resetting) the generator sequence.
*
* If the seed value is <code>null, then the underlying random number
* generator retrieves the next value in its current sequence, else the seed
* alters the state of the generator object so as to be in exactly the same state
* as if it had just been created with the seed value.
* @param seed an optional parameter with which to reseed the underlying
* pseudorandom number generator
* @return the next pseudorandom, uniformly distributed <code>double value between
* 0.0 and 1.0
*/
public static double rand(Integer seed) {
// boucherb@users 20020918
// CHECKME: perhaps rRandom should be a member of Session,
// since otherwise connections are *not* guranteed to get the
// same pseudorandom sequence, given the same set of calls to this
// SQL function. This makes comparitive analysis difficult.
// In fact, rRandom will be shared across multiple in-process
// database instances, so it is not even guaranteed that the
// sole connection to one instance will get the same sequence given
// the same set of calls to this SQL function.
synchronized (rRandom) {
if (seed != null) {
rRandom.setSeed(seed.intValue());
}
return rRandom.nextDouble();
}
}
/**
* Returns the absolute value of the given <code>double value.
* @param d the number for which to determine the absolute value
* @return the absolute value of <code>d, as a double
*/
public static double abs(double d) {
return Math.abs(d);
}
// this magic number works for 100000000000000; but not for 0.1 and 0.01
private static final double LOG10_FACTOR = 0.43429448190325183;
/**
* Returns the base 10 logarithm of the given <code>double value.
* @param x the value for which to calculate the base 10 logarithm
* @return the base 10 logarithm of <code>x, as a double
*/
public static double log10(double x) {
return roundMagic(Math.log(x) * LOG10_FACTOR);
}
/**
* Retrieves a <em>magically rounded double value produced
* from the given <code>double value. This method provides special
* handling for numbers close to zero and performs rounding only for
* numbers within a specific range, returning precisely the given value
* if it does not lie in this range. <p>
*
* Special handling includes: <p>
*
* <UL>
* <LI> input in the interval -0.0000000000001..0.0000000000001 returns 0.0
* <LI> input outside the interval -1000000000000..1000000000000 returns
* input unchanged
* <LI> input is converted to String form
* <LI> input with a String
form length greater than 16 returns
* input unchaged
* <LI> String
form with last four characters of '...000x' where
* x != '.' is converted to '...0000'
* <LI> String
form with last four characters of '...9999' is
* converted to '...999999'
* <LI> the java.lang.Double.doubleValue
of the String
* form is returned
* </UL>
* @param d the double value for which to retrieve the <em>magically
* rounded value
* @return the <em>magically rounded value produced
*/
public static double roundMagic(double d) {
// this function rounds numbers in a good way but slow:
// - special handling for numbers around 0
// - only numbers <= +/-1000000000000
// - convert to a string
// - check the last 4 characters:
// '000x' becomes '0000'
// '999x' becomes '999999' (this is rounded automatically)
if ((d < 0.0000000000001) && (d > -0.0000000000001)) {
return 0.0;
}
if ((d > 1000000000000.) || (d < -1000000000000.)) {
return d;
}
StringBuffer s = new StringBuffer();
s.append(d);
int len = s.length();
if (len < 16) {
return d;
}
char cx = s.charAt(len - 1);
char c1 = s.charAt(len - 2);
char c2 = s.charAt(len - 3);
char c3 = s.charAt(len - 4);
if ((c1 == '0') && (c2 == '0') && (c3 == '0') && (cx != '.')) {
s.setCharAt(len - 1, '0');
} else if ((c1 == '9') && (c2 == '9') && (c3 == '9') && (cx != '.')) {
s.setCharAt(len - 1, '9');
s.append('9');
s.append('9');
}
return Double.valueOf(s.toString()).doubleValue();
}
/**
* Returns the cotangent of the given <code>double value
* expressed in radians.
* @param d the angle, expressed in radians
* @return the cotangent
*/
public static double cot(double d) {
return 1. / Math.tan(d);
}
/**
* Returns the remainder (modulus) of the first given integer divided
* by the second. <p>
*
* @param i1 the numerator
* @param i2 the divisor
* @return <code>i1 % i2
, as an int
*/
public static int mod(int i1, int i2) {
return i1 % i2;
}
/**
* Returns the constant value, pi.
* @return pi as a <code>double value
*/
public static double pi() {
return Math.PI;
}
/**
* Returns the given <code>double value, rounded to the given
* <code>int places right of the decimal point. If
* the supplied rounding place value is negative, rounding is performed
* to the left of the decimal point, using its magnitude (absolute value).
* @param d the value to be rounded
* @param p the rounding place value
* @return <code>d rounded
*/
public static double round(double d, int p) {
double f = Math.pow(10., p);
return Math.round(d * f) / f;
}
/**
* Returns an indicator of the sign of the given <code>double
* value. If the value is less than zero, -1 is returned. If the value
* equals zero, 0 is returned. If the value is greater than zero, 1 is
* returned.
* @param d the value
* @return the sign of <code>d
*/
public static int sign(double d) {
return (d < 0) ? -1
: ((d > 0) ? 1
: 0);
}
/**
* Returns the given <code>double value, truncated to
* the given <code>int places right of the decimal point.
* If the given place value is negative, the given <code>double
* value is truncated to the left of the decimal point, using the
* magnitude (aboslute value) of the place value.
* @param d the value to truncate
* @param p the places left or right of the decimal point at which to
* truncate
* @return <code>d, truncated
*/
public static double truncate(double d, int p) {
double f = Math.pow(10., p);
double g = d * f;
return ((d < 0) ? Math.ceil(g)
: Math.floor(g)) / f;
}
/**
* Returns the bit-wise logical <em>and of the given
* integer values.
* @param i the first value
* @param j the second value
* @return the bit-wise logical <em>and of
* <code>i and j
*/
public static int bitand(int i, int j) {
return i & j;
}
/**
* Returns the bit-wise logical <em>or of the given
* integer values.
*
* @param i the first value
* @param j the second value
* @return the bit-wise logical <em>or of
* <code>i and j
*/
public static int bitor(int i, int j) {
return i | j;
}
/**
* Returns the bit-wise logical <em>xor of the given
* integer values.
*
* @param i the first value
* @param j the second value
* @return the bit-wise logical <em>xor of
* <code>i and j
*
* @since 1.8.0
*/
public static int bitxor(int i, int j) {
return i ^ j;
}
// STRING FUNCTIONS
/**
* Returns the Unicode code value of the leftmost character of
* <code>s as an int
. This is the same as the
* ASCII value if the string contains only ASCII characters.
* @param s the <code>String to evaluate
* @return the integer Unicode value of the
* leftmost character
*/
public static Integer ascii(String s) {
if ((s == null) || (s.length() == 0)) {
return null;
}
return ValuePool.getInt(s.charAt(0));
}
/**
* Returns the character string corresponding to the given ASCII
* (or Unicode) value.
*
* <b>Note:
*
* In some SQL CLI
* implementations, a <code>null is returned if the range is outside 0..255.
* In HSQLDB, the corresponding Unicode character is returned
* unchecked.
* @param code the character code for which to return a String
* representation
* @return the String representation of the character
*/
public static String character(int code) {
return String.valueOf((char) code);
}
/**
* Returns a <code>String object that is the result of an
* concatenation of the given <code>String objects.
*
* <b>When only one string is NULL, the result is different from that
* returned by an (string1 || string2) expression:
*
* <UL>
* <LI> if both String
objects are null
, return
* <code>null
* <LI> if only one string is null
, return the other
* <LI> if both String
objects are non-null, return as a
* <code>String object the character sequence obtained by listing,
* in left to right order, the characters of the first string followed by
* the characters of the second
* </UL>
* @param s1 the first <code>String
* @param s2 the second <code>String
* @return <code>s1 concatentated with s2
*/
public static String concat(String s1, String s2) {
if (s1 == null) {
if (s2 == null) {
return null;
}
return s2;
}
if (s2 == null) {
return s1;
}
return s1.concat(s2);
}
/**
* Returns a count of the characters that do not match when comparing
* the 4 digit numeric SOUNDEX character sequences for the
* given <code>String objects. If either String
object is
* <code>null, zero is returned.
* @param s1 the first <code>String
* @param s2 the second <code>String
* @return the number of differences between the <code>SOUNDEX of
* <code>s1 and the SOUNDEX
of s2
*/
// fredt@users 20020305 - patch 460907 by fredt - soundex
public static int difference(String s1, String s2) {
// todo: check if this is the standard algorithm
if ((s1 == null) || (s2 == null)) {
return 0;
}
s1 = soundex(s1);
s2 = soundex(s2);
int e = 0;
for (int i = 0; i < 4; i++) {
if (s1.charAt(i) != s2.charAt(i)) {
e++;
}
}
return e;
}
/**
* Converts a <code>String of hexidecimal digit characters to a raw
* binary value, represented as a <code>String.
*
* The given <code>String object must consist of a sequence of
* 4 digit hexidecimal character substrings.<p> If its length is not
* evenly divisible by 4, <code>null is returned. If any of
* its 4 character subsequences cannot be parsed as a
* 4 digit, base 16 value, then a NumberFormatException is thrown.
*
* This conversion has the effect of reducing the character count 4:1.
*
* @param s a <code>String of hexidecimal digit characters
* @return an equivalent raw binary value, represented as a
* <code>String
*/
public static String hexToRaw(String s) {
if (s == null) {
return null;
}
char raw;
StringBuffer to = new StringBuffer();
int len = s.length();
if (len % 4 != 0) {
return null;
}
for (int i = 0; i < len; i += 4) {
raw = (char) Integer.parseInt(s.substring(i, i + 4), 16);
to.append(raw);
}
return (to.toString());
}
/**
* Returns a character sequence which is the result of writing the
* first <code>length number of characters from the second
* given <code>String over the first string. The start position
* in the first string where the characters are overwritten is given by
* <code>start.
*
* <b>Note: In order of precedence, boundry conditions are handled as
* follows:<p>
*
* <UL>
* <LI>if either supplied String
is null, then the other is
* returned; the check starts with the first given <code>String.
* <LI>if start
is less than one, s1
is returned
* <LI>if length
is less than or equal to zero,
* <code>s1 is returned
* <LI>if the length of s2
is zero, s1
is returned
* <LI>if start
is greater than the length of s1
,
* <code>s1 is returned
* <LI>if length
is such that, taken together with
* <code>start, the indicated interval extends
* beyond the end of <code>s1, then the insertion is performed
* precisely as if upon a copy of <code>s1 extended in length
* to just include the indicated interval
* </UL>
* @param s1 the <code>String into which to insert s2
* @param start the position, with origin one, at which to start the insertion
* @param length the number of characters in <code>s1 to replace
* @param s2 the <code>String to insert into s1
* @return <code>s2 inserted into s1
, as indicated
* by <code>start and length
and adjusted for
* boundry conditions
*/
public static String insert(String s1, int start, int length, String s2) {
if (s1 == null) {
return s2;
}
if (s2 == null) {
return s1;
}
int len1 = s1.length();
int len2 = s2.length();
start--;
if (start < 0 || length <= 0 || len2 == 0 || start > len1) {
return s1;
}
if (start + length > len1) {
length = len1 - start;
}
return s1.substring(0, start) + s2 + s1.substring(start + length);
}
/**
* Returns a copy of the given <code>String, with all upper case
* characters converted to lower case. This uses the default Java String
* conversion.
* @param s the <code>String from which to produce a lower case
* version
* @return a lower case version of <code>s
*/
public static String lcase(String s) {
return (s == null) ? null
: s.toLowerCase();
}
/**
* Returns the leftmost <code>count characters from the given
* <code>String.
*
* <b>Note: boundry conditions are handled in the following order of
* precedence:
*
* <UL>
* <LI> if s
is null
, then null
* is returned
* <LI> if count
is less than 1, then a zero-length
* <code>String is returned
* <LI> if count
is greater than the length of s
,
* then a copy of <code>s is returned
* </UL>
* @param s the <code>String from which to retrieve the leftmost
* characters
* @param count the count of leftmost characters to retrieve
* @return the leftmost <code>count characters of s
*/
public static String left(String s, int count) {
if (s == null) {
return null;
}
return s.substring(0, ((count < 0) ? 0
: (count < s.length()) ? count
: s.length()));
}
// fredt@users - 20020819 - patch 595854 by thomasm@users
/**
* Returns the number of characters in the given <code>String.
* This includes trailing blanks.
*
* @param s the <code>String for which to determine length
* @return the length of <code>s, including trailing blanks
*/
public static Integer length(String s) {
return s == null ? null
: ValuePool.getInt(s.length());
}
/**
* Returns the number of bytes in the given <code>String.
* This includes trailing blanks.
*
* @param s the <code>String for which to determine the octet length
* @return the octet length of <code>s, including trailing blanks
* @since 1.7.2
*/
public static Integer octetLength(String s) {
return s == null ? null
: ValuePool.getInt(s.length() * 2);
}
/**
* Returns the number of bits in the given <code>String.
* This includes trailing blanks.
*
* @param s the <code>String for which to determine the bit length
* @return the bit length of <code>s, including trailing blanks
* @since 1.7.2
*/
public static Integer bitLength(String s) {
return s == null ? null
: ValuePool.getInt(s.length() * 16);
}
/**
* Returns the starting position of the first occurrence of
* the given <code>search String
object within
* the given <code>String object, s
.
*
* The search for the first occurrence of <code>search begins with
* the first character position in <code>s, unless the optional
* argument, <code>start, is specified (non-null). If
* <code>start is specified, the search begins with the character
* position indicated by the value of <code>start, where the
* first character position in <code>s is indicated by the value 1.
* If <code>search is not found within s
, the
* value 0 is returned.
* @param search the <code>String occurence to find in s
* @param s the <code>String within which to find the first
* occurence of <code>search
* @param start the optional character position from which to start
* looking in <code>s
* @return the one-based starting position of the first occurrence of
* <code>search within s
, or 0 if not found
*/
public static int locate(String search, String s, Integer start) {
if (s == null || search == null) {
return 0;
}
int i = (start == null) ? 0
: start.intValue() - 1;
return s.indexOf(search, (i < 0) ? 0
: i) + 1;
}
/**
* As locate but from start position l. <p>
*
* @param search the <code>String occurence to find in s
* @param s the <code>String within which to find the first
* occurence of <code>search
* @return the one-based starting position of the first occurrence of
* <code>search within s
, or 0 if not found
*/
public static int position(String search, String s) {
return locate(search, s, null);
}
/**
* Returns the characters of the given <code>String, with the
* leading spaces removed. Characters such as TAB are not removed.
*
* @param s the <code>String from which to remove the leading blanks
* @return the characters of the given <code>String, with the leading
* spaces removed
*/
public static String ltrim(String s) {
if (s == null) {
return s;
}
int len = s.length(),
i = 0;
while (i < len && s.charAt(i) <= ' ') {
i++;
}
return (i == 0) ? s
: s.substring(i);
}
/**
* Converts a raw binary value, as represented by the given
* <code>String, to the equivalent String
* of hexidecimal digit characters. <p>
*
* This conversion has the effect of expanding the character count 1:4.
*
* @param s the raw binary value, as a <code>String
* @return an equivalent <code>String of hexidecimal digit characters
*/
public static String rawToHex(String s) {
if (s == null) {
return null;
}
char[] from = s.toCharArray();
String hex;
StringBuffer to = new StringBuffer(4 * s.length());
for (int i = 0; i < from.length; i++) {
hex = Integer.toHexString(from[i] & 0xffff);
for (int j = hex.length(); j < 4; j++) {
to.append('0');
}
to.append(hex);
}
return (to.toString());
}
/**
* Returns a <code>String composed of the given String
,
* repeated <code>count times.
*
* @param s the <code>String to repeat
* @param count the number of repetitions
* @return the given <code>String, repeated count
times
*/
public static String repeat(String s, Integer count) {
if (s == null || count == null || count.intValue() < 0) {
return null;
}
int i = count.intValue();
StringBuffer b = new StringBuffer(s.length() * i);
while (i-- > 0) {
b.append(s);
}
return b.toString();
}
// fredt@users - 20020903 - patch 1.7.1 - bug fix to allow multiple replaces
/**
* Replaces all occurrences of <code>replace in s
* with the <code>String object: with
* @param s the target for replacement
* @param replace the substring(s), if any, in <code>s to replace
* @param with the value to substitute for <code>replace
* @return <code>s, with all occurences of replace
* replaced by <code>with
*/
public static String replace(String s, String replace, String with) {
if (s == null || replace == null) {
return s;
}
if (with == null) {
with = "";
}
StringBuffer b = new StringBuffer();
int start = 0;
int lenreplace = replace.length();
while (true) {
int i = s.indexOf(replace, start);
if (i == -1) {
b.append(s.substring(start));
break;
}
b.append(s.substring(start, i));
b.append(with);
start = i + lenreplace;
}
return b.toString();
}
/**
* Returns the rightmost <code>count characters of the given
* <code>String, s
.
*
* <b>Note: boundry conditions are handled in the following order of
* precedence: <p>
*
* <UL>
* <LI> if s
is null
, null
is returned
* <LI> if count
is less than one, a zero-length
* <code>String is returned
* <LI> if count
is greater than the length of s
,
* a copy of <code>s is returned
* </UL>
* @param s the <code>String from which to retrieve the rightmost
* <code>count characters
* @param count the number of rightmost characters to retrieve
* @return the rightmost <code>count characters of s
*/
public static String right(String s, int count) {
if (s == null) {
return null;
}
count = s.length() - count;
return s.substring((count < 0) ? 0
: (count < s.length()) ? count
: s.length());
}
// fredt@users 20020530 - patch 1.7.0 fredt - trim only the space character
/**
* Returns the characters of the given <code>String, with trailing
* spaces removed.
* @param s the <code>String from which to remove the trailing blanks
* @return the characters of the given <code>String, with the
* trailing spaces removed
*/
public static String rtrim(String s) {
if (s == null) {
return s;
}
int endindex = s.length() - 1;
int i = endindex;
for (; i >= 0 && s.charAt(i) == ' '; i--) {}
return i == endindex ? s
: s.substring(0, i + 1);
}
/**
* Returns the character sequence <code>s, with the leading,
* trailing or both the leading and trailing occurences of the first
* character of the character sequence <code>trimstr removed.
*
* This method is in support of the standard SQL String function TRIM.
* Ordinarily, the functionality of this method is accessed from SQL using
* the following syntax: <p>
*
* <pre class="SqlCodeExample">
* <trim function> ::= TRIM <left paren> <trim operands> <right paren>
* <trim operands> ::= [ [ <trim specification> ] [ <trim character> ] FROM ] <trim source>
* <trim source> ::= <character value expression>
* <trim specification> ::= LEADING | TRAILING | BOTH
* <trim character> ::= <character value expression>
* </pre>
*
* @param s the string to trim
* @param trimstr the character whose occurences will be removed
* @param leading if true, remove leading occurences
* @param trailing if true, remove trailing occurences
* @return s, with the leading, trailing or both the leading and trailing
* occurences of the first character of <code>trimstr removed
* @since 1.7.2
*/
public static String trim(String s, String trimstr, boolean leading,
boolean trailing) {
if (s == null) {
return s;
}
int trim = trimstr.charAt(0);
int endindex = s.length();
if (trailing) {
for (--endindex; endindex >= 0 && s.charAt(endindex) == trim;
endindex--) {}
endindex++;
}
if (endindex == 0) {
return "";
}
int startindex = 0;
if (leading) {
while (startindex < endindex && s.charAt(startindex) == trim) {
startindex++;
}
}
if (startindex == 0 && endindex == s.length()) {
return s;
} else {
return s.substring(startindex, endindex);
}
}
// fredt@users 20011010 - patch 460907 by fredt - soundex
/**
* Returns a four character code representing the sound of the given
* <code>String. Non-ASCCI characters in the
* input <code>String are ignored.
*
* This method was
* rewritten for HSQLDB by fredt@users to comply with the description at
* <a href="http://www.nara.gov/genealogy/coding.html">
* http://www.nara.gov/genealogy/coding.html</a>.
* @param s the <code>String for which to calculate the 4 character
* <code>SOUNDEX value
* @return the 4 character <code>SOUNDEX value for the given
* <code>String
*/
public static String soundex(String s) {
if (s == null) {
return s;
}
s = s.toUpperCase(Locale.ENGLISH);
int len = s.length();
char[] b = new char[] {
'0', '0', '0', '0'
};
char lastdigit = '0';
for (int i = 0, j = 0; i < len && j < 4; i++) {
char c = s.charAt(i);
char newdigit;
if ("AEIOUY".indexOf(c) != -1) {
newdigit = '7';
} else if (c == 'H' || c == 'W') {
newdigit = '8';
} else if ("BFPV".indexOf(c) != -1) {
newdigit = '1';
} else if ("CGJKQSXZ".indexOf(c) != -1) {
newdigit = '2';
} else if (c == 'D' || c == 'T') {
newdigit = '3';
} else if (c == 'L') {
newdigit = '4';
} else if (c == 'M' || c == 'N') {
newdigit = '5';
} else if (c == 'R') {
newdigit = '6';
} else {
continue;
}
if (j == 0) {
b[j++] = c;
lastdigit = newdigit;
} else if (newdigit <= '6') {
if (newdigit != lastdigit) {
b[j++] = newdigit;
lastdigit = newdigit;
}
} else if (newdigit == '7') {
lastdigit = newdigit;
}
}
return new String(b, 0, 4);
}
/**
* Returns a <code>String consisting of count
spaces, or
* <code>null if count
is less than zero.
*
* @param count the number of spaces to produce
* @return a <code>String of count
spaces
*/
public static String space(int count) {
if (count < 0) {
return null;
}
char[] c = new char[count];
while (count > 0) {
c[--count] = ' ';
}
return new String(c);
}
/**
* Returns the characters from the given <code>String, starting at
* the indicated one-based <code>start position and extending the
* (optional) indicated <code>length. If length
is not
* specified (is <code>null), the remainder of s
is
* implied.
*
* The rules for boundary conditions on s, start and length are,
* in order of precedence: <p>
*
* 1.) if s is null, return null
*
* 2.) If length is less than 1, return null.
*
* 3.) If start is 0, it is treated as 1.
*
* 4.) If start is positive, count from the beginning of s to find
* the first character postion.
*
* 5.) If start is negative, count backwards from the end of s
* to find the first character.
*
* 6.) If, after applying 2.) or 3.), the start position lies outside s,
* then return null
*
* 7.) if length is ommited or is greated than the number of characters
* from the start position to the end of s, return the remaineder of s,
* starting with the start position.
*
* @param s the <code>String from which to produce the indicated
* substring
* @param start the starting position of the desired substring
* @param length the length of the desired substring
* @return the indicted substring of <code>s.
*/
// fredt@users 20020210 - patch 500767 by adjbirch@users - modified
// boucherb@users 20050205 - patch to correct bug 1107477
public static String substring(final String s, int start,
final Integer length) {
if (s == null) {
return null;
}
int sl = s.length();
int ol = (length == null) ? sl
: length.intValue();
if (ol < 1) {
return null;
}
if (start < 0) {
start = sl + start;
} else if (start > 0) {
start--;
}
if (start < 0 || start >= sl) {
return null;
} else if (start > sl - ol) {
ol = sl - start;
}
return s.substring(start, start + ol);
}
/**
* Returns a copy of the given <code>String, with all lower case
* characters converted to upper case using the default Java method.
* @param s the <code>String from which to produce an upper case
* version
* @return an upper case version of <code>s
*/
public static String ucase(String s) {
return (s == null) ? null
: s.toUpperCase();
}
// TIME AND DATE
/**
* Returns the current date as a date value. <p>
*
* Dummy mehtod.<p>
*
* @return a date value representing the current date
*/
public static Date curdate(Connection c) {
return null;
}
/**
* Returns the current local time as a time value. <p>
*
* Dummy mehtod.<p>
*
* @return a time value representing the current local time
*/
public static Time curtime(Connection c) {
return null;
}
/**
* Returns a character string containing the name of the day
* (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday )
* for the day portion of the given <code>java.sql.Date.
* @param d the date value from which to extract the day name
* @return the name of the day corresponding to the given
* <code>java.sql.Date
*/
public static String dayname(Date d) {
if (d == null) {
return null;
}
synchronized (daynameBuffer) {
daynameBuffer.setLength(0);
return daynameFormat.format(d, daynameBuffer,
dayPosition).toString();
}
}
/**
* Returns the day of the month from the given date value, as an integer
* value in the range of 1-31.
*
* @param d the date value from which to extract the day of month
* @return the day of the month from the given date value
*/
public static Integer dayofmonth(Date d) {
if (d == null) {
return null;
}
return ValuePool.getInt(HsqlDateTime.getDateTimePart(d,
Calendar.DAY_OF_MONTH));
}
/**
* Returns the day of the week from the given date value, as an integer
* value in the range 1-7, where 1 represents Sunday.
*
* @param d the date value from which to extract the day of week
* @return the day of the week from the given date value
*/
public static Integer dayofweek(Date d) {
if (d == null) {
return null;
}
return ValuePool.getInt(HsqlDateTime.getDateTimePart(d,
Calendar.DAY_OF_WEEK));
}
/**
* Returns the day of the year from the given date value, as an integer
* value in the range 1-366.
*
* @param d the date value from which to extract the day of year
* @return the day of the year from the given date value
*/
public static Integer dayofyear(Date d) {
if (d == null) {
return null;
}
return ValuePool.getInt(HsqlDateTime.getDateTimePart(d,
Calendar.DAY_OF_YEAR));
}
/**
* Returns the hour from the given time value, as an integer value in
* the range of 0-23.
*
* @param t the time value from which to extract the hour of day
* @return the hour of day from the given time value
*/
// fredt@users 20020210 - patch 513005 by sqlbob@users (RMP) - hour
public static Integer hour(Time t) {
if (t == null) {
return null;
}
return ValuePool.getInt(HsqlDateTime.getDateTimePart(t,
Calendar.HOUR_OF_DAY));
}
/**
* Returns the minute from the given time value, as integer value in
* the range of 0-59.
*
* @param t the time value from which to extract the minute value
* @return the minute value from the given time value
*/
public static Integer minute(Time t) {
if (t == null) {
return null;
}
return ValuePool.getInt(HsqlDateTime.getDateTimePart(t,
Calendar.MINUTE));
}
/**
* Returns the month from the given date value, as an integer value in the
* range of 1-12. <p>
*
* The sql_month database property is now obsolete.
* The function always returns the SQL (1-12) value for month.
*
* @param d the date value from which to extract the month value
* @return the month value from the given date value
*/
public static Integer month(Date d) {
if (d == null) {
return null;
}
return ValuePool.getInt(
HsqlDateTime.getDateTimePart(d, Calendar.MONTH) + 1);
}
/**
* Returns a character string containing the name of month
* (January, February, March, April, May, June, July, August,
* September, October, November, December) for the month portion of
* the given date value.
*
* @param d the date value from which to extract the month name
* @return a String representing the month name from the given date value
*/
public static String monthname(Date d) {
if (d == null) {
return null;
}
synchronized (monthnameBuffer) {
monthnameBuffer.setLength(0);
return monthnameFormat.format(d, monthnameBuffer,
monthPosition).toString();
}
}
/**
* Returns the current date and time as a timestamp value. <p>
*
* Dummy mehtod.<p>
*
* @return a timestamp value representing the current date and time
*/
public static Timestamp now(Connection c) {
return null;
}
/**
* Returns the quarter of the year in the given date value, as an integer
* value in the range of 1-4. <p>
*
* @param d the date value from which to extract the quarter of the year
* @return an integer representing the quater of the year from the given
* date value
*/
public static Integer quarter(Date d) {
if (d == null) {
return null;
}
return ValuePool.getInt(
(HsqlDateTime.getDateTimePart(d, Calendar.MONTH) / 3) + 1);
}
/**
* Returns the second of the given time value, as an integer value in
* the range of 0-59.
*
* @param d the date value from which to extract the second of the hour
* @return an integer representing the second of the hour from the
* given time value
*/
public static Integer second(Time d) {
if (d == null) {
return null;
}
return ValuePool.getInt(HsqlDateTime.getDateTimePart(d,
Calendar.SECOND));
}
/**
* Returns the week of the year from the given date value, as an integer
* value in the range of 1-53. <p>
*
* @param d the date value from which to extract the week of the year
* @return an integer representing the week of the year from the given
* date value
*/
public static Integer week(Date d) {
if (d == null) {
return null;
}
return ValuePool.getInt(HsqlDateTime.getDateTimePart(d,
Calendar.WEEK_OF_YEAR));
}
/**
* Returns the year from the given date value, as an integer value in
* the range of 1-9999. <p>
*
* @param d the date value from which to extract the year
* @return an integer value representing the year from the given
* date value
*/
public static Integer year(Date d) {
if (d == null) {
return null;
}
return ValuePool.getInt(HsqlDateTime.getDateTimePart(d,
Calendar.YEAR));
}
/**
* @since 1.8.0
*/
public static String to_char(java.util.Date d, String format) {
if (d == null || format == null) {
return null;
}
synchronized (tocharFormat) {
tocharFormat.applyPattern(HsqlDateTime.toJavaDatePattern(format));
return tocharFormat.format(d);
}
}
// date calculations.
/**
* Returns the number of units elapsed between two dates.<p>
* The datapart parameter indicates the part to be used for computing the
* difference. Supported types include: 'year', 'yy', 'month', 'mm'
* 'day', 'dd', 'hour', 'hh', 'minute', 'mi', 'second', 'ss', 'millisecond',
* 'ms'.
*
* Contributed by Michael Landon<p>
*
* @param datepart Specifies the unit in which the interval is to be measured.
* @param d1 The starting datetime value for the interval. This value is
* subtracted from d2 to return the number of
* date-parts between the two arguments.
* @param d2 The ending datetime for the interval. d1 is subtracted
* from this value to return the number of date-parts
* between the two arguments.
*
* since 1.7.3
*/
public static Long datediff(String datepart, Timestamp d1,
Timestamp d2) throws HsqlException {
// make sure we've got valid data
if (d1 == null || d2 == null) {
return null;
}
if ("yy".equalsIgnoreCase(datepart)
|| "year".equalsIgnoreCase(datepart)) {
return ValuePool.getLong(getElapsed(Calendar.YEAR, d1, d2));
} else if ("mm".equalsIgnoreCase(datepart)
|| "month".equalsIgnoreCase(datepart)) {
return ValuePool.getLong(getElapsed(Calendar.MONTH, d1, d2));
} else if ("dd".equalsIgnoreCase(datepart)
|| "day".equalsIgnoreCase(datepart)) {
return ValuePool.getLong(getElapsed(Calendar.DATE, d1, d2));
} else if ("hh".equalsIgnoreCase(datepart)
|| "hour".equalsIgnoreCase(datepart)) {
return ValuePool.getLong(getElapsed(Calendar.HOUR, d1, d2));
} else if ("mi".equalsIgnoreCase(datepart)
|| "minute".equalsIgnoreCase(datepart)) {
return ValuePool.getLong(getElapsed(Calendar.MINUTE, d1, d2));
} else if ("ss".equalsIgnoreCase(datepart)
|| "second".equalsIgnoreCase(datepart)) {
return ValuePool.getLong(getElapsed(Calendar.SECOND, d1, d2));
} else if ("ms".equalsIgnoreCase(datepart)
|| "millisecond".equalsIgnoreCase(datepart)) {
return ValuePool.getLong(getElapsed(Calendar.MILLISECOND, d1,
d2));
} else {
throw Trace.error(Trace.INVALID_CONVERSION);
}
}
/**
* Private method used to do actual calculation units elapsed between
* two given dates. <p>
*
* @param field Calendar field to use to calculate elapsed time
* @param d1 The starting date for the interval. This value is
* subtracted from d2 to return the number of
* date-parts between the two arguments.
* @param d2 The ending date for the interval. d1 is subtracted
* from this value to return the number of date-parts
* between the two arguments.
*/
private static long getElapsed(int field, java.util.Date d1,
java.util.Date d2) {
// can we do this very simply?
if (field == Calendar.MILLISECOND) {
return d2.getTime() - d1.getTime();
}
// ok, let's work a little harder:
Calendar g1 = Calendar.getInstance(),
g2 = Calendar.getInstance();
g1.setTime(d1);
g2.setTime(d2);
g1.set(Calendar.MILLISECOND, 0);
g2.set(Calendar.MILLISECOND, 0);
if (field == Calendar.SECOND) {
return (g2.getTime().getTime() - g1.getTime().getTime()) / 1000;
}
g1.set(Calendar.SECOND, 0);
g2.set(Calendar.SECOND, 0);
if (field == Calendar.MINUTE) {
return (g2.getTime().getTime() - g1.getTime().getTime())
/ (1000 * 60);
}
g1.set(Calendar.MINUTE, 0);
g2.set(Calendar.MINUTE, 0);
if (field == Calendar.HOUR) {
return (g2.getTime().getTime() - g1.getTime().getTime())
/ (1000 * 60 * 60);
} // end if-else
// if we got here, then we really need to work:
long elapsed = 0;
short sign = 1;
if (g2.before(g1)) {
sign = -1;
Calendar tmp = g1;
g1 = g2;
g2 = tmp;
} // end if
g1.set(Calendar.HOUR_OF_DAY, 0);
g2.set(Calendar.HOUR_OF_DAY, 0);
if (field == Calendar.MONTH || field == Calendar.YEAR) {
g1.set(Calendar.DATE, 1);
g2.set(Calendar.DATE, 1);
}
if (field == Calendar.YEAR) {
g1.set(Calendar.MONTH, 1);
g2.set(Calendar.MONTH, 1);
} // end if-else
// then calculate elapsed units
while (g1.before(g2)) {
g1.add(field, 1);
elapsed++;
}
return sign * elapsed;
} // end getElapsed
// SYSTEM
/*
* All system functions that return Session dependent information are
* dummies here.
*/
/**
* Returns the name of the database corresponding to this connection.
*
* @param conn the connection for which to retrieve the database name
* @return the name of the database for the given connection
* @throws HsqlException if a database access error occurs
*/
public static String database(Connection conn) throws HsqlException {
return null;
}
/**
* Returns the user's authorization name (the user's name as known to this
* database).
*
* @param conn the connection for which to retrieve the user name
* @return the user's name as known to the database
* @throws HsqlException if a database access error occurs
*/
public static String user(Connection conn) throws HsqlException {
return null;
}
/**
* Retrieves the last auto-generated integer indentity value
* used by this connection. <p>
*
* Dummy mehtod.<p>
*
* @return the connection's the last generated integer identity value
* @throws HsqlException if a database access error occurs
*/
public static int identity() throws HsqlException {
return 0;
}
// JDBC SYSTEM
/**
* Retrieves the autocommit status of this connection. <p>
*
* @param conn the <code>Connection object for which to retrieve
* the current autocommit status
* @return a boolean value representing the connection's autocommit status
* @since 1.7.0
*/
public static boolean getAutoCommit(Connection conn) {
return false;
}
/**
* Retrieves the full version number of this database product. <p>
*
* @return database version number as a <code>String object
* @since 1.8.0.4
*/
public static String getDatabaseFullProductVersion() {
return HsqlDatabaseProperties.THIS_FULL_VERSION;
}
/**
* Retrieves the name of this database product. <p>
*
* @return database product name as a <code>String object
* @since 1.7.2
*/
public static String getDatabaseProductName() {
return HsqlDatabaseProperties.PRODUCT_NAME;
}
/**
* Retrieves the version number of this database product. <p>
*
* @return database version number as a <code>String object
* @since 1.7.2
*/
public static String getDatabaseProductVersion() {
return HsqlDatabaseProperties.THIS_VERSION;
}
/**
* Retrieves the major version number of this database. <p>
*
* @return the database's major version as an <code>int value
* @since 1.7.2
*/
public static int getDatabaseMajorVersion() {
return HsqlDatabaseProperties.MAJOR;
}
/**
* Retrieves the major version number of this database. <p>
*
* @return the database's major version as an <code>int value
* @since 1.7.2
*/
public static int getDatabaseMinorVersion() {
return HsqlDatabaseProperties.MINOR;
}
/**
* Retrieves whether this connection is in read-only mode. <p>
*
* Dummy mehtod.<p>
*
* @param conn the <code>Connection object for which to retrieve
* the current read-only status
* @return <code>true if connection is read-only and
* <code>false otherwise
* @since 1.7.2
*/
public static boolean isReadOnlyConnection(Connection conn) {
return false;
}
/**
* Dummy method. Retrieves whether this database is in read-only mode. <p>
*
* @param c the <code>Connection object for which to retrieve
* the current database read-only status
* @return <code>true if so; false
otherwise
* @since 1.7.2
*/
public static boolean isReadOnlyDatabase(Connection c) {
return false;
}
/**
* Retrieves whether the files of this database are in read-only mode. <p>
*
* Dummy mehtod.<p>
*
* @param c the <code>Connection object for which to retrieve
* the current database files read-only status
* @return <code>true if so; false
otherwise
* @since 1.7.2
*/
public static boolean isReadOnlyDatabaseFiles(Connection c) {
return false;
}
static final int abs = 0;
static final int ascii = 1;
static final int bitand = 2;
static final int bitLength = 3;
static final int bitor = 4;
static final int bitxor = 5;
static final int character = 6;
static final int concat = 7;
static final int cot = 8;
static final int curdate = 9;
static final int curtime = 10;
static final int database = 11;
static final int datediff = 12;
static final int day = 13;
static final int dayname = 14;
static final int dayofmonth = 15;
static final int dayofweek = 16;
static final int dayofyear = 17;
static final int difference = 18;
static final int getAutoCommit = 19;
static final int getDatabaseFullProductVersion = 20;
static final int getDatabaseMajorVersion = 21;
static final int getDatabaseMinorVersion = 22;
static final int getDatabaseProductName = 23;
static final int getDatabaseProductVersion = 24;
static final int hexToRaw = 25;
static final int hour = 26;
static final int identity = 27;
static final int insert = 28;
static final int isReadOnlyConnection = 29;
static final int isReadOnlyDatabase = 30;
static final int isReadOnlyDatabaseFiles = 31;
static final int lcase = 32;
static final int left = 33;
static final int length = 34;
static final int locate = 35;
static final int log10 = 36;
static final int ltrim = 37;
static final int minute = 38;
static final int mod = 39;
static final int month = 40;
static final int monthname = 41;
static final int now = 42;
static final int octetLength = 43;
static final int pi = 44;
static final int position = 45;
static final int quarter = 46;
static final int rand = 47;
static final int rawToHex = 48;
static final int repeat = 49;
static final int replace = 50;
static final int right = 51;
static final int round = 52;
static final int roundMagic = 53;
static final int rtrim = 54;
static final int second = 55;
static final int sign = 56;
static final int soundex = 57;
static final int space = 58;
static final int substring = 59;
static final int to_char = 60;
static final int trim = 61;
static final int truncate = 62;
static final int ucase = 63;
static final int user = 64;
static final int week = 65;
static final int year = 66;
/** @todo see bitxor and datediff numbering */
//
private static final IntValueHashMap functionMap =
new IntValueHashMap(67);
static final Double piValue = new Double(Library.pi());
static {
functionMap.put("abs", abs);
functionMap.put("ascii", ascii);
functionMap.put("bitand", bitand);
functionMap.put("bitlength", bitLength);
functionMap.put("bitor", bitor);
functionMap.put("bitxor", bitxor);
functionMap.put("character", character);
functionMap.put("concat", concat);
functionMap.put("cot", cot);
functionMap.put("curdate", curdate);
functionMap.put("curtime", curtime);
functionMap.put("database", database);
functionMap.put("datediff", datediff);
functionMap.put("dayname", dayname);
functionMap.put("day", day);
functionMap.put("dayofmonth", dayofmonth);
functionMap.put("dayofweek", dayofweek);
functionMap.put("dayofyear", dayofyear);
functionMap.put("difference", difference);
functionMap.put("getAutoCommit", getAutoCommit);
functionMap.put("getDatabaseFullProductVersion",
getDatabaseFullProductVersion);
functionMap.put("getDatabaseMajorVersion", getDatabaseMajorVersion);
functionMap.put("getDatabaseMinorVersion", getDatabaseMinorVersion);
functionMap.put("getDatabaseProductName", getDatabaseProductName);
functionMap.put("getDatabaseProductVersion",
getDatabaseProductVersion);
functionMap.put("hexToRaw", hexToRaw);
functionMap.put("hour", hour);
functionMap.put("identity", identity);
functionMap.put("insert", insert);
functionMap.put("isReadOnlyConnection", isReadOnlyConnection);
functionMap.put("isReadOnlyDatabase", isReadOnlyDatabase);
functionMap.put("isReadOnlyDatabaseFiles", isReadOnlyDatabaseFiles);
functionMap.put("lcase", lcase);
functionMap.put("left", left);
functionMap.put("length", length);
functionMap.put("locate", locate);
functionMap.put("log10", log10);
functionMap.put("ltrim", ltrim);
functionMap.put("minute", minute);
functionMap.put("mod", mod);
functionMap.put("month", month);
functionMap.put("monthname", monthname);
functionMap.put("now", now);
functionMap.put("octetLength", octetLength);
functionMap.put("pi", pi);
functionMap.put("position", position);
functionMap.put("quarter", quarter);
functionMap.put("rand", rand);
functionMap.put("rawToHex", rawToHex);
functionMap.put("repeat", repeat);
functionMap.put("replace", replace);
functionMap.put("right", right);
functionMap.put("round", round);
functionMap.put("roundMagic", roundMagic);
functionMap.put("rtrim", rtrim);
functionMap.put("second", second);
functionMap.put("sign", sign);
functionMap.put("soundex", soundex);
functionMap.put("space", space);
functionMap.put("substring", substring);
functionMap.put("to_char", to_char);
functionMap.put("trim", trim);
functionMap.put("truncate", truncate);
functionMap.put("ucase", ucase);
functionMap.put("user", user);
functionMap.put("week", week);
functionMap.put("year", year);
}
static Object invoke(int fID, Object[] params) throws HsqlException {
try {
switch (fID) {
case abs : {
return new Double(
Library.abs(((Number) params[0]).doubleValue()));
}
case ascii : {
return ascii((String) params[0]);
}
case bitand : {
return ValuePool.getInt(
bitand(((Number) params[0]).intValue(),
((Number) params[1]).intValue()));
}
case bitLength : {
return bitLength((String) params[0]);
}
case bitor : {
return ValuePool.getInt(
bitor(((Number) params[0]).intValue(),
((Number) params[1]).intValue()));
}
case bitxor : {
return ValuePool.getInt(
bitxor(((Number) params[0]).intValue(),
((Number) params[1]).intValue()));
}
case character : {
return character(((Number) params[0]).intValue());
}
case concat : {
return concat((String) params[0], (String) params[1]);
}
case cot : {
return new Double(
cot(((Number) params[0]).doubleValue()));
}
case curdate : {
return null;
}
case curtime : {
return null;
}
case database : {
return null;
}
case datediff : {
return datediff((String) params[0],
(Timestamp) params[1],
(Timestamp) params[2]);
}
case dayname : {
return dayname((Date) params[0]);
}
case dayofmonth :
case day : {
return dayofmonth((Date) params[0]);
}
case dayofweek : {
return dayofweek((Date) params[0]);
}
case dayofyear : {
return dayofyear((Date) params[0]);
}
case difference : {
return ValuePool.getInt(difference((String) params[0],
(String) params[1]));
}
case getAutoCommit : {
return null;
}
case getDatabaseFullProductVersion : {
return getDatabaseFullProductVersion();
}
case getDatabaseMajorVersion : {
return ValuePool.getInt(getDatabaseMajorVersion());
}
case getDatabaseMinorVersion : {
return ValuePool.getInt(getDatabaseMinorVersion());
}
case getDatabaseProductName : {
return getDatabaseProductName();
}
case getDatabaseProductVersion : {
return getDatabaseProductVersion();
}
case hexToRaw : {
return hexToRaw((String) params[0]);
}
case hour : {
return hour((Time) params[0]);
}
case identity : {
return null;
}
case insert : {
return insert((String) params[0],
((Number) params[1]).intValue(),
((Number) params[2]).intValue(),
(String) params[3]);
}
case isReadOnlyConnection : {
return null;
}
case isReadOnlyDatabase : {
return null;
}
case lcase : {
return lcase((String) params[0]);
}
case left : {
return left((String) params[0],
((Number) params[1]).intValue());
}
case length : {
return length((String) params[0]);
}
case locate : {
return ValuePool.getInt(locate((String) params[0],
(String) params[1],
(Integer) params[2]));
}
case log10 : {
return new Double(
log10(((Number) params[0]).doubleValue()));
}
case ltrim : {
return ltrim((String) params[0]);
}
case minute : {
return minute((Time) params[0]);
}
case mod : {
return ValuePool.getInt(
mod(
((Number) params[0]).intValue(),
((Number) params[1]).intValue()));
}
case month : {
return month((Date) params[0]);
}
case monthname : {
return ValuePool.getString(monthname((Date) params[0]));
}
case now : {
return null;
}
case octetLength : {
return octetLength((String) params[0]);
}
case position : {
return ValuePool.getInt(position((String) params[0],
(String) params[1]));
}
case pi : {
return piValue;
}
case quarter : {
return quarter((Date) params[0]);
}
case rand : {
return new Double(rand((Integer) params[0]));
}
case rawToHex : {
return rawToHex((String) params[0]);
}
case repeat : {
return repeat((String) params[0], (Integer) params[1]);
}
case replace : {
return replace((String) params[0], (String) params[1],
(String) params[2]);
}
case right : {
return right((String) params[0],
((Number) params[1]).intValue());
}
case round : {
return new Double(
round(((Number) params[0]).doubleValue(),
((Number) params[1]).intValue()));
}
case roundMagic : {
return new Double(
roundMagic(((Number) params[0]).doubleValue()));
}
case rtrim : {
return rtrim((String) params[0]);
}
case second : {
return second((Time) params[0]);
}
case sign : {
return ValuePool.getInt(
sign(((Number) params[0]).doubleValue()));
}
case soundex : {
return soundex((String) params[0]);
}
case space : {
return space(((Number) params[0]).intValue());
}
case substring : {
return substring((String) params[0],
((Number) params[1]).intValue(),
(Integer) params[2]);
}
case trim : {
return trim((String) params[0], (String) params[1],
((Boolean) params[2]).booleanValue(),
((Boolean) params[3]).booleanValue());
}
case truncate : {
return new Double(
truncate(
((Number) params[0]).doubleValue(),
((Number) params[1]).intValue()));
}
case ucase : {
return ucase((String) params[0]);
}
case user : {
return null;
}
case week : {
return week((Date) params[0]);
}
case year : {
return year((Date) params[0]);
}
case to_char : {
return to_char((java.util.Date) params[0],
(String) params[1]);
}
case isReadOnlyDatabaseFiles : {
return null;
}
default : {
// coding error
Trace.doAssert(false);
return null;
}
}
} catch (Exception e) {
throw Trace.error(Trace.FUNCTION_CALL_ERROR, e.toString());
}
}
static final String prefix = "org.hsqldb.Library.";
static final int prefixLength = prefix.length();
static int functionID(String fname) {
return fname.startsWith(prefix)
? functionMap.get(fname.substring(prefixLength), -1)
: -1;
}
}
Other HSQLDB examples (source code examples)
Here is a short list of links related to this HSQLDB Library.java source code file: