SnowConvert: BigQuery Functional Differences¶

Note

Conversion Scope

SnowConvert for Google BigQuery currently supports assessment and translation for TABLES and VIEWS. Although SnowConvert can recognize other types of statements, they are not fully supported.

SSC-FDM-BQ0001¶

Accessing arrays produces NULL instead of an error for positive out of bounds indexes in Snowflake.

Description¶

When accessing an ARRAY object by index in Snowflake, specifying an index greater than the size of the array will result in a NULL value, this differs with the behavior of BigQuery, where accessing an ARRAY with an index that is out of bounds will produce an error, unless the functions SAFE_OFFSET or SAFE_ORDINAL are used.

This warning will be added to any ARRAY access that is not safe.

Code Example¶

Input Code:¶
BigQuery¶
 SELECT ([40, 12, 30])[8];

SELECT ([40, 12, 30])[SAFE_OFFSET(8)];
Copy
Generated Code:¶
Snowflake¶
 SELECT
--** SSC-FDM-BQ0001 - ACCESSING ARRAYS PRODUCES NULL INSTEAD OF AN ERROR FOR POSITIVE OUT OF BOUNDS INDEXES IN SNOWFLAKE **
([40, 12, 30])[8];

SELECT
PUBLIC.SAFE_OFFSET_UDF( ([40, 12, 30]), 8);
Copy

Best Practices¶

  • Analyze the uses of array access in the code, if there was never the risk of getting an out of bounds error in the original code then no difference will be observed and this warning can be safely ignored.

  • If you need more support, you can email us at snowconvert-support@snowflake.com

SSC-FDM-BQ0002¶

Exception system variables are not supported in Snowflake.

Description¶

This FDM is added when a statement references exception variables in BigQuery because they are not supported in Snowflake, and the content of these variables is quite different from the exception variables allowed in Snowflake. For more information, please refer to Handling Exceptions in Snowflake.

Code Example¶

Input Code:¶
BigQuery¶
 CREATE OR REPLACE PROCEDURE test.proc1()
BEGIN
  SELECT 1/0;
EXCEPTION WHEN ERROR THEN
  SELECT
    @@error.message as message,
    @@error.stack_trace as stack_trace,
    @@error.statement_text as statement_text,
    @@error.formatted_stack_trace as formatted_stack_trace;
END;
Copy
Result¶
 [{
  "message": "Query error: division by zero: 1 / 0 at [snowflake-snowconvert-team.test.proc1:2:3]",
  "stack_trace": [{
    "line": "2",
    "column": "3",
    "filename": null,
    "location": "snowflake-snowconvert-team.test.proc1"
  }, {
    "line": "1",
    "column": "1",
    "filename": null,
    "location": null
  }],
  "statement_text": "SELECT 1/0",
  "formatted_stack_trace": "At snowflake-snowconvert-team.test.proc1[2:3]\nAt [1:1]\n"
}]
Copy
Generated Code:¶
Snowflake¶
 CREATE OR REPLACE PROCEDURE test.proc1 ()
RETURNS VARCHAR
LANGUAGE SQL
EXECUTE AS CALLER
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "bigquery",  "convertedOn": "04/09/2025",  "domain": "test" }}'
AS
$$
    BEGIN
    SELECT 1/0;
  EXCEPTION WHEN OTHER THEN
--      --** SSC-FDM-BQ0002 - EXCEPTION SYSTEM VARIABLES ARE NOT SUPPORTED IN SNOWFLAKE. **
--    SELECT
--      @@error.message as message,
--      @@error.stack_trace as stack_trace,
--      @@error.statement_text as statement_text,
--      @@error.formatted_stack_trace as formatted_stack_trace;
      RETURN OBJECT_CONSTRUCT('SQLERRM', SQLERRM, 'SQLCODE', SQLCODE, 'SQLSTATE', SQLSTATE);
    END;
$$;
Copy
Result¶
 {
  "SQLCODE": 100051,
  "SQLERRM": "Division by zero",
  "SQLSTATE": "22012"
}
Copy

Best Practices¶

  • Snowflake has three built-in variables that provide information about the exception:

    1. SQLSTATE: This is a 5-character code modeled on the ANSI SQL standard SQLSTATE .

    2. SQLERRM: This is an error message.

    3. SQLCODE: This is a 5-digit signed integer.

  • If you need more support, you can email us at snowconvert-support@snowflake.com

SSC-FDM-BQ0003¶

Unable to generate correct return table clause due to missing dependent object information.

Description¶

Snowflake requires a valid RETURNS TABLE clause for CREATE TABLE FUNCTION statements.

