提交 67a43816 authored 作者: Thomas Mueller's avatar Thomas Mueller

function overloading

上级 2a83a1ba
......@@ -10,7 +10,9 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.SQLException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import org.h2.api.Trigger;
import org.h2.command.ddl.AlterIndexRename;
......@@ -1810,15 +1812,17 @@ public class Parser {
// ( CALL "java.lang.Math.sqrt"(2.0) )
throw Message.getSQLException(ErrorCode.FUNCTION_NOT_FOUND_1, name);
}
int paramCount = functionAlias.getParameterCount();
Expression[] args = new Expression[paramCount];
for (int i = 0; i < args.length; i++) {
if (i > 0) {
Expression[] args;
List argList = new ArrayList();
int numArgs = 0;
while (!readIf(")")) {
if (numArgs++ > 0) {
read(",");
}
args[i] = readExpression();
argList.add(readExpression());
}
read(")");
args = new Expression[numArgs];
argList.toArray(args);
JavaFunction func = new JavaFunction(functionAlias, args);
return func;
}
......
......@@ -1092,6 +1092,22 @@ public class ErrorCode {
*/
public static final int ROLES_AND_RIGHT_CANNOT_BE_MIXED = 90072;
/**
* The error with code <code>90073</code> is thrown when trying to create
* an alias for a Java method, if two methods exists in this class that have
* this name and the same number of parameters. Example:
* <pre>
* CREATE ALIAS GET_LONG FOR
* "java.lang.Long.getLong";
* </pre>
* Correct:
* <pre>
* CREATE ALIAS GET_LONG FOR
* "java.lang.Long.getLong(java.lang.String, java.lang.Long)";
* </pre>
*/
public static final int METHODS_MUST_HAVE_DIFFERENT_PARAMETER_COUNTS_2 = 90073;
/**
* The error with code <code>90074</code> is thrown when
* trying to grant a role that has already been granted.
......
......@@ -23,19 +23,21 @@ import org.h2.value.ValueResultSet;
public class JavaFunction extends Expression implements FunctionCall {
private FunctionAlias functionAlias;
private FunctionAlias.JavaMethod javaMethod;
private Expression[] args;
public JavaFunction(FunctionAlias functionAlias, Expression[] args) {
public JavaFunction(FunctionAlias functionAlias, Expression[] args) throws SQLException {
this.functionAlias = functionAlias;
this.javaMethod = functionAlias.findJavaMethod(args);
this.args = args;
}
public Value getValue(Session session) throws SQLException {
return functionAlias.getValue(session, args, false);
return javaMethod.getValue(session, args, false);
}
public int getType() {
return functionAlias.getDataType();
return javaMethod.getDataType();
}
public void mapColumns(ColumnResolver resolver, int level) throws SQLException {
......@@ -102,11 +104,11 @@ public class JavaFunction extends Expression implements FunctionCall {
}
public int getParameterCount() throws SQLException {
return functionAlias.getParameterCount();
return javaMethod.getParameterCount();
}
public ValueResultSet getValueForColumnList(Session session, Expression[] args) throws SQLException {
Value v = functionAlias.getValue(session, args, true);
Value v = javaMethod.getValue(session, args, true);
return v == ValueNull.INSTANCE ? null : (ValueResultSet) v;
}
......@@ -135,7 +137,7 @@ public class JavaFunction extends Expression implements FunctionCall {
}
public int getCost() {
int cost = functionAlias.hasConnectionParam() ? 25 : 5;
int cost = javaMethod.hasConnectionParam() ? 25 : 5;
for (int i = 0; i < args.length; i++) {
cost += args[i].getCost();
}
......
......@@ -493,13 +493,15 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
/**
* Gets the list of procedures. The result set is sorted by PROCEDURE_SCHEM,
* and PROCEDURE_NAME.
* PROCEDURE_NAME, and NUM_INPUT_PARAMS. There are potentially multiple
* procedures with the same name, each with a different number of input
* parameters.
*
* <ul>
* <li>1 PROCEDURE_CAT (String) catalog </li>
* <li>2 PROCEDURE_SCHEM (String) schema </li>
* <li>3 PROCEDURE_NAME (String) name </li>
* <li>4 NUM_INPUT_PARAMS (int) for future use, always 0 </li>
* <li>4 NUM_INPUT_PARAMS (int) the number of arguments </li>
* <li>5 NUM_OUTPUT_PARAMS (int) for future use, always 0 </li>
* <li>6 NUM_RESULT_SETS (int) for future use, always 0 </li>
* <li>7 REMARKS (String) description </li>
......@@ -507,7 +509,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
* (procedureNoResult or procedureReturnsResult) </li>
* </ul>
*
* @return an empty result set
* @return the procedures.
* @throws SQLException if the connection is closed
*/
public ResultSet getProcedures(String catalog, String schemaPattern,
......@@ -524,7 +526,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "ALIAS_CATALOG PROCEDURE_CAT, "
+ "ALIAS_SCHEMA PROCEDURE_SCHEM, "
+ "ALIAS_NAME PROCEDURE_NAME, "
+ "ZERO() NUM_INPUT_PARAMS, "
+ "COLUMN_COUNT NUM_INPUT_PARAMS, "
+ "ZERO() NUM_OUTPUT_PARAMS, "
+ "ZERO() NUM_RESULT_SETS, "
+ "REMARKS, "
......@@ -533,7 +535,7 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "WHERE ALIAS_CATALOG LIKE ? "
+ "AND ALIAS_SCHEMA LIKE ? "
+ "AND ALIAS_NAME LIKE ? "
+ "ORDER BY PROCEDURE_SCHEM, PROCEDURE_NAME");
+ "ORDER BY PROCEDURE_SCHEM, PROCEDURE_NAME, NUM_INPUT_PARAMS");
prep.setString(1, getCatalogPattern(catalog));
prep.setString(2, getSchemaPattern(schemaPattern));
prep.setString(3, getPattern(procedureNamePattern));
......@@ -544,24 +546,29 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
}
/**
* Gets the list of procedure columns.
*
* Gets the list of procedure columns. The result set is sorted by
* PROCEDURE_SCHEM, PROCEDURE_NAME, NUM_INPUT_PARAMS, and POS.
* There are potentially multiple procedures with the same name, each with a
* different number of input parameters.
*
* <ul>
* <li>1 PROCEDURE_CAT (String) catalog
* </li><li>2 PROCEDURE_SCHEM (String) schema
* </li><li>3 PROCEDURE_NAME (String) name
* </li><li>4 COLUMN_NAME (String) column name
* </li><li>5 COLUMN_TYPE (short) column type
* </li><li>6 DATA_TYPE (short) sql type
* </li><li>7 TYPE_NAME (String) type name
* </li><li>8 PRECISION (int) precision
* </li><li>9 LENGTH (int) length
* </li><li>10 SCALE (short) scale
* </li><li>11 RADIX (int) always 10
* </li><li>12 NULLABLE (short) nullable
* </li><li>13 REMARKS (String) description
* </li></ul>
*
* <li>1 PROCEDURE_CAT (String) catalog </li>
* <li>2 PROCEDURE_SCHEM (String) schema </li>
* <li>3 PROCEDURE_NAME (String) name </li>
* <li>4 COLUMN_NAME (String) column name </li>
* <li>5 COLUMN_TYPE (short) column type </li>
* <li>6 DATA_TYPE (short) sql type </li>
* <li>7 TYPE_NAME (String) type name </li>
* <li>8 PRECISION (int) precision </li>
* <li>9 LENGTH (int) length </li>
* <li>10 SCALE (short) scale </li>
* <li>11 RADIX (int) always 10 </li>
* <li>12 NULLABLE (short) nullable </li>
* <li>13 REMARKS (String) description </li>
* <li>14 NUM_INPUT_PARAMS (int) the parameter count </li>
* <li>15 POS (int) the parameter index </li>
* </ul>
*
* @throws SQLException if the connection is closed
*/
public ResultSet getProcedureColumns(String catalog, String schemaPattern,
......@@ -589,12 +596,15 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "SCALE, "
+ "RADIX, "
+ "NULLABLE, "
+ "REMARKS "
+ "REMARKS, "
+ "COLUMN_COUNT NUM_INPUT_PARAMS, "
+ "POS "
+ "FROM INFORMATION_SCHEMA.FUNCTION_COLUMNS "
+ "WHERE ALIAS_CATALOG LIKE ? "
+ "AND ALIAS_SCHEMA LIKE ? "
+ "AND ALIAS_NAME LIKE ? "
+ "AND COLUMN_NAME LIKE ?");
+ "AND COLUMN_NAME LIKE ? "
+ "ORDER BY PROCEDURE_SCHEM, PROCEDURE_NAME, NUM_INPUT_PARAMS, POS");
prep.setString(1, getCatalogPattern(catalog));
prep.setString(2, getSchemaPattern(schemaPattern));
prep.setString(3, getPattern(procedureNamePattern));
......
......@@ -93,7 +93,7 @@
90070=Rolle {0} nicht gefunden
90071=Benutzer or Rolle {0} nicht gefunden
90072=Rollen und Rechte k\u00F6nnen nicht gemischt werden
90073=Recht nicht gefunden
90073=Java Methoden m\u00FCssen eine unterschiedliche Anzahl Parameter aufweisen\: {0} und {1}
90074=Rolle {0} bereits zugewiesen
90075=Feld ist Teil eines Indexes {0}
90076=Funktions-Alias {0} besteht bereits
......
......@@ -93,7 +93,7 @@
90070=Role {0} not found
90071=User or role {0} not found
90072=Roles and rights cannot be mixed
90073=Right not found
90073=Matching Java methods must have different parameter counts\: {0} and {1}
90074=Role {0} already granted
90075=Column is part of the index {0}
90076=Function alias {0} already exists
......
......@@ -93,7 +93,7 @@
90070=\u30ED\u30FC\u30EB {0} \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
90071=\u30E6\u30FC\u30B6\u3001\u307E\u305F\u306F\u30ED\u30FC\u30EB {0} \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
90072=\u30ED\u30FC\u30EB\u3068\u6A29\u9650\u306F\u6DF7\u5728\u3067\u304D\u307E\u305B\u3093
90073=\u6A29\u9650\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
90073=\#Matching Java methods must have different parameter counts\: {0} and {1}
90074=\u30ED\u30FC\u30EB {0} \u306F\u3059\u3067\u306B\u8A31\u53EF\u3055\u308C\u3066\u3044\u307E\u3059
90075=\u5217\u306F\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9 {0} \u306E\u4E00\u90E8\u3067\u3059
90076=\u95A2\u6570\u306E\u5225\u540D {0} \u306F\u3059\u3067\u306B\u5B58\u5728\u3057\u307E\u3059
......
......@@ -93,7 +93,7 @@
90070=Rola {0} nie istnieje
90071=Uzytkownik lub Rola User {0} nie istnieje
90072=Role i prawa nie moga byc mieszane
90073=Prawo nie istnieje
90073=\#Matching Java methods must have different parameter counts\: {0} and {1}
90074=Rola {0} juz przyznana
90075=Kolumna jest czescia indeksu {0}
90076=Alias funkcji {0} juz istnieje
......
......@@ -93,7 +93,7 @@
90070=Regra {0} n\u00E3o foi encontrada
90071=Usu\u00E1rio ou regra {0} n\u00E3o foram encontrados
90072=Regras e permiss\u00F5es n\u00E3o podem ser combinados
90073=Permiss\u00E3o n\u00E3o encontrada
90073=\#Matching Java methods must have different parameter counts\: {0} and {1}
90074=Regra {0} j\u00E1 foi concedida
90075=A coluna faz parte do \u00EDndice {0}
90076=Nome alternativo da fun\u00E7\u00E3o {0} j\u00E1 existe
......
......@@ -362,6 +362,8 @@ and may optionally include the parameter classes as in ""java.lang.Integer.parse
Admin rights are required to execute this command.
If the first parameter of the Java function is a java.sql.Connection, then
the current to the database is provided. This connection must not be closed.
Functions may be overloaded, that means multiple functions with the same name may exist.
In this case, each function must have a different parameter count.
","
CREATE ALIAS MY_SQRT FOR ""java.lang.Math.sqrt""
"
......
......@@ -264,6 +264,7 @@ public class MetaTable extends Table {
"ALIAS_NAME",
"JAVA_CLASS",
"JAVA_METHOD",
"COLUMN_COUNT INT",
"POS INT",
"COLUMN_NAME",
"DATA_TYPE INT",
......@@ -990,30 +991,34 @@ public class MetaTable extends Table {
ObjectArray aliases = database.getAllFunctionAliases();
for (int i = 0; i < aliases.size(); i++) {
FunctionAlias alias = (FunctionAlias) aliases.get(i);
int returnsResult = alias.getDataType() == Value.NULL ? DatabaseMetaData.procedureNoResult
: DatabaseMetaData.procedureReturnsResult;
add(rows, new String[] {
// ALIAS_CATALOG
catalog,
// ALIAS_SCHEMA
Constants.SCHEMA_MAIN,
// ALIAS_NAME
identifier(alias.getName()),
// JAVA_CLASS
alias.getJavaClassName(),
// JAVA_METHOD
alias.getJavaMethodName(),
// DATA_TYPE
""+DataType.convertTypeToSQLType(alias.getDataType()),
// COLUMN_COUNT INT
""+ alias.getColumnClasses().length,
// RETURNS_RESULT SMALLINT
""+ returnsResult,
// REMARKS
replaceNullWithEmpty(alias.getComment()),
// ID
"" + alias.getId()
});
FunctionAlias.JavaMethod[] methods = alias.getJavaMethods();
for (int j = 0; j < methods.length; j++) {
FunctionAlias.JavaMethod method = methods[j];
int returnsResult = method.getDataType() == Value.NULL ? DatabaseMetaData.procedureNoResult
: DatabaseMetaData.procedureReturnsResult;
add(rows, new String[] {
// ALIAS_CATALOG
catalog,
// ALIAS_SCHEMA
Constants.SCHEMA_MAIN,
// ALIAS_NAME
identifier(alias.getName()),
// JAVA_CLASS
alias.getJavaClassName(),
// JAVA_METHOD
alias.getJavaMethodName(),
// DATA_TYPE
""+DataType.convertTypeToSQLType(method.getDataType()),
// COLUMN_COUNT INT
""+ method.getColumnClasses().length,
// RETURNS_RESULT SMALLINT
""+ returnsResult,
// REMARKS
replaceNullWithEmpty(alias.getComment()),
// ID
"" + alias.getId()
});
}
}
ObjectArray aggregates = database.getAllAggregates();
for (int i = 0; i < aggregates.size(); i++) {
......@@ -1048,45 +1053,51 @@ public class MetaTable extends Table {
ObjectArray aliases = database.getAllFunctionAliases();
for (int i = 0; i < aliases.size(); i++) {
FunctionAlias alias = (FunctionAlias) aliases.get(i);
Class[] columns = alias.getColumnClasses();
for (int j = 0; j < columns.length; j++) {
Class clazz = columns[j];
int type = DataType.getTypeFromClass(clazz);
DataType dt = DataType.getDataType(type);
int nullable = clazz.isPrimitive() ? DatabaseMetaData.columnNoNulls
: DatabaseMetaData.columnNullable;
add(rows, new String[] {
// ALIAS_CATALOG
catalog,
// ALIAS_SCHEMA
Constants.SCHEMA_MAIN,
// ALIAS_NAME
identifier(alias.getName()),
// JAVA_CLASS
alias.getJavaClassName(),
// JAVA_METHOD
alias.getJavaMethodName(),
// POS INT
"" + j,
// COLUMN_NAME
"P" + (j+1),
// DATA_TYPE
"" + DataType.convertTypeToSQLType(dt.type),
// TYPE_NAME
dt.name,
// PRECISION
"" + dt.defaultPrecision,
// SCALE
"" + dt.defaultScale,
// RADIX
"10",
// NULLABLE SMALLINT
"" + nullable,
// COLUMN_TYPE
"" + DatabaseMetaData.procedureColumnIn,
// REMARKS
""
});
FunctionAlias.JavaMethod[] methods = alias.getJavaMethods();
for (int j = 0; j < methods.length; j++) {
FunctionAlias.JavaMethod method = methods[j];
Class[] columns = method.getColumnClasses();
for (int k = 0; k < columns.length; k++) {
Class clazz = columns[k];
int type = DataType.getTypeFromClass(clazz);
DataType dt = DataType.getDataType(type);
int nullable = clazz.isPrimitive() ? DatabaseMetaData.columnNoNulls
: DatabaseMetaData.columnNullable;
add(rows, new String[] {
// ALIAS_CATALOG
catalog,
// ALIAS_SCHEMA
Constants.SCHEMA_MAIN,
// ALIAS_NAME
identifier(alias.getName()),
// JAVA_CLASS
alias.getJavaClassName(),
// JAVA_METHOD
alias.getJavaMethodName(),
// COLUMN_COUNT
"" + method.getParameterCount(),
// POS INT
"" + k,
// COLUMN_NAME
"P" + (k+1),
// DATA_TYPE
"" + DataType.convertTypeToSQLType(dt.type),
// TYPE_NAME
dt.name,
// PRECISION
"" + dt.defaultPrecision,
// SCALE
"" + dt.defaultScale,
// RADIX
"10",
// NULLABLE SMALLINT
"" + nullable,
// COLUMN_TYPE
"" + DatabaseMetaData.procedureColumnIn,
// REMARKS
""
});
}
}
}
break;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论