This document shows example Dataform core and JavaScript scripts that you can use to create a workflow in Dataform.
Creating tables
Creating a view with Dataform core
The following code sample shows definition of a view called new_view 
in the definitions/new_view.sqlx 
file:
 config { type: "view" }
SELECT * FROM source_data 
 
Creating a materialized view with Dataform core
The following code sample shows definition of a materialized view called new_materialized_view 
in the definitions/new_materialized_view.sqlx 
file:
 config {
  type: "view",
  materialized: true
}
SELECT * FROM source_data 
 
Creating a table with Dataform core
The following code sample shows definition of a table called new_table 
in the definitions/new_table.sqlx 
file:
 config { type: "table" }
SELECT * FROM source_data 
 
Creating an incremental table with Dataform core
The following code sample shows an incremental table that
incrementally processes rows of the productiondb.logs 
table:
 config { type: "incremental" }
SELECT timestamp, message FROM ${ref("productiondb", "logs")}
${when(incremental(), `WHERE timestamp > (SELECT MAX(timestamp) FROM ${self()})`) } 
 
Using the ref 
function to reference tables with Dataform core
 
 The following code sample shows the ref 
function used to reference the source_data 
table in the definitions/new_table_with_ref.sqlx 
table definition file:
 config { type: "table" }
SELECT * FROM ${ref("source_data")} 
 
Adding documentation to a table, view, or declaration with Dataform core
The following code sample shows table and columns descriptions
in the definitions/documented_table.sqlx 
table definition file:
 config { type: "table",
         description: "This table is an example",
         columns:{
             user_name: "Name of the user",
             user_id: "ID of the user"
      }
  }
SELECT user_name, user_id FROM ${ref("source_data")} 
 
Configuring incremental tables
Adding new table rows for new dates in source data with Dataform core
The following code sample shows a configuration of an incremental table
in the definitions/incremental_table.sqlx 
file. In this configuration,
Dataform appends a new row to the incremental_table 
for each new date:
 config { type: "incremental" }
