提交 7914d55a authored 作者: noelgrandin's avatar noelgrandin

Issue 534: CREATE ALIAS NOCACHE, Patch by Nicolas Fortin

上级 397d3126
......@@ -420,11 +420,15 @@ CREATE AGGREGATE MEDIAN FOR ""com.acme.db.Median""
"
"Commands (DDL)","CREATE ALIAS","
CREATE ALIAS [ IF NOT EXISTS ] newFunctionAliasName [ DETERMINISTIC ]
CREATE ALIAS [ IF NOT EXISTS ] newFunctionAliasName [ DETERMINISTIC ] [ NOBUFFER ]
{ FOR classAndMethodName | AS sourceCodeString }
","
Creates a new function alias. Deterministic functions must always return the
same value for the same parameters. The result of such functions is cached if possible.
Creates a new function alias. If this is a ResultSet returning function,
by default the return value is cached in a local temporary file.
NOBUFFER - disables caching of ResultSet return value to temporary file.
DETERMINISTIC - Deterministic functions must always return the same value for the same parameters.
The method name must be the full qualified class and method name,
and may optionally include the parameter classes as in
......
......@@ -45,6 +45,7 @@ Change Log
</li><li>Extend support of "GRANT ALTER ANY SCHEMA TO &lt;user&gt;" to allow grantee ability to manipulate tables
</li><li>Issue 532: Javadoc for ErrorCode.ROLES_AND_RIGHT_CANNOT_BE_MIXED looks wrong
</li><li>Issue 528: Add Oracle-compatible TO_CHAR function, patch by Daniel Gredler.
</li><li>Issue 534: CREATE ALIAS NOCACHE, Patch by Nicolas Fortin
</li></ul>
<h2>Version 1.3.174 (2013-10-19)</h2>
......
......@@ -4433,6 +4433,7 @@ public class Parser {
command.setAliasName(aliasName);
command.setIfNotExists(ifNotExists);
command.setDeterministic(readIf("DETERMINISTIC"));
command.setBufferResultSetToLocalTemp(!readIf("NOBUFFER"));
if (readIf("AS")) {
command.setSource(readString());
} else {
......
......@@ -27,6 +27,7 @@ public class CreateFunctionAlias extends SchemaCommand {
private boolean ifNotExists;
private boolean force;
private String source;
private boolean bufferResultSetToLocalTemp = true;
public CreateFunctionAlias(Session session, Schema schema) {
super(session, schema);
......@@ -45,9 +46,9 @@ public class CreateFunctionAlias extends SchemaCommand {
int id = getObjectId();
FunctionAlias functionAlias;
if (javaClassMethod != null) {
functionAlias = FunctionAlias.newInstance(getSchema(), id, aliasName, javaClassMethod, force);
functionAlias = FunctionAlias.newInstance(getSchema(), id, aliasName, javaClassMethod, force, bufferResultSetToLocalTemp);
} else {
functionAlias = FunctionAlias.newInstanceFromSource(getSchema(), id, aliasName, source, force);
functionAlias = FunctionAlias.newInstanceFromSource(getSchema(), id, aliasName, source, force, bufferResultSetToLocalTemp);
}
functionAlias.setDeterministic(deterministic);
db.addSchemaObject(session, functionAlias);
......@@ -80,6 +81,13 @@ public class CreateFunctionAlias extends SchemaCommand {
this.deterministic = deterministic;
}
/**
* Should the return value ResultSet be buffered in a local temporary file?
*/
public void setBufferResultSetToLocalTemp(boolean b) {
this.bufferResultSetToLocalTemp = b;
}
public void setSource(String source) {
this.source = source;
}
......
......@@ -46,6 +46,7 @@ public class FunctionAlias extends SchemaObjectBase {
private String source;
private JavaMethod[] javaMethods;
private boolean deterministic;
private boolean bufferResultSetToLocalTemp = true;
private FunctionAlias(Schema schema, int id, String name) {
initSchemaObjectBase(schema, id, name, Trace.FUNCTION);
......@@ -61,7 +62,7 @@ public class FunctionAlias extends SchemaObjectBase {
* @param force create the object even if the class or method does not exist
* @return the database object
*/
public static FunctionAlias newInstance(Schema schema, int id, String name, String javaClassMethod, boolean force) {
public static FunctionAlias newInstance(Schema schema, int id, String name, String javaClassMethod, boolean force, boolean bufferResultSetToLocalTemp) {
FunctionAlias alias = new FunctionAlias(schema, id, name);
int paren = javaClassMethod.indexOf('(');
int lastDot = javaClassMethod.lastIndexOf('.', paren < 0 ? javaClassMethod.length() : paren);
......@@ -70,6 +71,7 @@ public class FunctionAlias extends SchemaObjectBase {
}
alias.className = javaClassMethod.substring(0, lastDot);
alias.methodName = javaClassMethod.substring(lastDot + 1);
alias.bufferResultSetToLocalTemp = bufferResultSetToLocalTemp;
alias.init(force);
return alias;
}
......@@ -84,9 +86,10 @@ public class FunctionAlias extends SchemaObjectBase {
* @param force create the object even if the class or method does not exist
* @return the database object
*/
public static FunctionAlias newInstanceFromSource(Schema schema, int id, String name, String source, boolean force) {
public static FunctionAlias newInstanceFromSource(Schema schema, int id, String name, String source, boolean force, boolean bufferResultSetToLocalTemp) {
FunctionAlias alias = new FunctionAlias(schema, id, name);
alias.source = source;
alias.bufferResultSetToLocalTemp = bufferResultSetToLocalTemp;
alias.init(force);
return alias;
}
......@@ -209,6 +212,9 @@ public class FunctionAlias extends SchemaObjectBase {
if (deterministic) {
buff.append(" DETERMINISTIC");
}
if (!bufferResultSetToLocalTemp) {
buff.append(" NOBUFFER");
}
if (source != null) {
buff.append(" AS ").append(StringUtils.quoteStringSQL(source));
} else {
......@@ -505,4 +511,10 @@ public class FunctionAlias extends SchemaObjectBase {
}
}
/**
* Should the return value ResultSet be buffered in a local temporary file?
*/
public boolean isBufferResultSetToLocalTemp() {
return bufferResultSetToLocalTemp;
}
}
......@@ -346,9 +346,9 @@ public class Function extends Expression implements FunctionCall {
addFunctionNotDeterministic("NEXTVAL", NEXTVAL, VAR_ARGS, Value.LONG);
addFunctionNotDeterministic("CURRVAL", CURRVAL, VAR_ARGS, Value.LONG);
addFunction("ARRAY_GET", ARRAY_GET, 2, Value.STRING);
addFunction("ARRAY_CONTAINS", ARRAY_CONTAINS, 2, Value.BOOLEAN, false, true, false);
addFunction("CSVREAD", CSVREAD, VAR_ARGS, Value.RESULT_SET, false, false, true);
addFunction("CSVWRITE", CSVWRITE, VAR_ARGS, Value.INT, false, false, false);
addFunction("ARRAY_CONTAINS", ARRAY_CONTAINS, 2, Value.BOOLEAN, false, true, true);
addFunction("CSVREAD", CSVREAD, VAR_ARGS, Value.RESULT_SET, false, false, false);
addFunction("CSVWRITE", CSVWRITE, VAR_ARGS, Value.INT, false, false, true);
addFunctionNotDeterministic("MEMORY_FREE", MEMORY_FREE, 0, Value.INT);
addFunctionNotDeterministic("MEMORY_USED", MEMORY_USED, 0, Value.INT);
addFunctionNotDeterministic("LOCK_MODE", LOCK_MODE, 0, Value.INT);
......@@ -359,8 +359,8 @@ public class Function extends Expression implements FunctionCall {
addFunctionWithNull("LEAST", LEAST, VAR_ARGS, Value.NULL);
addFunctionWithNull("GREATEST", GREATEST, VAR_ARGS, Value.NULL);
addFunctionNotDeterministic("CANCEL_SESSION", CANCEL_SESSION, 1, Value.BOOLEAN);
addFunction("SET", SET, 2, Value.NULL, false, false, false);
addFunction("FILE_READ", FILE_READ, VAR_ARGS, Value.NULL, false, false, false);
addFunction("SET", SET, 2, Value.NULL, false, false, true);
addFunction("FILE_READ", FILE_READ, VAR_ARGS, Value.NULL, false, false, true);
addFunctionNotDeterministic("TRANSACTION_ID", TRANSACTION_ID, 0, Value.STRING);
addFunctionWithNull("DECODE", DECODE, VAR_ARGS, Value.NULL);
addFunctionNotDeterministic("DISK_SPACE_USED", DISK_SPACE_USED, 1, Value.LONG);
......@@ -374,7 +374,7 @@ public class Function extends Expression implements FunctionCall {
addFunctionWithNull("ROW_NUMBER", ROW_NUMBER, 0, Value.LONG);
// ON DUPLICATE KEY VALUES function
addFunction("VALUES", VALUES, 1, Value.NULL, false, true, true);
addFunction("VALUES", VALUES, 1, Value.NULL, false, true, false);
}
protected Function(Database database, FunctionInfo info) {
......@@ -388,7 +388,7 @@ public class Function extends Expression implements FunctionCall {
}
private static void addFunction(String name, int type, int parameterCount, int dataType,
boolean nullIfParameterIsNull, boolean deterministic, boolean fast) {
boolean nullIfParameterIsNull, boolean deterministic, boolean bufferResultSetToLocalTemp) {
FunctionInfo info = new FunctionInfo();
info.name = name;
info.type = type;
......@@ -396,20 +396,20 @@ public class Function extends Expression implements FunctionCall {
info.dataType = dataType;
info.nullIfParameterIsNull = nullIfParameterIsNull;
info.deterministic = deterministic;
info.fast = fast;
info.bufferResultSetToLocalTemp = bufferResultSetToLocalTemp;
FUNCTIONS.put(name, info);
}
private static void addFunctionNotDeterministic(String name, int type, int parameterCount, int dataType) {
addFunction(name, type, parameterCount, dataType, true, false, false);
addFunction(name, type, parameterCount, dataType, true, false, true);
}
private static void addFunction(String name, int type, int parameterCount, int dataType) {
addFunction(name, type, parameterCount, dataType, true, true, false);
addFunction(name, type, parameterCount, dataType, true, true, true);
}
private static void addFunctionWithNull(String name, int type, int parameterCount, int dataType) {
addFunction(name, type, parameterCount, dataType, false, true, false);
addFunction(name, type, parameterCount, dataType, false, true, true);
}
/**
......@@ -2354,8 +2354,8 @@ public class Function extends Expression implements FunctionCall {
}
@Override
public boolean isFast() {
return info.fast;
public boolean isBufferResultSetToLocalTemp() {
return info.bufferResultSetToLocalTemp;
}
}
......@@ -75,10 +75,10 @@ public interface FunctionCall {
boolean isDeterministic();
/**
* Whether the function is fast, meaning the result shouldn't be cached.
* Should the return value ResultSet be buffered in a local temporary file?
*
* @return true if it is
* @return true if it should be.
*/
boolean isFast();
boolean isBufferResultSetToLocalTemp();
}
......@@ -42,8 +42,8 @@ class FunctionInfo {
boolean deterministic;
/**
* Whether the function is fast, meaning the result shouldn't be cached.
* Should the return value ResultSet be buffered in a local temporary file?
*/
boolean fast;
boolean bufferResultSetToLocalTemp = true;
}
......@@ -184,8 +184,8 @@ public class JavaFunction extends Expression implements FunctionCall {
}
@Override
public boolean isFast() {
return false;
public boolean isBufferResultSetToLocalTemp() {
return functionAlias.isBufferResultSetToLocalTemp();
}
}
......@@ -45,10 +45,11 @@ public class FunctionIndex extends BaseIndex {
@Override
public Cursor find(Session session, SearchRow first, SearchRow last) {
if (functionTable.isFast()) {
return new FunctionCursorResultSet(session, functionTable.getResultSet(session));
if (functionTable.isBufferResultSetToLocalTemp()) {
return new FunctionCursor(functionTable.getResult(session));
} else {
return new FunctionCursorResultSet(session, functionTable.getResultSet(session));
}
return new FunctionCursor(functionTable.getResult(session));
}
@Override
......
......@@ -155,7 +155,7 @@ CREATE AGGREGATE [ IF NOT EXISTS ] newAggregateName FOR className
","
Creates a new user-defined aggregate function."
"Commands (DDL)","CREATE ALIAS","
CREATE ALIAS [ IF NOT EXISTS ] newFunctionAliasName [ DETERMINISTIC ]
CREATE ALIAS [ IF NOT EXISTS ] newFunctionAliasName [ DETERMINISTIC ] [ NOBUFFER ]
{ FOR classAndMethodName | AS sourceCodeString }
","
Creates a new function alias."
......
......@@ -171,7 +171,7 @@ public class FunctionTable extends Table {
}
/**
* Read the result from the function. This method caches the result.
* Read the result from the function. This method buffers the result in a temporary file.
*
* @param session the session
* @return the result
......@@ -213,8 +213,8 @@ public class FunctionTable extends Table {
return (ValueResultSet) v;
}
public boolean isFast() {
return function.isFast();
public boolean isBufferResultSetToLocalTemp() {
return function.isBufferResultSetToLocalTemp();
}
@Override
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论