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 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:
For curated EVM logs / raw_logs datasets, topics is a comma-separated string: topics LIKE '0xSIGNATURE%' matches the first topic, and SPLIT_INDEX(topics, ',', n) reads topic n (zero-based). For edge.evm.logs, topics is a list: use topics[1] for the event signature and topics[n] for other positions (one-based). Do not apply LIKE or SPLIT_INDEX directly to a list.
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.

evm_trace_decode

Decodes EVM trace (call) data using an ABI definition, the trace counterpart of evm_log_decode. Aliases: evm_decode_trace, _gs_trace_decode Signature:
Parameters: Returns: A struct with three fields:
  • function_signature (string): the matched function name
  • inputs (array of strings): decoded input values in positional order
  • outputs (array of strings): decoded output values in positional order
The function is matched by its selector; partial ABIs that contain only the target function also work. If no function matches, or the ABI or data cannot be decoded, the result is NULL. Example: Decode traces

_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_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, using eth_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:
Parameters: 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. Use CAST(balance AS TEXT) to render it and standard operators for 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.
block_number gives the balance at the end of that block. Pass block_number - 1 for the balance before the transfer, or NULL for the current balance at the chain head.
Every row that reaches this function costs one RPC request per distinct address in its list. Filter rows down to the addresses you care about before calling it, for example with dynamic_table_check.

_gs_keccak256

Compute Keccak256 hash (same as Solidity’s keccak256). Signature:
Parameters:
  • input - String to hash. A 0x-prefixed input is hex-decoded first and the resulting bytes are hashed; any other string is hashed as UTF-8 text.
Returns: Hex-encoded hash with “0x” prefix, or NULL if a 0x-prefixed input is not valid hex. 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; invalid or NULL input returns an empty byte array, not NULL. _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:
Returns: The decoded bytes. Invalid or NULL input returns an empty byte array, not NULL. Example:

_gs_solana_base58

Base58-encode raw Solana bytes. Strings that are already base58 are passed through unchanged, so the same expression works for raw and pinned schemas. Signature:
Accepts: VARCHAR or BINARY. Example:

_gs_solana_pin_token_balances

Normalize a preTokenBalances / postTokenBalances array from the raw block schema into the pinned schema, base58-encoding raw mint, owner and programId bytes. Already-pinned values pass through. Signature:
The input must be entirely the raw variant or entirely the pinned variant, not a mix of field types. Example:

_gs_flatten_balances

Flatten a pinned token-balance array by lifting uiTokenAmount.amount and uiTokenAmount.decimals onto each entry. Signature:
Returns: amount is a VARCHAR and decimals a UINT8. A NULL input list produces an empty list. Example:

_gs_decode_log_message

Decode Solana program log messages (e.g. Anchor events) using an IDL. Signature:
Parameters: Returns: Parallel lists of decoded event names, values (JSON text) and emitting program IDs. Example:

_gs_solana_get_leader_info

Extract the block leader from a block’s rewards: the pubkey and lamports of the first Fee reward. Signature:
Returns: Both fields are NULL when the block has no Fee reward. rewards must be an array column. Example:

Large Numbers (256-bit integers and wide decimals)

Smart contracts use 256-bit integers for token amounts and balances. Turbo stores these values, and any DECIMAL(p, s) with a precision above 76, as an arbitrary-precision decimal type, decimal_arb. Wide-integer dataset columns such as amount in erc20_transfers and native_transfers, and the balance returned by _gs_evm_get_balances, already have this type. You work with them using standard SQL operators and CAST; no conversion functions are needed.
The to_u256, to_i256, u256_*, i256_* and to_int64 functions have been removed, with no aliases. A transform that still calls one fails at planning with Invalid function. Rewrite it with the replacements below.

