SET dialect = 'clickhouse' permet de revenir au dialecte précédent. SET est la seule instruction SQL reconnue lorsque
le dialecte KQL est actif, afin qu’une session puisse toujours le quitter.
Éléments pris en charge
Il s’agit volontairement d’un sous-ensemble restreint. Une construction KQL est soit traduite conformément à la sémantique documentée par Kusto, soit rejetée explicitement avec une erreur d’analyse — aucune approximation n’est effectuée silencieusement. Si une requête est analysée, son résultat doit correspondre à celui de Kusto. Sources : un nom de table,print, datatable, range, un pipeline entre parenthèses et union.
Un range part d’un nombre avec un pas numérique, d’une date-heure avec un pas correspondant à une durée, ou d’une durée avec un pas correspondant à une durée.
Opérateurs : where / filter, extend, project, project-away, project-keep,
project-rename, summarize, sort by / order by, take / limit, top, distinct,
count, mv-expand, join, union, as, render.
Opérateurs scalaires : ==, !=, <, <=, >, >=, =~, !~, in, in~, between,
contains, startswith, endswith, has, hasprefix, hassuffix, leurs variantes _cs
(sensibles à la casse) et ! (négatives), has_any, has_all et matches regex.
in et !in acceptent également une expression tabulaire dont la première colonne fournit les valeurs
(x in (T | project key)); in~ n’accepte qu’une liste. Un nom seul dans in (...) qu’aucun
let ne lie est interprété comme une colonne, car l’analyseur ne dispose d’aucun schéma permettant de distinguer une colonne d’une table ;
liez la table avec let, qualifiez-la (db.table) ou ajoutez un pipe pour obtenir la forme tabulaire.
Instructions : let, qui lie un scalaire, une expression tabulaire complète ou une fonction :
T: (*) ou T: (col: type, ...), qui doivent figurer en premier. Un paramètre tabulaire qui
nomme ses colonnes n’expose au corps que les colonnes correspondantes de l’argument, de sorte qu’un corps qui lit une
colonne non déclarée est rejeté, même lorsque l’argument concret la contient ; T: (*)
transmet l’argument tel quel. Les types déclarés sont vérifiés à la frontière de l’appel :
un argument (ou une colonne déclarée d’un argument tabulaire) dont le type n’appartient pas au
type KQL déclaré est rejeté, une conversion sans perte telle que de long vers real est appliquée, et
une valeur qui ne correspond pas au type déclaré — par exemple, un dépassement de capacité de int — produit une erreur plutôt
qu’une troncature silencieuse. Les arguments peuvent être transmis par
nom dans n’importe quel ordre (f(c = 7, a = 12)). Un corps se compose d’un nombre quelconque d’instructions let suivies d’
une expression, et peut accéder aux liaisons qui l’englobent. Une fonction dont le corps est un
pipeline renvoie une table plutôt qu’une valeur ; elle est donc rejetée là où une expression est attendue -
dans extend, where ou print. Une fonction sans paramètre peut être
appelée avec ou sans parenthèses. view () est accepté et, puisque rien ici ne résout les
caractères génériques de union *, a la même signification que (). La récursion est rejetée, comme dans Kusto.
Un let ne crée une liaison que pour l’instruction qui le suit, car une instruction KQL correspond à une
requête ClickHouse — ce qui empêche également une liaison de fuiter dans une requête concurrente. Un
nom dont deux instructions ont besoin doit être lié deux fois.
Littéraux : chaînes (y compris les chaînes verbatim @'...'), nombres, datetime(...), guid(...),
durées telles que 1d / 2.5h / 500ms, et tableaux dynamic([...]).
Environ 130 fonctions scalaires et d’agrégation sont traduites. Comme dans Kusto, les fonctions
d’agrégation ne peuvent être appelées que dans la liste d’agrégation de summarize ; print count() est
rejeté plutôt que transmis à la fonction d’agrégation ClickHouse du même nom.
Les fonctions ClickHouse sont également accessibles. Un nom que le registre KQL ne connaît pas est transmis
à ClickHouse avec l’orthographe utilisée, afin qu’une requête puisse utiliser tout ce que le serveur
propose :
range en est l’exemple le plus clair — range(1, 3, 1) donne [1, 2, 3] dans Kusto et [1, 2] dans
ClickHouse ; son utilisation en KQL génère donc une erreur plutôt qu’un résultat incorrect.
Couverture par rapport à la référence Kusto
Évaluée par rapport aux propres index de Microsoft (opérateurs tabulaires, fonctions scalaires, fonctions d’agrégation) :
Les opérateurs pris en charge sont ceux enseignés dans le tutoriel Learn common operators de Microsoft,
ainsi que
datatable, range, print, union et join — suffisamment pour les types de requêtes que
ce tutoriel et la référence rapide KQL permettent de construire progressivement.
Ce qui n’est pas pris en charge
Les éléments suivants sont rejetés avec une erreur d’analyse plutôt que traduits incorrectement :- Opérateurs :
search,parse,mv-apply,lookup,evaluate,invoke,facet,top-nested,make-series,sample,serialize,partition,rangeutilisé comme opérateur. - Fonctions : la famille
series_*,bag_*/pack_*,parse_url,parse_csv,parse_json,todynamic,toscalar,format_timespan,format_datetime,extract_all,range, la famillepercentiles*et les fonctions de fenêtrerow_*. (format_datetimeetextract_allsont rejetées plutôt qu’approximées : les spécificateurs de formatyyyy-MM-ddde Kusto ne sont pas ceux de ClickHouse, etextract_allde Kusto renvoie un tableau par groupe de capture.) - Noms Kusto qui entrent en conflit avec une fonction ClickHouse de sens différent :
range(indiqué ci-dessus),repeat,replace,translateetmaterialize. Les laisser passer tels quels calculerait silencieusement autre chose —repeat(1, 3)en Kusto produit le tableau[1, 1, 1], tandis querepeatde ClickHouse répète une chaîne — ils sont donc tous rejetés par leur nom. - Les fonctions géospatiales qui acceptent ou renvoient du GeoJSON — toutes les fonctions
geo_*_to_central_point, ainsi que tout ce qui opère sur des polygones et des lignes. Les fonctions de points, de geohash et H3 qui utilisent directement longitude/latitude sont prises en charge.geo_point_to_s2cellne l’est pas : ClickHouse ne propose pas de forme de jeton S2. - Les objets
dynamic(dynamic({"a": 1})), l’accès aux membres (x.y) et la recherche par clé (x['k']). Seuls les tableauxdynamicsont mappés versArrayde ClickHouse.dynamicen tant que type déclaré — dans un schémadatatable, untypeof(...)ou un paramètre de fonction — est également rejeté : l’annotation ne contient aucun type d’élément, il n’existe donc aucune correspondance fidèle. - Références inter-clusters et inter-bases de données telles que
cluster(...)etdatabase(...). - Indications pour les requêtes et les
join(hint.strategy,hint.shufflekey, …). - Options d’opérateur :
mv-expand ... to typeof(T)/limit N/bagexpansion, indications poursummarize,union kind=/withsource=/isfuzzy=,join hint.*. - Motifs génériques de colonnes dans
project-awayetproject-keep(project-away Tmp*) : leur développement nécessite le schéma, qui n’est pas visible lors de l’analyse. Énumérez explicitement les colonnes. - L’intégralité du mécanisme de plug-ins
evaluate, ainsi quebag_unpack,pivot,narrow,python,Ret les autres. - Instructions d’application :
alias database,declare pattern,declare query_parameters,restrict access to. - Littéraux de chaîne obfusqués (
h"...") et littéraux multilignes (triple accent grave).
Comportements à connaître
- Les durées sont des valeurs
Interval.1ddevienttoIntervalNanosecond(86400000000000). Définissezinterval_output_format = 'kusto'pour les afficher au format Kusto (1.00:00:00) plutôt que sous forme de nombre. - La division suit les règles de Kusto :
7 / 2donne3, car les deux opérandes sont des entiers, et une durée divisée par une durée donne leur rapport réel (15ms / 10msdonne1.5). Ce comportement est implémenté parkqlDivide, qui se base sur les types d’arguments. - La soustraction de deux valeurs date-heure donne un nombre de secondes, alors que Kusto renvoie une durée. L’ajout ou la soustraction d’une durée fonctionne comme prévu.
sorttrie par défaut par ordre décroissant, contrairement à SQL, et place les valeurs nulles à l’extrémité inférieure.project-renamedéplace la colonne renommée à la fin de la ligne. Kusto conserve sa position d’origine ; reproduire ce comportement nécessiterait de connaître le schéma lors de l’analyse.unionexige que les opérandes aient des schémas compatibles. Kusto étend le résultat à l’union de toutes les colonnes et complète avec des valeurs nulles ;UNION ALLde ClickHouse ne le fait pas.- Les opérateurs sur les chaînes sont des fonctions de correspondance, et non des motifs
LIKE.contains '50%'recherche un signe pour cent littéral. geo_*prend la longitude avant la latitude, comme Kusto.geo_distance_2pointsutilisegreatCircleDistancede ClickHouse, une approximation rapide qui diffère de Kusto au quatrième chiffre significatif — environ 600 m sur 1 500 km — etuse_spheroid = truesélectionnegeoDistance, la formule ellipsoïdale, comme dans Kusto. Une correspondance exacte n’est pas l’objectif : ces fonctions servent généralement au filtrage plutôt qu’à la génération de rapports. Notez qu’une coordonnée hors de [-180, 180] ou [-90, 90] produit un nombre dénué de sens plutôt que la valeur nulle renvoyée par Kusto : aucune fonction ClickHouse ne vérifie la plage de ses arguments, et cette vérification coûterait huit comparaisons par ligne.dayofweek()renvoie une durée, et non un nombre : un lundi vaut1.00:00:00.tohex()affiche une valeur négative sur 64 bits. Kusto l’affiche selon la largeur du propre type de l’argument, ce qui n’est pas visible lors de l’analyse.- Les valeurs date-heure sont de véritables valeurs
DateTime64, elles s’affichent donc au format ClickHouse (2017-01-01 00:00:00) plutôt qu’au format Kusto (2017-01-01T00:00:00.0000000). L’implémentation précédente produisait une chaîne formatée, qui ressemblait à Kusto mais ne pouvait pas être comparée ou triée comme une valeur date-heure. - Les agrégats paramétriques de ClickHouse (
quantileExact(0.5)(x)) n’ont pas d’équivalent en KQL. Utilisez une alternative nommée telle quemedianExact(x).