Skip to content

SQL Reference

ParticleDB speaks PostgreSQL-compatible SQL with extensions for vector search, time-series, and hybrid transactional/analytical workloads. Connect with any PostgreSQL client (psql, JDBC, node-postgres, etc.) and use the SQL you already know.

StatementDescriptionExample
CREATE TABLECreate a new tableCREATE TABLE orders (id BIGINT PRIMARY KEY, total FLOAT64)
DROP TABLERemove a tableDROP TABLE IF EXISTS orders
ALTER TABLEModify table schemaALTER TABLE orders ADD COLUMN status TEXT
TRUNCATERemove all rows from a tableTRUNCATE TABLE orders
CREATE INDEXCreate a B-tree or vector indexCREATE INDEX idx_total ON orders (total)
DROP INDEXRemove an indexDROP INDEX IF EXISTS idx_total
CREATE VIEWDefine a named queryCREATE VIEW high_value AS SELECT * FROM orders WHERE total > 1000
DROP VIEWRemove a viewDROP VIEW IF EXISTS high_value
CREATE TYPE ... AS ENUMDefine an enumerated typeCREATE TYPE status AS ENUM ('pending', 'shipped', 'delivered')
DROP TYPERemove a user-defined typeDROP TYPE IF EXISTS status
CREATE PROCEDUREDefine a stored procedureCREATE PROCEDURE archive(cutoff INT64) AS $$ ... $$
DROP PROCEDURERemove a stored procedureDROP PROCEDURE IF EXISTS archive
CREATE FUNCTIONDefine a user-defined functionCREATE FUNCTION double(x INT64) RETURNS INT64 AS $$ ... $$
DROP FUNCTIONRemove a user-defined functionDROP FUNCTION IF EXISTS double
ANALYZERefresh table statisticsANALYZE orders

See DDL for full syntax.

StatementDescriptionExample
SELECTQuery dataSELECT name, price FROM products WHERE price > 50
INSERTAdd rowsINSERT INTO products (id, name) VALUES (1, 'Widget')
INSERT ... ON CONFLICTUpsertINSERT INTO products ... ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name
UPDATEModify existing rowsUPDATE products SET price = 19.99 WHERE id = 1
DELETERemove rowsDELETE FROM products WHERE discontinued = true
COPY FROMBulk import (CSV, Parquet, JSON)COPY products FROM '/data/products.csv' WITH (FORMAT CSV)
COPY TOBulk exportCOPY products TO '/data/export.parquet' WITH (FORMAT PARQUET)
INSERT INTO ... SELECTInsert from a queryINSERT INTO archive SELECT * FROM orders WHERE created_at < '2025-01-01'

See SELECT, INSERT / UPDATE / DELETE.

StatementDescriptionExample
BEGINStart a transactionBEGIN
COMMITCommit the current transactionCOMMIT
ROLLBACKAbort the current transactionROLLBACK
SAVEPOINTCreate a named savepointSAVEPOINT before_update
RELEASE SAVEPOINTRelease a savepointRELEASE SAVEPOINT before_update
PREPARE TRANSACTIONPrepare for two-phase commitPREPARE TRANSACTION 'tx_001'
COMMIT PREPAREDCommit a prepared transactionCOMMIT PREPARED 'tx_001'
ROLLBACK PREPAREDRollback a prepared transactionROLLBACK PREPARED 'tx_001'

See Transactions.

StatementDescriptionExample
CREATE ROLECreate a roleCREATE ROLE analyst
CREATE USERCreate a user (role with login)CREATE USER bob WITH PASSWORD 'secret'
DROP ROLERemove a roleDROP ROLE IF EXISTS analyst
GRANTGrant privileges or rolesGRANT SELECT ON orders TO analyst
REVOKERevoke privileges or rolesREVOKE INSERT ON orders FROM analyst
ALTER ROLEModify role propertiesALTER ROLE bob SET PASSWORD 'new_secret'
CREATE POLICYDefine row-level security policyCREATE POLICY tenant_iso ON orders FOR SELECT USING (tenant_id = current_user_attr('tenant'))
DROP POLICYRemove an RLS policyDROP POLICY tenant_iso ON orders

See DDL for full syntax.

