Skip to content
This repository has been archived by the owner on Sep 19, 2023. It is now read-only.

Support custom functions #16

Closed
wschella opened this issue Nov 18, 2018 · 12 comments
Closed

Support custom functions #16

wschella opened this issue Nov 18, 2018 · 12 comments
Assignees
Labels
difficulty:hard Implementing or fixing this will require a serious amount of work and / or thinking priority:low spec

Comments

@wschella
Copy link
Member

See https://www.w3.org/TR/sparql11-query/#extensionFunctions. Could be very useful to pass custom functions that SPARQL doesn't support.

@wschella wschella added difficulty:hard Implementing or fixing this will require a serious amount of work and / or thinking priority:low spec labels Nov 18, 2018
@wschella wschella changed the title Support extensible value testing Support custom functions May 20, 2019
@rubensworks
Copy link
Member

@wschella Could you give some (quick) pointers on how we could implement support for custom functions? Someone may work on this in the near future.

@wschella
Copy link
Member Author

wschella commented Mar 9, 2020

Yes.

  1. The functions should be passed as an argument to the evaluator, e.g. AsyncEvaluator.ts, down to call to transformAlgebra(algExpr, newCustomFuncs).
  2. In transformAlgebra, you should make sure transformOperator handles these unknown operator names, based on the custom functions (which should ofcourse have a name). It can potentially also be used to overwrite behaviour of existing funcs.
  3. transformOperator should then return a new expression type: Expression.CustomOperator, similar to Expression.Operator, or Expression.SpecialOperator.
  4. The cases should be handled where in evaluation the expression tree, a custom operator is found. On top of my head this should only be relevant in the evaluators, with a similar function as evalSpecialOperator. This new function should be added to the subevaluators like the other methods. Implementing this should be not much more difficult then expr.apply(args). Given that Expression.CustomOperator does the heavy lifting.

Note: It is likely it will be slightly more complicated regarding the type system and sync/async differentation. So you might need Expression.CustomAsyncOperator and Expression.CustomSyncOperator or something, where in a sync evaluator the async operators can not be handled, or can be handled blocking. A good interface regarding the configuration is important.

@rubensworks
Copy link
Member

Thanks for the input!

@rubensworks rubensworks added this to To do (prio:low) in Development via automation Jun 22, 2020
@rubensworks rubensworks moved this from To do (prio:low) to To do (prio:high) in Development Jun 22, 2020
@rubensworks rubensworks added this to To do in Students Jun 22, 2020
@jitsedesmet
Copy link
Member

jitsedesmet commented Jul 22, 2021

NOTE to Self: A custom function in Algebra format looks like this:

"input": {
    "type": "filter",
    "input": {
      "type": "bgp",
      "patterns": [...]
    },
    "expression": {
      "type": "expression",
      "expressionType": "named",
      "name": {
        "termType": "NamedNode",
        "value": "http://example.org/functions#even"
      },
      "args": [
        {
          "type": "expression",
          "expressionType": "term",
          "term": {
            "termType": "Variable",
            "value": "id"
          }
        }
      ]
    }
  }

I suspect we should use transformNamed instead of transformOperator.

@wschella
Copy link
Member Author

You're right! I now see I even left a todo there.

// TODO: Support passing functions to override default behaviour;
!

@jitsedesmet
Copy link
Member

jitsedesmet commented Jul 23, 2021

@wschella
You wrote (I'll edit it a bit ;) ):

transformNamed should then return a new expression type: Expression.CustomOperator, similar to Expression.Operator, or Expression.SpecialOperator.

I was wondering why we can't just use Expression.Named as a starting point? Maybe give another SimpleApplication (given by the user) as an argument to it's constructor. Is there a specific reason you where thinking of creating a new type?
Is what you meant with the "TODO" you mentioned earlier?

@wschella
Copy link
Member Author

The terminology I used is not great, so it could make sense. Also I was a bit confused, my apologies.

The TODO I mentioned there I put there likely because I think the spec allows overriding the functionality of the Named operators (which are functions like toString and such). I forgot that. But this is different case still from adding NEW operators, which this issue was originally meant for: https://www.w3.org/TR/sparql11-query/#extensionFunctions.

We should distinguish between these two cases (and check the spec to see if I'm right).

  • I think it would be cleaner to give extensions these a new type, i.e. my arguing CustomOperator. But likely ExtensionOperator is even better to more closely match the spec.
  • Using Expression.Named would make sense for the overriding of the default behavior of existing functions (even if only to distinguish from extensions).

Now, since for overriding you likely want to tag the Expression.Named with a source = "default" | "custom", it could just be as clean, and maybe even better, to just make that tag source = "default" | "custom" | "extension".

The question with these matters is always how much their execution differs from each other. On first glance, maybe not at all. But I can also imagine errors or logging should be handled differently. Anyway, I don't have strong opinions (nor the authority to have them), so do as you see fit 😄

@rubensworks
Copy link
Member

Thanks for your input @wschella!

Just to make sure we're aligned; the tag source = "default" | "custom" | "extension" would then have the following semantics?

  • default: The named expression corresponds to a named expression defined by the SPARQL spec.
  • custom: The named expression overrides a named expression, to behave differently from defined by the SPARQL spec. (override may also be a valid type name)
  • extension: The named expression introduces a new extension function.

In any case, I guess the injection point (for Comunica) for custom and extension may be the same, and this distinction would only be internally for Sparqlee.

@wschella
Copy link
Member Author

@rubensworks Yeah that sums it up. And override is better indeed.

I do think there is merit in keeping the injection point separate (but equal in config/type). You likely want different errors if something is wrong (e.g. override types need to match the ones from default, while extension has free choice), but more importantly you don't want to allow unintentionally overriding default behavior by choosing an extensions which happens to have the same name or something. I don't know if this is valid. But in config passed to comunica/sparqlee I think explicit difference between { overrideFuncs: ..., extensionFuncs: ...} and { customFuncs: ...} is meaningfull, and adds little (or even reduces) cognitive overhead.

@rubensworks
Copy link
Member

I do think there is merit in keeping the injection point separate (but equal in config/type)
You likely want different errors if something is wrong

Good point!
Let's try it this way @jitsedesmet.

@jitsedesmet
Copy link
Member

Thank you for your clarification! I think I understand what you're saying. If I am uncertain about anything, I hope I an contact you again 😄

@wschella
Copy link
Member Author

Definitely :)

jitsedesmet added a commit to jitsedesmet/sparqlee that referenced this issue Jul 23, 2021
jitsedesmet added a commit to jitsedesmet/sparqlee that referenced this issue Jul 26, 2021
jitsedesmet added a commit to jitsedesmet/sparqlee that referenced this issue Jul 26, 2021
@rubensworks rubensworks moved this from To do to In progress in Students Jul 27, 2021
Development automation moved this from To do (prio:high) to Done Jul 29, 2021
Students automation moved this from In progress to Done Jul 29, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
difficulty:hard Implementing or fixing this will require a serious amount of work and / or thinking priority:low spec
Projects
Archived in project
Students
  
Done
Development
  
Done
Development

No branches or pull requests

3 participants