Search in sources :

Example 1 with FunctionName

use of org.apache.cassandra.cql3.functions.FunctionName in project cassandra by apache.

the class SchemaKeyspace method createUDAFromRow.

private static UDAggregate createUDAFromRow(UntypedResultSet.Row row, Functions functions, Types types) {
    String ksName = row.getString("keyspace_name");
    String functionName = row.getString("aggregate_name");
    FunctionName name = new FunctionName(ksName, functionName);
    List<AbstractType<?>> argTypes = row.getFrozenList("argument_types", UTF8Type.instance).stream().map(t -> CQLTypeParser.parse(ksName, t, types)).collect(toList());
    AbstractType<?> returnType = CQLTypeParser.parse(ksName, row.getString("return_type"), types);
    FunctionName stateFunc = new FunctionName(ksName, (row.getString("state_func")));
    FunctionName finalFunc = row.has("final_func") ? new FunctionName(ksName, row.getString("final_func")) : null;
    AbstractType<?> stateType = row.has("state_type") ? CQLTypeParser.parse(ksName, row.getString("state_type"), types) : null;
    ByteBuffer initcond = row.has("initcond") ? Terms.asBytes(ksName, row.getString("initcond"), stateType) : null;
    try {
        return UDAggregate.create(functions, name, argTypes, returnType, stateFunc, finalFunc, stateType, initcond);
    } catch (InvalidRequestException reason) {
        return UDAggregate.createBroken(name, argTypes, returnType, initcond, reason);
    }
}
Also used : org.apache.cassandra.config(org.apache.cassandra.config) java.util(java.util) CharacterCodingException(java.nio.charset.CharacterCodingException) org.apache.cassandra.db.marshal(org.apache.cassandra.db.marshal) MessageDigest(java.security.MessageDigest) LoggerFactory(org.slf4j.LoggerFactory) org.apache.cassandra.db(org.apache.cassandra.db) ByteBuffer(java.nio.ByteBuffer) org.apache.cassandra.cql3(org.apache.cassandra.cql3) org.apache.cassandra.db.rows(org.apache.cassandra.db.rows) View(org.apache.cassandra.db.view.View) ImmutableList(com.google.common.collect.ImmutableList) SelectStatement(org.apache.cassandra.cql3.statements.SelectStatement) ColumnFilter(org.apache.cassandra.db.filter.ColumnFilter) ProtocolVersion(org.apache.cassandra.transport.ProtocolVersion) org.apache.cassandra.cql3.functions(org.apache.cassandra.cql3.functions) InvalidRequestException(org.apache.cassandra.exceptions.InvalidRequestException) org.apache.cassandra.db.partitions(org.apache.cassandra.db.partitions) Collectors.toSet(java.util.stream.Collectors.toSet) ClusteringOrder(org.apache.cassandra.schema.ColumnMetadata.ClusteringOrder) Logger(org.slf4j.Logger) FBUtilities(org.apache.cassandra.utils.FBUtilities) ByteBufferUtil(org.apache.cassandra.utils.ByteBufferUtil) QueryProcessor.executeInternal(org.apache.cassandra.cql3.QueryProcessor.executeInternal) Maps(com.google.common.collect.Maps) String.format(java.lang.String.format) QueryProcessor.executeOnceInternal(org.apache.cassandra.cql3.QueryProcessor.executeOnceInternal) TimeUnit(java.util.concurrent.TimeUnit) MapDifference(com.google.common.collect.MapDifference) Collectors.toList(java.util.stream.Collectors.toList) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) CreateTableStatement(org.apache.cassandra.cql3.statements.CreateTableStatement) InvalidRequestException(org.apache.cassandra.exceptions.InvalidRequestException) ByteBuffer(java.nio.ByteBuffer)

Example 2 with FunctionName

use of org.apache.cassandra.cql3.functions.FunctionName in project cassandra by apache.

the class FunctionResolver method get.

/**
     * @param keyspace the current keyspace
     * @param name the name of the function
     * @param providedArgs the arguments provided for the function call
     * @param receiverKs the receiver's keyspace
     * @param receiverCf the receiver's table
     * @param receiverType if the receiver type is known (during inserts, for example), this should be the type of
     *                     the receiver
     * @throws InvalidRequestException
     */