StatementDescriptionExample
EXPLAINShow the query planEXPLAIN SELECT * FROM orders WHERE id = 42
EXPLAIN ANALYZEExecute and show actual timingsEXPLAIN ANALYZE SELECT COUNT(*) FROM orders
SETSet a session variableSET search_path = 'public'
SHOWShow a session variableSHOW server_version
LISTENSubscribe to a notification channelLISTEN order_updates
UNLISTENUnsubscribe from a channelUNLISTEN order_updates
NOTIFYSend a notificationNOTIFY order_updates, 'order 42 shipped'
CALLExecute a stored procedureCALL archive(30)

TypeAliasesDescription
INT64INT, BIGINT, SMALLINT, TINYINT64-bit signed integer
FLOAT64FLOAT, DOUBLE, REAL, DOUBLE PRECISION64-bit IEEE 754 floating point
BOOLEANBOOLTRUE or FALSE
TEXTVARCHAR, STRING, CHARVariable-length UTF-8 string
BYTESBYTEA, BLOB, BINARYVariable-length byte array
TIMESTAMPMicrosecond-precision UTC timestamp
VECTOR(n)Dense array of n 32-bit floats for similarity search
JSONJSONBJSON document stored as text
ARRAYArray of scalar values
ENUMUser-defined enumerated type (via CREATE TYPE)

See Data Types for casting, storage details, and examples.


OperatorDescriptionExample
=Equalprice = 9.99
!= or <>Not equalstatus != 'cancelled'
<Less thanage < 30
&lt;=Less than or equalprice &lt;= 100
>Greater thanscore > 90
>=Greater than or equalquantity >= 5
OperatorDescriptionExample
ANDLogical conjunctionprice > 10 AND price < 50
ORLogical disjunctionstatus = 'active' OR status = 'pending'
NOTLogical negationNOT is_deleted
OperatorDescriptionExample
+Additionprice + tax
-Subtractiontotal - discount
*Multiplicationquantity * price
/Divisiontotal / count
%Moduloid % 10
OperatorDescriptionExample
||String concatenationfirst_name || ' ' || last_name
LIKEPattern match (case-sensitive)name LIKE 'Jo%'
NOT LIKENegated pattern matchemail NOT LIKE '%@spam.com'
ILIKEPattern match (case-insensitive)name ILIKE '%smith%'
PredicateDescriptionExample
IS NULLTest for nullemail IS NULL
IS NOT NULLTest for non-nullphone IS NOT NULL
IN (...)Set membershipstatus IN ('active', 'pending')
NOT IN (...)Negated set membershipid NOT IN (1, 2, 3)
BETWEEN ... ANDRange test (inclusive)price BETWEEN 10 AND 50
EXISTS (subquery)Test for non-empty subqueryEXISTS (SELECT 1 FROM orders WHERE customer_id = c.id)
ANY / SOMECompare to any subquery rowprice > ANY (SELECT min_price FROM tiers)
ALLCompare to all subquery rowsscore >= ALL (SELECT threshold FROM rules)
CONTAINS(s, sub)True if string contains substringCONTAINS(email, '@gmail.com')
OperatorDescriptionExample
->Extract JSON element (returns JSON)data -> 'address'
->>Extract JSON element (returns text)data ->> 'name'
OperatorDescriptionExample
&lt;=>Vector distance (for ORDER BY)ORDER BY embedding &lt;=> '[0.1, 0.2, ...]' LIMIT 10

