Details

    • Type: New Feature
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 0.9.0-incubating
    • Component/s: None
    • Labels:
      None

      Description

      We already allow UDFs based on classes, provided that that classes have just one method. This change would allow UDFs based on classes with several methods.

      E.g. should be able to use 'String String.replace(String s, String s2)' as a SQL UDF 'REPLACE(String, String, String) RETURNS String'.

        Activity

        Hide
        julianhyde Julian Hyde added a comment -

        Close issues resolved in release 0.9.0-incubating (2014-08-25).

        Show
        julianhyde Julian Hyde added a comment - Close issues resolved in release 0.9.0-incubating (2014-08-25).
        Show
        julianhyde Julian Hyde added a comment - Fixed in http://git-wip-us.apache.org/repos/asf/incubator-optiq/commit/679b31a2 .
        Hide
        julianhyde Julian Hyde added a comment -

        Now if you specify methodName, Optiq finds all methods with that name in the class. (It excludes non-static ones if the class does not have a public zero-args constructor.) Overloads are resolved based on runtime arguments.

        If you specify methodName='*' it loads all methods, as above. You don't need to specify name; the name of the function is based on the name of the method.

        You cannot use methodName with aggregate functions. (They require several implementation methods, with fixed names.)

        As part of this change, I also improved how overloaded argument lists are resolved. In particular, an Object parameter becomes a SQL ANY type and can thus match anything.

        I also added OptiqAssert.AssertQuery.returnsValue, to make it easier to test statements that return 1 row with 1 column.

        Show
        julianhyde Julian Hyde added a comment - Now if you specify methodName , Optiq finds all methods with that name in the class. (It excludes non-static ones if the class does not have a public zero-args constructor.) Overloads are resolved based on runtime arguments. If you specify methodName='*' it loads all methods, as above. You don't need to specify name ; the name of the function is based on the name of the method. You cannot use methodName with aggregate functions. (They require several implementation methods, with fixed names.) As part of this change, I also improved how overloaded argument lists are resolved. In particular, an Object parameter becomes a SQL ANY type and can thus match anything. I also added OptiqAssert.AssertQuery.returnsValue , to make it easier to test statements that return 1 row with 1 column.
        Hide
        julianhyde Julian Hyde added a comment -

        I was thinking of automatic overloads. For example, if they specify

        functions: [ {
          name: "MY_ABS",
          className: "java.lang.Math",
          methodName: "abs"
        }]
        

        they will get SQL UDFs MY_ABS(INT), MY_ABS(LONG), MY_ABS(REAL), MY_ABS(DOUBLE) because java.lang.Math has overloaded functions abs(int), abs(long), abs(float), abs(double).

        if you hoped that the public String replace(String, String) of java.lang.String could be used to implement REPLACE(VARCHAR, VARCHAR, VARCHAR) RETURNS VARCHAR, you are out of luck; it actually becomes REPLACE(VARCHAR, VARCHAR) RETURNS VARCHAR). Optiq does not use the "this" as an extra parameter. Optiq will instantiate the class before the first row (the class must have a public default constructor), then uses the same instance (in this case, the String object) for each call. The instance can be used to hold state variables. (Not much use in this case, because String has no mutable fields.)

        Show
        julianhyde Julian Hyde added a comment - I was thinking of automatic overloads. For example, if they specify functions: [ { name: "MY_ABS", className: "java.lang. Math ", methodName: "abs" }] they will get SQL UDFs MY_ABS(INT) , MY_ABS(LONG) , MY_ABS(REAL) , MY_ABS(DOUBLE) because java.lang.Math has overloaded functions abs(int) , abs(long) , abs(float) , abs(double) . if you hoped that the public String replace(String, String) of java.lang.String could be used to implement REPLACE(VARCHAR, VARCHAR, VARCHAR) RETURNS VARCHAR , you are out of luck; it actually becomes REPLACE(VARCHAR, VARCHAR) RETURNS VARCHAR) . Optiq does not use the "this" as an extra parameter. Optiq will instantiate the class before the first row (the class must have a public default constructor), then uses the same instance (in this case, the String object) for each call. The instance can be used to hold state variables. (Not much use in this case, because String has no mutable fields.)
        Hide
        vladimirsitnikov Vladimir Sitnikov added a comment -

        What with overloads then?
        Method name is not sufficient to identify a method.

        We either pick up all the methods with given name and use them as overloads, or provide a way to specify argument types.

        Show
        vladimirsitnikov Vladimir Sitnikov added a comment - What with overloads then? Method name is not sufficient to identify a method. We either pick up all the methods with given name and use them as overloads, or provide a way to specify argument types.
        Hide
        julianhyde Julian Hyde added a comment - - edited

        Right now the method has to be called "eval". We'd need to add a "String methodName" member to JsonFunction to allow stuff like

        functions: [ { className: "java.lang.String", methodName: "replace" } ]
        

        in the schema.

        Show
        julianhyde Julian Hyde added a comment - - edited Right now the method has to be called "eval". We'd need to add a "String methodName" member to JsonFunction to allow stuff like functions: [ { className: "java.lang. String ", methodName: "replace" } ] in the schema.
        Hide
        vladimirsitnikov Vladimir Sitnikov added a comment -

        Are you sure it is not available now?

        public static ScalarFunction ScalarFunctionImpl.create(Method method) should do the trick.

        Show
        vladimirsitnikov Vladimir Sitnikov added a comment - Are you sure it is not available now? public static ScalarFunction ScalarFunctionImpl.create(Method method) should do the trick.

          People

          • Assignee:
            julianhyde Julian Hyde
            Reporter:
            julianhyde Julian Hyde
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development