Uživatelem definované funkce

Uživatelem definované funkce jsou opakovaně použitelné poddotazy, které lze definovat jako součást samotného dotazu (ad hoc funkce) nebo trvalé jako součást metadat databáze (uložené funkce). Uživatelem definované funkce se vyvolávají prostřednictvím názvu, poskytují se nula nebo více vstupních argumentů (které můžou být skalární nebo tabulkové) a vytvářejí jednu hodnotu (která může být skalární nebo tabulková) založenou na těle funkce.

Uživatelem definovaná funkce patří do jedné ze dvou kategorií:

  • Skalární funkce
  • Tabulkové funkce, označované také jako zobrazení

Vstupní argumenty a výstup funkce určují, zda je funkce skalární, nebo tabulková, což následně určuje způsob jejího použití.

Projděte si téma Uložené funkce pro vytváření a správu entit, které umožňují opakované použití dotazů Kusto nebo částí dotazů.

Pokud chcete optimalizovat více použití uživatelem definovaných funkcí v rámci jednoho dotazu, přečtěte si téma Optimalizace dotazů, které používají pojmenované výrazy.

Skalární funkce

  • Má nula vstupních argumentů nebo všechny jeho vstupní argumenty jsou skalární hodnoty.
  • Vytvoří jednu skalární hodnotu.
  • Dá se použít všude, kde je povolený skalární výraz.
  • Může použít pouze kontext řádku, ve kterém je definován.
  • Může odkazovat pouze na tabulky (a zobrazení), které jsou ve schématu přístupnosti.

Tabulková funkce

  • Přijímá jeden nebo více tabulkových vstupních argumentů a nula nebo více skalárních vstupních argumentů a/nebo:
  • Vytvoří jednu tabulkovou hodnotu.

Názvy funkcí

Platné uživatelem definované názvy funkcí musí dodržovat stejná pravidla pojmenování identifikátorů jako jiné entity.

Název musí být také jedinečný ve svém oboru definice.

Poznámka

Pokud mají uložená funkce i tabulka stejný název, přeloží se všechny odkazy na tento název na uloženou funkci, nikoli na název tabulky. Místo toho použijte funkci table , která na tabulku odkazuje.

Vstupní argumenty

Platné uživatelem definované funkce se řídí těmito pravidly:

  • Uživatelem definovaná funkce obsahuje seznam se silnými typy žádných nebo více vstupních argumentů.
  • Vstupní argument má název, typ a (pro skalární argumenty) výchozí hodnotu.
  • Název vstupního argumentu je identifikátor.
  • Typ vstupního argumentu je buď jeden ze skalárních datových typů, nebo tabulkové schéma.

Seznam vstupních argumentů je syntakticky seznam definic argumentů oddělený čárkami, který je zabalený v závorkách. Každá definice argumentu se zadává jako

ArgName:ArgType [= ArgDefaultValue]

Pro tabulkové argumenty má typ ArgType stejnou syntaxi jako definice tabulky (závorky a seznam dvojic název/typ sloupce), přičemž přidání solitérní (*) syntaxe označuje "libovolné tabulkové schéma".

Příklad:

Syntax Popis seznamu vstupních argumentů
() Žádné argumenty
(s:string) Jeden skalární argument s názvem s převzetí hodnoty typu string
(a:long, b:bool=true) Dva skalární argumenty, z nichž druhý má výchozí hodnotu
(T1:(*), T2(r:real), b:bool) Tři argumenty (dva tabulkové argumenty a jeden skalární argument)

Poznámka

Při použití tabulkových i skalárních vstupních argumentů umístěte všechny vstupní tabulkové argumenty před skalární vstupní argumenty.

Příklady

Skalární funkce:

let Add7 = (arg0:long = 5) { arg0 + 7 };
range x from 1 to 10 step 1
| extend x_plus_7 = Add7(x), five_plus_seven = Add7()

Tabulková funkce bez argumentů:

let tenNumbers = () { range x from 1 to 10 step 1};
tenNumbers
| extend x_plus_7 = x + 7

Tabulková funkce, která přijímá tabulkový i skalární vstup:

let MyFilter = (T:(x:long), v:long) {
  T | where x >= v
};
MyFilter((range x from 1 to 10 step 1), 9)
x
9
10

Tabulková funkce, která používá tabulkový vstup bez zadaného sloupce. Funkci lze předat libovolnou tabulku a ve funkci nelze odkazovat na žádné sloupce tabulky.

let MyDistinct = (T:(*)) {
  T | distinct *
};
MyDistinct((range x from 1 to 3 step 1))
x
1
2
3

Deklarace uživatelem definovaných funkcí

