Appendix B: SQL Compatibility Reference

This appendix provides a comprehensive reference for SQL compatibility in Cognica, documenting supported statements, data types, operators, functions, and PostgreSQL compatibility features. Cognica implements a substantial subset of PostgreSQL SQL dialect, enabling compatibility with most PostgreSQL client applications and tools.

B.1 Statement Support Matrix

B.1.1 Data Query Language (DQL)

StatementSupportNotes
SELECTFullAll standard clauses supported
FROMFullTables, subqueries, joins, LATERAL
WHEREFullAll predicates and subqueries
GROUP BYFullIncluding GROUPING SETS, CUBE, ROLLUP
HAVINGFullAggregate filtering
ORDER BYFullASC/DESC, NULLS FIRST/LAST
LIMIT/OFFSETFullRow limiting, parameterized expressions
DISTINCTFullIncluding DISTINCT ON
UNION/INTERSECT/EXCEPTFullSet operations with ALL
WITH (CTE)FullIncluding WITH RECURSIVE
EXPLAINFullANALYZE, VERBOSE options

SELECT Clause Features:

-- Standard SELECT
SELECT column1, column2 FROM table_name;

-- SELECT with expressions
SELECT id, price * quantity AS total FROM orders;

-- DISTINCT
SELECT DISTINCT category FROM products;

-- DISTINCT ON (PostgreSQL extension)
SELECT DISTINCT ON (department) employee_id, name, salary
FROM employees ORDER BY department, salary DESC;

-- Subquery in SELECT
SELECT name, (SELECT COUNT(*) FROM orders WHERE orders.customer_id = c.id)
FROM customers c;

-- Parameterized LIMIT/OFFSET (useful in prepared statements)
SELECT id FROM users LIMIT $1 + 1 OFFSET $2;

B.1.2 Data Manipulation Language (DML)

StatementSupportNotes
INSERTFullVALUES, SELECT, RETURNING, ON CONFLICT
UPDATEFullSET, WHERE, RETURNING
DELETEFullWHERE, RETURNING
COPYFullImport/export operations
TRUNCATEFullFast table emptying

DML Examples:

-- INSERT with VALUES
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');

-- INSERT with SELECT
INSERT INTO archive SELECT * FROM logs WHERE created_at < '2024-01-01';

-- INSERT with RETURNING
INSERT INTO orders (product_id, quantity) VALUES (1, 5)
RETURNING id, created_at;

-- UPDATE with RETURNING
UPDATE products SET price = price * 1.1 WHERE category = 'electronics'
RETURNING id, name, price;

-- DELETE with RETURNING
DELETE FROM sessions WHERE expires_at < NOW() RETURNING user_id;

-- INSERT ON CONFLICT (upsert)
INSERT INTO users (id, name, email) VALUES (1, 'Alice', 'alice@example.com')
ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, email = EXCLUDED.email;

-- INSERT ON CONFLICT DO NOTHING
INSERT INTO tags (name) VALUES ('important')
ON CONFLICT (name) DO NOTHING;

-- COPY for bulk operations
COPY users TO '/tmp/users.csv' WITH (FORMAT CSV, HEADER);
COPY users FROM '/tmp/users.csv' WITH (FORMAT CSV, HEADER);

B.1.3 Data Definition Language (DDL)

StatementSupportNotes
CREATE TABLEFullAll constraint types
DROP TABLEFullIF EXISTS, CASCADE
ALTER TABLEFullAdd/drop columns, constraints
CREATE INDEXFullB-tree indexes
DROP INDEXFullIF EXISTS
CREATE VIEWFullVirtual tables
DROP VIEWFullIF EXISTS, CASCADE
CREATE MATERIALIZED VIEWFullCached query results
REFRESH MATERIALIZED VIEWFullUpdate cached data
CREATE SEQUENCEFullAuto-increment values
ALTER SEQUENCEFullModify sequence properties
CREATE TRIGGERFullEvent-based actions
CREATE FUNCTIONFullUser-defined functions
CREATE PROCEDUREFullStored procedures
CALLFullProcedure invocation
CREATE SCHEMAFullNamespace management
DROP SCHEMAFullIF EXISTS, CASCADE
ALTER SCHEMAFullRENAME TO
CREATE DATABASEFullWorkspace-based isolation
DROP DATABASEFullIF EXISTS
CREATE TYPEPartialENUM types supported

DDL Examples:

-- CREATE TABLE with constraints
CREATE TABLE orders (
    id BIGSERIAL PRIMARY KEY,
    customer_id BIGINT NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
    total DECIMAL(10,2) CHECK (total >= 0),
    status VARCHAR(20) DEFAULT 'pending',
    created_at TIMESTAMP DEFAULT NOW(),
    UNIQUE (customer_id, created_at)
);

-- ALTER TABLE operations
ALTER TABLE orders ADD COLUMN notes TEXT;
ALTER TABLE orders DROP COLUMN notes;
ALTER TABLE orders ALTER COLUMN status SET DEFAULT 'new';
ALTER TABLE orders ADD CONSTRAINT positive_total CHECK (total > 0);
ALTER TABLE orders RENAME COLUMN total TO order_total;
ALTER TABLE orders RENAME TO customer_orders;

-- CREATE INDEX
CREATE INDEX idx_orders_customer ON orders(customer_id);
CREATE INDEX idx_orders_status ON orders(status) WHERE status != 'completed';

-- CREATE VIEW
CREATE VIEW active_orders AS
SELECT * FROM orders WHERE status IN ('pending', 'processing');

-- CREATE MATERIALIZED VIEW
CREATE MATERIALIZED VIEW monthly_sales AS
SELECT DATE_TRUNC('month', created_at) AS month,
       SUM(total) AS revenue,
       COUNT(*) AS order_count
FROM orders
GROUP BY DATE_TRUNC('month', created_at);

-- Refresh materialized view
REFRESH MATERIALIZED VIEW monthly_sales;

-- CREATE SEQUENCE
CREATE SEQUENCE order_number_seq START 1000 INCREMENT 1;

-- CREATE TRIGGER
CREATE TRIGGER update_timestamp
BEFORE UPDATE ON orders
FOR EACH ROW EXECUTE FUNCTION update_modified_column();

B.1.4 Transaction Control

StatementSupportNotes
BEGIN / START TRANSACTIONFullTransaction start
COMMITFullPersist changes
ROLLBACKFullDiscard changes
SAVEPOINTFullNested transactions
RELEASE SAVEPOINTFullRelease savepoint
SET TRANSACTIONFullIsolation levels
PREPARE TRANSACTIONFullTwo-phase commit

Transaction Examples:

-- Basic transaction
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

-- Transaction with savepoint
BEGIN;
INSERT INTO orders (customer_id, total) VALUES (1, 500);
SAVEPOINT order_created;

INSERT INTO order_items (order_id, product_id) VALUES (currval('orders_id_seq'), 1);
-- Error occurs, rollback to savepoint
ROLLBACK TO SAVEPOINT order_created;

-- Try different item
INSERT INTO order_items (order_id, product_id) VALUES (currval('orders_id_seq'), 2);
COMMIT;

-- Set isolation level
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
-- Transaction with serializable isolation
COMMIT;

B.1.5 Access Control

StatementSupportNotes
CREATE ROLEFullUser/role creation
ALTER ROLEFullModify role properties
DROP ROLEFullRemove roles
GRANTFullObject and role privileges
REVOKEFullRemove privileges
CREATE POLICYFullRow-level security
ALTER POLICYFullModify RLS policies
SET ROLEFullSwitch active role

