/* Copyright (c) 2001-2009, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.hsqldb;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.hsqldb.lib.IntKeyIntValueHashMap;
import org.hsqldb.store.ValuePool;
import org.hsqldb.types.CharacterType;
import org.hsqldb.types.ClobData;
import org.hsqldb.types.DTIType;
import org.hsqldb.types.DateTimeType;
import org.hsqldb.types.IntervalMonthData;
import org.hsqldb.types.IntervalSecondData;
import org.hsqldb.types.IntervalType;
import org.hsqldb.types.NumberType;
import org.hsqldb.types.TimeData;
import org.hsqldb.types.TimestampData;
import org.hsqldb.types.Type;
/**
* Implementation of calls to HSQLDB functions with reserved names or functions
* that have an SQL standard equivalent.<p>
*
* Some functions are translated into equivalent SQL Standard functions.
*
* @author Fred Toussi (fredt@users dot sourceforge.net)
* @version 1.9.0
* @since 1.9.0
*/
public class FunctionCustom extends FunctionSQL {
public static final String[] openGroupNumericFunctions = {
"ABS", "ACOS", "ASIN", "ATAN", "ATAN2", "BITAND", "BITOR", "BITXOR",
"CEILING", "COS", "COT", "DEGREES", "EXP", "FLOOR", "LOG", "LOG10",
"MOD", "PI", "POWER", "RADIANS", "RAND", "ROUND", "ROUNDMAGIC", "SIGN",
"SIN", "SQRT", "TAN", "TRUNCATE"
};
public static final String[] openGroupStringFunctions = {
"ASCII", "CHAR", "CONCAT", "DIFFERENCE", "HEXTORAW", "INSERT", "LCASE",
"LEFT", "LENGTH", "LOCATE", "LTRIM", "RAWTOHEX", "REPEAT", "REPLACE",
"RIGHT", "RTRIM", "SOUNDEX", "SPACE", "SUBSTR", "UCASE",
};
public static final String[] openGroupDateTimeFunctions = {
"CURDATE", "CURTIME", "DATEDIFF", "DAYNAME", "DAYOFMONTH", "DAYOFWEEK",
"DAYOFYEAR", "HOUR", "MINUTE", "MONTH", "MONTHNAME", "NOW", "QUARTER",
"SECOND", "SECONDS_SINCE_MIDNIGHT", "TIMESTAMPADD", "TIMESTAMPDIFF",
"TO_CHAR", "WEEK", "YEAR"
};
public static final String[] openGroupSystemFunctions = {
"DATABASE", "IFNULL", "USER"
};
//
private final static int FUNC_ISAUTOCOMMIT = 71;
private final static int FUNC_ISREADONLYSESSION = 72;
private final static int FUNC_ISREADONLYDATABASE = 73;
private final static int FUNC_ISREADONLYDATABASEFILES = 74;
private final static int FUNC_DATABASE = 75;
private final static int FUNC_IDENTITY = 76;
private final static int FUNC_SYSDATE = 77;
private final static int FUNC_TIMESTAMPADD = 78;
private final static int FUNC_TIMESTAMPDIFF = 79;
private final static int FUNC_TRUNCATE = 80;
private final static int FUNC_TO_CHAR = 81;
private final static int FUNC_TIMESTAMP = 82;
//
private static final int FUNC_ACOS = 101;
private static final int FUNC_ASIN = 102;
private static final int FUNC_ATAN = 103;
private static final int FUNC_ATAN2 = 104;
private static final int FUNC_COS = 105;
private static final int FUNC_COT = 106;
private static final int FUNC_DEGREES = 107;
private static final int FUNC_LOG10 = 110;
private static final int FUNC_PI = 111;
private static final int FUNC_RADIANS = 112;
private static final int FUNC_RAND = 113;
private static final int FUNC_ROUND = 114;
private static final int FUNC_SIGN = 115;
private static final int FUNC_SIN = 116;
private static final int FUNC_TAN = 117;
private static final int FUNC_BITAND = 118;
private static final int FUNC_BITOR = 119;
private static final int FUNC_BITXOR = 120;
private static final int FUNC_ROUNDMAGIC = 121;
private static final int FUNC_ASCII = 122;
private static final int FUNC_CHAR = 123;
private static final int FUNC_CONCAT = 124;
private static final int FUNC_DIFFERENCE = 125;
private static final int FUNC_HEXTORAW = 126;
private static final int FUNC_LEFT = 128;
private static final int FUNC_LOCATE = 130;
private static final int FUNC_LTRIM = 131;
private static final int FUNC_RAWTOHEX = 132;
private static final int FUNC_REPEAT = 133;
private static final int FUNC_REPLACE = 134;
private static final int FUNC_RIGHT = 135;
private static final int FUNC_RTRIM = 136;
private static final int FUNC_SOUNDEX = 137;
private static final int FUNC_SPACE = 138;
private static final int FUNC_SUBSTR = 139;
private static final int FUNC_DATEDIFF = 140;
private static final int FUNC_SECONDS_MIDNIGHT = 141;
//
static final IntKeyIntValueHashMap customRegularFuncMap =
new IntKeyIntValueHashMap();
static {
customRegularFuncMap.put(Tokens.LENGTH, FUNC_CHAR_LENGTH);
customRegularFuncMap.put(Tokens.BITLENGTH, FUNC_BIT_LENGTH);
customRegularFuncMap.put(Tokens.OCTETLENGTH, FUNC_OCTET_LENGTH);
customRegularFuncMap.put(Tokens.LCASE, FUNC_FOLD_LOWER);
customRegularFuncMap.put(Tokens.UCASE, FUNC_FOLD_UPPER);
customRegularFuncMap.put(Tokens.LOG, FUNC_LN);
//
customRegularFuncMap.put(Tokens.CURDATE, FUNC_CURRENT_DATE);
customRegularFuncMap.put(Tokens.CURTIME, FUNC_LOCALTIME);
customRegularFuncMap.put(Tokens.SUBSTR, FUNC_SUBSTRING_CHAR);
//
customRegularFuncMap.put(Tokens.YEAR, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.MONTH, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.DAY, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.HOUR, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.MINUTE, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.SECOND, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.DAYNAME, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.NONTHNAME, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.DAYOFMONTH, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.DAYOFWEEK, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.DAYOFYEAR, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.QUARTER, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.WEEK, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.SECONDS_MIDNIGHT, FUNC_EXTRACT);
customRegularFuncMap.put(Tokens.LTRIM, FUNC_TRIM_CHAR);
customRegularFuncMap.put(Tokens.RTRIM, FUNC_TRIM_CHAR);
customRegularFuncMap.put(Tokens.LEFT, FUNC_LEFT);
//
customRegularFuncMap.put(Tokens.IDENTITY, FUNC_IDENTITY);
customRegularFuncMap.put(Tokens.TIMESTAMPADD, FUNC_TIMESTAMPADD);
customRegularFuncMap.put(Tokens.TIMESTAMPDIFF, FUNC_TIMESTAMPDIFF);
customRegularFuncMap.put(Tokens.TRUNCATE, FUNC_TRUNCATE);
customRegularFuncMap.put(Tokens.TO_CHAR, FUNC_TO_CHAR);
customRegularFuncMap.put(Tokens.TIMESTAMP, FUNC_TIMESTAMP);
//
customRegularFuncMap.put(Tokens.LOCATE, FUNC_LOCATE);
customRegularFuncMap.put(Tokens.INSERT, FUNC_OVERLAY_CHAR);
//
//
customRegularFuncMap.put(Tokens.DATABASE, FUNC_DATABASE);
customRegularFuncMap.put(Tokens.ISAUTOCOMMIT, FUNC_ISAUTOCOMMIT);
customRegularFuncMap.put(Tokens.ISREADONLYSESSION,
FUNC_ISREADONLYSESSION);
customRegularFuncMap.put(Tokens.ISREADONLYDATABASE,
FUNC_ISREADONLYDATABASE);
customRegularFuncMap.put(Tokens.ISREADONLYDATABASEFILES,
FUNC_ISREADONLYDATABASEFILES);
//
customRegularFuncMap.put(Tokens.ACOS, FUNC_ACOS);
customRegularFuncMap.put(Tokens.ASIN, FUNC_ASIN);
customRegularFuncMap.put(Tokens.ATAN, FUNC_ATAN);
customRegularFuncMap.put(Tokens.ATAN2, FUNC_ATAN2);
customRegularFuncMap.put(Tokens.COS, FUNC_COS);
customRegularFuncMap.put(Tokens.COT, FUNC_COT);
customRegularFuncMap.put(Tokens.DEGREES, FUNC_DEGREES);
customRegularFuncMap.put(Tokens.LOG10, FUNC_LOG10);
customRegularFuncMap.put(Tokens.PI, FUNC_PI);
customRegularFuncMap.put(Tokens.RADIANS, FUNC_RADIANS);
customRegularFuncMap.put(Tokens.RAND, FUNC_RAND);
customRegularFuncMap.put(Tokens.ROUND, FUNC_ROUND);
customRegularFuncMap.put(Tokens.SIGN, FUNC_SIGN);
customRegularFuncMap.put(Tokens.SIN, FUNC_SIN);
customRegularFuncMap.put(Tokens.TAN, FUNC_TAN);
customRegularFuncMap.put(Tokens.BITAND, FUNC_BITAND);
customRegularFuncMap.put(Tokens.BITOR, FUNC_BITOR);
customRegularFuncMap.put(Tokens.BITXOR, FUNC_BITXOR);
customRegularFuncMap.put(Tokens.ROUNDMAGIC, FUNC_ROUNDMAGIC);
customRegularFuncMap.put(Tokens.ASCII, FUNC_ASCII);
customRegularFuncMap.put(Tokens.CHAR, FUNC_CHAR);
customRegularFuncMap.put(Tokens.CONCAT_WORD, FUNC_CONCAT);
customRegularFuncMap.put(Tokens.DIFFERENCE, FUNC_DIFFERENCE);
customRegularFuncMap.put(Tokens.HEXTORAW, FUNC_HEXTORAW);
customRegularFuncMap.put(Tokens.RAWTOHEX, FUNC_RAWTOHEX);
customRegularFuncMap.put(Tokens.REPEAT, FUNC_REPEAT);
customRegularFuncMap.put(Tokens.REPLACE, FUNC_REPLACE);
customRegularFuncMap.put(Tokens.RIGHT, FUNC_RIGHT);
customRegularFuncMap.put(Tokens.SOUNDEX, FUNC_SOUNDEX);
customRegularFuncMap.put(Tokens.SPACE, FUNC_SPACE);
customRegularFuncMap.put(Tokens.DATEDIFF, FUNC_DATEDIFF);
}
static final IntKeyIntValueHashMap customValueFuncMap =
new IntKeyIntValueHashMap();
static {
customValueFuncMap.put(Tokens.SYSDATE, FUNC_SYSDATE);
customValueFuncMap.put(Tokens.TODAY, FUNC_CURRENT_DATE);
customValueFuncMap.put(Tokens.NOW, FUNC_CURRENT_TIMESTAMP);
}
private int extractSpec;
public static FunctionSQL newCustomFunction(String token, int tokenType) {
int id = customRegularFuncMap.get(tokenType, -1);
if (id == -1) {
id = customValueFuncMap.get(tokenType, -1);
}
if (id == -1) {
return null;
}
switch (tokenType) {
case Tokens.LN :
case Tokens.LCASE :
case Tokens.UCASE :
case Tokens.LENGTH :
case Tokens.BITLENGTH :
case Tokens.OCTETLENGTH :
case Tokens.TODAY :
case Tokens.NOW :
return new FunctionSQL(id);
case Tokens.CURDATE :
case Tokens.CURTIME : {
FunctionSQL function = new FunctionSQL(id);
function.parseList = emptyParamList;
return function;
}
case Tokens.SUBSTR : {
FunctionSQL function = new FunctionSQL(id);
function.parseList = tripleParamList;
return function;
}
}
FunctionCustom function = new FunctionCustom(id);
if (id == FUNC_TRIM_CHAR) {
switch (tokenType) {
case Tokens.LTRIM :
function.extractSpec = Tokens.LEADING;
break;
case Tokens.RTRIM :
function.extractSpec = Tokens.TRAILING;
break;
}
}
if (id == FUNC_EXTRACT) {
switch (tokenType) {
case Tokens.DAYNAME :
function.extractSpec = Tokens.DAY_OF_WEEK;
break;
case Tokens.NONTHNAME :
function.extractSpec = Tokens.MONTH_NAME;
break;
case Tokens.DAYOFMONTH :
function.extractSpec = Tokens.DAY_OF_MONTH;
break;
case Tokens.DAYOFWEEK :
function.extractSpec = Tokens.DAY_OF_WEEK;
break;
case Tokens.DAYOFYEAR :
function.extractSpec = Tokens.DAY_OF_YEAR;
break;
default :
function.extractSpec = tokenType;
}
}
if (function.name == null) {
function.name = token;
}
return function;
}
public static boolean isRegularFunction(int tokenType) {
return customRegularFuncMap.get(tokenType, -1) != -1;
}
public static boolean isValueFunction(int tokenType) {
return customValueFuncMap.get(tokenType, -1) != -1;
}
private FunctionCustom(int id) {
super();
this.funcType = id;
switch (id) {
case FUNC_CONCAT :
case FUNC_LEFT :
parseList = doubleParamList;
break;
case FUNC_DATABASE :
parseList = emptyParamList;
break;
case FUNC_ISAUTOCOMMIT :
case FUNC_ISREADONLYSESSION :
case FUNC_ISREADONLYDATABASE :
case FUNC_ISREADONLYDATABASEFILES :
parseList = emptyParamList;
break;
case FUNC_EXTRACT :
name = Tokens.T_EXTRACT;
parseList = singleParamList;
break;
case FUNC_TRIM_CHAR :
name = Tokens.T_TRIM;
parseList = singleParamList;
break;
case FUNC_OVERLAY_CHAR :
name = Tokens.T_OVERLAY;
parseList = quadParamList;
break;
case FUNC_IDENTITY :
name = Tokens.T_IDENTITY;
parseList = emptyParamList;
break;
case FUNC_SYSDATE :
name = Tokens.T_SYSDATE;
parseList = noParamList;
break;
case FUNC_TIMESTAMPADD :
name = Tokens.T_TIMESTAMPADD;
parseList = new short[] {
Tokens.OPENBRACKET, Tokens.X_KEYSET, 9,
Tokens.SQL_TSI_FRAC_SECOND, Tokens.SQL_TSI_SECOND,
Tokens.SQL_TSI_MINUTE, Tokens.SQL_TSI_HOUR,
Tokens.SQL_TSI_DAY, Tokens.SQL_TSI_WEEK,
Tokens.SQL_TSI_MONTH, Tokens.SQL_TSI_QUARTER,
Tokens.SQL_TSI_YEAR, Tokens.COMMA, Tokens.QUESTION,
Tokens.COMMA, Tokens.QUESTION, Tokens.CLOSEBRACKET
};
break;
case FUNC_TIMESTAMPDIFF :
name = Tokens.T_TIMESTAMPDIFF;
parseList = new short[] {
Tokens.OPENBRACKET, Tokens.X_KEYSET, 9,
Tokens.SQL_TSI_FRAC_SECOND, Tokens.SQL_TSI_SECOND,
Tokens.SQL_TSI_MINUTE, Tokens.SQL_TSI_HOUR,
Tokens.SQL_TSI_DAY, Tokens.SQL_TSI_WEEK,
Tokens.SQL_TSI_MONTH, Tokens.SQL_TSI_QUARTER,
Tokens.SQL_TSI_YEAR, Tokens.COMMA, Tokens.QUESTION,
Tokens.COMMA, Tokens.QUESTION, Tokens.CLOSEBRACKET
};
break;
case FUNC_TRUNCATE :
parseList = doubleParamList;
break;
case FUNC_TO_CHAR :
parseList = doubleParamList;
break;
case FUNC_TIMESTAMP :
name = Tokens.T_TIMESTAMP;
parseList = new short[] {
Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.X_OPTION, 2,
Tokens.COMMA, Tokens.QUESTION, Tokens.CLOSEBRACKET
};
break;
case FUNC_PI :
parseList = emptyParamList;
break;
case FUNC_RAND :
parseList = optionalIntegerParamList;
break;
case FUNC_ACOS :
case FUNC_ASIN :
case FUNC_ATAN :
case FUNC_ATAN2 :
case FUNC_COS :
case FUNC_COT :
case FUNC_DEGREES :
case FUNC_SIN :
case FUNC_TAN :
case FUNC_LOG10 :
case FUNC_RADIANS :
case FUNC_ROUNDMAGIC :
case FUNC_SIGN :
case FUNC_SOUNDEX :
case FUNC_ASCII :
case FUNC_CHAR :
case FUNC_HEXTORAW :
case FUNC_RAWTOHEX :
case FUNC_SPACE :
parseList = singleParamList;
break;
case FUNC_ROUND :
case FUNC_BITAND :
case FUNC_BITOR :
case FUNC_BITXOR :
case FUNC_DIFFERENCE :
case FUNC_REPEAT :
case FUNC_DATEDIFF :
case FUNC_RIGHT :
parseList = doubleParamList;
break;
case FUNC_LOCATE :
parseList = new short[] {
Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.COMMA,
Tokens.QUESTION, Tokens.X_OPTION, 2, Tokens.COMMA,
Tokens.QUESTION, Tokens.CLOSEBRACKET
};
break;
case FUNC_REPLACE :
parseList = tripleParamList;
break;
default :
throw Error.runtimeError(ErrorCode.U_S0500, "SQLFunction");
}
}
public void setArguments(Expression[] nodes) {
switch (funcType) {
case FUNC_OVERLAY_CHAR : {
Expression start = nodes[1];
Expression length = nodes[2];
nodes[1] = nodes[3];
nodes[2] = start;
nodes[3] = length;
break;
}
case FUNC_EXTRACT : {
Expression[] newNodes = new Expression[2];
newNodes[0] =
new ExpressionValue(ValuePool.getInt(extractSpec),
Type.SQL_INTEGER);
newNodes[1] = nodes[0];
nodes = newNodes;
break;
}
case FUNC_TRIM_CHAR : {
Expression[] newNodes = new Expression[3];
newNodes[0] =
new ExpressionValue(ValuePool.getInt(extractSpec),
Type.SQL_INTEGER);
newNodes[1] = new ExpressionValue(" ", Type.SQL_CHAR);
newNodes[2] = nodes[0];
nodes = newNodes;
}
}
super.setArguments(nodes);
}
public Expression getFunctionExpression() {
switch (funcType) {
case FUNC_SYSDATE : {
FunctionSQL f = new FunctionSQL(FUNC_CURRENT_TIMESTAMP);
f.nodes = new Expression[]{
new ExpressionValue(ValuePool.INTEGER_0,
Type.SQL_INTEGER) };
return f;
}
case FUNC_CONCAT :
return new ExpressionArithmetic(OpTypes.CONCAT,
nodes[Expression.LEFT],
nodes[Expression.RIGHT]);
}
return super.getFunctionExpression();
}
Object getValue(Session session, Object[] data) {
switch (funcType) {
case FUNC_EXTRACT :
case FUNC_TRIM_CHAR :
case FUNC_OVERLAY_CHAR :
return super.getValue(session, data);
case FUNC_DATABASE :
return session.getDatabase().getPath();
case FUNC_ISAUTOCOMMIT :
return session.isAutoCommit() ? Boolean.TRUE
: Boolean.FALSE;
case FUNC_ISREADONLYSESSION :
return session.isReadOnlyDefault() ? Boolean.TRUE
: Boolean.FALSE;
case FUNC_ISREADONLYDATABASE :
return session.getDatabase().databaseReadOnly ? Boolean.TRUE
: Boolean.FALSE;
case FUNC_ISREADONLYDATABASEFILES :
return session.getDatabase().isFilesReadOnly() ? Boolean.TRUE
: Boolean.FALSE;
case FUNC_IDENTITY : {
Number id = session.getLastIdentity();
if (id instanceof Long) {
return id;
} else {
return ValuePool.getLong(id.longValue());
}
}
case FUNC_TIMESTAMPADD : {
if (data[1] == null || data[2] == null) {
return null;
}
int part = ((Number) nodes[0].valueData).intValue();
long units = ((Number) data[1]).longValue();
TimestampData source = (TimestampData) data[2];
IntervalType t;
Object o;
switch (part) {
case Tokens.SQL_TSI_FRAC_SECOND : {
long seconds = units / DTIType.limitNanoseconds;
int nanos = (int) (units % DTIType.limitNanoseconds);
t = Type.SQL_INTERVAL_SECOND_MAX_FRACTION;
o = new IntervalSecondData(seconds, nanos, t);
return dataType.add(source, o, t);
}
case Tokens.SQL_TSI_SECOND :
t = Type.SQL_INTERVAL_SECOND;
o = IntervalSecondData.newIntervalSeconds(units, t);
return dataType.add(source, o, t);
case Tokens.SQL_TSI_MINUTE :
t = Type.SQL_INTERVAL_MINUTE;
o = IntervalSecondData.newIntervalMinute(units, t);
return dataType.add(source, o, t);
case Tokens.SQL_TSI_HOUR :
t = Type.SQL_INTERVAL_HOUR;
o = IntervalSecondData.newIntervalHour(units, t);
return dataType.add(source, o, t);
case Tokens.SQL_TSI_DAY :
t = Type.SQL_INTERVAL_DAY;
o = IntervalSecondData.newIntervalDay(units, t);
return dataType.add(source, o, t);
case Tokens.SQL_TSI_WEEK :
t = Type.SQL_INTERVAL_DAY;
o = IntervalSecondData.newIntervalDay(units * 7, t);
return dataType.add(source, o, t);
case Tokens.SQL_TSI_MONTH :
t = Type.SQL_INTERVAL_MONTH;
o = IntervalMonthData.newIntervalMonth(units, t);
return dataType.add(source, o, t);
case Tokens.SQL_TSI_QUARTER :
t = Type.SQL_INTERVAL_MONTH;
o = IntervalMonthData.newIntervalMonth(units * 3, t);
return dataType.add(source, o, t);
case Tokens.SQL_TSI_YEAR :
t = Type.SQL_INTERVAL_YEAR;
o = IntervalMonthData.newIntervalMonth(units, t);
return dataType.add(source, o, t);
default :
throw Error.runtimeError(ErrorCode.U_S0500,
"FunctionCustom");
}
}
case FUNC_TIMESTAMPDIFF : {
if (data[1] == null || data[2] == null) {
return null;
}
int part = ((Number) nodes[0].valueData).intValue();
TimestampData a = (TimestampData) data[2];
TimestampData b = (TimestampData) data[1];
if (nodes[2].dataType.isDateTimeTypeWithZone()) {
a = (TimestampData) Type.SQL_TIMESTAMP.convertToType(
session, a, Type.SQL_TIMESTAMP_WITH_TIME_ZONE);
}
if (nodes[1].dataType.isDateTimeTypeWithZone()) {
b = (TimestampData) Type.SQL_TIMESTAMP.convertToType(
session, b, Type.SQL_TIMESTAMP_WITH_TIME_ZONE);
}
IntervalType t;
switch (part) {
case Tokens.SQL_TSI_FRAC_SECOND :
t = Type.SQL_INTERVAL_SECOND_MAX_PRECISION;
IntervalSecondData interval =
(IntervalSecondData) t.subtract(a, b, null);
return new Long(
DTIType.limitNanoseconds * interval.getSeconds()
+ interval.getNanos());
case Tokens.SQL_TSI_SECOND :
t = Type.SQL_INTERVAL_SECOND_MAX_PRECISION;
return new Long(t.convertToLong(t.subtract(a, b,
null)));
case Tokens.SQL_TSI_MINUTE :
t = Type.SQL_INTERVAL_MINUTE_MAX_PRECISION;
return new Long(t.convertToLong(t.subtract(a, b,
null)));
case Tokens.SQL_TSI_HOUR :
t = Type.SQL_INTERVAL_HOUR_MAX_PRECISION;
return new Long(t.convertToLong(t.subtract(a, b,
null)));
case Tokens.SQL_TSI_DAY :
t = Type.SQL_INTERVAL_DAY_MAX_PRECISION;
return new Long(t.convertToLong(t.subtract(a, b,
null)));
case Tokens.SQL_TSI_WEEK :
t = Type.SQL_INTERVAL_DAY_MAX_PRECISION;
return new Long(t.convertToLong(t.subtract(a, b, null))
/ 7);
case Tokens.SQL_TSI_MONTH :
t = Type.SQL_INTERVAL_MONTH_MAX_PRECISION;
return new Long(t.convertToLong(t.subtract(a, b,
null)));
case Tokens.SQL_TSI_QUARTER :
t = Type.SQL_INTERVAL_MONTH_MAX_PRECISION;
return new Long(t.convertToLong(t.subtract(a, b, null))
/ 3);
case Tokens.SQL_TSI_YEAR :
t = Type.SQL_INTERVAL_YEAR_MAX_PRECISION;
return new Long(t.convertToLong(t.subtract(a, b,
null)));
default :
throw Error.runtimeError(ErrorCode.U_S0500,
"FunctionCustom");
}
}
case FUNC_SECONDS_MIDNIGHT : {
if (data[0] == null) {
return null;
}
}
// fall through
case FUNC_TRUNCATE : {
if (data[0] == null || data[1] == null) {
return null;
}
return ((NumberType) dataType).truncate(data[0],
((Number) data[1]).intValue());
}
case FUNC_TO_CHAR : {
if (data[0] == null || data[1] == null) {
return null;
}
SimpleDateFormat format = session.getSimpleDateFormatGMT();
String javaPattern =
HsqlDateTime.toJavaDatePattern((String) data[1]);
try {
format.applyPattern(javaPattern);
} catch (Exception e) {
throw Error.error(ErrorCode.X_22511);
}
Date date =
(Date) ((DateTimeType) nodes[0].dataType)
.convertSQLToJavaGMT(session, data[0]);
return format.format(date);
}
case FUNC_TIMESTAMP : {
boolean unary = nodes[1] == null;
if (data[0] == null) {
return null;
}
if (unary) {
return Type.SQL_TIMESTAMP.convertToType(session, data[0],
nodes[0].dataType);
}
if (data[1] == null) {
return null;
}
TimestampData date =
(TimestampData) Type.SQL_DATE.convertToType(session,
data[0], nodes[0].dataType);
TimeData time = (TimeData) Type.SQL_TIME.convertToType(session,
data[1], nodes[1].dataType);
return new TimestampData(date.getSeconds()
+ time.getSeconds(), time.getNanos());
}
case FUNC_PI :
return Double.valueOf(Math.PI);
case FUNC_RAND : {
if (nodes[0] == null) {
return Double.valueOf(session.random());
} else {
long seed = ((Number) data[0]).longValue();
return Double.valueOf(seed);
}
}
case FUNC_ACOS : {
if (data[0] == null) {
return null;
}
double d = NumberType.toDouble(data[0]);
return Double.valueOf(java.lang.Math.acos(d));
}
case FUNC_ASIN : {
if (data[0] == null) {
return null;
}
double d = NumberType.toDouble(data[0]);
return Double.valueOf(java.lang.Math.asin(d));
}
case FUNC_ATAN : {
if (data[0] == null) {
return null;
}
double d = NumberType.toDouble(data[0]);
return Double.valueOf(java.lang.Math.atan(d));
}
case FUNC_COS : {
if (data[0] == null) {
return null;
}
double d = NumberType.toDouble(data[0]);
return Double.valueOf(java.lang.Math.cos(d));
}
case FUNC_COT : {
if (data[0] == null) {
return null;
}
double d = NumberType.toDouble(data[0]);
double c = 1.0 / java.lang.Math.tan(d);
return Double.valueOf(c);
}
case FUNC_DEGREES : {
if (data[0] == null) {
return null;
}
double d = NumberType.toDouble(data[0]);
return Double.valueOf(java.lang.Math.toDegrees(d));
}
case FUNC_SIN : {
if (data[0] == null) {
return null;
}
double d = NumberType.toDouble(data[0]);
return Double.valueOf(java.lang.Math.sin(d));
}
case FUNC_TAN : {
if (data[0] == null) {
return null;
}
double d = NumberType.toDouble(data[0]);
return Double.valueOf(java.lang.Math.tan(d));
}
case FUNC_LOG10 : {
if (data[0] == null) {
return null;
}
double d = NumberType.toDouble(data[0]);
return Double.valueOf(java.lang.Math.log10(d));
}
case FUNC_RADIANS : {
if (data[0] == null) {
return null;
}
double d = NumberType.toDouble(data[0]);
return Double.valueOf(java.lang.Math.toRadians(d));
}
//
case FUNC_SIGN : {
if (data[0] == null) {
return null;
}
return ((NumberType) nodes[0].dataType).compareToZero(data[0]);
}
case FUNC_ATAN2 : {
if (data[0] == null) {
return null;
}
double a = NumberType.toDouble(data[0]);
double b = NumberType.toDouble(data[1]);
return Double.valueOf(java.lang.Math.atan2(a, b));
}
case FUNC_ASCII : {
String arg;
if (data[0] == null) {
return null;
}
if (nodes[0].dataType.isLobType()) {
arg = ((ClobData) data[0]).getSubString(session, 0, 1);
} else {
arg = (String) data[0];
}
if (arg.length() == 0) {
return null;
}
return ValuePool.getInt(arg.charAt(0));
}
case FUNC_CHAR :
if (data[0] == null) {
return null;
}
int arg = ((Number) data[0]).intValue();
return String.valueOf(arg);
case FUNC_ROUND : {
if (data[0] == null || data[1] == null) {
return null;
}
double d = NumberType.toDouble(data[0]);
int i = ((Number) data[1]).intValue();
return Library.round(d, i);
}
case FUNC_ROUNDMAGIC : {
if (data[0] == null) {
return null;
}
double d = NumberType.toDouble(data[0]);
return Library.roundMagic(d);
}
case FUNC_SOUNDEX : {
if (data[0] == null) {
return null;
}
String s = (String) data[0];
return Library.soundex(s);
}
case FUNC_BITAND :
case FUNC_BITOR :
case FUNC_BITXOR : {
for (int i = 0; i < data.length; i++) {
if (data[0] == null) {
return null;
}
}
if (nodes[0].dataType.isIntegralType()) {
int v = 0;
int a = ((Number) data[0]).intValue();
int b = ((Number) data[0]).intValue();
switch (funcType) {
case FUNC_BITAND :
v = a & b;
break;
case FUNC_BITOR :
v = a | b;
break;
case FUNC_BITXOR :
v = a ^ b;
break;
}
return ValuePool.getInt(v);
} else {
/** @todo - for binary */
return null;
}
}
case FUNC_DIFFERENCE : {
for (int i = 0; i < data.length; i++) {
if (data[0] == null) {
return null;
}
}
int v = Library.difference((String) data[0], (String) data[1]);
return ValuePool.getInt(v);
}
case FUNC_HEXTORAW : {
if (data[0] == null) {
return null;
}
return dataType.convertToType(session, data[0],
nodes[0].dataType);
}
case FUNC_RAWTOHEX : {
if (data[0] == null) {
return null;
}
return nodes[0].dataType.convertToString(data[0]);
}
case FUNC_LOCATE : {
for (int i = 0; i < data.length; i++) {
if (data[0] == null) {
return null;
}
}
int v = Library.locate((String) data[0], (String) data[1],
(Integer) data[2]);
return ValuePool.getInt(v);
}
case FUNC_REPEAT : {
for (int i = 0; i < data.length; i++) {
if (data[0] == null) {
return null;
}
}
return Library.repeat((String) data[0],
((Number) data[1]).intValue());
}
case FUNC_REPLACE : {
for (int i = 0; i < data.length; i++) {
if (data[0] == null) {
return null;
}
}
return Library.replace((String) data[0], (String) data[1],
(String) data[2]);
}
case FUNC_LEFT :
case FUNC_RIGHT : {
for (int i = 0; i < data.length; i++) {
if (data[0] == null) {
return null;
}
}
int count = ((Number) data[1]).intValue();
return ((CharacterType) dataType).substring(session, data[0],
0, count, true, funcType == FUNC_RIGHT);
}
case FUNC_SPACE : {
for (int i = 0; i < data.length; i++) {
if (data[0] == null) {
return null;
}
}
int count = ((Number) data[0]).intValue();
return ValuePool.getSpaces(count);
}
default :
throw Error.runtimeError(ErrorCode.U_S0500, "FunctionCustom");
}
}
public void resolveTypes(Session session, Expression parent) {
for (int i = 0; i < nodes.length; i++) {
if (nodes[i] != null) {
nodes[i].resolveTypes(session, this);
}
}
switch (funcType) {
case FUNC_EXTRACT :
case FUNC_TRIM_CHAR :
case FUNC_OVERLAY_CHAR :
super.resolveTypes(session, parent);
return;
case FUNC_DATABASE :
dataType = Type.SQL_VARCHAR;
return;
case FUNC_ISAUTOCOMMIT :
case FUNC_ISREADONLYSESSION :
case FUNC_ISREADONLYDATABASE :
case FUNC_ISREADONLYDATABASEFILES :
dataType = Type.SQL_BOOLEAN;
return;
case FUNC_IDENTITY :
dataType = Type.SQL_BIGINT;
return;
case FUNC_TIMESTAMPADD :
if (nodes[1].dataType == null) {
nodes[1].dataType = Type.SQL_BIGINT;
}
if (nodes[2].dataType == null) {
nodes[2].dataType = Type.SQL_TIMESTAMP;
}
if (!nodes[1].dataType.isIntegralType()
|| nodes[2].dataType.typeCode != Types.SQL_TIMESTAMP) {
throw Error.error(ErrorCode.X_42561);
}
dataType = nodes[2].dataType;
return;
case FUNC_DATEDIFF : {
int part;
if (!nodes[0].dataType.isCharacterType()) {
throw Error.error(ErrorCode.X_42561);
}
if ("yy".equalsIgnoreCase((String) nodes[0].valueData)) {
part = Tokens.SQL_TSI_YEAR;
} else if ("mm".equalsIgnoreCase(
(String) nodes[0].valueData)) {
part = Tokens.SQL_TSI_MONTH;
} else if ("dd".equalsIgnoreCase(
(String) nodes[0].valueData)) {
part = Tokens.SQL_TSI_DAY;
} else if ("hh".equalsIgnoreCase(
(String) nodes[0].valueData)) {
part = Tokens.SQL_TSI_HOUR;
} else if ("mi".equalsIgnoreCase(
(String) nodes[0].valueData)) {
part = Tokens.SQL_TSI_MINUTE;
} else if ("ss".equalsIgnoreCase(
(String) nodes[0].valueData)) {
part = Tokens.SQL_TSI_SECOND;
} else if ("ms".equalsIgnoreCase(
(String) nodes[0].valueData)) {
part = Tokens.SQL_TSI_FRAC_SECOND;
} else {
throw Error.error(ErrorCode.X_42561);
}
nodes[0].valueData = ValuePool.getInt(part);
funcType = FUNC_TIMESTAMPDIFF;
}
// fall through
case FUNC_TIMESTAMPDIFF : {
if (nodes[1].dataType == null) {
nodes[1].dataType = Type.SQL_TIMESTAMP;
}
if (nodes[2].dataType == null) {
nodes[2].dataType = Type.SQL_TIMESTAMP;
}
if (nodes[1].dataType.typeCode != Types.SQL_TIMESTAMP
&& nodes[1].dataType.typeCode
!= Types.SQL_TIMESTAMP_WITH_TIME_ZONE) {
throw Error.error(ErrorCode.X_42561);
}
if (nodes[2].dataType.typeCode != Types.SQL_TIMESTAMP
&& nodes[2].dataType.typeCode
!= Types.SQL_TIMESTAMP_WITH_TIME_ZONE) {
throw Error.error(ErrorCode.X_42561);
}
dataType = Type.SQL_BIGINT;
return;
}
case FUNC_TRUNCATE : {
if (nodes[0].dataType == null) {
throw Error.error(ErrorCode.X_42567);
}
if (nodes[1].dataType == null) {
nodes[1].dataType = Type.SQL_INTEGER;
} else if (!nodes[1].dataType.isIntegralType()) {
throw Error.error(ErrorCode.X_42565);
}
if (!nodes[0].dataType.isNumberType()) {
throw Error.error(ErrorCode.X_42565);
}
dataType = nodes[0].dataType;
return;
}
case FUNC_TO_CHAR : {
if (nodes[0].dataType == null) {
throw Error.error(ErrorCode.X_42567);
}
if (nodes[1].dataType == null
|| !nodes[1].dataType.isCharacterType()) {
throw Error.error(ErrorCode.X_42567);
}
if (!nodes[0].dataType.isExactNumberType()
&& !nodes[0].dataType.isDateTimeType()) {
throw Error.error(ErrorCode.X_42565);
}
// fixed maximum as format is a variable
dataType = CharacterType.getCharacterType(Types.SQL_VARCHAR,
40);
if (nodes[1].opType == OpTypes.VALUE) {
nodes[1].setAsConstantValue(session);
}
return;
}
case FUNC_TIMESTAMP : {
boolean unary = nodes[1] == null;
if (unary) {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_TIMESTAMP;
}
if (nodes[0].dataType.isCharacterType()) {}
else {
if (nodes[0].dataType.typeCode != Types.SQL_TIMESTAMP
&& nodes[0].dataType.typeCode
!= Types.SQL_TIMESTAMP_WITH_TIME_ZONE) {
throw Error.error(ErrorCode.X_42561);
}
}
} else {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_DATE;
}
if (nodes[1].dataType == null) {
nodes[1].dataType = Type.SQL_TIME;
}
if (nodes[0].dataType.typeCode != Types.SQL_DATE
&& nodes[0].dataType.isCharacterType()) {
throw Error.error(ErrorCode.X_42561);
}
if (nodes[1].dataType.typeCode != Types.SQL_TIME
&& nodes[1].dataType.isCharacterType()) {
throw Error.error(ErrorCode.X_42561);
}
}
dataType = Type.SQL_TIMESTAMP;
return;
}
case FUNC_PI :
dataType = Type.SQL_DOUBLE;
break;
case FUNC_RAND : {
if (nodes[0] != null) {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_BIGINT;
} else if (!nodes[0].dataType.isExactNumberType()) {
throw Error.error(ErrorCode.X_42565);
}
}
dataType = Type.SQL_DOUBLE;
break;
}
case FUNC_ROUND :
if (nodes[1].dataType == null) {
nodes[1].dataType = Type.SQL_INTEGER;
}
if (!nodes[1].dataType.isExactNumberType()) {
throw Error.error(ErrorCode.X_42561);
}
// fall through
case FUNC_ACOS :
case FUNC_ASIN :
case FUNC_ATAN :
case FUNC_COS :
case FUNC_COT :
case FUNC_DEGREES :
case FUNC_SIN :
case FUNC_TAN :
case FUNC_LOG10 :
case FUNC_RADIANS :
case FUNC_ROUNDMAGIC : {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_DOUBLE;
}
if (!nodes[0].dataType.isNumberType()) {
throw Error.error(ErrorCode.X_42561);
}
dataType = Type.SQL_DOUBLE;
break;
}
case FUNC_SIGN : {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_DOUBLE;
}
if (!nodes[0].dataType.isNumberType()) {
throw Error.error(ErrorCode.X_42561);
}
dataType = Type.SQL_INTEGER;
break;
}
case FUNC_ATAN2 : {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_DOUBLE;
}
if (nodes[1].dataType == null) {
nodes[1].dataType = Type.SQL_DOUBLE;
}
if (!nodes[0].dataType.isNumberType()
|| !nodes[1].dataType.isNumberType()) {
throw Error.error(ErrorCode.X_42561);
}
dataType = Type.SQL_DOUBLE;
break;
}
case FUNC_SOUNDEX : {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_VARCHAR;
}
if (!nodes[0].dataType.isCharacterType()) {
throw Error.error(ErrorCode.X_42561);
}
dataType = Type.getType(Types.SQL_VARCHAR, 0, 4, 0);
break;
}
case FUNC_BITAND :
case FUNC_BITOR :
case FUNC_BITXOR : {
for (int i = 0; i < nodes.length; i++) {
if (nodes[i].dataType == null) {
nodes[i].dataType = Type.SQL_INTEGER;
} else if (nodes[i].dataType.typeCode
!= Types.SQL_INTEGER) {
throw Error.error(ErrorCode.X_42561);
}
}
dataType = Type.SQL_INTEGER;
break;
}
case FUNC_ASCII : {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_VARCHAR;
}
if (!nodes[0].dataType.isCharacterType()) {
throw Error.error(ErrorCode.X_42561);
}
dataType = Type.SQL_INTEGER;
break;
}
case FUNC_CHAR : {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_INTEGER;
}
if (!nodes[0].dataType.isExactNumberType()) {
throw Error.error(ErrorCode.X_42561);
}
dataType = Type.getType(Types.SQL_VARCHAR, 0, 1, 0);
break;
}
case FUNC_DIFFERENCE : {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_VARCHAR;
}
if (nodes[1].dataType == null) {
nodes[1].dataType = Type.SQL_VARCHAR;
}
dataType = Type.SQL_INTEGER;
break;
}
case FUNC_HEXTORAW : {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_VARCHAR;
}
if (!nodes[0].dataType.isCharacterType()) {
throw Error.error(ErrorCode.X_42561);
}
dataType = Type.SQL_VARBINARY;
break;
}
case FUNC_RAWTOHEX : {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_VARBINARY;
}
if (!nodes[0].dataType.isBinaryType()) {
throw Error.error(ErrorCode.X_42561);
}
dataType = Type.SQL_VARCHAR;
break;
}
case FUNC_LOCATE : {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_VARCHAR;
}
if (nodes[1].dataType == null) {
nodes[1].dataType = Type.SQL_VARCHAR;
}
if (nodes[2] == null) {
nodes[2] = new ExpressionValue(ValuePool.INTEGER_0,
Type.SQL_INTEGER);
}
if (nodes[2].dataType == null) {
nodes[2].dataType = Type.SQL_INTEGER;
}
boolean isChar = nodes[0].dataType.isCharacterType()
&& nodes[1].dataType.isCharacterType();
if (!isChar || !nodes[2].dataType.isExactNumberType()) {
throw Error.error(ErrorCode.X_42561);
}
dataType = Type.SQL_INTEGER;;
break;
}
case FUNC_REPEAT : {
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_VARCHAR;
}
boolean isChar = nodes[0].dataType.isCharacterType();
if (!isChar && !nodes[0].dataType.isBinaryType()) {
throw Error.error(ErrorCode.X_42561);
}
dataType = isChar ? Type.SQL_VARCHAR
: Type.SQL_VARBINARY;;
break;
}
case FUNC_REPLACE : {
for (int i = 0; i < nodes.length; i++) {
if (nodes[i].dataType == null) {
nodes[i].dataType = Type.SQL_VARCHAR;
} else if (!nodes[i].dataType.isCharacterType()) {
throw Error.error(ErrorCode.X_42561);
}
}
dataType = Type.SQL_VARCHAR;
break;
}
case FUNC_LEFT :
case FUNC_RIGHT :
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_VARCHAR;
}
if (!nodes[0].dataType.isCharacterType()) {
throw Error.error(ErrorCode.X_42561);
}
if (nodes[1].dataType == null) {
nodes[1].dataType = Type.SQL_INTEGER;
}
if (!nodes[1].dataType.isExactNumberType()) {
throw Error.error(ErrorCode.X_42561);
}
dataType = Type.SQL_VARCHAR;
break;
case FUNC_SPACE :
if (nodes[0].dataType == null) {
nodes[0].dataType = Type.SQL_INTEGER;
}
dataType = Type.SQL_VARCHAR;
break;
default :
throw Error.runtimeError(ErrorCode.U_S0500, "FunctionCustom");
}
}
public String getSQL() {
switch (funcType) {
case FUNC_EXTRACT :
case FUNC_TRIM_CHAR :
case FUNC_OVERLAY_CHAR :
return super.getSQL();
case FUNC_DATABASE :
case FUNC_ISAUTOCOMMIT :
case FUNC_ISREADONLYSESSION :
case FUNC_ISREADONLYDATABASE :
case FUNC_ISREADONLYDATABASEFILES :
return new StringBuffer(name).append(
Tokens.T_OPENBRACKET).append(
Tokens.T_CLOSEBRACKET).toString();
case FUNC_IDENTITY :
return new StringBuffer(Tokens.T_IDENTITY).append(
Tokens.T_OPENBRACKET).append(
Tokens.T_CLOSEBRACKET).toString();
case FUNC_TIMESTAMPADD :
return new StringBuffer(Tokens.T_TIMESTAMPADD).append(
Tokens.T_OPENBRACKET).append(nodes[0].getSQL()) //
.append(Tokens.T_COMMA).append(nodes[1].getSQL()) //
.append(Tokens.T_COMMA).append(nodes[2].getSQL()) //
.append(Tokens.T_CLOSEBRACKET).toString();
case FUNC_TIMESTAMPDIFF :
return new StringBuffer(Tokens.T_TIMESTAMPDIFF).append(
Tokens.T_OPENBRACKET).append(nodes[0].getSQL()) //
.append(Tokens.T_COMMA).append(nodes[1].getSQL()) //
.append(Tokens.T_COMMA).append(nodes[2].getSQL()) //
.append(Tokens.T_CLOSEBRACKET).toString();
case FUNC_TRUNCATE : {
return new StringBuffer(Tokens.T_TRUNCATE).append('(') //
.append(nodes[0].getSQL()).append(Tokens.T_COMMA) //
.append(nodes[1].getSQL()).append(')').toString();
}
case FUNC_TO_CHAR : {
return new StringBuffer(Tokens.T_TO_CHAR).append('(') //
.append(nodes[0].getSQL()).append(Tokens.T_COMMA) //
.append(nodes[1].getSQL()).append(')').toString();
}
case FUNC_PI :
case FUNC_RAND : {
return new StringBuffer(name).append('(').append(
')').toString();
}
case FUNC_ACOS :
case FUNC_ASIN :
case FUNC_ATAN :
case FUNC_ATAN2 :
case FUNC_COS :
case FUNC_COT :
case FUNC_DEGREES :
case FUNC_SIN :
case FUNC_TAN :
case FUNC_LOG10 :
case FUNC_RADIANS :
case FUNC_ROUNDMAGIC :
case FUNC_SIGN : {
return new StringBuffer(name).append('(') //
.append(nodes[0].getSQL()).append(')').toString();
}
case FUNC_ROUND : {
return new StringBuffer(Tokens.ROUND).append('(') //
.append(nodes[0].getSQL()).append(Tokens.T_COMMA) //
.append(nodes[1].getSQL()).append(')').toString();
}
default :
return super.getSQL();
}
}
}