FunctionDescriptionExample
ABS(x)Absolute valueABS(-42)42
ROUND(x [, d])Round to d decimal placesROUND(3.14159, 2)3.14
CEIL(x) / CEILING(x)Round up to nearest integerCEIL(2.3)3.0
FLOOR(x)Round down to nearest integerFLOOR(2.7)2.0
PI()Pi constant (3.14159…)PI()3.141592653589793
SQRT(x)Square rootSQRT(144)12.0
POWER(base, exp) / POWExponentiationPOWER(2, 10)1024.0
EXP(x)Natural exponential (e^x)EXP(1)2.718...
LN(x)Natural logarithmLN(2.718)~1.0
LOG(x)Natural logarithm (single arg)LOG(2.718)~1.0
LOG(base, x)Logarithm with explicit baseLOG(2, 1024)10.0
LOG10(x)Base-10 logarithmLOG10(100)2.0
LOG2(x)Base-2 logarithmLOG2(8)3.0
TRUNC(x [, n])Truncate to n decimal places (no rounding)TRUNC(3.14159, 3)3.141
SIGN(x)Sign of x (-1, 0, or 1)SIGN(-7)-1
CBRT(x)Cube rootCBRT(27)3.0
DIV(a, b)Integer (truncated) divisionDIV(7, 2)3
MOD(a, b)Modulo (remainder)MOD(7, 3)1
DEGREES(x)Radians to degreesDEGREES(3.14159)~180.0
RADIANS(x)Degrees to radiansRADIANS(180)~3.14159
SIN(x)SineSIN(0)0.0
COS(x)CosineCOS(0)1.0
TAN(x)TangentTAN(0)0.0
ASIN(x)Inverse sineASIN(1)~1.5708
ACOS(x)Inverse cosineACOS(1)0.0
ATAN(x)Inverse tangentATAN(1)~0.7854
ATAN2(y, x)Two-argument inverse tangentATAN2(1, 1)~0.7854
SINH(x)Hyperbolic sineSINH(1)~1.1752
COSH(x)Hyperbolic cosineCOSH(0)1.0
TANH(x)Hyperbolic tangentTANH(0)0.0
COT(x)Cotangent (1/tan)COT(1)~0.6421
RANDOM() / RAND()Random float in [0.0, 1.0)RANDOM()
FunctionDescriptionExample
UPPER(s)Convert to uppercaseUPPER('hello')'HELLO'
LOWER(s)Convert to lowercaseLOWER('HELLO')'hello'
LENGTH(s) / LEN / STRLENString lengthLENGTH('hello')5
SUBSTRING(s, start [, len]) / SUBSTRExtract substring (1-based)SUBSTRING('hello', 2, 3)'ell'
TRIM(s)Remove leading/trailing whitespaceTRIM(' hi ')'hi'
LTRIM(s)Remove leading whitespaceLTRIM(' hi')'hi'
RTRIM(s)Remove trailing whitespaceRTRIM('hi ')'hi'
LEFT(s, n)First n charactersLEFT('hello', 3)'hel'
RIGHT(s, n)Last n charactersRIGHT('hello', 3)'llo'
REPLACE(s, from, to)Replace all occurrencesREPLACE('hello', 'l', 'r')'herro'
REVERSE(s)Reverse a stringREVERSE('abc')'cba'
REPEAT(s, n)Repeat string n timesREPEAT('ab', 3)'ababab'
INITCAP(s)Capitalize first letter of each wordINITCAP('hello world')'Hello World'
CONCAT(a, b, ...)Concatenate strings (NULL-safe)CONCAT('a', NULL, 'b')'ab'
POSITION(haystack, needle) / STRPOSFind substring position (1-based, 0 = not found)POSITION('hello', 'ell')2
STARTS_WITH(s, prefix)True if string starts with prefixSTARTS_WITH('hello', 'hel')TRUE
ENDS_WITH(s, suffix)True if string ends with suffixENDS_WITH('hello', 'llo')TRUE
CONCAT_WS(sep, a, b, ...)Concatenate with separator (NULL-safe)CONCAT_WS('-', 'a', 'b', 'c')'a-b-c'
LPAD(s, len [, fill])Left-pad string to length (fill defaults to space)LPAD('42', 5, '0')'00042'
RPAD(s, len [, fill])Right-pad string to length (fill defaults to space)RPAD('hi', 5, '.')'hi...'
CONTAINS(s, substr)True if s contains substrCONTAINS('hello', 'ell')TRUE
SPLIT_PART(s, delim, n)Return the nth token after splitting by delimiterSPLIT_PART('a.b.c', '.', 2)'b'
CHAR_LENGTH(s) / CHARACTER_LENGTHCharacter length (same as LENGTH)CHAR_LENGTH('hello')5
OCTET_LENGTH(s)Length in bytesOCTET_LENGTH('hello')5
BIT_LENGTH(s)Length in bitsBIT_LENGTH('hello')40
TRANSLATE(s, from, to)Replace characters by positional mappingTRANSLATE('hello', 'el', 'ip')'hippo'
HEX(s) / TO_HEX(s)Encode string as hexadecimalTO_HEX('AB')
ASCII(s)ASCII code of the first characterASCII('A')65
CHR(n)Character for the given ASCII codeCHR(65)'A'
REGEXP_REPLACE(s, pattern, replacement)Regex-based string replacementREGEXP_REPLACE(url, '^https?://([^/]+)/.*', '\1')
MD5(s)MD5 hash as hex stringMD5('hello')
SHA1(s)SHA-1 hash as hex stringSHA1('hello')
SHA256(s)SHA-256 hash as hex stringSHA256('hello')
SHA512(s)SHA-512 hash as hex stringSHA512('hello')
FunctionDescriptionExample
NOW() / CURRENT_TIMESTAMPCurrent UTC timestampNOW()
CURRENT_DATECurrent UTC date (midnight)CURRENT_DATE
CURRENT_TIMECurrent time as HH:MM:SSCURRENT_TIME
DATE(expr)Truncate a timestamp to the date partDATE(NOW())'2025-04-10'
EXTRACT(field FROM ts)Extract part of timestampEXTRACT(YEAR FROM created_at)
DATE_TRUNC(unit, ts)Truncate to specified precisionDATE_TRUNC('hour', created_at)
DATE_FORMAT(ts, fmt)Format timestamp (MySQL-style)DATE_FORMAT(NOW(), '%Y-%m-%d')
TO_CHAR(ts, fmt)Format timestamp with PostgreSQL format codesTO_CHAR(NOW(), 'YYYY-MM-DD HH24:MI:SS')
TO_DATE(str, fmt)Parse a date string using a format patternTO_DATE('2025-04-10', 'YYYY-MM-DD')
TIME_BUCKET(interval_secs, ts)Bucket timestamps (time-series)TIME_BUCKET(300, event_time)

