Skip to main content

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:
Parameters:
When filtering by event signature (the first topic), you can also use topics LIKE '0xSIGNATURE%' as an alternative to SPLIT_INDEX. This only works for matching the first topic — use SPLIT_INDEX when you need to access topics at other positions.
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'].
Example: Decode an ERC-20 Transfer event
Example: Using _gs_fetch_abi for dynamic ABI lookup Instead of hardcoding the ABI JSON, fetch it at runtime from Etherscan:
The decoder uses caching internally for performance. The same ABI can be reused across millions of records efficiently.

_gs_fetch_abi

Fetches an ABI JSON from a URL. Results are cached for the lifetime of the pipeline. Signature:
Parameters: Returns: ABI JSON string that can be passed to evm_decode_log or _gs_decode_instruction_data Example: Fetch ABI from Etherscan
Example: Fetch raw ABI from URL
The fetched ABI is cached internally for performance. The same URL will only be fetched once, even when processing millions of records.

_gs_eth_call

Performs an eth_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:
Parameters: 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.
The Multicall3 defaults (use_multicall = false, chunk size 50) are tuned for typical workloads. Only raise the chunk size if you’ve measured RPC throughput as your bottleneck — very large batches can hit per-request gas limits on the RPC node and start returning errors (which surface as NULL rows). When in doubt, leave the optional args off.
Example: Enrich ERC-20 transfers with totalSupply at the transfer’s block
Example: Look up an account balance with an argument
We recommend using a Goldsky Edge RPC endpoint as rpc_url for the best performance and reliability.
Output values are stringified element-by-element. Scalar return types (uint*, address, string, bytes, …) round-trip losslessly. For nested return types (string[], tuples), commas and brackets inside elements aren’t escaped — prefer one call per scalar field, or post-process the raw bytes, when you need strict re-parsing.

_gs_keccak256

Compute Keccak256 hash (same as Solidity’s keccak256). Signature:
Parameters:
  • input - String to hash (can be regular string or hex with “0x” prefix)
Returns: Hex-encoded hash with “0x” prefix Example: Compute Event Signatures
Example: Verify Topic Matches

_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).
Example:

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:
Parameters: 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:
Parameters: 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 default solana.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:
Parameters:
  • idl_json - IDL specification as JSON string (can be fetched with _gs_fetch_abi())
  • data - Base58-encoded instruction data
Returns: Struct containing:
  • name - Instruction or event name (e.g., “initialize”, “swap”, “transfer”)
  • value - JSON string with decoded parameter values
How it works:
  1. Parses the IDL JSON specification
  2. Attempts to decode as an instruction first
  3. Falls back to event decoding if instruction decoding fails
  4. Returns both the name and decoded values
Example: Access Decoded Fields after decoding
Example: Decode with Inline IDL For simpler programs, you can provide the IDL directly:
Performance: IDL decoders are cached internally. Reusing the same IDL JSON string (via _gs_fetch_abi()) across multiple rows is very efficient - the IDL is only parsed once.
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
Use program-specific decoders instead for:
  • 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 data
  • accounts — List of account public keys for the instruction
Example: Decode Token Instructions

_gs_solana_decode_system_program_instruction

Decode Solana System Program instructions (transfers, account creation, etc.). No IDL required. Signature:
  • data — Base58-encoded instruction data
  • accounts — List of account public keys for the instruction
Example: Decode System Program Instructions

_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 the accounts column on solana.instructions. Signature:
Parameters:
  • account_keys - LIST<VARCHAR> of account pubkeys from the message header
  • loaded_readonly - LIST<VARCHAR> of readonly pubkeys loaded via address lookup tables
  • loaded_writable - LIST<VARCHAR> of writable pubkeys loaded via address lookup tables
  • num_required_signatures - UINT8 header field
  • num_readonly_signed_accounts - UINT8 header field
  • num_readonly_unsigned_accounts - UINT8 header field
  • source - VARCHAR tag stored on each resulting account record

_gs_solana_get_balance_changes

Pair a transaction’s unified account list with its preBalances / postBalances arrays to produce per-account SOL balance changes. Signature:
Parameters:
  • accounts - LIST<STRUCT<pubkey, source, writable, signer>> (typically the output of _gs_solana_get_accounts)
  • pre_balances - LIST<UINT64> of lamport balances before the transaction
  • post_balances - LIST<UINT64> of lamport balances after the transaction
Example: Monitor Large Balance Changes

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:
Example:

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:
Accepts: VARCHAR, INT64, UINT64, INT32, UINT32, INT16, UINT16, INT8, UINT8 Example:

u256_to_string

Convert U256 back to decimal string. Signature:

u256_add / u256_sub / u256_mul / u256_div / u256_mod

U256 arithmetic operations. Signatures:
Automatic Operator Rewriting: Once values are cast to U256 or I256 types, you can use standard SQL operators (+, -, *, /, %) instead of explicit function calls. Turbo’s SQL preprocessor automatically rewrites these to the appropriate functions.
Example: Calculate Token Amounts in ETH
Example: Sum Multiple Token Amounts
U256 division truncates (no decimals). For percentage calculations or conversions to smaller units, multiply first, then divide.Good: (amount * to_u256('100')) / to_u256('1000000') (multiply by 100 first)Bad: (amount / to_u256('1000000')) * to_u256('100') (loses precision)

