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_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_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
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_zip_arrays
Combine multiple arrays element-wise. Signature:String & Encoding Functions
string_to_array
Split string into array by delimiter. Signature: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)