package my.test.expression;
import java.sql.CallableStatement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import my.test.TestBase;
import org.h2.expression.Function;
public class FunctionTest extends TestBase {
public static void main(String[] args) throws Exception {
new FunctionTest().start();
}
@Override
public void init() throws Exception {
prop.setProperty("MODE", "PostgreSQL"); //只有PostgreSQL才把LOG和LN看成一样,其他数据库把把LOG和LOG10
}
void soundex_index() {
// SOUNDEX_INDEX
// 34个字符(26个大写字母加1到8这8个数字)
// 7: AEIOUY 及它们的小写(下同)
// 8: HW
// 1: BFPV
// 2: CGJKQSXZ
// 3: DT
// 4: L
// 5: MN
// 6: R
char[] SOUNDEX_INDEX = new char[128];
// SOUNDEX_INDEX
String index = "7AEIOUY8HW1BFPV2CGJKQSXZ3DT4L5MN6R";
char number = 0;
for (int i = 0, length = index.length(); i < length; i++) {
char c = index.charAt(i);
if (c < '9') {
number = c;
} else {
SOUNDEX_INDEX[c] = number;
SOUNDEX_INDEX[Character.toLowerCase(c)] = number;
}
}
}
void printFunctionInfos() {
HashMap<Integer, List<Object>> FUNCTIONS = new java.util.LinkedHashMap<Integer, List<Object>>();
for (Object fi : Function.getFunctionInfos()) {
List<Object> list = FUNCTIONS.get(fi.hashCode());
if (list == null)
list = new ArrayList<Object>();
list.add(fi);
FUNCTIONS.put(fi.hashCode(), list);
//System.out.println(fi);
}
for (List<Object> fi : FUNCTIONS.values()) {
Object last = null;
for (Object o : fi) {
System.out.print(o);
if (last != null) {
if (!last.equals(o))
System.out.print(" 与前面不同 ");
else
System.out.print(" 与前面相同 ");
//System.out.println(last);
//System.out.println(o);
//System.out.println();
}
last = o;
}
System.out.println();
//System.out.println(fi);
}
}
//测试org.h2.expression.Function
@Override
public void startInternal() throws Exception {
stmt.executeUpdate("CREATE SCHEMA IF NOT EXISTS myschema AUTHORIZATION sa");
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS FunctionTest(id int primary key, name varchar(500))");
stmt.executeUpdate("CREATE ALIAS IF NOT EXISTS myschema.MY_SQRT FOR \"java.lang.Math.sqrt\"");
//callableStatement();
sql = "SELECT * FROM TABLE(ID INT=(1, 2), NAME VARCHAR=('Hello', 'World'))";
sql = "SELECT * FROM SYSTEM_RANGE(1, 9)";
sql = "SELECT ROWNUM(), * FROM SYSTEM_RANGE(1, 9)";
sql = "SELECT ABS(-1) FROM FunctionTest";
sql = "SELECT ABS(-1)";
numericFunctions();
stringFunctions();
timeAndDateFunctions();
//systemFunctions();
executeQuery();
}
void numericFunctions() throws Exception {
sql = "SELECT ROUND(12.234, 2)"; //12.23, 4舍5入,小数保留两位
sql = "SELECT ROUND(12.235, 2)"; //12.24
sql = "SELECT ROUND(12.236, 2)"; //12.24
sql = "SELECT TRUNCATE(12.236, 2)"; //12.23
sql = "SELECT TRUNCATE(0.236, 2)"; //12.23
//sql = "SELECT TRUNCATE(-0.236, 2)"; //-0.23
sql = "SELECT ABS(null)";
sql = "SELECT CEILING(1.22)"; //2.0
sql = "SELECT CEILING(0.22)"; //1.0 //天花板
sql = "SELECT FLOOR(1.22)"; //1.0
sql = "SELECT FLOOR(0.22)"; //0.0 //地板
sql = "SELECT LN(100)"; //4.605170185988092, 即e的4.605170185988092次幂是100
//当org.h2.engine.Mode.logIsLogBase10是true时与LOG与LN一样,是false与LOG10一样,默认是false
sql = "SELECT LOG(100)"; //4.605170185988092, 即e的4.605170185988092次幂是100
sql = "SELECT LOG10(100)"; //2.0, 即10的2次幂是100
sql = "SELECT RAND()";
sql = "SELECT RAND(10), RAND(10), RAND(10)";
sql = "SELECT ROUNDMAGIC(0.199933)";
sql = "SELECT ROUNDMAGIC(0.1999333455444444444444444444444)";
sql = "SELECT EXPAND(x'1234')"; //解压,只能接COMPRESS函数
sql = "SELECT UTF8TOSTRING(EXPAND(COMPRESS(STRINGTOUTF8('Test'))))";
sql = "SELECT RANDOM_UUID()";
}
void stringFunctions() throws Exception {
sql = "SELECT ASCII('Hi')";
sql = "SELECT CONCAT_WS(', ', 1,2,3), CONCAT(1,2,3)";
sql = "SELECT HEXTORAW('abc')";
sql = "SELECT HEXTORAW('abcd1234')";
sql = "SELECT HEXTORAW(RAWTOHEX('abc'))='abc'";
// 34个字符(26个大写字母加1到8这8个数字)
// 7: AEIOUY 及它们的小写(下同)
// 8: HW
// 1: BFPV
// 2: CGJKQSXZ
// 3: DT
// 4: L
// 5: MN
// 6: R
//算法是: 忽略所有的非字符,然后保留第一个字符,忽略对应7和8的字符,其他的转成对应的数字,重复的不算,不够4位的补0
sql = "SELECT SOUNDEX('1aaa')"; //1被去掉,保留第一个a,第二和第三个a对应7被忽略,所以最后是a000
//B保留,H去掉,C转成2,W去掉,D转成3,H去掉,A去掉,最后是B23因为是3位,所以不够4位,最后是B230
sql = "SELECT SOUNDEX('BHCWDHA')";
sql = "SELECT 'ab'||SPACE(10)||'cd'";
sql = "SELECT XMLCOMMENT('aaa--bbb--ccc')";
}
void timeAndDateFunctions() throws Exception {
//以下有21个时间与日期函数,
//在这个方法中org.h2.expression.Function.getSimpleValue(Session, Value, Expression[], Value[])
//----------------------------------------------------------------------------------------
sql = "SELECT DAYNAME(DATE '2000-01-01')";
sql = "SELECT DAY_OF_MONTH(CURRENT_DATE),DAY_OF_WEEK(CURRENT_DATE),DAY_OF_YEAR(CURRENT_DATE)";
sql = "SELECT HOUR(CURRENT_TIMESTAMP),MINUTE(CURRENT_TIMESTAMP)";
sql = "SELECT MONTH(CURRENT_DATE)"; //加括号也可以SELECT MONTH(CURRENT_DATE())
sql = "SELECT MONTHNAME(CURRENT_DATE)"; //不是MONTH_NAME,没有下划线
sql = "SELECT QUARTER(CURRENT_DATE)"; //第几个季度,用1、2、3、4表示
sql = "SELECT SECOND(CURRENT_TIMESTAMP)";
sql = "SELECT WEEK(CURRENT_DATE),YEAR(CURRENT_DATE)";
//ISO_DAY_OF_WEEK这个就正常了,周1用数字1表示,跟DAY_OF_WEEK不一样
sql = "SELECT ISO_YEAR(CURRENT_DATE),ISO_WEEK(CURRENT_DATE),ISO_DAY_OF_WEEK(CURRENT_DATE)";
//NOW(1)表示毫秒数只保留一位,如NOW()="2012-12-03 22:03:44.647" 则NOW(1)="2012-12-03 22:03:44.6"
//毫秒数一般是3位,如果NOW(100),100>3了,所以NOW(100)跟NOW()一样
sql = "SELECT CURDATE(),CURRENT_DATE(),CURTIME(),CURRENT_TIME(),NOW(),CURRENT_TIMESTAMP(),NOW(1),NOW(100)";
//CURDATE=CURRENT_DATE, CURTIME=CURRENT_TIME, NOW=CURRENT_TIMESTAMP
//这个不加括号可以
sql = "SELECT CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP";
//这个就不行
//sql = "SELECT CURDATE, CURTIME, NOW";
//
//
//
//以下有5个时间与日期函数,
//在这个方法中org.h2.expression.Function.getValueWithArgs(Session, Expression[])
//----------------------------------------------------------------------------------------
//月份加1,结果是2001-02-28 00:00:00.0
sql = "SELECT DATEADD('MONTH', 1, DATE '2001-01-31')";
//用后面的YEAR减去前面的YEAR,1999-2001=-2
sql = "SELECT DATEDIFF('YEAR', DATE '2001-01-31', DATE '1999-01-31')";
//抽取日期和年份 CURRENT_TIMESTAMP=2012-12-03 22:20:08.597 DAY=3 YEAR=2012
sql = "SELECT CURRENT_TIMESTAMP, EXTRACT(DAY FROM CURRENT_TIMESTAMP), EXTRACT(YEAR FROM CURRENT_TIMESTAMP)";
//format datetime 格式化日期时间
//timestamp = TIMESTAMP '2001-02-03 04:05:06' ,
//formatString = 'EEE, d MMM yyyy HH:mm:ss z'
//localeString = 'en'
//timeZoneString = 'GMT'
//结果 Fri, 2 Feb 2001 20:05:06 GMT
sql = "SELECT FORMATDATETIME(TIMESTAMP '2001-02-03 04:05:06', 'EEE, d MMM yyyy HH:mm:ss z', 'en', 'GMT')";
//只要timestamp和formatString其中之一为null,结果为null
sql = "SELECT FORMATDATETIME(null, 'EEE, d MMM yyyy HH:mm:ss z')"; //null
sql = "SELECT FORMATDATETIME(TIMESTAMP '2001-02-03 04:05:06', null)"; //null
//parse datetime解析日期时间
//按后面三个参数指定的格式解析第一个参数,得到一个java.util.Date
//结果: 2001-02-03 11:05:06.0
sql = "SELECT PARSEDATETIME('Sat, 3 Feb 2001 03:05:06 GMT', 'EEE, d MMM yyyy HH:mm:ss z', 'en', 'GMT')";
}
void systemFunctions() throws Exception {
sql = "SELECT DECODE(RAND()>0.5, 0, 'Red', 1, 'Black')";
sql = "SELECT DECODE(RAND()>0.5, 0, 'Red1', 0, 'Red2', 1, 'Black1', 1, 'Black2')";
sql = "SELECT DECODE(RAND()>0.5, 2, 'Red1', 2, 'Red2', 2, 'Black1', 2)";
sql = "SELECT DECODE(RAND()>0.5, 2, 'Red1', 2, 'Red2', 2, 'Black1', 2, 'Black2')";
sql = "SELECT DECODE(0, 0, 'v1', 0,/'v2', 1, 'v3', 1, 'v4')";
//ROW_NUMBER函数虽然定义了,但ROW_NUMBER()函数无效,不支持这样的语法
sql = "SELECT ROW_NUMBER()";
//ROWNUM函数虽然没有定义,但ROWNUM()是有效,Parser在解析时把他当成ROWNUM伪字段处理
//当成了org.h2.expression.Rownum,见org.h2.command.Parser.readTerm()
sql = "SELECT ROWNUM()";
//这样就没问题了,在这个方法中org.h2.command.Parser.readFunction(Schema, String)
//把ROW_NUMBER转成org.h2.expression.Rownum了
sql = "SELECT ROW_NUMBER()OVER()";
//相等返回null,不相等返回v0
sql = "SELECT NULLIF(1,2)"; //1
sql = "SELECT NULLIF(1,1)"; //null
sql = "SELECT DATABASE()";
sql = "SELECT USER(), CURRENT_USER()";
sql = "SELECT IDENTITY(), SCOPE_IDENTITY()";
sql = "SELECT LOCK_TIMEOUT()";
sql = "SELECT MEMORY_FREE(), MEMORY_USED()";
sql = "SELECT GREATEST(1,2,3), LEAST(1,2,3)";
sql = "SELECT ARRAY_GET(('Hello', 'World'), 2), ARRAY_LENGTH(('Hello', 'World')), "
+ "ARRAY_CONTAINS(('Hello', 'World'), 'Hello')";
//sql = "SELECT CASE(1>0, 1, b<0, 2)"; //不能这样用
sql = "SELECT SET(@v, 1), CASE @v WHEN 0 THEN 'No' WHEN 1 THEN 'One' ELSE 'Some' END";
sql = "SELECT SET(@v, 11), CASE WHEN @v<10 THEN 'Low' ELSE 'High' END";
stmt.executeUpdate("CREATE SEQUENCE IF NOT EXISTS SEQ_ID");
sql = "SELECT CURRVAL('SEQ_ID'), NEXTVAL('SEQ_ID')";
sql = "SELECT LENGTH(FILE_READ('E:/H2/my-h2/my-h2-src/my/test/expression/FunctionTest.java'))";
}
void callableStatement() throws Exception {
CallableStatement cs = conn.prepareCall("?= CALL myschema.MY_SQRT(2.2)");
cs.registerOutParameter(1, 0);
cs.execute();
//System.out.println(cs.getDouble(1));
}
}