Supported EXTRACT fields: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, QUARTER, WEEK, ISODOW, MILLISECOND.

FunctionDescriptionExample
COALESCE(a, b, ...)First non-null argumentCOALESCE(nickname, first_name, 'Anonymous')
NULLIF(a, b)Returns NULL if a = b, else aNULLIF(discount, 0)
GREATEST(a, b, ...)Largest argumentGREATEST(score1, score2, score3)
LEAST(a, b, ...)Smallest argumentLEAST(price, max_price)
CASE WHEN ... THEN ... ENDConditional expressionCASE WHEN age >= 18 THEN 'adult' ELSE 'minor' END
FunctionDescriptionExample
CAST(expr AS type)Convert to target type (error on failure)CAST('42' AS INT64)
TRY_CAST(expr AS type)Convert to target type (NULL on failure)TRY_CAST('abc' AS INT64)NULL
expr::typePostgreSQL-style cast shorthand'42'::INT64
FunctionDescriptionExample
GEN_RANDOM_UUID()Generate a v4 UUID stringGEN_RANDOM_UUID()
TYPEOF(expr) / PG_TYPEOFReturn the data type name of an expressionTYPEOF(42)'INT64'
IF(cond, then, else) / IIFInline conditional (shorthand for CASE)IF(x > 0, 'pos', 'non-pos')
SESSION_USERCurrent session user nameSELECT SESSION_USER
FunctionDescriptionExample
L2_DISTANCE(a, b)Euclidean distance between two vectorsL2_DISTANCE(embedding, VECTOR('[0.1, 0.2]'))
COSINE_SIMILARITY(a, b)Cosine similarity (1.0 = identical)COSINE_SIMILARITY(embedding, query_vec)
INNER_PRODUCT(a, b) / DOT_PRODUCTDot product of two vectorsINNER_PRODUCT(embedding, query_vec)
FunctionDescriptionExample
JSON_EXTRACT(json, path)Extract JSON element (via ->)JSON_EXTRACT(data, 'name')
JSON_EXTRACT_SCALAR(json, path)Extract JSON element as text (via ->>)JSON_EXTRACT_SCALAR(data, 'email')
JSON_PATH(json, path) / JSON_PATH_QUERYExtract element using JSONPath expression (returns JSON)JSON_PATH(data, '$.address.city')
JSON_PATH_SCALAR(json, path) / JSON_PATH_QUERY_SCALARExtract element using JSONPath expression (returns text)JSON_PATH_SCALAR(data, '$.name')

