클린룸에서 사용자 지정 함수 업로드 및 실행

개요

사용자 지정 Python UDFs 및 UDTFs를 클린룸으로 업로드하고 템플릿에서 실행하여 복잡한 데이터 작업을 수행할 수 있습니다. 이러한 작업으로는 단일 단계 또는 다단계 흐름 중에 쿼리 내에서 머신 러닝 또는 사용자 지정 데이터 조작을 하는 것이 있습니다. Python은 사용자 지정 UDFs에 대해 지원되는 유일한 코딩 언어입니다.

업로드한 코드는 `승인된 Python 패키지 번들<https://repo.anaconda.com/pkgs/snowflake/>`_ 및 :ref:`Snowpark API<label-dcr_snowpark_udf>`에서 패키지를 가져오고 사용할 수 있습니다.

Templates in a clean room can call code uploaded by the account that added the template. Uploaded code can’t be viewed or downloaded. Snowflake scans uploaded code for security issues before installing the code.

There are different mechanisms for uploading code into a clean room, depending on your role:

Providers

  • Inline code upload: If you want to upload code using the default compute resources for a clean room, and need to use only the standard bundle of Python packages (including the Snowpark API), you should upload inline code.

  • Snowpark Container Services running within a clean room: If you need more control over the environment, such as specifying additional compute or custom libraries, you can run a container within a clean room.

Consumers

  • Inline upload with template: Consumers can upload and run a template bundled with code. The code is bound to the template, and must be approved by the clean room provider.

이 항목에서는 공급자 또는 컨슈머가 사용자 지정 Python UDFs 및 UDTFs를 업로드하고 실행하는 방법을 보여줍니다.

클린룸에서 Python UDFs를 직접 개발하는 방법에 대한 배경 정보는 다음 항목을 참조하세요.

  • UDFs가 Snowflake에서 작동하는 방식:Snowflake에서 Python 함수를 작성하는 방법에 대한 일반적인 배경 정보가 나와 있습니다.

  • Snowflake에서 UDTFs를 작성하는 방법: 함수에서 테이블을 반환하려는 경우에 참조합니다.

  • :doc:`사용자 지정 템플릿을 만들고 클린룸에 업로드하는 방법: </user-guide/cleanrooms/demo-flows/custom-templates>`UDFs/UDTFs는 사용자 지정 템플릿에서 호출됩니다.

  • :doc:`클린룸에서 Snowpark 사용 </user-guide/cleanrooms/demo-flows/snowpark>`(Snowpark에서 UDFs를 호출하려는 경우)

Entry points for uploaded code

업로드된 코드의 각 번들은 서로를 호출하는 여러 함수를 정의할 수 있지만, 번들은 하나의 처리기 함수만 노출합니다. 이 처리기 함수는 클린룸을 사용하는 모든 사용자가 만들거나 실행하는 템플릿으로 호출할 수 있습니다. 코드가 내부 테이블을 생성하는 경우 :doc:`/user-guide/cleanrooms/multistep-flows`에 설명된 대로 이러한 테이블에 액세스할 수 있습니다

예를 들어 두 개의 숫자 매개 변수를 사용하는 simple_add``인 함수를 업로드한 경우 여기에 표시된 대로 템플릿에서 호출할 있습니다. 함수는 항상 ``cleanroom 범위를 사용하여 참조됩니다. 예를 들어, 템플릿은 다음과 같이 ``simple_add``를 호출합니다.

SELECT cleanroom.simple_add({{ price | sqlsafe | int }}, {{ tax | sqlsafe | int }}) ...
Copy

공급자가 위의 코드를 실행하려면 결과 테이블이 백그라운드에서 생성되므로 집계 또는 사용자 지정 함수를 사용하는 모든 SELECT 열의 별칭을 지정해야 합니다.

SELECT
  cleanroom.simple_add(
    {{ price | sqlsafe | int }}, {{ tax | sqlsafe | int }}
    ) AS TOTAL_ITEM_COST
...
Copy

You can upload multiple functions in a single package, and functions within a single package can call each other, but functions can’t call functions within other packages. (They can call the handler functions, though.) For example, if you have a clean room where you upload two packages, each with a handler function and two helper functions:

업로드된 두 개의 Python 패키지가 있는 클린룸

패키지 1

패키지 2

  • 처리기 함수 A

  • 헬퍼 함수 A1

  • 헬퍼 함수 A2

  • 처리기 함수 B

  • 헬퍼 함수 B1

  • 헬퍼 함수 B2

  • Code uploaded by either party (provider or consumer) can be run templates submitted by either party.

  • A template can call function A or function B, but not A1, A2, B1, or B2.

  • 함수 A는 함수 B를 호출할 수 있으며, 그 반대의 경우도 마찬가지입니다.

  • 함수 A는 B1 또는 B2를 호출할 수 없고 함수 B는 A1 또는 A2를 호출할 수 없습니다.

  • A1은 A2를 호출할 수 있으며 그 반대의 경우도 마찬가지입니다. A1과 A2는 B를 호출할 수 있습니다. A1과 A2는 B1 또는 B2를 호출할 수 없습니다.

  • B1은 B2를 호출할 수 있고 그 반대의 경우도 마찬가지입니다. B1과 B2는 A를 호출할 수 있습니다. B1과 B2는 A1 또는 A2를 호출할 수 없습니다.

사용자 지정 함수 업데이트 또는 삭제하기

업로드한 기존 함수 또는 템플릿을 업로드하거나 덮어쓸 수 있지만, 기존 함수 또는 템플릿을 삭제할 수는 없습니다. 함수를 “제거”하는 유일한 방법은 항상 성공 값을 반환하는, 정확히 동일한 이름과 서명을 가진 더미 함수를 생성하는 것입니다.

Uploading a function with the same signature as one that you previously uploaded will overwrite the existing function, where a signature means the case-insensitive function name of an external handler, plus the data types of all its arguments, in the same order. Argument names are not part of the signature. You can’t overwrite a function uploaded by another account.

함수를 업데이트할 때 서명이 일치해야 하므로 기존 함수의 서명을 변경할 수 없습니다. 함수 ``foo(name VARIANT age INTEGER)``를 업로드한 다음, 함수 ``foo(name VARIANT age FLOAT)``를 업로드하면 인자 유형이 다르기 때문에 첫 번째 함수 외에 두 번째 함수가 클린룸에 추가됩니다.

공급자 제출 코드

공급자가 제출한 함수는 인라인 코드로 업로드하거나 Snowflake 스테이지에서 업로드할 수 있습니다. 두 기술 모두 여기에서 살펴봅니다.

업로드한 코드는 기본적으로 `승인된 Python 패키지 세트<https://repo.anaconda.com/pkgs/snowflake/>`_에서 패키지를 가져와 사용할 수 있습니다. 기본 패키지가 아닌 패키지가 필요한 경우 :ref:`클린룸의 Snowpark Container Services<label-dcr_snowpark_spcs>`를 사용하여 코드를 호스트해야 합니다.

업로드된 코드는 물론 자신의 코드도 볼 수 없으므로, 클린룸에 업로드한 코드의 복사본을 그대로 포함해야 합니다.

개요

다음에서는 공급자가 클린룸에 코드를 추가하는 방법을 개략적으로 살펴봅니다.

  1. 공급자는 일반적인 방식으로 클린룸을 만들고 구성합니다.

  2. The provider uploads a bundle by calling provider.load_python_into_cleanroom. You can either upload your code inline directly within that procedure, or upload a code file to a stage, then provide the stage location to that procedure.

    Although each bundle can include multiple functions, only one handler function is exposed for each upload. To expose multiple functions to templates, upload each handler separately or do a bulk upload (described below).

  3. If the clean room is exposed externally, security checks are run before the code is installed in the clean room, and you must call provider.view_cleanroom_scan_status to confirm that security checks have passed before incrementing the default version.

  4. After each successful upload, a new patch version of the clean room is generated. You must then increase the default version by calling provider.set_default_release_directive with the new patch number.

  5. Create and upload a custom template that calls handlers in your code. The template must call the handler function using the cleanroom scope, that is: cleanroom.my_function(...).

  6. 컨슈머는 다른 템플릿과 동일한 방식으로 템플릿을 실행합니다.

    컨슈머가 사용자 지정 코드로 클린룸을 설치할 때 마운트 오류가 발생하는 경우 코드에 구문 오류가 있다는 의미일 수 있습니다.

:ref:`공급자가 작성한 코드 예제 섹션<label-dcr_provider_written_code_examples>`에서 이 흐름을 보여주는 코드 예제를 찾을 수 있습니다.

버전 관리에 대한 중요 참고 사항

Every time the provider uploads a function, it increases the clean room patch number (and there is a limit of 99 patch numbers). Therefore, do your best to test and debug your code thoroughly before adding it to the clean room to reduce version updates during development.

You can upload multiple packages at once in a single bulk upload to reduce the number of patches generated. However, bulk uploads can make it more challenging to debug if the upload has a security scan issue, because the file that caused the problem isn’t reported in the error response.

패치 번호를 업데이트하면 클린룸 UI를 사용하는 고객이 변경 사항을 확인하기 위해 페이지를 새로 고쳐야 할 수도 있습니다. API를 사용하는 고객에게는 변경 사항이 즉시 표시되지만, 사용 가능한 리소스에 따라 지연이 발생할 수 있습니다. 클린룸 버전 관리에 대해 자세히 알아보세요.

공급자가 작성한 인라인 함수 업로드

provider.load_python_into_cleanroom``의 ``code 매개 변수에서 코드를 인라인으로 업로드할 수 있습니다. 다음은 간단한 함수를 인라인으로 업로드하는 예입니다.

CALL samooha_by_snowflake_local_db.provider.load_python_into_cleanroom(
$cleanroom_name,
'simple_add',                         -- Name used to call the UDF from a template.
['first INTEGER', 'second INTEGER'],  -- Arguments of the UDF, specified as '<variable_name> <SQL type>' pairs.
['numpy', 'pandas'],                  -- Packages imported by the UDF.
'INTEGER',                            -- SQL return type of UDF.
'add_two',                            -- Handler function in your code called when external name is called.
$$
import numpy as np   # Not used, but you can load supported packages.
import pandas as pd

def add_two(first, second):
    return first + second
$$
);
Copy

호출 템플릿은 ``cleanroom.simple_add``를 호출하여 이 함수를 호출합니다. :ref:`공급자 예제<label-dcr_provider_written_code_examples>`는 인라인 코드를 업로드하는 방법을 보여줍니다.

스테이지에서 공급자 작성 함수 업로드

You can upload Python files to a clean room stage and reference the stage when you call provider.load_python_into_cleanroom. Loading code from a stage allows you to develop the code in your local system in an editor, avoid copy/paste errors when loading it inline, and also have better versioning control of your source code. Note that you can upload multiple files in a single procedure call, but only one handler function is exposed for each upload.

``load_python_into_cleanroom``을 호출하면 코드가 스테이지에서 클린룸으로 로드됩니다. 나중에 스테이지의 코드 변경 사항이 클린룸으로 전파되지 않습니다.

스테이지로 UDF를 업로드하려면:

  1. .py 파일을 만들고 Snowsight 스테이지에 업로드할 수 있는 위치에 저장합니다.

  2. To get the name of the stage for your clean room, call provider.get_stage_for_python_files. You must use the specified stage; you cannot use an arbitrary stage that you create.

  3. .py 파일을 클린룸의 스테이지에 업로드합니다. CLI, Snowsight 또는 언어별 드라이버를 사용하는 것을 포함하여 :doc:`이 작업을 수행하는 여러 가지 방법</user-guide/data-load-local-file-system-stage>`이 있습니다.

  4. 스테이지 위치, 처리기, 외부 이름, 인자 및 반환 유형을 지정하여 ``provider.load_python_into_cleanroom``을 호출합니다. 이제 클린룸의 템플릿에서 이 함수를 호출할 수 있습니다.

다음 예제 코드는 스테이지에서 클린룸으로 코드를 로드하는 방법을 보여줍니다.

-- Save the following code as reverser.py:
--import numpy as np
--def main(some_string):
--  '''Return the reverse of a string plus a random number 1-10'''
--  return some_string[::-1] + str(np.random.randint(1,10))

-- Get the stage for your clean room.
CALL samooha_by_snowflake_local_db.provider.get_stage_for_python_files($cleanroom_name);

-- Save the file to the stage. Here is how to do it by using the Snowflake CLI
PUT file://~/reverser.py <STAGE_NAME> overwrite=True auto_compress=False;

-- Load the code from the stage into the clean room.
CALL samooha_by_snowflake_local_db.provider.load_python_into_cleanroom(
    $cleanroom_name,
    'reverse', -- Name used to call the function
    ['some_string  STRING'], -- Arguments and SQL types
    ['numpy'],               -- Any required packages
    ['/reverser.py'],        -- Relative path to file on stage
    'STRING',                -- Return type
    'reverser.main'          -- <FILE_NAME>.<FUNCTION_NAME>
);

-- Uploading code, even from a stage, increases the patch number.
CALL samooha_by_snowflake_local_db.provider.set_default_release_directive(
  $cleanroom_name, 'V1_0', <NEW_PATCH_NUMBER>);

-- Upload a template that calls the function.
CALL samooha_by_snowflake_local_db.provider.add_custom_sql_template(
    $cleanroom_name,
    $udf_template_name,
    $$
    SELECT
      p.status,
      cleanroom.reverse(p.status)
    FROM SAMOOHA_SAMPLE_DATABASE.DEMO.CUSTOMERS AS p
    LIMIT 100;
    $$
);

-- Switch to the consumer account and run the template to see the results.
Copy

:ref:`공급자 예제<label-dcr_provider_written_code_examples>`는 스테이지에서 코드를 업로드하는 방법을 보여줍니다.

업로드된 코드의 구문 오류 또는 검사 실패 문제 해결하기

구문 오류로 인해 실패하는 함수를 업로드하거나 보안 검사에 실패하면 게시할 수 없는 패치가 생성될 수 있습니다. 따라서 업로드하기 전에 코드를 철저히 테스트하여 구문 오류가 없는지 확인해야 합니다.

다음 SQL 명령을 실행하여 패키지 목록과 해당 검토 상태를 볼 수 있으며, 표시된 위치에 클린룸 ID가 제공됩니다.

SHOW VERSIONS IN APPLICATION PACKAGE samooha_cleanroom_cleanroom_id;

보안 검사

보안 검사는 공급자가 Python을 클린룸에 업로드하는 경우와 같이 외부 클린룸에서 새 패치 버전을 생성하는 모든 작업 후에 실행됩니다. (이 페이지에 설명된 컨슈머 제출 코드는 보안 검사를 트리거하지 않습니다.) 내부 클린룸은 보안 검사를 실행하지 않지만, 내부 클린룸을 외부 클린룸으로 변경하면 해당 패치에 대한 보안 검사가 트리거됩니다. 클린룸 패치는 패치를 검사할 때까지 외부에 게시할 수 없습니다.

Snowflake Clean Rooms는 :doc:`Snowflake Native App 보안 검사 프레임워크</developer-guide/native-apps/security-run-scan>`를 사용합니다. 보안 검사 오류를 방지하려면 :doc:`네이티브 앱 보안 모범 사례</developer-guide/native-apps/security-app-requirements>`를 따릅니다.

마지막 보안 검사가 완료되기 전에 추가 패치 생성 작업을 수행할 수 있습니다. 그러나 클린룸의 최신 버전을 제공하기 위해 기본 릴리스 지시문 업데이트하기 전에 ``provider.view_cleanroom_scan_status``가 성공으로 표시될 때까지 기다려야 합니다.

Uploading multiple Python functions in a single patch (bulk uploading)

If you want to upload multiple Python packages to your clean room, you can call prepare_python_for_cleanroom multiple times, then call load_prepared_python_into_cleanroom once to scan, upload, and generate a single patch for your clean room. The following example demonstrates uploading a UDF and a UDTF using bulk uploading:

---- Add custom inline UDF ----
CALL samooha_by_snowflake_local_db.provider.prepare_python_for_cleanroom(
    $cleanroom_name,
    'get_next_status',  -- Name of the UDF. Can be different from the handler.
    ['status VARCHAR'], -- Arguments of the UDF, specified as (variable name, SQL type).
    ['numpy'],          -- Packages needed by UDF.
    [],                 -- When providing the code inline, this is an empty array.
    'VARCHAR',          -- Return type of UDF.
    'get_next_status',  -- Handler.
    $$
import numpy as np
def get_next_status(status):
  """Return the next higher status, or a random status
  if no matching status found or at the top of the list."""

  statuses = ['MEMBER', 'SILVER', 'GOLD', 'PLATINUM', 'DIAMOND']
  try:
    return statuses[statuses.index(status.upper()) + 1]
  except:
    return 'NO MATCH'
    $$
);

---- Add custom inline UDTF. ----
CALL samooha_by_snowflake_local_db.provider.prepare_python_for_cleanroom(
    $cleanroom_name,
    'get_info',  -- Name of the UDTF. Can be different from the handler.
    ['hashed_email VARCHAR', 'days_active INT', 'status VARCHAR', 'income VARCHAR'],   -- Name/Type arguments of the UDTF.
    ['numpy'],         -- Packages used by UDTF.
    [],                -- When providing the code inline, this is an empty array.
    'TABLE(hashed_email VARCHAR, months_active INT, level VARCHAR)',  -- Return type of UDTF.
    'GetSomeVals',     -- Handler class name.
$$
class GetSomeVals:
  def __init__(self):
    self.month_days = 30

  def process(self, hashed_email, days_active, status, income):
    '''Change days into rough months, and also return whether we
    think the user's membership status is lower, higher, or equal to
    what is expected, based on their income.'''

    months_active = days_active // self.month_days
    brackets = ['0-50K', '50K-100K', '100K-250K', '250K+']
    statuses = ['MEMBER', 'SILVER', 'GOLD', 'PLATINUM']
    if(statuses.index(status) < brackets.index(income)):
      level = 'low'
    elif(statuses.index(status) > brackets.index(income)):
      level = 'high'
    else:
      level = 'equal'

    yield(hashed_email, months_active, level)
$$
);

-- Upload all stored procedures.
-- Note the new patch number returned by this procedure. Keep this number for later use.
CALL samooha_by_snowflake_local_db.provider.load_prepared_python_into_cleanroom($cleanroom_name);

-- Set the release directive specified by the last load_python_into_cleanroom call.
CALL samooha_by_snowflake_local_db.provider.set_default_release_directive($cleanroom_name, 'V1_0', <PATCH_NUMBER>);
Copy

공급자가 작성한 코드 예제

다음 예제는 공급자가 작성한 UDFs 및 UDTFs를 클린룸에 추가하는 방법을 보여줍니다.

Download the following examples and then upload them as worksheet files in your Snowflake account. You need separate accounts for the provider and consumer, each with the clean rooms API installed. Replace the information as noted in the sample files. See instructions to upload a SQL worksheet into your Snowflake account.

컨슈머가 제출한 코드

컨슈머 업로드 코드는 번들로 제공되며 :ref:`컨슈머 템플릿 업로드 흐름<label-dcr_consumer_written_templates>`을 사용하여 사용자 지정 템플릿과 함께 업로드됩니다. 업로드된 코드는 클린룸의 모든 템플릿에서 호출할 수 있습니다.

컨슈머로서 코드를 업로드하려면 :doc:`사용자 지정 템플릿 구문</user-guide/cleanrooms/demo-flows/custom-templates>`을 이해해야 합니다.

컨슈머가 업로드한 모든 코드는 공급자가 업로드 권한을 요청할 때 볼 수 있습니다. 공급자 또는 컨슈머가 템플릿을 검사할 때마다 컨슈머 코드도 표시됩니다.

다음은 사용자 지정 컨슈머 코드를 업로드하는 단계의 개요입니다.

  1. 공급자가 표준 방식으로 클린룸을 만든 다음, 컨슈머를 초대합니다.

  2. 컨슈머가 표준 방식으로 클린룸을 설치하고 구성합니다.

  3. 컨슈머는 cleanroom 네임스페이스 내에서 UDF 또는 UDTF를 호출하는 템플릿을 준비합니다. 예를 들어, 컨슈머 정의 calculate_tax 함수를 호출하려면 간단한 템플릿은 다음 코드 조각과 같을 수 있습니다.

    SELECT {{ cleanroom.calculate_tax(p.cost) }} AS Tax FROM my_db.my_sch.sales AS p;
    
    Copy
  4. 컨슈머는 Python 코드를 준비합니다. 나중에 추가 이스케이프 처리가 필요하지 않도록 코드에서 작은따옴표(' ') 대신 큰따옴표(" ")를 사용하는 것이 좋습니다. 코드에서 `지원되는 Python 라이브러리<https://repo.anaconda.com/pkgs/snowflake/>`_를 참조할 수 있습니다.

  5. 컨슈머는 Python 코드를 ``consumer.generate_python_request_template``에 전달합니다. 이 프로시저는 사용자 지정 JinjaSQL 템플릿에 대한 자리 표시자와 함께 Python 코드를 저장 프로시저로 반환합니다. 이 템플릿에는 ``$$``를 여러 줄 구분 기호로 사용하는 여러 줄 문자열이 있습니다.

  6. 컨슈머는 ``generate_python_request_template``의 출력에서 템플릿 자리 표시자를 해당 JinjaSQL 템플릿으로 바꿉니다.

  7. 결합된 템플릿에서 ``'``와 같이 작은따옴표를 이스케이프합니다. 이는 클린룸에 업로드할 때 전체 여러 줄 프로시저 문자열에 대한 가장 바깥쪽 구분 기호로 작은따옴표가 사용되기 때문입니다. 다음은 문자 이스케이프와 함께 컨슈머 Python 코드와 사용자 지정 템플릿을 포함하는 저장 프로시저의 예입니다.

      BEGIN
    
      CREATE OR REPLACE FUNCTION CLEANROOM.custom_compare(min_status STRING, max_status STRING, this_status STRING)
      RETURNS boolean
      LANGUAGE PYTHON
      RUNTIME_VERSION = 3.10
      PACKAGES = (\'numpy\')
    
      HANDLER = \'custom_compare\'
      AS $$
      import numpy as np
    
      def custom_compare(min_status:str, max_status:str, this_status:str):
        statuses = [\'MEMBER\', \'SILVER\', \'GOLD\', \'PLATINUM\']
        return ((statuses.index(this_status) >= statuses.index(min_status)) &
                (statuses.index(this_status) <= statuses.index(max_status)))
      $$;
    
      -- Custom template
      LET SQL_TEXT varchar := $$
      SELECT
        c.status,
        c.hashed_email
      FROM IDENTIFIER( {{ my_table[0] }} ) as c
      WHERE cleanroom.custom_compare({{ min_status }}, {{ max_status }}, c.status);
      $$;
    
      LET RES resultset := (EXECUTE IMMEDIATE :SQL_TEXT);
      RETURN TABLE(RES);
    
      END;
    
    Copy
  8. 컨슈머는 결합된 템플릿을 사용하여 consumer.create_template_request``를 호출합니다. ``template_definition 인자에서 저장 프로시저에 제공하는 코드에 이중 달러 기호 구분 기호($$...$$) 대신 작은따옴표(' ')를 사용합니다. 예:

    CALL samooha_by_snowflake_local_db.consumer.create_template_request(
      $cleanroom_name,
      $template_name,
      '
    BEGIN
    
    -- First, define the Python UDF.
    CREATE OR REPLACE FUNCTION CLEANROOM.custom_compare(min_status STRING, max_status STRING, this_status STRING)
    RETURNS boolean
    LANGUAGE PYTHON
    RUNTIME_VERSION = 3.10
    PACKAGES = (\'numpy\')
    
    HANDLER = \'custom_compare\'
    AS $$
    import numpy as np
    
    def custom_compare(min_status:str, max_status:str, this_status:str):
      statuses = [\'MEMBER\', \'SILVER\', \'GOLD\', \'PLATINUM\']
      return ((statuses.index(this_status) >= statuses.index(min_status)) &
              (statuses.index(this_status) <= statuses.index(max_status)))
        $$;
    
    -- Then define and execute the SQL query.
    LET SQL_TEXT varchar := $$
    SELECT
      c.status,
      c.hashed_email
    FROM IDENTIFIER( {{ my_table[0] }} ) as c
    WHERE cleanroom.custom_compare({{ min_status }}, {{ max_status }}, c.status);
    $$;
    
    -- Execute the query and then return the result.
    LET RES resultset := (EXECUTE IMMEDIATE :SQL_TEXT);
    RETURN TABLE(RES);
    
    END;
    ');
    
    Copy
  9. 컨슈머와 공급자가 표준 :ref:`컨슈머 정의 템플릿 흐름<label-dcr_consumer_written_templates>`을 계속 유지합니다.

    1. 공급자가 템플릿 요청을 확인한 다음(provider.list_pending_template_requests), ``approve_template_request``를 호출하여 승인합니다. 공급자는 요청에서 템플릿과 번들 코드를 볼 수 있습니다.

    2. 컨슈머가 요청 상태를 확인하고(consumer.list_template_requests) 상태가 APPROVED인 경우 템플릿을 실행합니다(consumer.run_analysis).

    Consumer code uploads don’t trigger a security scan or affect the clean room patch number.

컨슈머가 작성한 코드 예제

다음 예제에서는 공급자가 작성한 UDFs를 클린룸에 추가하는 방법을 보여줍니다.

Download the following examples and then upload them as worksheet files in your Snowflake account. You need separate accounts for the provider and consumer, each with the clean rooms API installed. Replace the information as noted in the sample files. See instructions to upload a SQL worksheet into your Snowflake account.