Working with 256-bit values

  • Convert in. CAST(x AS DECIMAL(78, 0)) turns a decimal string, an integer, or an existing 256-bit column into a 256-bit integer. Signed values are fine. A string that isn’t a number fails the query; TRY_CAST(x AS DECIMAL(78, 0)) returns NULL instead.
  • Calculate. +, -, *, /, %, unary -, comparisons, ABS, COALESCE and GREATEST/LEAST all work directly on 256-bit values. A numeric literal next to one is exact however many digits it has, so amount / 1000000000000000000 and amount > 1000000000000000000000000 need no quoting.
  • Convert out. CAST(x AS TEXT) renders the value as a decimal string. To get a native number, go through text, for example CAST(CAST(x AS TEXT) AS BIGINT), or use decimal_arb_to_decimal128 for a DECIMAL(38, s). A direct CAST(x AS BIGINT), CAST(x AS DOUBLE) or CAST(x AS DECIMAL(38, s)) fails with Unsupported CAST from LargeBinary.
  • NULLs. A NULL input or operand gives NULL. It does not raise an error.
Division does not truncate. a / b keeps 18 fractional digits (or more, if a already has more), rounded half-to-even, so CAST('1500000000000000000' AS DECIMAL(78, 0)) / 1000000000000000000 is 1.500000000000000000. Division and modulo by zero raise an error.Casting a result that has non-zero fractional digits back to DECIMAL(78, 0) raises an error rather than rounding. For an integer quotient, subtract the remainder first: CAST((a - a % b) / b AS DECIMAL(78, 0)).
Example: Convert token amounts
Example: Signed balance deltas
When a ClickHouse sink creates a table, it stores a 256-bit column as UInt256. Results derived from these columns, including a - b, keep that type, so a negative value fails the write. If a column can go negative, set it to Int256 in the sink’s schema_override.

decimal_arb functions

Operators and casts cover most needs. These functions handle explicit precision and scale, and conversions to and from other numeric types. Precision and scale arguments must be integer literals, with 1 <= precision <= 65535 and 0 <= scale <= precision. A NULL value gives NULL. The operators are rewritten to decimal_arb_add, decimal_arb_sub, decimal_arb_mul, decimal_arb_div, decimal_arb_mod, decimal_arb_neg, decimal_arb_abs, decimal_arb_eq, decimal_arb_neq, decimal_arb_lt, decimal_arb_lte, decimal_arb_gt and decimal_arb_gte. You can call these directly, but the operators are clearer. SUM, MIN, MAX and AVG also accept decimal_arb, but streaming SQL transforms don’t run aggregates. Use the PostgreSQL aggregation sink to sum values instead. Example:

coalesce_meta

Return the first non-null argument per row, like COALESCE, preserving the first argument’s field metadata. It only works on values in the old 256-bit format. For 256-bit columns, use COALESCE. Signature:
Although the planner accepts any argument types, every argument must be a FixedSizeBinary(32) value of the same type at runtime. A decimal_arb argument fails with coalesce_meta currently supports only FixedSizeBinary(32).

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:
All values must share a type. 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:
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:

array_struct_field

Project one string field out of every struct in an array, producing an array of strings with the same shape. NULL struct elements become NULL strings. Signature:
field_name must be a non-null string literal (not a column), and the named field must be a VARCHAR field.
Example:

_gs_map_to_array_struct

Convert a MAP<VARCHAR, VARCHAR> into an array of key/value structs, for example to unnest the params map returned by the Solana program decoders. Signature:
The map must have non-nullable VARCHAR keys and values. Example:

_gs_generate_series

Generate an array of integers from start to stop, inclusive of both endpoints. Combine with CROSS JOIN UNNEST for one-to-many row expansion, for example emitting one row per element of a decoded batch. Signature:
step is optional and defaults to 1. A negative step counts down (e.g. _gs_generate_series(5, 1, -2) returns [5, 3, 1]). A step of 0 raises an error, and a step pointing away from stop returns an empty array.
Pass start, stop and step either all as columns or all as literals. Mixing a literal with a column (for example a literal start of 1 with a column stop) fails on batches of more than one row. For a literal start, use DataFusion’s built-in generate_series(start, stop) instead.
Example: Expand one row per block in a range

_gs_zip_arrays

Combine multiple arrays element-wise. Signature:
Example:

String & Encoding Functions

string_to_array

Split string into array by delimiter. Signature:
Example:

_gs_split_string_to_array / _gs_split_string_by