Deklarace uživatelem definované funkce poskytuje:

  • Název funkce
  • Schéma funkce (parametry, které přijímá, pokud existuje)
  • Tělo funkce

Poznámka

Přetížení funkcí není podporováno. Nemůžete vytvořit více funkcí se stejným názvem a různými vstupními schématy.

Tip

Funkce lambda nemají název a jsou vázané na název pomocí příkazu let. Proto je lze považovat za uživatelem definované uložené funkce. Příklad: Deklarace funkce lambda, která přijímá dva argumenty (volaný strings a volaný longi). Vrátí součin prvního (po převodu na číslo) a druhého. Lambda je svázaná s názvem f:

let f=(s:string, i:long) {
    tolong(s) * i
};

Tělo funkce obsahuje :

  • Přesně jeden výraz, který poskytuje návratovou hodnotu funkce (skalární nebo tabulkovou hodnotu).
  • Libovolné číslo (nula nebo více) příkazů let, jejichž oborem je rozsah těla funkce. Pokud je zadaný, příkazy let musí předcházet výrazu definujícím návratovou hodnotu funkce.
  • Libovolný počet příkazů parametrů dotazu (nula nebo více), které deklarují parametry dotazu používané funkcí. Pokud jsou zadané, musí předcházet výrazu definujícím návratovou hodnotu funkce.

Poznámka

Jiné typy příkazů dotazu , které jsou podporované v dotazu na nejvyšší úrovni, nejsou v těle funkce podporovány. Jakékoli dva příkazy musí být odděleny středníkem.

Příklady uživatelem definovaných funkcí

Následující část ukazuje příklady použití uživatelem definovaných funkcí.

Uživatelem definovaná funkce, která používá příkaz let

Následující příklad ukazuje uživatelem definovanou funkci (lambda), která přijímá parametr s názvem ID. Funkce je vázaná na název Test a používá tři příkazy let , ve kterých definice Test3 používá parametr ID . Při spuštění je výstup dotazu 70:

let Test = (id: int) {
  let Test2 = 10;
  let Test3 = 10 + Test2 + id;
  let Test4 = (arg: int) {
      let Test5 = 20;
      Test2 + Test3 + Test5 + arg
  };
  Test4(10)
};
range x from 1 to Test(10) step 1
| count

Uživatelem definovaná funkce, která definuje výchozí hodnotu parametru

Následující příklad ukazuje funkci, která přijímá tři argumenty. Poslední dvě mají výchozí hodnotu a nemusí se nacházet na webu volání.

let f = (a:long, b:string = "b.default", c:long = 0) {
  strcat(a, "-", b, "-", c)
};
print f(12, c=7) // Returns "12-b.default-7"

Vyvolání uživatelem definované funkce

Uživatelem definovaná funkce, která nepřijímá žádné argumenty a může být vyvolána buď svým názvem, nebo názvem a prázdným seznamem argumentů v závorkách.

Příklady:

// Bind the identifier a to a user-defined function (lambda) that takes
// no arguments and returns a constant of type long:
let a=(){123};
// Invoke the function in two equivalent ways:
range x from 1 to 10 step 1
| extend y = x * a, z = x * a()
// Bind the identifier T to a user-defined function (lambda) that takes
// no arguments and returns a random two-by-two table:
let T=(){
  range x from 1 to 2 step 1
  | project x1 = rand(), x2 = rand()
};
// Invoke the function in two equivalent ways:
// (Note that the second invocation must be itself wrapped in
// an additional set of parentheses, as the union operator
// differentiates between "plain" names and expressions)
union T, (T())

Uživatelem definovanou funkci, která přijímá jeden nebo více skalárních argumentů, lze vyvolat pomocí názvu funkce a konkrétního seznamu argumentů v závorkách:

let f=(a:string, b:string) {
  strcat(a, " (la la la)", b)
};
print f("hello", "world")

Uživatelem definovaná funkce, která přijímá jeden nebo více argumentů tabulky (s libovolným počtem skalárních argumentů) a je možné ji vyvolat pomocí názvu funkce a konkrétního seznamu argumentů v závorkách:

let MyFilter = (T:(x:long), v:long) {
  T | where x >= v
};
MyFilter((range x from 1 to 10 step 1), 9)

Operátor můžete použít invoke také k vyvolání uživatelem definované funkce, která přebírá jeden nebo více argumentů tabulky a vrací tabulku. Tato funkce je užitečná v případě, že první konkrétní argument tabulky funkce je zdrojem operátoru invoke :

let append_to_column_a=(T:(a:string), what:string) {
    T | extend a=strcat(a, " ", what)
};
datatable (a:string) ["sad", "really", "sad"]
| invoke append_to_column_a(":-)")

