Skip to content

Functions

View Markdown

PizzaSQL ships a fixed set of built-in functions. There are no user-defined functions, no CREATE FUNCTION, and no extension mechanism.

A few functions are declared in the engine’s function catalog (so they parse without an “unknown function” error) but are not implemented in the executor — they return NULL. Those are listed separately so you don’t mistake their presence in autocomplete for real behaviour.

Used in SELECT with or without GROUP BY, and in HAVING.

Function Description
COUNT(*) number of rows
COUNT(expr) number of non-NULL values
COUNT(DISTINCT expr) number of distinct non-NULL values
SUM(expr) sum; integer result when all inputs are integers, otherwise real; NULL when no values
SUM(DISTINCT expr) distinct sum
AVG(expr) average (real); NULL when no values
MIN(expr) minimum, ignoring NULLs
MAX(expr) maximum, ignoring NULLs
  • Aggregates may be nested inside expressions: SELECT sum(x) / count(x) FROM t.
  • On an empty input set, COUNT returns 0; SUM, AVG, MIN, MAX return NULL.
  • MIN/MAX also work as scalar functions over multiple arguments: MIN(a, b, c).
  • TOTAL and GROUP_CONCAT are declared in the catalog but not implemented — do not rely on them.
Function Description
upper(s) uppercase
lower(s) lowercase
length(s) character length
substr(s, start[, len]) / substring(...) 1-indexed substring
trim(s) trims whitespace
replace(s, find, repl) replace all occurrences
instr(s, sub) 1-indexed position of sub, or 0
printf(format, ...) fmt.Sprintf-style formatting
concat(a, b, ...) concatenate all arguments as text
Function Description
abs(x) absolute value
round(x[, n]) round to n decimals (naive implementation; see caveats)
min(a, b, ...) scalar minimum
max(a, b, ...) scalar maximum
random() random 64-bit integer
percent_diff(a, b) percentage difference used by GoatCounter

PizzaSQL implements a JSON1-compatible function subset. JSON values are stored as text; there is no native JSON type or JSON operators.

Function Description
json(x) / jsonb(x) validate and normalize JSON text
json_valid(x) / jsonb_valid(x) 1 when the value is valid JSON, else 0
json_type(x[, path]) JSON type at the value or path
json_extract(x, path, ...) / jsonb_extract(...) extract one or more values by path
json_set(x, path, value, ...) / jsonb_set(...) set or create values at paths
json_insert(x, path, value, ...) / jsonb_insert(...) insert values only where paths do not exist
json_replace(x, path, value, ...) / jsonb_replace(...) replace values only where paths exist
json_remove(x, path, ...) / jsonb_remove(...) remove values at paths
json_array(...) / jsonb_array(...) construct a JSON array
json_object(key, value, ...) / jsonb_object(...) construct a JSON object from text keys and values
json_quote(x) / jsonb_quote(x) return a JSON string literal for the value
json_group_array(x) / jsonb_group_array(x) aggregate values into a JSON array
Function Description
coalesce(a, b, ...) first non-NULL argument
ifnull(a, b) b when a is NULL, else a
nullif(a, b) NULL when a equals b, else a
Function Description
typeof(x) "null", "integer", "real", "text", or "blob"
Function Description
hex(x) uppercase hex of the value’s bytes
unhex(x) decode hex to a string
zeroblob(n) a string of n NUL bytes (capped at 1 MiB)
Function Description
date(...) YYYY-MM-DD
time(...) HH:MM:SS
datetime(...) YYYY-MM-DD HH:MM:SS
julianday(...) Julian day number
unixepoch(...) Unix seconds (or fractional with subsec)
strftime(format, ...) formatted time
timediff(a, b) ±YYYY-MM-DD HH:MM:SS.SSS from b to a

Date/time functions accept SQLite-style time values and modifiers:

  • Time values: 'now', ISO-8601 text (e.g. '2026-01-02 03:04:05'), or a numeric Julian day (optionally followed by unixepoch, julianday, or auto).
  • Modifiers: NNN days|hours|minutes|seconds|months|years, start of day|month|year, weekday N, utc, localtime, subsec/subsecond, and ±YYYY-MM-DD HH:MM:SS.SSS.
  • Unknown modifiers are silently ignored rather than erroring.
Function Description
pizzasql_version() engine build version
sqlite_version() same value, for SQLite compatibility

These mirror SQLite’s connection-local counters and are tracked per connection:

Function Description
last_insert_rowid() rowid of the most recent successful INSERT on this connection; 0 before any insert
changes() number of rows changed by the most recent INSERT/UPDATE/DELETE
total_changes() total rows changed since this connection opened; monotonic, never decremented by ROLLBACK

Notes:

  • last_insert_rowid() reflects the actual generated rowid (not a naive counter or MAX), including for multi-row INSERT and INSERT ... SELECT, and holds across ROLLBACK.
  • total_changes() is incremented by every completed DML statement even when the change is later undone, matching SQLite.

These names are recognized by the parser/analyzer but return NULL when called. Treat them as unsupported:

  • ltrim, rtrim
  • ceil, floor
  • mod
  • iif
  • quote
  • total, group_concat
  • randomblob is implemented in the executor but not registered with the analyzer, so calls are currently rejected as an unknown function.
  • round uses int64(v*mult + 0.5) and only behaves correctly for non-negative decimal counts; treat it as approximate for edge cases.
  • random() is not cryptographically secure — do not use it for secrets.
  • zeroblob is capped at 1 MiB regardless of the requested size.
  • printf uses Go’s fmt.Sprintf, whose format verbs differ from SQLite’s printf in places.