Split a string into an array by a separator. _gs_split_string_by is an alias of _gs_split_string_to_array. Signatures:
The separator argument is optional and defaults to a single space.
A literal separator only works when string is also a literal: combined with a column, it fails on batches of more than one row. To split a column, omit the separator and replace the delimiter with a space first (as below), or use string_to_array.
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 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 every regex match
The replacement is literal: $1 / \1 group references are not expanded, and there is no flags argument. regexp_count - Count regex matches
regexp_extract_all - Extract a capture group (default 1) from every match
regexp_substr - Return the first whole match
regexp_instr - Position (1-based) of a match, 0 if none
An invalid pattern returns NULL from all of these functions. Example: Extract Address from Log Message

URL Functions

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

_gs_conv_base

Convert a number written as a string between bases 2–36. Signature:
Accepts: number as VARCHAR; from_base and to_base must both be INT32 columns or both be VARCHAR. Returns NULL for an invalid number or a base outside 2–36.
Pass literal bases as strings ('16', not 16). Pass all three arguments as literals or all three as columns: literal bases combined with a number column fail on batches of more than one row.
Example:

base32_to_hex

Decode an RFC 4648 base32 string (padding optional) into a lowercase 0x-prefixed hex string. Signature:
Returns: The hex string, or NULL for invalid or blank input. Example:

bytes_to_hex_string

Convert a list of bytes into a lowercase 0x-prefixed hex string. Signature:
Accepts: LIST<UINT8>, or LIST<VARCHAR> of decimal byte strings ('0'–'255'). Returns: The hex string, or NULL for a NULL or empty list, a NULL element, or an invalid decimal byte. Example:

gs_ss58_decode / gs_ss58_encode

Convert between Substrate/Polkadot SS58 addresses and 32-byte AccountId32 public keys. Signatures:
Parameters: Returns: gs_ss58_decode returns the 0x-prefixed 32-byte key; gs_ss58_encode returns the SS58 address. Both return NULL for invalid input. Example:

Arweave Tag Functions

Decode and index Arweave transaction tags. Signatures:
  • _gs_arweave_tags_decode takes a JSON array of base64url-encoded {"name", "value"} pairs and returns the decoded name/value structs.
  • _gs_arweave_string_array takes the decoded tag list and returns each tag as URL-escaped name#value text, which is convenient for searching.
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 (1-based)
  • locate(substring, string[, start]) - Find substring position (1-based; 0 if not found)
  • instr(string, substring[, start[, occurrence]]) - Find the position of the nth occurrence (1-based; a negative start searches from the end)
  • split(string, delimiter) - Split into an array, keeping empty tokens
  • 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

Return the JSON object or array at a path, as JSON text. Signature:
A scalar (string, number or boolean) at path returns NULL. Use json_value to extract scalars.
Paths support $, .key, [n] and ['key'] steps only; wildcards, recursive descent ($..) and filters are not supported. 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

Other JSON Functions

  • json_quote(string) - Quote and escape a string as a JSON string literal
  • json_unquote(string) - Unescape a double-quoted JSON string; other text is returned unchanged
  • json(string) - Validate JSON text and re-serialize it compactly (errors on invalid JSON)
  • json_arrayagg_null_on_null(value) / json_arrayagg_absent_on_null(value) - Aggregate a group’s values into a JSON array, keeping or omitting NULLs
  • json_objectagg_null_on_null(key, value) / json_objectagg_absent_on_null(key, value) - Aggregate a group’s key/value pairs into a JSON object; NULL or duplicate keys raise an error

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:

_gs_json_objects_to_clickhouse_tuples

Format selected keys from a JSON array of objects as ClickHouse tuple literals, for example to load nested rows into a ClickHouse Array(Tuple(...)) column. Signature:
Parameters: 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). An unknown name fails at execution.
  • value - Value to check for existence: a string, or an array of strings (LIST<VARCHAR>)
Returns: true if the value exists in the table, false otherwise, and NULL for a NULL value. For an array, true if any non-null element exists in the table; an empty array returns false. 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
256-bit arithmetic is more expensive than native integers:
  • Use DECIMAL(78, 0) only for values that need it, such as token amounts
  • Do as much filtering as possible before 256-bit operations
  • Convert to text once, at the end: CAST(a / b AS TEXT), not arithmetic on text values
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 256-bit integers (DECIMAL(78, 0)) 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