Access Control Examples:

-- Create role with login
CREATE ROLE app_user WITH LOGIN PASSWORD 'secret';

-- Grant privileges
GRANT SELECT, INSERT, UPDATE ON orders TO app_user;
GRANT USAGE ON SEQUENCE orders_id_seq TO app_user;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO admin;

-- Row-level security
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

CREATE POLICY orders_isolation ON orders
    USING (customer_id = current_setting('app.current_customer')::BIGINT);

-- Grant role membership
GRANT admin TO app_user;

B.2 Data Type Reference

B.2.1 Numeric Types

SQL TypeAliasesInternal StorageRange
SMALLINTINT264-bit integer-32768 to 32767
INTEGERINT, INT464-bit integer-2^31 to 2^31-1
BIGINTINT864-bit integer-2^63 to 2^63-1
REALFLOAT464-bit doubleIEEE 754 single
DOUBLE PRECISIONFLOAT8, FLOAT64-bit doubleIEEE 754 double
NUMERICDECIMAL64-bit doubleApproximate
SERIAL-64-bit integerAuto-increment
BIGSERIAL-64-bit integerAuto-increment
SMALLSERIAL-64-bit integerAuto-increment
MONEY-64-bit doubleCurrency values

Numeric Type Notes:

  • All integer types are stored as 64-bit integers internally for uniformity
  • NUMERIC/DECIMAL are stored as double-precision floating point
  • SERIAL types automatically create associated sequences
-- Numeric type usage
CREATE TABLE metrics (
    id BIGSERIAL PRIMARY KEY,
    count INTEGER NOT NULL DEFAULT 0,
    rate DOUBLE PRECISION,
    amount NUMERIC(10, 2)
);

B.2.2 Character Types

SQL TypeAliasesInternal StorageNotes
TEXT-UTF-8 stringUnlimited length
VARCHAR(n)CHARACTER VARYINGUTF-8 stringLength limit
CHAR(n)CHARACTERUTF-8 stringFixed length
BPCHAR-UTF-8 stringBlank-padded
NAME-UTF-8 stringPostgreSQL identifier

Character Type Notes:

  • All character types stored as UTF-8 strings internally
  • Length constraints enforced at input time
  • CHAR pads with spaces to specified length
-- Character type usage
CREATE TABLE documents (
    id BIGSERIAL PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content TEXT,
    code CHAR(10)
);

B.2.3 Date/Time Types

SQL TypeAliasesInternal StoragePrecision
DATE-Date valueDay
TIME-Time valueMicrosecond
TIMESTAMP-TimestampMicrosecond
TIMESTAMPTZTIMESTAMP WITH TIME ZONEUTC timestampMicrosecond
TIMETZTIME WITH TIME ZONETime with zoneMicrosecond
INTERVAL-IntervalMicrosecond

Date/Time Type Notes:

  • TIMESTAMP WITHOUT TIME ZONE stores local time
  • TIMESTAMPTZ stores UTC, converts on display
  • INTERVAL supports year-month and day-time components
-- Date/time type usage
CREATE TABLE events (
    id BIGSERIAL PRIMARY KEY,
    event_date DATE NOT NULL,
    start_time TIME,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    duration INTERVAL
);

-- Date/time literals
SELECT DATE '2024-01-15';
SELECT TIME '14:30:00';
SELECT TIMESTAMP '2024-01-15 14:30:00';
SELECT INTERVAL '2 hours 30 minutes';

B.2.4 Boolean Type

SQL TypeAliasesTrue ValuesFalse Values
BOOLEANBOOLTRUE, 't', 'true', 'y', 'yes', 'on', '1'FALSE, 'f', 'false', 'n', 'no', 'off', '0'
-- Boolean usage
CREATE TABLE features (
    name VARCHAR(100) PRIMARY KEY,
    enabled BOOLEAN DEFAULT FALSE,
    visible BOOLEAN DEFAULT TRUE
);

SELECT * FROM features WHERE enabled AND visible;

B.2.5 Binary Types

SQL TypeAliasesInternal StorageNotes
BYTEABLOBBase64 stringBinary data
-- Binary type usage
CREATE TABLE files (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(255),
    content BYTEA
);

-- Insert binary data (hex format)
INSERT INTO files (name, content) VALUES ('test', '\x48454C4C4F');

B.2.6 JSON Types

SQL TypeInternal StorageOperatorsNotes
JSONJSON string->, ->>, #>, #>>Text JSON
JSONBBinary JSONAll JSON + @>, <@, ?, ?, ?&

JSON Type Features:

  • Full JSONPath support with @? and @@ operators
  • JSONB indexing for efficient queries
  • Nested object and array access
-- JSON type usage
CREATE TABLE documents (
    id BIGSERIAL PRIMARY KEY,
    data JSONB NOT NULL,
    metadata JSON
);

-- JSON queries
SELECT data->'name' FROM documents;                    -- JSON value
SELECT data->>'name' FROM documents;                   -- Text value
SELECT data#>'{address,city}' FROM documents;          -- Path access
SELECT * FROM documents WHERE data @> '{"active": true}';
SELECT * FROM documents WHERE data ? 'email';
SELECT * FROM documents WHERE data @@ '$.price > 100';

B.2.7 Special Types

SQL TypeInternal StorageNotes
UUIDString128-bit identifier
OID64-bit integerObject identifier
ARRAYJSON arrayMulti-dimensional
-- UUID usage
CREATE TABLE sessions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id BIGINT NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Array usage
CREATE TABLE tags (
    id BIGSERIAL PRIMARY KEY,
    labels TEXT[] NOT NULL
);

B.2.8 ENUM Types

User-defined enumeration types with automatic vectorized analysis:

-- Create an ENUM type
CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');

-- Use in table
CREATE TABLE journal (
    id BIGSERIAL PRIMARY KEY,
    entry_date DATE NOT NULL,
    current_mood mood NOT NULL
);

-- Enum comparison follows definition order
SELECT * FROM journal WHERE current_mood > 'ok';  -- Returns 'happy' entries

B.2.9 Range Types

PostgreSQL-compatible range types for representing intervals:

SQL TypeElement TypeDescription
INT4RANGEINTEGERInteger range
INT8RANGEBIGINTBig integer range
NUMRANGENUMERICNumeric range
TSRANGETIMESTAMPTimestamp range
TSTZRANGETIMESTAMPTZTimestamptz range
DATERANGEDATEDate range
-- Range type usage
CREATE TABLE reservations (
    id BIGSERIAL PRIMARY KEY,
    room_id INTEGER NOT NULL,
    during TSRANGE NOT NULL,
    EXCLUDE USING gist (room_id WITH =, during WITH &&)
);

-- Range operators
SELECT * FROM reservations WHERE during @> NOW()::timestamp;
SELECT * FROM reservations WHERE during && '[2026-01-01, 2026-02-01)';
SELECT lower(during), upper(during) FROM reservations;

INSERT INTO tags (labels) VALUES (ARRAY['important', 'urgent']);
SELECT * FROM tags WHERE 'urgent' = ANY(labels);

B.3 Operator Reference

B.3.1 Arithmetic Operators

OperatorDescriptionExampleResult
+Addition2 + 35
-Subtraction5 - 23
*Multiplication3 * 412
/Division10 / 33
%Modulo10 % 31
^Power2 ^ 101024

B.3.2 Comparison Operators

