Source Code Cross Referenced for Function.java in  » Database-DBMS » h2database » org » h2 » expression » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » h2database » org.h2.expression 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
0003:         * (http://h2database.com/html/license.html).
0004:         * Initial Developer: H2 Group
0005:         */
0006:        package org.h2.expression;
0007:
0008:        import java.io.IOException;
0009:        import java.io.InputStream;
0010:        import java.io.InputStreamReader;
0011:        import java.io.Reader;
0012:        import java.sql.Connection;
0013:        import java.sql.Date;
0014:        import java.sql.ResultSet;
0015:        import java.sql.SQLException;
0016:        import java.sql.Time;
0017:        import java.sql.Timestamp;
0018:        import java.text.SimpleDateFormat;
0019:        import java.util.Calendar;
0020:        import java.util.HashMap;
0021:        import java.util.Locale;
0022:        import java.util.TimeZone;
0023:        import java.util.regex.PatternSyntaxException;
0024:
0025:        import org.h2.command.Command;
0026:        import org.h2.constant.ErrorCode;
0027:        import org.h2.engine.Database;
0028:        import org.h2.engine.Mode;
0029:        import org.h2.engine.Session;
0030:        import org.h2.message.Message;
0031:        import org.h2.schema.Sequence;
0032:        import org.h2.security.BlockCipher;
0033:        import org.h2.security.CipherFactory;
0034:        import org.h2.security.SHA256;
0035:        import org.h2.table.Column;
0036:        import org.h2.table.ColumnResolver;
0037:        import org.h2.table.LinkSchema;
0038:        import org.h2.table.TableFilter;
0039:        import org.h2.tools.CompressTool;
0040:        import org.h2.tools.Csv;
0041:        import org.h2.util.AutoCloseInputStream;
0042:        import org.h2.util.FileUtils;
0043:        import org.h2.util.MathUtils;
0044:        import org.h2.util.MemoryUtils;
0045:        import org.h2.util.ObjectArray;
0046:        import org.h2.util.ObjectUtils;
0047:        import org.h2.util.RandomUtils;
0048:        import org.h2.util.StringUtils;
0049:        import org.h2.value.Value;
0050:        import org.h2.value.ValueArray;
0051:        import org.h2.value.ValueBoolean;
0052:        import org.h2.value.ValueBytes;
0053:        import org.h2.value.ValueDate;
0054:        import org.h2.value.ValueDouble;
0055:        import org.h2.value.ValueInt;
0056:        import org.h2.value.ValueLob;
0057:        import org.h2.value.ValueLong;
0058:        import org.h2.value.ValueNull;
0059:        import org.h2.value.ValueResultSet;
0060:        import org.h2.value.ValueString;
0061:        import org.h2.value.ValueTime;
0062:        import org.h2.value.ValueTimestamp;
0063:        import org.h2.value.ValueUuid;
0064:
0065:        /**
0066:         * This class implements most built-in functions of this database.
0067:         */
0068:        public class Function extends Expression implements  FunctionCall {
0069:            // TODO functions: add function hashcode(value)
0070:
0071:            public static final int ABS = 0, ACOS = 1, ASIN = 2, ATAN = 3,
0072:                    ATAN2 = 4, BITAND = 5, BITOR = 6, BITXOR = 7, CEILING = 8,
0073:                    COS = 9, COT = 10, DEGREES = 11, EXP = 12, FLOOR = 13,
0074:                    LOG = 14, LOG10 = 15, MOD = 16, PI = 17, POWER = 18,
0075:                    RADIANS = 19, RAND = 20, ROUND = 21, ROUNDMAGIC = 22,
0076:                    SIGN = 23, SIN = 24, SQRT = 25, TAN = 26, TRUNCATE = 27,
0077:                    SECURE_RAND = 28, HASH = 29, ENCRYPT = 30, DECRYPT = 31,
0078:                    COMPRESS = 32, EXPAND = 33, ZERO = 34, RANDOM_UUID = 35;
0079:
0080:            public static final int ASCII = 50, BIT_LENGTH = 51, CHAR = 52,
0081:                    CHAR_LENGTH = 53, CONCAT = 54, DIFFERENCE = 55,
0082:                    HEXTORAW = 56, INSERT = 57, INSTR = 58, LCASE = 59,
0083:                    LEFT = 60, LENGTH = 61, LOCATE = 62, LTRIM = 63,
0084:                    OCTET_LENGTH = 64, RAWTOHEX = 65, REPEAT = 66,
0085:                    REPLACE = 67, RIGHT = 68, RTRIM = 69, SOUNDEX = 70,
0086:                    SPACE = 71, SUBSTR = 72, SUBSTRING = 73, UCASE = 74,
0087:                    LOWER = 75, UPPER = 76, POSITION = 77, TRIM = 78,
0088:                    STRINGENCODE = 79, STRINGDECODE = 80, STRINGTOUTF8 = 81,
0089:                    UTF8TOSTRING = 82, XMLATTR = 83, XMLNODE = 84,
0090:                    XMLCOMMENT = 85, XMLCDATA = 86, XMLSTARTDOC = 87,
0091:                    XMLTEXT = 88, REGEXP_REPLACE = 89, RPAD = 90, LPAD = 91;
0092:
0093:            public static final int CURDATE = 100, CURTIME = 101,
0094:                    DATEADD = 102, DATEDIFF = 103, DAYNAME = 104,
0095:                    DAYOFMONTH = 105, DAYOFWEEK = 106, DAYOFYEAR = 107,
0096:                    HOUR = 108, MINUTE = 109, MONTH = 110, MONTHNAME = 111,
0097:                    NOW = 112, QUARTER = 113, SECOND = 114, WEEK = 115,
0098:                    YEAR = 116, CURRENT_DATE = 117, CURRENT_TIME = 118,
0099:                    CURRENT_TIMESTAMP = 119, EXTRACT = 120,
0100:                    FORMATDATETIME = 121, PARSEDATETIME = 122;
0101:
0102:            public static final int DATABASE = 150, USER = 151,
0103:                    CURRENT_USER = 152, IDENTITY = 153, AUTOCOMMIT = 154,
0104:                    READONLY = 155, DATABASE_PATH = 156, LOCK_TIMEOUT = 157;
0105:
0106:            public static final int IFNULL = 200, CASEWHEN = 201,
0107:                    CONVERT = 202, CAST = 203, COALESCE = 204, NULLIF = 205,
0108:                    CASE = 206, NEXTVAL = 207, CURRVAL = 208, ARRAY_GET = 209,
0109:                    CSVREAD = 210, CSVWRITE = 211, MEMORY_FREE = 212,
0110:                    MEMORY_USED = 213, LOCK_MODE = 214, SCHEMA = 215,
0111:                    SESSION_ID = 216, ARRAY_LENGTH = 217, LINK_SCHEMA = 218,
0112:                    GREATEST = 219, LEAST = 220, CANCEL_SESSION = 221,
0113:                    SET = 222, TABLE = 223, TABLE_DISTINCT = 224,
0114:                    FILE_READ = 225;
0115:
0116:            private static final int VAR_ARGS = -1;
0117:
0118:            private static final HashMap FUNCTIONS = new HashMap();
0119:            private static final HashMap DATE_PART = new HashMap();
0120:            private static final SimpleDateFormat FORMAT_DAYNAME = new SimpleDateFormat(
0121:                    "EEEE", Locale.ENGLISH);
0122:            private static final SimpleDateFormat FORMAT_MONTHNAME = new SimpleDateFormat(
0123:                    "MMMM", Locale.ENGLISH);
0124:            private static final char[] SOUNDEX_INDEX = new char[128];
0125:
0126:            private FunctionInfo info;
0127:            protected Expression[] args;
0128:            private ObjectArray varArgs;
0129:            private int dataType, scale;
0130:            private long precision;
0131:            private int displaySize;
0132:            private Database database;
0133:
0134:            static {
0135:                // DATE_PART
0136:                DATE_PART.put("YY", ObjectUtils.getInteger(Calendar.YEAR));
0137:                DATE_PART.put("YEAR", ObjectUtils.getInteger(Calendar.YEAR));
0138:                DATE_PART.put("MM", ObjectUtils.getInteger(Calendar.MONTH));
0139:                DATE_PART.put("MONTH", ObjectUtils.getInteger(Calendar.MONTH));
0140:                DATE_PART.put("DD", ObjectUtils.getInteger(Calendar.DATE));
0141:                DATE_PART.put("DAY", ObjectUtils.getInteger(Calendar.DATE));
0142:                DATE_PART.put("HH", ObjectUtils
0143:                        .getInteger(Calendar.HOUR_OF_DAY));
0144:                DATE_PART.put("HOUR", ObjectUtils
0145:                        .getInteger(Calendar.HOUR_OF_DAY));
0146:                DATE_PART.put("MI", ObjectUtils.getInteger(Calendar.MINUTE));
0147:                DATE_PART
0148:                        .put("MINUTE", ObjectUtils.getInteger(Calendar.MINUTE));
0149:                DATE_PART.put("SS", ObjectUtils.getInteger(Calendar.SECOND));
0150:                DATE_PART
0151:                        .put("SECOND", ObjectUtils.getInteger(Calendar.SECOND));
0152:                DATE_PART.put("MS", ObjectUtils
0153:                        .getInteger(Calendar.MILLISECOND));
0154:                DATE_PART.put("MILLISECOND", ObjectUtils
0155:                        .getInteger(Calendar.MILLISECOND));
0156:
0157:                // SOUNDEX_INDEX
0158:                String index = "7AEIOUY8HW1BFPV2CGJKQSXZ3DT4L5MN6R";
0159:                char number = 0;
0160:                for (int i = 0; i < index.length(); i++) {
0161:                    char c = index.charAt(i);
0162:                    if (c < '9') {
0163:                        number = c;
0164:                    } else {
0165:                        SOUNDEX_INDEX[c] = number;
0166:                        SOUNDEX_INDEX[Character.toLowerCase(c)] = number;
0167:                    }
0168:                }
0169:
0170:                // FUNCTIONS
0171:                addFunction("ABS", ABS, 1, Value.NULL);
0172:                addFunction("ACOS", ACOS, 1, Value.DOUBLE);
0173:                addFunction("ASIN", ASIN, 1, Value.DOUBLE);
0174:                addFunction("ATAN", ATAN, 1, Value.DOUBLE);
0175:                addFunction("ATAN2", ATAN2, 2, Value.DOUBLE);
0176:                addFunction("BITAND", BITAND, 2, Value.INT);
0177:                addFunction("BITOR", BITOR, 2, Value.INT);
0178:                addFunction("BITXOR", BITXOR, 2, Value.INT);
0179:                addFunction("CEILING", CEILING, 1, Value.DOUBLE);
0180:                addFunction("COS", COS, 1, Value.DOUBLE);
0181:                addFunction("COT", COT, 1, Value.DOUBLE);
0182:                addFunction("DEGREES", DEGREES, 1, Value.DOUBLE);
0183:                addFunction("EXP", EXP, 1, Value.DOUBLE);
0184:                addFunction("FLOOR", FLOOR, 1, Value.DOUBLE);
0185:                addFunction("LOG", LOG, 1, Value.DOUBLE);
0186:                addFunction("LOG10", LOG10, 1, Value.DOUBLE);
0187:                addFunction("MOD", MOD, 2, Value.INT);
0188:                addFunction("PI", PI, 0, Value.DOUBLE);
0189:                addFunction("POWER", POWER, 2, Value.DOUBLE);
0190:                addFunction("RADIANS", RADIANS, 1, Value.DOUBLE);
0191:                // RAND without argument: get the next value
0192:                // RAND with one argument: seed the random generator
0193:                addFunctionNotConst("RAND", RAND, VAR_ARGS, Value.DOUBLE);
0194:                addFunction("ROUND", ROUND, 2, Value.DOUBLE);
0195:                addFunction("ROUNDMAGIC", ROUNDMAGIC, 1, Value.DOUBLE);
0196:                addFunction("SIGN", SIGN, 1, Value.INT);
0197:                addFunction("SIN", SIN, 1, Value.DOUBLE);
0198:                addFunction("SQRT", SQRT, 1, Value.DOUBLE);
0199:                addFunction("TAN", TAN, 1, Value.DOUBLE);
0200:                addFunction("TRUNCATE", TRUNCATE, 2, Value.DOUBLE);
0201:                addFunction("HASH", HASH, 3, Value.BYTES);
0202:                addFunction("ENCRYPT", ENCRYPT, 3, Value.BYTES);
0203:                addFunction("DECRYPT", DECRYPT, 3, Value.BYTES);
0204:                addFunctionNotConst("SECURE_RAND", SECURE_RAND, 1, Value.BYTES);
0205:                addFunction("COMPRESS", COMPRESS, VAR_ARGS, Value.BYTES);
0206:                addFunction("EXPAND", EXPAND, 1, Value.BYTES);
0207:                addFunction("ZERO", ZERO, 0, Value.INT);
0208:                addFunctionNotConst("RANDOM_UUID", RANDOM_UUID, 0, Value.UUID);
0209:                addFunctionNotConst("SYS_GUID", RANDOM_UUID, 0, Value.UUID);
0210:                // string
0211:                addFunction("ASCII", ASCII, 1, Value.INT);
0212:                addFunction("BIT_LENGTH", BIT_LENGTH, 1, Value.INT);
0213:                addFunction("CHAR", CHAR, 1, Value.STRING);
0214:                addFunction("CHR", CHAR, 1, Value.STRING);
0215:                addFunction("CHAR_LENGTH", CHAR_LENGTH, 1, Value.INT);
0216:                addFunction("CHARACTER_LENGTH", CHAR_LENGTH, 1, Value.INT); // same as
0217:                // CHAR_LENGTH
0218:                addFunctionWithNull("CONCAT", CONCAT, VAR_ARGS, Value.STRING);
0219:                addFunction("DIFFERENCE", DIFFERENCE, 2, Value.INT);
0220:                addFunction("HEXTORAW", HEXTORAW, 1, Value.STRING);
0221:                addFunctionWithNull("INSERT", INSERT, 4, Value.STRING);
0222:                addFunction("LCASE", LCASE, 1, Value.STRING);
0223:                addFunction("LEFT", LEFT, 2, Value.STRING);
0224:                addFunction("LENGTH", LENGTH, 1, Value.INT);
0225:                addFunction("LOCATE", LOCATE, VAR_ARGS, Value.INT); // 2 or 3 arguments
0226:                addFunction("POSITION", LOCATE, 2, Value.INT); // same as LOCATE with 2
0227:                // arguments
0228:                addFunction("INSTR", INSTR, VAR_ARGS, Value.INT);
0229:                addFunction("LTRIM", LTRIM, VAR_ARGS, Value.STRING);
0230:                addFunction("OCTET_LENGTH", OCTET_LENGTH, 1, Value.INT);
0231:                addFunction("RAWTOHEX", RAWTOHEX, 1, Value.STRING);
0232:                addFunction("REPEAT", REPEAT, 2, Value.STRING);
0233:                addFunctionWithNull("REPLACE", REPLACE, VAR_ARGS, Value.STRING);
0234:                addFunction("RIGHT", RIGHT, 2, Value.STRING);
0235:                addFunction("RTRIM", RTRIM, VAR_ARGS, Value.STRING);
0236:                addFunction("SOUNDEX", SOUNDEX, 1, Value.STRING);
0237:                addFunction("SPACE", SPACE, 1, Value.STRING);
0238:                addFunction("SUBSTR", SUBSTR, VAR_ARGS, Value.STRING);
0239:                addFunction("SUBSTRING", SUBSTRING, VAR_ARGS, Value.STRING);
0240:                addFunction("UCASE", UCASE, 1, Value.STRING);
0241:                addFunction("LOWER", LOWER, 1, Value.STRING);
0242:                addFunction("UPPER", UPPER, 1, Value.STRING);
0243:                addFunction("POSITION", POSITION, 2, Value.INT);
0244:                addFunction("TRIM", TRIM, VAR_ARGS, Value.STRING);
0245:                addFunction("STRINGENCODE", STRINGENCODE, 1, Value.STRING);
0246:                addFunction("STRINGDECODE", STRINGDECODE, 1, Value.STRING);
0247:                addFunction("STRINGTOUTF8", STRINGTOUTF8, 1, Value.BYTES);
0248:                addFunction("UTF8TOSTRING", UTF8TOSTRING, 1, Value.STRING);
0249:                addFunction("XMLATTR", XMLATTR, 2, Value.STRING);
0250:                addFunctionWithNull("XMLNODE", XMLNODE, VAR_ARGS, Value.STRING);
0251:                addFunction("XMLCOMMENT", XMLCOMMENT, 1, Value.STRING);
0252:                addFunction("XMLCDATA", XMLCDATA, 1, Value.STRING);
0253:                addFunction("XMLSTARTDOC", XMLSTARTDOC, 0, Value.STRING);
0254:                addFunction("XMLTEXT", XMLTEXT, 1, Value.STRING);
0255:                addFunction("REGEXP_REPLACE", REGEXP_REPLACE, 3, Value.STRING);
0256:                addFunction("RPAD", RPAD, VAR_ARGS, Value.STRING);
0257:                addFunction("LPAD", LPAD, VAR_ARGS, Value.STRING);
0258:
0259:                // date
0260:                addFunctionNotConst("CURRENT_DATE", CURRENT_DATE, 0, Value.DATE);
0261:                addFunctionNotConst("CURDATE", CURDATE, 0, Value.DATE);
0262:                addFunctionNotConst("CURRENT_TIME", CURRENT_TIME, 0, Value.TIME);
0263:                addFunctionNotConst("CURTIME", CURTIME, 0, Value.TIME);
0264:                addFunctionNotConst("CURRENT_TIMESTAMP", CURRENT_TIMESTAMP,
0265:                        VAR_ARGS, Value.TIMESTAMP);
0266:                addFunctionNotConst("NOW", NOW, VAR_ARGS, Value.TIMESTAMP);
0267:                addFunction("DATEADD", DATEADD, 3, Value.TIMESTAMP);
0268:                addFunction("DATEDIFF", DATEDIFF, 3, Value.LONG);
0269:                addFunction("DAYNAME", DAYNAME, 1, Value.STRING);
0270:                addFunction("DAY", DAYOFMONTH, 1, Value.INT);
0271:                addFunction("DAYOFMONTH", DAYOFMONTH, 1, Value.INT);
0272:                addFunction("DAYOFWEEK", DAYOFWEEK, 1, Value.INT);
0273:                addFunction("DAYOFYEAR", DAYOFYEAR, 1, Value.INT);
0274:                addFunction("HOUR", HOUR, 1, Value.INT);
0275:                addFunction("MINUTE", MINUTE, 1, Value.INT);
0276:                addFunction("MONTH", MONTH, 1, Value.INT);
0277:                addFunction("MONTHNAME", MONTHNAME, 1, Value.STRING);
0278:                addFunction("QUARTER", QUARTER, 1, Value.INT);
0279:                addFunction("SECOND", SECOND, 1, Value.INT);
0280:                addFunction("WEEK", WEEK, 1, Value.INT);
0281:                addFunction("YEAR", YEAR, 1, Value.INT);
0282:                addFunction("EXTRACT", EXTRACT, 2, Value.INT);
0283:                addFunctionWithNull("FORMATDATETIME", FORMATDATETIME, VAR_ARGS,
0284:                        Value.STRING);
0285:                addFunctionWithNull("PARSEDATETIME", PARSEDATETIME, VAR_ARGS,
0286:                        Value.TIMESTAMP);
0287:                // system
0288:                addFunctionNotConst("DATABASE", DATABASE, 0, Value.STRING);
0289:                addFunctionNotConst("USER", USER, 0, Value.STRING);
0290:                addFunctionNotConst("CURRENT_USER", CURRENT_USER, 0,
0291:                        Value.STRING);
0292:                addFunctionNotConst("IDENTITY", IDENTITY, 0, Value.LONG);
0293:                addFunctionNotConst("IDENTITY_VAL_LOCAL", IDENTITY, 0,
0294:                        Value.LONG);
0295:                addFunctionNotConst("LAST_INSERT_ID", IDENTITY, 0, Value.LONG);
0296:                addFunctionNotConst("AUTOCOMMIT", AUTOCOMMIT, 0, Value.BOOLEAN);
0297:                addFunctionNotConst("READONLY", READONLY, 0, Value.BOOLEAN);
0298:                addFunction("DATABASE_PATH", DATABASE_PATH, 0, Value.STRING);
0299:                addFunction("LOCK_TIMEOUT", LOCK_TIMEOUT, 0, Value.INT);
0300:                addFunctionWithNull("IFNULL", IFNULL, 2, Value.NULL);
0301:                addFunctionWithNull("CASEWHEN", CASEWHEN, 3, Value.NULL);
0302:                addFunctionWithNull("CONVERT", CONVERT, 1, Value.NULL);
0303:                addFunctionWithNull("CAST", CAST, 1, Value.NULL);
0304:                addFunctionWithNull("COALESCE", COALESCE, VAR_ARGS, Value.NULL);
0305:                addFunctionWithNull("NVL", COALESCE, VAR_ARGS, Value.NULL);
0306:                addFunctionWithNull("NULLIF", NULLIF, 2, Value.NULL);
0307:                addFunctionWithNull("CASE", CASE, VAR_ARGS, Value.NULL);
0308:                addFunctionNotConst("NEXTVAL", NEXTVAL, VAR_ARGS, Value.LONG);
0309:                addFunctionNotConst("CURRVAL", CURRVAL, VAR_ARGS, Value.LONG);
0310:                addFunction("ARRAY_GET", ARRAY_GET, 2, Value.NULL);
0311:                addFunction("CSVREAD", CSVREAD, VAR_ARGS, Value.RESULT_SET,
0312:                        false, false);
0313:                addFunction("CSVWRITE", CSVWRITE, VAR_ARGS, Value.INT, false,
0314:                        false);
0315:                addFunctionNotConst("MEMORY_FREE", MEMORY_FREE, 0, Value.INT);
0316:                addFunctionNotConst("MEMORY_USED", MEMORY_USED, 0, Value.INT);
0317:                addFunctionNotConst("LOCK_MODE", LOCK_MODE, 0, Value.INT);
0318:                addFunctionNotConst("SCHEMA", SCHEMA, 0, Value.STRING);
0319:                addFunctionNotConst("SESSION_ID", SESSION_ID, 0, Value.INT);
0320:                addFunction("ARRAY_LENGTH", ARRAY_LENGTH, 1, Value.INT);
0321:                addFunction("LINK_SCHEMA", LINK_SCHEMA, 6, Value.RESULT_SET);
0322:                addFunctionWithNull("LEAST", LEAST, VAR_ARGS, Value.NULL);
0323:                addFunctionWithNull("GREATEST", GREATEST, VAR_ARGS, Value.NULL);
0324:                addFunction("CANCEL_SESSION", CANCEL_SESSION, 1, Value.BOOLEAN);
0325:                addFunction("SET", SET, 2, Value.NULL, false, false);
0326:                addFunction("FILE_READ", FILE_READ, VAR_ARGS, Value.NULL,
0327:                        false, true);
0328:
0329:                // TableFunction
0330:                addFunctionWithNull("TABLE", TABLE, VAR_ARGS, Value.RESULT_SET);
0331:                addFunctionWithNull("TABLE_DISTINCT", TABLE_DISTINCT, VAR_ARGS,
0332:                        Value.RESULT_SET);
0333:            }
0334:
0335:            private static void addFunction(String name, int type,
0336:                    int parameterCount, int dataType,
0337:                    boolean nullIfParameterIsNull, boolean isDeterm) {
0338:                FunctionInfo info = new FunctionInfo();
0339:                info.name = name;
0340:                info.type = type;
0341:                info.parameterCount = parameterCount;
0342:                info.dataType = dataType;
0343:                info.nullIfParameterIsNull = nullIfParameterIsNull;
0344:                info.isDeterministic = isDeterm;
0345:                FUNCTIONS.put(name, info);
0346:            }
0347:
0348:            private static void addFunctionNotConst(String name, int type,
0349:                    int parameterCount, int dataType) {
0350:                addFunction(name, type, parameterCount, dataType, true, false);
0351:            }
0352:
0353:            private static void addFunction(String name, int type,
0354:                    int parameterCount, int dataType) {
0355:                addFunction(name, type, parameterCount, dataType, true, true);
0356:            }
0357:
0358:            private static void addFunctionWithNull(String name, int type,
0359:                    int parameterCount, int dataType) {
0360:                addFunction(name, type, parameterCount, dataType, false, true);
0361:            }
0362:
0363:            public static FunctionInfo getFunctionInfo(String name) {
0364:                return (FunctionInfo) FUNCTIONS.get(name);
0365:            }
0366:
0367:            public static Function getFunction(Database database, String name)
0368:                    throws SQLException {
0369:                FunctionInfo info = getFunctionInfo(name);
0370:                if (info == null) {
0371:                    return null;
0372:                }
0373:                switch (info.type) {
0374:                case TABLE:
0375:                case TABLE_DISTINCT:
0376:                    return new TableFunction(database, info);
0377:                default:
0378:                    return new Function(database, info);
0379:                }
0380:            }
0381:
0382:            protected Function(Database database, FunctionInfo info) {
0383:                this .database = database;
0384:                this .info = info;
0385:                if (info.parameterCount == VAR_ARGS) {
0386:                    varArgs = new ObjectArray();
0387:                } else {
0388:                    args = new Expression[info.parameterCount];
0389:                }
0390:            }
0391:
0392:            public void setParameter(int index, Expression param)
0393:                    throws SQLException {
0394:                if (varArgs != null) {
0395:                    varArgs.add(param);
0396:                } else {
0397:                    if (index >= args.length) {
0398:                        throw Message.getSQLException(
0399:                                ErrorCode.INVALID_PARAMETER_COUNT_2,
0400:                                new String[] { info.name, "" + args.length });
0401:                    }
0402:                    args[index] = param;
0403:                }
0404:            }
0405:
0406:            private strictfp double log10(double value) {
0407:                return roundmagic(StrictMath.log(value) / StrictMath.log(10));
0408:            }
0409:
0410:            public Value getValue(Session session) throws SQLException {
0411:                return getValueWithArgs(session, args);
0412:            }
0413:
0414:            private Value getNullOrValue(Session session, Expression[] x, int i)
0415:                    throws SQLException {
0416:                if (i < x.length) {
0417:                    Expression e = x[i];
0418:                    if (e != null) {
0419:                        return e.getValue(session);
0420:                    }
0421:                }
0422:                return null;
0423:            }
0424:
0425:            private Value getSimpleValue(Session session, Value v0,
0426:                    Expression[] args) throws SQLException {
0427:                Value result;
0428:                switch (info.type) {
0429:                case ABS:
0430:                    result = v0.getSignum() > 0 ? v0 : v0.negate();
0431:                    break;
0432:                case ACOS:
0433:                    result = ValueDouble.get(Math.acos(v0.getDouble()));
0434:                    break;
0435:                case ASIN:
0436:                    result = ValueDouble.get(Math.asin(v0.getDouble()));
0437:                    break;
0438:                case ATAN:
0439:                    result = ValueDouble.get(Math.atan(v0.getDouble()));
0440:                    break;
0441:                case CEILING:
0442:                    result = ValueDouble.get(Math.ceil(v0.getDouble()));
0443:                    break;
0444:                case COS:
0445:                    result = ValueDouble.get(Math.cos(v0.getDouble()));
0446:                    break;
0447:                case COT: {
0448:                    double d = Math.tan(v0.getDouble());
0449:                    if (d == 0.0) {
0450:                        throw Message.getSQLException(
0451:                                ErrorCode.DIVISION_BY_ZERO_1, getSQL());
0452:                    }
0453:                    result = ValueDouble.get(1. / d);
0454:                    break;
0455:                }
0456:                case DEGREES:
0457:                    result = ValueDouble.get(Math.toDegrees(v0.getDouble()));
0458:                    break;
0459:                case EXP:
0460:                    result = ValueDouble.get(Math.exp(v0.getDouble()));
0461:                    break;
0462:                case FLOOR:
0463:                    result = ValueDouble.get(Math.floor(v0.getDouble()));
0464:                    break;
0465:                case LOG:
0466:                    result = ValueDouble.get(Math.log(v0.getDouble()));
0467:                    break;
0468:                case LOG10:
0469:                    result = ValueDouble.get(log10(v0.getDouble()));
0470:                    break;
0471:                case PI:
0472:                    result = ValueDouble.get(Math.PI);
0473:                    break;
0474:                case RADIANS:
0475:                    result = ValueDouble.get(Math.toRadians(v0.getDouble()));
0476:                    break;
0477:                case RAND: {
0478:                    if (v0 != null) {
0479:                        session.getRandom().setSeed(v0.getInt());
0480:                    }
0481:                    // TODO function rand: if seed value is set,
0482:                    // return a random value? probably yes
0483:                    result = ValueDouble.get(session.getRandom().nextDouble());
0484:                    break;
0485:                }
0486:                case ROUNDMAGIC:
0487:                    result = ValueDouble.get(roundmagic(v0.getDouble()));
0488:                    break;
0489:                case SIGN:
0490:                    result = ValueInt.get(v0.getSignum());
0491:                    break;
0492:                case SIN:
0493:                    result = ValueDouble.get(Math.sin(v0.getDouble()));
0494:                    break;
0495:                case SQRT:
0496:                    result = ValueDouble.get(Math.sqrt(v0.getDouble()));
0497:                    break;
0498:                case TAN:
0499:                    result = ValueDouble.get(Math.tan(v0.getDouble()));
0500:                    break;
0501:                case SECURE_RAND:
0502:                    result = ValueBytes.getNoCopy(RandomUtils.getSecureBytes(v0
0503:                            .getInt()));
0504:                    break;
0505:                case EXPAND:
0506:                    result = ValueBytes.getNoCopy(CompressTool.getInstance()
0507:                            .expand(v0.getBytesNoCopy()));
0508:                    break;
0509:                case ZERO:
0510:                    result = ValueInt.get(0);
0511:                    break;
0512:                case RANDOM_UUID:
0513:                    result = ValueUuid.getNewRandom();
0514:                    break;
0515:                // string
0516:                case ASCII: {
0517:                    String s = v0.getString();
0518:                    if (s.length() == 0) {
0519:                        result = ValueNull.INSTANCE;
0520:                    } else {
0521:                        result = ValueInt.get(s.charAt(0));
0522:                    }
0523:                    break;
0524:                }
0525:                case BIT_LENGTH:
0526:                    result = ValueInt.get(16 * length(v0));
0527:                    break;
0528:                case CHAR:
0529:                    result = ValueString
0530:                            .get(String.valueOf((char) v0.getInt()));
0531:                    break;
0532:                case CHAR_LENGTH:
0533:                case LENGTH:
0534:                    result = ValueInt.get(length(v0));
0535:                    break;
0536:                case OCTET_LENGTH:
0537:                    result = ValueInt.get(2 * length(v0));
0538:                    break;
0539:                case CONCAT: {
0540:                    result = ValueNull.INSTANCE;
0541:                    for (int i = 0; i < args.length; i++) {
0542:                        Value v = args[i].getValue(session);
0543:                        if (v == ValueNull.INSTANCE) {
0544:                            continue;
0545:                        }
0546:                        if (result == ValueNull.INSTANCE) {
0547:                            result = v;
0548:                        } else {
0549:                            result = ValueString.get(result.getString().concat(
0550:                                    v.getString()));
0551:                        }
0552:                    }
0553:                    break;
0554:                }
0555:                case HEXTORAW:
0556:                    result = ValueString.get(hexToRaw(v0.getString()));
0557:                    break;
0558:                case LOWER:
0559:                case LCASE:
0560:                    // TODO this is locale specific, need to document or provide a way
0561:                    // to set the locale
0562:                    result = ValueString.get(v0.getString().toLowerCase());
0563:                    break;
0564:                case RAWTOHEX:
0565:                    result = ValueString.get(rawToHex(v0.getString()));
0566:                    break;
0567:                case SOUNDEX:
0568:                    result = ValueString.get(getSoundex(v0.getString()));
0569:                    break;
0570:                case SPACE: {
0571:                    // TODO DOS attacks: limit len?
0572:                    int len = Math.max(0, v0.getInt());
0573:                    char[] chars = new char[len];
0574:                    for (int i = len - 1; i >= 0; i--) {
0575:                        chars[i] = ' ';
0576:                    }
0577:                    result = ValueString.get(new String(chars));
0578:                    break;
0579:                }
0580:                case UPPER:
0581:                case UCASE:
0582:                    // TODO this is locale specific, need to document or provide a way
0583:                    // to set the locale
0584:                    result = ValueString.get(v0.getString().toUpperCase());
0585:                    break;
0586:                case STRINGENCODE:
0587:                    result = ValueString.get(StringUtils.javaEncode(v0
0588:                            .getString()));
0589:                    break;
0590:                case STRINGDECODE:
0591:                    result = ValueString.get(StringUtils.javaDecode(v0
0592:                            .getString()));
0593:                    break;
0594:                case STRINGTOUTF8:
0595:                    result = ValueBytes.getNoCopy(StringUtils.utf8Encode(v0
0596:                            .getString()));
0597:                    break;
0598:                case UTF8TOSTRING:
0599:                    result = ValueString.get(StringUtils.utf8Decode(v0
0600:                            .getBytesNoCopy()));
0601:                    break;
0602:                case XMLCOMMENT:
0603:                    result = ValueString.get(StringUtils.xmlComment(v0
0604:                            .getString()));
0605:                    break;
0606:                case XMLCDATA:
0607:                    result = ValueString.get(StringUtils.xmlCData(v0
0608:                            .getString()));
0609:                    break;
0610:                case XMLSTARTDOC:
0611:                    result = ValueString.get(StringUtils.xmlStartDoc());
0612:                    break;
0613:                case XMLTEXT:
0614:                    result = ValueString.get(StringUtils
0615:                            .xmlText(v0.getString()));
0616:                    break;
0617:                case DAYNAME: {
0618:                    synchronized (FORMAT_DAYNAME) {
0619:                        result = ValueString.get(FORMAT_DAYNAME.format(v0
0620:                                .getDateNoCopy()));
0621:                    }
0622:                    break;
0623:                }
0624:                case DAYOFMONTH:
0625:                    result = ValueInt.get(getDatePart(v0.getTimestampNoCopy(),
0626:                            Calendar.DAY_OF_MONTH));
0627:                    break;
0628:                case DAYOFWEEK:
0629:                    result = ValueInt.get(getDatePart(v0.getTimestampNoCopy(),
0630:                            Calendar.DAY_OF_WEEK));
0631:                    break;
0632:                case DAYOFYEAR:
0633:                    result = ValueInt.get(getDatePart(v0.getTimestampNoCopy(),
0634:                            Calendar.DAY_OF_YEAR));
0635:                    break;
0636:                case HOUR:
0637:                    result = ValueInt.get(getDatePart(v0.getTimestampNoCopy(),
0638:                            Calendar.HOUR_OF_DAY));
0639:                    break;
0640:                case MINUTE:
0641:                    result = ValueInt.get(getDatePart(v0.getTimestampNoCopy(),
0642:                            Calendar.MINUTE));
0643:                    break;
0644:                case MONTH:
0645:                    result = ValueInt.get(getDatePart(v0.getTimestampNoCopy(),
0646:                            Calendar.MONTH));
0647:                    break;
0648:                case MONTHNAME: {
0649:                    synchronized (FORMAT_MONTHNAME) {
0650:                        result = ValueString.get(FORMAT_MONTHNAME.format(v0
0651:                                .getDateNoCopy()));
0652:                    }
0653:                    break;
0654:                }
0655:                case QUARTER:
0656:                    result = ValueInt.get((getDatePart(v0.getTimestamp(),
0657:                            Calendar.MONTH) - 1) / 3 + 1);
0658:                    break;
0659:                case SECOND:
0660:                    result = ValueInt.get(getDatePart(v0.getTimestamp(),
0661:                            Calendar.SECOND));
0662:                    break;
0663:                case WEEK:
0664:                    result = ValueInt.get(getDatePart(v0.getTimestamp(),
0665:                            Calendar.WEEK_OF_YEAR));
0666:                    break;
0667:                case YEAR:
0668:                    result = ValueInt.get(getDatePart(v0.getTimestamp(),
0669:                            Calendar.YEAR));
0670:                    break;
0671:                case CURDATE:
0672:                case CURRENT_DATE:
0673:                    // need to normalize
0674:                    result = ValueDate
0675:                            .get(new Date(System.currentTimeMillis()));
0676:                    break;
0677:                case CURTIME:
0678:                case CURRENT_TIME:
0679:                    // need to normalize
0680:                    result = ValueTime
0681:                            .get(new Time(System.currentTimeMillis()));
0682:                    break;
0683:                case NOW:
0684:                case CURRENT_TIMESTAMP: {
0685:                    ValueTimestamp vt = ValueTimestamp.getNoCopy(new Timestamp(
0686:                            System.currentTimeMillis()));
0687:                    if (v0 != null) {
0688:                        Mode mode = database.getMode();
0689:                        vt = (ValueTimestamp) vt.convertScale(
0690:                                mode.convertOnlyToSmallerScale, v0.getInt());
0691:                    }
0692:                    result = vt;
0693:                    break;
0694:                }
0695:                case DATABASE:
0696:                    result = ValueString.get(database.getShortName());
0697:                    break;
0698:                case USER:
0699:                case CURRENT_USER:
0700:                    result = ValueString.get(session.getUser().getName());
0701:                    break;
0702:                case IDENTITY:
0703:                    result = session.getLastIdentity();
0704:                    break;
0705:                case AUTOCOMMIT:
0706:                    result = ValueBoolean.get(session.getAutoCommit());
0707:                    break;
0708:                case READONLY:
0709:                    result = ValueBoolean.get(database.getReadOnly());
0710:                    break;
0711:                case DATABASE_PATH: {
0712:                    String path = database.getDatabasePath();
0713:                    result = path == null ? (Value) ValueNull.INSTANCE
0714:                            : ValueString.get(path);
0715:                    break;
0716:                }
0717:                case LOCK_TIMEOUT:
0718:                    result = ValueInt.get(session.getLockTimeout());
0719:                    break;
0720:                case CAST:
0721:                case CONVERT: {
0722:                    v0 = v0.convertTo(dataType);
0723:                    Mode mode = database.getMode();
0724:                    v0 = v0.convertScale(mode.convertOnlyToSmallerScale, scale);
0725:                    v0 = v0.convertPrecision(getPrecision());
0726:                    result = v0;
0727:                    break;
0728:                }
0729:                case MEMORY_FREE:
0730:                    session.getUser().checkAdmin();
0731:                    result = ValueInt.get(MemoryUtils.getMemoryFree());
0732:                    break;
0733:                case MEMORY_USED:
0734:                    session.getUser().checkAdmin();
0735:                    result = ValueInt.get(MemoryUtils.getMemoryUsed());
0736:                    break;
0737:                case LOCK_MODE:
0738:                    result = ValueInt.get(database.getLockMode());
0739:                    break;
0740:                case SCHEMA:
0741:                    result = ValueString.get(session.getCurrentSchemaName());
0742:                    break;
0743:                case SESSION_ID:
0744:                    result = ValueInt.get(session.getId());
0745:                    break;
0746:                case IFNULL: {
0747:                    result = v0 == ValueNull.INSTANCE ? args[1]
0748:                            .getValue(session) : v0;
0749:                    break;
0750:                }
0751:                case CASEWHEN: {
0752:                    Expression expr;
0753:                    if (v0 == ValueNull.INSTANCE
0754:                            || !v0.getBoolean().booleanValue()) {
0755:                        expr = args[2];
0756:                    } else {
0757:                        expr = args[1];
0758:                    }
0759:                    Value v = expr.getValue(session);
0760:                    result = v.convertTo(dataType);
0761:                    break;
0762:                }
0763:                case COALESCE: {
0764:                    result = v0;
0765:                    for (int i = 0; i < args.length; i++) {
0766:                        Value v = i == 0 ? v0 : args[i].getValue(session);
0767:                        if (!(v == ValueNull.INSTANCE)) {
0768:                            result = v.convertTo(dataType);
0769:                            break;
0770:                        }
0771:                    }
0772:                    break;
0773:                }
0774:                case GREATEST:
0775:                case LEAST: {
0776:                    result = ValueNull.INSTANCE;
0777:                    for (int i = 0; i < args.length; i++) {
0778:                        Value v = i == 0 ? v0 : args[i].getValue(session);
0779:                        if (!(v == ValueNull.INSTANCE)) {
0780:                            v = v.convertTo(dataType);
0781:                            if (result == ValueNull.INSTANCE) {
0782:                                result = v;
0783:                            } else {
0784:                                int comp = database.compareTypeSave(result, v);
0785:                                if (info.type == GREATEST && comp < 0) {
0786:                                    result = v;
0787:                                } else if (info.type == LEAST && comp > 0) {
0788:                                    result = v;
0789:                                }
0790:                            }
0791:                        }
0792:                    }
0793:                    break;
0794:                }
0795:                case CASE: {
0796:                    result = null;
0797:                    int i = 0;
0798:                    for (; i < args.length; i++) {
0799:                        Value when = args[i++].getValue(session);
0800:                        if (Boolean.TRUE.equals(when)) {
0801:                            result = args[i].getValue(session);
0802:                            break;
0803:                        }
0804:                    }
0805:                    if (result == null) {
0806:                        result = i < args.length ? args[i].getValue(session)
0807:                                : ValueNull.INSTANCE;
0808:                    }
0809:                    break;
0810:                }
0811:                case ARRAY_GET: {
0812:                    if (v0.getType() == Value.ARRAY) {
0813:                        Value v1 = args[1].getValue(session);
0814:                        int element = v1.getInt();
0815:                        Value[] list = ((ValueArray) v0).getList();
0816:                        if (element < 1 || element > list.length) {
0817:                            result = ValueNull.INSTANCE;
0818:                        } else {
0819:                            result = list[element - 1];
0820:                        }
0821:                    } else {
0822:                        result = ValueNull.INSTANCE;
0823:                    }
0824:                    break;
0825:                }
0826:                case ARRAY_LENGTH: {
0827:                    if (v0.getType() == Value.ARRAY) {
0828:                        Value[] list = ((ValueArray) v0).getList();
0829:                        result = ValueInt.get(list.length);
0830:                    } else {
0831:                        result = ValueNull.INSTANCE;
0832:                    }
0833:                    break;
0834:                }
0835:                case CANCEL_SESSION: {
0836:                    result = ValueBoolean.get(cancelStatement(session, v0
0837:                            .getInt()));
0838:                    break;
0839:                }
0840:                default:
0841:                    result = null;
0842:                }
0843:                return result;
0844:            }
0845:
0846:            private boolean cancelStatement(Session session, int targetSessionId)
0847:                    throws SQLException {
0848:                session.getUser().checkAdmin();
0849:                Session[] sessions = session.getDatabase().getSessions();
0850:                for (int i = 0; i < sessions.length; i++) {
0851:                    Session s = sessions[i];
0852:                    if (s.getId() == targetSessionId) {
0853:                        Command c = s.getCurrentCommand();
0854:                        if (c == null) {
0855:                            return false;
0856:                        } else {
0857:                            c.cancel();
0858:                            return true;
0859:                        }
0860:                    }
0861:                }
0862:                return false;
0863:            }
0864:
0865:            public Value getValueWithArgs(Session session, Expression[] args)
0866:                    throws SQLException {
0867:                if (info.nullIfParameterIsNull) {
0868:                    for (int i = 0; i < args.length; i++) {
0869:                        if (getNullOrValue(session, args, i) == ValueNull.INSTANCE) {
0870:                            return ValueNull.INSTANCE;
0871:                        }
0872:                    }
0873:                }
0874:                Value v0 = getNullOrValue(session, args, 0);
0875:                Value resultSimple = getSimpleValue(session, v0, args);
0876:                if (resultSimple != null) {
0877:                    return resultSimple;
0878:                }
0879:                Value v1 = getNullOrValue(session, args, 1);
0880:                Value v2 = getNullOrValue(session, args, 2);
0881:                Value v3 = getNullOrValue(session, args, 3);
0882:                Value v4 = getNullOrValue(session, args, 4);
0883:                Value v5 = getNullOrValue(session, args, 5);
0884:                Value result;
0885:                switch (info.type) {
0886:                case ATAN2:
0887:                    result = ValueDouble.get(Math.atan2(v0.getDouble(), v1
0888:                            .getDouble()));
0889:                    break;
0890:                case BITAND:
0891:                    result = ValueInt.get(v0.getInt() & v1.getInt());
0892:                    break;
0893:                case BITOR:
0894:                    result = ValueInt.get(v0.getInt() | v1.getInt());
0895:                    break;
0896:                case BITXOR:
0897:                    result = ValueInt.get(v0.getInt() ^ v1.getInt());
0898:                    break;
0899:                case MOD: {
0900:                    int x = v1.getInt();
0901:                    if (x == 0.0) {
0902:                        throw Message.getSQLException(
0903:                                ErrorCode.DIVISION_BY_ZERO_1, getSQL());
0904:                    }
0905:                    result = ValueInt.get(v0.getInt() % x);
0906:                    break;
0907:                }
0908:                case POWER:
0909:                    result = ValueDouble.get(Math.pow(v0.getDouble(), v1
0910:                            .getDouble()));
0911:                    break;
0912:                case ROUND: {
0913:                    double f = Math.pow(10., v1.getDouble());
0914:                    result = ValueDouble
0915:                            .get(Math.round(v0.getDouble() * f) / f);
0916:                    break;
0917:                }
0918:                case TRUNCATE: {
0919:                    double d = v0.getDouble();
0920:                    int p = v1.getInt();
0921:                    double f = Math.pow(10., p);
0922:                    double g = d * f;
0923:                    result = ValueDouble.get(((d < 0) ? Math.ceil(g) : Math
0924:                            .floor(g))
0925:                            / f);
0926:                    break;
0927:                }
0928:                case HASH:
0929:                    result = ValueBytes.getNoCopy(getHash(v0.getString(), v1
0930:                            .getBytesNoCopy(), v2.getInt()));
0931:                    break;
0932:                case ENCRYPT:
0933:                    result = ValueBytes.getNoCopy(encrypt(v0.getString(), v1
0934:                            .getBytesNoCopy(), v2.getBytesNoCopy()));
0935:                    break;
0936:                case DECRYPT:
0937:                    result = ValueBytes.getNoCopy(decrypt(v0.getString(), v1
0938:                            .getBytesNoCopy(), v2.getBytesNoCopy()));
0939:                    break;
0940:                case COMPRESS: {
0941:                    String algorithm = null;
0942:                    if (v1 != null) {
0943:                        algorithm = v1.getString();
0944:                    }
0945:                    result = ValueBytes.getNoCopy(CompressTool.getInstance()
0946:                            .compress(v0.getBytesNoCopy(), algorithm));
0947:                    break;
0948:                }
0949:                case DIFFERENCE:
0950:                    result = ValueInt.get(getDifference(v0.getString(), v1
0951:                            .getString()));
0952:                    break;
0953:                case INSERT: {
0954:                    if (v1 == ValueNull.INSTANCE || v2 == ValueNull.INSTANCE) {
0955:                        result = v1;
0956:                    } else {
0957:                        result = ValueString.get(insert(v0.getString(), v1
0958:                                .getInt(), v2.getInt(), v3.getString()));
0959:                    }
0960:                    break;
0961:                }
0962:                case LEFT:
0963:                    result = ValueString.get(left(v0.getString(), v1.getInt()));
0964:                    break;
0965:                case LOCATE: {
0966:                    int start = v2 == null ? 0 : v2.getInt();
0967:                    result = ValueInt.get(locate(v0.getString(),
0968:                            v1.getString(), start));
0969:                    break;
0970:                }
0971:                case INSTR: {
0972:                    int start = v2 == null ? 0 : v2.getInt();
0973:                    result = ValueInt.get(locate(v1.getString(),
0974:                            v0.getString(), start));
0975:                    break;
0976:                }
0977:                case REPEAT: {
0978:                    int count = Math.max(0, v1.getInt());
0979:                    result = ValueString.get(repeat(v0.getString(), count));
0980:                    break;
0981:                }
0982:                case REPLACE: {
0983:                    String s0 = v0 == ValueNull.INSTANCE ? "" : v0.getString();
0984:                    String s1 = v1 == ValueNull.INSTANCE ? "" : v1.getString();
0985:                    String s2 = (v2 == null || v2 == ValueNull.INSTANCE) ? ""
0986:                            : v2.getString();
0987:                    result = ValueString.get(replace(s0, s1, s2));
0988:                    break;
0989:                }
0990:                case RIGHT:
0991:                    result = ValueString
0992:                            .get(right(v0.getString(), v1.getInt()));
0993:                    break;
0994:                case LTRIM:
0995:                    result = ValueString.get(trim(v0.getString(), true, false,
0996:                            v1 == null ? " " : v1.getString()));
0997:                    break;
0998:                case TRIM:
0999:                    result = ValueString.get(trim(v0.getString(), true, true,
1000:                            v1 == null ? " " : v1.getString()));
1001:                    break;
1002:                case RTRIM:
1003:                    result = ValueString.get(trim(v0.getString(), false, true,
1004:                            v1 == null ? " " : v1.getString()));
1005:                    break;
1006:                case SUBSTR:
1007:                case SUBSTRING: {
1008:                    String s = v0.getString();
1009:                    int length = v2 == null ? s.length() : v2.getInt();
1010:                    result = ValueString.get(substring(s, v1.getInt(), length));
1011:                    break;
1012:                }
1013:                case POSITION:
1014:                    result = ValueInt.get(locate(v0.getString(),
1015:                            v1.getString(), 0));
1016:                    break;
1017:                case XMLATTR:
1018:                    result = ValueString.get(StringUtils.xmlAttr(
1019:                            v0.getString(), v1.getString()));
1020:                    break;
1021:                case XMLNODE: {
1022:                    String attr = v1 == null ? null
1023:                            : v1 == ValueNull.INSTANCE ? null : v1.getString();
1024:                    String content = v2 == null ? null
1025:                            : v2 == ValueNull.INSTANCE ? null : v2.getString();
1026:                    result = ValueString.get(StringUtils.xmlNode(
1027:                            v0.getString(), attr, content));
1028:                    break;
1029:                }
1030:                case REGEXP_REPLACE: {
1031:                    String regexp = v1.getString();
1032:                    try {
1033:                        result = ValueString.get(v0.getString().replaceAll(
1034:                                regexp, v2.getString()));
1035:                    } catch (PatternSyntaxException e) {
1036:                        throw Message.getSQLException(
1037:                                ErrorCode.LIKE_ESCAPE_ERROR_1,
1038:                                new String[] { regexp }, e);
1039:                    }
1040:                    break;
1041:                }
1042:                case RPAD:
1043:                    result = ValueString.get(StringUtils
1044:                            .pad(v0.getString(), v1.getInt(), v2 == null ? null
1045:                                    : v2.getString(), true));
1046:                    break;
1047:                case LPAD:
1048:                    result = ValueString.get(StringUtils.pad(v0.getString(), v1
1049:                            .getInt(), v2 == null ? null : v2.getString(),
1050:                            false));
1051:                    break;
1052:                // date
1053:                case DATEADD:
1054:                    result = ValueTimestamp.getNoCopy(dateadd(v0.getString(),
1055:                            v1.getInt(), v2.getTimestampNoCopy()));
1056:                    break;
1057:                case DATEDIFF:
1058:                    result = ValueLong.get(datediff(v0.getString(), v1
1059:                            .getTimestampNoCopy(), v2.getTimestampNoCopy()));
1060:                    break;
1061:                case EXTRACT: {
1062:                    int field = getDatePart(v0.getString());
1063:                    result = ValueInt
1064:                            .get(getDatePart(v1.getTimestamp(), field));
1065:                    break;
1066:                }
1067:                case FORMATDATETIME: {
1068:                    if (v0 == ValueNull.INSTANCE || v1 == ValueNull.INSTANCE) {
1069:                        result = ValueNull.INSTANCE;
1070:                    } else {
1071:                        String locale = v2 == null ? null
1072:                                : v2 == ValueNull.INSTANCE ? null : v2
1073:                                        .getString();
1074:                        String tz = v3 == null ? null
1075:                                : v3 == ValueNull.INSTANCE ? null : v3
1076:                                        .getString();
1077:                        result = ValueString.get(StringUtils.formatDateTime(v0
1078:                                .getTimestamp(), v1.getString(), locale, tz));
1079:                    }
1080:                    break;
1081:                }
1082:                case PARSEDATETIME: {
1083:                    if (v0 == ValueNull.INSTANCE || v1 == ValueNull.INSTANCE) {
1084:                        result = ValueNull.INSTANCE;
1085:                    } else {
1086:                        String locale = v2 == null ? null
1087:                                : v2 == ValueNull.INSTANCE ? null : v2
1088:                                        .getString();
1089:                        String tz = v3 == null ? null
1090:                                : v3 == ValueNull.INSTANCE ? null : v3
1091:                                        .getString();
1092:                        java.util.Date d = StringUtils.parseDateTime(v0
1093:                                .getString(), v1.getString(), locale, tz);
1094:                        result = ValueTimestamp.getNoCopy(new Timestamp(d
1095:                                .getTime()));
1096:                    }
1097:                    break;
1098:                }
1099:                case NULLIF:
1100:                    result = database.areEqual(v0, v1) ? ValueNull.INSTANCE
1101:                            : v0;
1102:                    break;
1103:                // system
1104:                case NEXTVAL: {
1105:                    Sequence sequence = getSequence(session, v0, v1);
1106:                    SequenceValue value = new SequenceValue(sequence);
1107:                    result = value.getValue(session);
1108:                    break;
1109:                }
1110:                case CURRVAL: {
1111:                    Sequence sequence = getSequence(session, v0, v1);
1112:                    result = ValueLong.get(sequence.getCurrentValue());
1113:                    break;
1114:                }
1115:                case CSVREAD: {
1116:                    String fileName = v0.getString();
1117:                    String columnList = v1 == null ? null : v1.getString();
1118:                    String charset = v2 == null ? null : v2.getString();
1119:                    String fieldSeparatorRead = v3 == null ? null : v3
1120:                            .getString();
1121:                    String fieldDelimiter = v4 == null ? null : v4.getString();
1122:                    String escapeCharacter = v5 == null ? null : v5.getString();
1123:                    Value v6 = getNullOrValue(session, args, 6);
1124:                    String nullString = v6 == null ? null : v6.getString();
1125:                    Csv csv = Csv.getInstance();
1126:                    setCsvDelimiterEscape(csv, fieldSeparatorRead,
1127:                            fieldDelimiter, escapeCharacter);
1128:                    csv.setNullString(nullString);
1129:                    char fieldSeparator = csv.getFieldSeparatorRead();
1130:                    String[] columns = StringUtils.arraySplit(columnList,
1131:                            fieldSeparator, true);
1132:                    ValueResultSet vr = ValueResultSet.get(csv.read(fileName,
1133:                            columns, charset));
1134:                    result = vr;
1135:                    break;
1136:                }
1137:                case LINK_SCHEMA: {
1138:                    session.getUser().checkAdmin();
1139:                    Connection conn = session.createConnection(false);
1140:                    ResultSet rs = LinkSchema.linkSchema(conn, v0.getString(),
1141:                            v1.getString(), v2.getString(), v3.getString(), v4
1142:                                    .getString(), v5.getString());
1143:                    result = ValueResultSet.get(rs);
1144:                    break;
1145:                }
1146:                case CSVWRITE: {
1147:                    session.getUser().checkAdmin();
1148:                    Connection conn = session.createConnection(false);
1149:                    String charset = v2 == null ? null : v2.getString();
1150:                    String fieldSeparatorWrite = v3 == null ? null : v3
1151:                            .getString();
1152:                    String fieldDelimiter = v4 == null ? null : v4.getString();
1153:                    String escapeCharacter = v5 == null ? null : v5.getString();
1154:                    Value v6 = getNullOrValue(session, args, 6);
1155:                    String nullString = v6 == null ? null : v6.getString();
1156:                    Value v7 = getNullOrValue(session, args, 7);
1157:                    String lineSeparator = v7 == null ? null : v7.getString();
1158:                    Csv csv = Csv.getInstance();
1159:                    setCsvDelimiterEscape(csv, fieldSeparatorWrite,
1160:                            fieldDelimiter, escapeCharacter);
1161:                    csv.setNullString(nullString);
1162:                    if (lineSeparator != null) {
1163:                        csv.setLineSeparator(lineSeparator);
1164:                    }
1165:                    int rows = csv.write(conn, v0.getString(), v1.getString(),
1166:                            charset);
1167:                    result = ValueInt.get(rows);
1168:                    break;
1169:                }
1170:                case SET: {
1171:                    Variable var = (Variable) args[0];
1172:                    session.setVariable(var.getName(), v1);
1173:                    result = v1;
1174:                    break;
1175:                }
1176:                case FILE_READ: {
1177:                    session.getUser().checkAdmin();
1178:                    String fileName = v0.getString();
1179:                    boolean blob = args.length == 1;
1180:                    try {
1181:                        InputStream in = new AutoCloseInputStream(FileUtils
1182:                                .openFileInputStream(fileName));
1183:                        if (blob) {
1184:                            result = ValueLob.createBlob(in, -1, database);
1185:                        } else {
1186:                            Reader reader;
1187:                            if (v1 == ValueNull.INSTANCE) {
1188:                                reader = new InputStreamReader(in);
1189:                            } else {
1190:                                reader = new InputStreamReader(in, v1
1191:                                        .getString());
1192:                            }
1193:                            result = ValueLob.createClob(reader, -1, database);
1194:                        }
1195:                    } catch (IOException e) {
1196:                        throw Message.convertIOException(e, fileName);
1197:                    }
1198:                    break;
1199:                }
1200:                default:
1201:                    throw Message.getInternalError("type=" + info.type);
1202:                }
1203:                return result;
1204:            }
1205:
1206:            private Sequence getSequence(Session session, Value v0, Value v1)
1207:                    throws SQLException {
1208:                String schemaName, sequenceName;
1209:                if (v1 == null) {
1210:                    schemaName = session.getCurrentSchemaName();
1211:                    sequenceName = StringUtils.toUpperEnglish(v0.getString());
1212:                } else {
1213:                    schemaName = v0.getString();
1214:                    sequenceName = v1.getString();
1215:                }
1216:                return database.getSchema(schemaName).getSequence(sequenceName);
1217:            }
1218:
1219:            private int length(Value v) throws SQLException {
1220:                switch (v.getType()) {
1221:                case Value.BLOB:
1222:                case Value.CLOB:
1223:                case Value.BYTES:
1224:                case Value.JAVA_OBJECT:
1225:                    return (int) v.getPrecision();
1226:                default:
1227:                    return v.getString().length();
1228:                }
1229:            }
1230:
1231:            private byte[] getPaddedArrayCopy(byte[] data, int blockSize) {
1232:                int size = MathUtils.roundUp(data.length, blockSize);
1233:                byte[] newData = new byte[size];
1234:                System.arraycopy(data, 0, newData, 0, data.length);
1235:                return newData;
1236:            }
1237:
1238:            private byte[] decrypt(String algorithm, byte[] key, byte[] data)
1239:                    throws SQLException {
1240:                BlockCipher cipher = CipherFactory.getBlockCipher(algorithm);
1241:                byte[] newKey = getPaddedArrayCopy(key, cipher.getKeyLength());
1242:                cipher.setKey(newKey);
1243:                byte[] newData = getPaddedArrayCopy(data, BlockCipher.ALIGN);
1244:                cipher.decrypt(newData, 0, newData.length);
1245:                return newData;
1246:            }
1247:
1248:            private byte[] encrypt(String algorithm, byte[] key, byte[] data)
1249:                    throws SQLException {
1250:                BlockCipher cipher = CipherFactory.getBlockCipher(algorithm);
1251:                byte[] newKey = getPaddedArrayCopy(key, cipher.getKeyLength());
1252:                cipher.setKey(newKey);
1253:                byte[] newData = getPaddedArrayCopy(data, BlockCipher.ALIGN);
1254:                cipher.encrypt(newData, 0, newData.length);
1255:                return newData;
1256:            }
1257:
1258:            private byte[] getHash(String algorithm, byte[] bytes,
1259:                    int iterations) throws SQLException {
1260:                SHA256 hash = CipherFactory.getHash(algorithm);
1261:                for (int i = 0; i < iterations; i++) {
1262:                    bytes = hash.getHash(bytes);
1263:                }
1264:                return bytes;
1265:            }
1266:
1267:            private static int getDatePart(Timestamp d, int field) {
1268:                Calendar c = Calendar.getInstance();
1269:                c.setTime(d);
1270:                int value = c.get(field);
1271:                if (field == Calendar.MONTH) {
1272:                    value++;
1273:                }
1274:                return value;
1275:            }
1276:
1277:            //     private static long datediffRound(String part, Date d1, Date d2) 
1278:            //                throws SQLException {
1279:            //        // diff (yy, 31.12.2004, 1.1.2005) = 0
1280:            //        Integer p = (Integer) datePart.get(StringUtils.toUpperEnglish(part));
1281:            //        if (p == null) {
1282:            //            throw Message.getSQLException(ErrorCode.INVALID_VALUE_2, 
1283:            //                new String[] { "part", part }, null);
1284:            //        }
1285:            //        int field = p.intValue();
1286:            //        long t1 = d1.getTime(), t2 = d2.getTime();
1287:            //        switch (field) {
1288:            //        case Calendar.MILLISECOND:
1289:            //            return t2 - t1;
1290:            //        case Calendar.SECOND:
1291:            //            return (t2 - t1) / 1000;
1292:            //        case Calendar.MINUTE:
1293:            //            return (t2 - t1) / 1000 / 60;
1294:            //        case Calendar.HOUR_OF_DAY:
1295:            //            return (t2 - t1) / 1000 / 60 / 60;
1296:            //        case Calendar.DATE:
1297:            //            return (t2 - t1) / 1000 / 60 / 60 / 24;
1298:            //        }
1299:            //        Calendar g1 = Calendar.getInstance();
1300:            //        g1.setTimeInMillis(t1);
1301:            //        int year1 = g1.get(Calendar.YEAR);
1302:            //        Calendar g2 = Calendar.getInstance();
1303:            //        g2.setTimeInMillis(t2);
1304:            //        int year2 = g2.get(Calendar.YEAR);
1305:            //        int result = year2 - year1;
1306:            //        if (field == Calendar.MONTH) {
1307:            //            int month1 = g1.get(Calendar.MONTH);
1308:            //            int month2 = g2.get(Calendar.MONTH);
1309:            //            result = 12 * result + (month2 - month1);
1310:            //            g2.set(Calendar.MONTH, month1);
1311:            //        }
1312:            //        g2.set(Calendar.YEAR, year1);
1313:            //        if (result > 0 && g1.after(g2)) {
1314:            //            result--;
1315:            //        } else if (result < 0 && g1.before(g2)) {
1316:            //            result++;
1317:            //        }
1318:            //        return result;
1319:            //    }
1320:
1321:            private static int getDatePart(String part) throws SQLException {
1322:                Integer p = (Integer) DATE_PART.get(StringUtils
1323:                        .toUpperEnglish(part));
1324:                if (p == null) {
1325:                    throw Message.getSQLException(ErrorCode.INVALID_VALUE_2,
1326:                            new String[] { "date part", part });
1327:                }
1328:                return p.intValue();
1329:            }
1330:
1331:            private static Timestamp dateadd(String part, int count, Timestamp d)
1332:                    throws SQLException {
1333:                int field = getDatePart(part);
1334:                Calendar calendar = Calendar.getInstance();
1335:                int nanos = d.getNanos() % 1000000;
1336:                calendar.setTime(d);
1337:                calendar.add(field, count);
1338:                long t = calendar.getTime().getTime();
1339:                Timestamp ts = new Timestamp(t);
1340:                ts.setNanos(ts.getNanos() + nanos);
1341:                return ts;
1342:            }
1343:
1344:            private static long datediff(String part, Timestamp d1, Timestamp d2)
1345:                    throws SQLException {
1346:                // diff (yy, 31.12.2004, 1.1.2005) = 1
1347:                int field = getDatePart(part);
1348:                Calendar calendar = Calendar.getInstance();
1349:                long t1 = d1.getTime(), t2 = d2.getTime();
1350:                // need to convert to UTC, otherwise we get inconsistent results with
1351:                // certain timezones (those that are 30 minutes off)
1352:                TimeZone zone = calendar.getTimeZone();
1353:                calendar.setTime(d1);
1354:                t1 += zone.getOffset(calendar.get(Calendar.ERA), calendar
1355:                        .get(Calendar.YEAR), calendar.get(Calendar.MONTH),
1356:                        calendar.get(Calendar.DAY_OF_MONTH), calendar
1357:                                .get(Calendar.DAY_OF_WEEK), calendar
1358:                                .get(Calendar.MILLISECOND));
1359:                calendar.setTime(d2);
1360:                t2 += zone.getOffset(calendar.get(Calendar.ERA), calendar
1361:                        .get(Calendar.YEAR), calendar.get(Calendar.MONTH),
1362:                        calendar.get(Calendar.DAY_OF_MONTH), calendar
1363:                                .get(Calendar.DAY_OF_WEEK), calendar
1364:                                .get(Calendar.MILLISECOND));
1365:                switch (field) {
1366:                case Calendar.MILLISECOND:
1367:                    return t2 - t1;
1368:                case Calendar.SECOND:
1369:                case Calendar.MINUTE:
1370:                case Calendar.HOUR_OF_DAY: {
1371:                    // first 'normalize' the numbers so both are not negative
1372:                    long hour = 60 * 60 * 1000;
1373:                    long add = Math.min(t1 / hour * hour, t2 / hour * hour);
1374:                    t1 -= add;
1375:                    t2 -= add;
1376:                    switch (field) {
1377:                    case Calendar.SECOND:
1378:                        return t2 / 1000 - t1 / 1000;
1379:                    case Calendar.MINUTE:
1380:                        return t2 / (60 * 1000) - t1 / (60 * 1000);
1381:                    case Calendar.HOUR_OF_DAY:
1382:                        return t2 / hour - t1 / hour;
1383:                    default:
1384:                        throw Message.getInternalError("field:" + field);
1385:                    }
1386:                }
1387:                case Calendar.DATE:
1388:                    return t2 / (24 * 60 * 60 * 1000) - t1
1389:                            / (24 * 60 * 60 * 1000);
1390:                default:
1391:                    break;
1392:                }
1393:                calendar.setTime(new Timestamp(t1));
1394:                int year1 = calendar.get(Calendar.YEAR);
1395:                int month1 = calendar.get(Calendar.MONTH);
1396:                calendar.setTime(new Timestamp(t2));
1397:                int year2 = calendar.get(Calendar.YEAR);
1398:                int month2 = calendar.get(Calendar.MONTH);
1399:                int result = year2 - year1;
1400:                if (field == Calendar.MONTH) {
1401:                    result = 12 * result + (month2 - month1);
1402:                }
1403:                return result;
1404:            }
1405:
1406:            private static String substring(String s, int start, int length) {
1407:                int len = s.length();
1408:                start--;
1409:                if (start < 0) {
1410:                    start = 0;
1411:                }
1412:                if (length < 0) {
1413:                    length = 0;
1414:                }
1415:                start = (start > len) ? len : start;
1416:                if (start + length > len) {
1417:                    length = len - start;
1418:                }
1419:                return s.substring(start, start + length);
1420:            }
1421:
1422:            private static String trim(String s, boolean leading,
1423:                    boolean trailing, String sp) {
1424:                char space = (sp == null || sp.length() < 1) ? ' ' : sp
1425:                        .charAt(0);
1426:                // TODO function trim: HSQLDB says 'tabs are not removed', but they are.
1427:                // check what other databases do
1428:                if (leading) {
1429:                    int len = s.length(), i = 0;
1430:                    while (i < len && s.charAt(i) == space) {
1431:                        i++;
1432:                    }
1433:                    s = (i == 0) ? s : s.substring(i);
1434:                }
1435:                if (trailing) {
1436:                    int endIndex = s.length() - 1;
1437:                    int i = endIndex;
1438:                    while (i >= 0 && s.charAt(i) == space) {
1439:                        i--;
1440:                    }
1441:                    s = i == endIndex ? s : s.substring(0, i + 1);
1442:                }
1443:                return s;
1444:            }
1445:
1446:            private static String replace(String s, String replace, String with) {
1447:                if (replace == null || replace.length() == 0) {
1448:                    // avoid out of memory
1449:                    return s;
1450:                }
1451:                StringBuffer buff = new StringBuffer(s.length());
1452:                int start = 0;
1453:                int len = replace.length();
1454:                while (true) {
1455:                    int i = s.indexOf(replace, start);
1456:                    if (i == -1) {
1457:                        break;
1458:                    }
1459:                    buff.append(s.substring(start, i));
1460:                    buff.append(with);
1461:                    start = i + len;
1462:                }
1463:                buff.append(s.substring(start));
1464:                return buff.toString();
1465:            }
1466:
1467:            private static String repeat(String s, int count) {
1468:                StringBuffer buff = new StringBuffer(s.length() * count);
1469:                while (count-- > 0) {
1470:                    buff.append(s);
1471:                }
1472:                return buff.toString();
1473:            }
1474:
1475:            private static String rawToHex(String s) {
1476:                StringBuffer buff = new StringBuffer(4 * s.length());
1477:                for (int i = 0; i < s.length(); i++) {
1478:                    String hex = Integer.toHexString(s.charAt(i) & 0xffff);
1479:                    for (int j = hex.length(); j < 4; j++) {
1480:                        buff.append('0');
1481:                    }
1482:                    buff.append(hex);
1483:                }
1484:                return buff.toString();
1485:            }
1486:
1487:            private static int locate(String search, String s, int start) {
1488:                if (start < 0) {
1489:                    int i = s.length() + start;
1490:                    return s.lastIndexOf(search, i) + 1;
1491:                } else {
1492:                    int i = (start == 0) ? 0 : start - 1;
1493:                    return s.indexOf(search, i) + 1;
1494:                }
1495:            }
1496:
1497:            private static String right(String s, int count) {
1498:                if (count < 0) {
1499:                    count = 0;
1500:                } else if (count > s.length()) {
1501:                    count = s.length();
1502:                }
1503:                return s.substring(s.length() - count);
1504:            }
1505:
1506:            private static String left(String s, int count) {
1507:                if (count < 0) {
1508:                    count = 0;
1509:                } else if (count > s.length()) {
1510:                    count = s.length();
1511:                }
1512:                return s.substring(0, count);
1513:            }
1514:
1515:            private static String insert(String s1, int start, int length,
1516:                    String s2) {
1517:                if (s1 == null) {
1518:                    return s2;
1519:                }
1520:                if (s2 == null) {
1521:                    return s1;
1522:                }
1523:                int len1 = s1.length();
1524:                int len2 = s2.length();
1525:                start--;
1526:                if (start < 0 || length <= 0 || len2 == 0 || start > len1) {
1527:                    return s1;
1528:                }
1529:                if (start + length > len1) {
1530:                    length = len1 - start;
1531:                }
1532:                return s1.substring(0, start) + s2
1533:                        + s1.substring(start + length);
1534:            }
1535:
1536:            private static String hexToRaw(String s) throws SQLException {
1537:                // TODO function hextoraw compatibility with oracle
1538:                int len = s.length();
1539:                if (len % 4 != 0) {
1540:                    throw Message.getSQLException(
1541:                            ErrorCode.DATA_CONVERSION_ERROR_1, s);
1542:                }
1543:                StringBuffer buff = new StringBuffer(len / 4);
1544:                for (int i = 0; i < len; i += 4) {
1545:                    try {
1546:                        char raw = (char) Integer.parseInt(s
1547:                                .substring(i, i + 4), 16);
1548:                        buff.append(raw);
1549:                    } catch (NumberFormatException e) {
1550:                        throw Message.getSQLException(
1551:                                ErrorCode.DATA_CONVERSION_ERROR_1, s);
1552:                    }
1553:                }
1554:                return buff.toString();
1555:            }
1556:
1557:            private static int getDifference(String s1, String s2) {
1558:                // TODO function difference: compatibility with SQL Server and HSQLDB
1559:                s1 = getSoundex(s1);
1560:                s2 = getSoundex(s2);
1561:                int e = 0;
1562:                for (int i = 0; i < 4; i++) {
1563:                    if (s1.charAt(i) == s2.charAt(i)) {
1564:                        e++;
1565:                    }
1566:                }
1567:                return e;
1568:            }
1569:
1570:            private double roundmagic(double d) {
1571:                if ((d < 0.0000000000001) && (d > -0.0000000000001)) {
1572:                    return 0.0;
1573:                }
1574:                if ((d > 1000000000000.) || (d < -1000000000000.)) {
1575:                    return d;
1576:                }
1577:                StringBuffer s = new StringBuffer();
1578:                s.append(d);
1579:                if (s.toString().indexOf("E") >= 0) {
1580:                    return d;
1581:                }
1582:                int len = s.length();
1583:                if (len < 16) {
1584:                    return d;
1585:                }
1586:                if (s.toString().indexOf(".") > len - 3) {
1587:                    return d;
1588:                }
1589:                s.delete(len - 2, len);
1590:                len -= 2;
1591:                char c1 = s.charAt(len - 2);
1592:                char c2 = s.charAt(len - 3);
1593:                char c3 = s.charAt(len - 4);
1594:                if ((c1 == '0') && (c2 == '0') && (c3 == '0')) {
1595:                    s.setCharAt(len - 1, '0');
1596:                } else if ((c1 == '9') && (c2 == '9') && (c3 == '9')) {
1597:                    s.setCharAt(len - 1, '9');
1598:                    s.append('9');
1599:                    s.append('9');
1600:                    s.append('9');
1601:                }
1602:                return Double.valueOf(s.toString()).doubleValue();
1603:            }
1604:
1605:            private static String getSoundex(String s) {
1606:                int len = s.length();
1607:                char[] chars = new char[] { '0', '0', '0', '0' };
1608:                char lastDigit = '0';
1609:                for (int i = 0, j = 0; i < len && j < 4; i++) {
1610:                    char c = s.charAt(i);
1611:                    char newDigit = c > SOUNDEX_INDEX.length ? 0
1612:                            : SOUNDEX_INDEX[c];
1613:                    if (newDigit != 0) {
1614:                        if (j == 0) {
1615:                            chars[j++] = c;
1616:                            lastDigit = newDigit;
1617:                        } else if (newDigit <= '6') {
1618:                            if (newDigit != lastDigit) {
1619:                                chars[j++] = newDigit;
1620:                                lastDigit = newDigit;
1621:                            }
1622:                        } else if (newDigit == '7') {
1623:                            lastDigit = newDigit;
1624:                        }
1625:                    }
1626:                }
1627:                return new String(chars);
1628:            }
1629:
1630:            public int getType() {
1631:                return dataType;
1632:            }
1633:
1634:            public void mapColumns(ColumnResolver resolver, int level)
1635:                    throws SQLException {
1636:                for (int i = 0; i < args.length; i++) {
1637:                    args[i].mapColumns(resolver, level);
1638:                }
1639:            }
1640:
1641:            protected void checkParameterCount(int len) throws SQLException {
1642:                int min = 0, max = Integer.MAX_VALUE;
1643:                switch (info.type) {
1644:                case COALESCE:
1645:                case CSVREAD:
1646:                case LEAST:
1647:                case GREATEST:
1648:                    min = 1;
1649:                    break;
1650:                case NOW:
1651:                case CURRENT_TIMESTAMP:
1652:                case RAND:
1653:                    max = 1;
1654:                    break;
1655:                case COMPRESS:
1656:                case LTRIM:
1657:                case RTRIM:
1658:                case TRIM:
1659:                case FILE_READ:
1660:                    min = 1;
1661:                    max = 2;
1662:                    break;
1663:                case REPLACE:
1664:                case LOCATE:
1665:                case INSTR:
1666:                case SUBSTR:
1667:                case SUBSTRING:
1668:                case LPAD:
1669:                case RPAD:
1670:                    min = 2;
1671:                    max = 3;
1672:                    break;
1673:                case CASE:
1674:                case CONCAT:
1675:                case CSVWRITE:
1676:                    min = 2;
1677:                    break;
1678:                case XMLNODE:
1679:                    min = 1;
1680:                    max = 3;
1681:                    break;
1682:                case FORMATDATETIME:
1683:                case PARSEDATETIME:
1684:                    min = 2;
1685:                    max = 4;
1686:                    break;
1687:                case CURRVAL:
1688:                case NEXTVAL:
1689:                    min = 1;
1690:                    max = 2;
1691:                    break;
1692:                default:
1693:                    throw Message.getInternalError("type=" + info.type);
1694:                }
1695:                boolean ok = (len >= min) && (len <= max);
1696:                if (!ok) {
1697:                    throw Message.getSQLException(
1698:                            ErrorCode.INVALID_PARAMETER_COUNT_2, new String[] {
1699:                                    info.name, min + ".." + max });
1700:                }
1701:            }
1702:
1703:            public void doneWithParameters() throws SQLException {
1704:                if (info.parameterCount == VAR_ARGS) {
1705:                    int len = varArgs.size();
1706:                    checkParameterCount(len);
1707:                    args = new Expression[len];
1708:                    varArgs.toArray(args);
1709:                    varArgs = null;
1710:                } else {
1711:                    int len = args.length;
1712:                    if (len > 0 && args[len - 1] == null) {
1713:                        throw Message.getSQLException(
1714:                                ErrorCode.INVALID_PARAMETER_COUNT_2,
1715:                                new String[] { info.name, "" + len });
1716:                    }
1717:                }
1718:            }
1719:
1720:            /**
1721:             * Set the result data type of this function.
1722:             * 
1723:             * @param dataType the data type
1724:             * @param precision the precision
1725:             * @param scale the scale
1726:             * @param displaySize the display size
1727:             */
1728:            public void setDataType(int dataType, long precision, int scale,
1729:                    int displaySize) {
1730:                this .dataType = dataType;
1731:                this .precision = precision;
1732:                this .displaySize = displaySize;
1733:                this .scale = scale;
1734:            }
1735:
1736:            public void setDataType(Column col) {
1737:                dataType = col.getType();
1738:                precision = col.getPrecision();
1739:                displaySize = col.getDisplaySize();
1740:                scale = col.getScale();
1741:            }
1742:
1743:            public Expression optimize(Session session) throws SQLException {
1744:                boolean allConst = info.isDeterministic;
1745:                for (int i = 0; i < args.length; i++) {
1746:                    Expression e = args[i].optimize(session);
1747:                    args[i] = e;
1748:                    if (!e.isConstant()) {
1749:                        allConst = false;
1750:                    }
1751:                }
1752:                Expression p0 = args.length < 1 ? null : args[0];
1753:                switch (info.type) {
1754:                case IFNULL:
1755:                case NULLIF:
1756:                case COALESCE:
1757:                case LEAST:
1758:                case GREATEST: {
1759:                    dataType = Value.UNKNOWN;
1760:                    scale = 0;
1761:                    precision = 0;
1762:                    displaySize = 0;
1763:                    for (int i = 0; i < args.length; i++) {
1764:                        Expression e = args[i];
1765:                        if (e != ValueExpression.NULL
1766:                                && e.getType() != Value.UNKNOWN) {
1767:                            dataType = Value.getHigherOrder(dataType, e
1768:                                    .getType());
1769:                            scale = Math.max(scale, e.getScale());
1770:                            precision = Math.max(precision, e.getPrecision());
1771:                            displaySize = Math.max(displaySize, e
1772:                                    .getDisplaySize());
1773:                        }
1774:                    }
1775:                    if (dataType == Value.UNKNOWN) {
1776:                        dataType = Value.STRING;
1777:                        scale = 0;
1778:                        precision = Integer.MAX_VALUE;
1779:                        displaySize = Integer.MAX_VALUE;
1780:                    }
1781:                    break;
1782:                }
1783:                case CASEWHEN:
1784:                    dataType = Value.getHigherOrder(args[1].getType(), args[2]
1785:                            .getType());
1786:                    precision = Math.max(args[1].getPrecision(), args[2]
1787:                            .getPrecision());
1788:                    displaySize = Math.max(args[1].getDisplaySize(), args[2]
1789:                            .getDisplaySize());
1790:                    scale = Math.max(args[1].getScale(), args[2].getScale());
1791:                    break;
1792:                case CAST:
1793:                case CONVERT:
1794:                    // data type, precision and scale is already set
1795:                    break;
1796:                case ABS:
1797:                case FLOOR:
1798:                case RADIANS:
1799:                case ROUND:
1800:                case TRUNCATE:
1801:                case POWER:
1802:                case ARRAY_GET:
1803:                    dataType = p0.getType();
1804:                    scale = p0.getScale();
1805:                    precision = p0.getPrecision();
1806:                    displaySize = p0.getDisplaySize();
1807:                    if (dataType == Value.NULL) {
1808:                        dataType = Value.INT;
1809:                        precision = ValueInt.PRECISION;
1810:                        displaySize = ValueInt.DISPLAY_SIZE;
1811:                        scale = 0;
1812:                    }
1813:                    break;
1814:                case SET: {
1815:                    Expression p1 = args[1];
1816:                    dataType = p1.getType();
1817:                    precision = p1.getPrecision();
1818:                    scale = p1.getScale();
1819:                    displaySize = p1.getDisplaySize();
1820:                    if (!(p0 instanceof  Variable)) {
1821:                        throw Message.getSQLException(
1822:                                ErrorCode.CAN_ONLY_ASSIGN_TO_VARIABLE_1, p0
1823:                                        .getSQL());
1824:                    }
1825:                    break;
1826:                }
1827:                case FILE_READ: {
1828:                    if (args.length == 1) {
1829:                        dataType = Value.BLOB;
1830:                    } else {
1831:                        dataType = Value.CLOB;
1832:                    }
1833:                    precision = Integer.MAX_VALUE;
1834:                    scale = 0;
1835:                    displaySize = Integer.MAX_VALUE;
1836:                    break;
1837:                }
1838:                default:
1839:                    dataType = info.dataType;
1840:                    precision = 0;
1841:                    displaySize = 0;
1842:                    scale = 0;
1843:                }
1844:                if (allConst) {
1845:                    return ValueExpression.get(getValue(session));
1846:                }
1847:                return this ;
1848:            }
1849:
1850:            public void setEvaluatable(TableFilter tableFilter, boolean b) {
1851:                for (int i = 0; i < args.length; i++) {
1852:                    Expression e = args[i];
1853:                    if (e != null) {
1854:                        e.setEvaluatable(tableFilter, b);
1855:                    }
1856:                }
1857:            }
1858:
1859:            public int getScale() {
1860:                return scale;
1861:            }
1862:
1863:            public long getPrecision() {
1864:                if (precision == 0) {
1865:                    calculatePrecisionAndDisplaySize();
1866:                }
1867:                return precision;
1868:            }
1869:
1870:            public int getDisplaySize() {
1871:                if (precision == 0) {
1872:                    calculatePrecisionAndDisplaySize();
1873:                }
1874:                return displaySize;
1875:            }
1876:
1877:            private void calculatePrecisionAndDisplaySize() {
1878:                switch (info.type) {
1879:                case ENCRYPT:
1880:                case DECRYPT:
1881:                    precision = args[2].getPrecision();
1882:                    displaySize = args[2].getDisplaySize();
1883:                    break;
1884:                case COMPRESS:
1885:                    precision = args[0].getPrecision();
1886:                    displaySize = args[0].getDisplaySize();
1887:                    break;
1888:                case CHAR:
1889:                    precision = 1;
1890:                    displaySize = 1;
1891:                    break;
1892:                case CONCAT:
1893:                    precision = 0;
1894:                    displaySize = 0;
1895:                    for (int i = 0; i < args.length; i++) {
1896:                        precision += args[i].getPrecision();
1897:                        displaySize = MathUtils
1898:                                .convertLongToInt((long) displaySize
1899:                                        + args[i].getDisplaySize());
1900:                        if (precision < 0) {
1901:                            precision = Long.MAX_VALUE;
1902:                        }
1903:                    }
1904:                    break;
1905:                case HEXTORAW:
1906:                    precision = (args[0].getPrecision() + 3) / 4;
1907:                    displaySize = MathUtils.convertLongToInt(precision);
1908:                    break;
1909:                case LCASE:
1910:                case LTRIM:
1911:                case RIGHT:
1912:                case RTRIM:
1913:                case UCASE:
1914:                case LOWER:
1915:                case UPPER:
1916:                case TRIM:
1917:                case STRINGDECODE:
1918:                case UTF8TOSTRING:
1919:                    precision = args[0].getPrecision();
1920:                    displaySize = args[0].getDisplaySize();
1921:                    break;
1922:                case RAWTOHEX:
1923:                    precision = args[0].getPrecision() * 4;
1924:                    displaySize = MathUtils.convertLongToInt(precision);
1925:                    break;
1926:                case SOUNDEX:
1927:                    precision = 4;
1928:                    displaySize = (int) precision;
1929:                    break;
1930:                case DAYNAME:
1931:                case MONTHNAME:
1932:                    precision = 20; // day and month names may be long in some languages
1933:                    displaySize = (int) precision;
1934:                    break;
1935:                }
1936:            }
1937:
1938:            public String getSQL() {
1939:                StringBuffer buff = new StringBuffer();
1940:                buff.append(info.name);
1941:                buff.append('(');
1942:                switch (info.type) {
1943:                case CAST: {
1944:                    buff.append(args[0].getSQL());
1945:                    buff.append(" AS ");
1946:                    buff.append(new Column(null, dataType, precision, scale,
1947:                            displaySize).getCreateSQL());
1948:                    break;
1949:                }
1950:                case CONVERT: {
1951:                    buff.append(args[0].getSQL());
1952:                    buff.append(",");
1953:                    buff.append(new Column(null, dataType, precision, scale,
1954:                            displaySize).getCreateSQL());
1955:                    break;
1956:                }
1957:                case EXTRACT: {
1958:                    ValueString v = (ValueString) ((ValueExpression) args[0])
1959:                            .getValue(null);
1960:                    buff.append(v.getString());
1961:                    buff.append(" FROM ");
1962:                    buff.append(args[1].getSQL());
1963:                    break;
1964:                }
1965:                default: {
1966:                    for (int i = 0; i < args.length; i++) {
1967:                        if (i > 0) {
1968:                            buff.append(", ");
1969:                        }
1970:                        Expression e = args[i];
1971:                        buff.append(e.getSQL());
1972:                    }
1973:                }
1974:                }
1975:                buff.append(')');
1976:                return buff.toString();
1977:            }
1978:
1979:            public void updateAggregate(Session session) throws SQLException {
1980:                for (int i = 0; i < args.length; i++) {
1981:                    Expression e = args[i];
1982:                    if (e != null) {
1983:                        e.updateAggregate(session);
1984:                    }
1985:                }
1986:            }
1987:
1988:            public int getFunctionType() {
1989:                return info.type;
1990:            }
1991:
1992:            public String getName() {
1993:                return info.name;
1994:            }
1995:
1996:            public int getParameterCount() {
1997:                return args.length;
1998:            }
1999:
2000:            public ValueResultSet getValueForColumnList(Session session,
2001:                    Expression[] args) throws SQLException {
2002:                switch (info.type) {
2003:                case CSVREAD: {
2004:                    String fileName = args[0].getValue(session).getString();
2005:                    if (fileName == null) {
2006:                        throw Message.getSQLException(
2007:                                ErrorCode.PARAMETER_NOT_SET_1, "fileName");
2008:                    }
2009:                    String columnList = args.length < 2 ? null : args[1]
2010:                            .getValue(session).getString();
2011:                    String charset = args.length < 3 ? null : args[2].getValue(
2012:                            session).getString();
2013:                    String fieldSeparatorRead = args.length < 4 ? null
2014:                            : args[3].getValue(session).getString();
2015:                    String fieldDelimiter = args.length < 5 ? null : args[4]
2016:                            .getValue(session).getString();
2017:                    String escapeCharacter = args.length < 6 ? null : args[5]
2018:                            .getValue(session).getString();
2019:                    Csv csv = Csv.getInstance();
2020:                    setCsvDelimiterEscape(csv, fieldSeparatorRead,
2021:                            fieldDelimiter, escapeCharacter);
2022:                    char fieldSeparator = csv.getFieldSeparatorRead();
2023:                    String[] columns = StringUtils.arraySplit(columnList,
2024:                            fieldSeparator, true);
2025:                    ResultSet rs = csv.read(fileName, columns, charset);
2026:                    ValueResultSet vr = ValueResultSet.getCopy(rs, 0);
2027:                    return vr;
2028:                }
2029:                default:
2030:                    break;
2031:                }
2032:                return (ValueResultSet) getValueWithArgs(session, args);
2033:            }
2034:
2035:            private void setCsvDelimiterEscape(Csv csv, String fieldSeparator,
2036:                    String fieldDelimiter, String escapeCharacter) {
2037:                if (fieldSeparator != null) {
2038:                    csv.setFieldSeparatorWrite(fieldSeparator);
2039:                    if (fieldSeparator.length() > 0) {
2040:                        char fs = fieldSeparator.charAt(0);
2041:                        csv.setFieldSeparatorRead(fs);
2042:                    }
2043:                }
2044:                if (fieldDelimiter != null) {
2045:                    char fd = fieldDelimiter.length() == 0 ? 0 : fieldDelimiter
2046:                            .charAt(0);
2047:                    csv.setFieldDelimiter(fd);
2048:                }
2049:                if (escapeCharacter != null) {
2050:                    char ec = escapeCharacter.length() == 0 ? 0
2051:                            : escapeCharacter.charAt(0);
2052:                    csv.setEscapeCharacter(ec);
2053:                }
2054:            }
2055:
2056:            public Expression[] getArgs() {
2057:                return args;
2058:            }
2059:
2060:            public boolean isEverything(ExpressionVisitor visitor) {
2061:                if (visitor.type == ExpressionVisitor.DETERMINISTIC
2062:                        && !info.isDeterministic) {
2063:                    return false;
2064:                }
2065:                for (int i = 0; i < args.length; i++) {
2066:                    Expression e = args[i];
2067:                    if (e != null && !e.isEverything(visitor)) {
2068:                        return false;
2069:                    }
2070:                }
2071:                return true;
2072:            }
2073:
2074:            public int getCost() {
2075:                int cost = 3;
2076:                for (int i = 0; i < args.length; i++) {
2077:                    cost += args[i].getCost();
2078:                }
2079:                return cost;
2080:            }
2081:
2082:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.