SnowConvert may encounter scenarios where the original BigQuery source code does not have a RETURNS TABLE clause, and has to build a new one from the ground up. To do this, an analysis is made to the CREATE TABLE FUNCTION query in order to properly infer the types of the columns of the resulting table. When SnowConvert cannot gather the required information, this EWI is added.

Code Example¶

Input Code:¶
BigQuery¶
 CREATE OR REPLACE TABLE FUNCTION function_name_noreturns_asterisk_join (parameter_name INTEGER)
AS
  SELECT * 
  FROM unknownTable1 t1 
  JOIN unknownTable2 t2 ON t1.col1 = t2.fk_col1;
Copy
Generated Code:¶
Snowflake¶
 --** SSC-FDM-0007 - MISSING DEPENDENT OBJECTS "unknownTable1", "unknownTable2" **

CREATE OR REPLACE FUNCTION function_name_noreturns_asterisk_join (parameter_name INTEGER)
----** SSC-FDM-BQ0003 - UNABLE TO GENERATE CORRECT RETURNS TABLE CLAUSE DUE TO MISSING DEPENDENT OBJECT INFORMATION. **
--RETURNS TABLE (
--)
AS
    $$
      SELECT *
      FROM
      unknownTable1 t1
      JOIN
          unknownTable2 t2 ON t1.col1 = t2.fk_col1
    $$;
Copy

Best Practices¶

  • Always try to include any dependent object definitions in the input code, so that SnowConvert has access to important information.

  • If you need more support, you can email us at snowconvert-support@snowflake.com

SSC-FDM-BQ0004¶

The INFER_SCHEMA function requires a file path without wildcards to generate the table template, replace the FILE_PATH placeholder with it

Warning

This FDM is deprecated; please refer to SSC-FDM-0035 for the latest version of this FDM.

Description¶

The INFER_SCHEMA function is used in Snowflake to generate the columns definition of a table based on the structure of a file, it requires a LOCATION parameter that specifies the path to a file or folder that will be used to construct the table columns, however, this path does not support regex, meaning that the wildcard * character is not supported.

When the table has no columns, SnowConvert will check all URIS in order to find one that does not use wildcards and use it in the INFER_SCHEMA function, when no URI meets such criteria this FDM and a FILE_PATH placeholder will be generated, the placeholder has to be replaced with the path of one of the files referenced by the external table in order to generate the table columns.

Code Example¶

Input Code:¶
BigQuery¶
 CREATE OR REPLACE EXTERNAL TABLE test.my_external_table_json2
OPTIONS(
  FORMAT='JSON',
  URIS=['gs://sc_external_table_bucket/folder_with_json/*']
);
Copy
Generated Code:¶
Snowflake¶
 CREATE OR REPLACE TEMPORARY FILE FORMAT SC_TEST_MY_EXTERNAL_TABLE_JSON2_FORMAT
TYPE = JSON;


CREATE OR REPLACE EXTERNAL TABLE test.my_external_table_json2 USING TEMPLATE (
SELECT
  ARRAY_AGG(OBJECT_CONSTRUCT('COLUMN_NAME', COLUMN_NAME, 'TYPE', TYPE, 'NULLABLE', NULLABLE, 'EXPRESSION', EXPRESSION))
FROM
  --** SSC-FDM-BQ0004 - THE INFER_SCHEMA FUNCTION REQUIRES A FILE PATH WITHOUT WILDCARDS TO GENERATE THE TABLE TEMPLATE, REPLACE THE FILE_PATH PLACEHOLDER WITH IT **
  TABLE(INFER_SCHEMA(LOCATION => '@EXTERNAL_STAGE/FILE_PATH', FILE_FORMAT => 'SC_TEST_MY_EXTERNAL_TABLE_JSON2_FORMAT'))
)
!!!RESOLVE EWI!!! /*** SSC-EWI-BQ0015 - EXTERNAL TABLE REQUIRES AN EXTERNAL STAGE TO ACCESS gs://sc_external_table_bucket, DEFINE AND REPLACE THE EXTERNAL_STAGE PLACEHOLDER ***/!!!
LOCATION = @EXTERNAL_STAGE
AUTO_REFRESH = false
PATTERN = 'folder_with_json/.*'
FILE_FORMAT = (TYPE = JSON);
Copy

Best Practices¶

SSC-FDM-BQ0005¶

Parsing the CSV header is not supported in external tables, columns must be renamed to match the original names

Description¶

Currently, Snowflake external tables do not support parsing the header of CSV files. When a external table with no explicit column list and CSV file format is found, SnowConvert will produce the SKIP_HEADER file format option to avoid runtime errors, however, this will cause the table column names to have the autogenerated names c1, c2, …, cN.

This FDM is generated to notify that the header can not be parsed and that manually renaming the columns is necessary to preserve the original column names.

Code Example¶

