提交 e57c42ec authored 作者: Noel Grandin's avatar Noel Grandin

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	h2/src/docsrc/html/changelog.html
...@@ -1165,6 +1165,19 @@ This setting is persistent. ...@@ -1165,6 +1165,19 @@ This setting is persistent.
SET BINARY_COLLATION SIGNED SET BINARY_COLLATION SIGNED
" "
"Commands (Other)","SET BUILTIN_ALIAS_OVERRIDE","
SET BUILTIN_ALIAS_OVERRIDE
{ TRUE | FALSE } ] }
","
Allows the overriding of the builtin system date/time functions
for unit testing purposes.
Admin rights are required to execute this command.
This command commits an open transaction in this connection.
","
SET BUILTIN_ALIAS_OVERRIDE TRUE
"
"Commands (Other)","SET COLLATION"," "Commands (Other)","SET COLLATION","
SET [ DATABASE ] COLLATION SET [ DATABASE ] COLLATION
{ OFF | collationName [ STRENGTH { PRIMARY | SECONDARY | TERTIARY | IDENTICAL } ] } { OFF | collationName [ STRENGTH { PRIMARY | SECONDARY | TERTIARY | IDENTICAL } ] }
......
...@@ -23,6 +23,8 @@ Change Log ...@@ -23,6 +23,8 @@ Change Log
<ul> <ul>
<li>Issue #569: ClassCastException when filtering on ENUM value in WHERE clause <li>Issue #569: ClassCastException when filtering on ENUM value in WHERE clause
</li> </li>
<li>Issue #539: Allow override of builtin functions/aliases
</li>
<li>Issue #535: Allow explicit paths on Windows without drive letter <li>Issue #535: Allow explicit paths on Windows without drive letter
</li> </li>
<li>Issue #549: Removed UNION ALL requirements for CTE <li>Issue #549: Removed UNION ALL requirements for CTE
......
...@@ -2707,10 +2707,17 @@ public class Parser { ...@@ -2707,10 +2707,17 @@ public class Parser {
return function; return function;
} }
private Function readFunctionWithoutParameters(String name) { private Expression readFunctionWithoutParameters(String name) {
if (readIf("(")) { if (readIf("(")) {
read(")"); read(")");
} }
if (database.isAllowBuiltinAliasOverride()) {
FunctionAlias functionAlias = database.getSchema(session.getCurrentSchemaName()).findFunction(name);
if (functionAlias != null) {
JavaFunction func = new JavaFunction(functionAlias, new Expression[0]);
return func;
}
}
Function function = Function.getFunction(database, name); Function function = Function.getFunction(database, name);
function.doneWithParameters(); function.doneWithParameters();
return function; return function;
...@@ -4850,8 +4857,18 @@ public class Parser { ...@@ -4850,8 +4857,18 @@ public class Parser {
private CreateFunctionAlias parseCreateFunctionAlias(boolean force) { private CreateFunctionAlias parseCreateFunctionAlias(boolean force) {
boolean ifNotExists = readIfNotExists(); boolean ifNotExists = readIfNotExists();
String aliasName = readIdentifierWithSchema(); final boolean newAliasSameNameAsBuiltin = Function.getFunction(database, currentToken) != null;
if (isKeyword(aliasName) || String aliasName;
if (database.isAllowBuiltinAliasOverride() && newAliasSameNameAsBuiltin) {
aliasName = currentToken;
schemaName = session.getCurrentSchemaName();
read();
} else {
aliasName = readIdentifierWithSchema();
}
if (database.isAllowBuiltinAliasOverride() && newAliasSameNameAsBuiltin) {
// fine
} else if (isKeyword(aliasName) ||
Function.getFunction(database, aliasName) != null || Function.getFunction(database, aliasName) != null ||
getAggregateType(aliasName) >= 0) { getAggregateType(aliasName) >= 0) {
throw DbException.get(ErrorCode.FUNCTION_ALIAS_ALREADY_EXISTS_1, throw DbException.get(ErrorCode.FUNCTION_ALIAS_ALREADY_EXISTS_1,
......
...@@ -169,7 +169,7 @@ public class Merge extends Prepared { ...@@ -169,7 +169,7 @@ public class Merge extends Prepared {
if (index != null) { if (index != null) {
// verify the index columns match the key // verify the index columns match the key
Column[] indexColumns = index.getColumns(); Column[] indexColumns = index.getColumns();
boolean indexMatchesKeys = false; boolean indexMatchesKeys = true;
if (indexColumns.length <= keys.length) { if (indexColumns.length <= keys.length) {
for (int i = 0; i < indexColumns.length; i++) { for (int i = 0; i < indexColumns.length; i++) {
if (indexColumns[i] != keys[i]) { if (indexColumns[i] != keys[i]) {
......
...@@ -524,6 +524,16 @@ public class Set extends Prepared { ...@@ -524,6 +524,16 @@ public class Set extends Prepared {
session.setLazyQueryExecution(value == 1); session.setLazyQueryExecution(value == 1);
break; break;
} }
case SetTypes.BUILTIN_ALIAS_OVERRIDE: {
session.getUser().checkAdmin();
int value = getIntValue();
if (value != 0 && value != 1) {
throw DbException.getInvalidValueException("BUILTIN_ALIAS_OVERRIDE",
value);
}
database.setAllowBuiltinAliasOverride(value == 1);
break;
}
default: default:
DbException.throwInternalError("type="+type); DbException.throwInternalError("type="+type);
} }
......
...@@ -243,6 +243,11 @@ public class SetTypes { ...@@ -243,6 +243,11 @@ public class SetTypes {
*/ */
public static final int LAZY_QUERY_EXECUTION = 46; public static final int LAZY_QUERY_EXECUTION = 46;
/**
* The type of SET BUILTIN_ALIAS_OVERRIDE statement.
*/
public static final int BUILTIN_ALIAS_OVERRIDE = 47;
private static final ArrayList<String> TYPES = New.arrayList(); private static final ArrayList<String> TYPES = New.arrayList();
private SetTypes() { private SetTypes() {
...@@ -298,6 +303,7 @@ public class SetTypes { ...@@ -298,6 +303,7 @@ public class SetTypes {
list.add(BATCH_JOINS, "BATCH_JOINS"); list.add(BATCH_JOINS, "BATCH_JOINS");
list.add(FORCE_JOIN_ORDER, "FORCE_JOIN_ORDER"); list.add(FORCE_JOIN_ORDER, "FORCE_JOIN_ORDER");
list.add(LAZY_QUERY_EXECUTION, "LAZY_QUERY_EXECUTION"); list.add(LAZY_QUERY_EXECUTION, "LAZY_QUERY_EXECUTION");
list.add(BUILTIN_ALIAS_OVERRIDE, "BUILTIN_ALIAS_OVERRIDE");
} }
/** /**
......
...@@ -191,6 +191,7 @@ public class Database implements DataHandler { ...@@ -191,6 +191,7 @@ public class Database implements DataHandler {
private int logMode; private int logMode;
private MVTableEngine.Store mvStore; private MVTableEngine.Store mvStore;
private int retentionTime; private int retentionTime;
private boolean allowBuiltinAliasOverride;
private DbException backgroundException; private DbException backgroundException;
private JavaObjectSerializer javaObjectSerializer; private JavaObjectSerializer javaObjectSerializer;
private String javaObjectSerializerName; private String javaObjectSerializerName;
...@@ -1983,7 +1984,15 @@ public class Database implements DataHandler { ...@@ -1983,7 +1984,15 @@ public class Database implements DataHandler {
mvStore.getStore().setRetentionTime(value); mvStore.getStore().setRetentionTime(value);
} }
} }
public void setAllowBuiltinAliasOverride(boolean b) {
allowBuiltinAliasOverride = b;
}
public boolean isAllowBuiltinAliasOverride() {
return allowBuiltinAliasOverride;
}
/** /**
* Check if flush-on-each-commit is enabled. * Check if flush-on-each-commit is enabled.
* *
......
...@@ -76,6 +76,7 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -76,6 +76,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
@Override @Override
public void test() throws Exception { public void test() throws Exception {
deleteDb("functions"); deleteDb("functions");
testOverrideAlias();
testIfNull(); testIfNull();
testToDate(); testToDate();
testToDateException(); testToDateException();
...@@ -1671,7 +1672,9 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -1671,7 +1672,9 @@ public class TestFunctions extends TestBase implements AggregateFunction {
conn.close(); conn.close();
} }
private void testIfNull() throws SQLException { private void testIfNull() throws SQLException {
deleteDb("functions");
Connection conn = getConnection("functions"); Connection conn = getConnection("functions");
Statement stat = conn.createStatement( Statement stat = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
...@@ -2113,6 +2116,26 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -2113,6 +2116,26 @@ public class TestFunctions extends TestBase implements AggregateFunction {
conn.close(); conn.close();
} }
private void testOverrideAlias()
throws SQLException, InterruptedException {
deleteDb("functions");
Connection conn = getConnection("functions");
conn.setAutoCommit(true);
Statement stat = conn.createStatement();
assertThrows(ErrorCode.FUNCTION_ALIAS_ALREADY_EXISTS_1, stat).execute("create alias CURRENT_TIMESTAMP for \"" +
getClass().getName() + ".currentTimestamp\"");
stat.execute("set BUILTIN_ALIAS_OVERRIDE true");
stat.execute("create alias CURRENT_TIMESTAMP for \"" +
getClass().getName() + ".currentTimestampOverride\"");
assertCallResult("3141", stat, "CURRENT_TIMESTAMP");
conn.close();
}
private void callCompiledFunction(String functionName) throws SQLException { private void callCompiledFunction(String functionName) throws SQLException {
deleteDb("functions"); deleteDb("functions");
try (Connection conn = getConnection("functions")) { try (Connection conn = getConnection("functions")) {
...@@ -2430,6 +2453,13 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -2430,6 +2453,13 @@ public class TestFunctions extends TestBase implements AggregateFunction {
} }
return new Object[] { buff.toString() }; return new Object[] { buff.toString() };
} }
/**
* This method is called via reflection from the database.
*/
public static long currentTimestampOverride() {
return 3141;
}
@Override @Override
public void add(Object value) { public void add(Object value) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论