OperatorDescriptionExample
=Equala = b
<> or !=Not equala <> b
<Less thana < b
>Greater thana > b
<=Less than or equala <= b
>=Greater than or equala >= b
IS NULLNull testa IS NULL
IS NOT NULLNot null testa IS NOT NULL
IS DISTINCT FROMNull-safe inequalitya IS DISTINCT FROM b
IS NOT DISTINCT FROMNull-safe equalitya IS NOT DISTINCT FROM b
BETWEENRange testa BETWEEN x AND y
INSet membershipa IN (1, 2, 3)

B.3.3 Logical Operators

OperatorDescriptionExample
ANDLogical conjunctiona AND b
ORLogical disjunctiona OR b
NOTLogical negationNOT a

Three-Valued Logic:

aba AND ba OR bNOT a
TRUETRUETRUETRUEFALSE
TRUEFALSEFALSETRUEFALSE
TRUENULLNULLTRUEFALSE
FALSEFALSEFALSEFALSETRUE
FALSENULLFALSENULLTRUE
NULLNULLNULLNULLNULL

B.3.4 Pattern Matching Operators

OperatorDescriptionCase SensitiveExample
LIKEPattern matchYesname LIKE 'A%'
NOT LIKENegated pattern matchYesname NOT LIKE 'A%'
ILIKEPattern matchNoname ILIKE 'a%'
NOT ILIKENegated pattern matchNoname NOT ILIKE 'a%'
SIMILAR TOSQL regexYesname SIMILAR TO 'A.*'
~POSIX regexYesname ~ '^A'
~*POSIX regexNoname ~* '^a'
!~Negated POSIX regexYesname !~ '^A'
!~*Negated POSIX regexNoname !~* '^a'

Pattern Wildcards:

PatternLIKE MeaningRegex Meaning
%Any stringN/A
_Any single characterN/A
.Literal dotAny character
.*N/AAny string
^N/AStart of string
$N/AEnd of string

B.3.5 String Operators

OperatorDescriptionExampleResult
||Concatenation'Hello' || ' ' || 'World''Hello World'

B.3.6 JSON/JSONB Operators

OperatorDescriptionExampleResult Type
->Get JSON fielddata->'name'JSON
->>Get JSON field as textdata->>'name'TEXT
#>Get JSON at pathdata#>'{a,b}'JSON
#>>Get JSON at path as textdata#>>'{a,b}'TEXT
@>Containsdata @> '{"a":1}'BOOLEAN
<@Contained by'{"a":1}' <@ dataBOOLEAN
?Key existsdata ? 'name'BOOLEAN
?|Any key existsdata ?| ARRAY['a','b']BOOLEAN
?&All keys existdata ?& ARRAY['a','b']BOOLEAN
||Merge/concatenatedata1 || data2JSONB
-Delete keydata - 'key'JSONB
#-Delete at pathdata #- '{a,b}'JSONB
@?JSONPath existsdata @? '$.a'BOOLEAN
@@JSONPath predicatedata @@ '$.price > 10'BOOLEAN

JSON Operator Examples:

-- Object field access
SELECT data->'address'->>'city' FROM customers;

-- Path access
SELECT data#>'{items,0,name}' FROM orders;

-- Containment queries
SELECT * FROM products WHERE specs @> '{"color": "red"}';

-- Key existence
SELECT * FROM documents WHERE data ? 'email';

-- JSONPath queries
SELECT * FROM products WHERE data @@ '$.price < 100';
SELECT * FROM products WHERE data @? '$.reviews[*] ? (@.rating > 4)';

B.3.7 Array Operators

OperatorDescriptionExample
= ANY(array)Element in array5 = ANY(ARRAY[1,3,5])
<> ALL(array)Element not in array5 <> ALL(ARRAY[1,2,3])
@>ContainsARRAY[1,2] @> ARRAY[1]
<@Contained byARRAY[1] <@ ARRAY[1,2]
&&OverlapARRAY[1,2] && ARRAY[2,3]
||ConcatenationARRAY[1,2] || ARRAY[3]

B.3.8 Full-Text Search Operators

OperatorDescriptionExample
@@Text search matchto_tsvector('text') @@ to_tsquery('word')

B.4 Function Reference

B.4.1 Mathematical Functions

FunctionDescriptionExampleResult
abs(x)Absolute valueabs(-5)5
ceil(x)Ceilingceil(4.2)5
floor(x)Floorfloor(4.8)4
round(x)Round to nearestround(4.5)5
round(x, n)Round to n decimalsround(4.567, 2)4.57
trunc(x)Truncate to integertrunc(4.9)4
trunc(x, n)Truncate to n decimalstrunc(4.567, 2)4.56
mod(x, y)Modulomod(10, 3)1
power(x, y)Exponentiationpower(2, 3)8
sqrt(x)Square rootsqrt(16)4
cbrt(x)Cube rootcbrt(27)3
exp(x)Exponentialexp(1)2.718...
ln(x)Natural logarithmln(2.718)1
log(x)Base-10 logarithmlog(100)2
log(b, x)Logarithm base blog(2, 8)3
sign(x)Sign (-1, 0, 1)sign(-5)-1
random()Random [0, 1)random()0.xxx
rand()Alias for random()rand()0.xxx
e()Euler's numbere()2.718...

Trigonometric Functions:

FunctionDescription
sin(x), cos(x), tan(x)Trigonometric (radians)
asin(x), acos(x), atan(x)Inverse trigonometric
atan2(y, x)Two-argument arctangent
sinh(x), cosh(x), tanh(x)Hyperbolic
sind(x), cosd(x), tand(x)Trigonometric (degrees)
asind(x), acosd(x), atand(x)Inverse trigonometric (degrees)
atan2d(y, x)Two-argument arctangent (degrees)
cotd(x)Cotangent (degrees)
degrees(x)Radians to degrees
radians(x)Degrees to radians
pi()Pi constant

B.4.2 String Functions

FunctionDescriptionExampleResult
length(s)String lengthlength('hello')5
char_length(s)Character countchar_length('hello')5
upper(s)Uppercaseupper('Hello')'HELLO'
lower(s)Lowercaselower('Hello')'hello'
initcap(s)Title caseinitcap('hello world')'Hello World'
concat(s1, s2, ...)Concatenateconcat('a', 'b', 'c')'abc'
concat_ws(sep, s1, s2)Concatenate with separatorconcat_ws('-', 'a', 'b')'a-b'
substring(s, start, len)Extract substringsubstring('hello', 2, 3)'ell'
substr(s, start, len)Extract substringsubstr('hello', 2, 3)'ell'
left(s, n)Left n charactersleft('hello', 2)'he'
right(s, n)Right n charactersright('hello', 2)'lo'
trim(s)Remove whitespacetrim(' hi ')'hi'
ltrim(s)Left trimltrim(' hi')'hi'
rtrim(s)Right trimrtrim('hi ')'hi'
lpad(s, len, fill)Left padlpad('hi', 5, '*')'***hi'
rpad(s, len, fill)Right padrpad('hi', 5, '*')'hi***'
replace(s, from, to)Replace substringreplace('hello', 'l', 'L')'heLLo'
reverse(s)Reverse stringreverse('hello')'olleh'
repeat(s, n)Repeat stringrepeat('ab', 3)'ababab'
position(sub IN s)Find positionposition('ll' IN 'hello')3
strpos(s, sub)Find positionstrpos('hello', 'll')3
split_part(s, del, n)Split and get partsplit_part('a-b-c', '-', 2)'b'
ascii(s)ASCII codeascii('A')65
chr(n)Character from codechr(65)'A'
starts_with(s, prefix)Prefix teststarts_with('hello', 'he')true
ends_with(s, suffix)Suffix testends_with('hello', 'lo')true
md5(s)MD5 hashmd5('hello')'5d41402abc4b...'
encode(data, format)Encode binaryencode('hello', 'base64')'aGVsbG8='
decode(s, format)Decode to binarydecode('aGVsbG8=', 'base64')'hello'
quote_ident(s)Quote identifierquote_ident('user')'"user"'
quote_literal(s)Quote literalquote_literal('it''s')'''it''s'''
quote_nullable(s)Quote or NULLquote_nullable(NULL)'NULL'
to_hex(n)Integer to hexto_hex(255)'ff'

