COPY FROM to load data from external sources, such as from Amazon S3, into Firebolt tables. COPY FROM supports various data loading workflows, including schema discovery, metadata filtering, and parallel processing, offering flexibility for different use cases. This page provides an overview of the COPY FROM syntax, parameters, and best practices.
Syntax
AWS_ROLE_ARN, set the optional AWS_ROLE_EXTERNAL_ID to add a customer-controlled condition to your role’s trust policy.
For role-based AWS access you can additionally set an external ID. An external ID is a value you choose and control that AWS checks when Firebolt assumes your role, adding a second condition on top of your account’s unique IAM principal. Configuring one is a recommended best practice. See IAM roles.
Parameters
Parameters for CSV files
Parameters for Parquet files
Best practice
Firebolt recommends using aLOCATION object to specify credentials.
Location objects provide a secure, centralized way to manage Amazon S3 credentials and URLs. LOCATION objects let you specify credentials with the following:
- Centralized credential management.
- Reduced exposure of credentials in queries.
- Role-based access control.
- Simplified maintenance and updates.
Settings to control behavior
insert_shardingto enforce partition locality during ingestion into partitioned tables.tablet_min_size_bytesandtablet_max_size_bytesto control min/max tablet sizes during ingestion.cross_region_request_modeto access data in cross-region Amazon S3 buckets.
Examples
COPY FROM with LOCATION
The following code example copies data from files matching the *.parquet pattern in the specified my_location intomy_table:
Filter by metadata during loading
When loading data into tables, you can filter data using the following options:-
LIMIT: Restricts the number of rows loaded, which can be useful to preview or create sample datasets. -
OFFSET: Skips a specified number of rows in the final result set before ingestion. TheOFFSETclause inCOPY FROMbehaves the same way as theOFFSETclause inSELECTqueries behaves.-
COPY FROMcurrently does not support theORDER BYclause. Thus, usingOFFSETmay result in different outcomes every time you run the command. -
Both
LIMITandOFFSETapply to the entire result set, not to individual files.
-
-
WHERE: Filters data based on source file metadata, as follows:$source_file_name- The full path of the source file in an Amazon S3 bucket, without the name of the bucket. For example, if your bucket is:s3://my_bucket/xyz/year=2018/month=01/part-00001.parquet, then$source_file_nameisxyz/year=2018/month=01/part-00001.parquet.$source_file_timestamp- The timestamp in UTC, to the second when the source file was last modified in an Amazon S3 bucket.$source_file_size- The size in bytes of the source file.$source_file_etag- The ETag of the file, often used for version control.
COPY FROM first reads all the files in the specified directory that were modified in the last three years. Then, it applies the offset and limit clause. As long as all source files modified in the last three years have at least 100 rows combined, the result set will have exactly 50 rows. It returns a table containing 50 rows of data that was modified in the last three years.
LOCATION to store credentials to authenticate:
Use LOCATION to copy data
The following code example creates a table and uses aLOCATION object to copy Parquet files that match the specified pattern into it:
Load multiple directories with LOCATION
The following code example copies data from Parquet files matching a pattern inmy_tournaments_location to the tournament_results table:
Load multiple files and directories in parallel
You can useCOPY FROM to read multiple sources and from multiple directories into a single table, simultaneously. The following code example reads any file ending in .parquet from multiple directories into table_from_multiple_directories.
table_from_multiple_files:
firebolt_sample_dataset folder: levels.csv and tournaments.csv. These files have a different schema. COPY FROM reads these files into a single table, and infers the schema from the first file. Any column mismatches are filled with NULL values.
Automatic schema discovery
You can use the automatic schema discovery feature inCOPY FROM to handle even very large data sources instead of manually defining it. The following apply:
- Parquet files - Firebolt automatically reads metadata in Parquet files to create corresponding target tables.
- CSV files - Firebolt infers column types based on the data content itself, which can streamline the initial data loading process significantly. Use
WITH HEADER=TRUEif your CSV file contains column names in the first line.
When loading multiple files, Firebolt infers the schema from the most recently modified file. The remaining files must have compatible data types. If types vary between files (e.g., a column contains integers in one file but doubles in another, or is numeric in one file but text in another), the inferred schema may not match all files and thus cause data type errors or query failures. In such cases, we recommend defining an explicit schema using either external tables or
COPY FROM into existing tables.levels.csv, a sample dataset from the fictional “Ultra Fast Gaming Inc.” company. The example implicitly uses automatic schema creation with AUTO_CREATE=TRUE, which defaults to TRUE, and also triggers automatic table creation:
Use PATTERN to insert data into an existing table
You can use thePATTERN feature, which uses regular expressions, to select several files that match the specified pattern to populate a target table. The following example uses the *.csv pattern to read all files ending in .csv into the pattern_target table:
firebolt_sample_dataset folder: levels.csv and tournaments.csv. These files have a different schema. COPY FROM reads these files into a single table, and infers the schema from the first file. Any column mismatches are filled with NULL values.
Load metadata into a table
You can load metadata information about your source file into your table so that you can track the source name, timestamp, size, and etag information for each row. You can use the following metadata columns:$source_file_name- The full path of the source file in an Amazon S3 bucket, without the name of the bucket. For example, if your bucket is:s3://my_bucket/xyz/year=2018/month=01/part-00001.parquet, then$source_file_nameisxyz/year=2018/month=01/part-00001.parquet.$source_file_timestamp- The timestamp in UTC, to the second when the source file was last modified in an Amazon S3 bucket.$source_file_size- The size in bytes of the source file.$source_file_etag- The ETag of the file, often used for version control.
levels table, and populates it with information from the LevelID column and the timestamp from the source data:
levels:
Column mapping
When loading data into a target table, you can manually map source and target schemas by column name or index position. Column mapping ensures that data from the source file is correctly inserted into the appropriate columns in the target table.Handling case sensitivity
By default, column mapping in Firebolt is case-insensitive, meaning column names in theCOPY FROM statement are matched without quotes and are treated as lowercase. The CASE_SENSITIVE_COLUMN_MAPPING parameter is ignored, and data loads into the table regardless of case differences. If you need to enforce case-sensitive column mapping, set the CASE_SENSITIVE_COLUMN_MAPPING parameter to TRUE. When enabled, column names must match exactly, including case, and COPY FROM will either fail or populate columns with NULL values if there is a case mismatch. You can also use quoted identifiers to preserve case-sensitive behavior.
Mapping by column name
Before mapping schemas and ingesting data, you must first create a target table. You can explicitly map source columns to target table columns by matching column names.The following code example creates a table and maps columns by name:
COPY FROM statement match exactly with the source file.
Mapping by index position
Instead of mapping by column name, you can reference column positions in the source file using$cN notation, where N represents the column index starting from one.The following code example maps the first column in the source file to the
id column in the target table and the fourth column to name:
Mapping source columns and metadata
You can also map both source columns and metadata columns to store additional details about the ingested data. Metadata columns provide useful information such as file creation date, size, and last modified timestamp.The following code example maps source file columns by name and includes metadata:
- Standard columns such as
LevelID,NumberofLaps, andSceneDetailsare mapped by name. - Metadata columns such as
date_of_creation,file_name,file_last_modified, andfile_sizecapture file-level information from the source file. This approach is particularly useful for auditing, tracking data lineage, or managing incremental loads.
ALLOW_COLUMN_MISMATCH is enabled. For cases where column names may change or be missing in the source file, see the following section ALLOW_COLUMN_MISMATCH.
Allow column name mismatch
If you specify a column mapping during data loading,COPY FROM treats the columns listed in the <column_mapping> as required. If no column mapping is specified, the columns in the target table are considered required. To allow the data to continue loading when some required columns are missing from the source file, you can use ALLOW_COLUMN_MISMATCH, which is enabled by default.
For example, if you create a table with LevelID2 and Name columns and attempt to load data from the levels.csv dataset, which lacks a LevelID2 column, COPY FROM will populate the Name column as specified and fill the LevelID2 column with NULL values. This allows flexible handling of missing data without raising errors, as shown in the following code example:
Load Parquet structs
TheSUPPORT_STRUCTS parameter controls how structs in Parquet files are handled during schema inference.
- When
SUPPORT_STRUCTS=TRUE: Nested structures in the source data will be treated asSTRUCTdata types. - When
SUPPORT_STRUCTS=FALSE: Nested structures in the source data will be treated as individual shredded columns.
SUPPORT_STRUCTS applies only during schema discovery: It controls the type inference process for structs.
When working with predefined schemas: It has no effect, as the system maps incoming data to your defined schema.
Error handling
The following sections show you how to handle errors for both CSV and Parquet files.Row-based errors in CSV
COPY FROM generates a row-based error when there’s a mismatch between source and target table columns. In the following example, the col_mismatch_csv table includes a LevelID2 column defined as NOT NULL, that does not exist in the source levels.csv table. It uses MAX_ERRORS_PER_FILE='0%', which causes the loading job to fail if there is a single error.
COPY FROM does not see the same column name in the target table col_mismatch_csv, it tries to fill the column with NULL values. Because LevelID2 is defined with a constraint that it cannot have NULL values, the query generates the following error:
ERROR: The INSERT INTO statement failed because it tried to insert a NULL into the column LevelID2, which is NOT NULL. Please specify a value or redefine the column's logical constraints. and stops loading into the table.
Allow all row-based errors in CSV
You can change this behavior to allow errors. The following code example allows all errors, and the load job completes even if no data loads into the target table:Column data type mismatch in CSV
If you try to load data into a column in an existing table that has a different data type than the source data,COPY FROM will attempt to cast the data into the specified data type. If the cast fails, COPY FROM generates an error. To demonstrate this error, the following example intentionally creates a table that defines the LevelID column incorrectly as an integer, instead of as text, and then attempts to copy data into it. It generates the following error: Line 1, Column 8: Unable to cast text 'Thunderbolt Circuit' to integer.
MAX_ERRORS_PER_FILE is 0. You can set MAX_ERRORS_PER_FILE to 100% to allow all errors, as shown in the following section.
Allow all errors, and write them to file
You can also allow all errors, so that the loading job continues until it has attempted to load all rows in your dataset. Firebolt can write these errors to an Amazon S3 bucket as CSV files. If your specified S3 bucket requires access credentials, you must specify them so that Firebolt can write the files on your behalf. Data rows that load without error are ingested in row order. A loading job that specifies writing error files will write files with the following syntax to your Amazon S3 bucket:error_reasons.csv- An error file that contains all the reasons that a row generated an error, and also file-based errors.rejected_rows.csv- An error file that contains all the rejected rows in row order.
error_reasons.csv file is generated.
The previous files will have an order appended to the name such as error_reasons_1.csv.
The following code example allows all errors, provides credentials, and writes two error files to an Amazon S3 bucket:
- Replace the
<aws_access_key_id>with an AWS access key ID that is associated with an AWS user or AWS role. The AWS access key ID is a 20-character string such asAKIAIOSFODNN7EXAMPLE. - Replace the
<aws_secret_access_key>with an AWS secret access key associated with an AWS user or IAM role associated with the AWS access key ID. The AWS secret access key is a 40-character string such aswJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY.
Read errors from file
The previousCOPY FROM example shows how to create two error files, one that describes the error reasons and one that contains the rows that had errors. This example shows how to load and view the contents of these files.
The following code example reads all files that begin with error_reasons and end with .csv into an error_reasons table:
error_reasons table:
error_reasons table:
The following code reads all files that begin with
rejected_rows and ends with .csv into a rejected_rows table:
SELECT to view the contents of a file.
The following code returns the contents of the rejected_rows table:
rejected_rows table after running the previous SELECT statement:
Column mapping and default values
You can map a specific source column to a target column, and specify a default value to replace anyNULL values generated during mapping.
The following code example maps the LevelID column from the levels.csv sample dataset, into a column LevelID_team_A in a target_default_mapping table. It also maps a non-existent Country column in the levels.csv dataset, into LevelsID_team_B:
LevelsID_team_B will contain the value 50.
Type mismatch errors
If you read a column from a source file into a table with an incompatible data type, the mapping generates a casting error. A loading job that specifies writing error files will write files starting with the following prefixes to a specified Amazon S3 bucket:error_reasons- An error file that contains all the reasons that a row generated an error, and also file-based errors.rejected_rows- An error file that contains all the rejected rows in row order.
players dataset which has a column PlayerID with a data type of INTEGER, and attempts to read it into an existing column with a DATE data type:
error_reasons:
The type mismatch error in this example creates a file-based error, which is an error that affects the entire file during processing. This query only produces a file-based error and does not produce the
rejected_rows error file.