Conditionals#
edg supports two conditional constructs for branching logic: if/then/else for binary conditions and match/when/default for multi-way dispatch. Both work inside transactions and as standalone run items.
if/then/else#
Evaluates an expression and executes the then branch if true, the else branch if false. The else branch is optional.
Inside a transaction#
run:
- transaction: place_order
queries:
- name: read_buyer
type: query
args: [ref_rand('fetch_customers').id]
query: SELECT id, market FROM customer WHERE id = $1::UUID
- name: read_product
type: query
args: [ref_rand('fetch_products').id]
query: SELECT id, price FROM product WHERE id = $1::UUID
- if: "ref_same('read_buyer').market == 'uk'"
then:
- name: insert_uk_order
type: exec
args:
- ref_same('read_buyer').id
- ref_same('read_product').id
- ref_same('read_product').price
- ref_same('read_product').price * 0.20
- ref_same('read_buyer').market
query: |-
INSERT INTO order_log (customer_id, product_id, subtotal, tax, currency, market)
VALUES ($1::UUID, $2::UUID, $3::FLOAT, $4::FLOAT, 'GBP', $5::STRING)
else:
- name: insert_other_order
type: exec
args:
- ref_same('read_buyer').id
- ref_same('read_product').id
- ref_same('read_product').price
- ref_same('read_product').price * 0.10
- ref_same('read_buyer').market
query: |-
INSERT INTO order_log (customer_id, product_id, subtotal, tax, currency, market)
VALUES ($1::UUID, $2::UUID, $3::FLOAT, $4::FLOAT, 'USD', $5::STRING)UK customers get 20% VAT in GBP; all others get 10% tax in USD. The market is captured in the order for verification.
Standalone (outside a transaction)#
run:
- name: read_customer
type: query
args:
- ref_rand('fetch_customers').id
query: SELECT id, market FROM customer WHERE id = $1::UUID
- if: "ref_same('read_customer').market == 'uk'"
then:
- name: log_gdpr_check
type: exec
args:
- ref_same('read_customer').id
- ref_same('read_customer').market
query: |-
INSERT INTO compliance_log (customer_id, market, check_type)
VALUES ($1::UUID, $2::STRING, 'gdpr_data_access')
else:
- noopStandalone conditionals run outside any transaction context. Each branch query executes independently.
match/when/default#
Evaluates a match expression once, then compares the result to each eq value in order. The first matching when clause executes. If nothing matches, the default branch runs (if present).
Inside a transaction#
run:
- transaction: place_order
queries:
- name: read_buyer
type: query
args: [ref_rand('fetch_customers').id]
query: SELECT id, market FROM customer WHERE id = $1::UUID
- name: read_product
type: query
args: [ref_rand('fetch_products').id]
query: SELECT id, price FROM product WHERE id = $1::UUID
- match: "ref_same('read_buyer').market"
when:
- eq: "'uk'"
queries:
- name: insert_uk_order
type: exec
args:
- ref_same('read_buyer').id
- ref_same('read_product').id
- ref_same('read_product').price
- ref_same('read_product').price * 0.20
- ref_same('read_buyer').market
query: |-
INSERT INTO order_log (customer_id, product_id, subtotal, tax, currency, market)
VALUES ($1::UUID, $2::UUID, $3::FLOAT, $4::FLOAT, 'GBP', $5::STRING)
- eq: "'us'"
queries:
- name: insert_us_order
type: exec
args:
- ref_same('read_buyer').id
- ref_same('read_product').id
- ref_same('read_product').price
- ref_same('read_product').price * 0.10
- ref_same('read_buyer').market
query: |-
INSERT INTO order_log (customer_id, product_id, subtotal, tax, currency, market)
VALUES ($1::UUID, $2::UUID, $3::FLOAT, $4::FLOAT, 'USD', $5::STRING)
default:
- name: insert_eu_order
type: exec
args:
- ref_same('read_buyer').id
- ref_same('read_product').id
- ref_same('read_product').price
- ref_same('read_product').price * 0.23
- ref_same('read_buyer').market
query: |-
INSERT INTO order_log (customer_id, product_id, subtotal, tax, currency, market)
VALUES ($1::UUID, $2::UUID, $3::FLOAT, $4::FLOAT, 'EUR', $5::STRING)UK gets 20% VAT in GBP, US gets 10% sales tax in USD, everyone else (default) gets 23% VAT in EUR.
Standalone (outside a transaction)#
run:
- name: read_customer
type: query
args: [ref_rand('fetch_customers').id]
query: SELECT id, market FROM customer WHERE id = $1::UUID
- match: "ref_same('read_customer').market"
when:
- eq: "'uk'"
queries:
- name: log_gdpr
type: exec
args:
- ref_same('read_customer').id
- ref_same('read_customer').market
query: |-
INSERT INTO compliance_log (customer_id, market, check_type)
VALUES ($1::UUID, $2::STRING, 'gdpr')
- eq: "'us'"
queries:
- name: log_ccpa
type: exec
args:
- ref_same('read_customer').id
- ref_same('read_customer').market
query: |-
INSERT INTO compliance_log (customer_id, market, check_type)
VALUES ($1::UUID, $2::STRING, 'ccpa')
default:
- name: log_standard
type: exec
args:
- ref_same('read_customer').id
- ref_same('read_customer').market
query: |-
INSERT INTO compliance_log (customer_id, market, check_type)
VALUES ($1::UUID, $2::STRING, 'standard')Special entries#
Two naked scalar entries can be used as branch targets:
noop#
Does nothing. Use in branches where no action is needed.
else:
- noopWorks both inside and outside transactions.
rollback#
Immediately rolls back the current transaction. Only valid inside a transaction.
else:
- rollbackConditional rollbacks are not errors. The worker continues to the next iteration and the rollback is counted in transaction stats.
Nesting#
Conditionals can be nested. An if or match block can appear inside the then, else, when, or default branches of another conditional.
- if: "ref_same('read_buyer').market == 'uk'"
then:
- match: "ref_same('read_product').category"
when:
- eq: "'digital'"
queries:
- name: insert_digital_uk
type: exec
args: [ref_same('read_buyer').id, ref_same('read_product').price * 0.20]
query: |-
INSERT INTO order_log (customer_id, tax, currency)
VALUES ($1::UUID, $2::FLOAT, 'GBP')
- eq: "'food'"
queries:
- name: insert_food_uk
type: exec
args: [ref_same('read_buyer').id, ref_same('read_product').price * 0.0]
query: |-
INSERT INTO order_log (customer_id, tax, currency)
VALUES ($1::UUID, $2::FLOAT, 'GBP')
else:
- rollbackExpressions#
The if condition must evaluate to a boolean. The match expression and each eq value can be any type; types don’t need to match because both sides are stringified before comparison.
All conditional expressions have access to:
ref_same(),ref_rand(),ref_diff()and other reference functionslocal('name')for transaction-scoped variablesglobal('name')for global variables- Any other function available in the expression environment
Constraints#
ifentries must have athenbranchmatchentries must have at least onewhenclause- Each
whenclause must have botheqandqueries rollbackcan only appear inside a transactionrollback_ifcan only appear inside a transaction- An entry cannot combine multiple special fields (e.g.
if+rollback_if,if+match) - Conditional entries must not have
name,type,args, orqueryfields - Standalone conditionals (outside transactions) cannot be used with
run_weights