Kusto: Handling null parameter in user defined funtion - azure-data-explorer

I am writing a custom User defined function in kusto where I want to have some optional parameters to the function which will be used in the "where" clause. I want to dynamically handle this. For example: If the value is present, then my where clause should consider that column filter, else it should not be included in the "where" clause>
Eg (psuedo code where value is not null):
function Calculate(string:test)
{
T | where test == test | order by timestamp
}
Eg (psuedo code where value is null or empty. My final query should look like this):
function Calculate(string:test)
{
T | order by timestamp
}
What is the efficient way to implement this. I will call this function from my c# class.

you can define a function with a default value for its argument, and use the logical or operator and the isempty() function to implement the condition you've described.
for example:
(note: the following is demonstrated using a let statement, but can be applied similarly to stored functions)
let T = range x from 1 to 5 step 1 | project x = tostring(x)
;
let F = (_x: string = "") {
T
| where isempty(_x) or _x == x
| order by x desc
}
;
F("abc")
if you run F() or F("") (i.e. no argument, or an empty string as the argument) - it will return all values 1-5.
if you run F("3") - it will return a single record with the value 3.
if you run F("abc") - it will return no records.

Related

writing a if-else-then fucntion

I am trying to write a function to call a function from a package, snippets as below:
library(optionstrat)
# sameple detla
# do not run
# calldelta(s,x,sigma,t,r)
# putdelta(s,x,sigma,t,r)
x=10
sigma=0.25
t=0.25
r=0.05
delta<-function(option_type,stock_price) {
if (option_type="c") {
delta<-calldelta(s,x,sigma,t,r)
} else {
delta<-putdelta(s,x,sigma,t,r)
}
}
both calldelta and putdelta are built in functions from optionstrat package, and I would like to write a function so that if option_type="c", then return with a call delta value based on the stock price input. Likewise, if option_type!="c", then return with a put delta value based on the stock price input.
My end goal here is to come up with a function like delta(c,10) then return with a call delta value based on stock price 10. May I know how should I do from here? Thanks.
Update 1:
Now I try working with the below snippets:
x=10
sigma=0.25
t=0.25
r=0.05
stock_delta<-function(option_type,s) {
if (option_type="c") {
delta<-calldelta(s,x,sigma,t,r)
} else {
delta<-putdelta(s,x,sigma,t,r)
}
}
And again, if I define optiontype equals to c & s equals to 10, the same warning msg is returned...
Update 2:
Thanks to #akrun, now the function is created & now I would like to add one more return value from the delta function by adding:
calleval(s,x,sigma,t,r)$Gamma
puteval(s,x,sigma,t,r)$Gamma
The first line will return with the call gamma value & the latter will return with put gamma. May I know how do I string it with the function written previously?
There are multiple issues in the function - 1) function arguments passed should match the arguments to the inner function, 2) = is assignment and == is comparison operator, 3) if the last statement is assigned to an object, it wouldn't print on the console. We may either need to return(delta) or in this case there is no need to create an object delta inside (when the function name is also the same), 4) Passing unquoted argument (c) checks for object name c and even have an additional issue as c is also a function name. Instead, pass a string "c" as is expected in the if condition
delta<-function(option_type,stock_price)
{
if (option_type=="c")
calldelta(stock_price,x,sigma,t,r)
else
putdelta(stock_price,x,sigma,t,r)
}
-testing
> delta("c", 10)
[1] 0.5645439

Does materialize function not work with tabular function argument in Kusto?

I created a simple function MaterializeRemoteInputTable below which accepts the output of a table as an input.
To test if the input is materialized, I am using it twice to calculate two scalar values - x and y:
.create-or-alter function MaterializeRemoteInputTable(inputTable: (State:string)) {
let materializedInput = materialize(inputTable);
let x = toscalar(materializedInput | count );
let y = toscalar(materializedInput | where State contains "S" | count);
print x, y;
}
I am using the sample kusto database's function output as an input to the above function:
cluster('https://help.kusto.windows.net').database('Samples').
GetStatesWithPopulationSmallerThan(1000000)
| invoke MaterializeRemoteInputTable()
On querying the help.kusto.windows.net cluster with my ClientActivityId, I see two queries are executed:
.show commands-and-queries
| where ClientActivityId contains "KE.RunQuery;<guid...>"
Above query outputs two rows:
GetStatesWithPopulationSmallerThan(long(1000000))|__executeAndCache|count as Count|limit long(1)|project ["b2fb..."]=["Count"]
GetStatesWithPopulationSmallerThan(long(1000000))|__executeAndCache|where (["State"] contains ("S"))|count as Count|limit long(1)|project ["5d0e2..."]=["Count"]
Since I have materialized the input to my MaterializeRemoteInputTable, why are two queries executed on the remote cluster, once each for x and y?
There is no issue with materialize & tabular argument to a function.
The issue is a known limitation in materialize with cross cluster query that in some cases the materialization is not performed.
Please note that this is only a performance issue and not a logical issue (query results are guaranteed to be correct).

Kusto: Failed to cast argument to scalar constant when using countof()

I defined a UDF function in kusto:
.create-or-alter function with (docstring = 'abc', folder='udfs')
get_index_of(input:string, lookup:string)
{
countof(input, lookup)
}
Next, I am going to use it an a sample table and it does not work
datatable (Input:string, Lookup:string)
[
"text:1", ":"
]
| extend Result = get_index_of(Input, Lookup)
I get the error message:
countof(): failed to cast argument 2 to scalar constant
Do you have any idea what is wrong? Please note, that the function works, because a sample run return result:
print get_index_of('text', 'e')
1
as of this writing, the 2nd argument to countof() is expected to be a constant string literal (i.e., one that doesn't change based on row context)

What's the correct way to pass a cursor to a user defined function?

I'm trying to pass a cursor to a function like this:
.create-or-alter function GetLatestValues(cursor:string) {
Logs | where cursor_after(cursor)
}
But I get a Error cursor_after(): argument #1 is invalid response. Is there something I'm missing? Is string the wrong data type to use?
This approach works properly for lambda functions:
let GetLatestValues = (cursor:string) {
Logs | where cursor_after(cursor)
};
GetLatestValues('') | take 1
By default, defining a function in Kusto validates stored function, and in case you're using cursor the system will attempt to do it with empty parameter, leading to failure.
You can override this behavior using skipvalidation=true parameter (see docs at:
https://learn.microsoft.com/en-us/azure/kusto/management/functions#create-function)
.create-or-alter function with (skipvalidation = "true")
GetLatestValues(cursor:string)
{
Logs | where cursor_after(cursor)
}

How to cast a value type to Map in Rascal?

I have a variable of type value that stores a map, but I can not access the values by providing the keys:
rascal>a
value: ("s":"s")
rascal>a["s"]
|stdin:///|(2,3,<1,2>,<1,5>): subscript not supported on value at |stdin:///|(2,3,<1,2>,<1,5>)
☞ Advice
How can I parse the value to map in order to be able to retrieve my value ?
if (map[str,str] myMap := a) {
// do stuff with myMap
}
else {
throw "<a> is not a map?";
}
Another way of "narrowing types" is using pattern matching in function parameters:
rascal>value x = 1;
int: 1
rascal>int myFunc(int i) = 2 * i;
ok
rascal>myFunc(x);
int: 2
And yet another way is using visit or switch:
visit(bigValue) {
case Expression e => ...work with e...
}
The general idea is:
pattern matching means narrowing (downcasting)
pattern matching may fail and so is always in a conditional context
there are many places in Rascal where you can use pattern matching: function dispatch, switch, visit, :=, <-

Resources