Portabilité vers Snowflake
Objectif du labo : transposer chez le client le travail fait au labo sans le réécrire. Ce document liste ce qui reste identique, ce qui change, et ce qui n'est pas encore outillé.
Ce qui reste identique
- Noms à trois niveaux :
analytics.<schema>.<table>au labo (catalogue Trino, catalogue Polaris, attachement DuckDB),ANALYTICS.<SCHEMA>.<TABLE>chez Snowflake. Les schémas portent les mêmes noms :raw,standardized,semantic,intake,forecast,shared_calendar. - Identifiants en minuscules, jamais entre guillemets : le même SQL est valide partout (Snowflake met en majuscules les identifiants non quotés). Référence : https://docs.snowflake.com/en/sql-reference/identifiers-syntax (vérifiée le 2026-10-22).
- Projet dbt unique (
dbt/) : mêmes modèles, mêmes tests, mêmes snapshots, même couche MetricFlow ;quotingdésactivé ; schémas nommés tels quels (generate_schema_name). - Appels
AI_*écrits comme dans Snowflake (noms, arguments, littéraux), accès aux champs parGET(x, 'champ')plutôt quex:champ. - Colonnes de preuve (
_source_file,_row_numberpourMETADATA$FILENAME,METADATA$FILE_ROW_NUMBER),confidence_classet schéma de la tableforecast. - Types :
decimal(38, s),timestamp,timestamptz, JSON en chaîne (voir les écarts ci-dessous). Une colonne Icebergtimestamptzse lit chez Snowflake enTIMESTAMP_LTZ, pas enTIMESTAMP_TZ(voir les écarts).
Ce qui change chez le client
| Élément | Au labo | Chez le client | Où agir |
|---|---|---|---|
| Adapter dbt | dbt-duckdb (cible duckdb, défaut) ou dbt-trino |
dbt-snowflake : cible snowflake de dbt/profiles.example.yml |
dbt build --target snowflake avec SNOWFLAKE_ACCOUNT, SNOWFLAKE_USER, SNOWFLAKE_PASSWORD, SNOWFLAKE_ROLE, SNOWFLAKE_WAREHOUSE ; groupe de dépendances snowflake (uv sync --group snowflake) |
| Base des sources raw | Variable raw_database vide : base de la cible (target.database, soit analytics), pour les trois adapters |
Idem | Rien : le SQL compilé lit analytics.raw.* partout |
| Nom de la base | analytics |
Nom de la base Snowflake du client | Voir ci-dessous |
Fonctions AI_* en SQL |
Macros DuckDB de cortex_lab (plugin dbt-duckdb) |
Fonctions natives Cortex | Rien : le SQL est le même ; la macro dbt get dispatche vers GET natif |
| Fonctions Cortex en Python | cortex_lab.cortex, cortex_lab.snowpark |
snowflake.cortex, snowflake.snowpark.functions |
CORTEX_BACKEND=snowflake et import par cortex_lab.compat |
Modèle d'AI_COMPLETE |
Alias LiteLLM cortex-complete |
Nom d'un modèle hébergé par Snowflake | CORTEX_COMPLETE_MODEL (lu par ingest/mapping.py) ; dans le SQL, l'argument model |
| Stages et chargement | landing/ sur MinIO, ingest.raw_loader |
Stage Snowflake, COPY INTO ou Snowpipe |
Non outillé dans le dépôt (voir plus bas) |
| Prévision | Conteneur forecast lancé par Docker Compose |
Même image dans Snowpark Container Services, ou modèle custom du Model Registry | Voir prevision.md |
| Lineage | Marquez | Lineage de Snowsight (page lue le 2026-10-23 : mouvements de données par COPY INTO, CREATE TABLE AS SELECT, INSERT ... SELECT, MERGE, UPDATE et dépendances de vues, Enterprise Edition requise ; le lineage des tables du client reste à constater chez lui) |
Aucun code à changer côté dbt ; l'émetteur ingest/lineage.py et la CLI ingest.raw_loader sont propres au labo |
Renommer la base
Au labo, le nom de la base est porté par plusieurs fichiers. Pour aligner le labo sur le nom réel du client :
LAB_DATABASEdans.env(catalogue Polaris créé parpolaris-init, attachement DuckDB, profils dbttrinoetsnowflake) ;- le nom du fichier
infra/trino/catalog/analytics.propertieset sa propriétéiceberg.rest-catalog.warehouse=analytics; - les règles
infra/trino/rules.json, qui nomment le catalogueanalyticsen dur ; - le catalogue Polaris existant n'est pas renommé par le job : un nouveau catalogue est créé sous le nouveau nom (les tables de l'ancien restent dans l'ancien, à migrer ; la documentation de Polaris sur l'enregistrement de tables dans un autre catalogue n'a pas été lue : point V24, toujours à vérifier).
Côté client, seul LAB_DATABASE (lu par le profil snowflake) compte.
Bascule CORTEX_BACKEND
CORTEX_BACKEND=snowflake python mon_script.py
cortex_lab.compat importe alors snowflake.cortex et snowflake.snowpark.functions au lieu des façades du labo. Ces paquets doivent être installés chez le client (ils ne sont pas des dépendances du labo). Le code client importe toujours depuis cortex_lab.compat.
Écarts à garder en tête
| Écart | Conséquence chez le client |
|---|---|
| Casse : identifiants stockés en majuscules chez Snowflake | Le SQL non quoté fonctionne ; les noms renvoyés par les métadonnées sont en majuscules |
| Timestamps en nanosecondes chez Snowflake, microsecondes au labo | Comparaisons d'horodatages au-delà de la microseconde différentes. Précision relue le 2026-10-23 (https://docs.snowflake.com/en/user-guide/tables-iceberg-data-types) : sur des tables Iceberg v2 du client, la précision est aussi la microseconde (timestamp vers TIMESTAMP_NTZ(6)), l'écart ne vaut que pour les tables Snowflake natives ; timestamp_ns n'existe qu'en Iceberg v3 |
timestamptz Iceberg lu en TIMESTAMP_LTZ chez Snowflake |
La convention du labo timestamp et timestamptz pour TIMESTAMP_NTZ et TIMESTAMP_TZ vaut pour les types natifs ; sur une table Iceberg, Snowflake lit timestamptz en TIMESTAMP_LTZ(6) (même instant, interprété dans le fuseau de la session, pas de fuseau conservé par valeur). Les décimaux decimal(P, S) deviennent NUMBER(P, S), string devient VARCHAR(134217728), list, struct et map deviennent des ARRAY, OBJECT et MAP structurés ; VECTOR n'est pas mentionné par la page (les embeddings du labo sont des listes de flottants) ; VARIANT n'existe qu'en Iceberg v3 |
GET renvoie VARIANT chez Snowflake, VARCHAR au labo |
Liste testée des casts portables ci-dessous (B6). Côté Snowflake, le comportement des casts d'un VARIANT reste à constater chez le client |
| JSON en chaîne au labo | Chez Snowflake, une colonne VARIANT se lit sans parse explicite, et GET sur une colonne VARCHAR contenant du JSON peut demander PARSE_JSON (page de GET lue le 2026-10-23 : retour VARIANT pour une entrée semi-structurée, aucune règle de cast sur la page). Le code qui parse une chaîne JSON doit rester valide ; le comportement chez le client reste à constater |
AI_COMPLETE forme chaîne seulement au labo |
Les formes image et objet prompt ne sont pas testées au labo (pages lues le 2026-10-23) |
Fonctions AI_* de l'avenant du 2026-10-23 |
Textes seulement, fenêtre de contexte du modèle local, types de retour des macros, AI_REDACT sans valeur de sécurité : voir cortex-lab.md et contracts.md |
snowflake.cortex.sentiment renvoie un float |
Même forme des deux côtés ; ne pas la confondre avec l'objet d'AI_SENTIMENT |
| Semantic views | MetricFlow seul au labo (décision S6 du 2026-10-25) ; la CREATE SEMANTIC VIEW n'est pas générée ni versionnée. Table de traduction de dbt/models/semantic/semantic_models.yml, voir la sous-section « Traduction de MetricFlow en semantic view » ci-dessous (page https://docs.snowflake.com/en/sql-reference/sql/create-semantic-view, lue le 2026-10-24) |
| Clone | Branches et tags par table au labo ; CREATE [OR REPLACE] {DATABASE \| SCHEMA \| TABLE} ... CLONE <source> [{AT \| BEFORE} (...)] chez Snowflake (https://docs.snowflake.com/en/sql-reference/sql/create-clone, lue le 2026-10-23). Un clone est accessible en écriture et indépendant ; le clone d'une table Iceberg n'existe que si elle est gérée par Snowflake (pas avec un catalogue externe) ; l'historique de chargement n'est pas copié (des fichiers déjà chargés peuvent l'être de nouveau dans le clone) |
| Time Travel d'une table remplacée | Chez Snowflake, CREATE OR REPLACE TABLE supprime puis recrée, l'ancienne table restant récupérable en Time Travel (https://docs.snowflake.com/en/sql-reference/sql/create-table et https://docs.snowflake.com/en/user-guide/data-time-travel, lues le 2026-10-23) ; une table recréée sous le même nom ne restaure pas l'ancienne, et UNDROP échoue si le nom existe. Au labo, la table Iceberg remplacée par dbt-duckdb est supprimée de Polaris et n'est pas récupérable (pas d'UNDROP), et ses fichiers restent dans MinIO (test B7) |
| Rétention | expire_snapshots au labo ; DATA_RETENTION_TIME_IN_DAYS chez Snowflake (https://docs.snowflake.com/en/user-guide/data-time-travel) |
CREATE AI FUNCTION absente du labo |
Écart connu, sans équivalent au labo (page https://docs.snowflake.com/en/sql-reference/sql/create-ai-function, lue le 2026-10-24). La commande est marquée « Preview Feature, Open » et « Available to all accounts ». Elle crée une fonction scalaire dont le corps est une seule expression SQL qui appelle AI_COMPLETE au moins une fois, et peut aussi appeler AI_CLASSIFY, AI_FILTER ou une autre fonction AI définie par l'utilisateur ; AI_AGG est refusée (non scalaire), un corps multi-instructions aussi, RETURNS TABLE(...) n'est pas admis. Seconde forme : FROM EXPERIMENT <experiment> RUN <run> (promotion d'un essai d'optimisation, sans équivalent au labo). Droits : CREATE FUNCTION sur le schéma (pas de privilège dédié), rôle de base SNOWFLAKE.CORTEX_USER à l'appel. La fonction apparaît dans SHOW USER FUNCTIONS et se supprime par DROP FUNCTION. La page rappelle qu'AI_COMPLETE renvoie un VARIANT à caster vers le type déclaré (même écart que pour GET, ci-dessous). Au labo, aucune instruction CREATE AI FUNCTION n'est reconnue par DuckDB : un code client qui en dépend ne s'exécute pas au labo |
Surcharges de macros propres au labo
dbt/macros/drop_relation.sql et dbt/macros/intermediate_relation.sql sont préfixées duckdb__ : elles contournent des limites de DuckDB et de Polaris (suppression sans CASCADE, nom intermédiaire unique) et ne s'appliquent ni à dbt-trino ni à dbt-snowflake. Rien à retirer chez le client. Chez Snowflake, une matérialisation table est un CREATE OR REPLACE TABLE ; au labo la table Iceberg est recréée à chaque exécution et son historique de snapshots Iceberg repart de zéro, comme une table recréée chez Snowflake dont l'ancienne version n'est plus la table courante (voir la ligne « Time Travel d'une table remplacée » ci-dessus).
dbt/macros/trino_list_relations.sql est préfixée trino__ : la macro de l'adapter lit system.metadata.materialized_views, catalogue que les règles de Trino refusent à lab_tech. Même requête sans cette jointure (le labo n'a aucune vue matérialisée). Rien à retirer chez le client.
Voie Horizon IRC : moteurs externes sur les tables Iceberg du client
Si le client garde des tables Iceberg gérées par Snowflake et veut les lire ou les écrire depuis Trino, DuckDB ou PyIceberg, il passe par le catalogue REST Iceberg de Horizon, compatible avec l'API de Polaris. Cette voie est documentée ici seulement : le dépôt ne contient aucune configuration qui la cible.
Sources lues le 2026-10-24 : https://docs.snowflake.com/en/user-guide/tables-iceberg-access-using-external-query-engine-snowflake-horizon (page non datée ; la légende du schéma dit lecture et écriture « Generally Available ») et https://docs.snowflake.com/en/release-notes/2026/other/2026-05-26-tables-iceberg-query-using-external-query-engine-snowflake-horizon-writes-ga (écriture GA le 2026-05-26 ; lecture GA le 2026-02-06 d'après la veille, veille-snowflake-2026-10.md).
| Élément | Ce que dit la page |
|---|---|
| Point d'accès | https://<organisation>-<compte>.snowflakecomputing.com/polaris/api/catalog |
Nom du catalogue (warehouse) |
Le nom de la base Snowflake, pas celui d'un warehouse. Une base créée sans guillemets doit être donnée en majuscules, même si elle a été créée en minuscules. La même règle s'applique aux namespaces et aux tables dans l'exemple de lecture des métadonnées |
| Namespaces | Correspondent aux schémas de la base (règle implicite des exemples : use namespace <schéma>, chemin /<base>/namespaces/<namespace>/tables/<table>) |
| Authentification | OAuth externe ; paire de clés (JWT signé échangé contre un jeton d'accès) ; jeton d'accès programmatique (PAT) ; fédération d'identité de charge de travail (OIDC) |
| Credentials | En-tête X-Iceberg-Access-Delegation: vended-credentials, requis pour le vending |
| Moteurs cités comme pris en charge | Apache Doris, Apache Flink, Apache Spark, Dremio, DuckDB, PyIceberg, StarRocks, Trino |
| Versions de table | Lecture et écriture des tables Iceberg v2 et v3 |
| Écritures non prises en charge depuis un moteur externe | CREATE TABLE AS SELECT (CTAS) ; equality deletes ; création de tags et de branches ; rollback vers un snapshot antérieur ; montée de version v2 vers v3 ; CREATE TABLE avec un emplacement de base explicite ; écriture dans les tables dynamiques ; écriture dans les tables Iceberg partagées ; enregistrement de tables ; écriture dans une table convertie avec vended credentials ; écriture dans une table convertie de gérée en externe vers gérée par Snowflake |
| Stockage | Amazon S3, Google Cloud ou Azure dans les régions commerciales ; le stockage compatible S3 hors AWS n'est pas encore pris en charge |
| Droits (lecture) | SELECT sur la table, USAGE (ou autre privilège) sur la base et le schéma ; le rôle propriétaire de la table doit garder USAGE sur le volume externe, sinon les opérations à vended credentials échouent |
| Droits (écriture DML) | SELECT, UPDATE, TRUNCATE, INSERT, DELETE sur la table, plus USAGE sur la base et le schéma ; CREATE ICEBERG TABLE sur le schéma et USAGE sur le volume externe pour créer une table ; CREATE SCHEMA sur la base pour créer un namespace ; OWNERSHIP pour renommer une table ou changer ses colonnes |
| Facturation | 0,5 crédit par million d'appels d'API (Cloud Services), début annoncé au second semestre 2026, « subject to change » ; frais de sortie inter-régions le cas échéant |
| Tables gérées en externe | Accessibles par le même point d'accès quand elles sont dans une base liée à un catalogue (page séparée) |
Conséquences pour la transposition (déductions de cette documentation, à vérifier chez le client) :
- Casse du catalogue : le labo nomme le catalogue
analyticsen minuscules (iceberg.rest-catalog.warehouse=analyticsdansinfra/trino/catalog/analytics.properties,warehouseégal àLAB_DATABASEdanslab/iceberg.pyet dans l'attachement DuckDB). Vers Horizon, la valeur attendue estANALYTICS(lu). Les namespaces du labo (raw,standardized...) devraient de même être donnés en majuscules (inféré de l'exemple de la page). La règle « identifiants en minuscules, jamais quotés » reste valable pour le SQL exécuté dans Snowflake ; elle ne suffit pas pour les noms passés à un client REST. - CTAS : la matérialisation
tablede dbt-duckdb et celle de dbt-trino créent la table parCREATE TABLE ... AS SELECT(voir l'avenant du 2026-10-23 dePLAN.md). Exécutées via Horizon, elles relèveraient de l'écriture non prise en charge (inféré). Chez le client, dbt s'exécute avecdbt-snowflake, dans Snowflake, et n'est pas concerné. - Tags et branches :
lab/maintenance.py(équivalent du clone par branches et tags) ne s'applique pas via Horizon (lu : création de tags et de branches non prise en charge). - Écrivains PyIceberg : le chargeur raw et l'écrivain de
forecastcréent la table sans emplacement explicite puis ajoutent des lignes ; ces opérations n'apparaissent pas dans la liste des écritures refusées (inféré, à vérifier).lab/iceberg.pydésactive aujourd'hui le vending (en-tête vide) et passe des clés MinIO statiques : vers Horizon, il faudrait l'en-têtevended-credentialset une authentification Snowflake (PAT, paire de clés, OAuth externe ou fédération d'identité). - Stockage du labo : MinIO est un stockage compatible S3 hors AWS, non pris en charge par Horizon (lu). Le labo ne peut donc pas servir de stockage à des tables gérées par Snowflake, et la voie Horizon ne peut pas être testée au labo.
Toute configuration Trino, DuckDB ou PyIceberg qui ciblerait Horizon change le périmètre et passe par un avenant à PLAN.md.
Traduction de MetricFlow en semantic view
Décision S6 du 2026-10-25 : la couche sémantique du labo reste MetricFlow seul (dbt/models/semantic/semantic_models.yml). Aucun générateur, aucune semantic view versionnée et aucun paquet dbt_semantic_view ne sont ajoutés. Si le client utilise des semantic views, Cortex Analyst ou Cortex Agents, la semantic view s'écrit à la main à partir de la table ci-dessous (clauses de https://docs.snowflake.com/en/sql-reference/sql/create-semantic-view, lue le 2026-10-24 ; BCR-2287 du bundle 2026_07 lu le même jour). Le labo ne peut ni créer ni interroger une semantic view : cette traduction n'a jamais été exécutée.
| MetricFlow (labo) | Semantic view | Remarque |
|---|---|---|
Modèle sémantique hotel_daily sur fct_hotel_daily |
Table logique hotel_daily AS analytics.semantic.fct_hotel_daily PRIMARY KEY (hotel_id, business_date) |
L'entité primaire hotel_day n'a pas d'expression : la clé se déclare en colonnes |
Modèle sémantique hotel sur dim_hotel |
Table logique hotel AS analytics.semantic.dim_hotel PRIMARY KEY (hotel_id) |
|
Entité étrangère hotel (hotel_id) |
RELATIONSHIPS (hotel_daily (hotel_id) REFERENCES hotel) |
La cible doit être en PRIMARY KEY ou UNIQUE |
Dimension temporelle business_date, granularité day, agg_time_dimension |
DIMENSIONS (hotel_daily.business_date AS business_date) |
La page ne décrit ni dimension temporelle ni granularité : les granularités de MetricFlow (metric_time__month...) deviennent des dimensions explicites (DATE_TRUNC), à écrire une par une |
Dimensions city, hotel_name |
DIMENSIONS (hotel.city AS city, hotel.hotel_name AS hotel_name) |
|
Mesures rooms_available, rooms_sold, room_revenue (sum) et métriques simples *_total |
METRICS (hotel_daily.rooms_sold_total AS SUM(rooms_sold), ...) |
BCR-2287 : interroger des FACTS avec des DIMENSIONS n'est plus pris en charge (activé par défaut) ; exposer des métriques plutôt que des faits |
Métriques ratio occupancy_rate, adr, revpar |
hotel_daily.occupancy_rate AS SUM(rooms_sold) / SUM(rooms_available) (même table) |
Division par zéro à traiter dans l'expression (DIV0 chez Snowflake, à vérifier) ; les métriques dérivées entre tables utilisent USING, en préversion |
Points non vérifiés (classe c) : les tables Iceberg comme tables logiques (la page ne les admet ni ne les exclut) ; la procédure SYSTEM$CREATE_SEMANTIC_VIEW_FROM_YAML (spécification YAML propre à Snowflake, page non lue) ; l'existence d'un outil de conversion de MetricFlow (aucun trouvé le 2026-10-24, absence non confirmée). Le paquet dbt Snowflake-Labs/dbt_semantic_view (version 1.0.3 citée par la page dbt, Snowflake seul, corps écrit à la main) deviendrait utile dès que le client confirme l'usage de semantic views ; il ajouterait un code tiers, un accès réseau pour dbt deps et deux définitions des mêmes KPI à garder cohérentes.
Ce qui n'est pas outillé dans le dépôt
- Cible
dbt-snowflake: vérifiée hors connexion le 2026-10-23, avec un compte factice du domaine réservé.invalidet des variables d'environnementSNOWFLAKE_*factices (le test coupe aussi le réseau par des proxys fermés).dbt parse --target snowflakeaboutit sans connexion et écrit le manifeste (B1,tests/ingest/test_dbt_snowflake_offline.py).dbt compile --target snowflake --no-introspect --no-populate-cacheaboutit aussi sans connexion (B2) : le SQL compilé litanalytics.raw.pms_dailyet ne cite aucun identifiant ; la macrogetse rend enget(payload, 'k')natif (aucun modèle du projet n'appellegetaujourd'hui, le critère s'est donc vérifié sur un appel en ligne). La validité du SQL compilé pour Snowflake, la compilation avec introspection et l'exécution restent à constater chez le client. Le groupesnowflake(dbt-snowflake==1.12.4) est installé par défaut en développement. - Chargement chez le client :
ingest/écrit dans Iceberg via Polaris et lit MinIO. L'équivalent chez Snowflake (stage,COPY INTO, Snowpipe, tablesintake) n'a pas d'implémentation dans le dépôt. - Prévision dans SPCS : la lecture de standardized (DuckDB sur Polaris) et l'écriture (PyIceberg via Polaris) sont propres au labo ; la spécification de service SPCS n'est pas dans le dépôt (voir prevision.md).
- Données partagées :
shared_calendarsimule un partage ; chez le client, la source réelle (partage, Marketplace) est à brancher. - Accès par Horizon IRC : aucune configuration de moteur ne cible le catalogue REST de Horizon (voir la section dédiée ci-dessus).
Casts portables de GET (B6)
La macro get renvoie un VARCHAR (chaîne JSON sans guillemets, autres valeurs en texte JSON, NULL pour un null JSON ou une clé absente). Testé au labo dans tests/cortex_lab/test_get_casts.py (DuckDB 2.0.0), sur des valeurs JSON chaîne, nombre, entier, booléen, date, null et clé absente :
Cast de GET(x, 'f') |
Portable au labo | Échoue au labo |
|---|---|---|
varchar |
toujours (la chaîne, ou le texte JSON de la valeur) | jamais |
integer, bigint |
nombre ou chaîne numérique (une fraction est arrondie : 12.5 donne 13) ; bigint pour les grands entiers |
booléen, texte non numérique, date, entier trop grand pour integer |
double, decimal(38, s) |
nombre ou chaîne numérique | booléen, texte non numérique, date |
boolean |
booléen JSON | nombre, texte, chaîne numérique |
date |
chaîne ISO AAAA-MM-JJ |
tout le reste |
| tous les types | NULL pour un null JSON et pour une clé absente |
Règle : caster vers le type qui correspond à la valeur JSON ; un cast qui change de nature (booléen vers nombre, texte vers nombre) échoue au labo et n'est pas portable. Le rendu de la macro dbt get par adapter est testé : get(payload, 'k') pour duckdb et snowflake, json_extract_scalar(payload, '$.k') pour trino.
Résultats de la vérification du 2026-10-23
| Point | Résultat |
|---|---|
B1 dbt parse sur snowflake |
Aboutit hors connexion, manifeste écrit |
B2 dbt compile --no-introspect sur snowflake |
Aboutit sans connexion ; SQL lisant analytics.raw.pms_daily, sans identifiant cité |
B3 dbt build sur trino |
Premier build : passe (après la macro trino__list_relations_without_caching) ; mf query --metrics occupancy_rate aboutit si target: du profil vaut trino (la CLI mf n'a pas d'option --target). Second build : échouait le 2026-10-23 (Trino envoie le DROP TABLE avec purge, Polaris le refusait) ; passe depuis le 2026-10-24 grâce à la propriété de catalogue polaris.config.drop-with-purge.enabled fixée par infra/polaris/init_catalog.py : les tables et seeds sont remplacés, les versions SCD2 fermées |
B4 dbt-ol build |
Aboutit ; jobs et datasets visibles dans Marquez ; espace de noms des datasets duckdb://:memory:, différent de iceberg://analytics du chargeur (écart documenté, pas de changement du code d'émission) |
| B5 Time Travel | FOR TIMESTAMP AS OF inclut le snapshot validé à l'instant exact ; le snapshot parent donne BEFORE(STATEMENT) ; current_timestamp - INTERVAL 'n' SECOND donne AT(OFFSET) (voir socle.md) |
B6 casts de GET |
Liste ci-dessus |
| B7 fichiers orphelins | Les fichiers d'une table remplacée et d'une table supprimée restent dans MinIO (voir exploitation.md) |
| B11 fenêtre de contexte | 32 768 jetons (chat), 2 048 jetons (embeddings) ; Ollama coupe en silence, le labo refuse avant l'appel |
| B12 embeddings | cortex-embed renvoie 1 024 flottants avec la clé du labo |
| B13 syntaxe DuckDB 2.0.0 | Aucun nom ne masque une fonction existante ; => et := sont acceptés pour les paramètres nommés d'une macro |
| B14 agrégat | list(col) dans une macro vers une UDF Arrow à argument VARCHAR[] fonctionne avec GROUP BY, sur une constante et sur une table vide |
À vérifier chez le client (classe c)
Ces points exigent le compte Snowflake du client ; ils ne sont pas implémentés au labo.
- Statut des bundles BCR-2184 et BCR-2358 dans le compte (le titre actuel de BCR-2358 est « Enabled by default »), et valeur de
AI_SQL_ERROR_HANDLING_USE_FAIL_ON_ERROR(paramètre absent de la liste de paramètres de session lue). - Modèles Cortex disponibles dans la région du client, et inférence inter-régions.
- Comparaisons et casts de
GETsurVARIANTet sur une colonne VARCHAR contenant du JSON (PARSE_JSONéventuellement nécessaire). - Compilation avec introspection et exécution de
dbt-snowflake, validité du SQL compilé. - Lineage Snowsight sur les tables du client (Enterprise Edition).
- Type des tables Iceberg du client (gérées par Snowflake ou catalogue externe), qui conditionne le clone.
- Time Travel et
UNDROPselon la rétention du compte. - Comptes de jetons et réponses réelles des fonctions Cortex ; fenêtres de contexte par modèle ; dimension de
multilingual-e5-largeet desnowflake-arctic-embed-l-v2.0-8k; prise en charge deVECTORdans les tables Iceberg. HistorySourceet écrivain Snowflake de la prévision (voir prevision.md).
Points ajoutés après la veille du 2026-10-24 (veille-snowflake-2026-10.md, action P6). Chaque source a été relue le 2026-10-24.
- Rôles de modèle (BCR-2378) : le contrôle d'accès par rôles de modèle devient le seul mécanisme d'accès aux modèles ;
CORTEX_MODELS_ALLOWLISTn'est plus consulté et les modèles d'embedding sont désormais couverts (AI_EMBED,AI_MULTI_EMBED,AI_SIMILARITY,EMBED_TEXT_768,EMBED_TEXT_1024). Bundle 2026_07, « Enabled by default », activation générale annoncée en janvier 2027. À constater : valeur deCORTEX_MODELS_ALLOWLIST(SHOW PARAMETERS LIKE 'CORTEX_MODELS_ALLOWLIST' IN ACCOUNT), présence de l'octroiCORTEX-MODEL-ROLE-ALLàPUBLIC, rôles de modèle accordés aux rôles qui exécutent dbt et la prévision ; tester avec un rôle autre qu'ACCOUNTADMIN, qui a toujours accès à tous les modèles. Source : https://docs.snowflake.com/en/release-notes/bcr-bundles/2026_07/bcr-2378. - Inférence inter-régions (BCR-2376) : quand le bundle 2026_06 (« Generally enabled ») s'applique, Snowflake fixe par défaut
CORTEX_ENABLED_CROSS_REGIONà une valeur limitée au fournisseur et à la géographie du compte (par exempleAWS_EU) ; les comptes qui ont déjà une valeur explicite (y comprisDISABLED) et les comptes des secteurs finance, santé, administration, FedRAMP et VPS ne sont pas concernés. À constater : valeur effective du paramètre dans le compte du client, et modèles disponibles dans cette géographie. Source : https://docs.snowflake.com/en/release-notes/bcr-bundles/2026_06/bcr-2376. - Compte « inactif » au sens de BCR-2432 : dans le bundle 2026_08 (« Disabled by default »), les fonctions historiques
SNOWFLAKE.CORTEX(COMPLETE,TRY_COMPLETE,CLASSIFY_TEXT,TRANSLATE,SENTIMENT,ENTITY_SENTIMENT,PARSE_DOCUMENT,COUNT_TOKENS,SUMMARIZE,EXTRACT_ANSWER,EMBED_TEXT_768,EMBED_TEXT_1024) échouent dans un compte qui n'en a appelé aucune du 9 juillet au 6 octobre 2026 ; un usage postérieur à la publication du bundle ne change pas ce classement. Le module Pythonsnowflake.cortexest concerné, sauf à partir desnowflake-ml-python2.4.0 qui appelle les fonctionsAI_*. À constater : classement du compte du client, et version desnowflake-ml-pythoninstallée chez lui. La page ne dit pas comment vérifier l'usage du compte. Source : https://docs.snowflake.com/en/release-notes/bcr-bundles/2026_08/bcr-2432. - Privilèges
USE AI FUNCTIONSetUSE AI FUNCTION <nom>: le privilège de compteUSE AI FUNCTIONSest accordé àPUBLICpar défaut (note du 2026-02-20) ; le privilège par fonctionUSE AI FUNCTION <nom>est GA depuis le 2026-05-13, et un rôle qui détient l'un ou l'autre peut appeler la fonction. À constater : retrait éventuel deUSE AI FUNCTIONSàPUBLICet privilèges par fonction accordés aux rôles qui exécutent dbt,ingestet la prévision (le labo n'a aucun contrôle d'accès par fonction). Sources : https://docs.snowflake.com/en/release-notes/2026/other/2026-02-20-use-ai-functions-privilege, https://docs.snowflake.com/en/release-notes/2026/other/2026-05-13-use-ai-function-per-function-privileges. - Modèles legacy :
SHOW CORTEX BASE MODELSaffiche pour chaque modèlelifecycle_status,legacy_dateeteol_date(syntaxe complète non lue). À constater : statut du modèle retenu pourCORTEX_COMPLETE_MODELet pour les appelsAI_COMPLETEdu client ; un modèle passé en legacy n'est plus appelable par un compte qui ne l'utilisait pas avant la date (vague du 2026-08-12, d'après la veille). Source : https://docs.snowflake.com/en/user-guide/snowflake-cortex/aisql-regional-availability. - Droits après
CREATE OR REPLACE(BCR-2433) : dans le bundle 2026_08 (« Disabled by default »),CREATE OR REPLACErecopie les droits de l'objet remplacé, saufOWNERSHIP, comme siCOPY GRANTSétait précisé ; concerne tables, vues, vues matérialisées, streams, semantic views, fonctions, procédures et Cortex Agents ; la clauseIGNORE GRANTSrétablit l'ancien comportement. Les matérialisationstablededbt-snowflakesont desCREATE OR REPLACE(inféré) : à constater, état du bundle dans le compte et droits observés sur une table recréée par dbt. Source : https://docs.snowflake.com/en/release-notes/bcr-bundles/2026_08/bcr-2433. - Version Iceberg des tables du client : Snowflake crée les tables Iceberg en v2 par défaut ;
ICEBERG_VERSION_DEFAULT(compte, base, schéma) ouICEBERG_VERSION = 3à la création donnent du v3 ; la montée en v3 est définitive ; dbt Projects on Snowflake n'est pas pris en charge sur les tables v3. À constater : version des tables du client et valeur deICEBERG_VERSION_DEFAULT. Le labo reste en v2. Source : https://docs.snowflake.com/en/user-guide/tables-iceberg-v3-specification-support.
Références
- Tables Iceberg dans Snowflake : https://docs.snowflake.com/en/user-guide/tables-iceberg (vérifiée le 2026-10-22).
- Snowpipe : https://docs.snowflake.com/en/user-guide/data-load-snowpipe-intro (vérifiée le 2026-10-22).
- Snowpark Container Services : https://docs.snowflake.com/en/developer-guide/snowpark-container-services/overview (vérifiée le 2026-10-22).
- Modèle custom du Model Registry : https://docs.snowflake.com/en/developer-guide/snowflake-ml/model-registry/bring-your-own-model-types (vérifiée le 2026-10-22).
- Module
snowflake.cortex: https://docs.snowflake.com/en/developer-guide/snowpark-ml/reference/latest/cortex (liste et paramètres lus le 2026-10-23, la page répond ; types de retour lus dans le code desnowflake-ml-python2.6.0). - Types Iceberg côté Snowflake : https://docs.snowflake.com/en/user-guide/tables-iceberg-data-types (lue le 2026-10-23).
GET: https://docs.snowflake.com/en/sql-reference/functions/get (relue le 2026-10-23).CREATE ... CLONE: https://docs.snowflake.com/en/sql-reference/sql/create-clone (lue le 2026-10-23).- Accès des moteurs externes par Horizon IRC : https://docs.snowflake.com/en/user-guide/tables-iceberg-access-using-external-query-engine-snowflake-horizon (lue le 2026-10-24).
CREATE AI FUNCTION: https://docs.snowflake.com/en/sql-reference/sql/create-ai-function (lue le 2026-10-24).- Iceberg v3 chez Snowflake : https://docs.snowflake.com/en/user-guide/tables-iceberg-v3-specification-support (lue le 2026-10-24).