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;
      }
   }
}