public static FunctionExecutionException create(Function function, Throwable cause) { List<String> cqlTypes = AbstractType.asCQLTypeStringList(function.argTypes()); FunctionExecutionException fee = new FunctionExecutionException(function.name(), cqlTypes, cause.toString()); fee.initCause(cause); return fee; }
public Selector.Factory newSelectorFactory(CFMetaData cfm, AbstractType<?> expectedType, List<ColumnDefinition> defs, VariableSpecifications boundNames) { SelectorFactories factories = SelectorFactories.createFactoriesAndCollectColumnDefinitions(args, function.argTypes(), cfm, defs, boundNames); //lookup first for generic function taking arbitrary types Function fun = GenericFunctionRegistry.getInstance(function.name(), factories.getReturnTypes()); if (fun == null) fun = FunctionResolver.get(cfm.ksName, function.name(), args, cfm.ksName, cfm.cfName, null); if (fun == null) throw new InvalidRequestException(String.format("Unknown function '%s'", function.name())); if (fun.returnType() == null) throw new InvalidRequestException(String.format("Unknown function %s called in selection clause", function.name())); return AbstractFunctionSelector.newFactory(function, factories); }
public void addFunctionsTo(List<Function> functions) { fun.addFunctionsTo(functions); factories.addFunctionsTo(functions); }
public void ensureHasPermission(Permission permission, Function function) { // Save creating a FunctionResource is we don't need to if (!DatabaseDescriptor.getAuthorizer().requireAuthorization()) return; // built in functions are always available to all if (function.isNative()) return; checkPermissionOnResourceChain(permission, FunctionResource.function(function.name().keyspace, function.name().name, function.argTypes())); }
private static String signature(Function fun) { List<AbstractType<?>> args = fun.argsType(); StringBuilder sb = new StringBuilder(); sb.append("("); for (int i = 0; i < args.size(); i++) { if (i > 0) sb.append(", "); sb.append(args.get(i).asCQL3Type()); } sb.append(") -> "); sb.append(fun.returnType().asCQL3Type()); return sb.toString(); }
public Builder add(Function fun) { functions.put(fun.name(), fun); return this; }
public AbstractType<?> getType() { return fun.returnType(); }
public AssignmentTestable.TestResult testAssignment(String keyspace, ColumnSpecification receiver) { // Note: Functions.get() will return null if the function doesn't exist, or throw is no function matching // the arguments can be found. We may get one of those if an undefined/wrong function is used as argument // of another, existing, function. In that case, we return true here because we'll throw a proper exception // later with a more helpful error message that if we were to return false here. try { Function fun = FunctionResolver.get(keyspace, name, terms, receiver.ksName, receiver.cfName, receiver.type); // Because fromJson() can return whatever type the receiver is, we'll always get EXACT_MATCH. To // handle potentially ambiguous function calls with fromJson() as an argument, always return // WEAKLY_ASSIGNABLE to force the user to typecast if necessary if (fun != null && fun.name().equals(FromJsonFct.NAME)) return TestResult.WEAKLY_ASSIGNABLE; if (fun != null && receiver.type.equals(fun.returnType())) return AssignmentTestable.TestResult.EXACT_MATCH; else if (fun == null || receiver.type.isValueCompatibleWith(fun.returnType())) return AssignmentTestable.TestResult.WEAKLY_ASSIGNABLE; else return AssignmentTestable.TestResult.NOT_ASSIGNABLE; } catch (InvalidRequestException e) { return AssignmentTestable.TestResult.WEAKLY_ASSIGNABLE; } }
private static void validateTypes(String keyspace, Function fun, List<? extends AssignementTestable> providedArgs, ColumnSpecification receiver) throws InvalidRequestException { if (!receiver.type.isValueCompatibleWith(fun.returnType())) throw new InvalidRequestException(String.format("Type error: cannot assign result of function %s (type %s) to %s (type %s)", fun.name(), fun.returnType().asCQL3Type(), receiver, receiver.type.asCQL3Type())); if (providedArgs.size() != fun.argsType().size()) throw new InvalidRequestException(String.format("Invalid number of arguments in call to function %s: %d required but %d provided", fun.name(), fun.argsType().size(), providedArgs.size())); for (int i = 0; i < providedArgs.size(); i++) { AssignementTestable provided = providedArgs.get(i); // If the concrete argument is a bind variables, it can have any type. // We'll validate the actually provided value at execution time. if (provided == null) continue; ColumnSpecification expected = makeArgSpec(receiver, fun, i); if (!provided.isAssignableTo(keyspace, expected)) throw new InvalidRequestException(String.format("Type error: %s cannot be passed as argument %d of function %s of type %s", provided, i, fun.name(), expected.type.asCQL3Type())); } }
public Term prepare(String keyspace, ColumnSpecification receiver) throws InvalidRequestException { Function fun = FunctionResolver.get(keyspace, name, terms, receiver.ksName, receiver.cfName, receiver.type); if (fun == null) throw new InvalidRequestException(String.format("Unknown function %s called", name)); if (fun.isAggregate()) throw new InvalidRequestException("Aggregation function are not supported in the where clause"); ScalarFunction scalarFun = (ScalarFunction) fun; // Functions.get() will complain if no function "name" type check with the provided arguments. // We still have to validate that the return type matches however if (!scalarFun.testAssignment(keyspace, receiver).isAssignable()) throw new InvalidRequestException(String.format("Type error: cannot assign result of function %s (type %s) to %s (type %s)", scalarFun.name(), scalarFun.returnType().asCQL3Type(), receiver.name, receiver.type.asCQL3Type())); if (fun.argTypes().size() != terms.size()) throw new InvalidRequestException(String.format("Incorrect number of arguments specified for function %s (expected %d, found %d)", fun, fun.argTypes().size(), terms.size())); List<Term> parameters = new ArrayList<>(terms.size()); for (int i = 0; i < terms.size(); i++) { Term t = terms.get(i).prepare(keyspace, FunctionResolver.makeArgSpec(receiver.ksName, receiver.cfName, scalarFun, i)); parameters.add(t); } return new FunctionCall(scalarFun, parameters); }
public Event.SchemaChange announceMigration(QueryState queryState, boolean isLocalOnly) throws RequestValidationException { Function old = Schema.instance.findFunction(functionName, argTypes).orElse(null); boolean replaced = old != null; if (replaced) { if (ifNotExists) return null; if (!orReplace) throw new InvalidRequestException(String.format("Function %s already exists", old)); if (!(old instanceof AggregateFunction)) throw new InvalidRequestException(String.format("Aggregate %s can only replace an aggregate", old)); // Means we're replacing the function. We still need to validate that 1) it's not a native function and 2) that the return type // matches (or that could break existing code badly) if (old.isNative()) throw new InvalidRequestException(String.format("Cannot replace native aggregate %s", old)); if (!old.returnType().isValueCompatibleWith(returnType)) throw new InvalidRequestException(String.format("Cannot replace aggregate %s, the new return type %s is not compatible with the return type %s of existing function", functionName, returnType.asCQL3Type(), old.returnType().asCQL3Type())); } if (!stateFunction.isCalledOnNullInput() && initcond == null) throw new InvalidRequestException(String.format("Cannot create aggregate %s without INITCOND because state function %s does not accept 'null' arguments", functionName, stateFunc)); UDAggregate udAggregate = new UDAggregate(functionName, argTypes, returnType, stateFunction, finalFunction, initcond); MigrationManager.announceNewAggregate(udAggregate, isLocalOnly); return new Event.SchemaChange(replaced ? Event.SchemaChange.Change.UPDATED : Event.SchemaChange.Change.CREATED, Event.SchemaChange.Target.AGGREGATE, udAggregate.name().keyspace, udAggregate.name().name, AbstractType.asCQLTypeStringList(udAggregate.argTypes())); }
/** * Find the function with the specified name * * @param name fully qualified function name * @param argTypes function argument types * @return an empty {@link Optional} if the function name is not found; a non-empty optional of {@link Function} otherwise */ public Optional<Function> find(FunctionName name, List<AbstractType<?>> argTypes) { return get(name).stream() .filter(fun -> typesMatch(fun.argTypes(), argTypes)) .findAny(); }
public boolean isAggregateSelectorFactory() { return fun.isAggregate() || factories.doesAggregation(); } };
if (function.returnType().referencesUserType(name.getStringTypeName())) throw new InvalidRequestException(String.format("Cannot drop user type %s as it is still used by function %s", name, function)); for (AbstractType<?> argType : function.argTypes()) if (argType.referencesUserType(name.getStringTypeName())) throw new InvalidRequestException(String.format("Cannot drop user type %s as it is still used by function %s", name, function));
private static ByteBuffer executeInternal(Function fun, List<ByteBuffer> params) throws InvalidRequestException { ByteBuffer result = fun.execute(params); try { // Check the method didn't lied on it's declared return type if (result != null) fun.returnType().validate(result); return result; } catch (MarshalException e) { throw new RuntimeException(String.format("Return of function %s (%s) is not a valid value for its declared return type %s", fun, ByteBufferUtil.bytesToHex(result), fun.returnType().asCQL3Type())); } }
protected String getColumnName() { return fun.columnName(factories.getColumnNames()); }
public void ensureHasPermission(Permission permission, Function function) { // Save creating a FunctionResource is we don't need to if (!DatabaseDescriptor.getAuthorizer().requireAuthorization()) return; // built in functions are always available to all if (function.isNative()) return; checkPermissionOnResourceChain(permission, FunctionResource.function(function.name().keyspace, function.name().name, function.argTypes())); }
public Builder add(Function fun) { functions.put(fun.name(), fun); return this; }
protected AbstractType<?> getReturnType() { return fun.returnType(); }