FunctionDescriptionExample
COUNT(*)Count all rowsSELECT COUNT(*) FROM orders
COUNT(expr)Count non-null valuesCOUNT(email)
COUNT(DISTINCT expr)Count distinct non-null valuesCOUNT(DISTINCT customer_id)
SUM(expr)Sum of valuesSUM(amount)
AVG(expr)Arithmetic meanAVG(price)
MIN(expr)Minimum valueMIN(created_at)
MAX(expr)Maximum valueMAX(score)
MEDIAN(expr)Median valueMEDIAN(response_time)
MODE(expr)Most frequent valueMODE(category)
STDDEV(expr) / STDDEV_POPPopulation standard deviationSTDDEV(latency)
STDDEV_SAMP(expr)Sample standard deviationSTDDEV_SAMP(latency)
VAR_POP(expr) / VARIANCEPopulation varianceVAR_POP(score)
VAR_SAMP(expr)Sample varianceVAR_SAMP(score)
STRING_AGG(expr, sep)Concatenate strings with separatorSTRING_AGG(tag, ', ')
GROUP_CONCAT(expr)Concatenate strings (MySQL compat)GROUP_CONCAT(name)
ARRAY_AGG(expr) / JSON_ARRAYAGG / JSONB_AGG / JSON_AGGCollect values into an arrayARRAY_AGG(product_id)
BOOL_AND(expr)True if all values are trueBOOL_AND(is_verified)
BOOL_OR(expr)True if any value is trueBOOL_OR(has_error)
BIT_AND(expr)Bitwise AND across all values in groupBIT_AND(flags)
BIT_OR(expr)Bitwise OR across all values in groupBIT_OR(flags)
BIT_XOR(expr)Bitwise XOR across all values in groupBIT_XOR(flags)
ANY_VALUE(expr)Arbitrary non-null value from groupANY_VALUE(description)
FIRST(val, ts)Value with the earliest timestampFIRST(status, updated_at)
LAST(val, ts)Value with the latest timestampLAST(status, updated_at)
ARG_MIN(val, key) / MIN_BY / ARGMINValue where key is minimumARG_MIN(name, price)
ARG_MAX(val, key) / MAX_BY / ARGMAXValue where key is maximumARG_MAX(name, score)
PERCENTILE_CONT(pct)Continuous percentilePERCENTILE_CONT(0.95)
PERCENTILE_DISC(pct)Discrete percentilePERCENTILE_DISC(0.5)
APPROX_COUNT_DISTINCT(expr)Approximate distinct count (HyperLogLog)APPROX_COUNT_DISTINCT(user_id)

All aggregates support the FILTER (WHERE ...) modifier:

SELECT
COUNT(*) AS total,
COUNT(*) FILTER (WHERE status = 'shipped') AS shipped
FROM orders;

See Aggregations for detailed reference.


FunctionDescription
ROW_NUMBER()Sequential row number within partition
RANK()Rank with gaps for ties
DENSE_RANK()Rank without gaps for ties
NTILE(n)Divide rows into n buckets
PERCENT_RANK()Relative rank (0.0 to 1.0)
CUME_DIST()Cumulative distribution
LAG(expr [, offset [, default]])Value from preceding row
LEAD(expr [, offset [, default]])Value from following row
FIRST_VALUE(expr)First value in the window frame
LAST_VALUE(expr)Last value in the window frame
NTH_VALUE(expr, n)Nth value in the window frame
SUM(expr) OVER (...)Running or partitioned sum
AVG(expr) OVER (...)Running or partitioned average
COUNT(expr) OVER (...)Running or partitioned count
MIN(expr) OVER (...)Running or partitioned minimum
MAX(expr) OVER (...)Running or partitioned maximum
MOVING_AVG(expr [, window_size])Moving average over a sliding window
MOVING_SUM(expr [, window_size])Moving sum over a sliding window
EXP_MOVING_AVG(expr [, alpha])Exponential moving average
DELTA(expr)Difference from the previous row
RATE(expr)Rate of change from the previous row
SELECT
department,
name,
salary,
RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dept_rank,
SUM(salary) OVER (PARTITION BY department) AS dept_total
FROM employees;

See SELECT for window function syntax details.


FunctionDescriptionExample
GENERATE_SERIES(start, stop [, step])Generate a sequence of valuesSELECT * FROM GENERATE_SERIES(1, 10)
UNNEST(array)Expand an array into rowsSELECT * FROM UNNEST(ARRAY[1, 2, 3])

ParticleDB supports several SQL extensions beyond the standard dialect for improved ergonomics and analytical power.

Automatically infers which select-list columns belong in the GROUP BY — any column not inside an aggregate function is included automatically.

-- Standard GROUP BY (explicit)
SELECT category, region, SUM(amount) FROM orders GROUP BY category, region;
-- GROUP BY ALL (auto-inferred — equivalent)
SELECT category, region, SUM(amount) FROM orders GROUP BY ALL;
-- Works with multiple aggregates and ORDER BY
SELECT a, b, COUNT(*), AVG(c) FROM t GROUP BY ALL ORDER BY COUNT(*) DESC;

Return all columns except the named ones. Useful for wide tables where you want to drop sensitive or internal columns without listing every remaining column.