SELECT date(timestamp) AS date, action
FROM weblogs.user_actions
${ when(incremental(), `WHERE timestamp > (select max(date) FROM ${self()})`) 
 
Taking a snapshot of a table periodically with Dataform core
The following code sample shows a configuration of an incremental table in the definitions/snapshots_table.sqlx 
file. In this configuration,
Dataform creates snapshots_table 
with a snapshot of productiondb.customers 
at the specified date:
 config { type: "incremental" }
SELECT current_date() AS snapshot_date, customer_id, name, account_settings FROM productiondb.customers
${ when(incremental(), `WHERE snapshot_date > (SELECT max(snapshot_date) FROM ${self()})`) } 
 
Building a rolling 30-days table that updates incrementally with Dataform core
The following code sample shows a configuration of an incremental table in the definitions/incremental_example.sqlx 
file. In this configuration,
Dataform creates a temporary incremental_example 
that updates
incrementally, and deletes the table after 30 days from its creation:
 config {type: "incremental"}
post_operations {
  delete FROM ${self()} WHERE date < (date_add(Day, -30, CURRENT_DATE))
}
SELECT
 date(timestamp) AS date,
 order_id,
FROM source_table
  ${ when(incremental(), `WHERE timestamp > (SELECT max(date) FROM ${self()})`) } 
 
Creating custom SQL operations
Running several SQL operations in a SQLX file with Dataform core
The following code sample shows ; 
used to separate multiple SQL operations
defined in definitions/operations.sqlx 
:
 config { type: "operations" }
DELETE FROM datatable where country = 'GB';
DELETE FROM datatable where country = 'FR'; 
 
Running custom SQL before creating a table with Dataform core
The following code sample shows a custom SQL operation defined in the pre_operations 
block of the definitions/table_with_preops.sqlx 
table definition file:
 config {type: "table"}
SELECT * FROM ...
pre_operations {
  INSERT INTO table ...
} 
 
Running custom SQL after creating a table with Dataform core
The following code sample shows a custom SQL operation defined in the post_operations 
block of the definitions/table_with_postops.sqlx 
table definition file:
 config {type: "table"}
SELECT * FROM ...
post_operations {
  GRANT `roles/bigquery.dataViewer`
  ON
  TABLE ${self()}
  TO "group:allusers@example.com", "user:otheruser@example.com"
} 
 
Validating tables
Adding assertions to a table, view, or declaration with Dataform core
The following code sample shows uniqueKey 
, nonNull 
,
and rowConditions 
assertions added to the definitions/tested_table.sqlx 
table definition file:
 config {
  type: "table",
  assertions: {
    uniqueKey: ["user_id"],
    nonNull: ["user_id", "customer_id"],
    rowConditions: [
      'signup_date is null or signup_date > "2022-01-01"',
      'email like "%@%.%"'
    ]
  }
}
SELECT ... 
 
Adding a custom assertion with Dataform core
The following code sample shows a custom assertion in a table definition file
that validates if columns a 
, or b 
, or c 
from source_data 
are null 
:
 config { type: "assertion" }
SELECT
  *
FROM
  ${ref("source_data")}
WHERE
  a is null
  or b is null
  or c is null 
 
Developing with JavaScript
Using inline variables and functions with JavaScript
The following code sample shows the foo 
variable defined in a js 
block
and then used inline in a SQLX file:
 js {
 const foo = 1;
 function bar(number){
     return number+1;
 }
}
SELECT
 ${foo} AS one,
 ${bar(foo)} AS two 
 
Generating one table per country with JavaScript
The following code sample shows the use of the forEach 
function to generate
one table per each country defined in countries 
in the definitions/one_table_per_country.js 
file:
  const 
  
 countries 
  
 = 
  
 [ 
 "GB" 
 , 
  
 "US" 
 , 
  
 "FR" 
 , 
  
 "TH" 
 , 
  
 "NG" 
 ]; 
 countries 
 . 
 forEach 
 ( 
 country 
  
 = 
>  
 { 
  
 publish 
 ( 
 "reporting_" 
  
 + 
  
 country 
 ) 
  
 . 
 dependencies 
 ([ 
 "source_table" 
 ]) 
  
 . 
 query 
 ( 
  
 ctx 
  
 = 
>  
 ` 
 SELECT ' 
 ${ 
 country 
 } 
 ' AS country 
 ` 
  
 ); 
 }); 
 
 
Declaring multiple sources within one file with JavaScript
The following code sample shows declaration of multiple data sources in the definitions/external_dependencies.js 
file:
  declare 
 ({ 
  
 schema 
 : 
  
 "stripe" 
 , 
  
 name 
 : 
  
 "charges" 
 }); 
 declare 
 ({ 
  
 schema 
 : 
  
 "shopify" 
 , 
  
 name 
 : 
  
 "orders" 
 }); 
 declare 
 ({ 
  
 schema 
 : 
  
 "salesforce" 
 , 
  
 name 
 : 
  
 "accounts" 
 }); 
 
 
Declaring multiple sources within one file using forEach 
 
 The following code sample shows declaration of multiple data sources with the forEach 
function in the definitions/external_dependencies.js 
file:
 ["charges", "subscriptions", "line_items", "invoices"]
  .forEach(source => declare({
      schema: "stripe",
      name: source
    })
  ); 
 
Deleting sensitive information in all tables containing PII with JavaScript
The following code sample shows a function in the definitions/delete_pii.js 
file that deletes selected information in all tables that contain
personal identifiable information (PII):
  const 
  
 pii_tables 
  
 = 
  
 [ 
 "users" 
 , 
  
 "customers" 
 , 
  
 "leads" 
 ]; 
 pii_tables 
 . 
 forEach 
 ( 
 table 
  
 = 
>  
 operate 
 ( 
 `gdpr_cleanup: 
 ${ 
 table 
 } 
 ` 
 , 
  
 ctx 
  
 = 
>  
 ` 
 DELETE FROM raw_data. 
 ${ 
 table 
 } 
 WHERE user_id in (SELECT * FROM users_who_requested_deletion)` 
 ) 
  
 . 
 tags 
 ([ 
 "gdpr_deletion" 
 ])) 
 ); 
 
 
Adding preOps 
and postOps 
with JavaScript
 
 The following code sample shows the publish 
