Felhasználó által definiált függvények

A felhasználó által definiált függvények újrafelhasználható al lekérdezések, amelyek a lekérdezés részeként (alkalmi függvények) vagy az adatbázis metaadatai (tárolt függvények) részeként is meghatározhatók. A felhasználó által definiált függvények neven keresztül hívhatók meg, nulla vagy több bemeneti argumentummal vannak ellátva (amelyek lehetnek skalárisak vagy táblázatosak), és egyetlen értéket állítanak elő (amely lehet skaláris vagy táblázatos) a függvény törzse alapján.

A felhasználó által definiált függvények két kategória egyikéhez tartoznak:

  • Skaláris függvények
  • Táblázatos függvények, más néven nézetek

A függvény bemeneti argumentumai és kimenete határozza meg, hogy skaláris vagy táblázatos- vagy skaláris-e, és ez határozza meg a használat módját.

A Tárolt függvények című témakörben olyan entitásokat hozhat létre és kezelhet, amelyek lehetővé teszik a Kusto-lekérdezések vagy -lekérdezésrészek újrafelhasználását.

Ha a felhasználó által definiált függvények több használatát szeretné optimalizálni egyetlen lekérdezésen belül, olvassa el az Elnevezett kifejezéseket használó lekérdezések optimalizálása című témakört.

Skaláris függvény

  • Nulla bemeneti argumentuma van, vagy az összes bemeneti argumentuma skaláris érték
  • Egyetlen skaláris értéket állít elő
  • Bárhol használható, ahol egy skaláris kifejezés engedélyezve van
  • Csak azt a sorkörnyezetet használhatja, amelyben definiálva van
  • Csak az akadálymentes sémában lévő táblákra (és nézetekre) hivatkozhat

Táblázatos függvény

  • Egy vagy több táblázatos bemeneti argumentumot és nulla vagy több skaláris bemeneti argumentumot fogad el, és/vagy:
  • Egyetlen táblázatos értéket állít elő

Függvények neve

A felhasználó által definiált érvényes függvényneveknek ugyanazokat az azonosítóelnevezési szabályokat kell követnie, mint a többi entitásnak.

A névnek a definíció hatókörében is egyedinek kell lennie.

Megjegyzés

Ha egy tárolt függvény és egy tábla is ugyanazzal a névvel rendelkezik, akkor a névre való hivatkozás a tárolt függvényre, nem pedig a tábla nevére lesz feloldva. Ehelyett használja a táblafüggvényt a táblára való hivatkozáshoz.

Bemeneti argumentumok

A felhasználó által definiált érvényes függvények az alábbi szabályokat követik:

  • A felhasználó által definiált függvények szigorúan beírt, nulla vagy több bemeneti argumentumot tartalmazó listával rendelkezik.
  • A bemeneti argumentumok neve, típusa és (skaláris argumentumok esetén) egy alapértelmezett érték.
  • A bemeneti argumentum neve egy azonosító.
  • A bemeneti argumentum típusa vagy az egyik skaláris adattípus, vagy táblázatos séma.

Szintaktikailag a bemeneti argumentumok listája az argumentumdefiníciók vesszővel tagolt listája, zárójelbe csomagolva. Minden argumentumdefiníció a következőképpen van megadva:

ArgName:ArgType [= ArgDefaultValue]

Táblázatos argumentumok esetén az ArgType szintaxisa megegyezik a tábladefiníció szintaxisával (zárójel és oszlopnév/típus párok listája), és egy "bármely táblázatos séma" jelző magánzárlatot (*) is tartalmaz.

Például:

Syntax Bemeneti argumentumok listaleírása
() Nincsenek argumentumok
(s:string) Egyetlen skaláris argumentum, amelynek az a neve s , hogy egy értéktípust vesz fel string
(a:long, b:bool=true) Két skaláris argumentum, amelyek közül a második alapértelmezett értékkel rendelkezik
(T1:(*), T2(r:real), b:bool) Három argumentum (két táblázatos és egy skaláris argumentum)

Megjegyzés

Ha táblázatos bemeneti argumentumokat és skaláris bemeneti argumentumokat is használ, helyezze az összes táblázatos bemeneti argumentumot a skaláris bemeneti argumentumok elé.

Példák

Skaláris függvény:

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()

Argumentumokat nem használó táblázatos függvény:

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

Táblázatos függvény, amely táblázatos bemenetet és skaláris bemenetet is használ:

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

Táblázatos függvény, amely oszlop nélküli táblázatos bemenetet használ. Bármely tábla átadható egy függvénynek, és a függvényen belül nem lehet táblaoszlopra hivatkozni.

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

Felhasználó által definiált függvények deklarálása

A felhasználó által definiált függvény deklarációja a következőt biztosítja:

  • Függvény neve
  • Függvényséma (az általa elfogadott paraméterek, ha vannak)
  • Függvény törzse

Megjegyzés

A túlterhelési függvények nem támogatottak. Nem hozhat létre több függvényt ugyanazzal a névvel és különböző bemeneti sémákkal.

Tipp

A Lambda függvények nem rendelkeznek névvel, és let utasítással vannak egy névhez kötve. Ezért ezek felhasználó által definiált tárolt függvényekként tekinthetők. Példa: Egy lambda függvény deklarációja, amely két argumentumot fogad el (egy string hívott s és egy long úgynevezett i). Az első (számmá alakítás után) és a második szorzatát adja vissza. A lambda a következő névhez fvan kötve:

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

