# Functions.java

    /*
    ** Module   : Functions.java
    ** Abstract : Dispatcher methods for Java language, server-side database
    **            functions which replace Progress built-in functions
    **
    ** Copyright (c) 2004-2025, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- --JPRM-- ----------------------------Description-----------------------------
    ** 001 ECF 20060811   @28584 Created initial version. Backing methods for
    **                           Progress built-in functions executed within
    **                           the database server as custom, Java-language
    **                           functions.
    ** 002 ECF 20060818   @28692 Added new functions.
    ** 003 GES 20060907   @29295 Added new variants of toString() that take
    **                           format strings.
    ** 004 ECF 20060908   @29382 Reimplemented all toString() methods. Old
    **                           implementations did not properly handle null
    **                           values as unknown.
    ** 005 ECF 20060912   @29479 Added toInt() variant which accepts Integer.
    **                           Changed Number variant to accept Double
    **                           instead.
    ** 006 ECF 20061023   @30618 Fixed variants of toString() which do not
    **                           take a format phrase. These were generating
    **                           left-padded strings, but should generate
    **                           unpadded strings.
    ** 007 ECF 20070309   @32368 Fixed round() method signatures. These were
    **                           still using Number and int; need to use
    **                           Double and Integer, respectively.
    ** 008 ECF 20070426   @33230 Added concat() method.
    ** 009 ECF 20070608   @34014 Replaced all Double with BigDecimal. Reflects
    **                           new implementations of decimal and MathOps
    **                           classes.
    ** 010 ECF 20070618   @34092 Added a variant of toDec() which accepts a
    **                           BigDecimal value and a precision. Also
    **                           reimplemented several methods which use
    **                           BigDecimal to preserve precision.
    ** 011 ECF 20071210   @36494 Implemented error handling for CAN-FINDs.
    **                           Built-in functions/operators within converted
    **                           CAN-FIND statements must handle errors by
    **                           returning null instead of throwing an
    **                           exception. These are wrapped in the
    **                           ErrorHandler.checkError() function, which
    **                           checks pending error state and returns an
    **                           appropriate result.
    ** 012 ECF 20080313   @37511 Expanded API to provide variants with
    **                           exhaustive combinations of numeric parameter
    **                           types. This is necessary to enable "manual"
    **                           overloading user defined functions.
    ** 013 GES 20080910   @39765 Minor javadoc update.
    ** 014 GES 20081003   @40031 Matched signature changes.
    ** 015 CA  20090702   @43026 Added versions of toInt, toString and toDec which
    **                           receive a java.sql.Date as a parameter.
    ** 016 ECF 20090721   @43314 Partially backed out #015 (@43026). Removed the
    **                           Date variants of toInt() and toDec(). These were
    **                           redundant with julianDayInt() and julianDayDec(),
    **                           respectively.
    ** 017 ECF 20091002   @44178 Added reportPrecisionScale() helper function to
    **                           report precision and scale of a numeric value.
    ** 018 GES 20110712          Javadoc fix.
    ** 019 AIL 20121206          Update from character to TextOps.
    ** 020 GES 20130224          Renamed julianDayDec/julianDayInt to toDec/toInt
    **                           which should be equivalent.
    ** 021 ECF 20130314          Added trim function.
    ** 022 CS  20130315          Added support for: to-rowid, length, weekday, chr,
    **                           date, caps, left-trim, maximum, minimum, logical,
    **                           num-entries and replace functions
    ** 023 OM  20130502          Switch to 64-bit integer computing (Long/int64).
    **                           Fixed small bugs that made some functions inaccessible.
    ** 024 OM  20130507          Added datetime/-tz support. However, since the numbers of possible
    **                           overloads methods for getTimestamp the method list is not complete.
    **                           Missing functionality will be added as needed.
    ** 025 OM  20140924          Added unix-escapes support for matches functions.
    **                           Added missing overloaded methods.
    ** 026 ECF 20141230          Added missing ltrimWS method variant.
    ** 027 ECF 20150928          Added error handling in toLogical variants to always return unknown
    **                           value (null) in the event of an otherwise unhandled error.
    ** 028 ECF 20151209          Minor documentation fixes.
    ** 029 OM  20151130          Added support for DATE(DATETIME) as toDate(Timestamp). Fixed javadoc
    **                           wrong references. Added HQLFunction annotation from methods exposed
    **                           as UDFs.
    ** 030 EVL 20160223          Javadoc fixes to make compatible with Oracle Java 8 for Solaris 10.
    ** 031 IAS 20160608          Fixed H2 alias for the 'entry' methods (OM).
    ** 032 OM  20160908          Added trimWS(s, l) function.
    ** 033 GES 20160804          Javadoc update.
    ** 034 HC  20170119          Added getFWDVersion() function.
    ** 035 OM  20180619          Added support for FILL function.
    **     ECF 20180622          Changed FILL parameters from primitive to class types.
    ** 036 ECF 20180830          Added contains function variants.
    ** 037 OM  20190301          Fixed numEntries() return value for null parameter values.
    ** 038 CA  20190821          Allow a specified set of characters to be used as word delimiters.
    ** 039 AIL 20191111          Change initialization of ErrorHandler's static context.
    ** 040 ECF 20200504          Added missing alias for entryIn(Long, String).
    ** 041 OM  20200212          Unknown value fixes.
    ** 042 IAS 20201121          Added 'words' functions.
    ** 043 IAS 20210407          Added 'fwdSession' function.
    ** 044 IAS 20210407          Added 'placeholder' version of
    **                           toString((date|datetime) value, fmt, sessionFormat)
    ** 045 IAS 20210905          Added 'placeholder' versions of
    **                           toString(datetime value, fmt, sessionFormat, sessionTimezone)
    **                           and toString(long value, fmt, sessionTimezone)
    ** 046 IAS 20210913          Only SQLException can be thrown on toString(dataetime ..)
    **     IAS 20210027          Only SQLException can be thrown on toLogical()
    **     IAS 20211112          Added 'native' signature to the 'matches' UDF
    **     TJD 20220504          Upgrade do Java 11 minor changes
    **     IAS 20220915          Added indexof(text, text, boolean) and lookup(text, text, boolean)
    **     IAS 20220919          Added tostring(bigint, text, integer)
    ** 047 GBB 20230512          Logging methods replaced by CentralLogger/ConversionStatus.
    ** 048 GBB 20230825          SecurityManager session methods calls updated.
    ** 049 DDF 20240410          Overload getInterval() for two datetime-tz values.
    **     DDF 20240411          Added all getInterval() overloads required for datetime-tz support.
    ** 050 EAB 20240614          Added toRowidString(Long).
    ** 051 SP  20240612          Retrieve the word delimiters using the new I18nOps.getWordDelimiters().
    ** 052 AS  20240718          Added support for DATE(DATETIME-TZ) as toDate(ValueTimestampTimeZone).
    ** 053 AI  20241010          Added support for substitute.
    ** 054 CA  20241030          Avoid 'Text.javaSpacifyNull' if the string is known to already have been
    **                           processed.
    ** 055 AI  20240123          Added support for getBits.
    ** 056 SP  20250314          Moved getDelimiterPattern() to I18nOps.
    */

    /*
    ** This program is free software: you can redistribute it and/or modify
    ** it under the terms of the GNU Affero General Public License as
    ** published by the Free Software Foundation, either version 3 of the
    ** License, or (at your option) any later version.
    **
    ** This program is distributed in the hope that it will be useful,
    ** but WITHOUT ANY WARRANTY; without even the implied warranty of
    ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    ** GNU Affero General Public License for more details.
    **
    ** You may find a copy of the GNU Affero GPL version 3 at the following
    ** location: https://www.gnu.org/licenses/agpl-3.0.en.html
    **
    ** Additional terms under GNU Affero GPL version 3 section 7:
    **
    **   Under Section 7 of the GNU Affero GPL version 3, the following additional
    **   terms apply to the works covered under the License.  These additional terms
    **   are non-permissive additional terms allowed under Section 7 of the GNU
    **   Affero GPL version 3 and may not be removed by you.
    **
    **   0. Attribution Requirement.
    **
    **     You must preserve all legal notices or author attributions in the covered
    **     work or Appropriate Legal Notices displayed by works containing the covered
    **     work.  You may not remove from the covered work any author or developer
    **     credit already included within the covered work.
    **
    **   1. No License To Use Trademarks.
    **
    **     This license does not grant any license or rights to use the trademarks
    **     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
    **     of Golden Code Development Corporation. You are not authorized to use the
    **     name Golden Code, FWD, or the names of any author or contributor, for
    **     publicity purposes without written authorization.
    **
    **   2. No Misrepresentation of Affiliation.
    **
    **     You may not represent yourself as Golden Code Development Corporation or FWD.
    **
    **     You may not represent yourself for publicity purposes as associated with
    **     Golden Code Development Corporation, FWD, or any author or contributor to
    **     the covered work, without written authorization.
    **
    **   3. No Misrepresentation of Source or Origin.
    **
    **     You may not represent the covered work as solely your work.  All modified
    **     versions of the covered work must be marked in a reasonable way to make it
    **     clear that the modified work is not originating from Golden Code Development
    **     Corporation or FWD.  All modified versions must contain the notices of
    **     attribution required in this license.
    */

    package com.goldencode.p2j.persist.pl;

    import java.math.*;
    import java.sql.*;
    import java.util.function.*;
    import com.goldencode.p2j.*;
    import com.goldencode.p2j.security.SecurityManager;
    import com.goldencode.p2j.util.*;
    import com.goldencode.p2j.util.logging.*;

    import org.h2.value.ValueTimestampTimeZone;

    /**
     * A collection of static methods which provide the backing functionality for Progress-like
     * built-in functions, which are executed within the database server as custom, Java-language
     * functions.  This provides a much faster alternative to client-side where clause processing.
     * This mechanism (or client-side where clause processing) must be used in cases where a function
     * converted from Progress code must retain semantics specific to the Progress environment.
     * Executing these operations on the server is much preferred, since moving records across the
     * network only to test them for inclusion in a result set is prohibitively expensive.
     * <p>
     * This class serves primarily as a consolidation point and dispatcher for
     * worker methods located in diverse classes.  All method calls made by the
     * database server are redirected to those worker methods.  However, since
     * the database server knows nothing of the P2J wrapper types used by those
     * methods to represent primitives, this class also performs a transformation
     * to (on input) and from (on output) the P2J wrapper types.  Thus, all
     * parameters and return types for methods in this class are specified in
     * terms of the standard J2SE wrapper types or primitive types.
     * <p>
     * The transformation handles conversion between <code>null</code> J2SE
     * wrapper types and the implementation of <code>unknown value</code> in the
     * P2J wrapper types.  This is possible because unknown value maps to SQL
     * NULL in the backing database.  However, certain data can be lost in the
     * transformation, and if these data are necessary, this mechanism should be
     * avoided.  Instead, client-side where clause processing should be used in
     * these cases.  Specifically, the following data are not represented by J2SE
     * wrappers or primitives and thus cannot be preserved during transformation:
     * <ul>
     *   <li>non-default precision of a <code>decimal</code> value;
     *   <li>non-default case sensitivity of a <code>character</code> value;
     *   <li>non-default timezone of a <code>date</code> value.
     * </ul>
     *
     * @see  Operators
     */
    public final class Functions
    {
       /** Logger */
       private static final CentralLogger LOG = CentralLogger.get(Functions.class);

       /** The character encoding used to get word delimiters */
       private static String codePage = I18nOps._getCPInternal();

       static
       {
          // make sure static initialization take place before using functions
          try
          {
             Class.forName("com.goldencode.p2j.persist.pl.ErrorHandler");
          }
          catch (ClassNotFoundException e)
          {
             ErrorHandler.handleError(new RuntimeException(e));
          }
       }

       /**
        * Test whether one string begins with another case insensitively.
        *
        * @see  com.goldencode.p2j.util.TextOps#begins(Text, character)
        */
       @HQLFunction
       public static Boolean begins(String a, String b)
       {
          try
          {
             return TextOps.begins(new character(a), new character(b)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Test whether one string begins with another, optionally taking case
        * into account.
        *
        * @see  com.goldencode.p2j.util.TextOps#begins(String, String, boolean)
        */
       @HQLFunction
       public static Boolean begins(String a, String b, boolean caseSensitive)
       {
          try
          {
             return TextOps.begins(a, b, caseSensitive).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Split a string to an array of words
        *
        * @param data
        *        string to be parsed
        *
        * @return words contained in a string
        */
       @HQLFunction
       public static String[] words(String data)
       {
          return words(data, false);
       }

       /**
        * Split a string to an array of words
        *
        * @param data
        *        string to be parsed
        * @param toUpperCase
        *        convert words to uppercase
        *
        * @return words contained in a string
        */
       @HQLFunction
       public static String[] words(String data, boolean toUpperCase)
       {
          if (data == null)
          {
             return new String[0];
          }
          try
          {
             return new Contains(null, !toUpperCase, codePage).
                   words(data.trim(), toUpperCase).toArray(new String[0]);
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Split a string to an array of words
        *
        * @param data
        *        string to be parsed
        * @param toUpperCase
        *        convert words to uppercase
        * @param forCaseInsensitive
        *        return words which are unique in case-insensitive sense
        *
        * @return words contained in a string
        */
       @HQLFunction
       public static String[] words(String data, boolean toUpperCase, boolean forCaseInsensitive)
       {
          if (data == null)
          {
             return new String[0];
          }
          try
          {
             return new Contains(null, !toUpperCase, codePage).
                   words(data.trim(), forCaseInsensitive).toArray(new String[0]);
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Test whether a data string contains the word(s) indicated by the given expression.
        * optionally taking case into account.
        */
       @HQLFunction
       public static Boolean contains(String data, String expr)
       {
          return contains(data, expr, false);
       }

       /**
        * Test whether a data string contains the word(s) indicated by the given expression.
        * optionally taking case into account.
        */
       @HQLFunction
       public static Boolean contains(String data, String expr, boolean caseSensitive)
       {
          try
          {
             return new Contains(expr, caseSensitive, codePage).evaluate(data);
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Set the code page (character encoding) for selecting the delimiters
        * used for word splitting. If {@code codePage} is null, then the value
        * of {@code I18nOps._getCPInternal()} is used.
        *
        * @param   codePage
        *          Character encoding used for selecting the delimiters.
        */
       public static void setCodePage(String codePage)
       {
          if (codePage == null)
          {
             codePage = I18nOps._getCPInternal();
          }
          Functions.codePage = codePage;
       }

       /**
        * Returns the character value of a numeric expression which must be
        * between 1 and 65534 (inclusive).
        *
        * @see  com.goldencode.p2j.util.character#chr(long)
        */
       @HQLFunction(name = "toChr")
       public static String chr(Long value)
       {
          try
          {
             return character.chr(new integer(value)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the character value of a numeric expression which must be
        * between 1 and 65534 (inclusive).
        *
        * @see  com.goldencode.p2j.util.character#chr(long)
        */
       @HQLFunction(name = "toChr")
       public static String chr(Integer value)
       {
          return chr(toLong(value));
       }

       /**
        * Test for a pattern match within a string case insensitively.
        *
        * @see  com.goldencode.p2j.util.TextOps#matches(Text, character, boolean)
        */
       @HQLFunction
       public static Boolean matches(String a, String b)
       {
          try
          {
             return TextOps.matches(new character(a), new character(b), false).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Test for a pattern match within a string case insensitively.
        *
        * @see  com.goldencode.p2j.util.TextOps#matches(Text, character, boolean)
        */
       @HQLFunction
       public static Boolean matches(String a, String b, Boolean windows)
       {
          try
          {
             return TextOps.matches(new character(a), new character(b), windows).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Test for a pattern match within a string, optionally taking case into account.
        *
        * @see  com.goldencode.p2j.util.TextOps#matches(String, String, boolean, boolean)
        */
       @HQLFunction
       public static Boolean matches(String a, String b, Boolean caseSensitive, Boolean windows)
       {
          try
          {
             return TextOps.matches(a, b, caseSensitive, windows).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the 1-based index at which one string is found within another,
        * or 0 if the string is not found.
        *
        * @see  com.goldencode.p2j.util.TextOps#indexOf(Text, Text)
        */
       @HQLFunction
       public static Long indexOf(String source, String target)
       {
          try
          {
             return TextOps.indexOf(new character(source),
                                    new character(target)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the 1-based index at which one string is found within another,
        * or 0 if the string is not found, starting at a particular index.
        *
        * @see  com.goldencode.p2j.util.TextOps#indexOf(Text, Text, NumberType)
        */
       @HQLFunction
       public static Long indexOf(String source, String target, Long start)
       {
          try
          {
             return TextOps.indexOf(new character(source),
                                    new character(target),
                                    new integer(start)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the 1-based index at which one string is found within another,
        * or 0 if the string is not found, starting at a particular index.
        *
        * @see  com.goldencode.p2j.util.TextOps#indexOf(Text, Text, NumberType)
        */
       @HQLFunction
       public static Long indexOf(String source, String target, Integer start)
       {
          return indexOf(source, target, toLong(start));
       }

       /**
        * Retrieve the 1-based index at which one string is found within another,
        * or 0 if the string is not found, starting at a particular index.
        *
        * @see  com.goldencode.p2j.util.TextOps#indexOf(Text, Text, NumberType)
        */
       @HQLFunction
       public static Long indexOf(String source, String target, BigDecimal start)
       {
          try
          {
             return TextOps.indexOf(new character(source),
                                    new character(target),
                                    new integer(start)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the 1-based index at which one string is found within another,
        * or 0 if the string is not found, starting at a particular index,
        * optionally taking case into account.
        *
        * @see  com.goldencode.p2j.util.TextOps#indexOf(
        *          java.lang.String,
        *          java.lang.String,
        *          double,
        *          boolean)
        */
       @HQLFunction
       public static Long indexOf(String source, String target, Long start, boolean caseSensitive)
       {
          try
          {
             return TextOps.indexOf(source, target, start, caseSensitive).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the 1-based index at which one string is found within another,
        * or 0 if the string is not found, starting at a particular index,
        * optionally taking case into account.
        *
        * @see  com.goldencode.p2j.util.TextOps#indexOf(
        *          java.lang.String,
        *          java.lang.String,
        *          double,
        *          boolean)
        */
       @HQLFunction
       public static Long indexOf(String source, String target, boolean caseSensitive)
       {
          return indexOf(source, target, 0, caseSensitive);
       }

       /**
        * Retrieve the 1-based index at which one string is found within another,
        * or 0 if the string is not found, starting at a particular index,
        * optionally taking case into account.
        *
        * @see  com.goldencode.p2j.util.TextOps#indexOf(
        *          java.lang.String,
        *          java.lang.String,
        *          double,
        *          boolean)
        */
       @HQLFunction
       public static Long indexOf(String source, String target, Integer start, boolean caseSensitive)
       {
          return indexOf(source, target, toLong(start), caseSensitive);
       }

       /**
        * Retrieve the 1-based index at which one string is found within another,
        * or 0 if the string is not found, starting at a particular index,
        * optionally taking case into account.
        *
        * @see  com.goldencode.p2j.util.TextOps#indexOf(
        *          java.lang.String,
        *          java.lang.String,
        *          double,
        *          boolean)
        */
       @HQLFunction
       public static Long indexOf(String source,
                                  String target,
                                  BigDecimal start,
                                  boolean caseSensitive)
       {
          try
          {
             return TextOps.indexOf(source,
                                    target,
                                    start.intValue(),
                                    caseSensitive).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>integer</code>, then return it
        * as a J2SE <code>Long</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.integer#integer(java.lang.Boolean)
        */
       @HQLFunction
       public static Long toInt(Boolean value)
       {
          try
          {
             return (new integer(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>integer</code>, then return it
        * as a J2SE <code>Long</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.integer#integer(java.lang.Number)
        */
       @HQLFunction
       public static Long toInt(Long value)
       {
          try
          {
             return (new integer(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>integer</code>, then return it
        * as a J2SE <code>Long</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.integer#integer(java.lang.Number)
        */
       @HQLFunction
       public static Long toInt(Integer value)
       {
          return toInt(toLong(value));
       }

       /**
        * Transform the given value into an <code>integer</code>, then return it
        * as a J2SE <code>Long</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.integer#integer(java.lang.Number)
        */
       @HQLFunction
       public static Long toInt(BigDecimal value)
       {
          try
          {
             return (new integer(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>integer</code>, then return it
        * as a J2SE <code>Long</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.integer#integer(java.lang.String)
        */
       @HQLFunction
       public static Long toInt(String value)
       {
          try
          {
             return (new integer(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>integer</code>, then return it as a J2SE
        * <code>Long</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.date#longValue()
        */
       @HQLFunction
       public static Long toInt(Date value)
       {
          try
          {
             return new date(value).longValue();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>int64</code>, then return it
        * as a J2SE <code>Long</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.int64#int64(java.lang.Boolean)
        */
       @HQLFunction
       public static Long toInt64(Boolean value)
       {
          try
          {
             return (new int64(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>int64</code>, then return it
        * as a J2SE <code>Long</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.int64#int64(java.lang.Number)
        */
       @HQLFunction
       public static Long toInt64(Long value)
       {
          try
          {
             return (new int64(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>integer</code>, then return it
        * as a J2SE <code>Long</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.int64#int64(java.lang.Number)
        */
       @HQLFunction
       public static Long toInt64(Integer value)
       {
          return toInt64(toLong(value));
       }

       /**
        * Transform the given value into an <code>int64</code>, then return it
        * as a J2SE <code>Long</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.int64#int64(java.lang.Number)
        */
       @HQLFunction
       public static Long toInt64(BigDecimal value)
       {
          try
          {
             return (new int64(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>int64</code>, then return it
        * as a J2SE <code>Long</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.int64#int64(java.lang.String)
        */
       @HQLFunction
       public static Long toInt64(String value)
       {
          try
          {
             return (new int64(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>int64</code>, then return it as a J2SE
        * <code>Long</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.date#longValue()
        */
       @HQLFunction
       public static Long toInt64(Date value)
       {
          try
          {
             return new date(value).longValue();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into a <code>decimal</code>, then return it
        * as a J2SE <code>BigDecimal</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.decimal#decimal(
        *          com.goldencode.p2j.util.logical)
        */
       @HQLFunction
       public static BigDecimal toDec(Boolean value)
       {
          try
          {
             return (new decimal(new logical(value))).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into a <code>decimal</code>, then return it
        * as a J2SE <code>BigDecimal</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.decimal#decimal(java.lang.Number)
        */
       @HQLFunction
       public static BigDecimal toDec(Long value)
       {
          try
          {
             return (new decimal(value)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into a <code>decimal</code>, then return it
        * as a J2SE <code>BigDecimal</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.decimal#decimal(java.lang.Number)
        */
       @HQLFunction
       public static BigDecimal toDec(Integer value)
       {
          return toDec(toLong(value));
       }

       /**
        * Return the given <code>BigDecimal</code> value.  Do not alter the
        * precision.
        *
        * @param   value
        *          decimal numeric value.
        */
       @HQLFunction
       public static BigDecimal toDec(BigDecimal value)
       {
          return value;
       }

       /**
        * Return the given <code>BigDecimal</code> value after applying the given
        * precision.  This function is provided for the special case of a literal
        * value, where the default precision derived from that literal is not
        * appropriate.
        *
        * @param   value
        *          Decimal numeric value.
        * @param   precision
        *          Precision to apply.
        */
       @HQLFunction
       public static BigDecimal toDec(BigDecimal value, Long precision)
       {
          try
          {
             return value.setScale(precision.intValue(), RoundingMode.HALF_UP);
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Return the given <code>BigDecimal</code> value after applying the given
        * precision.  This function is provided for the special case of a literal
        * value, where the default precision derived from that literal is not
        * appropriate.
        *
        * @param   value
        *          Decimal numeric value.
        * @param   precision
        *          Precision to apply.
        */
       @HQLFunction
       public static BigDecimal toDec(BigDecimal value, Integer precision)
       {
          return toDec(value, toLong(precision));
       }

       /**
        * Transform the given value into a <code>decimal</code>, then return it
        * as a J2SE <code>BigDecimal</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.decimal#decimal(java.lang.String)
        */
       @HQLFunction
       public static BigDecimal toDec(String value)
       {
          try
          {
             return (new decimal(value)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into a <code>decimal</code>, then return it
        * as a J2SE <code>BigDecimal</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.decimal#decimal(
        *          com.goldencode.p2j.util.date)
        */
       @HQLFunction
       public static BigDecimal toDec(Date value)
       {
          try
          {
             return (new decimal(new date(value))).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(boolean)
        */
       @HQLFunction
       public static String toString(Boolean value)
       {
          try
          {
             return character.valueOf(new logical(value)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(boolean,String)
        */
       @HQLFunction
       public static String toString(Boolean value, String fmt)
       {
          try
          {
             return character.valueOf(new logical(value), fmt).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(long)
        */
       @HQLFunction
       public static String toString(Long value)
       {
          try
          {
             return character.valueOf(new int64(value)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(long)
        */
       @HQLFunction
       public static String toString(Integer value)
       {
          return toString(toLong(value));
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(long,String)
        */
       @HQLFunction
       public static String toString(Long value, String fmt)
       {
          try
          {
             return character.valueOf(new int64(value), fmt).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(long,String)
        */
       @HQLFunction
       public static String toString(Long value, String fmt, String sessionTimezone)
       {
          try
          {
             return character.valueOf(new int64(value), fmt).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(long,String)
        */
       @HQLFunction
       public static String toString(Long value, String fmt, Integer sessionTimezone)
       {
          try
          {
             return character.valueOf(new int64(value), fmt).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(long,String)
        */
       @HQLFunction
       public static String toString(Integer value, String fmt)
       {
          return toString(toLong(value), fmt);
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(BaseDataType)
        */
       @HQLFunction
       public static String toString(Date value)
       {
          try
          {
             return character.valueOf(new date(value)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(BaseDataType,String)
        */
       @HQLFunction
       public static String toString(Date value, String fmt)
       {
          try
          {
             return character.valueOf(new date(value), fmt).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(BaseDataType,String)
        */
       @HQLFunction
       public static String toString(Date value, String fmt, String sessionDateFormat)
       {
          // Just ignore the third parameter for now
          // TODO: provide 'real' implementation
          return toString(value, fmt);
       }

       /**
        * Transform the given datetime value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(BaseDataType)
        */
       @HQLFunction
       public static String toString(Timestamp value)
       {
          try
          {
             return character.valueOf(new datetime(value)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given datetime value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        * @throws SQLException
        *
        * @see  com.goldencode.p2j.util.character#valueOf(BaseDataType,String)
        */
       @HQLFunction
       public static String toString(Timestamp value, String fmt)
       throws SQLException
       {
          return guarded(() -> character.valueOf(new datetime(value), fmt).toJavaType());
       }

       /**
        * Transform the given datetime value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        * @throws SQLException
        *
        * @see  com.goldencode.p2j.util.character#valueOf(BaseDataType,String)
        */
       @HQLFunction
       public static String toString(Timestamp value, String fmt, String sessionDateFormat)
       throws SQLException
       {
          // Just ignore the third parameter for now
          // TODO: provide 'real' implementation
          return toString(value, fmt);
       }

       /**
        * Transform the given datetime value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(BaseDataType,String)
        */
       @HQLFunction
       public static String toString(Timestamp value, String fmt, String sessionDateFormat,
                                     int sessionTimezone)
       throws SQLException
       {
          // Just ignore the third parameter for now
          // TODO: provide 'real' implementation
          return toString(value, fmt);
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(double)
        */
       @HQLFunction
       public static String toString(BigDecimal value)
       {
          try
          {
             return character.valueOf(new decimal(value)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(double,String)
        */
       @HQLFunction
       public static String toString(BigDecimal value, String fmt)
       {
          try
          {
             return character.valueOf(new decimal(value), fmt).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Simply return the given string.  Normally, the value would be converted
        * to a <code>character</code>, then back to a J2SE <code>String</code>,
        * but this method short-circuits that unnecessary, round trip.
        *
        * @param   value
        *          String to be returned.
        *
        * @return  <code>value</code> parameter, unchanged.
        */
       @HQLFunction
       public static String toString(String value)
       {
          try
          {
             return character.valueOf(new character(value)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>character</code>, then return
        * it as a J2SE <code>String</code>, or <code>null</code> if unknown.
        *
        * @see  com.goldencode.p2j.util.character#valueOf(String,String)
        */
       @HQLFunction
       public static String toString(String value, String fmt)
       {
          try
          {
             return character.valueOf(new character(value), fmt).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Transform the given value into an <code>character</code> that represents
        * its hexadecimal form.
        *
        * @param   value
        *          The value to be transformed into its hexadecimal form.
        *
        * @return   A string which represents hexadecimal form of the value.
        */
       @HQLFunction
       public static String toRowidString(Long value)
       {
          try
          {
              return new rowid(value).toString();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the rowid representation of a String value, as a Long.
        *
        * @see  com.goldencode.p2j.util.rowid#parseRowidString
        */
       @HQLFunction
       public static Long toRowid(String text)
       {
          try
          {
             return rowid.parseRowidString(text);
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Concatenate two strings using P2J character's default behavior.  Return
        * the result as a J2SE <code>String</code>, or <code>null</code> if
        * unknown.
        *
        * @see  com.goldencode.p2j.util.TextOps#concat
        */
       @HQLFunction
       public static String concat(String a, String b)
       {
          try
          {
             return TextOps.concat(new character(a),
                                   new character(b)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Perform positional replacement of '&amp;n' specifiers in the format string {@code fmt},
        * using available replacements. Any specifiers that do not correspond to an object in the array are
        * replaced with an empty string.
        *
        * @param    fmt
        *           The string specifying the text and format specifiers
        *
        * @return   The resulting string.
        */
       @HQLFunction
       public static String substitute(String fmt)
       {
          try
          {
             return TextOps.substitute(fmt).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Perform positional replacement of '&amp;n' specifiers in the format string {@code fmt},
        * using available replacements. Any specifiers that do not correspond to an object in the array are
        * replaced with an empty string.
        *
        * @param    fmt
        *           The string specifying the text and format specifiers.
        * @param    repl1
        *           Replacement string for 1st position.
        *
        * @return   The resulting string.
        */
       @HQLFunction
       public static String substitute(String fmt, String repl1)
       {
          try
          {
             return TextOps.substitute(fmt, repl1).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Perform positional replacement of '&amp;n' specifiers in the format string {@code fmt},
        * using available replacements. Any specifiers that do not correspond to an object in the array are
        * replaced with an empty string.
        *
        * @param    fmt
        *           The string specifying the text and format specifiers.
        * @param    repl1
        *           Replacement string for 1st position.
        * @param    repl2
        *           Replacement string for 2nd position.
        *
        * @return   The resulting string.
        */
       @HQLFunction
       public static String substitute(String fmt, String repl1, String repl2)
       {
          try
          {
             return TextOps.substitute(fmt, repl1, repl2).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Perform positional replacement of '&amp;n' specifiers in the format string {@code fmt},
        * using available replacements. Any specifiers that do not correspond to an object in the array are
        * replaced with an empty string.
        *
        * @param    fmt
        *           The string specifying the text and format specifiers.
        * @param    repl1
        *           Replacement string for 1st position.
        * @param    repl2
        *           Replacement string for 2nd position.
        * @param    repl3
        *           Replacement string for 3rd position.
        *
        * @return   The resulting string.
        */
       @HQLFunction
       public static String substitute(String fmt, String repl1, String repl2, String repl3)
       {
          try
          {
             return TextOps.substitute(fmt, repl1, repl2, repl3).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Perform positional replacement of '&amp;n' specifiers in the format string {@code fmt},
        * using available replacements. Any specifiers that do not correspond to an object in the array are
        * replaced with an empty string.
        *
        * @param    fmt
        *           The string specifying the text and format specifiers.
        * @param    repl1
        *           Replacement string for 1st position.
        * @param    repl2
        *           Replacement string for 2nd position.
        * @param    repl3
        *           Replacement string for 3rd position.
        * @param    repl4
        *           Replacement string for 4th position.
        *
        * @return   The resulting string.
        */
       @HQLFunction
       public static String substitute(String fmt, String repl1, String repl2, String repl3, String repl4)
       {
          try
          {
             return TextOps.substitute(fmt, repl1, repl2, repl3, repl4).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Perform positional replacement of '&amp;n' specifiers in the format string {@code fmt},
        * using available replacements. Any specifiers that do not correspond to an object in the array are
        * replaced with an empty string.
        *
        * @param    fmt
        *           The string specifying the text and format specifiers.
        * @param    repl1
        *           Replacement string for 1st position.
        * @param    repl2
        *           Replacement string for 2nd position.
        * @param    repl3
        *           Replacement string for 3rd position.
        * @param    repl4
        *           Replacement string for 4th position.
        * @param    repl5
        *           Replacement string for 5th position.
        *
        * @return   The resulting string.
        */
       @HQLFunction
       public static String substitute(String fmt, String repl1, String repl2, String repl3, String repl4,
                                       String repl5)
       {
          try
          {
             return TextOps.substitute(fmt, repl1, repl2, repl3, repl4, repl5).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Perform positional replacement of '&amp;n' specifiers in the format string {@code fmt},
        * using available replacements. Any specifiers that do not correspond to an object in the array are
        * replaced with an empty string.
        *
        * @param    fmt
        *           The string specifying the text and format specifiers.
        * @param    repl1
        *           Replacement string for 1st position.
        * @param    repl2
        *           Replacement string for 2nd position.
        * @param    repl3
        *           Replacement string for 3rd position.
        * @param    repl4
        *           Replacement string for 4th position.
        * @param    repl5
        *           Replacement string for 5th position.
        * @param    repl6
        *           Replacement string for 6th position.
        *
        * @return   The resulting string.
        */
       @HQLFunction
       public static String substitute(String fmt, String repl1, String repl2, String repl3, String repl4,
                                       String repl5, String repl6)
       {
          try
          {
             return TextOps.substitute(fmt, repl1, repl2, repl3, repl4, repl5, repl6).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Perform positional replacement of '&amp;n' specifiers in the format string {@code fmt},
        * using available replacements. Any specifiers that do not correspond to an object in the array are
        * replaced with an empty string.
        *
        * @param    fmt
        *           The string specifying the text and format specifiers.
        * @param    repl1
        *           Replacement string for 1st position.
        * @param    repl2
        *           Replacement string for 2nd position.
        * @param    repl3
        *           Replacement string for 3rd position.
        * @param    repl4
        *           Replacement string for 4th position.
        * @param    repl5
        *           Replacement string for 5th position.
        * @param    repl6
        *           Replacement string for 6th position.
        * @param    repl7
        *           Replacement string for 7th position.
        *
        * @return   The resulting string.
        */
       @HQLFunction
       public static String substitute(String fmt, String repl1, String repl2, String repl3, String repl4,
                                       String repl5, String repl6, String repl7)
       {
          try
          {
             return TextOps.substitute(fmt, repl1, repl2, repl3, repl4, repl5, repl6, repl7).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Perform positional replacement of '&amp;n' specifiers in the format string {@code fmt},
        * using available replacements. Any specifiers that do not correspond to an object in the array are
        * replaced with an empty string.
        *
        * @param    fmt
        *           The string specifying the text and format specifiers.
        * @param    repl1
        *           Replacement string for 1st position.
        * @param    repl2
        *           Replacement string for 2nd position.
        * @param    repl3
        *           Replacement string for 3rd position.
        * @param    repl4
        *           Replacement string for 4th position.
        * @param    repl5
        *           Replacement string for 5th position.
        * @param    repl6
        *           Replacement string for 6th position.
        * @param    repl7
        *           Replacement string for 7th position.
        * @param    repl8
        *           Replacement string for 8th position.
        *
        * @return   The resulting string.
        */
       @HQLFunction
       public static String substitute(String fmt, String repl1, String repl2, String repl3, String repl4,
                                       String repl5, String repl6, String repl7, String repl8)
       {
          try
          {
             return TextOps.substitute(fmt, repl1, repl2, repl3, repl4, repl5, repl6, repl7, repl8).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Perform positional replacement of '&amp;n' specifiers in the format string {@code fmt},
        * using available replacements. Any specifiers that do not correspond to an object in the array are
        * replaced with an empty string.
        *
        * @param    fmt
        *           The string specifying the text and format specifiers.
        * @param    repl1
        *           Replacement string for 1st position.
        * @param    repl2
        *           Replacement string for 2nd position.
        * @param    repl3
        *           Replacement string for 3rd position.
        * @param    repl4
        *           Replacement string for 4th position.
        * @param    repl5
        *           Replacement string for 5th position.
        * @param    repl6
        *           Replacement string for 6th position.
        * @param    repl7
        *           Replacement string for 7th position.
        * @param    repl8
        *           Replacement string for 8th position.
        * @param    repl9
        *           Replacement string for 9th position.
        *
        * @return   The resulting string.
        */
       @HQLFunction
       public static String substitute(String fmt, String repl1, String repl2, String repl3, String repl4,
                                       String repl5, String repl6, String repl7, String repl8, String repl9)
       {
          try
          {
             return TextOps.substitute(fmt, repl1, repl2, repl3, repl4, repl5, repl6, repl7, repl8, repl9)
                           .toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Extract a substring from a string, starting at a specific index.
        *
        * @see  com.goldencode.p2j.util.TextOps#substring
        */
       @HQLFunction
       public static String substringOf(String text, Long pos)
       {
          try
          {
             return TextOps.substring(new character(text), new integer(pos)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Extract a substring from a string, starting at a specific index.
        *
        * @see  com.goldencode.p2j.util.TextOps#substring
        */
       @HQLFunction
       public static String substringOf(String text, Integer pos)
       {
          return substringOf(text, toLong(pos));
       }

       /**
        * Extract a substring of a specific length from a string, starting at a
        * specific index.
        *
        * @see  com.goldencode.p2j.util.TextOps#substring
        */
       @HQLFunction
       public static String substringOf(String text, Long pos, Long len)
       {
          try
          {
             return TextOps.substring(new character(text),
                                      new integer(pos),
                                      new integer(len)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Extract a substring of a specific length from a string, starting at a
        * specific index.
        *
        * @see  com.goldencode.p2j.util.TextOps#substring
        */
       @HQLFunction
       public static String substringOf(String text, Long pos, Integer len)
       {
          return substringOf(text, pos, toLong(len));
       }

       /**
        * Extract a substring of a specific length from a string, starting at a
        * specific index.
        *
        * @see  com.goldencode.p2j.util.TextOps#substring
        */
       @HQLFunction
       public static String substringOf(String text, Integer pos, Long len)
       {
          return substringOf(text, toLong(pos), len);
       }

       /**
        * Extract a substring of a specific length from a string, starting at a
        * specific index.
        *
        * @see  com.goldencode.p2j.util.TextOps#substring
        */
       @HQLFunction
       public static String substringOf(String text, Integer pos, Integer len)
       {
          return substringOf(text, toLong(pos), toLong(len));
       }

       /**
        * Extract a substring of a specific length and Progress type from a
        * string, starting at a specific index.
        *
        * @see  com.goldencode.p2j.util.TextOps#substring
        */
       @HQLFunction
       public static String substringOf(String text, Long pos, Long len, String type)
       {
          try
          {
             return TextOps.substring(new character(text),
                                      new integer(pos),
                                      new integer(len),
                                      new character(type)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Extract a substring of a specific length and Progress type from a
        * string, starting at a specific index.
        *
        * @see  com.goldencode.p2j.util.TextOps#substring
        */
       @HQLFunction
       public static String substringOf(String text, Long pos, Integer len, String type)
       {
          return substringOf(text, pos, toLong(len), type);
       }

       /**
        * Extract a substring of a specific length and Progress type from a
        * string, starting at a specific index.
        *
        * @see  com.goldencode.p2j.util.TextOps#substring
        */
       @HQLFunction
       public static String substringOf(String text, Integer pos, Long len, String type)
       {
          return substringOf(text, toLong(pos), len, type);
       }

       /**
        * Extract a substring of a specific length and Progress type from a
        * string, starting at a specific index.
        *
        * @see  com.goldencode.p2j.util.TextOps#substring
        */
       @HQLFunction
       public static String substringOf(String text, Integer pos, Integer len, String type)
       {
          return substringOf(text, toLong(pos), toLong(len), type);
       }

       /**
        * Returns the maximum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The maximum of the given values.
        */
       @HQLFunction
       public static BigDecimal maximum(BigDecimal var1, BigDecimal var2)
       {
          try
          {
             return decimal.maximum(new decimal(var1), new decimal(var2)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the maximum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The maximum of the given values.
        */
       @HQLFunction
       public static BigDecimal maximum(Long var1, BigDecimal var2)
       {
          try
          {
             return decimal.maximum(new int64(var1), new decimal(var2)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the maximum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The maximum of the given values.
        */
       @HQLFunction
       public static BigDecimal maximum(Integer var1, BigDecimal var2)
       {
          return maximum(toLong(var1), var2);
       }

       /**
        * Returns the maximum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The maximum of the given values.
        */
       @HQLFunction
       public static BigDecimal maximum(BigDecimal var1, Long var2)
       {
          try
          {
             return decimal.maximum(new decimal(var1), new int64(var2)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the maximum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The maximum of the given values.
        */
       @HQLFunction
       public static BigDecimal maximum(BigDecimal var1, Integer var2)
       {
          return maximum(var1, toLong(var2));
       }

       /**
        * Returns the maximum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The maximum of the given values.
        */
       @HQLFunction
       public static Long maximum(Long var1, Long var2)
       {
          try
          {
             return int64.maximum(new int64(var1), new int64(var2)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the maximum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The maximum of the given values.
        */
       @HQLFunction
       public static Long maximum(Long var1, Integer var2)
       {
          return maximum(var1, toLong(var2));
       }

       /**
        * Returns the maximum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The maximum of the given values.
        */
       @HQLFunction
       public static Long maximum(Integer var1, Long var2)
       {
          return maximum(toLong(var1), var2);
       }

       /**
        * Returns the maximum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The maximum of the given values.
        */
       @HQLFunction
       public static Long maximum(Integer var1, Integer var2)
       {
          return maximum(toLong(var1), toLong(var2));
       }

       /**
        * Returns the maximum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The maximum of the given values.
        */
       @HQLFunction
       public static String maximum(String var1, String var2)
       {
          try
          {
             return TextOps.maximum(new character(var1), new character(var2)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the maximum from a list of date values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The maximum of the given values.
        */
       @HQLFunction
       public static Date maximum(Date var1, Date var2)
       {
          try
          {
             return new Date(date.maximum(new date(var1), new date(var2)).dateValue().getTime()); // TODO: what if [var1] or [var2] is unknown?
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the maximum from a list of datetime values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The maximum of the given values.
        */
       @HQLFunction
       public static Timestamp maximum(Timestamp var1, Timestamp var2)
       {
          try
          {
             return new Timestamp(datetime.maximum(new datetime(var1), new datetime(var2))
                             .dateValue().getTime()); // TODO: what if [var1] or [var2] is unknown?
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the minimum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The minimum of the given values.
        */
       @HQLFunction
       public static BigDecimal minimum(BigDecimal var1, BigDecimal var2)
       {
          try
          {
             return decimal.minimum(new decimal(var1), new decimal(var2)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the minimum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The minimum of the given values.
        */
       @HQLFunction
       public static BigDecimal minimum(Long var1, BigDecimal var2)
       {
          try
          {
             return decimal.minimum(new int64(var1), new decimal(var2)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the minimum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The minimum of the given values.
        */
       @HQLFunction
       public static BigDecimal minimum(Integer var1, BigDecimal var2)
       {
          return minimum(toLong(var1), var2);
       }

       /**
        * Returns the minimum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The minimum of the given values.
        */
       @HQLFunction
       public static BigDecimal minimum(BigDecimal var1, Long var2)
       {
          try
          {
             return decimal.minimum(new decimal(var1), new int64(var2)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the minimum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The minimum of the given values.
        */
       @HQLFunction
       public static BigDecimal minimum(BigDecimal var1, Integer var2)
       {
          return minimum(var1, toLong(var2));
       }

       /**
        * Returns the minimum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The minimum of the given values.
        */
       @HQLFunction
       public static Long minimum(Long var1, Long var2)
       {
          try
          {
             return int64.minimum(new int64(var1), new int64(var2)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the minimum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The minimum of the given values.
        */
       @HQLFunction
       public static Long minimum(Long var1, Integer var2)
       {
          return minimum(var1, toLong(var2));
       }

       /**
        * Returns the minimum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The minimum of the given values.
        */
       @HQLFunction
       public static Long minimum(Integer var1, Long var2)
       {
          return minimum(toLong(var1), var2);
       }

       /**
        * Returns the minimum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The minimum of the given values.
        */
       @HQLFunction
       public static Long minimum(Integer var1, Integer var2)
       {
          return minimum(toLong(var1), toLong(var2));
       }

       /**
        * Returns the minimum from a list of values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The minimum of the given values.
        */
       @HQLFunction
       public static String minimum(String var1, String var2)
       {
          try
          {
             return TextOps.minimum(new character(var1), new character(var2)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the minimum from a list of date values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The minimum of the given values.
        */
       @HQLFunction
       public static Date minimum(Date var1, Date var2)
       {
          try
          {
             return new Date(date.minimum(new date(var1), new date(var2)).dateValue().getTime()); // TODO: what if [var1] or [var2] is unknown?
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the minimum from a list of datetime values.
        *
        * @param   var1
        *          Value 1.
        * @param   var2
        *          Value 2.
        *
        * @return  The minimum of the given values.
        */
       @HQLFunction
       public static Timestamp minimum(Timestamp var1, Timestamp var2)
       {
          try
          {
             return new Timestamp(datetime.minimum(new datetime(var1), new datetime(var2))
                             .dateValue().getTime()); // TODO: what if [var1] or [var2] is unknown?
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns logical representation of a char variable from a format of type "true/false".
        *
        * @param   var
        *          The variable we want to match against the logical format
        *
        * @return  The logical representation of a char variable from a format of type "true/false"
        */
       @HQLFunction
       public static Boolean toLogical(String var)
       {
          try
          {
             return new logical(var).toJavaType();
          }
          catch (RuntimeException exc)
          {
             try
             {
                ErrorHandler.handleError(exc);
             }
             catch (RuntimeException exc2)
             {
                // ignore; we'll return null (i.e., unknown value) below
             }

             return null;
          }
       }

       /**
        * Returns logical representation of a char variable from a format of type "true/false".
        *
        * @param   var
        *          The variable we want to match against the logical format
        * @param   format
        *          The format of form "leftLogical/rightLogical" in which leftLogical will represent
        *          <code>true</code> and rightLogical represents <code>false</code>
        *
        * @return  The logical representation of a char variable from a format of type "true/false"
        * @throws SQLException
        */
       @HQLFunction
       public static Boolean toLogical(String var, String format)
       throws SQLException
       {
          return guarded(() -> new logical(var, format).toJavaType());
       }

       /**
        * Replaces the given values into the destination.
        *
        * @see  com.goldencode.p2j.util.TextOps#replaceAll
        */
       @HQLFunction(name = "replaceText")
       public static String replace(String source, String toReplace, String replacement)
       {
          try
          {
             return TextOps.replaceAll(source, toReplace, replacement).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Trim white space from the left side of text.
        *
        * @see  com.goldencode.p2j.util.TextOps#leftTrim
        */
       @HQLFunction(name = "ltrimws")
       public static String ltrimWS(String text)
       {
          try
          {
             return TextOps.leftTrim(text).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Trim the specified characters from the left side of text.
        *
        * @see  com.goldencode.p2j.util.TextOps#leftTrim(String, String)
        */
       @HQLFunction(name = "ltrimws")
       public static String ltrimWS(String text, String list)
       {
          try
          {
             return TextOps.leftTrim(text, list).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Trim white space from the left and right side of text.
        *
        * @see  com.goldencode.p2j.util.TextOps#trim
        */
       @HQLFunction(name = "trimws")
       public static String trimWS(String text)
       {
          try
          {
             return TextOps.trim(text).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Trim special characters listed in {@code trimChars} from the left and right side of text.
        *
        * @see  com.goldencode.p2j.util.TextOps#trim
        */
       @HQLFunction(name = "trimws")
       public static String trimWS(String text, String trimChars)
       {
          try
          {
             return TextOps.trim(text, trimChars).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Returns the uppercase representation of the string
        *
        * @see  com.goldencode.p2j.util.TextOps#toUpperCase(String, boolean)
        */
       @HQLFunction
       @Deprecated
       public static String caps(String text)
       {
          try
          {
             return TextOps.toUpperCase(text, true);
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the number of entries in the variable.
        *
        * @see  com.goldencode.p2j.util.TextOps#numEntries(Text)
        */
       @HQLFunction
       public static Long numEntries(String value)
       {
          try
          {
             return TextOps.numEntries(value).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the number of entries in the variable.
        *
        * @see  com.goldencode.p2j.util.TextOps#numEntries(Text, String)
        */
       @HQLFunction
       public static Long numEntries(String value, String separator)
       {
          if (value == null)
          {
             return null;
          }

          try
          {
             return TextOps.numEntries(value, separator).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Get the length of a string.
        *
        * @see  com.goldencode.p2j.util.TextOps#length(Text)
        */
       @HQLFunction
       public static Long lengthOf(String text)
       {
          try
          {
             return TextOps.length(new character(text)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Get the length of a string.
        *
        * @see  com.goldencode.p2j.util.TextOps#length(Text)
        */
       @HQLFunction
       public static Long lengthOf(String text, String type)
       {
          try
          {
             return TextOps.length(new character(text), new character(type)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Extract a string from a comma-delimited list represented by another
        * string, given its index within the list.
        *
        * @see  com.goldencode.p2j.util.TextOps#entry
        */
       @HQLFunction(name="entryIn")
       public static String entry(Long i, String list)
       {
          try
          {
             return TextOps.entry(new integer(i),
                                  new character(list)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Extract a string from a comma-delimited list represented by another
        * string, given its index within the list.
        *
        * @see  com.goldencode.p2j.util.TextOps#entry
        */
       @HQLFunction(name="entryIn")
       public static String entry(Integer i, String list)
       {
          return entry(toLong(i), list);
       }

       /**
        * Extract a string from a delimited list represented by another string,
        * given its index within the list and the delimiter.
        *
        * @see  com.goldencode.p2j.util.TextOps#entry
        */
       @HQLFunction(name="entryIn")
       public static String entry(Long i, String list, String delimiter)
       {
          try
          {
             return TextOps.entry(new integer(i),
                                  new character(list),
                                  new character(delimiter)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Extract a string from a delimited list represented by another string,
        * given its index within the list and the delimiter.
        *
        * @see  com.goldencode.p2j.util.TextOps#entry
        */
       @HQLFunction(name="entryIn")
       public static String entry(Integer i, String list, String delimiter)
       {
          return entry(toLong(i), list, delimiter);
       }

       /**
        * Look up the index of a string which represents an element in a
        * comma-delimited list represented by another string.
        *
        * @see  com.goldencode.p2j.util.TextOps#lookup(character, Text)
        */
       @HQLFunction
       public static Long lookup(String entry, String list)
       {
          try
          {
             return TextOps.lookup(new character(entry, false, false),
                                   new character(list, false, false)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Look up the index of a string which represents an element in a
        * delimited list represented by another string, using a specific
        * delimiter.
        *
        * @see  com.goldencode.p2j.util.TextOps#lookup(
        *          com.goldencode.p2j.util.character,
        *          com.goldencode.p2j.util.Text,
        *          com.goldencode.p2j.util.character)
        */
       @HQLFunction
       public static Long lookup(String entry, String list, String delimiter)
       {
          try
          {
             return TextOps.lookup(new character(entry),
                                   new character(list),
                                   new character(delimiter)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Look up the index of a string which represents an element in a
        * delimited list represented by another string, using a specific
        * delimiter, and optionally taking case into account.
        *
        * @see  com.goldencode.p2j.util.TextOps#lookup(
        *          java.lang.String,
        *          java.lang.String,
        *          char,
        *          boolean)
        */
       @HQLFunction
       public static Long lookup(String entry, String list, Boolean caseSensitive)
       {
          return lookup(entry, list, ",", caseSensitive);
       }

       /**
        * Look up the index of a string which represents an element in a
        * delimited list represented by another string, using a specific
        * delimiter, and optionally taking case into account.
        *
        * @see  com.goldencode.p2j.util.TextOps#lookup(
        *          java.lang.String,
        *          java.lang.String,
        *          char,
        *          boolean)
        */
       @HQLFunction
       public static Long lookup(String entry, String list, String delimiter, Boolean caseSensitive)
       {
          try
          {
             return TextOps.lookup(entry,
                                   list,
                                   delimiter.charAt(0),
                                   caseSensitive).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Determine whether a comma-separated list contains a specific item.
        *
        * @see  com.goldencode.p2j.util.TextOps#matchesList(Text, character)
        */
       @HQLFunction
       public static Boolean matchesList(String list, String item)
       {
          try
          {
             return TextOps.matchesList(new character(list),
                                        new character(item)).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Return a character instance that is comprised of {@code num} concatenated copies of a given
        * string.
        *
        * @param    str
        *           The string to be repeated.
        * @param    num
        *           The number of times to repeat.
        *
        * @see  com.goldencode.p2j.util.character#fill
        */
       @HQLFunction
       public static String fill(String str, Integer num)
       {
          try
          {
             return character.fill(str, num).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Return a character instance that is comprised of {@code num} concatenated copies of a given
        * string.
        *
        * @param    str
        *           The string to be repeated.
        * @param    num
        *           The number of times to repeat.
        *
        * @see  com.goldencode.p2j.util.character#fill
        */
       @HQLFunction
       public static String fill(String str, Long num)
       {
          try
          {
             return character.fill(str, num).toJavaType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Round a floating point number to 10 decimal places.
        *
        * @see  com.goldencode.p2j.util.MathOps#round(
        *          com.goldencode.p2j.util.decimal)
        */
       @HQLFunction
       public static BigDecimal roundDec(BigDecimal value)
       {
          try
          {
             return MathOps.round(value);
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Round a floating point number to a particular precision.
        *
        * @see  com.goldencode.p2j.util.MathOps#round(
        *          com.goldencode.p2j.util.decimal,
        *          int)
        */
       @HQLFunction
       public static BigDecimal roundDec(BigDecimal value, Long precision)
       {
          try
          {
             return MathOps.round(value, precision.intValue());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Round a floating point number to a particular precision.
        *
        * @see  com.goldencode.p2j.util.MathOps#round(
        *          com.goldencode.p2j.util.decimal,
        *          int)
        */
       @HQLFunction
       public static BigDecimal roundDec(BigDecimal value, Integer precision)
       {
          return roundDec(value, toLong(precision));
       }

       /**
        * Retrieve the date from a string variable.
        *
        * @param  text
        *         The text value from which we return the new date.
        *
        * @return The calculated date value.
        */
       @Deprecated
       @HQLFunction
       public static Date toDate(String text)
       {
          if (text.isEmpty() || "?".equals(text))
          {
             // avoid creation of some new short-lived objects, including a date object (it's rather
             // costly as it involves parsing and a couple of context accesses)
             return null;
          }

          try
          {
             return new Date(new date(text).dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the date from a string variable. The date format and windowing year must be
        * provided by the query.
        *
        * @param   text
        *          The text value from which we return the new date.
        * @param   fmt
        *          The format string used for date conversion.
        * @param   wYear
        *          The start of the 100 year window used for conversion when year is in 2-digits.
        *
        * @return The calculated date value.
        */
       @HQLFunction
       public static Date toDate(String text, String fmt, Integer wYear)
       {
          if (text.isEmpty() || "?".equals(text))
          {
             // avoid creation of some new short-lived objects, including a date object (it's rather
             // costly as it involves parsing and a couple of context accesses)
             return null;
          }

          try
          {
             return new Date(new date(text, fmt, wYear).dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the date from a string variable.
        *
        * @param  value
        *         The integer representing the number of days from the Progress 4GL base data time.
        *
        * @return The calculated date value.
        */
       @HQLFunction
       public static Date toDate(Long value)
       {
          if (value == null)
          {
             // avoid creation of some new short-lived objects, including a date object (it's rather
             // costly as it involves parsing and a couple of context accesses)
             return null;
          }
          try
          {
             return new Date(new date(value).dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the date from a string variable.
        *
        * @param  value
        *         The integer representing the number of days from the Progress 4GL base data time.
        *
        * @return The calculated date value.
        */
       @HQLFunction
       public static Date toDate(Integer value)
       {
          return toDate(toLong(value));
       }

       /**
        * Retrieve the date from a month/day/year combination .
        *
        * @param   month
        *          The month of the date.
        * @param   day
        *          The day of the date.
        * @param   year
        *          The year of the date.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Date toDate(Long month, Long day, Long year)
       {
          try
          {
             return new Date(new date(new integer(month),
                                      new integer(day),
                                      new integer(year)).dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the date from a month/day/year combination .
        *
        * @param   month
        *          The month of the date.
        * @param   day
        *          The day of the date.
        * @param   year
        *          The year of the date.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Date toDate(Long month, Long day, Integer year)
       {
          return toDate(month, day, toLong(year));
       }

       /**
        * Retrieve the date from a month/day/year combination .
        *
        * @param   month
        *          The month of the date.
        * @param   day
        *          The day of the date.
        * @param   year
        *          The year of the date.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Date toDate(Long month, Integer day, Long year)
       {
          return toDate(month, toLong(day), year);
       }

       /**
        * Retrieve the date from a month/day/year combination .
        *
        * @param   month
        *          The month of the date.
        * @param   day
        *          The day of the date.
        * @param   year
        *          The year of the date.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Date toDate(Long month, Integer day, Integer year)
       {
          return toDate(month, toLong(day), toLong(year));
       }

       /**
        * Retrieve the date from a month/day/year combination .
        *
        * @param   month
        *          The month of the date.
        * @param   day
        *          The day of the date.
        * @param   year
        *          The year of the date.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Date toDate(Integer month, Long day, Long year)
       {
          return toDate(toLong(month), day, year);
       }

       /**
        * Retrieve the date from a month/day/year combination .
        *
        * @param   month
        *          The month of the date.
        * @param   day
        *          The day of the date.
        * @param   year
        *          The year of the date.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Date toDate(Integer month, Long day, Integer year)
       {
          return toDate(toLong(month), day, toLong(year));
       }

       /**
        * Retrieve the date from a month/day/year combination .
        *
        * @param   month
        *          The month of the date.
        * @param   day
        *          The day of the date.
        * @param   year
        *          The year of the date.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Date toDate(Integer month, Integer day, Long year)
       {
          return toDate(toLong(month), toLong(day), year);
       }

       /**
        * Retrieve the date from a month/day/year combination .
        *
        * @param   month
        *          The month of the date.
        * @param   day
        *          The day of the date.
        * @param   year
        *          The year of the date.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Date toDate(Integer month, Integer day, Integer year)
       {
          return toDate(toLong(month), toLong(day), toLong(year));
       }

       /**
        * Extract the date from a timestamp variable.
        *
        * @param   t
        *          The timestamp.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Date toDate(Timestamp t)
       {
          try
          {
             return new Date(new datetime(t).dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Extract the date from a ValueTimestampTimeZone variable.
        *
        * @param   t
        *          The ValueTimestampTimeZone.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Date toDate(ValueTimestampTimeZone t)
       {
          try
          {
             datetimetz dttz = new datetimetz(new date(t.getDate()),
                                             (double) t.getTimeNanos() / 1_000_000,
                                             (double) t.getTimeZoneOffsetSeconds() / 60);

             return toDate(dttz.getMonth(), dttz.getDay(), dttz.getYear());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Construct a timestamp from a date variable.
        *
        * @param   d
        *          The date.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Timestamp toDatetime(Date d)
       {
          try
          {
             return new Timestamp(new datetime(new date(d)).dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the timestamp from a date/time combination.
        *
        * @param   d
        *          The date.
        * @param   mtime
        *          Times since midnight in milliseconds.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Timestamp toDatetime(Date d, Long mtime)
       {
          try
          {
             return new Timestamp(new datetime(new date(d), new int64(mtime)).dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the timestamp from a date/time combination.
        *
        * @param   d
        *          The date.
        * @param   mtime
        *          Times since midnight in milliseconds.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Timestamp toDatetime(Date d, Integer mtime)
       {
          return toDatetime(d, toLong(mtime));
       }

       /**
        * Retrieve the date from a month/day/year/hour/minutes combination .
        *
        * @param  month
        *         The month of the date.
        * @param  day
        *         The day of the date.
        * @param  year
        *         The year of the date.
        * @param  hour
        *         The hour of the day.
        * @param  minutes
        *         The minutes of the hour.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Timestamp toDatetime(Long month, Long day, Long year, Long hour, Long minutes)
       {
          try
          {
             return new Timestamp(new datetime(new integer(month),
                                          new integer(day),
                                          new integer(year),
                                          new integer(hour),
                                          new integer(minutes)).dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the date from a month/day/year/hour/minutes combination .
        *
        * @param  month
        *         The month of the date.
        * @param  day
        *         The day of the date.
        * @param  year
        *         The year of the date.
        * @param  hour
        *         The hour of the day.
        * @param  minutes
        *         The minutes of the hour.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Timestamp toDatetime(Integer month, Integer day, Integer year,
                                      Integer hour, Integer minutes)
       {
          return toDatetime(toLong(month), toLong(day), toLong(year), toLong(hour), toLong(minutes));
       }

       /**
        * Retrieve the timestamp from a month/day/year/hour/minutes./seconds combination .
        *
        * @param  month
        *         The month of the date.
        * @param  day
        *         The day of the date.
        * @param  year
        *         The year of the date.
        * @param  hour
        *         The hour of the day.
        * @param  minutes
        *         The minutes of the hour.
        * @param  seconds
        *         The seconds in the minute.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Timestamp toDatetime(Long month, Long day, Long year,
                                      Long hour, Long minutes, Long seconds)
       {
          try
          {
             return new Timestamp(new datetime(new integer(month),
                                          new integer(day),
                                          new integer(year),
                                          new integer(hour),
                                          new integer(minutes),
                                          new integer(seconds)).dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the timestamp from a month/day/year/hour/minutes./seconds combination .
        *
        * @param  month
        *         The month of the date.
        * @param  day
        *         The day of the date.
        * @param  year
        *         The year of the date.
        * @param  hour
        *         The hour of the day.
        * @param  minutes
        *         The minutes of the hour.
        * @param  seconds
        *         The seconds in the minute.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Timestamp toDatetime(Integer month, Integer day, Integer year,
                                      Integer hour, Integer minutes, Integer seconds)
       {
          return toDatetime(toLong(month), toLong(day), toLong(year),
                             toLong(hour), toLong(minutes), toLong(seconds));
       }

       /**
        * Retrieve the timestamp from a month/day/year/hour/minutes/seconds/millis combination .
        *
        * @param  month
        *         The month of the date.
        * @param  day
        *         The day of the date.
        * @param  year
        *         The year of the date.
        * @param  hour
        *         The hour of the day.
        * @param  minutes
        *         The minutes of the hour.
        * @param  seconds
        *         The seconds in the minute.
        * @param  millis
        *         The milliseconds of the second.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Timestamp toDatetime(Long month, Long day, Long year,
                                      Long hour, Long minutes, Long seconds, Long millis)
       {
          try
          {
             return new Timestamp(new datetime(new integer(month),
                                          new integer(day),
                                          new integer(year),
                                          new integer(hour),
                                          new integer(minutes),
                                          new integer(seconds),
                                          new integer(millis)).dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the timestamp from a month/day/year/hour/minutes/seconds/millis combination .
        *
        * @param  month
        *         The month of the date.
        * @param  day
        *         The day of the date.
        * @param  year
        *         The year of the date.
        * @param  hour
        *         The hour of the day.
        * @param  minutes
        *         The minutes of the hour.
        * @param  seconds
        *         The seconds in the minute.
        * @param  millis
        *         The milliseconds of the second.
        *
        * @return The calculated date value
        */
       @HQLFunction
       public static Timestamp toDatetime(Integer month, Integer day, Integer year,
                                      Integer hour, Integer minutes, Integer seconds, Integer millis)
       {
          return toDatetime(toLong(month), toLong(day), toLong(year),
                             toLong(hour), toLong(minutes), toLong(seconds), toLong(millis));
       }

       /**
        * Retrieve the timestamp from a string variable.
        *
        * @param  text
        *         The text value from which we return the new date.
        *
        * @return The calculated date value.
        */
       @Deprecated
       @HQLFunction
       public static Timestamp toDatetime(String text)
       {
          try
          {
             return new Timestamp(new datetime(text).dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the timestamp from a string variable. The date format and windowing year must be
        * provided by the query.
        *
        * @param   text
        *          The text value from which we return the new date.
        * @param   fmt
        *          The format string used for date conversion.
        * @param   wYear
        *          The start of the 100 year window used for conversion when year is in 2-digits.
        *
        * @return The calculated date value.
        */
       @HQLFunction
       public static Timestamp toDatetime(String text, String fmt, Integer wYear)
       {
          try
          {
             return new Timestamp(new datetime(text, fmt, wYear).dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the week day number from a datetime.
        *
        * @see  com.goldencode.p2j.util.date#weekday(com.goldencode.p2j.util.date)
        */
       @HQLFunction
       public static Long getWeekday(Timestamp value)
       {
          try
          {
             return date.weekday(new datetime(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Interprets one or more consecutive bits in an integer variable.
        *
        * @param   source
        *          The number from which bits are subtracted.
        * @param   position
        *          The 1-based index position to set, must be &gt; 0
        * @param   numBits
        *          The number of bite to take into consideration when performing
        *          the operation.
        *
        * @return  the number of bits from the given position.
        */
       @HQLFunction
       public static Long getBits(Integer source, Integer position, Integer numBits)
       {
          try
          {
             return new int64(source).getBits(position, numBits).longValue();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Interprets one or more consecutive bits in an integer variable.
        *
        * @param   source
        *          The number from which bits are subtracted.
        * @param   position
        *          The 1-based index position to set, must be &gt; 0
        * @param   numBits
        *          The number of bite to take into consideration when performing
        *          the operation.
        *
        * @return  the number of bits from the given position.
        */
       @HQLFunction
       public static Long getBits(Integer source, Integer position, Long numBits)
       {
          try
          {
             return new int64(source).getBits(position, numBits).longValue();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Interprets one or more consecutive bits in an integer variable.
        *
        * @param   source
        *          The number from which bits are subtracted.
        * @param   position
        *          The 1-based index position to set, must be &gt; 0
        * @param   numBits
        *          The number of bite to take into consideration when performing
        *          the operation.
        *
        * @return  the number of bits from the given position.
        */
       @HQLFunction
       public static Long getBits(Integer source, Long position, Integer numBits)
       {
          try
          {
             return new int64(source).getBits(position, numBits).longValue();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Interprets one or more consecutive bits in an integer variable.
        *
        * @param   source
        *          The number from which bits are subtracted.
        * @param   position
        *          The 1-based index position to set, must be &gt; 0
        * @param   numBits
        *          The number of bite to take into consideration when performing
        *          the operation.
        *
        * @return  the number of bits from the given position.
        */
       @HQLFunction
       public static Long getBits(Integer source, Long position, Long numBits)
       {
          try
          {
             return new int64(source).getBits(position, numBits).longValue();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Interprets one or more consecutive bits in an integer variable.
        *
        * @param   source
        *          The number from which bits are subtracted.
        * @param   position
        *          The 1-based index position to set, must be &gt; 0
        * @param   numBits
        *          The number of bite to take into consideration when performing
        *          the operation.
        *
        * @return  the number of bits from the given position.
        */
       @HQLFunction
       public static Long getBits(Long source, Integer position, Integer numBits)
       {
          try
          {
             return new int64(source).getBits(position, numBits).longValue();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Interprets one or more consecutive bits in an integer variable.
        *
        * @param   source
        *          The number from which bits are subtracted.
        * @param   position
        *          The 1-based index position to set, must be &gt; 0
        * @param   numBits
        *          The number of bite to take into consideration when performing
        *          the operation.
        *
        * @return  the number of bits from the given position.
        */
       @HQLFunction
       public static Long getBits(Long source, Integer position, Long numBits)
       {
          try
          {
             return new int64(source).getBits(position, numBits).longValue();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Interprets one or more consecutive bits in an integer variable.
        *
        * @param   source
        *          The number from which bits are subtracted.
        * @param   position
        *          The 1-based index position to set, must be &gt; 0
        * @param   numBits
        *          The number of bite to take into consideration when performing
        *          the operation.
        *
        * @return  the number of bits from the given position.
        */
       @HQLFunction
       public static Long getBits(Long source, Long position, Integer numBits)
       {
          try
          {
             return new int64(source).getBits(position, numBits).longValue();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Interprets one or more consecutive bits in an integer variable.
        *
        * @param   source
        *          The number from which bits are subtracted.
        * @param   position
        *          The 1-based index position to set, must be &gt; 0
        * @param   numBits
        *          The number of bite to take into consideration when performing
        *          the operation.
        *
        * @return  the number of bits from the given position.
        */
       @HQLFunction
       public static Long getBits(Long source, Long position, Long numBits)
       {
          try
          {
             return new int64(source).getBits(position, numBits).longValue();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the year number from a datetime.
        *
        * @see  com.goldencode.p2j.util.date#year(com.goldencode.p2j.util.date)
        */
       @HQLFunction
       public static Long getYear(Timestamp value)
       {
          try
          {
             return date.year(new datetime(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the month number (1-based) from a datetime.
        *
        * @see  com.goldencode.p2j.util.date#month(com.goldencode.p2j.util.date)
        */
       @HQLFunction
       public static Long getMonth(Timestamp value)
       {
          try
          {
             return date.month(new datetime(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the day of the month (1-based) from a datetime.
        *
        * @see  com.goldencode.p2j.util.date#year(com.goldencode.p2j.util.date)
        */
       @HQLFunction
       public static Long getDay(Timestamp value)
       {
          try
          {
             return date.day(new datetime(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the week day number from a date.
        *
        * @see  com.goldencode.p2j.util.date#weekday(com.goldencode.p2j.util.date)
        */
       @HQLFunction
       public static Long getWeekday(Date value)
       {
          try
          {
             return date.weekday(new date(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the year number from a date.
        *
        * @see  com.goldencode.p2j.util.date#year(com.goldencode.p2j.util.date)
        */
       @HQLFunction
       public static Long getYear(Date value)
       {
          try
          {
             return date.year(new date(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the month number (1-based) from a date.
        *
        * @see  com.goldencode.p2j.util.date#month(com.goldencode.p2j.util.date)
        */
       @HQLFunction
       public static Long getMonth(Date value)
       {
          try
          {
             return date.month(new date(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the day of the month (1-based) from a date.
        *
        * @see  com.goldencode.p2j.util.date#year(com.goldencode.p2j.util.date)
        */
       @HQLFunction
       public static Long getDay(Date value)
       {
          try
          {
             return date.day(new date(value)).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);

             return null;
          }
       }

       /**
        * Retrieve the time since midnight in milliseconds.
        * <p><strong>Note:</strong>
        * <br>This function is deprecated and should not exist as it should not be invoked on
        * sql-server side where the system clock is most likely different.
        *
        * @see  com.goldencode.p2j.util.datetime#millisecondsSinceMidnight()
        *
        * @return  current timezone.
        */
       @Deprecated
       @HQLFunction
       public static Long getMtime()
       {
          try
          {
             return (long) datetime.now().getTime();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Retrieve the time since midnight in milliseconds.
        *
        * @see  com.goldencode.p2j.util.datetime#getTime()
        */
       @HQLFunction
       public static Long getMtime(Timestamp value)
       {
          try
          {
             return (long) new datetime(value).getTime();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Computes the interval between two datetime-tz values. The value is expressed in <code>unit</code>
        * units.
        * @see     com.goldencode.p2j.util.DateOps#interval(date, date, String)
        *
        * @param   d1
        *          The first date.
        * @param   d2
        *          The second date.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The interval between the two dates.
        */
       @HQLFunction
       public static Long getInterval(ValueTimestampTimeZone d1, ValueTimestampTimeZone d2, String unit)
       {
          try
          {
             datetimetz dtz1 = new datetimetz(new date(d1.getDate()),
                                              (double) d1.getTimeNanos() / 1_000_000,
                                              (double) d1.getTimeZoneOffsetSeconds() / 60);
             datetimetz dtz2 = new datetimetz(new date(d2.getDate()),
                                              (double) d2.getTimeNanos() / 1_000_000,
                                              (double) d2.getTimeZoneOffsetSeconds() / 60);
             return DateOps.interval(dtz1, dtz2, unit).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Computes the interval between a datetime and a datetime-tz. The value is expressed in
        * <code>unit</code> units.
        * @see     com.goldencode.p2j.util.DateOps#interval(date, date, String)
        *
        * @param   d1
        *          The first date.
        * @param   d2
        *          The second date.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The interval between the two dates.
        */
       @HQLFunction
       public static Long getInterval(Timestamp d1, ValueTimestampTimeZone d2, String unit)
       {
          try
          {
             datetimetz dtz2 = new datetimetz(new date(d2.getDate()),
                                              (double) d2.getTimeNanos() / 1_000_000,
                                              (double) d2.getTimeZoneOffsetSeconds() / 60);
             return DateOps.interval(new datetime(d1), dtz2, unit).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Computes the interval between a date and a datetime-tz. The value is expressed in
        * <code>unit</code> units.
        * @see     com.goldencode.p2j.util.DateOps#interval(date, date, String)
        *
        * @param   d1
        *          The first date.
        * @param   d2
        *          The second date.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The interval between the two dates.
        */
       @HQLFunction
       public static Long getInterval(Date d1, ValueTimestampTimeZone d2, String unit)
       {
          try
          {
             datetimetz dtz2 = new datetimetz(new date(d2.getDate()),
                                              (double) d2.getTimeNanos() / 1_000_000,
                                              (double) d2.getTimeZoneOffsetSeconds() / 60);
             return DateOps.interval(new date(d1), dtz2, unit).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Computes the interval between a datetime-tz and a date. The value is expressed in
        * <code>unit</code> units.
        * @see     com.goldencode.p2j.util.DateOps#interval(date, date, String)
        *
        * @param   d1
        *          The first date.
        * @param   d2
        *          The second date.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The interval between the two dates.
        */
       @HQLFunction
       public static Long getInterval(ValueTimestampTimeZone d1, Date d2, String unit)
       {
          try
          {
             datetimetz dtz1 = new datetimetz(new date(d1.getDate()),
                                              (double) d1.getTimeNanos() / 1_000_000,
                                              (double) d1.getTimeZoneOffsetSeconds() / 60);
             return DateOps.interval(dtz1, new date(d2), unit).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Computes the interval between a datetime-tz and a datetime. The value is expressed in
        * <code>unit</code> units.
        * @see     com.goldencode.p2j.util.DateOps#interval(date, date, String)
        *
        * @param   d1
        *          The first date.
        * @param   d2
        *          The second date.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The interval between the two dates.
        */
       @HQLFunction
       public static Long getInterval(ValueTimestampTimeZone d1, Timestamp d2, String unit)
       {
          try
          {
             datetimetz dtz1 = new datetimetz(new date(d1.getDate()),
                                              (double) d1.getTimeNanos() / 1_000_000,
                                              (double) d1.getTimeZoneOffsetSeconds() / 60);
             return DateOps.interval(dtz1, new datetime(d2), unit).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Computes the interval between two datetimes. The value is expressed in <code>unit</code>
        * units.
        * @see     com.goldencode.p2j.util.DateOps#interval(date, date, String)
        *
        * @param   d1
        *          The first date.
        * @param   d2
        *          The second date.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The interval between the two dates.
        */
       @HQLFunction
       public static Long getInterval(Timestamp d1, Timestamp d2, String unit)
       {
          try
          {
             return DateOps.interval(new datetime(d1), new datetime(d2), unit).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Computes the interval between a date and a datetime. The value is expressed in
        * <code>unit</code> units.
        * @see     com.goldencode.p2j.util.DateOps#interval(date, date, String)
        *
        * @param   d1
        *          The date is the 1st reference.
        * @param   d2
        *          The datetime is the 2nd reference.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The interval between the two dates.
        */
       @HQLFunction
       public static Long getInterval(Date d1, Timestamp d2, String unit)
       {
          try
          {
             return DateOps.interval(new date(d1), new datetime(d2), unit).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Computes the interval between a datetime and a date. The value is expressed in
        * <code>unit</code> units.
        * @see     com.goldencode.p2j.util.DateOps#interval(date, date, String)
        *
        * @param   d1
        *          The datetime is the 1st reference.
        * @param   d2
        *          The date is the 2nd reference.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The interval between the two dates.
        */
       @HQLFunction
       public static Long getInterval(Timestamp d1, Date d2, String unit)
       {
          try
          {
             return DateOps.interval(new date(d1), new date(d2), unit).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Computes the interval between two dates. The value is expressed in <code>unit</code> units.
        * @see     com.goldencode.p2j.util.DateOps#interval(date, date, String)
        *
        * @param   d1
        *          The first date.
        * @param   d2
        *          The second date.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The interval between the two dates.
        */
       @HQLFunction
       public static Long getInterval(Date d1, Date d2, String unit)
       {
          try
          {
             return DateOps.interval(new date(d1), new date(d2), unit).toJavaLongType();
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Computes a new date by adding respective number of time units.
        * @see     com.goldencode.p2j.util.DateOps#addInterval(date, long, String)
        *
        * @param   initial
        *          The first date.
        * @param   amount
        *          The count of units to be added.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The date that is amount units further in time.
        */
       @HQLFunction
       public static Date addInterval(Date initial, Long amount, String unit)
       {
          try
          {
             return new Date(DateOps.addInterval(new datetime(initial), amount, unit)
                             .dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Computes a new date by adding respective number of time units.
        * @see     com.goldencode.p2j.util.DateOps#addInterval(date, long, String)
        *
        * @param   initial
        *          The first date.
        * @param   amount
        *          The count of units to be added.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The date that is amount units further in time.
        */
       @HQLFunction
       public static Date addInterval(Date initial, Integer amount, String unit)
       {
          return addInterval(initial, toLong(amount), unit);
       }

       /**
        * Computes a new datetime by adding respective number of time units.
        * @see     com.goldencode.p2j.util.DateOps#addInterval(date, long, String)
        *
        * @param   initial
        *          The first datetime.
        * @param   amount
        *          The count of units to be added.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The datetime that is amount units further in time.
        */
       @HQLFunction
       public static Timestamp addInterval(Timestamp initial, Long amount, String unit)
       {
          try
          {
             return new Timestamp(DateOps.addInterval(new datetime(initial), amount, unit)
                             .dateValue().getTime());
          }
          catch (RuntimeException exc)
          {
             ErrorHandler.handleError(exc);
             return null;
          }
       }

       /**
        * Computes a new datetime by adding respective number of time units.
        * @see     com.goldencode.p2j.util.DateOps#addInterval(date, long, String)
        *
        * @param   initial
        *          The first datetime.
        * @param   amount
        *          The count of units to be added.
        * @param   unit
        *          The unit to measure the interval.
        *
        * @return  The datetime that is amount units further in time.
        */
       @HQLFunction
       public static Timestamp addInterval(Timestamp initial, Integer amount, String unit)
       {
          return addInterval(initial, toLong(amount), unit);
       }

       /**
        * Returns the current timezone.
        * <p><strong>Note:</strong>
        * <br>This function is deprecated and should not exist as it should not be invoked on
        * sql-server side where the value of <code>SESSION:TIMEZONE</code> is not accessible.
        *
        * @see date#getDefaultOffset()
        *
        * @return  current timezone.
        */
       @Deprecated
       @HQLFunction
       public static Long getTimezone()
       {
          return (long) date.getDefaultOffset();
       }

       /**
        * Helper function to report the precision and scale of a numeric value.
        *
        * @param   num
        *          Numeric value.
        *
        * @return  String representing the precision <i>p</i> and the scale
        *          <i>s</i> in the form <code>(<i>p</i>,<i>s</i>)</code>.
        */
       @HQLFunction
       public static String reportPrecisionScale(BigDecimal num)
       {
          return "(" + num.precision() + "," + num.scale() + ")";
       }

       /**
        * Helper function to return the FWD version string.
        *
        * @return  See above.
        */
       @HQLFunction
       public static String getFWDVersion()
       {
          return Version.getFWDVersion();
       }

       /**
        * Helper function to return the FWD Session Id.
        * NB: this function is for embedded H2 only!
        * @return  FWD Session Id.
        */
       @HQLFunction
       public static int fwdSession()
       {
          return SecurityManager.getInstance().sessionSm.getSessionId().intValue();
       }

       /**
        * Rewraps an Integer value into a Long.
        *
        * @param   i
        *          The java.lang.Integer to be rewrapped.
        *
        * @return  The java.lang.Long that wraps the passed integer value or <code>null</code> if
        *          the argument was <code>null</code>.
        */
       private static Long toLong(Integer i)
       {
          return i == null ? null : i.longValue();
       }

       public static void main(String... args) throws Exception
       {
          try
          {
             System.out.println(toString(new Timestamp(System.currentTimeMillis()), "99999 HH:MM:SS.SSS aM+H"));
          }
          catch(Throwable t)
          {
             LOG.severe("", t);
          }
    //      System.out.println(addInterval(new Date(System.currentTimeMillis()), 1, "weeks"));
    //      for (String s: words(args[0], true))
    //      {
    //         System.out.println(s);
    //      }
       }

       public static <T> T guarded(Supplier<T> call)
       throws SQLException
       {
          try
          {
             return call.get();
          }
          catch (RuntimeException exc)
          {
             try
             {
                ErrorHandler.handleError(exc);
             }
             catch (Throwable e)
             {
                throw new SQLException(exc);
             }

             return null;
          }
       }
    }