-- Drop two sensitive columns
SELECT * EXCLUDE(password, ssn) FROM users;
-- Combine with WHERE
SELECT * EXCLUDE(id) FROM orders WHERE amount > 100;
-- Works on subquery results
SELECT * EXCLUDE(rn) FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY score DESC) AS rn FROM students
) sub;

Filter rows based on the result of a window function — analogous to HAVING for aggregates, but for window functions. Avoids a subquery wrap.

-- Top-3 employees per department by salary
SELECT *, ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn
FROM emp
QUALIFY rn <= 3;
-- Students tied for first place
SELECT *, RANK() OVER (ORDER BY score DESC) AS r
FROM students
QUALIFY r = 1;

CONTAINS(string, substring) returns TRUE if string contains substring. A readable alternative to LIKE '%substr%'.

-- Filter gmail users
SELECT * FROM users WHERE CONTAINS(email, '@gmail.com');
-- Compose multiple checks
SELECT CONTAINS('nested query', 'query') AND CONTAINS('test', 'es');

A trailing comma after the last item in a SELECT list is silently accepted.

SELECT
name,
email,
created_at, -- trailing comma is fine
FROM users
WHERE active = TRUE;

INSERT into a table with a primary key now returns an error if a row with the same PK already exists, matching the SQL standard. Use ON CONFLICT to upsert.

CREATE TABLE users (id INT PRIMARY KEY, name TEXT);
INSERT INTO users VALUES (1, 'alice');
INSERT INTO users VALUES (1, 'bob'); -- ERROR: duplicate key
-- Upsert instead
INSERT INTO users VALUES (1, 'bob')
ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name;
FunctionCategoryDescription
PI()MathReturns pi (3.14159…)
LOG(base, x)MathTwo-argument form: log base base of x
TRUNC(x [, n])MathTruncate to n decimal places (no rounding)
FLOOR(x)MathParser support added
CEIL(x) / CEILING(x)MathParser support added
BIT_AND(expr)AggregateBitwise AND over group
BIT_OR(expr)AggregateBitwise OR over group
BIT_XOR(expr)AggregateBitwise XOR over group
TO_CHAR(ts, fmt)DatePostgreSQL format codes: YYYY, MM, DD, HH24, MI, SS
TO_DATE(str, fmt)DateParse a date string into a timestamp
DATE(expr)DateTruncate timestamp to date (midnight UTC)
DATE_FORMAT(ts, fmt)DateMySQL-style alias for TO_CHAR
CURRENT_TIMEDateCurrent time as HH:MM:SS
SESSION_USERSystemCurrent session user name
EXTRACT(QUARTER ...)DateQuarter of the year (1-4)
EXTRACT(ISODOW ...)DateISO day of week (1=Monday, 7=Sunday)
EXTRACT(WEEK ...)DateISO week number (1-53)
EXTRACT(MILLISECOND ...)DateMilliseconds component
SPLIT_PART(s, delim, n)StringSplit and return the nth token
LPAD(s, len)Stringfill now optional (defaults to space)
RPAD(s, len)Stringfill now optional (defaults to space)
CONTAINS(s, sub)StringBoolean substring membership check
CROSS JOINJoinExplicit cross-join syntax fully supported
-- Math
SELECT PI(); -- 3.141592653589793
SELECT LOG(2, 1024); -- 10.0
SELECT TRUNC(3.14159, 3); -- 3.141
SELECT FLOOR(2.7), CEIL(2.3); -- 2.0, 3.0
-- Bitwise aggregates
SELECT role, BIT_AND(flags), BIT_OR(flags), BIT_XOR(flags)
FROM permissions
GROUP BY role;
-- Date formatting
SELECT TO_CHAR(NOW(), 'YYYY-MM-DD HH24:MI:SS');
SELECT TO_DATE('2025-04-10', 'YYYY-MM-DD');
SELECT CURRENT_TIME; -- e.g. '14:32:07'
-- Extended EXTRACT fields
SELECT
EXTRACT(QUARTER FROM NOW()), -- 1-4
EXTRACT(ISODOW FROM NOW()), -- 1=Mon ... 7=Sun
EXTRACT(WEEK FROM NOW()); -- ISO week 1-53
-- String helpers
SELECT SPLIT_PART('a.b.c', '.', 2); -- 'b'
SELECT LPAD('42', 5); -- ' 42'
SELECT RPAD('hi', 5); -- 'hi '