A függvény törzse a következőket tartalmazza:

  • Pontosan egy kifejezés, amely megadja a függvény visszatérési értékét (skaláris vagy táblázatos érték).
  • A let utasítások tetszőleges száma (nulla vagy több), amelynek hatóköre a függvény törzsének hatóköre. Ha meg van adva, a let utasításoknak meg kell előzniük a függvény visszatérési értékét meghatározó kifejezést.
  • A lekérdezésparaméter-utasítások tetszőleges száma (nulla vagy több), amely deklarálja a függvény által használt lekérdezési paramétereket. Ha meg van adva, akkor meg kell előzniük a függvény visszatérési értékét meghatározó kifejezést.

Megjegyzés

A lekérdezés felső szintjén támogatott egyéb lekérdezési utasítások nem támogatottak a függvény törzsében. A két utasítást pontosvesszővel kell elválasztani egymástól.

Példák felhasználó által definiált függvényekre

Az alábbi szakasz példákat mutat be a felhasználó által definiált függvények használatára.

Let utasítást használó, felhasználó által definiált függvény

Az alábbi példa egy felhasználó által definiált függvényt (lambda) mutat be, amely egy ID nevű paramétert fogad el. A függvény a Test névhez van kötve, és három let utasítást használ, amelyekben a Test3 definíciója az ID paramétert használja. Futtatáskor a lekérdezés kimenete 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

Felhasználó által definiált függvény, amely egy paraméter alapértelmezett értékét határozza meg

Az alábbi példa egy függvényt mutat be, amely három argumentumot fogad el. Az utóbbi kettő alapértelmezett értékkel rendelkezik, és nem kell jelen lennie a hívási webhelyen.

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"

Felhasználó által definiált függvény meghívása

Egy felhasználó által definiált függvény, amely nem vesz fel argumentumokat, és meghívható a neve, vagy a neve és egy üres argumentumlista zárójelben.

Példák:

// 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())

Egy felhasználó által definiált függvény, amely egy vagy több skaláris argumentumot vesz igénybe, a függvény nevével és egy zárójelben megadott konkrét argumentumlistával hívható meg:

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

Felhasználó által definiált függvény, amely egy vagy több táblaargumentumot vesz igénybe (tetszőleges számú skaláris argumentummal), és a függvény nevével és egy zárójelben megadott konkrét argumentumlistával hívható meg:

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

Az operátorral invoke egy felhasználó által definiált függvényt is meghívhat, amely egy vagy több táblaargumentumot vesz fel, és egy táblát ad vissza. Ez a függvény akkor hasznos, ha a függvény első konkrét táblaargumentuma az invoke operátor forrása:

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(":-)")

Alapértelmezett értékek

A függvények az alábbi feltételek mellett adhatnak meg alapértelmezett értékeket néhány paraméterüknek:

  • Az alapértelmezett értékek csak skaláris paraméterekhez adhatók meg.
  • Az alapértelmezett értékek mindig konstansok (állandók). Nem lehetnek tetszőleges számítások.
  • Az alapértelmezett értékkel nem rendelkező paraméterek mindig megelőzik az alapértelmezett értékkel rendelkező paramétereket.
  • A hívóknak minden olyan paraméter értékét meg kell adniuk, amely nem rendezi az alapértelmezett értékeket ugyanabban a sorrendben, mint a függvénydeklaráció.
  • A hívóknak nem kell megadniuk az alapértelmezett értékekkel rendelkező paraméterek értékét, de ezt megtehetik.
  • A hívók olyan sorrendben adhatnak meg argumentumokat, amelyek nem felelnek meg a paraméterek sorrendjének. Ha igen, el kell nevezniük az argumentumaikat.

Az alábbi példa egy táblát ad vissza két azonos rekorddal. Az első meghívásban faz argumentumok teljesen "össze vannak firkálva", így mindegyiknek explicit nevet ad:

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

Függvények megtekintése

A felhasználó által definiált függvények, amelyek nem vesznek fel argumentumokat, és táblázatos kifejezést ad vissza, nézetként jelölhetők meg. A felhasználó által definiált függvények nézetként való megjelölése azt jelenti, hogy a függvény táblázatként viselkedik, amikor helyettesítő karaktereket tartalmazó táblanévfeloldás történik. Az alábbi példa két felhasználó által definiált függvényt mutat be, és T_notviewazt mutatja be, T_view hogy csak az elsőt oldja fel a helyettesítő karakterek hivatkozása a unionkövetkezőben:

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

Korlátozások

Az alábbi korlátozások érvényesek:

  • A felhasználó által definiált függvények nem adhatnak át toscalar() hívási információkat, amelyek attól a sorkörnyezettől függenek, amelyben a függvényt meghívják.
  • A táblázatos kifejezést visszaadó, felhasználó által definiált függvények nem hívhatók meg a sorkörnyezettől eltérő argumentummal.
  • Egy legalább egy táblázatos bemenetet tartalmazó függvény nem hívható meg távoli fürtön.
  • Távoli fürtön nem hívható meg skaláris függvény.

A felhasználó által definiált függvények csak akkor hívhatók meg a sorkörnyezettől függően változó argumentummal, ha a felhasználó által definiált függvény csak skaláris függvényekből áll, és nem használ toscalar().

Példa az 1. korlátozásra

// 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élda a 2. korlátozásra

// 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)

A felhasználó által definiált függvények által jelenleg nem támogatott funkciók

A teljesség céljából íme néhány általánosan kért funkció a felhasználó által definiált függvényekhez, amelyek jelenleg nem támogatottak:

  1. Függvények túlterhelése: Jelenleg nem lehet túlterhelni egy függvényt (így több, azonos nevű és eltérő bemeneti sémával rendelkező függvényt hozhat létre).

  2. Alapértelmezett értékek: A függvény skaláris paraméterének alapértelmezett értékének skaláris literálnak (állandónak) kell lennie. Továbbá a tárolt függvények nem rendelkezhetnek alapértelmezett típusú dynamicértékkel.