Výchozí hodnoty

Funkce můžou některým parametrům poskytovat výchozí hodnoty za následujících podmínek:

  • Výchozí hodnoty lze zadat pouze pro skalární parametry.
  • Výchozí hodnoty jsou vždy literály (konstanty). Nemohou to být libovolné výpočty.
  • Parametry bez výchozí hodnoty jsou vždy před parametry, které mají výchozí hodnotu.
  • Volající musí zadat hodnotu všech parametrů bez výchozích hodnot uspořádaných ve stejném pořadí jako deklarace funkce.
  • Volající nemusí zadávat hodnotu parametrů s výchozími hodnotami, ale můžou to udělat.
  • Volající můžou zadávat argumenty v pořadí, které neodpovídá pořadí parametrů. Pokud ano, musí argumenty pojmenovat.

Následující příklad vrátí tabulku se dvěma identickými záznamy. Při prvním volání fmetody jsou argumenty zcela "zakódované", takže každý z nich je explicitně pojmenován:

let f = (a:long, b:string = "b.default", c:long = 0) {
  strcat(a, "-", b, "-", c)
};
union
  (print x=f(c=7, a=12)), // "12-b.default-7"
  (print x=f(12, c=7))    // "12-b.default-7"
x
12-b.default-7
12-b.default-7

Zobrazit funkce

Uživatelem definovanou funkci, která nepřijímá žádné argumenty a vrací tabulkový výraz, lze označit jako zobrazení. Označení uživatelem definované funkce jako zobrazení znamená, že se funkce chová jako tabulka při každém překládání názvů tabulek se zástupnými znaky. Následující příklad ukazuje dvě uživatelem definované funkce, a T_notviewa ukazuje, T_view jak pouze první funkce je vyřešena zástupným znakem v union:

let T_view = view () { print x=1 };
let T_notview = () { print x=2 };
union T*

Omezení

Vstupy mají nesledující mezení:

  • Uživatelem definované funkce nemohou předat do vyvolání funkce toscalar(), které závisí na kontextu řádku, ve kterém je funkce volána.
  • Uživatelem definované funkce, které vracejí tabulkový výraz, nelze vyvolat pomocí argumentu, který se liší podle kontextu řádku.
  • Funkci, která přijímá alespoň jeden tabulkový vstup, není možné vyvolat ve vzdáleném clusteru.
  • Skalární funkci není možné vyvolat ve vzdáleném clusteru.

Jediným místem, kde lze uživatelem definovanou funkci vyvolat s argumentem, který se liší podle kontextu řádku, je, když se uživatelem definovaná funkce skládá pouze ze skalárních funkcí a nepoužívá toscalar().

Příklad omezení 1

// Supported:
// f is a scalar function that doesn't reference any tabular expression
let Table1 = datatable(xdate:datetime)[datetime(1970-01-01)];
let Table2 = datatable(Column:long)[1235];
let f = (hours:long) { now() + hours*1h };
Table2 | where Column != 123 | project d = f(10)

// Supported:
// f is a scalar function that references the tabular expression Table1,
// but is invoked with no reference to the current row context f(10):
let Table1 = datatable(xdate:datetime)[datetime(1970-01-01)];
let Table2 = datatable(Column:long)[1235];
let f = (hours:long) { toscalar(Table1 | summarize min(xdate) - hours*1h) };
Table2 | where Column != 123 | project d = f(10)

// Not supported:
// f is a scalar function that references the tabular expression Table1,
// and is invoked with a reference to the current row context f(Column):
let Table1 = datatable(xdate:datetime)[datetime(1970-01-01)];
let Table2 = datatable(Column:long)[1235];
let f = (hours:long) { toscalar(Table1 | summarize min(xdate) - hours*1h) };
Table2 | where Column != 123 | project d = f(Column)

Příklad omezení 2

// Not supported:
// f is a tabular function that is invoked in a context
// that expects a scalar value.
let Table1 = datatable(xdate:datetime)[datetime(1970-01-01)];
let Table2 = datatable(Column:long)[1235];
let f = (hours:long) { range x from 1 to hours step 1 | summarize make_list(x) };
Table2 | where Column != 123 | project d = f(Column)

Funkce, které nejsou aktuálně podporovány uživatelem definovanými funkcemi

Pro úplnost uvádíme některé běžně požadované funkce pro uživatelem definované funkce, které se v současné době nepodporují:

  1. Přetížení funkce: V současné době neexistuje způsob, jak funkci přetížit (způsob, jak vytvořit více funkcí se stejným názvem a jiným vstupním schématem).

  2. Výchozí hodnoty: Výchozí hodnota skalárního parametru funkce musí být skalární literál (konstanta).