Function Aliases:

AliasEquivalent
toupper(s)upper(s)
tolower(s)lower(s)
split(s, del)string_to_array(s, del)
len(s)length(s)

Regular Expression Functions:

FunctionDescriptionExample
regexp_match(s, pattern)First matchregexp_match('abc123', '\d+')
regexp_matches(s, pattern, flags)All matchesregexp_matches('a1b2', '\d', 'g')
regexp_replace(s, pattern, repl)Replace matchesregexp_replace('abc', '[a-z]', 'X', 'g')
regexp_split_to_array(s, pattern)Split to arrayregexp_split_to_array('a1b2c', '\d')
regexp_split_to_table(s, pattern)Split to rowsregexp_split_to_table('a1b2c', '\d')

B.4.3 Date/Time Functions

FunctionDescriptionExample
now()Current timestampnow()
current_timestampCurrent timestampcurrent_timestamp
current_dateCurrent datecurrent_date
current_timeCurrent timecurrent_time
transaction_timestamp()Transaction start timetransaction_timestamp()
statement_timestamp()Statement start timestatement_timestamp()
clock_timestamp()Actual current timeclock_timestamp()
date_trunc(unit, ts)Truncate to unitdate_trunc('month', now())
extract(unit FROM ts)Extract componentextract(year FROM now())
date_part(unit, ts)Extract componentdate_part('month', now())
age(ts1, ts2)Interval betweenage(now(), '2020-01-01')
age(ts)Age from nowage('2020-01-01')
to_timestamp(epoch)Unix timestamp to timestampto_timestamp(1700000000)
to_timestamp(s, fmt)Parse timestampto_timestamp('2024-01-15', 'YYYY-MM-DD')
to_date(s, fmt)Parse dateto_date('2024-01-15', 'YYYY-MM-DD')
to_char(ts, fmt)Format timestampto_char(now(), 'YYYY-MM-DD HH24:MI')

Extract/Date_Part Units:

UnitDescription
year, month, dayDate components
hour, minute, secondTime components
millisecond, microsecondSub-second precision
dowDay of week (0=Sunday)
doyDay of year
weekISO week number
quarterQuarter (1-4)
epochUnix timestamp

B.4.4 JSON Functions

FunctionDescription
json_build_object(k1, v1, ...)Build JSON object
json_build_array(v1, v2, ...)Build JSON array
jsonb_build_object(k1, v1, ...)Build JSONB object
jsonb_build_array(v1, v2, ...)Build JSONB array
json_object(keys, values)Build from arrays
json_array_length(json)Array element count
jsonb_array_length(jsonb)Array element count
json_typeof(json)JSON value type
jsonb_typeof(jsonb)JSONB value type
jsonb_pretty(jsonb)Pretty-print JSONB
jsonb_strip_nulls(jsonb)Remove null values
jsonb_set(jsonb, path, value)Set value at path
jsonb_insert(jsonb, path, value)Insert at path
jsonb_path_query(jsonb, path)JSONPath query
jsonb_path_query_array(jsonb, path)JSONPath to array
jsonb_path_query_first(jsonb, path)First JSONPath match
jsonb_path_exists(jsonb, path)JSONPath exists
jsonb_path_match(jsonb, path)JSONPath predicate
jsonb_object_keys_array(jsonb)Object keys as array
json_object_keys_array(json)Object keys as array

JSON Set-Returning Functions:

FunctionDescription
json_each(json)Key-value pairs
jsonb_each(jsonb)Key-value pairs
json_each_text(json)Key-text pairs
jsonb_each_text(jsonb)Key-text pairs
json_array_elements(json)Array elements
jsonb_array_elements(jsonb)Array elements
json_array_elements_text(json)Array elements as text
jsonb_array_elements_text(jsonb)Array elements as text
jsonb_object_keys(jsonb)Object keys
json_to_record(json)JSON to record
jsonb_to_record(jsonb)JSONB to record
json_to_recordset(json)JSON array to records
jsonb_to_recordset(jsonb)JSONB array to records

B.4.5 Array Functions

FunctionDescriptionExample
array_length(arr, dim)Array lengtharray_length(ARRAY[1,2,3], 1)
array_dims(arr)Array dimensionsarray_dims(ARRAY[[1,2],[3,4]])
array_upper(arr, dim)Upper boundarray_upper(ARRAY[1,2,3], 1)
array_lower(arr, dim)Lower boundarray_lower(ARRAY[1,2,3], 1)
array_append(arr, elem)Append elementarray_append(ARRAY[1,2], 3)
array_prepend(elem, arr)Prepend elementarray_prepend(0, ARRAY[1,2])
array_cat(arr1, arr2)Concatenatearray_cat(ARRAY[1], ARRAY[2])
array_remove(arr, elem)Remove elementarray_remove(ARRAY[1,2,2], 2)
array_replace(arr, from, to)Replace elementsarray_replace(ARRAY[1,2], 2, 3)
array_position(arr, elem)Find positionarray_position(ARRAY['a','b'], 'b')
array_positions(arr, elem)Find all positionsarray_positions(ARRAY[1,2,1], 1)
array_to_string(arr, del)Join to stringarray_to_string(ARRAY[1,2], ',')
string_to_array(s, del)Split to arraystring_to_array('a,b,c', ',')
unnest(arr)Expand to rowsunnest(ARRAY[1,2,3])

B.4.6 Conditional Functions

FunctionDescriptionExample
COALESCE(v1, v2, ...)First non-nullCOALESCE(null, 'default')
NULLIF(v1, v2)Null if equalNULLIF(x, 0)
GREATEST(v1, v2, ...)Maximum valueGREATEST(1, 2, 3)
LEAST(v1, v2, ...)Minimum valueLEAST(1, 2, 3)
CASEConditional expressionSee below

CASE Expression:

-- Simple CASE
SELECT CASE status
    WHEN 'A' THEN 'Active'
    WHEN 'I' THEN 'Inactive'
    ELSE 'Unknown'
END FROM items;

-- Searched CASE
SELECT CASE
    WHEN price < 10 THEN 'Cheap'
    WHEN price < 100 THEN 'Moderate'
    ELSE 'Expensive'
END FROM products;

B.4.7 Type Conversion Functions

FunctionDescriptionExample
CAST(expr AS type)Type conversionCAST('123' AS INTEGER)
expr::typeType conversion'123'::INTEGER
to_char(num, fmt)Number to stringto_char(123.45, '999.99')
to_number(s, fmt)String to numberto_number('123.45', '999.99')

B.4.8 System Functions

FunctionDescription
current_userCurrent user name
session_userSession user name
current_database()Current database name
current_schema()Current schema name
current_schemas(bool)Search path schemas
pg_typeof(expr)Expression type
version()Database version
gen_random_uuid()Generate UUID
txid_current()Current transaction ID

B.4.9 Sequence Functions