public static Function get(String keyspace, FunctionName name, List<? extends AssignmentTestable> providedArgs, String receiverKs, String receiverCf, AbstractType<?> receiverType) throws InvalidRequestException {
    if (name.equalsNativeFunction(TOKEN_FUNCTION_NAME))
        return new TokenFct(Schema.instance.getTableMetadata(receiverKs, receiverCf));
    // due to needing to know the argument types in advance).
    if (name.equalsNativeFunction(ToJsonFct.NAME))
        throw new InvalidRequestException("toJson() may only be used within the selection clause of SELECT statements");
    // Similarly, we can only use fromJson when we know the receiver type (such as inserts)
    if (name.equalsNativeFunction(FromJsonFct.NAME)) {
        if (receiverType == null)
            throw new InvalidRequestException("fromJson() cannot be used in the selection clause of a SELECT statement");
        return FromJsonFct.getInstance(receiverType);
    }
    Collection<Function> candidates;
    if (!name.hasKeyspace()) {
        // function name not fully qualified
        candidates = new ArrayList<>();
        // add 'SYSTEM' (native) candidates
        candidates.addAll(Schema.instance.getFunctions(name.asNativeFunction()));
        // add 'current keyspace' candidates
        candidates.addAll(Schema.instance.getFunctions(new FunctionName(keyspace, name.name)));
    } else {
        // function name is fully qualified (keyspace + name)
        candidates = Schema.instance.getFunctions(name);
    }
    if (candidates.isEmpty())
        return null;
    // Fast path if there is only one choice
    if (candidates.size() == 1) {
        Function fun = candidates.iterator().next();
        validateTypes(keyspace, fun, providedArgs, receiverKs, receiverCf);
        return fun;
    }
    List<Function> compatibles = null;
    for (Function toTest : candidates) {
        if (matchReturnType(toTest, receiverType)) {
            AssignmentTestable.TestResult r = matchAguments(keyspace, toTest, providedArgs, receiverKs, receiverCf);
            switch(r) {
                case EXACT_MATCH:
                    // We always favor exact matches
                    return toTest;
                case WEAKLY_ASSIGNABLE:
                    if (compatibles == null)
                        compatibles = new ArrayList<>();
                    compatibles.add(toTest);
                    break;
            }
        }
    }
    if (compatibles == null) {
        if (OperationFcts.isOperation(name))
            throw invalidRequest("the '%s' operation is not supported between %s and %s", OperationFcts.getOperator(name), providedArgs.get(0), providedArgs.get(1));
        throw invalidRequest("Invalid call to function %s, none of its type signatures match (known type signatures: %s)", name, format(candidates));
    }
    if (compatibles.size() > 1) {
        if (OperationFcts.isOperation(name)) {
            if (receiverType != null && !containsMarkers(providedArgs)) {
                for (Function toTest : compatibles) {
                    List<AbstractType<?>> argTypes = toTest.argTypes();
                    if (receiverType.equals(argTypes.get(0)) && receiverType.equals(argTypes.get(1)))
                        return toTest;
                }
            }
            throw invalidRequest("Ambiguous '%s' operation: use type casts to disambiguate", OperationFcts.getOperator(name), providedArgs.get(0), providedArgs.get(1));
        }
        if (OperationFcts.isNegation(name))
            throw invalidRequest("Ambiguous negation: use type casts to disambiguate");
        throw invalidRequest("Ambiguous call to function %s (can be matched by following signatures: %s): use type casts to disambiguate", name, format(compatibles));
    }
    return compatibles.get(0);
}
Also used : AssignmentTestable(org.apache.cassandra.cql3.AssignmentTestable) ArrayList(java.util.ArrayList) AbstractType(org.apache.cassandra.db.marshal.AbstractType) InvalidRequestException(org.apache.cassandra.exceptions.InvalidRequestException)

Example 3 with FunctionName

use of org.apache.cassandra.cql3.functions.FunctionName in project cassandra by apache.

