提交 411e4eca authored 作者: Thomas Mueller's avatar Thomas Mueller

Improved Oracle compatibility: support for NVL2. Thanks to litailang for the patch!

上级 2d60abe3
...@@ -3337,7 +3337,7 @@ CAST(CAST('FFFF' AS BINARY) AS INT); ...@@ -3337,7 +3337,7 @@ CAST(CAST('FFFF' AS BINARY) AS INT);
" "
"Functions (System)","COALESCE"," "Functions (System)","COALESCE","
COALESCE(aValue, bValue [,...]) { COALESCE | NVL } (aValue, bValue [,...])
"," ","
Returns the first value that is not null. Returns the first value that is not null.
"," ","
...@@ -3565,6 +3565,14 @@ Returns NULL if 'a' is equals to 'b', otherwise 'a'. ...@@ -3565,6 +3565,14 @@ Returns NULL if 'a' is equals to 'b', otherwise 'a'.
NULLIF(A, B) NULLIF(A, B)
" "
"Functions (System)","NVL2","
NVL2(testValue, aValue, bValue)
","
If the test value is null, then 'b' is returned. Otherwise, 'a' is returned.
","
NVL2(X, 'not null', 'null')
"
"Functions (System)","READONLY"," "Functions (System)","READONLY","
READONLY() READONLY()
"," ","
......
...@@ -17,7 +17,8 @@ Change Log ...@@ -17,7 +17,8 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>Improved PostgreSQL compatibility: support for RANDOM() in addition to RAND(). <ul><li>Improved Oracle compatibility: support for NVL2. Thanks to litailang for the patch!
</li><li>Improved PostgreSQL compatibility: support for RANDOM() in addition to RAND().
</li><li>There was a classloader memory leak problem because a class contained a static </li><li>There was a classloader memory leak problem because a class contained a static
references to an exception (including stack trace). references to an exception (including stack trace).
</li><li>Split file system: truncating a file now deletes the parts in reverse order, </li><li>Split file system: truncating a file now deletes the parts in reverse order,
......
...@@ -95,7 +95,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -95,7 +95,7 @@ public class Function extends Expression implements FunctionCall {
CASE = 206, NEXTVAL = 207, CURRVAL = 208, ARRAY_GET = 209, CSVREAD = 210, CSVWRITE = 211, CASE = 206, NEXTVAL = 207, CURRVAL = 208, ARRAY_GET = 209, CSVREAD = 210, CSVWRITE = 211,
MEMORY_FREE = 212, MEMORY_USED = 213, LOCK_MODE = 214, SCHEMA = 215, SESSION_ID = 216, ARRAY_LENGTH = 217, MEMORY_FREE = 212, MEMORY_USED = 213, LOCK_MODE = 214, SCHEMA = 215, SESSION_ID = 216, ARRAY_LENGTH = 217,
LINK_SCHEMA = 218, GREATEST = 219, LEAST = 220, CANCEL_SESSION = 221, SET = 222, TABLE = 223, TABLE_DISTINCT = 224, LINK_SCHEMA = 218, GREATEST = 219, LEAST = 220, CANCEL_SESSION = 221, SET = 222, TABLE = 223, TABLE_DISTINCT = 224,
FILE_READ = 225, TRANSACTION_ID = 226, TRUNCATE_VALUE = 227; FILE_READ = 225, TRANSACTION_ID = 226, TRUNCATE_VALUE = 227, NVL2 = 228;
private static final int VAR_ARGS = -1; private static final int VAR_ARGS = -1;
private static final long PRECISION_UNKNOWN = -1; private static final long PRECISION_UNKNOWN = -1;
...@@ -301,6 +301,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -301,6 +301,7 @@ public class Function extends Expression implements FunctionCall {
addFunctionWithNull("TRUNCATE_VALUE", TRUNCATE_VALUE, 3, Value.NULL); addFunctionWithNull("TRUNCATE_VALUE", TRUNCATE_VALUE, 3, Value.NULL);
addFunctionWithNull("COALESCE", COALESCE, VAR_ARGS, Value.NULL); addFunctionWithNull("COALESCE", COALESCE, VAR_ARGS, Value.NULL);
addFunctionWithNull("NVL", COALESCE, VAR_ARGS, Value.NULL); addFunctionWithNull("NVL", COALESCE, VAR_ARGS, Value.NULL);
addFunctionWithNull("NVL2", NVL2, 3, Value.NULL);
addFunctionWithNull("NULLIF", NULLIF, 2, Value.NULL); addFunctionWithNull("NULLIF", NULLIF, 2, Value.NULL);
addFunctionWithNull("CASE", CASE, VAR_ARGS, Value.NULL); addFunctionWithNull("CASE", CASE, VAR_ARGS, Value.NULL);
addFunctionNotDeterministic("NEXTVAL", NEXTVAL, VAR_ARGS, Value.LONG); addFunctionNotDeterministic("NEXTVAL", NEXTVAL, VAR_ARGS, Value.LONG);
...@@ -753,6 +754,17 @@ public class Function extends Expression implements FunctionCall { ...@@ -753,6 +754,17 @@ public class Function extends Expression implements FunctionCall {
result = v.convertTo(dataType); result = v.convertTo(dataType);
break; break;
} }
case NVL2: {
Expression expr;
if (v0 == ValueNull.INSTANCE) {
expr = argList[2];
} else {
expr = argList[1];
}
Value v = expr.getValue(session);
result = v.convertTo(dataType);
break;
}
case COALESCE: { case COALESCE: {
result = v0; result = v0;
for (int i = 0; i < argList.length; i++) { for (int i = 0; i < argList.length; i++) {
...@@ -1677,6 +1689,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1677,6 +1689,7 @@ public class Function extends Expression implements FunctionCall {
break; break;
} }
case CASEWHEN: case CASEWHEN:
case NVL2:
t = Value.getHigherOrder(args[1].getType(), args[2].getType()); t = Value.getHigherOrder(args[1].getType(), args[2].getType());
p = Math.max(args[1].getPrecision(), args[2].getPrecision()); p = Math.max(args[1].getPrecision(), args[2].getPrecision());
d = Math.max(args[1].getDisplaySize(), args[2].getDisplaySize()); d = Math.max(args[1].getDisplaySize(), args[2].getDisplaySize());
......
...@@ -25,6 +25,7 @@ import java.util.Properties; ...@@ -25,6 +25,7 @@ import java.util.Properties;
import java.util.UUID; import java.util.UUID;
import org.h2.api.AggregateFunction; import org.h2.api.AggregateFunction;
import org.h2.jdbc.JdbcSQLException;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
...@@ -66,10 +67,60 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -66,10 +67,60 @@ public class TestFunctions extends TestBase implements AggregateFunction {
testFunctions(); testFunctions();
testFileRead(); testFileRead();
testValue(); testValue();
testNvl2();
deleteDb("functions"); deleteDb("functions");
IOUtils.deleteRecursive(TEMP_DIR, true); IOUtils.deleteRecursive(TEMP_DIR, true);
} }
private void testNvl2() throws SQLException {
Connection conn = getConnection("functions");
Statement stat = conn.createStatement();
String createSQL = "CREATE TABLE testNvl2 (id BIGINT,txt1 varchar,txt2 varchar,num number(9,0));";
stat.execute(createSQL);
stat.execute("insert into testNvl2(id,txt1,txt2,num) values (1,'test1','test2',null)");
stat.execute("insert into testNvl2(id,txt1,txt2,num) values (2,null,'test4',null)");
stat.execute("insert into testNvl2(id,txt1,txt2,num) values (3,'test5',null,null)");
stat.execute("insert into testNvl2(id,txt1,txt2,num) values (4,null,null,null)");
stat.execute("insert into testNvl2(id,txt1,txt2,num) values (5,'2',null,1)");
stat.execute("insert into testNvl2(id,txt1,txt2,num) values (6,'2',null,null)");
stat.execute("insert into testNvl2(id,txt1,txt2,num) values (7,'test2',null,null)");
String query = "SELECT NVL2(txt1, txt1, txt2), txt1 FROM testNvl2 order by id asc";
ResultSet rs = stat.executeQuery(query);
rs.next();
String actual = rs.getString(1);
assertEquals("test1", actual);
rs.next();
actual = rs.getString(1);
assertEquals("test4", actual);
rs.next();
actual = rs.getString(1);
assertEquals("test5", actual);
rs.next();
actual = rs.getString(1);
assertEquals(null, actual);
assertEquals(rs.getMetaData().getColumnType(2), rs.getMetaData().getColumnType(1));
rs.close();
rs = stat.executeQuery("SELECT NVL2(num, num, txt1), num FROM testNvl2 where id in (5,6) order by id asc");
rs.next();
assertEquals(rs.getMetaData().getColumnType(2), rs.getMetaData().getColumnType(1));
try {
rs = stat.executeQuery("SELECT NVL2(num, num, txt1), num FROM testNvl2 where id = 7 order by id asc");
} catch (JdbcSQLException e) {
Throwable t = e.getCause();
if (t instanceof NumberFormatException) {
//
} else {
throw e;
}
}
conn.close();
}
private void testValue() throws SQLException { private void testValue() throws SQLException {
Connection conn = getConnection("functions"); Connection conn = getConnection("functions");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论