📄 function.java
字号:
}
public static Function getFunction(Database database, String name) throws SQLException {
FunctionInfo info = getFunctionInfo(name);
if (info == null) {
return null;
}
switch(info.type) {
case TABLE:
case TABLE_DISTINCT:
return new TableFunction(database, info);
default:
return new Function(database, info);
}
}
protected Function(Database database, FunctionInfo info) {
this.database = database;
this.info = info;
if (info.parameterCount == VAR_ARGS) {
varArgs = new ObjectArray();
} else {
args = new Expression[info.parameterCount];
}
}
public void setParameter(int index, Expression param) throws SQLException {
if (varArgs != null) {
varArgs.add(param);
} else {
if (index >= args.length) {
throw Message.getSQLException(ErrorCode.INVALID_PARAMETER_COUNT_2, new String[] { info.name,
"" + args.length });
}
args[index] = param;
}
}
private strictfp double log10(double value) {
return roundmagic(StrictMath.log(value) / StrictMath.log(10));
}
public Value getValue(Session session) throws SQLException {
return getValueWithArgs(session, args);
}
private Value getNullOrValue(Session session, Expression[] x, int i) throws SQLException {
if (i < x.length) {
Expression e = x[i];
if (e != null) {
return e.getValue(session);
}
}
return null;
}
private Value getSimpleValue(Session session, Value v0, Expression[] args) throws SQLException {
Value result;
switch (info.type) {
case ABS:
result = v0.getSignum() > 0 ? v0 : v0.negate();
break;
case ACOS:
result = ValueDouble.get(Math.acos(v0.getDouble()));
break;
case ASIN:
result = ValueDouble.get(Math.asin(v0.getDouble()));
break;
case ATAN:
result = ValueDouble.get(Math.atan(v0.getDouble()));
break;
case CEILING:
result = ValueDouble.get(Math.ceil(v0.getDouble()));
break;
case COS:
result = ValueDouble.get(Math.cos(v0.getDouble()));
break;
case COT: {
double d = Math.tan(v0.getDouble());
if (d == 0.0) {
throw Message.getSQLException(ErrorCode.DIVISION_BY_ZERO_1, getSQL());
}
result = ValueDouble.get(1. / d);
break;
}
case DEGREES:
result = ValueDouble.get(Math.toDegrees(v0.getDouble()));
break;
case EXP:
result = ValueDouble.get(Math.exp(v0.getDouble()));
break;
case FLOOR:
result = ValueDouble.get(Math.floor(v0.getDouble()));
break;
case LOG:
result = ValueDouble.get(Math.log(v0.getDouble()));
break;
case LOG10:
result = ValueDouble.get(log10(v0.getDouble()));
break;
case PI:
result = ValueDouble.get(Math.PI);
break;
case RADIANS:
result = ValueDouble.get(Math.toRadians(v0.getDouble()));
break;
case RAND: {
if (v0 != null) {
session.getRandom().setSeed(v0.getInt());
}
// TODO function rand: if seed value is set,
// return a random value? probably yes
result = ValueDouble.get(session.getRandom().nextDouble());
break;
}
case ROUNDMAGIC:
result = ValueDouble.get(roundmagic(v0.getDouble()));
break;
case SIGN:
result = ValueInt.get(v0.getSignum());
break;
case SIN:
result = ValueDouble.get(Math.sin(v0.getDouble()));
break;
case SQRT:
result = ValueDouble.get(Math.sqrt(v0.getDouble()));
break;
case TAN:
result = ValueDouble.get(Math.tan(v0.getDouble()));
break;
case SECURE_RAND:
result = ValueBytes.getNoCopy(RandomUtils.getSecureBytes(v0.getInt()));
break;
case EXPAND:
result = ValueBytes.getNoCopy(CompressTool.getInstance().expand(v0.getBytesNoCopy()));
break;
case ZERO:
result = ValueInt.get(0);
break;
case RANDOM_UUID:
result = ValueUuid.getNewRandom();
break;
// string
case ASCII: {
String s = v0.getString();
if (s.length() == 0) {
result = ValueNull.INSTANCE;
} else {
result = ValueInt.get(s.charAt(0));
}
break;
}
case BIT_LENGTH:
result = ValueInt.get(16 * length(v0));
break;
case CHAR:
result = ValueString.get(String.valueOf((char) v0.getInt()));
break;
case CHAR_LENGTH:
case LENGTH:
result = ValueInt.get(length(v0));
break;
case OCTET_LENGTH:
result = ValueInt.get(2 * length(v0));
break;
case CONCAT: {
result = ValueNull.INSTANCE;
for (int i = 0; i < args.length; i++) {
Value v = args[i].getValue(session);
if (v == ValueNull.INSTANCE) {
continue;
}
if (result == ValueNull.INSTANCE) {
result = v;
} else {
result = ValueString.get(result.getString().concat(v.getString()));
}
}
break;
}
case HEXTORAW:
result = ValueString.get(hexToRaw(v0.getString()));
break;
case LOWER:
case LCASE:
// TODO this is locale specific, need to document or provide a way
// to set the locale
result = ValueString.get(v0.getString().toLowerCase());
break;
case RAWTOHEX:
result = ValueString.get(rawToHex(v0.getString()));
break;
case SOUNDEX:
result = ValueString.get(getSoundex(v0.getString()));
break;
case SPACE: {
// TODO DOS attacks: limit len?
int len = Math.max(0, v0.getInt());
char[] chars = new char[len];
for (int i = len - 1; i >= 0; i--) {
chars[i] = ' ';
}
result = ValueString.get(new String(chars));
break;
}
case UPPER:
case UCASE:
// TODO this is locale specific, need to document or provide a way
// to set the locale
result = ValueString.get(v0.getString().toUpperCase());
break;
case STRINGENCODE:
result = ValueString.get(StringUtils.javaEncode(v0.getString()));
break;
case STRINGDECODE:
result = ValueString.get(StringUtils.javaDecode(v0.getString()));
break;
case STRINGTOUTF8:
result = ValueBytes.getNoCopy(StringUtils.utf8Encode(v0.getString()));
break;
case UTF8TOSTRING:
result = ValueString.get(StringUtils.utf8Decode(v0.getBytesNoCopy()));
break;
case XMLCOMMENT:
result = ValueString.get(StringUtils.xmlComment(v0.getString()));
break;
case XMLCDATA:
result = ValueString.get(StringUtils.xmlCData(v0.getString()));
break;
case XMLSTARTDOC:
result = ValueString.get(StringUtils.xmlStartDoc());
break;
case XMLTEXT:
result = ValueString.get(StringUtils.xmlText(v0.getString()));
break;
case DAYNAME: {
synchronized (FORMAT_DAYNAME) {
result = ValueString.get(FORMAT_DAYNAME.format(v0.getDateNoCopy()));
}
break;
}
case DAYOFMONTH:
result = ValueInt.get(getDatePart(v0.getTimestampNoCopy(), Calendar.DAY_OF_MONTH));
break;
case DAYOFWEEK:
result = ValueInt.get(getDatePart(v0.getTimestampNoCopy(), Calendar.DAY_OF_WEEK));
break;
case DAYOFYEAR:
result = ValueInt.get(getDatePart(v0.getTimestampNoCopy(), Calendar.DAY_OF_YEAR));
break;
case HOUR:
result = ValueInt.get(getDatePart(v0.getTimestampNoCopy(), Calendar.HOUR_OF_DAY));
break;
case MINUTE:
result = ValueInt.get(getDatePart(v0.getTimestampNoCopy(), Calendar.MINUTE));
break;
case MONTH:
result = ValueInt.get(getDatePart(v0.getTimestampNoCopy(), Calendar.MONTH));
break;
case MONTHNAME: {
synchronized (FORMAT_MONTHNAME) {
result = ValueString.get(FORMAT_MONTHNAME.format(v0.getDateNoCopy()));
}
break;
}
case QUARTER:
result = ValueInt.get((getDatePart(v0.getTimestamp(), Calendar.MONTH) - 1) / 3 + 1);
break;
case SECOND:
result = ValueInt.get(getDatePart(v0.getTimestamp(), Calendar.SECOND));
break;
case WEEK:
result = ValueInt.get(getDatePart(v0.getTimestamp(), Calendar.WEEK_OF_YEAR));
break;
case YEAR:
result = ValueInt.get(getDatePart(v0.getTimestamp(), Calendar.YEAR));
break;
case CURDATE:
case CURRENT_DATE:
// need to normalize
result = ValueDate.get(new Date(System.currentTimeMillis()));
break;
case CURTIME:
case CURRENT_TIME:
// need to normalize
result = ValueTime.get(new Time(System.currentTimeMillis()));
break;
case NOW:
case CURRENT_TIMESTAMP: {
ValueTimestamp vt = ValueTimestamp.getNoCopy(new Timestamp(System.currentTimeMillis()));
if (v0 != null) {
Mode mode = database.getMode();
vt = (ValueTimestamp) vt.convertScale(mode.convertOnlyToSmallerScale, v0.getInt());
}
result = vt;
break;
}
case DATABASE:
result = ValueString.get(database.getShortName());
break;
case USER:
case CURRENT_USER:
result = ValueString.get(session.getUser().getName());
break;
case IDENTITY:
result = session.getLastIdentity();
break;
case AUTOCOMMIT:
result = ValueBoolean.get(session.getAutoCommit());
break;
case READONLY:
result = ValueBoolean.get(database.getReadOnly());
break;
case DATABASE_PATH: {
String path = database.getDatabasePath();
result = path == null ? (Value) ValueNull.INSTANCE : ValueString.get(path);
break;
}
case LOCK_TIMEOUT:
result = ValueInt.get(session.getLockTimeout());
break;
case CAST:
case CONVERT: {
v0 = v0.convertTo(dataType);
Mode mode = database.getMode();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -