# Core + Security Attributes - Initialization

### Create a new stage for datapancake files (or use an existing stage)

```sql
CREATE STAGE <DATABASE>.<SCHEMA>.DATAPANCAKE_FILES;
```

For more details on creating a stage, see <https://docs.snowflake.com/en/sql-reference/sql/create-stage>

![](https://colony-recorder.s3.amazonaws.com/files/2026-01-19/149fecfb-e559-4576-a13d-88e6b9d9798a/ascreenshot_e2dfe86c61b247be9cccc7da03b6f2a9_text_export.jpeg)

### Copy the Procedure DDL

```sql
CREATE OR REPLACE PROCEDURE <database_name>.<schema_name>.sp_update_datapancake_attribute_metadata_security(
    FILE_PATH string,
    ARCHIVE_PATH string, 
    USER_NAME string
)
RETURNS string
LANGUAGE PYTHON
RUNTIME_VERSION = '3.11'
PACKAGES = ('snowflake-snowpark-python','orjson')
HANDLER = 'update_datapancake_attribute_metadata'
EXECUTE AS CALLER

AS
$$
import snowflake.snowpark as snowpark
import datetime
import traceback
import orjson

def update_datapancake_attribute_metadata(session: snowpark.Session, FILE_PATH: str, ARCHIVE_PATH: str, USER_NAME: str):
    try:

        # Initialize the output variable
        
        attribute_data = ""

        # Step 1: Read the CSV file from the specified Snowflake stage
        # Set skip_header=0 so we can manually extract and process the first row as the header
        
        df = session.read.options({"field_delimiter": ",", "skip_header": 0}).csv(FILE_PATH)
        
        # Step 2: Collect all rows from the file
        
        rows = df.collect()
        if not rows:
            return "No rows found."

        # Step 3: Extract column names from the first row (header)
        # Convert column names to uppercase and strip whitespace
        
        header_row = rows[0]
        header_names = [str(getattr(header_row, f"c{i+1}")).strip().upper() for i in range(len(header_row))]

        # Step 4: Extract all remaining data rows
        
        data_rows = rows[1:]
        if not data_rows:
            return "Only header row found."

        # Step 5: Build a list of records (dicts) using the extracted headers
        
        records = []
        for row in data_rows:
            record = {}
            for i in range(len(header_names)):
                value = getattr(row, f"c{i+1}")
                record[header_names[i]] = str(value).strip() if value not in [None, ""] else None
            records.append(record) 
            
        # Step 6: Serialize the records list as JSON string using orjson
        # Default=str handles values like datetime or decimal types  
        
        attribute_data = orjson.dumps(records,default=str).decode("utf-8")

        # Step 7: Call the DataPancake procedure to update the attribute metadata
        result = session.call("DATAPANCAKE.CORE.UPDATE_ATTRIBUTE_METADATA_SECURITY",USER_NAME, attribute_data, FILE_PATH)
        if result == "Success":

            #Step 8: Optional: Archive the input file to a new location
            if ARCHIVE_PATH is not None and len(ARCHIVE_PATH) > 0 and ARCHIVE_PATH != FILE_PATH:
                session.sql(f"COPY FILES INTO '{ARCHIVE_PATH}' FROM '{FILE_PATH}'").collect()

            #Step 9: Optional - Remove the source file from the stage
            session.sql(f"REMOVE '{FILE_PATH}'").collect()

            #Step 10: Return message showing the successful result
            return f"The DataPancake attribute metadata has been successfully updated and the file has been archived. Processed {len(records)} rows with columns: {', '.join(header_names)}"
        else:
            #Step 10: Return the error message
            return f"Error: {result} and: {rows[1]}"
            
    except Exception as e:
        return f"Error: {str(e)} with a trace of: {traceback.format_exc()}"
$$;
```

### Paste the DDL and modify the database and schema name

{% hint style="info" %}
If you changed the name during install, modify DataPancake application database name.
{% endhint %}

![](https://colony-recorder.s3.amazonaws.com/files/2026-01-19/08a48753-77e8-42d4-8b26-bfd3975cf655/ascreenshot_af59fff4a3d74acbae85aa358dcf8b50_text_export.jpeg)

![](https://colony-recorder.s3.amazonaws.com/files/2026-01-19/0b3bb1f7-ddda-4a94-a866-ef18601b3873/ascreenshot_ef7432d644884206ae0391af2b65dfff_text_export.jpeg)

### Execute the create stored procedure statement

![](https://colony-recorder.s3.amazonaws.com/files/2026-01-19/e1381ebe-bafc-4c6a-8ca6-4807c00ff171/ascreenshot_dfc701671c0949b990f489f9aff23817_text_export.jpeg)

### Verify the stored procedure was created successfully

![](https://colony-recorder.s3.amazonaws.com/files/2026-01-19/479a2eb6-abce-4484-a932-e4159af96271/ascreenshot_b35428f606ee428991445782033c9daf_text_export.jpeg)

## Next Steps

[Attribute Metadata Bulk Updates (Security) - Execute](/guides/how-to-guides-bulk-upsert-via-csv/usage/core-+-security-attributes-bulk-update.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.datapancake.com/guides/how-to-guides-bulk-upsert-via-csv/database-object-initialization/core-+-security-attributes-initialization.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