FunctionDescription
nextval(sequence)Get and increment
currval(sequence)Get current value
setval(sequence, value)Set sequence value
lastval()Last returned value

B.5 Aggregate Functions

B.5.1 General-Purpose Aggregates

FunctionDescriptionNULL Handling
COUNT(*)Row countCounts all rows
COUNT(expr)Non-null countIgnores NULL
SUM(expr)Sum of valuesIgnores NULL
AVG(expr)AverageIgnores NULL
MIN(expr)Minimum valueIgnores NULL
MAX(expr)Maximum valueIgnores NULL
ANY_VALUE(expr)Any value from groupReturns non-NULL if available

B.5.2 Statistical Aggregates

FunctionDescription
STDDEV(expr)Standard deviation (sample)
STDDEV_POP(expr)Population standard deviation
STDDEV_SAMP(expr)Sample standard deviation
VARIANCE(expr)Variance (sample)
VAR_POP(expr)Population variance
VAR_SAMP(expr)Sample variance
CORR(y, x)Correlation coefficient
COVAR_POP(y, x)Population covariance
COVAR_SAMP(y, x)Sample covariance

B.5.3 Regression Aggregates

FunctionDescription
REGR_SLOPE(y, x)Slope of regression line
REGR_INTERCEPT(y, x)Y-intercept
REGR_R2(y, x)R-squared (coefficient of determination)
REGR_AVGX(y, x)Average of X
REGR_AVGY(y, x)Average of Y
REGR_COUNT(y, x)Non-null pair count
REGR_SXX(y, x)Sum of squares of X
REGR_SYY(y, x)Sum of squares of Y
REGR_SXY(y, x)Sum of products

B.5.4 Ordered-Set Aggregates

FunctionDescription
PERCENTILE_CONT(frac) WITHIN GROUP (ORDER BY col)Continuous percentile
PERCENTILE_DISC(frac) WITHIN GROUP (ORDER BY col)Discrete percentile
MODE() WITHIN GROUP (ORDER BY col)Most frequent value
-- Median calculation
SELECT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary)
FROM employees;

-- Mode calculation
SELECT MODE() WITHIN GROUP (ORDER BY department)
FROM employees;

B.5.5 Hypothetical-Set Aggregates

FunctionDescription
RANK(value) WITHIN GROUP (ORDER BY col)Hypothetical rank
DENSE_RANK(value) WITHIN GROUP (ORDER BY col)Hypothetical dense rank
PERCENT_RANK(value) WITHIN GROUP (ORDER BY col)Hypothetical percent rank
CUME_DIST(value) WITHIN GROUP (ORDER BY col)Hypothetical cumulative distribution

B.5.6 String and Array Aggregates

FunctionDescription
STRING_AGG(expr, delimiter)Concatenate strings
STRING_AGG(expr, delimiter ORDER BY ...)Ordered concatenation
ARRAY_AGG(expr)Collect into array
ARRAY_AGG(expr ORDER BY ...)Ordered array
-- String aggregation
SELECT department, STRING_AGG(name, ', ' ORDER BY name)
FROM employees GROUP BY department;

-- Array aggregation
SELECT customer_id, ARRAY_AGG(product_id ORDER BY order_date)
FROM orders GROUP BY customer_id;

B.5.7 JSON Aggregates

FunctionDescription
JSON_AGG(expr)Aggregate to JSON array
JSONB_AGG(expr)Aggregate to JSONB array
JSON_AGG_STRICT(expr)Aggregate, exclude NULL
JSONB_AGG_STRICT(expr)Aggregate, exclude NULL
JSON_OBJECT_AGG(key, value)Aggregate to JSON object
JSONB_OBJECT_AGG(key, value)Aggregate to JSONB object

B.5.8 Bitwise Aggregates

FunctionDescription
BIT_AND(expr)Bitwise AND
BIT_OR(expr)Bitwise OR
BIT_XOR(expr)Bitwise XOR
BOOL_AND(expr)Logical AND
BOOL_OR(expr)Logical OR

B.5.9 Aggregate Modifiers

FILTER Clause:

-- Conditional aggregation
SELECT
    COUNT(*) AS total,
    COUNT(*) FILTER (WHERE status = 'active') AS active_count,
    SUM(amount) FILTER (WHERE type = 'credit') AS total_credits
FROM transactions;

DISTINCT in Aggregates:

-- Count distinct values
SELECT COUNT(DISTINCT category) FROM products;

-- Sum distinct values
SELECT SUM(DISTINCT price) FROM products;

B.6 Window Functions

B.6.1 Ranking Functions

FunctionDescription
ROW_NUMBER()Sequential row number
RANK()Rank with gaps
DENSE_RANK()Rank without gaps
NTILE(n)Divide into n buckets
PERCENT_RANK()Relative rank (0-1)
CUME_DIST()Cumulative distribution
-- Ranking example
SELECT name, department, salary,
    ROW_NUMBER() OVER (ORDER BY salary DESC) AS row_num,
    RANK() OVER (ORDER BY salary DESC) AS rank,
    DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rank,
    NTILE(4) OVER (ORDER BY salary DESC) AS quartile
FROM employees;

-- Ranking within partitions
SELECT name, department, salary,
    RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS dept_rank
FROM employees;

B.6.2 Value Functions

FunctionDescription
LAG(expr, offset, default)Previous row value
LEAD(expr, offset, default)Next row value
FIRST_VALUE(expr)First value in frame
LAST_VALUE(expr)Last value in frame
NTH_VALUE(expr, n)Nth value in frame
-- Compare with previous/next row
SELECT date, value,
    LAG(value, 1, 0) OVER (ORDER BY date) AS prev_value,
    LEAD(value, 1, 0) OVER (ORDER BY date) AS next_value,
    value - LAG(value, 1, 0) OVER (ORDER BY date) AS change
FROM metrics;

-- First and last values
SELECT date, category, value,
    FIRST_VALUE(value) OVER w AS first_val,
    LAST_VALUE(value) OVER w AS last_val
FROM sales
WINDOW w AS (PARTITION BY category ORDER BY date
             ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING);

B.6.3 Aggregate Window Functions

All standard aggregates can be used as window functions:

-- Running totals
SELECT date, amount,
    SUM(amount) OVER (ORDER BY date) AS running_total,
    AVG(amount) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS moving_avg
FROM transactions;

-- Partition aggregates
SELECT department, name, salary,
    AVG(salary) OVER (PARTITION BY department) AS dept_avg,
    salary - AVG(salary) OVER (PARTITION BY department) AS diff_from_avg
FROM employees;

B.6.4 Window Frame Specification

Frame Types:

TypeDescription
ROWSPhysical row offset
RANGELogical value range
GROUPSPeer group offset

Frame Bounds:

BoundDescription
UNBOUNDED PRECEDINGStart of partition
n PRECEDINGn rows/values before
CURRENT ROWCurrent row
n FOLLOWINGn rows/values after
UNBOUNDED FOLLOWINGEnd of partition

Frame Exclusion:

OptionDescription
EXCLUDE CURRENT ROWExclude current row
EXCLUDE GROUPExclude current row's peers
EXCLUDE TIESExclude peers except current
EXCLUDE NO OTHERSInclude all (default)
-- Various frame specifications
SELECT value,
    -- Last 3 rows including current
    SUM(value) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW),

    -- All rows with same or lower value
    SUM(value) OVER (ORDER BY value RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW),

    -- Excluding current row
    AVG(value) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING
                     EXCLUDE CURRENT ROW)
