Overview
Turbo pipelines SQL transforms are powered by Apache DataFusion and include custom functions designed specifically for blockchain and Web3 data processing. These functions extend standard SQL with capabilities for:- Decoding EVM logs and Solana instructions
- Working with 256-bit integers (U256/I256) common in smart contracts
- Processing blockchain-specific data formats
- Advanced array and JSON manipulation
- Cryptographic operations
All standard DataFusion SQL functions are also available. This reference
focuses on Turbo-specific custom functions.
EVM & Ethereum Functions
evm_log_decode
Decodes an EVM event log using an ABI definition. Aliases:evm_decode_log, _gs_log_decode
Signature:
Returns: A struct with two fields:
event_signature(string): the event name (e.g."Transfer")event_params(array of strings): decoded parameter values in positional order
Parameters are returned by position, not by name. To access the third parameter, use
decoded.event_params[3], not decoded['paramName']._gs_fetch_abi for dynamic ABI lookup
Instead of hardcoding the ABI JSON, fetch it at runtime from Etherscan:
_gs_tx_decode
Decodes raw trace/transaction call data using an ABI definition, the trace counterpart ofevm_log_decode.
Signature:
Returns: A struct with three fields:
function(string): the matched function namedecoded_inputs(array of strings): decoded input values in positional orderdecoded_outputs(array of strings): decoded output values in positional order
_gs_fetch_abi
Fetches an ABI JSON from a URL. Results are cached for the lifetime of the pipeline. Signature:
Returns: ABI JSON string that can be passed to
evm_decode_log or _gs_decode_instruction_data
Example: Fetch ABI from Etherscan
_gs_eth_call
Performs aneth_call JSON-RPC request against an EVM node, ABI-encoding the inputs and ABI-decoding the outputs. Use this to enrich streaming rows with on-chain state at a specific block (token balances, totalSupply, oracle prices, contract metadata) without standing up a separate fetcher service.
Signature:
Returns: An
ARRAY<VARCHAR> of decoded output values, one element per declared output type. Index with [1] for the first return value. Returns NULL for any row whose call fails (bad signature, revert, RPC error, decode error); failures never tear down the batch.
Example: Enrich ERC-20 transfers with totalSupply at the transfer’s block
_gs_evm_get_balances
Reads native token balances (ETH on Ethereum, the native asset on any EVM chain) for a list of addresses at a given block, usingeth_getBalance against an RPC endpoint you provide. Use it to fetch exact balances for addresses that just moved value, instead of polling every address every block. See the native balances guide for a complete pipeline.
Signature:
Returns: One element per input address, in input order.
address is the address as you passed it; balance is the balance in wei as a 256-bit integer, the same type as the amount column of the native transfers dataset, so use u256_to_string to render it or the u256_* helpers to do arithmetic. A failed lookup (RPC error, timeout, malformed response) leaves that element’s balance as NULL and logs a warning; it never fails the row or the batch. An empty or NULL address list returns an empty list.
Example: balances of both parties after each transfer
Element access such as [1].balance is not supported on this list; use UNNEST in a subquery and read the struct fields from the outer query.
_gs_keccak256
Compute Keccak256 hash (same as Solidity’skeccak256).
Signature:
input- String to hash (can be regular string or hex with “0x” prefix)
_gs_hex_to_byte / _gs_byte_to_hex
Convert between hex strings and bytes. Signatures:_gs_hex_to_byte accepts input with or without a 0x prefix. _gs_byte_to_hex returns a bare hex string (no 0x prefix).to_checksum_address
Converts a hex address to its EIP-55 checksummed form (mixed-case encoding). Optionally accepts a chain ID for EIP-1191 chain-specific checksums. Signature:
Returns: A
0x-prefixed checksummed address, or NULL for invalid input.
Example:
reverse_bytes32
Reverses the byte order of a 32-byte value. Useful for endianness conversion of blockchain hashes and 256-bit integers. Signature:
Returns: The same 32 bytes in reversed order.
NULL is passed through.
Example:
Solana Functions
Turbo pipelines include specialized functions for decoding Solana program instructions and analyzing transaction data. Many of the below are already used in our defaultsolana.instructions dataset and other datasets.
_gs_decode_instruction_data (IDL Decode)
Decode Solana program instruction or event data using an IDL (Interface Definition Language) specification. This is the most flexible Solana decoding function - it works with any custom Solana program that has an IDL. Signature:idl_json- IDL specification as JSON string (can be fetched with_gs_fetch_abi())data- Base58-encoded instruction data
name- Instruction or event name (e.g., “initialize”, “swap”, “transfer”)value- JSON string with decoded parameter values
- Parses the IDL JSON specification
- Attempts to decode as an instruction first
- Falls back to event decoding if instruction decoding fails
- Returns both the name and decoded values
When to use:
- Custom Solana programs with available IDL specifications
- Decoding instructions from DEXes, DeFi protocols, NFT marketplaces
- Any program where you need flexible, schema-driven decoding
- Solana system programs (Token, System, Stake, Vote, etc.) - use
_gs_solana_decode_*functions below - Better performance for known programs with hardcoded decoders
_gs_solana_decode_token_program_instruction
Decode Solana Token Program (SPL Token) instructions. Signature:data: Base58-encoded instruction dataaccounts: List of account public keys for the instruction
_gs_solana_decode_system_program_instruction
Decode Solana System Program instructions (transfers, account creation, etc.). No IDL required. Signature:data: Base58-encoded instruction dataaccounts: List of account public keys for the instruction
_gs_solana_get_accounts
Build a unified list of accounts for a Solana transaction, annotated with source, writable, and signer flags. This is the same logic used to produce theaccounts column on solana.instructions.
Signature:
account_keys-LIST<VARCHAR>of account pubkeys from the message headerloaded_readonly-LIST<VARCHAR>of readonly pubkeys loaded via address lookup tablesloaded_writable-LIST<VARCHAR>of writable pubkeys loaded via address lookup tablesnum_required_signatures-UINT8header fieldnum_readonly_signed_accounts-UINT8header fieldnum_readonly_unsigned_accounts-UINT8header fieldsource-VARCHARtag stored on each resulting account record
_gs_solana_get_balance_changes
Pair a transaction’s unified account list with itspreBalances / postBalances arrays to produce per-account SOL balance changes.
Signature:
accounts-LIST<STRUCT<pubkey, source, writable, signer>>(typically the output of_gs_solana_get_accounts)pre_balances-LIST<UINT64>of lamport balances before the transactionpost_balances-LIST<UINT64>of lamport balances after the transaction
Other Solana Decoders
All program-specific decoders take(data, accounts) and follow the same pattern:
_gs_solana_decode_associated_token_program_instruction(data, accounts)- Decode ATA program_gs_solana_decode_stake_program_instruction(data, accounts)- Decode staking operations_gs_solana_decode_vote_program_instruction(data, accounts)- Decode vote program_gs_solana_decode_bpf_loader_instruction(data, accounts)- Decode BPF loader_gs_solana_decode_bpf_upgradeable_loader_instruction(data, accounts)- Decode upgradeable programs_gs_solana_decode_address_lookup_table_instruction(data, accounts)- Decode address lookup tables
_gs_from_base58
Decode Base58 strings (common in Solana for addresses and signatures). Signature:Large Numbers (U256 & I256)
Blockchain smart contracts frequently use 256-bit integers for token amounts, balances, and calculations. These functions provide precise arithmetic without JavaScript’s number precision limits.U256 Functions (Unsigned 256-bit)
to_u256
Convert various types to U256. Signature:u256_to_string
Convert U256 back to decimal string. Signature:u256_add / u256_sub / u256_mul / u256_div / u256_mod
U256 arithmetic operations. Signatures:I256 Functions (Signed 256-bit)
Similar to U256 but supports negative numbers. Available functions:to_i256(value)- Convert to I256i256_to_string(i256_value)- Convert to stringi256_add(a, b)/i256_sub(a, b)- Addition/subtractioni256_mul(a, b)/i256_div(a, b)/i256_mod(a, b)- Multiplication/division/moduloi256_neg(value)- Negate (multiply by -1)i256_abs(value)- Absolute value
I256 and U256 operators work the same way - standard operators (
+, -, *,
/, %) are automatically rewritten to their corresponding function calls by
the SQL preprocessor.Array Processing Functions
make_array
Build an array from individual values. Use it to pass several columns to a function that takes a list, such as_gs_evm_get_balances.
Signature:
ARRAY[value1, value2] is an equivalent literal form.
Example:
array_filter_in
Filter array elements where a struct field matches any value in a provided list. This is particularly useful for preventing overflow panics when processing large nested arrays by filtering before unnesting. Signature:array- Array of structs to filterfield_name- Name of the struct field to match against (Utf8 string)values_list- Array of values to match (supports Utf8 and Int64 types)
ListArray. When the total number of rows after unnesting exceeds ~2.1 billion, buffer offset calculations overflow.
By filtering arrays before unnesting, you reduce both memory usage and processing time while avoiding these overflow issues.
Example: Filter Stellar ledger entry changes
to_large_list
Convert a List array (i32 offsets) to a LargeList array (i64 offsets). This allows processing arrays that would otherwise overflow the i32 offset limit during operations like unnest. Signature:array- List, LargeList, or FixedSizeList array to convert
to_large_list when you need ALL elements from an array but the arrays might be extremely large. This changes the offset type from i32 (~2.1B max) to i64, preventing overflow in Arrow’s take function.
Example: Process large arrays safely
array_filter
Filter array elements based on field value. Signature:array- Array of structs to filterfield_name- Name of field to matchvalue- Value to match against
array_filter_first
Likearray_filter but returns only the first matching element.
Signature:
array_enumerate
Add index to each array element. Signature:_gs_generate_series
Generate an array of consecutive integers, inclusive of both endpoints. Combine withCROSS JOIN UNNEST for one-to-many row expansion, for example emitting one row per element of a decoded batch.
Signature:
_gs_zip_arrays
Combine multiple arrays element-wise. Signature:String & Encoding Functions
string_to_array
Split string into array by delimiter. Signature:_gs_split_string_by
Split a string into an array by the space character. Signature:REPLACE(col, ',', ' ')) or use string_to_array, which accepts an arbitrary delimiter.
Example: Split a decoded batch parameter
SPLIT_INDEX
Split a string by a delimiter and return the element at a given index. This is particularly useful for extracting individual topics from thetopics field in raw_logs datasets, which is a comma-separated string.
Signature:
string- The string to splitdelimiter- The delimiter to split onindex- 0-based index of the element to return
NULL if the index is out of bounds.
Example: Extract event signature from raw logs
Regular Expression Functions
Turbo pipelines include Flink-compatible regex functions: regexp_extract - Extract regex match groupsURL Functions
parse_url - Extract URL componentsOther String Functions
bin(number)- Convert to binary representationtranslate(string, from_chars, to_chars)- Character translationelt(index, string1, string2, ...)- Return element at indexlocate(substring, string)- Find substring positionunhex(hex_string)- Decode hex string
lower, upper, trim, substring, concat, replace, reverse, etc.
JSON Functions
Turbo pipelines have comprehensive JSON support compatible with Flink SQL.json_query
Query JSON documents using path expressions. Signature:json_value
Extract scalar value from JSON. Signature:parse_json / try_parse_json
Parse JSON string to validate or convert. Signatures:is_json
Check if string is valid JSON. Signature:json_object / json_array
Construct JSON objects and arrays. Signatures:json_object_absent_on_null- Omit null fieldsjson_array_absent_on_null- Omit null elements
json_exists
Check if JSON path exists. Signature:json_string
Converts any value to its JSON-encoded string representation. Primitives are quoted; structs and arrays are serialized to JSON objects/arrays. Signature:
Returns: A JSON string.
NULL input is passed through.
Example:
Time Functions
now / current_time / current_date
Get current timestamp, time, or date. Signatures:date_part
Extract part of a timestamp. Signature:to_timestamp / to_timestamp_micros
Convert Unix timestamp to TIMESTAMP. Signatures:Hash & ID Functions
_gs_xxhash
Fast non-cryptographic hash function (XXH3 128-bit). Returns a 32-character hex string. Signature:uuid7
Generates a UUIDv7, a time-ordered UUID that embeds the current timestamp. Useful as a primary key when you want inserts to be monotonically sorted by time. Signature:018f2a5c-1234-7abc-8def-0123456789ab). Called once per row, so every row gets a distinct value.
Example:
Dynamic Table Functions
dynamic_table_check
Check if a value exists in a dynamic table (async function). Signature:table_name- Reference name of the dynamic table (from your pipeline config)value- Value to check for existence
true if value exists in the table, false otherwise
See the Dynamic Tables documentation for complete details.
Example:
Function Composition
Functions can be composed to build complex transformations. Example: Decode Log and Convert ValuePerformance Considerations
Function Caching
Function Caching
Some functions use internal caching for performance:
evm_decode_logcaches ABI decoders (reuse the same ABI string)- Regex functions cache compiled patterns
- For best performance, use literal strings for patterns/ABIs when possible
Async Functions
Async Functions
dynamic_table_check is async and may perform I/O operations (database
lookups). Use it strategically: - Good: Filter with WHERE clause using dynamic
table - Avoid: Using in complex calculations or deeply nested expressionsU256/I256 Operations
U256/I256 Operations
Large number operations are more expensive than native integers: - Convert to
U256 only when needed for precision - Do as much filtering as possible before
U256 operations - Chain operations to minimize conversions:
u256_to_string(u256_div(...)) not u256_to_string(...) / u256_to_string(...)Array Operations
Array Operations
Array processing can be expensive on large arrays:
- Filter arrays early in the pipeline
- Use
array_filter_firstinstead ofarray_filterwhen you only need one element - Consider if SQL filtering can reduce array size before processing
Best Practices
1
Use type-specific functions
Use U256/I256 for token amounts, regular INT for counters and IDs
2
Validate data
Use
try_parse_json instead of parse_json when data quality is uncertain3
Minimize function calls
Store function results in CTEs when used multiple times:
sql WITH decoded AS ( SELECT id, evm_decode_log(abi, topics, data) as evt FROM logs ) SELECT evt.event_signature, evt.event_params[1], evt.event_params[2] FROM decoded 4
Handle NULLs
Many blockchain fields can be NULL - use COALESCE or NULL checks
5
Use appropriate hash functions
_gs_keccak256for EVM-compatible hashing (event signatures, etc.)_gs_xxhashfor fast non-cryptographic hashing (IDs, deduplication)