Adição de modelos personalizados a uma sala limpa¶
Tanto provedores quanto consumidores podem adicionar modelos personalizados a uma sala limpa. Os modelos personalizados são executados da mesma forma que os modelos fornecidos pelo Snowflake.
Nota
Um modelo de sala limpa é um JinjaSQL válido. Você deve ler o guia de referência de sala limpa para modelos personalizados antes de tentar criar seus próprios modelos de sala limpa.
Modelos personalizados escritos pelo provedor¶
Os provedores podem adicionar um modelo personalizado a uma sala limpa sem aprovação do consumidor. Os consumidores podem executar um modelo escrito pelo provedor sem aprovação. As próximas seções descrevem como o provedor pode adicionar um modelo personalizado, e como o consumidor o executa, usando a API.
Se o provedor quiser criar um modelo que um consumidor possa executar na UI de salas limpas, ele deve criar um formulário de entrada de usuário para o modelo.
Adição de um modelo escrito pelo provedor¶
Os provedores adicionam modelos personalizados, um de cada vez, chamando provider.add_custom_sql_template
e passando o modelo JinjaSQL como uma cadeia de caracteres. Os modelos personalizados aparecem na lista de modelos da sala limpa e se comportam da mesma forma que os modelos fornecidos pelo Snowflake. Uma sala limpa pode conter qualquer combinação de modelos personalizados e fornecidos pelo Snowflake.
Você também pode carregar UDFs Python personalizadas para o seu modelo chamar.
Dica
Ao adicionar um modelo personalizado para uso dos consumidores, você deve fornecer uma documentação que descreva o que o modelo faz e os argumentos obrigatórios e opcionais usados pelo modelo.
O seguinte exemplo mostra como um provedor adiciona um modelo personalizado à sala limpa:
CALL samooha_by_snowflake_local_db.provider.add_custom_sql_template(
$cleanroom_name,
$basic_template_name,
$$
SELECT
COUNT(*) AS total_count
FROM IDENTIFIER({{ my_table[0] }}) AS c
INNER JOIN IDENTIFIER({{ source_table[0] }}) AS p
ON IDENTIFIER({{ consumer_id | join_policy }}) = IDENTIFIER({{ provider_id | join_policy }})
{% if where_clause %}
WHERE {{ where_clause | sqlsafe }}
{% endif %};
$$
);
Na maioria dos modelos, incluindo o exemplo anterior, os nomes das colunas devem ser totalmente qualificados com o nome da tabela para evitar conflitos entre eles. Isso ocorre porque não é fácil concatenar um prefixo de nome de tabela com um nome de coluna no prefixo e obter um identificador válido (IDENTIFIER(p.{{col_name | sqlsafe }})
é um erro). Portanto, pode ser necessário que o autor da chamada forneça um nome de tabela totalmente qualificado, e não apenas um nome de coluna. Os nomes das tabelas devem usar os aliases p
e c
aprovados.
Execução de um modelo escrito pelo provedor¶
Ao usar a API de salas limpas, os consumidores chamam consumer.run_analysis
para executar um modelo, e os provedores chamam provider.submit_analysis_request
para análises executadas pelo provedor.
Se você quiser que um modelo seja executável na UI de salas limpas, o provedor deverá criar um formulário de entrada de usuário para o modelo. Somente os modelos escritos pelo provedor podem ser executados na UI de salas limpas.
Os colaboradores da sala limpa podem ver o JinjaSQL de qualquer modelo em uma sala limpa chamando consumer.view_template_definition
, a menos que o provedor tenha ocultado o modelo. Somente é possível ocultar modelos escritos pelo provedor.
Você pode chamar consumer.get_arguments_from_template
para analisar e listar as variáveis usadas em um modelo. No entanto, em modelos grandes ou complexos, esse procedimento pode não listar todas as variáveis de modelo, portanto, forneça uma documentação útil aos usuários do modelo.
O seguinte exemplo mostra como o consumidor executa o modelo personalizado do provedor que foi mostrado:
CALL samooha_by_snowflake_local_db.consumer.run_analysis(
$cleanroom_name,
'basic_template',
['SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS'], -- Populates the my_table array.
['SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS'], -- Populates the source_table array.
OBJECT_CONSTRUCT(
'consumer_id', 'c.hashed_email', -- hashed_email column from the consumer's table.
'provider_id', 'p.hashed_email', -- hashed_email column from the provider's table.
'where_clause','c.status = $$MEMBER$$ AND c.age_band > 30' -- $$...$$ is used to stringify the column value.
)
);
Código de exemplo de modelo do provedor¶
Este é um exemplo de código completo que mostra como um provedor adiciona um modelo personalizado, e como o consumidor o executa. Você precisa de duas contas separadas com a API de salas limpas instalada para executar o código: uma para atuar como provedor e outra para atuar como consumidor.
Modelos personalizados escritos pelo consumidor¶
O consumidor poderá adicionar um modelo personalizado à sala limpa se o provedor aprovar. Depois de adicionado à sala limpa, o modelo escrito pelo consumidor poderá ser executado da mesma forma que um modelo escrito pelo provedor. Veja como o consumidor adiciona um modelo personalizado:
O provedor cria, compartilha e publica uma sala limpa como de costume.
O consumidor instala e configura a sala limpa como de costume.
O consumidor chama
consumer.create_template_request
e passa a cadeia de caracteres do modelo personalizado.O provedor chama
provider.list_pending_template_requests
para ver as solicitações pendentes.O provedor pode aprovar (
provider.approve_template_request
) ou rejeitar (provider.reject_template_request
) a solicitação do consumidor para executar seu próprio modelo. (Também há versões em massa desses métodos para aprovar ou rejeitar várias solicitações.) Se o provedor aprovar, o modelo será adicionado à sala limpa imediatamente.Se o provedor aprovar o modelo, ele deverá adicionar as políticas de junção e de coluna necessárias ao modelo e seus dados. Se o provedor não tiver uma política de junção ou de coluna na sala limpa, será usado o padrão, ou seja, todas as colunas do provedor podem ser unidas e projetadas.
O consumidor verifica o status de sua solicitação chamando
consumer.list_template_requests
(que mostra o status, incluindo o de rejeição com uma explicação) ouconsumer.view_added_templates
(para ver se o modelo foi adicionado à sala limpa).Opcionalmente, o consumidor adiciona políticas de coluna ao modelo.
O consumidor executa o modelo chamando
consumer.run_analysis
como de costume.
Nota
O provedor poderá executar um modelo adicionado por um consumidor se o consumidor conceder permissão.
Exemplo de modelo do consumidor¶
Este é um exemplo de código completo que mostra como o consumidor pode enviar e executar um modelo personalizado. Carregue os seguintes arquivos de pasta de trabalho em sua conta Snowflake. Você precisa de duas contas separadas com a API de salas limpas instalada para executar o código: uma para atuar como provedor e outra para atuar como consumidor.
Definição de formulário de entrada de usuário para um modelo personalizado¶
Para que um modelo personalizado possa ser executado na UI de salas limpas, o provedor deve definir um formulário de entrada para o modelo. Esse requisito é aplicado mesmo que o modelo não tenha argumentos para o consumidor definir. Os consumidores não podem definir um formulário de entrada de usuário para um modelo.
Importante
Se você usou provider.restrict_table_options_to_consumers
ou provider.restrict_template_options_to_consumers
para restringir tabelas ou modelos a usuários específicos, essas restrições não funcionarão como esperado na UI de salas limpas. Você não deve habilitar modelos para uso da UI em salas limpas com essas restrições.
Um formulário de configuração permite que os usuários da UI de salas limpas passem valores ao modelo personalizado, semelhante a como você passa valores para um modelo quando usa a API.
O seguinte exemplo mostra um modelo personalizado que usa três variáveis: max_age
, favorite_color
e source_table
:
CALL samooha_by_snowflake_local_db.provider.add_custom_sql_template(
$cleanroom_name,
'color_picker_template',
$$
SELECT p.hashed_email
FROM source_table[0] AS p
WHERE
p.age <= {{ max_age }} AND
UPPER(p.favorite_color) = UPPER({{ favorite_color }});
$$);
O seguinte exemplo mostra como passar as variáveis de modelo ao executar o modelo personalizado anterior no código:
CALL samooha_by_snowflake_local_db.consumer.run_analysis(
$cleanroom_name,
'color_picker_template',
[], -- Consumer tables, assigned to my_table array.
['MYDB.MYSCH.COLOR_PREFERENCES'], -- Provider tables, assigned to source_table array.
object_construct(
'max_age', 30, -- Assign max_age.
'favorite_color', 'blue' -- Assign favorite_color.
)
);
Para executar esse modelo na UI de salas limpas, você deve definir um formulário no qual o consumidor designa essas variáveis de modelo. O seguinte exemplo mostra como definir um formulário simples no qual o consumidor pode designar valores a max_age
, favorite_color
e source_table
:
CALL samooha_by_snowflake_local_db.provider.add_ui_form_customizations(
$cleanroom_name,
'color_picker_template',
{ -- Top-level template settings.
'display_name': 'Color matcher',
'description': 'See which users like the same color as you',
'methodology': 'Choose a color and a max age',
'render_table_dropdowns': {
'render_consumer_table_dropdown': false,
'render_provider_table_dropdown': true -- Show a dropdown of provider tables.
} -- Chosen value is assigned to source_table.
},
{ -- Form entry elements, one per template argument.
'max_age': {
'type': 'integer',
'display_name': 'Maximum age',
'description': 'Matching user must be less than or equal to this value.',
'required': TRUE
},
'favorite_color': {
'type': 'dropdown',
'display_name': 'Favorite color',
'description': 'Choose the favorite color to match.',
'choices': ['Red', 'Blue', 'Green', 'Yellow'],
'required': TRUE
}
},
{} -- Output config not used in this example.
);
-- You must always call this procedure to propagate UI changes.
CALL samooha_by_snowflake_local_db.provider.create_or_update_cleanroom_listing(
$cleanroom_name);
O formulário definido aparece na UI de salas limpas quando o consumidor executa o modelo na etapa Configure Analysis & Query. O formulário inclui um seletor de tabelas para source_table
, chamado Collaborator table, um elemento de seletor de números inteiros para max_age
chamado Maximum age e um menu suspenso de nomes de cores para favorite_color
chamado Favorite color, conforme mostrado nesta imagem:

Você também pode definir menus suspensos que são pré-preenchidos com colunas das políticas de junção e de coluna do provedor, das tabelas e muito mais. Para obter mais informações sobre tipos de elementos de formulário, consulte add_ui_form_customizations.
Preenchimento de source_table
e my_table
¶
As variáveis de modelo padrão source_table
e my_table
podem ser preenchidas da seguinte maneira:
Habilite os menus suspensos do seletor de tabelas padrão: esses menus são de seleção única. Você pode mostrá-los ou ocultá-los usando as configurações
render_provider_table_dropdown
erender_consumer_table_dropdown
. Os menus suspensos passam nomes de tabela totalmente qualificados para as variáveis de modelosource_table
emy_table
, respectivamente.
Qualificação dos nomes de colunas¶
A maioria dos modelos exige que todos os nomes de colunas sejam totalmente qualificados para evitar ambiguidade.
O modelo deve ser o alias de todas as tabelas, como p
ou c
, dependendo se são tabelas de provedor ou consumidor. O modelo deve fazer referência a todas as colunas usando o respectivo alias p
ou c
. Saiba mais sobre o uso de alias.
Se você criar um seletor de colunas suspenso, deverá fornecer o alias de tabela p
ou c
explicitamente em uma matriz de choices
do menu suspenso, ou adicionar o alias ao seu modelo.
O seguinte exemplo mostra como fornecer o alias da tabela em um menu suspenso:
'provider_join_col': {
'display_name': 'Provider Join Column',
'choices': ['p.HASHED_EMAIL', 'p.HASHED_SSN'],
'type': 'dropdown',
'description': 'Select the provider column to join users on.',
'infoMessage': 'We recommend using HASHED_EMAIL.',
'size': 'M',
'group': 'Enable Provider Features'
}
No entanto, esse método é limitante porque você precisa saber todos os nomes das colunas com antecedência.
Se preferir, preencha dinamicamente o menu suspenso de uma coluna fornecendo uma propriedade references
. No entanto, esse seletor retorna nomes de colunas simples, por exemplo, hashed_email
, em vez de nomes de colunas totalmente qualificados, como p.hashed_email
. Se os nomes de colunas simples forem retornados, defina explicitamente o escopo da coluna para a tabela no seu modelo. Por exemplo, o seguinte código cria um menu suspenso no qual o usuário pode selecionar uma coluna com base na política de junção do provedor:
'p_join_col': { 'type': 'dropdown', 'references': ['PROVIDER_JOIN_POLICY'] }
Para usar o nome da coluna em um modelo, o modelo deve codificar o alias da tabela na frente do nome da coluna, como mostrado neste exemplo:
SELECT p.{{ p_join_col | sqlsafe }} FROM table_col AS p;
Recomendações para desenvolvimento de modelo que pode ser executado na UI de salas limpas¶
As seguintes etapas mostram um fluxo de trabalho recomendado para desenvolvimento de um modelo que pode ser executado na UI de salas limpas:
1. Desenvolvimento do modelo¶
Primeiro, desenvolva o modelo e os possíveis scripts que ele chama usando apenas a API de salas limpas nas contas tanto do provedor quanto do consumidor. O teste do modelo na API é muito mais rápido e menos propenso a erros do que na UI.
Teste o seu modelo cuidadosamente na API, no lado tanto do provedor quanto do consumidor, para garantir que o ele faça exatamente o que você quer. O teste na API é muito rápido, e as alterações são propagadas imediatamente para a conta do consumidor.
Depois de testar e comprovar que seu modelo é executado exatamente como você quer, prossiga para criar o formulário de entrada.
2. Desenvolvimento do formulário de entrada¶
Quando o modelo e todos os scripts carregados estiverem funcionando como pretendido, comece a trabalhar no formulário de entrada. Neste estágio, você não usa a API na conta de provedor, mas a UI na conta de consumidor.
Quando você faz alterações usando a API, alguns valores na UI são atualizados imediatamente, alguns são atualizados quando o usuário clica em Refresh e outros são atualizados apenas a cada 10 minutos. Portanto, quando você trabalhar no formulário de entrada, crie-o e atualize-o no lado do provedor usando a API, mas instale e configure a sala limpa na conta de consumidor usando a UI de salas limpas, não a API. Isso garante que você use os dados atualizados na UI de salas limpas.
Além disso, cada vez que você fizer alterações no formulário de entrada na API, crie uma nova sala limpa para garantir que use os dados mais recentes. Use um número incremental no nome, por exemplo, «Minha sala limpa 1», «Minha sala limpa 2» e assim por diante. Em seguida, instale a sala limpa no cliente usando a UI. Por fim, exclua as salas limpas antigas porque há um limite para o número de salas limpas armazenadas na conta.
Um formulário de entrada deve ser anexado a um modelo, caso contrário, a sala limpa e o formulário não poderão ser executados na UI de salas limpas. Ao desenvolver o formulário, considere usar um modelo que apenas espelhe todos os valores selecionados no formulário para que você possa verificar quais valores são enviados para o modelo.
Por exemplo, suponha que seu modelo de produção seja parecido com este:
SELECT {{ col1 | sqlsafe | column_policy }}, {{ col2 | sqlsafe | column_policy }}
FROM IDENTIFIER({{ source_table[0] }}) AS p
JOIN IDENTIFIER({{ my_table[0] }}) AS c
Você pode criar o seguinte modelo para espelhar todos os valores desse modelo de produção:
SELECT
{{ col1 | default('Undefined')}},
{{ col2 | default('Undefined') }},
{{ source_table[0] | default('Undefined') }},
{{ my_table[0] | default('Undefined') }},
{{ provider_join_col | default('Undefined') }},
{{ consumer_join_col | default('Undefined') }}
;
Em seguida, crie um formulário que defina esses seis valores de variáveis e anexe-o ao modelo de espelho em vez do modelo de produção.
Dicas gerais para desenvolver o formulário de entrada
A seguinte lista apresenta dicas detalhadas para ajudar você a desenvolver um formulário de entrada eficaz:
Se você receber uma mensagem genérica de «falha na instalação» ou «algo deu errado» ao instalar, configurar ou executar uma sala limpa na UI, talvez haja um erro no formulário da UI ou no modelo associado que não tenha sido capturado quando você adicionou o formulário ou o modelo.
Quando um campo depende de outro, por exemplo, um menu suspenso de coluna que se baseia no valor escolhido em um menu suspenso de tabela, coloque o campo pai primeiro, possivelmente logo acima do campo filho, para que os usuários preencham o campo pai antes de preencherem o campo filho. Com campos dependentes, o menu suspenso filho fica vazio até um valor ser escolhido no campo pai.
Se você não especificar um valor
order
ougroup
, os itens serão renderizados na ordem em que foram definidos.Inclua uma
infoMessage
informativa e um texto dedescription
, além de mostrar valores de exemplo que um usuário pode inserir.Escolha o tipo de elemento preciso para o tipo de dados da variável. Por exemplo, para um número inteiro, escolha
integer
em vez de uma caixa de texto de forma livre. O modelo pode converter valores usando filtros Jinja, por exemplo:SELECT {{ max_age | int }};
.Se você não definir um formulário de configuração mínima para um modelo personalizado, o modelo não poderá ser executado na UI de salas limpas.
Se você não definir um elemento de formulário para uma variável no modelo, uma caixa de texto simples será renderizada para essa variável no formulário de usuário. Isso provavelmente não é o que você quer, porque a caixa de texto é identificada com o nome da variável do modelo e não tem descrição nem sugestões.
Os elementos de formulário especificados em
add_ui_form_customizations
não serão renderizados, a menos que haja uma variável de modelo correspondente com o mesmo nome do elemento.As alterações do modelo feitas na API se propagam de forma rápida e confiável para a UI, portanto, você não precisa criar uma nova sala limpa para alterações do modelo. No entanto, você deve desenvolver e testar o modelo na API :emph:
antes
de chegar ao estágio da UI.Não é possível preencher automaticamente um menu suspenso com valores de coluna de uma determinada tabela. Você pode codificar os valores em um menu suspenso, mas não mostrar os valores de uma tabela em tempo de execução.
3. Conexão do formulário de entrada com o modelo de produção¶
Depois que o formulário estiver exatamente como você quer e tornar todas as variáveis de modelo acessíveis ao usuário, designe seu modelo de trabalho ao formulário de entrada na chamada para provider.add_ui_form_customizations
.