[ 
https://issues.apache.org/jira/browse/CASSANDRA-7395?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14056291#comment-14056291
 ] 

Robert Stupp commented on CASSANDRA-7395:
-----------------------------------------

I like the approach to define (and code as supposed in CASSANDRA-7526) UDFs 
directly in CQL although it requires to add UDFs to the system keyspace and 
implicitly require schema agreement like tables, indexes, UDT etc. 
And if we agree that CASSANDRA-7526 is the way to do it right, then we must 
agree that Java 8 is required for C* 3.0 (except for the "pure Java" idea 
below).

Using something like {{CREATE FUNCTION sum(a bigint, b bigint) AS ( return a + 
b; )}} is much easier to understand and to maintain than {{AS 
foo.bar.Class.method}}. Bundles could be implemented like this:
{noformat}
CREATE BUNDLE Math AS (
  FUNCTION sum(a bigint, b bigint) {
    return a + b;
  }
);
{noformat}
But in opposite to use Nashorn in the first step, it would be possible to use 
"plain" Java code using [Apache 
BCEL|https://commons.apache.org/proper/commons-bcel/] which does not have the 
Java8 requirement. Adding the language as a parameter could look like 
{{FUNCTION sum(a bigint, b bigint) AS JAVA ...}} or {{AS JAVASCRIPT}} or Groovy 
or whatever.

The _deterministic_ option was intended for use of UDFs in functional indexes - 
functional indexes require deterministic methods whereas "normal" execution 
does not require deterministic functions. So I'd like to keep this flag even in 
{{CREATE FUNCTION}} or {{CREATE BUNDLE ... FUNCTION}} syntax, but assume 
deterministic or non-deterministic as a default.

As a conclusion a bundle in CQL syntax using BCEL could look like this:
{noformat}
CREATE OR UPDATE BUNDLE MyUDFs (
    FUNCTION double sin(input double) AS JAVA {
        return input == null ? null : Math.sin(input);
    }

    FUNCTION float sin(input float) AS JAVA {
        return input == null ? null : Math.sin(input);
    }

    NON DETERMINISTIC FUNCTION double random() AS JAVA {
        return Math.random();
    }
)
{noformat}

But we should keep some "backdoor" to pass the raw blob for a UDF - 
{{fooToBlob}} sounds straightforward, if it's cheap. If it's not cheap, it's 
just possible and if demand is there, we can add a special "raw" wildcard type 
for UDF parameters later.

UDFs could be held in a table : 
{noformat}
CREATE TABLE system.user_functions (
   bundle       text,       -- bundle name
   signature    text,       -- function name + argument types ; might be a MD5 
hash of these
   name         text,       -- function name
   arguments    list<text>, -- list of CQL argument types
   return_type  text,       -- CQL return type
   language     text,       -- programming language
   body         text        -- code
   PRIMARY KEY ( ( bundle ), signature )
);
{noformat}

Altogether this one does not expose internals to UDFs and using/porting 
{{DataType}} + {{TypeCodec}} + {{CassandraTypeParser}} from the Java Driver to 
parse "complex" CQL types is not a big deal - primitive types can be easily 
parsed using the {{CQL3Type.Native.valueOf(parsedTypeDef.toUpperCase())}}.

As a "marketing bullet list" :
* pure CQL functionality
* no C* internals exposed
* support for "pure Java" plus scripting languages
* type raw representation support (using {{fooToBlob}})
* no periodic polling of filesystem or system tables
* UDFs distributed "transparently" using schema agreement
* no tooling necessary - cqlsh and everything that supports CQL is enough
* UDF development help could be integrated for example in "DevCenter" that 
would itself compile a UDF bundle and allows test / execution of individual 
functions - since it's based on Eclipse it might be possible even to "debug" 
UDFs in Java and Nashorn supported scripting languages - but that's stuff for 
another ticket...
* Access rules can be enforced using Java {{SecureClassLoader}} (UDF invocation 
surrounded with {{Thread.setContextClassLoader(...)}})

Drawbacks:
* no official support to use external code
* cluster schema agreement on UDFs necessary
* changes of UDF bundles force compilation on each node - but that should not 
be a big issue since UDFs should be small and efficient - they are not "full 
blown libraries"

I'm still not sure whether prepared statements must be invalidated if the 
bundle changes. As long as a UDF with the same signature exists execution can 
continue - and if the bundle/function is removed, execution will fail (which is 
ok).

Yes - I really like the "pure CQL" idea - simple to understand - easy for users 
to start with - explanation would just need two bullet points on a slide. I 
think it's worth the BCEL and schema agreement effort.

> Support for pure user-defined functions (UDF)
> ---------------------------------------------
>
>                 Key: CASSANDRA-7395
>                 URL: https://issues.apache.org/jira/browse/CASSANDRA-7395
>             Project: Cassandra
>          Issue Type: New Feature
>          Components: API, Core
>            Reporter: Jonathan Ellis
>              Labels: cql
>             Fix For: 3.0
>
>         Attachments: 7395-v2.diff, 7395.diff
>
>
> We have some tickets for various aspects of UDF (CASSANDRA-4914, 
> CASSANDRA-5970, CASSANDRA-4998) but they all suffer from various degrees of 
> ocean-boiling.
> Let's start with something simple: allowing pure user-defined functions in 
> the SELECT clause of a CQL query.  That's it.
> By "pure" I mean, must depend only on the input parameters.  No side effects. 
>  No exposure to C* internals.  Column values in, result out.  
> http://en.wikipedia.org/wiki/Pure_function



--
This message was sent by Atlassian JIRA
(v6.2#6252)

Reply via email to