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

Issue #539: Allow override of builtin functions/aliases

上级 233c1ce8
......@@ -1165,6 +1165,19 @@ This setting is persistent.
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","
SET [ DATABASE ] COLLATION
{ OFF | collationName [ STRENGTH { PRIMARY | SECONDARY | TERTIARY | IDENTICAL } ] }
......
......@@ -21,6 +21,8 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>Issue #539: Allow override of builtin functions/aliases
</li>
<li>Issue #535: Allow explicit paths on Windows without drive letter
</li>
<li>Issue #549: Removed UNION ALL requirements for CTE
......
......@@ -2707,10 +2707,17 @@ public class Parser {
return function;
}
private Function readFunctionWithoutParameters(String name) {
private Expression readFunctionWithoutParameters(String name) {
if (readIf("(")) {
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.doneWithParameters();
return function;
......@@ -4850,8 +4857,18 @@ public class Parser {
private CreateFunctionAlias parseCreateFunctionAlias(boolean force) {
boolean ifNotExists = readIfNotExists();
String aliasName = readIdentifierWithSchema();
if (isKeyword(aliasName) ||
final boolean newAliasSameNameAsBuiltin = Function.getFunction(database, currentToken) != null;
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 ||
getAggregateType(aliasName) >= 0) {
throw DbException.get(ErrorCode.FUNCTION_ALIAS_ALREADY_EXISTS_1,
......
......@@ -524,6 +524,16 @@ public class Set extends Prepared {
session.setLazyQueryExecution(value == 1);
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:
DbException.throwInternalError("type="+type);
}
......
......@@ -243,6 +243,11 @@ public class SetTypes {
*/
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 SetTypes() {
......@@ -298,6 +303,7 @@ public class SetTypes {
list.add(BATCH_JOINS, "BATCH_JOINS");
list.add(FORCE_JOIN_ORDER, "FORCE_JOIN_ORDER");
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 {
private int logMode;
private MVTableEngine.Store mvStore;
private int retentionTime;
private boolean allowBuiltinAliasOverride;
private DbException backgroundException;
private JavaObjectSerializer javaObjectSerializer;
private String javaObjectSerializerName;
......@@ -1983,7 +1984,15 @@ public class Database implements DataHandler {
mvStore.getStore().setRetentionTime(value);
}
}
public void setAllowBuiltinAliasOverride(boolean b) {
allowBuiltinAliasOverride = b;
}
public boolean isAllowBuiltinAliasOverride() {
return allowBuiltinAliasOverride;
}
/**
* Check if flush-on-each-commit is enabled.
*
......
......@@ -76,6 +76,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
@Override
public void test() throws Exception {
deleteDb("functions");
testOverrideAlias();
testIfNull();
testToDate();
testToDateException();
......@@ -1671,7 +1672,9 @@ public class TestFunctions extends TestBase implements AggregateFunction {
conn.close();
}
private void testIfNull() throws SQLException {
deleteDb("functions");
Connection conn = getConnection("functions");
Statement stat = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
......@@ -2113,6 +2116,26 @@ public class TestFunctions extends TestBase implements AggregateFunction {
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 {
deleteDb("functions");
try (Connection conn = getConnection("functions")) {
......@@ -2430,6 +2453,13 @@ public class TestFunctions extends TestBase implements AggregateFunction {
}
return new Object[] { buff.toString() };
}
/**
* This method is called via reflection from the database.
*/
public static long currentTimestampOverride() {
return 3141;
}
@Override
public void add(Object value) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论