Input Code:¶
BigQuery¶
 CREATE OR REPLACE EXTERNAL TABLE test.my_external_table_csv
OPTIONS(
  FORMAT='CSV',
  URIS=['gs://sc_external_table_bucket/folder_with_csv/Employees.csv']
);
Copy
Generated Code:¶
Snowflake¶
 CREATE OR REPLACE TEMPORARY FILE FORMAT SC_TEST_MY_EXTERNAL_TABLE_CSV_FORMAT
TYPE = CSV
SKIP_HEADER = 1;

CREATE OR REPLACE EXTERNAL TABLE test.my_external_table_csv
--** SSC-FDM-BQ0005 - PARSING THE CSV HEADER IS NOT SUPPORTED IN EXTERNAL TABLES, COLUMNS MUST BE RENAMED TO MATCH THE ORIGINAL NAMES **
USING TEMPLATE (
SELECT
  ARRAY_AGG(OBJECT_CONSTRUCT('COLUMN_NAME', COLUMN_NAME, 'TYPE', TYPE, 'NULLABLE', NULLABLE, 'EXPRESSION', EXPRESSION))
FROM
  TABLE(INFER_SCHEMA(LOCATION => '@EXTERNAL_STAGE/folder_with_csv/Employees.csv', FILE_FORMAT => 'SC_TEST_MY_EXTERNAL_TABLE_CSV_FORMAT'))
)
!!!RESOLVE EWI!!! /*** SSC-EWI-0032 - EXTERNAL TABLE REQUIRES AN EXTERNAL STAGE TO ACCESS gs://sc_external_table_bucket, DEFINE AND REPLACE THE EXTERNAL_STAGE PLACEHOLDER ***/!!!
LOCATION = @EXTERNAL_STAGE
AUTO_REFRESH = false
PATTERN = 'folder_with_csv/Employees.csv'
FILE_FORMAT = (TYPE = CSV SKIP_HEADER = 1);
Copy

Best Practices¶

  • Please rename the table columns to their original names from the file to complete the transformation

  • If you need more support, you can email us at snowconvert-support@snowflake.com

SSC-FDM-BQ0006¶

Reading from Google Drive is not supported in Snowflake, upload the files to the external location and replace the FILE_PATH placeholders

Description¶

Snowflake does not support reading data from files hosted in Google Drive, this FDM is generated to notify it, please upload the Google Drive files to the external location so they can be accessed through the external stage.

The PATTERN clause will hold autogenerated placeholders FILE_PATH0, FILE_PATH1, …, FILE_PATHN that should be replaced with the file/folder path after the files were moved to the external location.

Code Example¶

Input Code:¶
BigQuery¶
 CREATE OR REPLACE EXTERNAL TABLE test.my_external_table_drive_test
OPTIONS(
  FORMAT='JSON',
  URIS=['https://drive.google.com/open?id=someFileId']
);
Copy
Generated Code:¶
Snowflake¶
 CREATE OR REPLACE TEMPORARY FILE FORMAT SC_TEST_MY_EXTERNAL_TABLE_DRIVE_TEST_FORMAT
TYPE = JSON;

CREATE OR REPLACE EXTERNAL TABLE test.my_external_table_drive_test USING TEMPLATE (
SELECT
  ARRAY_AGG(OBJECT_CONSTRUCT('COLUMN_NAME', COLUMN_NAME, 'TYPE', TYPE, 'NULLABLE', NULLABLE, 'EXPRESSION', EXPRESSION))
FROM
  --** SSC-FDM-0035 - THE INFER_SCHEMA FUNCTION REQUIRES A FILE PATH WITHOUT WILDCARDS TO GENERATE THE TABLE TEMPLATE, REPLACE THE FILE_PATH PLACEHOLDER WITH IT **
  TABLE(INFER_SCHEMA(LOCATION => '@EXTERNAL_STAGE/FILE_PATH', FILE_FORMAT => 'SC_TEST_MY_EXTERNAL_TABLE_DRIVE_TEST_FORMAT'))
)
!!!RESOLVE EWI!!! /*** SSC-EWI-0032 - EXTERNAL TABLE REQUIRES AN EXTERNAL STAGE TO ACCESS AN EXTERNAL LOCATION, DEFINE AND REPLACE THE EXTERNAL_STAGE PLACEHOLDER ***/!!!
LOCATION = @EXTERNAL_STAGE
AUTO_REFRESH = false
--** SSC-FDM-BQ0006 - READING FROM GOOGLE DRIVE IS NOT SUPPORTED IN SNOWFLAKE, UPLOAD THE FILES TO THE EXTERNAL LOCATION AND REPLACE THE FILE_PATH PLACEHOLDERS **
PATTERN = 'FILE_PATH0'
FILE_FORMAT = (TYPE = JSON);
Copy

