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

A felhasználó által definiált függvények olyan újrafelhasználható al lekérdezések, amelyek a lekérdezés részeként (alkalmi függvények) definiálhatók, vagy az adatbázis metaadatainak (tárolt függvények) részeként maradnak meg. 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 hoznak létre (amely skaláris vagy táblázatos is lehet) 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-e, és ez határozza meg, hogyan használható.

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.

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 skaláris kifejezés engedélyezett
  • 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

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

Függvények neve

Az érvényes felhasználó által definiált függvényneveknek ugyanazokat az azonosítóelnevezési szabályokat kell követnie, mint más entitások.

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

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 zéró vagy több bemeneti argumentumot tartalmazó, erősen beírt 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 skaláris adattípus, vagy táblázatos séma.

A bemeneti argumentumok listája szintaktikailag 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óéval (zárójel és oszlopnév/típuspárok listája), és egy "bármely táblázatos sémát" jelző magánzárlat (*) hozzáadásával.

Például:

Syntax Bemeneti argumentumok lista leírása
() Nincsenek argumentumok
(s:string) Egy skaláris argumentum, amely egy típus értékének levételét hívja meg sstring
(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 é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 é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 táblázatos bemenetet használ, és nincs megadva oszlop. 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 ilyenek)
  • Függvény törzse

Megjegyzés

A túlterhelési függvények nem támogatottak. Nem hozhat létre több, azonos nevű és eltérő bemeneti sémával rendelkező függvényt.

Tipp

A Lambda-függvények nem rendelkeznek névvel, és let utasítással kapcsolódnak egy névhez. Ezért ezek felhasználó által definiált tárolt függvényekként tekinthetők. Példa: Deklaráció egy lambda függvényhez, amely két argumentumot fogad el (egy string hívott s és egy long hívott 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 függvény által használt lekérdezési paramétereket deklaráló lekérdezési paraméterek száma (nulla vagy több). Ha meg van adva, meg kell előzniük a függvény visszatérési értékét meghatározó kifejezést.

Megjegyzés

A "legfelső szinten" támogatott egyéb lekérdezési utasítások nem támogatottak a függvény törzsében. Minden két utasítást pontosvesszővel kell elválasztani.

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 elfogad egy ID nevű paramétert. 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 helyen.

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 zárójelben lévő üres argumentumlista alapján.

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ükhöz:

  • Az alapértelmezett értékek csak skaláris paraméterekhez adhatók meg.
  • Az alapértelmezett értékek mindig literálok (á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, amelynek nincsenek alapértelmezett értékei ugyanabban a sorrendben rendezve, mint a függvénydeklaráció.
  • A hívóknak nem kell megadniuk az alapértelmezett értékeket tartalmazó 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, meg kell adniuk az argumentumaikat.

Az alábbi példa egy táblát ad vissza két azonos rekorddal. Az első hívásban faz argumentumok teljesen "scrambled", így mindegyiknek külön 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 használnak 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ő karakteres 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 következő helyettesítő unionkarakteres hivatkozás:

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 olyan 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éseket visszaküldött, felhasználó által definiált függvények nem hívhatók meg olyan argumentummal, amely a sorkörnyezettől függően változik.
  • Egy legalább egy táblázatos bemenetet tartalmazó függvény nem hívható meg távoli fürtön.
  • A skaláris függvények nem hívhatók meg távoli fürtökön.

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álja 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 érdekében í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 függvényt is létrehozhat ugyanazzal a névvel és különböző bemeneti sémával).

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