I256 Functions (Signed 256-bit)

Similar to U256 but supports negative numbers. Available functions:
  • to_i256(value) - Convert to I256
  • i256_to_string(i256_value) - Convert to string
  • i256_add(a, b) / i256_sub(a, b) - Addition/subtraction
  • i256_mul(a, b) / i256_div(a, b) / i256_mod(a, b) - Multiplication/division/modulo
  • i256_neg(value) - Negate (multiply by -1)
  • i256_abs(value) - Absolute value
Example: Track Profit/Loss
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:
Parameters:
  • array - Array of structs to filter
  • field_name - Name of the struct field to match against (Utf8 string)
  • values_list - Array of values to match (supports Utf8 and Int64 types)
Returns: Filtered array containing only elements where the specified field matches any value in the list Use case: Preventing overflow panics When processing data with multiple nested unnest operations (e.g., transactions → operations → ledger_entry_changes), the row count can explode exponentially. In extreme cases, this causes an overflow panic in Arrow’s take function because Arrow uses i32 offsets internally for 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
Example: Filter Stellar operations by type

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:
Parameters:
  • array - List, LargeList, or FixedSizeList array to convert
Returns: LargeList array with i64 offsets (virtually unlimited capacity vs ~2.1B for i32) Use case: Safety net for large arrays Use 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
Example: Stellar ledger entry changes
When to use each function:

array_filter

Filter array elements based on field value. Signature:
Parameters:
  • array - Array of structs to filter
  • field_name - Name of field to match
  • value - Value to match against
Example: Filter Logs by Event Name
Example: Filter Failed Instructions

array_filter_first

Like array_filter but returns only the first matching element. Signature:
Example:

array_enumerate

Add index to each array element. Signature:
Example:

_gs_zip_arrays

Combine multiple arrays element-wise. Signature:
Example:

String & Encoding Functions

string_to_array

Split string into array by delimiter. Signature:
Example:

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 the topics field in raw_logs datasets, which is a comma-separated string. Signature:
Parameters:
  • string - The string to split
  • delimiter - The delimiter to split on
  • index - 0-based index of the element to return
Returns: The element at the given index, or NULL if the index is out of bounds. Example: Extract event signature from raw logs
Example: Extract indexed parameters from topics
Example: Distinguish ERC-721 from ERC-20 transfers

Regular Expression Functions

Turbo pipelines include Flink-compatible regex functions: regexp_extract - Extract regex match groups
regexp_replace - Replace regex matches
regexp_count - Count regex matches
Example: Extract Address from Log Message

URL Functions

parse_url - Extract URL components
url_encode / url_decode - URL encoding/decoding
Example:

Other String Functions

  • bin(number) - Convert to binary representation
  • translate(string, from_chars, to_chars) - Character translation
  • elt(index, string1, string2, ...) - Return element at index
  • locate(substring, string) - Find substring position
  • unhex(hex_string) - Decode hex string
Plus all standard SQL string functions: 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:
Example: Extract NFT Metadata

json_value

Extract scalar value from JSON. Signature:
Example:

parse_json / try_parse_json

Parse JSON string to validate or convert. Signatures:
Example: Safe JSON Parsing

is_json

Check if string is valid JSON. Signature:

json_object / json_array

Construct JSON objects and arrays. Signatures:
Example: Build JSON Response
Null handling variants:
  • json_object_absent_on_null - Omit null fields
  • json_array_absent_on_null - Omit null elements

json_exists

Check if JSON path exists. Signature:
Example:

json_string

Converts any value to its JSON-encoded string representation. Primitives are quoted; structs and arrays are serialized to JSON objects/arrays. Signature:
Parameters: Returns: A JSON string. NULL input is passed through. Example:

Time Functions

now / current_time / current_date

Get current timestamp, time, or date. Signatures:
These functions are volatile - they return different values on each call. Use them for adding processing timestamps, not for filtering historical data.
Example: Add Processing Timestamp

date_part

Extract part of a timestamp. Signature:
Example: Analyze by Hour

to_timestamp / to_timestamp_micros

Convert Unix timestamp to TIMESTAMP. Signatures:
Example:

Hash & ID Functions

_gs_xxhash

Fast non-cryptographic hash function (XXH3 128-bit). Returns a 32-character hex string. Signature:
Example: Create Deterministic IDs

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:
Returns: A newly generated UUIDv7 string (e.g. 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:
Parameters:
  • table_name - Reference name of the dynamic table (from your pipeline config)
  • value - Value to check for existence
Returns: 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 Value
Example: Filter Array and Decode First Match

Performance Considerations

Some functions use internal caching for performance:
  • evm_decode_log caches ABI decoders (reuse the same ABI string)
  • Regex functions cache compiled patterns
  • For best performance, use literal strings for patterns/ABIs when possible
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 expressions
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 processing can be expensive on large arrays:
  • Filter arrays early in the pipeline
  • Use array_filter_first instead of array_filter when 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 uncertain
3

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_keccak256 for EVM-compatible hashing (event signatures, etc.)
  • _gs_xxhash for fast non-cryptographic hashing (IDs, deduplication)

Common Patterns

Pattern: Decode and Transform ERC-20 Transfers

Pattern: Filter Solana Token Transfers

Pattern: Process NFT Metadata with JSON