FROM data;

B.6.5 Named Windows

SELECT name, department, salary,
    RANK() OVER w AS rank,
    SUM(salary) OVER w AS running_total,
    AVG(salary) OVER w AS running_avg
FROM employees
WINDOW w AS (PARTITION BY department ORDER BY salary DESC);

B.7 Table-Valued Functions

B.7.1 Series Generation

-- Integer series
SELECT * FROM generate_series(1, 10);           -- 1 to 10
SELECT * FROM generate_series(1, 10, 2);        -- 1, 3, 5, 7, 9
SELECT * FROM generate_series(10, 1, -1);       -- 10 down to 1

-- Timestamp series
SELECT * FROM generate_series(
    '2024-01-01'::timestamp,
    '2024-01-07'::timestamp,
    '1 day'::interval
);

B.7.2 Array Expansion

-- Unnest array
SELECT unnest(ARRAY[1, 2, 3]);

-- Unnest with ordinality
SELECT * FROM unnest(ARRAY['a', 'b', 'c']) WITH ORDINALITY AS t(value, idx);

B.7.3 JSON Expansion

-- Expand JSON array
SELECT * FROM jsonb_array_elements('[1, 2, 3]'::jsonb);
SELECT * FROM jsonb_array_elements_text('["a", "b", "c"]'::jsonb);

-- Expand JSON object
SELECT * FROM jsonb_each('{"a": 1, "b": 2}'::jsonb);
SELECT * FROM jsonb_each_text('{"a": "x", "b": "y"}'::jsonb);

-- Get object keys
SELECT * FROM jsonb_object_keys('{"a": 1, "b": 2}'::jsonb);

B.7.4 Regular Expression Expansion

-- Extract all matches
SELECT * FROM regexp_matches('abc123def456', '\d+', 'g');

-- Split string to rows
SELECT * FROM regexp_split_to_table('a1b2c3', '\d');
SELECT * FROM string_to_table('a,b,c', ',');

B.8 JOIN Support

B.8.1 Supported JOIN Types

JOIN TypeSyntax
Inner JoinJOIN, INNER JOIN
Left Outer JoinLEFT JOIN, LEFT OUTER JOIN
Right Outer JoinRIGHT JOIN, RIGHT OUTER JOIN
Full Outer JoinFULL JOIN, FULL OUTER JOIN
Cross JoinCROSS JOIN
Natural JoinNATURAL JOIN
Semi JoinEXISTS subquery
Anti JoinNOT EXISTS subquery

B.8.2 JOIN Syntax

-- Explicit join condition
SELECT * FROM orders o
JOIN customers c ON o.customer_id = c.id;

-- USING clause (same column name)
SELECT * FROM orders
JOIN customers USING (customer_id);

-- NATURAL join (all common columns)
SELECT * FROM orders
NATURAL JOIN order_items;

-- Multiple joins
SELECT o.id, c.name, p.name AS product
FROM orders o
JOIN customers c ON o.customer_id = c.id
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id;

-- Left join with null handling
SELECT c.name, COALESCE(SUM(o.total), 0) AS total_orders
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
GROUP BY c.name;

B.8.3 LATERAL Joins

-- LATERAL subquery can reference outer tables
SELECT c.name, recent.order_date, recent.total
FROM customers c
LEFT JOIN LATERAL (
    SELECT order_date, total
    FROM orders
    WHERE customer_id = c.id
    ORDER BY order_date DESC
    LIMIT 3
) recent ON true;

-- LATERAL with table function
SELECT e.name, t.tag
FROM entities e
LEFT JOIN LATERAL unnest(e.tags) AS t(tag) ON true;

B.9 Subquery Support

B.9.1 Scalar Subqueries

-- In SELECT clause
SELECT name,
       (SELECT COUNT(*) FROM orders WHERE customer_id = c.id) AS order_count
FROM customers c;

-- In WHERE clause
SELECT * FROM products
WHERE price > (SELECT AVG(price) FROM products);

B.9.2 Table Subqueries

-- Derived table
SELECT dept, avg_salary
FROM (
    SELECT department AS dept, AVG(salary) AS avg_salary
    FROM employees
    GROUP BY department
) AS dept_stats
WHERE avg_salary > 50000;

-- With column aliases
SELECT * FROM (
    SELECT id, name, salary
    FROM employees
) AS e(emp_id, emp_name, emp_salary);

B.9.3 EXISTS and IN Subqueries

-- EXISTS (semi-join)
SELECT * FROM customers c
WHERE EXISTS (
    SELECT 1 FROM orders o WHERE o.customer_id = c.id
);

-- NOT EXISTS (anti-join)
SELECT * FROM customers c
WHERE NOT EXISTS (
    SELECT 1 FROM orders o WHERE o.customer_id = c.id
);

-- IN subquery
SELECT * FROM products
WHERE category_id IN (
    SELECT id FROM categories WHERE active = true
);

B.9.4 Correlated Subqueries

-- Correlated scalar subquery
SELECT e.name, e.salary,
       (SELECT AVG(salary) FROM employees e2
        WHERE e2.department = e.department) AS dept_avg
FROM employees e;

-- Correlated EXISTS
SELECT * FROM departments d
WHERE EXISTS (
    SELECT 1 FROM employees e
    WHERE e.department_id = d.id AND e.salary > 100000
);

B.10 Common Table Expressions (CTE)

B.10.1 Basic CTE

-- Single CTE
WITH active_customers AS (
    SELECT * FROM customers WHERE status = 'active'
)
SELECT * FROM active_customers WHERE created_at > '2024-01-01';

-- Multiple CTEs
WITH
    active_customers AS (
        SELECT * FROM customers WHERE status = 'active'
    ),
    recent_orders AS (
        SELECT * FROM orders WHERE order_date > CURRENT_DATE - INTERVAL '30 days'
    )
SELECT c.name, COUNT(o.id) AS recent_order_count
FROM active_customers c
LEFT JOIN recent_orders o ON c.id = o.customer_id
GROUP BY c.name;

B.10.2 Recursive CTE

-- Hierarchical query (org chart)
WITH RECURSIVE org_tree AS (
    -- Base case: top-level employees
    SELECT id, name, manager_id, 1 AS level
    FROM employees
    WHERE manager_id IS NULL

    UNION ALL

    -- Recursive case: employees with managers
    SELECT e.id, e.name, e.manager_id, t.level + 1
    FROM employees e
    JOIN org_tree t ON e.manager_id = t.id
)
SELECT * FROM org_tree ORDER BY level, name;

-- Generate sequence
WITH RECURSIVE nums AS (
    SELECT 1 AS n
    UNION ALL
    SELECT n + 1 FROM nums WHERE n < 100
)
SELECT * FROM nums;

B.10.3 CTE Materialization Hints

-- Force materialization
WITH active_users AS MATERIALIZED (
    SELECT * FROM users WHERE active = true
)
SELECT * FROM active_users a1
JOIN active_users a2 ON a1.department = a2.department;

-- Prevent materialization (inline)
WITH user_stats AS NOT MATERIALIZED (
    SELECT user_id, COUNT(*) AS cnt FROM events GROUP BY user_id
)
SELECT * FROM user_stats WHERE cnt > 10;

B.11 Set Operations

B.11.1 UNION

-- Remove duplicates
SELECT name FROM customers
UNION
SELECT name FROM suppliers;

-- Keep duplicates
SELECT name FROM customers
UNION ALL
SELECT name FROM suppliers;

B.11.2 INTERSECT