the class UFJavaTest method testJavaFunction.

@Test
public void testJavaFunction() throws Throwable {
    createTable("CREATE TABLE %s (key int primary key, val double)");
    String functionBody = '\n' + "  // parameter val is of type java.lang.Double\n" + "  /* return type is of type java.lang.Double */\n" + "  if (val == null) {\n" + "    return null;\n" + "  }\n" + "  return Math.sin(val);\n";
    String fName = createFunction(KEYSPACE, "double", "CREATE OR REPLACE FUNCTION %s(val double) " + "CALLED ON NULL INPUT " + "RETURNS double " + "LANGUAGE JAVA " + "AS '" + functionBody + "';");
    FunctionName fNameName = parseFunctionName(fName);
    assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?", fNameName.keyspace, fNameName.name), row("java", functionBody));
    execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
    execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
    execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
    assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"), row(1, 1d, Math.sin(1d)), row(2, 2d, Math.sin(2d)), row(3, 3d, Math.sin(3d)));
}
Also used : FunctionName(org.apache.cassandra.cql3.functions.FunctionName) Test(org.junit.Test)

Example 4 with FunctionName

use of org.apache.cassandra.cql3.functions.FunctionName in project cassandra by apache.

the class UFScriptTest method testJavascriptFunction.

@Test
public void testJavascriptFunction() throws Throwable {
    createTable("CREATE TABLE %s (key int primary key, val double)");
    String functionBody = '\n' + "  Math.sin(val);\n";
    String fName = createFunction(KEYSPACE, "double", "CREATE OR REPLACE FUNCTION %s(val double) " + "RETURNS NULL ON NULL INPUT " + "RETURNS double " + "LANGUAGE javascript\n" + "AS '" + functionBody + "';");
    FunctionName fNameName = parseFunctionName(fName);
    assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?", fNameName.keyspace, fNameName.name), row("javascript", functionBody));
    execute("INSERT INTO %s (key, val) VALUES (?, ?)", 1, 1d);
    execute("INSERT INTO %s (key, val) VALUES (?, ?)", 2, 2d);
    execute("INSERT INTO %s (key, val) VALUES (?, ?)", 3, 3d);
    assertRows(execute("SELECT key, val, " + fName + "(val) FROM %s"), row(1, 1d, Math.sin(1d)), row(2, 2d, Math.sin(2d)), row(3, 3d, Math.sin(3d)));
}
Also used : FunctionName(org.apache.cassandra.cql3.functions.FunctionName) Test(org.junit.Test)

Example 5 with FunctionName

use of org.apache.cassandra.cql3.functions.FunctionName in project cassandra by apache.

the class UFTest method testFunctionDropPreparedStatement.