Best Practices¶

  • Complete the transformation by uploading the files hosted in Google Drive to the external location referenced by the external stage and replace the FILE_PATH placeholders

  • If you need more support, you can email us at snowconvert-support@snowflake.com

SSC-FDM-BQ0007¶

Reading from spreadsheets is not supported in snowflake, use the CSV file type instead

Description¶

Snowflake does not support Google Sheets as a file format, however, its structure is similar to CSV files, which are supported by Snowflake.

When SnowConvert detects a external table using the GOOGLE_SHEETS format, it will produce a external table with the CSV file format instead.

This FDM is generated to notify the user that the transformation now expects a CSV file instead of Google Sheets.

Code Example¶

Input Code:¶
BigQuery¶
 CREATE OR REPLACE EXTERNAL TABLE test.spreadsheetTable
(
  Name STRING,
  Code INTEGER,
  Price INTEGER,
  Expiration_date DATE
)
OPTIONS(
  format="GOOGLE_SHEETS",
  skip_leading_rows = 1,
  uris=['https://docs.google.com/spreadsheets/d/someFileId/edit?usp=sharing']
);
Copy
Generated Code:¶
Snowflake¶
 --** SSC-FDM-BQ0007 - READING FROM SPREADSHEETS IS NOT SUPPORTED IN SNOWFLAKE, USE THE CSV FILE TYPE INSTEAD **
CREATE OR REPLACE EXTERNAL TABLE test.spreadsheetTable
(
  Name STRING AS CAST(GET_IGNORE_CASE($1, 'c1') AS STRING),
  Code INTEGER AS CAST(GET_IGNORE_CASE($1, 'c2') AS INTEGER),
  Price INTEGER AS CAST(GET_IGNORE_CASE($1, 'c3') AS INTEGER),
  Expiration_date DATE AS CAST(GET_IGNORE_CASE($1, 'c4') AS DATE)
)
!!!RESOLVE EWI!!! /*** SSC-EWI-BQ0015 - EXTERNAL TABLE REQUIRES AN EXTERNAL STAGE TO ACCESS A EXTERNAL LOCATION, DEFINE AND REPLACE THE EXTERNAL_STAGE PLACEHOLDER ***/!!!
LOCATION = @EXTERNAL_STAGE
AUTO_REFRESH = false
--** SSC-FDM-BQ0006 - READING FROM GOOGLE DRIVE IS NOT SUPPORTED IN SNOWFLAKE, UPLOAD THE FILES TO THE EXTERNAL LOCATION AND REPLACE THE FILE_PATH PLACEHOLDERS **
PATTERN = 'FILE_PATH0'
FILE_FORMAT = (TYPE = CSV SKIP_HEADER = 1);
Copy

Best Practices¶

SSC-FDM-BQ0008¶

Where clause references a column of STRUCT type.

Description¶

If an Snowflake Object has a key value format, when a comparison is made with another Object, Snowflake compares both key and value. On the other hand, when BigQuery compares between Structs, it compares only values, regardless if the Struct has keys or not.

This difference between comparisons may cause that the results are not the same in SnowConvert and BigQuery for the same comparison. This FDM is added when a comparison is made on a Snowflake Object created from a BigQuery Struct.

Code Example¶

Input:¶
BigQuery¶
 CREATE OR REPLACE TABLE test.compExprTable
(
  COL1 STRUCT<sc1 INT64>,
  COL2 STRUCT<sc2 INT64>  
);

SELECT * FROM test.compExprTable WHERE COL1 <> (COL2);
Copy
Output:¶
Snowflake¶
 CREATE OR REPLACE TABLE test.compExprTable
(
  COL1 VARIANT /*** SSC-FDM-0034 - STRUCT<INT64> CONVERTED TO VARIANT. SOME OF ITS USAGES MIGHT HAVE FUNCTIONAL DIFFERENCES. ***/,
  COL2 VARIANT /*** SSC-FDM-0034 - STRUCT<INT64> CONVERTED TO VARIANT. SOME OF ITS USAGES MIGHT HAVE FUNCTIONAL DIFFERENCES. ***/
)
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": {  "major": 0,  "minor": 0,  "patch": "0" }, "attributes": {  "component": "bigquery",  "convertedOn": "07/02/2025",  "domain": "no-domain-provided" }}';

SELECT * FROM
  test.compExprTable
--** SSC-FDM-BQ0008 - WHERE CLAUSE REFERENCES A COLUMN OF STRUCT TYPE. COMPARISON OPERATIONS MAY PRODUCE DIFFERENT RESULTS IN SNOWFLAKE. **
WHERE COL1 <> (COL2);
Copy

Best Practices¶