-- Common elements
SELECT customer_id FROM orders_2023
INTERSECT
SELECT customer_id FROM orders_2024;

-- With ALL
SELECT product_id FROM warehouse_a
INTERSECT ALL
SELECT product_id FROM warehouse_b;

B.11.3 EXCEPT

-- Elements in first but not second
SELECT customer_id FROM all_customers
EXCEPT
SELECT customer_id FROM active_customers;

-- With ALL
SELECT item_id FROM inventory
EXCEPT ALL
SELECT item_id FROM sold_items;

B.11.4 Combining Set Operations

-- Complex set operations
(SELECT id FROM table_a
 UNION
 SELECT id FROM table_b)
INTERSECT
SELECT id FROM table_c
ORDER BY id;

B.12 GROUP BY Extensions

B.12.1 GROUPING SETS

-- Multiple grouping configurations
SELECT region, product, SUM(sales)
FROM sales_data
GROUP BY GROUPING SETS (
    (region, product),  -- By region and product
    (region),           -- By region only
    (product),          -- By product only
    ()                  -- Grand total
);

B.12.2 ROLLUP

-- Hierarchical grouping
SELECT year, quarter, month, SUM(revenue)
FROM sales
GROUP BY ROLLUP (year, quarter, month);
-- Produces: (year, quarter, month), (year, quarter), (year), ()

B.12.3 CUBE

-- All combinations
SELECT region, product, SUM(sales)
FROM sales_data
GROUP BY CUBE (region, product);
-- Produces: (region, product), (region), (product), ()

B.12.4 GROUPING Function

-- Identify grouping level
SELECT
    CASE WHEN GROUPING(region) = 1 THEN 'All Regions' ELSE region END AS region,
    CASE WHEN GROUPING(product) = 1 THEN 'All Products' ELSE product END AS product,
    SUM(sales)
FROM sales_data
GROUP BY CUBE (region, product);

B.13 PostgreSQL System Catalog Compatibility

B.13.1 pg_catalog Tables

Cognica implements the following PostgreSQL system catalog tables:

TableDescription
pg_classTables, indexes, sequences, views
pg_attributeTable columns
pg_typeData types
pg_namespaceSchemas
pg_procFunctions, procedures, aggregates
pg_indexIndex definitions
pg_constraintConstraints
pg_rolesRoles/users
pg_triggerTriggers
pg_viewsView definitions
pg_matviewsMaterialized views
pg_dependObject dependencies
pg_descriptionObject comments
pg_sequenceSequences
pg_aggregateAggregate functions
pg_operatorOperators
pg_tablesTable listing
pg_indexesIndex listing
pg_stat_user_tablesTable statistics
pg_statio_user_tablesI/O statistics
pg_stat_activitySession activity

B.13.2 information_schema Tables

TableDescription
schemataSchema information
tablesTable information
columnsColumn information
viewsView information
table_constraintsConstraint information
key_column_usageKey columns
referential_constraintsForeign key references
check_constraintsCheck constraints
routinesFunctions and procedures
parametersRoutine parameters
sequencesSequence information
triggersTrigger information

B.13.3 System Catalog Queries

-- List all tables
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public';

-- Get column information
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'users';

-- List foreign keys
SELECT tc.constraint_name, tc.table_name, kcu.column_name,
       ccu.table_name AS foreign_table, ccu.column_name AS foreign_column
FROM information_schema.table_constraints tc
JOIN information_schema.key_column_usage kcu
    ON tc.constraint_name = kcu.constraint_name
JOIN information_schema.constraint_column_usage ccu
    ON tc.constraint_name = ccu.constraint_name
WHERE tc.constraint_type = 'FOREIGN KEY';

-- Get table size statistics
SELECT relname, n_live_tup, n_dead_tup
FROM pg_stat_user_tables;

B.14 EXPLAIN Output

B.14.1 Basic EXPLAIN

EXPLAIN SELECT * FROM orders WHERE customer_id = 123;

Output shows:

  • Execution plan tree
  • Estimated costs (startup and total)
  • Estimated row counts
  • Access methods used

B.14.2 EXPLAIN ANALYZE

EXPLAIN ANALYZE SELECT * FROM orders WHERE customer_id = 123;

Additional information:

  • Actual execution time
  • Actual row counts
  • Number of loops
  • Memory usage

B.14.3 EXPLAIN VERBOSE

EXPLAIN VERBOSE SELECT * FROM orders WHERE customer_id = 123;

Additional details:

  • Output column lists
  • Schema-qualified names
  • Detailed cost breakdown

B.15 Limitations and Differences

B.15.1 Features Not Supported

FeatureNotes
Table InheritancePostgreSQL-specific feature
Domain TypesUser-defined constrained types
Composite TypesAs first-class storage
Large ObjectsBYTEA supported, not true LO
TablespacesCatalog present, not enforced
Custom OperatorsUser-defined operators
PartitioningTable partitioning
Constraint TriggersSpecial trigger type

B.15.2 Behavioral Differences

AreaPostgreSQLCognica
NUMERIC precisionArbitraryDouble precision
Integer typesVarious sizesAll 64-bit internally
Array storageNativeJSON representation
Default isolationRead CommittedSnapshot
MVCCTuple-basedDocument-based

B.15.3 Extensions

Cognica includes features not in standard PostgreSQL:

FeatureDescription
Document queriesNative JSON document operations
Full-text searchIntegrated FTS with BM25 and Bayesian BM25
Vector searchHNSW-based similarity search with calibrated scoring
Hybrid searchLog-odds probabilistic fusion of text and vector signals
Graph queriesProperty graph operations via table functions and Cypher
Cypher languageopenCypher-compatible graph query language via cypher()
SSITrue SERIALIZABLE isolation via Serializable Snapshot Isolation

B.16 Graph Query Support

Cognica provides property graph capabilities through two complementary interfaces: SQL table functions for programmatic graph operations, and the openCypher query language for declarative graph pattern matching.

B.16.1 Graph Table Functions

Graph operations are exposed as SQL table functions that can be composed with standard SQL clauses including JOINs, WHERE filters, and aggregations.

Graph Management:

FunctionDescription
graph_create(name)Create a new graph
graph_drop(name)Drop an existing graph
graph_list()List all graphs

Node Operations:

FunctionDescription
graph_create_node(graph, label, properties)Create a node
graph_get_node(graph, node_id)Get node by ID
graph_update_node(graph, node_id, properties)Update node properties
graph_nodes(graph, label?, properties?)Query nodes
graph_delete_node(graph, node_id)Delete a node

Edge Operations:

FunctionDescription
graph_create_edge(graph, type, source, target, properties)Create an edge
graph_get_edge(graph, edge_id)Get edge by ID
graph_update_edge(graph, edge_id, properties)Update edge properties
graph_edges(graph, node_id, type?, direction?)Query edges
graph_delete_edge(graph, edge_id)Delete an edge

Traversal Functions:

FunctionDescription
graph_traverse(graph, start, type?, direction?, depth?)Traverse from a node
graph_neighbors(graph, node_id, type?, direction?, depth?)Find neighbor nodes
graph_shortest_path(graph, start, end, type?, direction?)Find shortest path

Graph Table Function Examples:

-- Create a graph and add data
SELECT * FROM graph_create('social');
SELECT * FROM graph_create_node('social', 'Person', '{"name": "Alice", "age": 30}');
SELECT * FROM graph_create_node('social', 'Person', '{"name": "Bob", "age": 25}');
SELECT * FROM graph_create_edge('social', 'KNOWS', 'alice_id', 'bob_id',
                                 '{"since": 2024}');