@Test
public void testFunctionDropPreparedStatement() throws Throwable {
    createTable("CREATE TABLE %s (key int PRIMARY KEY, d double)");
    String fSin = createFunction(KEYSPACE_PER_TEST, "double", "CREATE FUNCTION %s ( input double ) " + "CALLED ON NULL INPUT " + "RETURNS double " + "LANGUAGE java " + "AS 'return Double.valueOf(Math.sin(input.doubleValue()));'");
    FunctionName fSinName = parseFunctionName(fSin);
    Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fSin)).size());
    // create a pairs of Select and Inserts. One statement in each pair uses the function so when we
    // drop it those statements should be removed from the cache in QueryProcessor. The other statements
    // should be unaffected.
    ResultMessage.Prepared preparedSelect1 = QueryProcessor.prepare(String.format("SELECT key, %s(d) FROM %s.%s", fSin, KEYSPACE, currentTable()), ClientState.forInternalCalls());
    ResultMessage.Prepared preparedSelect2 = QueryProcessor.prepare(String.format("SELECT key FROM %s.%s", KEYSPACE, currentTable()), ClientState.forInternalCalls());
    ResultMessage.Prepared preparedInsert1 = QueryProcessor.prepare(String.format("INSERT INTO %s.%s (key, d) VALUES (?, %s(?))", KEYSPACE, currentTable(), fSin), ClientState.forInternalCalls());
    ResultMessage.Prepared preparedInsert2 = QueryProcessor.prepare(String.format("INSERT INTO %s.%s (key, d) VALUES (?, ?)", KEYSPACE, currentTable()), ClientState.forInternalCalls());
    Assert.assertNotNull(QueryProcessor.instance.getPrepared(preparedSelect1.statementId));
    Assert.assertNotNull(QueryProcessor.instance.getPrepared(preparedSelect2.statementId));
    Assert.assertNotNull(QueryProcessor.instance.getPrepared(preparedInsert1.statementId));
    Assert.assertNotNull(QueryProcessor.instance.getPrepared(preparedInsert2.statementId));
    execute("DROP FUNCTION " + fSin + "(double);");
    // the statements which use the dropped function should be removed from cache, with the others remaining
    Assert.assertNull(QueryProcessor.instance.getPrepared(preparedSelect1.statementId));
    Assert.assertNotNull(QueryProcessor.instance.getPrepared(preparedSelect2.statementId));
    Assert.assertNull(QueryProcessor.instance.getPrepared(preparedInsert1.statementId));
    Assert.assertNotNull(QueryProcessor.instance.getPrepared(preparedInsert2.statementId));
    execute("CREATE FUNCTION " + fSin + " ( input double ) " + "RETURNS NULL ON NULL INPUT " + "RETURNS double " + "LANGUAGE java " + "AS 'return Double.valueOf(Math.sin(input));'");
    Assert.assertEquals(1, Schema.instance.getFunctions(fSinName).size());
    preparedSelect1 = QueryProcessor.prepare(String.format("SELECT key, %s(d) FROM %s.%s", fSin, KEYSPACE, currentTable()), ClientState.forInternalCalls());
    preparedInsert1 = QueryProcessor.prepare(String.format("INSERT INTO %s.%s (key, d) VALUES (?, %s(?))", KEYSPACE, currentTable(), fSin), ClientState.forInternalCalls());
    Assert.assertNotNull(QueryProcessor.instance.getPrepared(preparedSelect1.statementId));
    Assert.assertNotNull(QueryProcessor.instance.getPrepared(preparedInsert1.statementId));
    dropPerTestKeyspace();
    // again, only the 2 statements referencing the function should be removed from cache
    // this time because the statements select from tables in KEYSPACE, only the function
    // is scoped to KEYSPACE_PER_TEST
    Assert.assertNull(QueryProcessor.instance.getPrepared(preparedSelect1.statementId));
    Assert.assertNotNull(QueryProcessor.instance.getPrepared(preparedSelect2.statementId));
    Assert.assertNull(QueryProcessor.instance.getPrepared(preparedInsert1.statementId));
    Assert.assertNotNull(QueryProcessor.instance.getPrepared(preparedInsert2.statementId));
}
Also used : FunctionName(org.apache.cassandra.cql3.functions.FunctionName) ResultMessage(org.apache.cassandra.transport.messages.ResultMessage) Test(org.junit.Test)

Aggregations

FunctionName (org.apache.cassandra.cql3.functions.FunctionName)9 Test (org.junit.Test)9 InvalidRequestException (org.apache.cassandra.exceptions.InvalidRequestException)3 ArrayList (java.util.ArrayList)2 AbstractType (org.apache.cassandra.db.marshal.AbstractType)2 ResultMessage (org.apache.cassandra.transport.messages.ResultMessage)2 ImmutableList (com.google.common.collect.ImmutableList)1 MapDifference (com.google.common.collect.MapDifference)1 Maps (com.google.common.collect.Maps)1 String.format (java.lang.String.format)1 ByteBuffer (java.nio.ByteBuffer)1 CharacterCodingException (java.nio.charset.CharacterCodingException)1 MessageDigest (java.security.MessageDigest)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 java.util (java.util)1 TimeUnit (java.util.concurrent.TimeUnit)1 Collectors.toList (java.util.stream.Collectors.toList)1 Collectors.toSet (java.util.stream.Collectors.toSet)1 org.apache.cassandra.config (org.apache.cassandra.config)1 org.apache.cassandra.cql3 (org.apache.cassandra.cql3)1