function used to create a query
with preOps 
and postOps 
in the definitions/pre_and_post_ops_example.js 
table:
 publish("example")
  .preOps(ctx => `GRANT \`roles/bigquery.dataViewer\` ON TABLE ${ctx.ref("other_table")} TO "group:automation@example.com"`)
  .query(ctx => `SELECT * FROM ${ctx.ref("other_table")}`)
  .postOps(ctx => `REVOKE \`roles/bigquery.dataViewer\` ON TABLE ${ctx.ref("other_table")} TO "group:automation@example.com"`) 
 
Creating incremental tables with JavaScript
The following code sample shows the publish 
function used to create an
incremental table in the definitions/incremental_example.js 
file:
  publish 
 ( 
 "incremental_example" 
 , 
  
 { 
  
 type 
 : 
  
 "incremental" 
 }). 
 query 
 ( 
 ctx 
  
 = 
>  
 ` 
 SELECT * FROM 
 ${ 
 ctx 
 . 
 ref 
 ( 
 "other_table" 
 ) 
 } 
  
 ${ 
 ctx 
 . 
 when 
 ( 
 ctx 
 . 
 incremental 
 (), 
 `WHERE timestamp > (SELECT MAX(date) FROM 
 ${ 
 ctx 
 . 
 self 
 () 
 } 
 ` 
 ) 
 } 
 ` 
 ) 
 
 
Backfilling a daily table with JavaScript
The following code sample shows backfilling a table that updates daily in the definitions/backfill_daily_data.js 
file:
  var 
  
 getDateArray 
  
 = 
  
 function 
 ( 
 start 
 , 
  
 end 
 ) 
  
 { 
  
 var 
  
 startDate 
  
 = 
  
 new 
  
 Date 
 ( 
 start 
 ); 
  
 //YYYY-MM-DD 
  
 var 
  
 endDate 
  
 = 
  
 new 
  
 Date 
 ( 
 end 
 ); 
  
 //YYYY-MM-DD 
  
 var 
  
 arr 
  
 = 
  
 new 
  
 Array 
 (); 
  
 var 
  
 dt 
  
 = 
  
 new 
  
 Date 
 ( 
 startDate 
 ); 
  
 while 
  
 ( 
 dt 
  
< = 
  
 endDate 
 ) 
  
 { 
  
 arr 
 . 
 push 
 ( 
 new 
  
 Date 
 ( 
 dt 
 ). 
 toISOString 
 (). 
 split 
 ( 
 "T" 
 )[ 
 0 
 ]); 
  
 dt 
 . 
 setDate 
 ( 
 dt 
 . 
 getDate 
 () 
  
 + 
  
 1 
 ); 
  
 } 
  
 return 
  
 arr 
 ; 
 }; 
 var 
  
 dateArr 
  
 = 
  
 getDateArray 
 ( 
 "2020-03-01" 
 , 
  
 "2020-04-01" 
 ); 
 // step 1: create table 
 operate 
 ( 
 `create table` 
 , 
  
 'create table if not exists backfill_table (`fields`) `); 
 // step 2: insert into the table 
 dateArr.forEach((day, i) = 
> operate(`backfill ${day}` 
 `insert into backfill_table select fields where day = ' 
 $ 
 { 
 day 
 } 
 ' 
 `) 
 ); 
 
 
Reusing code with includes
Using global variables with JavaScript
The following code sample shows definition of project_id 
and first_date 
constants in the includes/constants.js 
:
  const 
  
 project_id 
  
 = 
  
 "project_id" 
 ; 
 const 
  
 first_date 
  
 = 
  
 "'1970-01-01'" 
 ; 
 module 
 . 
 exports 
  
 = 
  
 { 
  
 project_id 
 , 
  
 first_date 
 }; 
 
 
The following code sample shows the first_date 
constant referenced in the definitions/new_table.sqlx 
file:
 config {type: "table"}
SELECT * FROM source_table WHERE date > ${constants.first_date} 
 
Creating a country mapping with JavaScript
The following code sample shows the country_group 
custom function defined in
the includes/mapping.js 
file:
  function 
  
 country_group 
 ( 
 country 
 ){ 
  
 return 
  
 ` 
 case 
 when 
 ${ 
 country 
 } 
 in ('US', 'CA') then 'NA' 
 when 
 ${ 
 country 
 } 
 in ('GB', 'FR', 'DE', 'IT', 'PL', 'SE') then 'EU' 
 when 
 ${ 
 country 
 } 
 in ('AU') then 
 ${ 
 country 
 } 
 else 'Other' 
 end` 
 ; 
 } 
 module 
 . 
 exports 
  
 = 
  
 { 
  
 country_group 
 }; 
 
 
The following code sample shows a table definition that uses the country_group 
function in the definitions/new_table.sqlx 
table definition file:
 config { type: "table"}
SELECT
  country AS country,
  ${mapping.country_group("country")} AS country_group,
  device_type AS device_type,
  sum(revenue) AS revenue,
  sum(pageviews) AS pageviews,
  sum(sessions) AS sessions
FROM ${ref("source_table")}
GROUP BY 1, 2, 3 
 
The following code sample shows the query defined in definitions/new_table.sqlx 
compiled to SQL:
 SELECT
  country AS country,
  case
    when country in ('US', 'CA') then 'NA'
    when country in ('GB', 'FR', 'DE', 'IT', 'PL', 'SE') then 'EU'
    when country in ('AU') then country
    else 'Other'
  end AS country_group,
  device_type AS device_type,
  sum(revenue) AS revenue,
  sum(pageviews) AS pageviews,
  sum(sessions) AS sessions
FROM "dataform"."source_table"
GROUP BY 1, 2, 3 
 
Generating a SQL script with a custom JavaScript function
The following code sample shows the render_script 
custom function
defined in includes/script_builder.js 
:
  function 
  
 render_script 
 ( 
 table 
 , 
  
 dimensions 
 , 
  
 metrics 
 ) 
  
 { 
  
 return 
  
 ` 
 SELECT 
  
 ${ 
 dimensions 
 . 
 map 
 ( 
 field 
  
 = 
>  
 ` 
 ${ 
 field 
 } 
 AS 
 ${ 
 field 
 } 
 ` 
 ). 
 join 
 ( 
 "," 
 ) 
 } 
 , 
  
 ${ 
 metrics 
 . 
 map 
 ( 
 field 
  
 = 
>  
 `sum( 
 ${ 
 field 
 } 
 ) AS 
 ${ 
 field 
 } 
 ` 
 ). 
 join 
 ( 
 ",\n" 
 ) 
 } 
 FROM 
 ${ 
 table 
 } 
 GROUP BY 
 ${ 
 dimensions 
 . 
 map 
 (( 
 field 
 , 
  
 i 
 ) 
  
 = 
>  
 ` 
 ${ 
 i 
  
 + 
  
 1 
 } 
 ` 
 ). 
 join 
 ( 
 ", " 
 ) 
 } 
 ` 
 ; 
 } 
 module 
 . 
 exports 
  
 = 
  
 { 
  
 render_script 
  
 }; 
 
 
The following code sample shows a table definition that uses the render_script 
function in the definitions/new_table.sqlx 
table definition file:
 config {
    type: "table",
    tags: ["advanced", "hourly"],
    disabled: true
}
${script_builder.render_script(ref("source_table"),
                               ["country", "device_type"],
                               ["revenue", "pageviews", "sessions"]
                               )} 
 
The following code sample shows the query defined in definitions/new_table.sqlx 
compiled to SQL:
 SELECT
  country AS country,
  device_type AS device_type,
  sum(revenue) AS revenue,
  sum(pageviews) AS pageviews,
  sum(sessions) AS sessions
FROM "dataform"."source_table"
GROUP BY 1, 2 
 
Actions configs
Loading SQL files with action configs
Action configs facilitate loading pure SQL files. You can define action configs
in actions.yaml 
files in the definitions 
folder.
For more information about available action types and valid action configs options, see the Dataform Configs Reference .
The following code sample shows definition of a view called new_view 
in the definitions/actions.yaml 
file:
  actions 
 : 
  
 - 
  
 view 
 : 
  
 filename 
 : 
  
 new_view.sql 
 
 
The definitions/new_view.sql 
SQL file, referenced by the preceding code
sample, contains pure SQL:
  SELECT 
  
 * 
  
 FROM 
  
 source_data 
 
 

