microsoft / Kusto-Query-Language

Kusto Query Language is a simple and productive language for querying Big Data.
Apache License 2.0
510 stars 97 forks source link

Using functions with parameters in kusto.language nuget #64

Closed Amitbergman closed 2 years ago

Amitbergman commented 2 years ago

Hey, I saw in the examples that it is possible to add functions to the analyzer, so that it will take them into account when analyzing the query. The example that is shown there is of a function without parameters:

new FunctionSymbol("TallShapes", "{ Shapes | where width < height; }")

I was wondering if it is possible to show an example of using a function with parameters?

Ideally I will supply a function name, the parameters that it expects to get, and the schema of the result, and the analyzer would take this information into account.

Thanks!

mattwar commented 2 years ago

There are many overloads to the FunctionSymbol constructor. You can declare function symbols and give them explicit parameters and return types. The classes Function.cs and Aggregates.cs show how the built-in function symbols are declared. All of them specify parameters. To have them usable during ParseAndAnalyze you need to add the functions to the global state you pass to ParseAndAnalyze via either adding them to a DatabaseSymbol (same as with table schemas) or add them as a built-in function by changing the set of declared functions in the global state.

mattwar commented 2 years ago

You can add parameters like this:

    new FunctionSymbol("SmallShapes", "(maxHeight: real)", "{ Shapes | where width < maxHeight; }")

Or like this:

     new FunctionSymbol("SmallShapes', "{ Shapes | width < maxHeight; }",
            new Parameter("maxHeight", ScalarTypes.Real));

The reason you need to specify the body of the function and not the result schema is that this is how database functions are stored in Kusto. They are just the declarations of the function as code (text) and the result schema is not known until it is analyzed.

There are functions that have fixed result types, but this are usually built-in functions.

You create them like this: (note, the result type/schema comes before the parameters)

    new FunctionSymbol("SmallShapes", 
           TableSymbol.From("(width: real, height: real, name: string)"),
           new Parameter("maxHeight", ScalarTypes.Real))

It might work okay to add a function without a body to a DatabaseSymbol. I have not tried.

If you want to create a built-in function that is of course, not actually built-in, but just for the analyzer you can add them to the global state like this:

    var myFunction = new FunctionSymbol("myfunction", ScalarTypes.Real, new ParamterSymbol("myParameter", ScalarTypes.Real));

    globals = globals.WithFunctions(globals.Functions.Concat(new [] { myFunction }).ToArray())

You can do the same thing with aggregates by using the WithAggregates method instead.

mattwar commented 2 years ago

I've also updated the readme.md with examples.