-- Query nodes by label
SELECT * FROM graph_nodes('social', 'Person');

-- Update node properties
SELECT * FROM graph_update_node('social', 'alice_id', '{"age": 31}');

-- Update edge properties using LATERAL join
SELECT u.success FROM social_edges e
CROSS JOIN LATERAL graph_update_edge(
    'social', e._id, '{"since": 2025}'
) AS u(success)
WHERE e._type = 'KNOWS';

-- Traverse the graph
SELECT * FROM graph_traverse('social', 'alice_id', 'KNOWS', 'outgoing', 3);

-- Find shortest path
SELECT * FROM graph_shortest_path('social', 'alice_id', 'bob_id');

B.16.2 Cypher Query Language

Cognica supports the openCypher query language through the cypher() table function in FROM clauses. Cypher queries are transparently rewritten into optimized SQL subqueries at parse time, allowing full integration with the SQL query planner and optimizer.

Syntax:

SELECT <columns>
FROM cypher('<graph_name>', $$ <cypher_query> $$) AS (<column_definitions>)

Supported Cypher Clauses:

ClauseDescription
MATCHPattern matching on nodes and relationships
OPTIONAL MATCHPattern matching with NULL for unmatched patterns
WHEREFiltering conditions
RETURNProjection of results
ORDER BYResult ordering
LIMIT / SKIPResult pagination
CREATECreate nodes and relationships
SETUpdate properties and labels
REMOVERemove properties and labels
DELETE / DETACH DELETEDelete nodes and relationships
MERGEMatch or create patterns
WITHQuery chaining and aggregation
UNWINDExpand lists into rows
CALL { ... }Subquery execution
FOREACHIterative updates

Node Pattern Matching:

-- Match nodes by label
SELECT * FROM cypher('social', $$
    MATCH (p:Person)
    RETURN p.name AS name, p.age AS age
$$) AS (name text, age bigint);

-- Match with property filter
SELECT * FROM cypher('social', $$
    MATCH (p:Person {name: 'Alice'})
    RETURN p.age AS age
$$) AS (age bigint);

Relationship Pattern Matching:

-- Directed relationship
SELECT * FROM cypher('social', $$
    MATCH (a:Person)-[r:KNOWS]->(b:Person)
    RETURN a.name AS source, b.name AS target
$$) AS (source text, target text);

-- Variable-length relationships
SELECT * FROM cypher('social', $$
    MATCH (a:Person {name: 'Alice'})-[:KNOWS*1..3]->(b:Person)
    RETURN b.name AS name
$$) AS (name text);

-- Path variables with nodes() and relationships()
SELECT * FROM cypher('social', $$
    MATCH p = (a:Person {name: 'Alice'})-[:KNOWS*1..3]->(b:Person)
    RETURN nodes(p) AS path_nodes, relationships(p) AS path_edges,
           length(p) AS hops
$$) AS (path_nodes jsonb, path_edges jsonb, hops bigint);

Graph Mutation:

-- Create nodes
SELECT * FROM cypher('social', $$
    CREATE (p:Person {name: 'Carol', age: 28})
    RETURN p.name AS name
$$) AS (name text);

-- Create relationships
SELECT * FROM cypher('social', $$
    MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Carol'})
    CREATE (a)-[:KNOWS {since: 2025}]->(b)
    RETURN a.name AS source, b.name AS target
$$) AS (source text, target text);

-- Update properties
SELECT * FROM cypher('social', $$
    MATCH (p:Person {name: 'Alice'})
    SET p.age = 31
    RETURN p.name AS name, p.age AS age
$$) AS (name text, age bigint);

-- Merge (match or create)
SELECT * FROM cypher('social', $$
    MERGE (p:Person {name: 'Dave'})
    ON CREATE SET p.age = 35
    ON MATCH SET p.last_seen = timestamp()
    RETURN p.name AS name
$$) AS (name text);

Cypher Functions:

FunctionDescription
id(node_or_edge)Get the internal ID
labels(node)Get node labels
type(relationship)Get relationship type
properties(node_or_edge)Get all properties as JSON
start_id(relationship)Get source node ID
end_id(relationship)Get target node ID
startNode(relationship)Get source node
endNode(relationship)Get target node
nodes(path)Get nodes from a path
relationships(path)Get relationships from a path
length(path)Get path length (hop count)
size(list)List element count
head(list)First element of a list
last(list)Last element of a list
tail(list)All elements except the first
range(start, end, step?)Generate integer list
keys(map)Get map keys
vertex_stats(node)Node statistics (degree counts)
toBoolean(expr)Convert to boolean
toFloat(expr)Convert to float
toInteger(expr)Convert to integer
toString(expr)Convert to string
timestamp()Current time in milliseconds

Integration with SQL:

Cypher queries integrate naturally with SQL through the FROM clause, enabling hybrid queries that combine graph pattern matching with relational operations:

-- Join Cypher results with relational tables
SELECT c.*, o.total
FROM cypher('social', $$
    MATCH (p:Person)-[:LIVES_IN]->(c:City)
    RETURN p.name AS person_name, c.name AS city
$$) AS c(person_name text, city text)
JOIN orders o ON o.customer_name = c.person_name;

-- Use CTE with Cypher
WITH friends AS (
    SELECT * FROM cypher('social', $$
        MATCH (a:Person {name: 'Alice'})-[:KNOWS]->(f:Person)
        RETURN f.name AS name
    $$) AS (name text)
)
SELECT * FROM friends ORDER BY name;

B.17 SQL Conformance

B.17.1 SQL Standard Features

Cognica supports the following SQL standard features:

FeatureSQL Standard
Basic SELECTSQL-92
SubqueriesSQL-92
JOIN operationsSQL-92, SQL:1999
Set operationsSQL-92
GROUP BY, HAVINGSQL-92
ORDER BY with NULLSSQL:2003
CTEs (WITH clause)SQL:1999
Recursive CTEsSQL:1999
Window functionsSQL:2003
FILTER clauseSQL:2003
GROUPING SETSSQL:1999
CUBE, ROLLUPSQL:1999
LATERAL joinsSQL:1999
Ordered-set aggregatesSQL:2003

B.17.2 PostgreSQL Extensions

FeaturePostgreSQL Version
DISTINCT ONPostgreSQL
ILIKE operatorPostgreSQL
JSONB typePostgreSQL 9.4+
JSONPathPostgreSQL 12+
MATERIALIZED hintsPostgreSQL 12+
Row-level securityPostgreSQL 9.5+

Summary

Cognica provides comprehensive SQL support compatible with PostgreSQL, enabling seamless migration of applications and queries. The implementation covers:

  • Full DQL support: SELECT with all clauses, joins, subqueries, CTEs, parameterized LIMIT/OFFSET
  • Complete DML: INSERT (with ON CONFLICT upsert), UPDATE, DELETE with RETURNING
  • Extensive DDL: Tables, views, indexes (including partial), triggers, functions, schemas
  • Transaction control: ACID compliance with isolation levels
  • Rich function library: 200+ scalar, aggregate, and window functions
  • PostgreSQL compatibility: System catalogs, operators, extensions
  • Graph queries: Property graph operations via SQL table functions and openCypher language

Understanding these compatibility features enables developers to leverage existing PostgreSQL knowledge while taking advantage of Cognica's unique capabilities in document storage, full-text search, vector similarity operations, and graph query processing.

Copyright (c) 2023-2026 Cognica, Inc.