ttomcat-1778514358873.zip-extract/_dependencies/maven/com.h2database_h2-2.2.220/org/h2/schema/FunctionAlias.java

Path
ttomcat-1778514358873.zip-extract/_dependencies/maven/com.h2database_h2-2.2.220/org/h2/schema/FunctionAlias.java
Status
scanned
Type
file
Name
FunctionAlias.java
Extension
.java
Programming language
Java
Mime type
text/x-java
File type
Java source, ASCII text
Tag

      
    
Rootfs path

      
    
Size
20877 (20.4 KB)
MD5
6144c11952cd51a064d802a60e5e2c91
SHA1
50c983a4885f259356d254aed31402e141c78e28
SHA256
e51499a9e07e8cefae6840cc90bb3aef5ead9d825c25c588690161f2462f3b79
SHA512

      
    
SHA1_git
fc4a5cbd7a084106f0c24e9f1b1d09cd45481791
Is binary

      
    
Is text
True
Is archive

      
    
Is media

      
    
Is legal

      
    
Is manifest

      
    
Is readme

      
    
Is top level

      
    
Is key file

      
    
FunctionAlias.java | 20.4 KB |

/* * Copyright 2004-2023 H2 Group. Multiple-Licensed under the MPL 2.0, * and the EPL 1.0 (https://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.schema; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.sql.Connection; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import org.h2.Driver; import org.h2.api.ErrorCode; import org.h2.engine.Constants; import org.h2.engine.DbObject; import org.h2.engine.SessionLocal; import org.h2.expression.Alias; import org.h2.expression.Expression; import org.h2.expression.ExpressionColumn; import org.h2.jdbc.JdbcConnection; import org.h2.message.DbException; import org.h2.message.Trace; import org.h2.result.LocalResult; import org.h2.result.ResultInterface; import org.h2.table.Column; import org.h2.util.JdbcUtils; import org.h2.util.SourceCompiler; import org.h2.util.StringUtils; import org.h2.util.Utils; import org.h2.value.DataType; import org.h2.value.TypeInfo; import org.h2.value.Value; import org.h2.value.ValueNull; import org.h2.value.ValueToObjectConverter; import org.h2.value.ValueToObjectConverter2; /** * Represents a user-defined function, or alias. * * @author Thomas Mueller * @author Gary Tong */ public final class FunctionAlias extends UserDefinedFunction { private String methodName; private String source; private JavaMethod[] javaMethods; private boolean deterministic; private FunctionAlias(Schema schema, int id, String name) { super(schema, id, name, Trace.FUNCTION); } /** * Create a new alias based on a method name. * * @param schema the schema * @param id the id * @param name the name * @param javaClassMethod the class and method name * @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) { FunctionAlias alias = new FunctionAlias(schema, id, name); int paren = javaClassMethod.indexOf('('); int lastDot = javaClassMethod.lastIndexOf('.', paren < 0 ? javaClassMethod.length() : paren); if (lastDot < 0) { throw DbException.get(ErrorCode.SYNTAX_ERROR_1, javaClassMethod); } alias.className = javaClassMethod.substring(0, lastDot); alias.methodName = javaClassMethod.substring(lastDot + 1); alias.init(force); return alias; } /** * Create a new alias based on source code. * * @param schema the schema * @param id the id * @param name the name * @param source the source code * @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) { FunctionAlias alias = new FunctionAlias(schema, id, name); alias.source = source; alias.init(force); return alias; } private void init(boolean force) { try { // at least try to compile the class, otherwise the data type is not // initialized if it could be load(); } catch (DbException e) { if (!force) { throw e; } } } private synchronized void load() { if (javaMethods != null) { return; } if (source != null) { loadFromSource(); } else { loadClass(); } } private void loadFromSource() { SourceCompiler compiler = database.getCompiler(); synchronized (compiler) { String fullClassName = Constants.USER_PACKAGE + "." + getName(); compiler.setSource(fullClassName, source); try { Method m = compiler.getMethod(fullClassName); JavaMethod method = new JavaMethod(m, 0); javaMethods = new JavaMethod[] { method }; } catch (DbException e) { throw e; } catch (Exception e) { throw DbException.get(ErrorCode.SYNTAX_ERROR_1, e, source); } } } private void loadClass() { Class<?> javaClass = JdbcUtils.loadUserClass(className); Method[] methods = javaClass.getMethods(); ArrayList<JavaMethod> list = new ArrayList<>(1); for (int i = 0, len = methods.length; i < len; i++) { Method m = methods[i]; if (!Modifier.isStatic(m.getModifiers())) { continue; } if (m.getName().equals(methodName) || getMethodSignature(m).equals(methodName)) { JavaMethod javaMethod = new JavaMethod(m, i); for (JavaMethod old : list) { if (old.getParameterCount() == javaMethod.getParameterCount()) { throw DbException.get(ErrorCode. METHODS_MUST_HAVE_DIFFERENT_PARAMETER_COUNTS_2, old.toString(), javaMethod.toString()); } } list.add(javaMethod); } } if (list.isEmpty()) { throw DbException.get( ErrorCode.PUBLIC_STATIC_JAVA_METHOD_NOT_FOUND_1, methodName + " (" + className + ")"); } javaMethods = list.toArray(new JavaMethod[0]); // Sort elements. Methods with a variable number of arguments must be at // the end. Reason: there could be one method without parameters and one // with a variable number. The one without parameters needs to be used // if no parameters are given. Arrays.sort(javaMethods); } private static String getMethodSignature(Method m) { StringBuilder buff = new StringBuilder(m.getName()); buff.append('('); Class<?>[] parameterTypes = m.getParameterTypes(); for (int i = 0, length = parameterTypes.length; i < length; i++) { if (i > 0) { // do not use a space here, because spaces are removed // in CreateFunctionAlias.setJavaClassMethod() buff.append(','); } Class<?> p = parameterTypes[i]; if (p.isArray()) { buff.append(p.getComponentType().getName()).append("[]"); } else { buff.append(p.getName()); } } return buff.append(')').toString(); } @Override public String getDropSQL() { return getSQL(new StringBuilder("DROP ALIAS IF EXISTS "), DEFAULT_SQL_FLAGS).toString(); } @Override public String getCreateSQL() { StringBuilder builder = new StringBuilder("CREATE FORCE ALIAS "); getSQL(builder, DEFAULT_SQL_FLAGS); if (deterministic) { builder.append(" DETERMINISTIC"); } if (source != null) { StringUtils.quoteStringSQL(builder.append(" AS "), source); } else { StringUtils.quoteStringSQL(builder.append(" FOR "), className + '.' + methodName); } return builder.toString(); } @Override public int getType() { return DbObject.FUNCTION_ALIAS; } @Override public synchronized void removeChildrenAndResources(SessionLocal session) { database.removeMeta(session, getId()); className = null; methodName = null; javaMethods = null; invalidate(); } /** * Find the Java method that matches the arguments. * * @param args the argument list * @return the Java method * @throws DbException if no matching method could be found */ public JavaMethod findJavaMethod(Expression[] args) { load(); int parameterCount = args.length; for (JavaMethod m : javaMethods) { int count = m.getParameterCount(); if (count == parameterCount || (m.isVarArgs() && count <= parameterCount + 1)) { return m; } } throw DbException.get(ErrorCode.METHOD_NOT_FOUND_1, getName() + " (" + className + ", parameter count: " + parameterCount + ")"); } public String getJavaMethodName() { return this.methodName; } /** * Get the Java methods mapped by this function. * * @return the Java methods. */ public JavaMethod[] getJavaMethods() { load(); return javaMethods; } public void setDeterministic(boolean deterministic) { this.deterministic = deterministic; } public boolean isDeterministic() { return deterministic; } public String getSource() { return source; } /** * There may be multiple Java methods that match a function name. * Each method must have a different number of parameters however. * This helper class represents one such method. */ public static class JavaMethod implements Comparable<JavaMethod> { private final int id; private final Method method; private final TypeInfo dataType; private boolean hasConnectionParam; private boolean varArgs; private Class<?> varArgClass; private int paramCount; JavaMethod(Method method, int id) { this.method = method; this.id = id; Class<?>[] paramClasses = method.getParameterTypes(); paramCount = paramClasses.length; if (paramCount > 0) { Class<?> paramClass = paramClasses[0]; if (Connection.class.isAssignableFrom(paramClass)) { hasConnectionParam = true; paramCount--; } } if (paramCount > 0) { Class<?> lastArg = paramClasses[paramClasses.length - 1]; if (lastArg.isArray() && method.isVarArgs()) { varArgs = true; varArgClass = lastArg.getComponentType(); } } Class<?> returnClass = method.getReturnType(); dataType = ResultSet.class.isAssignableFrom(returnClass) ? null : ValueToObjectConverter2.classToType(returnClass); } @Override public String toString() { return method.toString(); } /** * Check if this function requires a database connection. * * @return if the function requires a connection */ public boolean hasConnectionParam() { return this.hasConnectionParam; } /** * Call the user-defined function and return the value. * * @param session the session * @param args the argument list * @param columnList true if the function should only return the column * list * @return the value */ public Value getValue(SessionLocal session, Expression[] args, boolean columnList) { Object returnValue = execute(session, args, columnList); if (Value.class.isAssignableFrom(method.getReturnType())) { return (Value) returnValue; } return ValueToObjectConverter.objectToValue(session, returnValue, dataType.getValueType()) .convertTo(dataType, session); } /** * Call the table user-defined function and return the value. * * @param session the session * @param args the argument list * @param columnList true if the function should only return the column * list * @return the value */ public ResultInterface getTableValue(SessionLocal session, Expression[] args, boolean columnList) { Object o = execute(session, args, columnList); if (o == null) { throw DbException.get(ErrorCode.FUNCTION_MUST_RETURN_RESULT_SET_1, method.getName()); } if (ResultInterface.class.isAssignableFrom(method.getReturnType())) { return (ResultInterface) o; } return resultSetToResult(session, (ResultSet) o, columnList ? 0 : Integer.MAX_VALUE); } /** * Create a result for the given result set. * * @param session the session * @param resultSet the result set * @param maxrows the maximum number of rows to read (0 to just read the * meta data) * @return the value */ public static ResultInterface resultSetToResult(SessionLocal session, ResultSet resultSet, int maxrows) { try (ResultSet rs = resultSet) { ResultSetMetaData meta = rs.getMetaData(); int columnCount = meta.getColumnCount(); Expression[] columns = new Expression[columnCount]; for (int i = 0; i < columnCount; i++) { String alias = meta.getColumnLabel(i + 1); String name = meta.getColumnName(i + 1); String columnTypeName = meta.getColumnTypeName(i + 1); int columnType = DataType.convertSQLTypeToValueType(meta.getColumnType(i + 1), columnTypeName); int precision = meta.getPrecision(i + 1); int scale = meta.getScale(i + 1); TypeInfo typeInfo; if (columnType == Value.ARRAY && columnTypeName.endsWith(" ARRAY")) { typeInfo = TypeInfo .getTypeInfo(Value.ARRAY, -1L, 0, TypeInfo.getTypeInfo(DataType.getTypeByName( columnTypeName.substring(0, columnTypeName.length() - 6), session.getMode()).type)); } else { typeInfo = TypeInfo.getTypeInfo(columnType, precision, scale, null); } Expression e = new ExpressionColumn(session.getDatabase(), new Column(name, typeInfo)); if (!alias.equals(name)) { e = new Alias(e, alias, false); } columns[i] = e; } LocalResult result = new LocalResult(session, columns, columnCount, columnCount); for (int i = 0; i < maxrows && rs.next(); i++) { Value[] list = new Value[columnCount]; for (int j = 0; j < columnCount; j++) { list[j] = ValueToObjectConverter.objectToValue(session, rs.getObject(j + 1), columns[j].getType().getValueType()); } result.addRow(list); } result.done(); return result; } catch (SQLException e) { throw DbException.convert(e); } } private Object execute(SessionLocal session, Expression[] args, boolean columnList) { Class<?>[] paramClasses = method.getParameterTypes(); Object[] params = new Object[paramClasses.length]; int p = 0; JdbcConnection conn = session.createConnection(columnList); if (hasConnectionParam && params.length > 0) { params[p++] = conn; } // allocate array for varArgs parameters Object varArg = null; if (varArgs) { int len = args.length - params.length + 1 + (hasConnectionParam ? 1 : 0); varArg = Array.newInstance(varArgClass, len); params[params.length - 1] = varArg; } for (int a = 0, len = args.length; a < len; a++, p++) { boolean currentIsVarArg = varArgs && p >= paramClasses.length - 1; Class<?> paramClass; if (currentIsVarArg) { paramClass = varArgClass; } else { paramClass = paramClasses[p]; } Value v = args[a].getValue(session); Object o; if (Value.class.isAssignableFrom(paramClass)) { o = v; } else { boolean primitive = paramClass.isPrimitive(); if (v == ValueNull.INSTANCE) { if (primitive) { if (columnList) { // If the column list is requested, the parameters // may be null. Need to set to default value, // otherwise the function can't be called at all. o = DataType.getDefaultForPrimitiveType(paramClass); } else { // NULL for a java primitive: return NULL return null; } } else { o = null; } } else { o = ValueToObjectConverter.valueToObject( (Class<?>) (primitive ? Utils.getNonPrimitiveClass(paramClass) : paramClass), v, conn); } } if (currentIsVarArg) { Array.set(varArg, p - params.length + 1, o); } else { params[p] = o; } } boolean old = session.getAutoCommit(); Value identity = session.getLastIdentity(); boolean defaultConnection = session.getDatabase(). getSettings().defaultConnection; try { session.setAutoCommit(false); Object returnValue; try { if (defaultConnection) { Driver.setDefaultConnection(session.createConnection(columnList)); } returnValue = method.invoke(null, params); if (returnValue == null) { return null; } } catch (InvocationTargetException e) { StringBuilder builder = new StringBuilder(method.getName()).append('('); for (int i = 0, length = params.length; i < length; i++) { if (i > 0) { builder.append(", "); } builder.append(params[i]); } builder.append(')'); throw DbException.convertInvocation(e, builder.toString()); } catch (Exception e) { throw DbException.convert(e); } return returnValue; } finally { session.setLastIdentity(identity); session.setAutoCommit(old); if (defaultConnection) { Driver.setDefaultConnection(null); } } } public Class<?>[] getColumnClasses() { return method.getParameterTypes(); } /** * Returns data type information for regular functions or {@code null} * for table value functions. * * @return data type information for regular functions or {@code null} * for table value functions */ public TypeInfo getDataType() { return dataType; } public int getParameterCount() { return paramCount; } public boolean isVarArgs() { return varArgs; } @Override public int compareTo(JavaMethod m) { if (varArgs != m.varArgs) { return varArgs ? 1 : -1; } if (paramCount != m.paramCount) { return paramCount - m.paramCount; } if (hasConnectionParam != m.hasConnectionParam) { return hasConnectionParam ? 1 : -1; } return id - m.id; } } }
Detected license expression

      
    
Detected license expression (SPDX)

      
    
Percentage of license text
0.63
Copyrights
- end_line: 2
  copyright: Copyright 2004-2023 H2 Group. Multiple-Licensed
  start_line: 2
Holders
- holder: H2 Group. Multiple-Licensed
  end_line: 2
  start_line: 2
Authors
- author: Thomas Mueller
  end_line: 47
  start_line: 47
- author: Gary Tong
  end_line: 48
  start_line: 48
License expression License clue details
(mpl-2.0 OR epl-1.0) AND proprietary-license {'score': 20.37, 'matcher': '3-seq', 'end_line': 3, 'rule_url': 'https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/mpl-2.0_or_epl-1.0_and_proprietary-license_2.RULE', 'from_file': None, 'start_line': 2, 'matched_text': ' * Copyright 2004-2023 H2 Group. Multiple-Licensed under the MPL 2.0,\n * and the EPL 1.0 (https://h2database.com/html/license.html).', 'match_coverage': 20.37, 'matched_length': 11, 'rule_relevance': 100, 'rule_identifier': 'mpl-2.0_or_epl-1.0_and_proprietary-license_2.RULE', 'license_expression': '(mpl-2.0 OR epl-1.0) AND proprietary-license', 'license_expression_spdx': '(MPL-2.0 OR EPL-1.0) AND LicenseRef-scancode-proprietary-license'}
URL Start line End line
https://h2database.com/html/license.html 3 3
Package URL License Primary language
pkg:osgi/com.h2database.source@2.2.220