3802 lines
100 KiB
PL/PgSQL
3802 lines
100 KiB
PL/PgSQL
SET check_function_bodies = false;
|
||
-- Hide warnings because casts on domains would show a lot of:
|
||
-- WARNING: cast will be ignored because the source data type is a domain
|
||
SET client_min_messages = error;
|
||
|
||
CREATE SCHEMA public;
|
||
CREATE SCHEMA postgrest;
|
||
CREATE SCHEMA private;
|
||
CREATE SCHEMA test;
|
||
CREATE SCHEMA تست;
|
||
CREATE SCHEMA extensions;
|
||
CREATE SCHEMA v1;
|
||
CREATE SCHEMA v2;
|
||
CREATE SCHEMA "SPECIAL ""@/\#~_-";
|
||
CREATE SCHEMA "EXTRA ""@/\#~_-";
|
||
|
||
COMMENT ON SCHEMA v1 IS 'v1 schema';
|
||
COMMENT ON SCHEMA v2 IS 'v2 schema';
|
||
|
||
COMMENT ON SCHEMA test IS
|
||
$$My API title
|
||
|
||
My API description
|
||
that spans
|
||
multiple lines$$;
|
||
--
|
||
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
|
||
--
|
||
|
||
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
|
||
|
||
SET search_path = public, pg_catalog;
|
||
|
||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||
|
||
--
|
||
-- Name: jwt_token; Type: TYPE; Schema: public; Owner: -
|
||
--
|
||
|
||
CREATE TYPE public.jwt_token AS (
|
||
token text
|
||
);
|
||
|
||
|
||
SET search_path = test, pg_catalog;
|
||
|
||
--
|
||
-- Name: enum_menagerie_type; Type: TYPE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TYPE enum_menagerie_type AS ENUM (
|
||
'foo',
|
||
'bar'
|
||
);
|
||
|
||
create type bit as enum ('one', 'two');
|
||
|
||
SET search_path = postgrest, pg_catalog;
|
||
|
||
--
|
||
-- Name: check_role_exists(); Type: FUNCTION; Schema: postgrest; Owner: -
|
||
--
|
||
|
||
CREATE FUNCTION check_role_exists() RETURNS trigger
|
||
LANGUAGE plpgsql
|
||
AS $$
|
||
begin
|
||
if not exists (select 1 from pg_roles as r where r.rolname = new.rolname) then
|
||
raise foreign_key_violation using message = 'Cannot create user with unknown role: ' || new.rolname;
|
||
return null;
|
||
end if;
|
||
return new;
|
||
end
|
||
$$;
|
||
|
||
|
||
--
|
||
-- Name: set_authors_only_owner(); Type: FUNCTION; Schema: postgrest; Owner: -
|
||
--
|
||
|
||
CREATE FUNCTION set_authors_only_owner() RETURNS trigger
|
||
LANGUAGE plpgsql
|
||
AS $$
|
||
begin
|
||
NEW.owner = current_setting('request.jwt.claims')::json->>'id';
|
||
RETURN NEW;
|
||
end
|
||
$$;
|
||
|
||
|
||
--
|
||
-- Name: update_owner(); Type: FUNCTION; Schema: postgrest; Owner: -
|
||
--
|
||
|
||
CREATE FUNCTION update_owner() RETURNS trigger
|
||
LANGUAGE plpgsql
|
||
AS $$
|
||
BEGIN
|
||
NEW.owner = current_user;
|
||
RETURN NEW;
|
||
END;
|
||
$$;
|
||
|
||
|
||
SET search_path = test, pg_catalog;
|
||
|
||
SET default_tablespace = '';
|
||
|
||
SET default_with_oids = false;
|
||
|
||
create domain "text/plain" as text;
|
||
create domain "text/html" as text;
|
||
create domain "text/xml" as pg_catalog.xml;
|
||
create domain "application/octet-stream" as bytea;
|
||
create domain "image/png" as bytea;
|
||
create domain "application/vnd.twkb" as bytea;
|
||
create domain "application/openapi+json" as json;
|
||
create domain "application/geo+json" as jsonb;
|
||
create domain "application/vnd.geo2+json" as jsonb;
|
||
create domain "application/json" as json;
|
||
create domain "application/vnd.pgrst.object" as json;
|
||
create domain "text/tab-separated-values" as text;
|
||
create domain "text/csv" as text;
|
||
create domain "*/*" as bytea;
|
||
|
||
CREATE TABLE items (
|
||
id bigserial primary key
|
||
);
|
||
|
||
CREATE TABLE items2 (
|
||
id bigserial primary key
|
||
);
|
||
|
||
CREATE TABLE items3 (
|
||
id bigserial primary key
|
||
);
|
||
|
||
CREATE FUNCTION search(id BIGINT) RETURNS SETOF items
|
||
LANGUAGE plpgsql
|
||
STABLE
|
||
AS $$BEGIN
|
||
RETURN QUERY SELECT items.id FROM items WHERE items.id=search.id;
|
||
END$$;
|
||
|
||
CREATE FUNCTION always_true(test.items) RETURNS boolean
|
||
LANGUAGE sql IMMUTABLE
|
||
AS $$ SELECT true $$;
|
||
|
||
CREATE FUNCTION computed_overload(test.items) RETURNS boolean
|
||
LANGUAGE sql IMMUTABLE
|
||
AS $$ SELECT true $$;
|
||
|
||
CREATE FUNCTION computed_overload(test.items2) RETURNS boolean
|
||
LANGUAGE sql IMMUTABLE
|
||
AS $$ SELECT true $$;
|
||
|
||
CREATE FUNCTION is_first(test.items) RETURNS boolean
|
||
LANGUAGE sql IMMUTABLE
|
||
AS $$ SELECT $1.id = 1 $$;
|
||
|
||
|
||
CREATE FUNCTION anti_id(test.items) RETURNS bigint
|
||
LANGUAGE sql IMMUTABLE
|
||
AS $_$ SELECT $1.id * -1 $_$;
|
||
|
||
SET search_path = public, pg_catalog;
|
||
|
||
CREATE FUNCTION always_false(test.items) RETURNS boolean
|
||
LANGUAGE sql IMMUTABLE
|
||
AS $$ SELECT false $$;
|
||
|
||
create table public_consumers (
|
||
id serial not null unique,
|
||
name text not null check (name <> ''),
|
||
primary key (id)
|
||
);
|
||
|
||
create table public_orders (
|
||
id serial not null unique,
|
||
consumer integer not null references public_consumers(id),
|
||
number integer not null,
|
||
primary key (id)
|
||
);
|
||
|
||
SET search_path = تست, pg_catalog;
|
||
|
||
CREATE TABLE موارد (
|
||
هویت bigint NOT NULL
|
||
);
|
||
|
||
|
||
SET search_path = test, pg_catalog;
|
||
|
||
|
||
create view orders_view as
|
||
select * from public.public_orders;
|
||
|
||
create view consumers_view as
|
||
select * from public.public_consumers;
|
||
|
||
create view consumers_view_view as
|
||
select * from consumers_view;
|
||
|
||
create view public.consumers_extra as
|
||
select * from consumers_view;
|
||
|
||
create view consumers_extra_view as
|
||
select * from public.consumers_extra;
|
||
|
||
--
|
||
-- Name: getitemrange(bigint, bigint); Type: FUNCTION; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE FUNCTION getitemrange(min bigint, max bigint) RETURNS SETOF items
|
||
LANGUAGE sql
|
||
STABLE
|
||
AS $_$
|
||
SELECT * FROM test.items WHERE id > $1 AND id <= $2;
|
||
$_$;
|
||
|
||
--
|
||
-- Name: version(); Type: FUNCTION; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE FUNCTION noparamsproc() RETURNS text
|
||
LANGUAGE sql
|
||
IMMUTABLE
|
||
AS $$
|
||
SELECT a FROM (VALUES ('Return value of no parameters procedure.')) s(a);
|
||
$$;
|
||
|
||
--
|
||
-- Name: login(text, text); Type: FUNCTION; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE FUNCTION login(id text, pass text) RETURNS public.jwt_token
|
||
LANGUAGE sql SECURITY DEFINER
|
||
STABLE
|
||
AS $$
|
||
SELECT jwt.sign(
|
||
row_to_json(r), 'reallyreallyreallyreallyverysafe'
|
||
) as token
|
||
FROM (
|
||
SELECT rolname::text, id::text
|
||
FROM postgrest.auth
|
||
WHERE id = id AND pass = pass
|
||
) r;
|
||
$$;
|
||
|
||
|
||
CREATE FUNCTION varied_arguments(
|
||
double double precision,
|
||
"varchar" character varying,
|
||
"boolean" boolean,
|
||
date date,
|
||
money money,
|
||
enum enum_menagerie_type,
|
||
arr text[],
|
||
"integer" integer default 42,
|
||
json json default '{}',
|
||
jsonb jsonb default '{}'
|
||
) RETURNS json
|
||
LANGUAGE sql
|
||
IMMUTABLE
|
||
AS $_$
|
||
SELECT json_build_object(
|
||
'double', double,
|
||
'varchar', "varchar",
|
||
'boolean', "boolean",
|
||
'date', date,
|
||
'money', money,
|
||
'enum', enum,
|
||
'arr', arr,
|
||
'integer', "integer",
|
||
'json', json,
|
||
'jsonb', jsonb
|
||
);
|
||
$_$;
|
||
|
||
COMMENT ON FUNCTION varied_arguments(double precision, character varying, boolean, date, money, enum_menagerie_type, text[], integer, json, jsonb) IS
|
||
$_$An RPC function
|
||
|
||
Just a test for RPC function arguments$_$;
|
||
|
||
CREATE FUNCTION varied_arguments_openapi(
|
||
double double precision,
|
||
"varchar" character varying,
|
||
"boolean" boolean,
|
||
date date,
|
||
money money,
|
||
enum enum_menagerie_type,
|
||
text_arr text[],
|
||
int_arr int[],
|
||
bool_arr boolean[],
|
||
char_arr char[],
|
||
varchar_arr varchar[],
|
||
bigint_arr bigint[],
|
||
numeric_arr numeric[],
|
||
json_arr json[],
|
||
jsonb_arr jsonb[],
|
||
"integer" integer default 42,
|
||
json json default '{}',
|
||
jsonb jsonb default '{}'
|
||
) RETURNS json
|
||
LANGUAGE sql
|
||
IMMUTABLE
|
||
AS $_$
|
||
SELECT json_build_object(
|
||
'double', double,
|
||
'varchar', "varchar",
|
||
'boolean', "boolean",
|
||
'date', date,
|
||
'money', money,
|
||
'enum', enum,
|
||
'text_arr', text_arr,
|
||
'int_arr', int_arr,
|
||
'bool_arr', bool_arr,
|
||
'char_arr', char_arr,
|
||
'varchar_arr', varchar_arr,
|
||
'bigint_arr', bigint_arr,
|
||
'numeric_arr', numeric_arr,
|
||
'json_arr', json_arr,
|
||
'jsonb_arr', jsonb_arr,
|
||
'integer', "integer",
|
||
'json', json,
|
||
'jsonb', jsonb
|
||
);
|
||
$_$;
|
||
|
||
COMMENT ON FUNCTION varied_arguments_openapi(double precision, character varying, boolean, date, money, enum_menagerie_type, text[], int[], boolean[], char[], varchar[], bigint[], numeric[], json[], jsonb[], integer, json, jsonb) IS
|
||
$_$An RPC function
|
||
|
||
Just a test for RPC function arguments$_$;
|
||
|
||
|
||
CREATE FUNCTION json_argument(arg json) RETURNS text
|
||
LANGUAGE sql
|
||
IMMUTABLE
|
||
AS $_$
|
||
SELECT json_typeof(arg);
|
||
$_$;
|
||
|
||
--
|
||
-- Name: jwt_test(); Type: FUNCTION; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE FUNCTION jwt_test() RETURNS public.jwt_token
|
||
LANGUAGE sql SECURITY DEFINER
|
||
IMMUTABLE
|
||
AS $$
|
||
SELECT jwt.sign(
|
||
row_to_json(r), 'reallyreallyreallyreallyverysafe'
|
||
) as token
|
||
FROM (
|
||
SELECT 'joe'::text as iss, 'fun'::text as sub, 'everyone'::text as aud,
|
||
1300819380 as exp, 1300819380 as nbf, 1300819380 as iat,
|
||
'foo'::text as jti, 'postgrest_test'::text as role,
|
||
true as "http://postgrest.com/foo"
|
||
) r;
|
||
$$;
|
||
|
||
|
||
CREATE OR REPLACE FUNCTION switch_role() RETURNS void
|
||
LANGUAGE plpgsql
|
||
AS $$
|
||
declare
|
||
user_id text;
|
||
Begin
|
||
user_id = (current_setting('request.jwt.claims')::json->>'id')::text;
|
||
if user_id = '1'::text then
|
||
execute 'set local role postgrest_test_author';
|
||
elseif user_id = '2'::text then
|
||
execute 'set local role postgrest_test_default_role';
|
||
elseif user_id = '3'::text then
|
||
RAISE EXCEPTION 'Disabled ID --> %', user_id USING HINT = 'Please contact administrator';
|
||
/* else */
|
||
/* execute 'set local role postgrest_test_anonymous'; */
|
||
end if;
|
||
end
|
||
$$;
|
||
|
||
CREATE FUNCTION get_current_user() RETURNS text
|
||
LANGUAGE sql
|
||
STABLE
|
||
AS $$
|
||
SELECT current_user::text;
|
||
$$;
|
||
|
||
--
|
||
-- Name: reveal_big_jwt(); Type: FUNCTION; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE FUNCTION reveal_big_jwt() RETURNS TABLE (
|
||
iss text, sub text, exp bigint,
|
||
nbf bigint, iat bigint, jti text, "http://postgrest.com/foo" boolean
|
||
)
|
||
AS $$
|
||
SELECT current_setting('request.jwt.claims')::json->>'iss' as iss,
|
||
current_setting('request.jwt.claims')::json->>'sub' as sub,
|
||
(current_setting('request.jwt.claims')::json->>'exp')::bigint as exp,
|
||
(current_setting('request.jwt.claims')::json->>'nbf')::bigint as nbf,
|
||
(current_setting('request.jwt.claims')::json->>'iat')::bigint as iat,
|
||
current_setting('request.jwt.claims')::json->>'jti' as jti,
|
||
(current_setting('request.jwt.claims')::json->>'http://postgrest.com/foo')::boolean as "http://postgrest.com/foo";
|
||
$$ LANGUAGE sql SECURITY DEFINER STABLE;
|
||
|
||
|
||
CREATE FUNCTION assert() RETURNS void
|
||
LANGUAGE plpgsql
|
||
AS $$
|
||
BEGIN
|
||
ASSERT false, 'bad thing';
|
||
END;
|
||
$$;
|
||
|
||
|
||
--
|
||
-- Name: problem(); Type: FUNCTION; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE FUNCTION problem() RETURNS void
|
||
LANGUAGE plpgsql
|
||
AS $$
|
||
BEGIN
|
||
RAISE 'bad thing';
|
||
END;
|
||
$$;
|
||
|
||
|
||
--
|
||
-- Name: sayhello(text); Type: FUNCTION; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE FUNCTION sayhello(name text) RETURNS text
|
||
LANGUAGE sql
|
||
IMMUTABLE
|
||
AS $_$
|
||
SELECT 'Hello, ' || $1;
|
||
$_$;
|
||
|
||
|
||
--
|
||
-- Name: callcounter(); Type: FUNCTION; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE SEQUENCE callcounter_count START 1;
|
||
|
||
CREATE FUNCTION callcounter() RETURNS bigint
|
||
LANGUAGE sql
|
||
AS $_$
|
||
SELECT nextval('test.callcounter_count');
|
||
$_$;
|
||
|
||
CREATE FUNCTION reset_sequence(name TEXT, value INTEGER) RETURNS void
|
||
SECURITY DEFINER
|
||
LANGUAGE plpgsql AS $_$
|
||
BEGIN
|
||
EXECUTE FORMAT($exec$
|
||
ALTER SEQUENCE %s RESTART WITH %s
|
||
$exec$, name, value);
|
||
END
|
||
$_$;
|
||
|
||
--
|
||
-- Name: singlejsonparam(json); Type: FUNCTION; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE FUNCTION singlejsonparam(single_param json) RETURNS json
|
||
LANGUAGE sql
|
||
IMMUTABLE
|
||
AS $_$
|
||
SELECT single_param;
|
||
$_$;
|
||
|
||
--
|
||
-- Name: test_empty_rowset(); Type: FUNCTION; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE FUNCTION test_empty_rowset() RETURNS SETOF integer
|
||
LANGUAGE sql
|
||
IMMUTABLE
|
||
AS $$
|
||
SELECT null::int FROM (SELECT 1) a WHERE false;
|
||
$$;
|
||
|
||
|
||
SET search_path = postgrest, pg_catalog;
|
||
|
||
--
|
||
-- Name: auth; Type: TABLE; Schema: postgrest; Owner: -
|
||
--
|
||
|
||
CREATE TABLE auth (
|
||
id character varying NOT NULL,
|
||
rolname name DEFAULT 'postgrest_test_author'::name NOT NULL,
|
||
pass character(60) NOT NULL
|
||
);
|
||
|
||
SET search_path = test, pg_catalog;
|
||
|
||
--
|
||
-- Name: authors_only; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE authors_only (
|
||
owner character varying NOT NULL,
|
||
secret character varying NOT NULL
|
||
);
|
||
|
||
|
||
--
|
||
-- Name: auto_incrementing_pk; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE auto_incrementing_pk (
|
||
id integer NOT NULL,
|
||
nullable_string character varying,
|
||
non_nullable_string character varying NOT NULL,
|
||
inserted_at timestamp with time zone DEFAULT now()
|
||
);
|
||
|
||
|
||
--
|
||
-- Name: auto_incrementing_pk_id_seq; Type: SEQUENCE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE SEQUENCE auto_incrementing_pk_id_seq
|
||
START WITH 1
|
||
INCREMENT BY 1
|
||
NO MINVALUE
|
||
NO MAXVALUE
|
||
CACHE 1;
|
||
|
||
|
||
--
|
||
-- Name: auto_incrementing_pk_id_seq; Type: SEQUENCE OWNED BY; Schema: test; Owner: -
|
||
--
|
||
|
||
ALTER SEQUENCE auto_incrementing_pk_id_seq OWNED BY auto_incrementing_pk.id;
|
||
|
||
|
||
--
|
||
-- Name: clients; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE clients (
|
||
id integer primary key,
|
||
name text NOT NULL
|
||
);
|
||
|
||
--
|
||
-- Name: complex_items; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE complex_items (
|
||
id bigint NOT NULL,
|
||
name text,
|
||
settings json,
|
||
arr_data integer[],
|
||
"field-with_sep" integer default 1 not null
|
||
);
|
||
|
||
|
||
--
|
||
-- Name: compound_pk; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE compound_pk (
|
||
-- those columns should not be referenced to in a foreign key anywhere
|
||
-- to allow the InsertSpec.Inserting into VIEWs.returns a location header
|
||
-- to test properly
|
||
PRIMARY KEY (k1, k2),
|
||
k1 integer NOT NULL,
|
||
k2 text NOT NULL,
|
||
extra integer
|
||
);
|
||
|
||
|
||
CREATE VIEW compound_pk_view AS
|
||
SELECT * FROM compound_pk;
|
||
|
||
--
|
||
-- Name: empty_table; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE empty_table (
|
||
k character varying NOT NULL,
|
||
extra character varying NOT NULL
|
||
);
|
||
|
||
|
||
--
|
||
-- Name: private_table; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE private_table ();
|
||
|
||
|
||
--
|
||
-- Name: has_count_column; Type: VIEW; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE VIEW has_count_column AS
|
||
SELECT 1 AS count;
|
||
|
||
|
||
--
|
||
-- Name: has_fk; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE has_fk (
|
||
id bigint NOT NULL,
|
||
auto_inc_fk integer,
|
||
simple_fk character varying(255)
|
||
);
|
||
|
||
|
||
--
|
||
-- Name: has_fk_id_seq; Type: SEQUENCE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE SEQUENCE has_fk_id_seq
|
||
START WITH 1
|
||
INCREMENT BY 1
|
||
NO MINVALUE
|
||
NO MAXVALUE
|
||
CACHE 1;
|
||
|
||
|
||
--
|
||
-- Name: has_fk_id_seq; Type: SEQUENCE OWNED BY; Schema: test; Owner: -
|
||
--
|
||
|
||
ALTER SEQUENCE has_fk_id_seq OWNED BY has_fk.id;
|
||
|
||
|
||
--
|
||
-- Name: insertable_view_with_join; Type: VIEW; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE VIEW insertable_view_with_join AS
|
||
SELECT has_fk.id,
|
||
has_fk.auto_inc_fk,
|
||
has_fk.simple_fk,
|
||
auto_incrementing_pk.nullable_string,
|
||
auto_incrementing_pk.non_nullable_string,
|
||
auto_incrementing_pk.inserted_at
|
||
FROM (has_fk
|
||
JOIN auto_incrementing_pk USING (id));
|
||
|
||
--
|
||
-- Name: json_table; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE json_table (
|
||
data json
|
||
);
|
||
|
||
|
||
--
|
||
-- Name: materialized_view; Type: MATERIALIZED VIEW; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE MATERIALIZED VIEW materialized_view AS
|
||
SELECT version() AS version
|
||
WITH NO DATA;
|
||
|
||
|
||
--
|
||
-- Name: menagerie; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE menagerie (
|
||
"integer" integer NOT NULL,
|
||
double double precision NOT NULL,
|
||
"varchar" character varying NOT NULL,
|
||
"boolean" boolean NOT NULL,
|
||
date date NOT NULL,
|
||
money money NOT NULL,
|
||
enum enum_menagerie_type NOT NULL
|
||
);
|
||
|
||
|
||
--
|
||
-- Name: no_pk; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE no_pk (
|
||
a character varying,
|
||
b character varying
|
||
);
|
||
|
||
CREATE TABLE only_pk (
|
||
id integer primary key
|
||
);
|
||
|
||
--
|
||
-- Name: nullable_integer; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE nullable_integer (
|
||
a integer
|
||
);
|
||
|
||
|
||
--
|
||
-- Name: insertonly; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE insertonly (
|
||
v text NOT NULL
|
||
);
|
||
|
||
|
||
--
|
||
-- Name: projects; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE projects (
|
||
id integer primary key,
|
||
name text NOT NULL,
|
||
client_id integer REFERENCES clients(id)
|
||
);
|
||
alter table projects rename constraint projects_client_id_fkey to client;
|
||
|
||
--
|
||
-- Name: projects_view; Type: VIEW; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE VIEW projects_view AS
|
||
SELECT projects.id,
|
||
projects.name,
|
||
projects.client_id
|
||
FROM projects;
|
||
|
||
|
||
CREATE VIEW projects_view_alt AS
|
||
SELECT projects.id as t_id,
|
||
projects.name,
|
||
projects.client_id as t_client_id
|
||
FROM projects;
|
||
|
||
CREATE TABLE sponsors (
|
||
id integer primary key,
|
||
name varchar(20) not null
|
||
);
|
||
|
||
CREATE TABLE competitors (
|
||
id integer primary key,
|
||
sponsor_id integer references sponsors(id),
|
||
full_name varchar(40) not null
|
||
);
|
||
|
||
CREATE VIEW test_null_pk_competitors_sponsors AS
|
||
SELECT c.id, s.id as sponsor_id
|
||
FROM competitors c
|
||
LEFT JOIN sponsors s on c.sponsor_id = s.id;
|
||
|
||
CREATE RULE test_null_pk_competitors_sponsors AS
|
||
ON INSERT TO test_null_pk_competitors_sponsors DO INSTEAD
|
||
INSERT INTO competitors(id, full_name, sponsor_id)
|
||
VALUES (new.id, 'Competitor without sponsor', new.sponsor_id)
|
||
RETURNING id, sponsor_id;
|
||
|
||
--
|
||
-- Name: simple_pk; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE simple_pk (
|
||
PRIMARY KEY (k),
|
||
k character varying NOT NULL,
|
||
extra character varying NOT NULL
|
||
);
|
||
|
||
CREATE TABLE simple_pk2 (
|
||
PRIMARY KEY (k),
|
||
k character varying NOT NULL,
|
||
extra character varying NOT NULL
|
||
);
|
||
|
||
CREATE TABLE users (
|
||
id integer primary key,
|
||
name text NOT NULL
|
||
);
|
||
|
||
CREATE TABLE users_projects (
|
||
user_id integer NOT NULL REFERENCES users(id),
|
||
project_id integer NOT NULL REFERENCES projects(id),
|
||
PRIMARY KEY (project_id, user_id)
|
||
);
|
||
|
||
CREATE TABLE tasks (
|
||
id integer primary key,
|
||
name text NOT NULL,
|
||
project_id integer REFERENCES projects(id)
|
||
);
|
||
alter table tasks rename constraint tasks_project_id_fkey to project;
|
||
|
||
CREATE OR REPLACE VIEW filtered_tasks AS
|
||
SELECT id AS "myId", name, project_id AS "projectID"
|
||
FROM tasks
|
||
WHERE project_id IN (
|
||
SELECT id FROM projects WHERE id = 1
|
||
) AND
|
||
project_id IN (
|
||
SELECT project_id FROM users_projects WHERE user_id = 1
|
||
);
|
||
|
||
CREATE TABLE users_tasks (
|
||
user_id integer NOT NULL REFERENCES users(id),
|
||
task_id integer NOT NULL REFERENCES tasks(id),
|
||
primary key (task_id, user_id)
|
||
);
|
||
|
||
CREATE TABLE comments (
|
||
id integer primary key,
|
||
commenter_id integer NOT NULL,
|
||
user_id integer NOT NULL,
|
||
task_id integer NOT NULL,
|
||
content text NOT NULL
|
||
);
|
||
alter table only comments
|
||
add constraint "user" foreign key (commenter_id) references users(id),
|
||
add constraint comments_task_id_fkey foreign key (task_id, user_id) references users_tasks(task_id, user_id);
|
||
|
||
CREATE TABLE files (
|
||
project_id integer NOT NULL,
|
||
filename text NOT NULL,
|
||
content text NOT NULL,
|
||
PRIMARY KEY (project_id, filename)
|
||
);
|
||
|
||
CREATE TABLE touched_files (
|
||
user_id integer NOT NULL,
|
||
task_id integer NOT NULL,
|
||
project_id integer NOT NULL,
|
||
filename text NOT NULL,
|
||
constraint fk_users_tasks foreign key (user_id, task_id) references users_tasks (user_id, task_id) on delete cascade on update cascade,
|
||
constraint fk_upload foreign key (project_id, filename) references files (project_id,filename) on delete cascade on update cascade,
|
||
primary key(user_id, task_id, project_id, filename)
|
||
);
|
||
|
||
create table private.articles (
|
||
id integer primary key,
|
||
body text,
|
||
owner name not null
|
||
);
|
||
|
||
create table private.article_stars (
|
||
article_id integer not null,
|
||
user_id integer not null,
|
||
created_at timestamp without time zone default now() not null,
|
||
primary key (article_id, user_id)
|
||
);
|
||
alter table only private.article_stars
|
||
add constraint article foreign key (article_id) references private.articles(id),
|
||
add constraint "user" foreign key (user_id) references test.users(id);
|
||
|
||
CREATE VIEW limited_article_stars AS
|
||
SELECT article_id, user_id, created_at FROM private.article_stars;
|
||
|
||
CREATE VIEW "articleStars" AS
|
||
SELECT article_stars.article_id AS "articleId",
|
||
article_stars.user_id AS "userId",
|
||
article_stars.created_at AS "createdAt"
|
||
FROM private.article_stars;
|
||
|
||
CREATE VIEW articles AS
|
||
SELECT articles.id,
|
||
articles.body,
|
||
articles.owner
|
||
FROM private.articles;
|
||
|
||
--
|
||
-- Name: tsearch; Type: TABLE; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TABLE tsearch (
|
||
text_search_vector tsvector
|
||
);
|
||
|
||
CREATE TABLE "Escap3e;" (
|
||
"so6meIdColumn" integer primary key
|
||
);
|
||
|
||
CREATE TABLE "ghostBusters" (
|
||
"escapeId" integer not null references "Escap3e;"("so6meIdColumn")
|
||
);
|
||
|
||
CREATE TABLE "withUnique" (
|
||
uni text UNIQUE,
|
||
extra text
|
||
);
|
||
|
||
CREATE TABLE clashing_column (
|
||
t text
|
||
);
|
||
|
||
--
|
||
-- Name: id; Type: DEFAULT; Schema: test; Owner: -
|
||
--
|
||
|
||
ALTER TABLE ONLY auto_incrementing_pk ALTER COLUMN id SET DEFAULT nextval('auto_incrementing_pk_id_seq'::regclass);
|
||
|
||
|
||
--
|
||
-- Name: id; Type: DEFAULT; Schema: test; Owner: -
|
||
--
|
||
|
||
ALTER TABLE ONLY has_fk ALTER COLUMN id SET DEFAULT nextval('has_fk_id_seq'::regclass);
|
||
|
||
|
||
SET search_path = postgrest, pg_catalog;
|
||
|
||
--
|
||
-- Name: auth_pkey; Type: CONSTRAINT; Schema: postgrest; Owner: -
|
||
--
|
||
|
||
ALTER TABLE ONLY auth
|
||
ADD CONSTRAINT auth_pkey PRIMARY KEY (id);
|
||
|
||
|
||
SET search_path = test, pg_catalog;
|
||
|
||
--
|
||
-- Name: authors_only_pkey; Type: CONSTRAINT; Schema: test; Owner: -
|
||
--
|
||
|
||
ALTER TABLE ONLY authors_only
|
||
ADD CONSTRAINT authors_only_pkey PRIMARY KEY (secret);
|
||
|
||
|
||
--
|
||
-- Name: auto_incrementing_pk_pkey; Type: CONSTRAINT; Schema: test; Owner: -
|
||
--
|
||
|
||
ALTER TABLE ONLY auto_incrementing_pk
|
||
ADD CONSTRAINT auto_incrementing_pk_pkey PRIMARY KEY (id);
|
||
|
||
--
|
||
-- Name: complex_items_pkey; Type: CONSTRAINT; Schema: test; Owner: -
|
||
--
|
||
|
||
ALTER TABLE ONLY complex_items
|
||
ADD CONSTRAINT complex_items_pkey PRIMARY KEY (id);
|
||
|
||
--
|
||
-- Name: has_fk_pkey; Type: CONSTRAINT; Schema: test; Owner: -
|
||
--
|
||
|
||
ALTER TABLE ONLY has_fk
|
||
ADD CONSTRAINT has_fk_pkey PRIMARY KEY (id);
|
||
|
||
--
|
||
-- Name: menagerie_pkey; Type: CONSTRAINT; Schema: test; Owner: -
|
||
--
|
||
|
||
ALTER TABLE ONLY menagerie
|
||
ADD CONSTRAINT menagerie_pkey PRIMARY KEY ("integer");
|
||
|
||
|
||
SET search_path = postgrest, pg_catalog;
|
||
|
||
--
|
||
-- Name: ensure_auth_role_exists; Type: TRIGGER; Schema: postgrest; Owner: -
|
||
--
|
||
|
||
CREATE CONSTRAINT TRIGGER ensure_auth_role_exists AFTER INSERT OR UPDATE ON auth NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE check_role_exists();
|
||
|
||
|
||
SET search_path = private, pg_catalog;
|
||
|
||
--
|
||
-- Name: articles_owner_track; Type: TRIGGER; Schema: private; Owner: -
|
||
--
|
||
|
||
CREATE TRIGGER articles_owner_track BEFORE INSERT OR UPDATE ON articles FOR EACH ROW EXECUTE PROCEDURE postgrest.update_owner();
|
||
|
||
|
||
SET search_path = test, pg_catalog;
|
||
|
||
--
|
||
-- Name: secrets_owner_track; Type: TRIGGER; Schema: test; Owner: -
|
||
--
|
||
|
||
CREATE TRIGGER secrets_owner_track BEFORE INSERT OR UPDATE ON authors_only FOR EACH ROW EXECUTE PROCEDURE postgrest.set_authors_only_owner();
|
||
|
||
SET search_path = test, pg_catalog;
|
||
|
||
--
|
||
-- Name: has_fk_fk_fkey; Type: FK CONSTRAINT; Schema: test; Owner: -
|
||
--
|
||
|
||
ALTER TABLE ONLY has_fk
|
||
ADD CONSTRAINT has_fk_fk_fkey FOREIGN KEY (auto_inc_fk) REFERENCES auto_incrementing_pk(id);
|
||
|
||
|
||
--
|
||
-- Name: has_fk_simple_fk_fkey; Type: FK CONSTRAINT; Schema: test; Owner: -
|
||
--
|
||
|
||
ALTER TABLE ONLY has_fk
|
||
ADD CONSTRAINT has_fk_simple_fk_fkey FOREIGN KEY (simple_fk) REFERENCES simple_pk(k);
|
||
|
||
create table addresses (
|
||
id int not null unique,
|
||
address text not null
|
||
);
|
||
|
||
create table orders (
|
||
id int not null unique,
|
||
name text not null,
|
||
billing_address_id int references addresses(id),
|
||
shipping_address_id int references addresses(id)
|
||
);
|
||
alter table orders rename constraint orders_billing_address_id_fkey to billing;
|
||
alter table orders rename constraint orders_shipping_address_id_fkey to shipping;
|
||
|
||
CREATE FUNCTION getproject(id int) RETURNS SETOF projects
|
||
LANGUAGE sql
|
||
AS $_$
|
||
SELECT * FROM test.projects WHERE id = $1;
|
||
$_$;
|
||
|
||
CREATE FUNCTION get_projects_below(id int) RETURNS SETOF projects
|
||
LANGUAGE sql
|
||
AS $_$
|
||
SELECT * FROM test.projects WHERE id < $1;
|
||
$_$;
|
||
|
||
CREATE FUNCTION get_projects_above(id int) RETURNS SETOF projects
|
||
LANGUAGE sql
|
||
AS $_$
|
||
SELECT * FROM test.projects WHERE id > $1;
|
||
$_$ ROWS 1;
|
||
|
||
CREATE FUNCTION getallprojects() RETURNS SETOF projects
|
||
LANGUAGE sql
|
||
AS $_$
|
||
SELECT * FROM test.projects;
|
||
$_$ ROWS 2019;
|
||
|
||
CREATE FUNCTION setprojects(id_l int, id_h int, name text) RETURNS SETOF projects
|
||
LANGUAGE sql
|
||
AS $_$
|
||
update test.projects set name = $3 WHERE id >= $1 AND id <= $2 returning *;
|
||
$_$;
|
||
|
||
-- domains on tables are only supported from pg 11 on
|
||
DO $do$BEGIN
|
||
IF (SELECT current_setting('server_version_num')::INT >= 110000) THEN
|
||
CREATE DOMAIN projects_domain AS projects;
|
||
|
||
CREATE FUNCTION getproject_domain(id int) RETURNS SETOF projects_domain
|
||
LANGUAGE sql
|
||
STABLE
|
||
AS $_$
|
||
SELECT projects::projects_domain FROM test.projects WHERE id = $1;
|
||
$_$;
|
||
END IF;
|
||
END$do$;
|
||
|
||
create table images (
|
||
name text not null,
|
||
img bytea not null
|
||
);
|
||
|
||
create view images_base64 as (
|
||
-- encoding in base64 puts a '\n' after every 76 character due to legacy reasons, this is isn't necessary here so it's removed
|
||
select name, replace(encode(img, 'base64'), E'\n', '') as img from images
|
||
);
|
||
|
||
create function test.ret_enum(val text) returns test.enum_menagerie_type as $$
|
||
select val::test.enum_menagerie_type;
|
||
$$ language sql;
|
||
|
||
create domain one_nine as integer check (value >= 1 and value <= 9);
|
||
|
||
create function test.ret_array() returns integer[] as $$
|
||
select '{1,2,3}'::integer[];
|
||
$$ language sql;
|
||
|
||
create function test.ret_domain(val integer) returns test.one_nine as $$
|
||
select val::test.one_nine;
|
||
$$ language sql;
|
||
|
||
create function test.ret_range(low integer, up integer) returns int4range as $$
|
||
select int4range(low, up);
|
||
$$ language sql;
|
||
|
||
create function test.ret_setof_integers() returns setof integer as $$
|
||
values (1), (2), (3);
|
||
$$ language sql;
|
||
|
||
-- this function does not have named arguments and should be ignored
|
||
-- if it's not ignored, it will break the test for the function before
|
||
create function test.ret_setof_integers(int, int) returns integer AS $$
|
||
values (1);
|
||
$$ language sql;
|
||
|
||
create function test.ret_scalars() returns table(
|
||
a text, b test.enum_menagerie_type, c test.one_nine, d int4range
|
||
) as $$
|
||
select row('scalars'::text, enum_first(null::test.enum_menagerie_type),
|
||
1::test.one_nine, int4range(10, 20));
|
||
$$ language sql;
|
||
|
||
create type test.point_2d as (x integer, y integer);
|
||
|
||
create function test.ret_point_2d() returns test.point_2d as $$
|
||
select row(10, 5)::test.point_2d;
|
||
$$ language sql;
|
||
|
||
create function test.ret_point_overloaded(x int, y int) returns test.point_2d as $$
|
||
select row(x, y)::test.point_2d;
|
||
$$ language sql;
|
||
|
||
create function test.ret_point_overloaded(x json) returns json as $$
|
||
select $1;
|
||
$$ language sql;
|
||
|
||
-- domains on composite types are only supported from pg 11 on
|
||
do $do$begin
|
||
if (SELECT current_setting('server_version_num')::int >= 110000) then
|
||
create domain test.composite_domain as test.point_2d;
|
||
|
||
create function test.ret_composite_domain() returns test.composite_domain as $$
|
||
select row(10, 5)::test.composite_domain;
|
||
$$ language sql;
|
||
end if;
|
||
end$do$;
|
||
|
||
create type private.point_3d as (x integer, y integer, z integer);
|
||
|
||
create function test.ret_point_3d() returns private.point_3d as $$
|
||
select row(7, -3, 4)::private.point_3d;
|
||
$$ language sql;
|
||
|
||
create function test.ret_void() returns void as '' language sql;
|
||
|
||
create or replace function test.ret_null() returns int as $$
|
||
select null::int;
|
||
$$ language sql;
|
||
|
||
create function test.ret_image() returns "image/png" as $$
|
||
select i.img::"image/png" from test.images i where i.name = 'A.png';
|
||
$$ language sql;
|
||
|
||
create function test.single_article(id integer) returns test.articles as $$
|
||
select a.* from test.articles a where a.id = $1;
|
||
$$ language sql;
|
||
|
||
create function test.get_guc_value(name text) returns text as $$
|
||
select nullif(current_setting(name), '')::text;
|
||
$$ language sql;
|
||
|
||
-- Get the JSON type GUC values
|
||
create function test.get_guc_value(prefix text, name text) returns text as $$
|
||
select nullif(current_setting(prefix)::json->>name, '')::text;
|
||
$$ language sql;
|
||
|
||
create table w_or_wo_comma_names ( name text );
|
||
|
||
create table items_with_different_col_types (
|
||
int_data integer,
|
||
text_data text,
|
||
bool_data bool,
|
||
bin_data bytea,
|
||
char_data character varying,
|
||
date_data date,
|
||
real_data real,
|
||
time_data time
|
||
);
|
||
|
||
-- Tables used for testing complex boolean logic with and/or query params
|
||
|
||
create table entities (
|
||
id integer primary key,
|
||
name text,
|
||
arr integer[],
|
||
text_search_vector tsvector
|
||
);
|
||
|
||
create table child_entities (
|
||
id integer primary key,
|
||
name text,
|
||
parent_id integer references entities(id)
|
||
);
|
||
|
||
create view child_entities_view as table child_entities;
|
||
|
||
create table grandchild_entities (
|
||
id integer primary key,
|
||
name text,
|
||
parent_id integer references child_entities(id),
|
||
or_starting_col text,
|
||
and_starting_col text,
|
||
jsonb_col jsonb
|
||
);
|
||
|
||
-- Table used for testing range operators
|
||
|
||
create table ranges (
|
||
id integer primary key,
|
||
range numrange
|
||
);
|
||
|
||
|
||
-- OpenAPI description tests
|
||
|
||
comment on table child_entities is 'child_entities comment';
|
||
comment on column child_entities.id is 'child_entities id comment';
|
||
comment on column child_entities.name is 'child_entities name comment. Can be longer than sixty-three characters long';
|
||
|
||
comment on view child_entities_view is 'child_entities_view comment';
|
||
comment on column child_entities_view.id is 'child_entities_view id comment';
|
||
comment on column child_entities_view.name is 'child_entities_view name comment. Can be longer than sixty-three characters long';
|
||
|
||
comment on table grandchild_entities is
|
||
$$grandchild_entities summary
|
||
|
||
grandchild_entities description
|
||
that spans
|
||
multiple lines$$;
|
||
|
||
-- Used for testing that having the same return column name as the proc name
|
||
-- doesn't conflict with the required output, details in #901
|
||
create function test.test() returns table(test text, value int) as $$
|
||
values ('hello', 1);
|
||
$$ language sql;
|
||
|
||
create function test.privileged_hello(name text) returns text as $$
|
||
select 'Privileged hello to ' || $1;
|
||
$$ language sql;
|
||
|
||
create function test.get_tsearch() returns setof test.tsearch AS $$
|
||
SELECT * FROM test.tsearch;
|
||
$$ language sql;
|
||
|
||
create table test.being (
|
||
being int primary key not null
|
||
);
|
||
|
||
create table test.descendant (
|
||
descendant int primary key not null,
|
||
being int references test.being(being)
|
||
);
|
||
|
||
create table test.part (
|
||
part int primary key not null
|
||
);
|
||
|
||
create table test.being_part (
|
||
being int not null references test.being(being),
|
||
part int not null references test.part(part),
|
||
primary key(being, part)
|
||
);
|
||
|
||
create function test.single_out_param(num int, OUT num_plus_one int) AS $$
|
||
select num + 1;
|
||
$$ language sql;
|
||
|
||
create function test.single_json_out_param(a int, b text, OUT my_json json) AS $$
|
||
select json_build_object('a', a, 'b', b);
|
||
$$ language sql;
|
||
|
||
create function test.many_out_params(OUT my_json json, OUT num int, OUT str text) AS $$
|
||
select '{"a": 1, "b": "two"}'::json, 3, 'four'::text;
|
||
$$ language sql;
|
||
|
||
create function test.single_inout_param(INOUT num int) AS $$
|
||
select num + 1;
|
||
$$ language sql;
|
||
|
||
create function test.many_inout_params(INOUT num int, INOUT str text, INOUT b bool DEFAULT true) AS $$
|
||
select num, str, b;
|
||
$$ language sql;
|
||
|
||
create function test.single_column_table_return () returns table (a text) AS $$
|
||
select 'A'::text;
|
||
$$ language sql;
|
||
|
||
create function test.multi_column_table_return () returns table (a text, b text) AS $$
|
||
select 'A'::text, 'B'::text;
|
||
$$ language sql;
|
||
|
||
CREATE FUNCTION test.variadic_param(VARIADIC v TEXT[] DEFAULT '{}') RETURNS text[]
|
||
IMMUTABLE
|
||
LANGUAGE SQL AS $$
|
||
SELECT v
|
||
$$;
|
||
|
||
CREATE FUNCTION test.sayhello_variadic(name TEXT, VARIADIC v TEXT[]) RETURNS text
|
||
IMMUTABLE
|
||
LANGUAGE SQL AS $$
|
||
SELECT 'Hello, ' || name
|
||
$$;
|
||
|
||
create or replace function test.raise_pt402() returns void as $$
|
||
begin
|
||
raise sqlstate 'PT402' using message = 'Payment Required',
|
||
detail = 'Quota exceeded',
|
||
hint = 'Upgrade your plan';
|
||
end;
|
||
$$ language plpgsql;
|
||
|
||
create or replace function test.raise_bad_pt() returns void as $$
|
||
begin
|
||
raise sqlstate 'PT40A' using message = 'Wrong';
|
||
end;
|
||
$$ language plpgsql;
|
||
|
||
create or replace function test.send_body_status_403() returns json as $$
|
||
begin
|
||
perform set_config('response.status', '403', true);
|
||
return json_build_object('message', 'invalid user or password');
|
||
end;
|
||
$$ language plpgsql;
|
||
|
||
create or replace function test.send_bad_status() returns json as $$
|
||
begin
|
||
perform set_config('response.status', 'bad', true);
|
||
return null;
|
||
end;
|
||
$$ language plpgsql;
|
||
|
||
create or replace function test.get_projects_and_guc_headers() returns setof test.projects as $$
|
||
set local "response.headers" = '[{"X-Test": "key1=val1; someValue; key2=val2"}, {"X-Test-2": "key1=val1"}]';
|
||
select * from test.projects;
|
||
$$ language sql;
|
||
|
||
create or replace function test.get_int_and_guc_headers(num int) returns integer as $$
|
||
set local "response.headers" = '[{"X-Test":"key1=val1; someValue; key2=val2"},{"X-Test-2":"key1=val1"}]';
|
||
select num;
|
||
$$ language sql;
|
||
|
||
create or replace function test.bad_guc_headers_1() returns void as $$
|
||
set local "response.headers" = '{"X-Test": "invalid structure for headers"}';
|
||
$$ language sql;
|
||
|
||
create or replace function test.bad_guc_headers_2() returns void as $$
|
||
set local "response.headers" = '["invalid", "structure", "for", "headers"]';
|
||
$$ language sql;
|
||
|
||
create or replace function test.bad_guc_headers_3() returns void as $$
|
||
set local "response.headers" = '{"X-Test": "invalid", "X-Test-2": "structure", "X-Test-3": "for headers"}';
|
||
$$ language sql;
|
||
|
||
create or replace function test.set_cookie_twice() returns void as $$
|
||
set local "response.headers" = '[{"Set-Cookie": "sessionid=38afes7a8; HttpOnly; Path=/"}, {"Set-Cookie": "id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly"}]';
|
||
$$ language sql;
|
||
|
||
create or replace function test.three_defaults(a int default 1, b int default 2, c int default 3) returns int as $$
|
||
select a + b + c
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded() returns setof int as $$
|
||
values (1), (2), (3);
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded(json) returns table(x int, y text) as $$
|
||
select * from json_to_recordset($1) as r(x int, y text);
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded(a int, b int) returns int as $$
|
||
select a + b
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded(a text, b text, c text) returns text as $$
|
||
select a || b || c
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_default(opt_param text default 'Code w7') returns setof test.tasks as $$
|
||
select * from test.tasks where name like opt_param;
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_default(must_param int) returns jsonb as $$
|
||
select row_to_json(r)::jsonb from (select must_param as val) as r;
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_default(a int, opt_param text default 'Design IOS') returns setof test.tasks as $$
|
||
select * from test.tasks where name like opt_param and id > a;
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_default(a int, must_param int) returns jsonb as $$
|
||
select row_to_json(r)::jsonb from (select a, must_param as val) as r;
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_html_form() returns setof int as $$
|
||
values (1), (2), (3);
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_html_form(single_param json) returns json as $$
|
||
select single_param;
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_html_form(a int, b int) returns int as $$
|
||
select a + b
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_html_form(a text, b text, c text) returns text as $$
|
||
select a || b || c
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_same_args(arg integer) returns json as $$
|
||
select json_build_object(
|
||
'type', pg_typeof(arg),
|
||
'value', arg
|
||
);
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_same_args(arg xml) returns json as $$
|
||
select json_build_object(
|
||
'type', pg_typeof(arg),
|
||
'value', arg
|
||
);
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_same_args(arg text, num integer default 0) returns json as $$
|
||
select json_build_object(
|
||
'type', pg_typeof(arg),
|
||
'value', arg
|
||
);
|
||
$$ language sql;
|
||
|
||
create table test.leak(
|
||
id serial primary key,
|
||
blob bytea
|
||
);
|
||
|
||
create function test.leak(blob bytea) returns void as $$ begin end; $$ language plpgsql;
|
||
|
||
create table test.perf_articles(
|
||
id integer not null,
|
||
body text not null
|
||
);
|
||
|
||
create table test.employees(
|
||
first_name text,
|
||
last_name text,
|
||
salary money,
|
||
company text,
|
||
occupation text,
|
||
primary key(first_name, last_name)
|
||
);
|
||
|
||
create table test.tiobe_pls(
|
||
name text primary key,
|
||
rank smallint
|
||
);
|
||
|
||
create table test.single_unique(
|
||
unique_key integer unique not null,
|
||
value text
|
||
);
|
||
|
||
create table test.compound_unique(
|
||
key1 integer not null,
|
||
key2 integer not null,
|
||
value text,
|
||
unique(key1, key2)
|
||
);
|
||
|
||
create table test.family_tree (
|
||
id text not null primary key,
|
||
name text not null,
|
||
parent text
|
||
);
|
||
alter table only test.family_tree add constraint pptr foreign key (parent) references test.family_tree(id);
|
||
|
||
create table test.managers (
|
||
id integer primary key,
|
||
name text
|
||
);
|
||
|
||
create table test.organizations (
|
||
id integer primary key,
|
||
name text,
|
||
referee integer references organizations(id),
|
||
auditor integer references organizations(id),
|
||
manager_id integer references managers(id)
|
||
);
|
||
alter table only test.organizations rename constraint organizations_manager_id_fkey to manager;
|
||
|
||
create table private.authors(
|
||
id integer primary key,
|
||
name text
|
||
);
|
||
|
||
create table private.publishers(
|
||
id integer primary key,
|
||
name text
|
||
);
|
||
|
||
create table private.books(
|
||
id integer primary key,
|
||
title text,
|
||
publication_year smallint,
|
||
author_id integer references private.authors(id),
|
||
first_publisher_id integer references private.publishers(id)
|
||
);
|
||
|
||
create view test.authors as select id, name from private.authors;
|
||
create view test.publishers as select id, name from private.publishers;
|
||
|
||
create view test.books as select id, title, publication_year, author_id, first_publisher_id from private.books;
|
||
create view test.forties_books as select id, title, publication_year, author_id from private.books where publication_year >= 1940 and publication_year < 1950;
|
||
create view test.fifties_books as select id, title, publication_year, author_id from private.books where publication_year >= 1950 and publication_year < 1960;
|
||
create view test.sixties_books as select id, title, publication_year, author_id from private.books where publication_year >= 1960 and publication_year < 1970;
|
||
|
||
create table person (
|
||
id integer primary key,
|
||
name character varying not null);
|
||
|
||
create table message (
|
||
id integer primary key,
|
||
body text not null default '',
|
||
sender bigint not null references person(id),
|
||
recipient bigint not null references person(id));
|
||
|
||
create view person_detail as
|
||
select p.id, p.name, s.count as sent, r.count as received
|
||
from person p
|
||
join lateral (select message.sender, count(message.id) as count from message group by message.sender) s on s.sender = p.id
|
||
join lateral (select message.recipient, count(message.id) as count from message group by message.recipient) r on r.recipient = p.id;
|
||
|
||
create table space(
|
||
id integer primary key,
|
||
name text);
|
||
|
||
create table zone(
|
||
id integer primary key,
|
||
name text,
|
||
zone_type_id integer,
|
||
space_id integer references space(id));
|
||
|
||
-- foreign table tests
|
||
create extension file_fdw;
|
||
|
||
create server import_csv foreign data wrapper file_fdw;
|
||
|
||
create foreign table projects_dump (
|
||
id integer,
|
||
name text,
|
||
client_id integer
|
||
) server import_csv options ( filename '/tmp/projects_dump.csv', format 'csv');
|
||
|
||
comment on foreign table projects_dump is
|
||
$$A temporary projects dump
|
||
|
||
Just a test for foreign tables$$;
|
||
|
||
create table "UnitTest"(
|
||
"idUnitTest" integer primary key,
|
||
"nameUnitTest" text
|
||
);
|
||
|
||
create table json_arr(
|
||
id integer primary key,
|
||
data json
|
||
);
|
||
|
||
create table jsonb_test(
|
||
id integer primary key,
|
||
data jsonb
|
||
);
|
||
|
||
create view test.authors_books_number as
|
||
select
|
||
id,
|
||
name,
|
||
(
|
||
select
|
||
count(*)
|
||
from forties_books where author_id = authors.id
|
||
) as num_in_forties,
|
||
(
|
||
select
|
||
count(*)
|
||
from fifties_books where author_id = authors.id
|
||
) as num_in_fifties,
|
||
(
|
||
select
|
||
count(*)
|
||
from sixties_books where author_id = authors.id
|
||
) as num_in_sixties,
|
||
(
|
||
select
|
||
count(*)
|
||
from (
|
||
select id
|
||
from forties_books where author_id = authors.id
|
||
union
|
||
select id
|
||
from fifties_books where author_id = authors.id
|
||
union
|
||
select id
|
||
from sixties_books where author_id = authors.id
|
||
) _
|
||
) as num_in_all_decades
|
||
from private.authors;
|
||
|
||
create view test.authors_have_book_in_decade as
|
||
select
|
||
id,
|
||
name,
|
||
case
|
||
when (x.id in (select author_id from test.forties_books))
|
||
then true
|
||
else false
|
||
end as has_book_in_forties,
|
||
case
|
||
when (x.id in (select author_id from test.fifties_books))
|
||
then true
|
||
else false
|
||
end as has_book_in_fifties,
|
||
case
|
||
when (x.id in (select author_id from test.sixties_books))
|
||
then true
|
||
else false
|
||
end as has_book_in_sixties
|
||
from private.authors x;
|
||
|
||
create view test.authors_have_book_in_decade2 as
|
||
select
|
||
id,
|
||
name,
|
||
coalesce(
|
||
(select true from test.forties_books where author_id=x.id limit 1),
|
||
false
|
||
) as has_book_in_forties,
|
||
coalesce(
|
||
(select true from test.fifties_books where author_id=x.id limit 1),
|
||
false
|
||
) as has_book_in_fifties,
|
||
coalesce(
|
||
(select true from test.sixties_books where author_id=x.id limit 1),
|
||
false
|
||
) as has_book_in_sixties
|
||
from private.authors x;
|
||
|
||
create view test.forties_and_fifties_books as
|
||
select x.id, x.title, x.publication_year, y.name as first_publisher, x.author_id
|
||
from (
|
||
select id, title, publication_year, author_id, first_publisher_id from private.books
|
||
where publication_year >= 1940 and publication_year < 1960) x
|
||
join private.publishers y on y.id = x.first_publisher_id;
|
||
|
||
create view test.odd_years_publications as
|
||
with
|
||
odd_years_books as(
|
||
select id, title, publication_year, author_id, first_publisher_id
|
||
from private.books
|
||
where publication_year % 2 <> 0
|
||
)
|
||
select
|
||
x.id, x.title, x.publication_year,
|
||
y.name as first_publisher, x.author_id
|
||
from odd_years_books x
|
||
join private.publishers y on y.id = x.first_publisher_id;
|
||
|
||
create view test.projects_count_grouped_by as
|
||
select
|
||
client_id,
|
||
count(id) as number_of_projects
|
||
from projects
|
||
group by client_id;
|
||
|
||
create view test.authors_w_entities as
|
||
select
|
||
id,
|
||
name,
|
||
(
|
||
select json_agg(id)
|
||
from test.entities
|
||
where id not in (
|
||
select parent_id from test.child_entities
|
||
)
|
||
) as entities
|
||
from private.authors;
|
||
|
||
CREATE TABLE test."Foo"(
|
||
id int primary key,
|
||
name text
|
||
);
|
||
|
||
CREATE TABLE test.bar(
|
||
id int primary key,
|
||
name text,
|
||
"fooId" int references "Foo"(id)
|
||
);
|
||
|
||
CREATE VIEW test.foos as select id,name from "Foo";
|
||
CREATE VIEW test.bars as select id, "fooId", name from bar;
|
||
|
||
create materialized view materialized_projects as
|
||
select id, name, client_id from projects;
|
||
|
||
comment on materialized view materialized_projects is
|
||
$$A materialized view for projects
|
||
|
||
Just a test for materialized views$$;
|
||
|
||
-- Tests for updatable, insertable and deletable views
|
||
create view test.projects_auto_updatable_view_with_pk as
|
||
select id, name, client_id from test.projects;
|
||
|
||
create view test.projects_auto_updatable_view_without_pk as
|
||
select name, client_id from test.projects;
|
||
|
||
create view test.projects_view_without_triggers as
|
||
select distinct id, name, client_id from test.projects;
|
||
|
||
create or replace function test.test_for_views_with_triggers() returns trigger as $$
|
||
begin
|
||
return null;
|
||
end;
|
||
$$ language plpgsql;
|
||
|
||
create view test.projects_view_with_all_triggers_with_pk as
|
||
select distinct id, name, client_id from test.projects;
|
||
|
||
create trigger projects_view_with_all_triggers_with_pk_insert
|
||
instead of insert on test.projects_view_with_all_triggers_with_pk
|
||
for each row execute procedure test_for_views_with_triggers();
|
||
|
||
create trigger projects_view_with_all_triggers_with_pk_update
|
||
instead of update on test.projects_view_with_all_triggers_with_pk
|
||
for each row execute procedure test_for_views_with_triggers();
|
||
|
||
create trigger projects_view_with_all_triggers_with_pk_delete
|
||
instead of delete on test.projects_view_with_all_triggers_with_pk
|
||
for each row execute procedure test_for_views_with_triggers();
|
||
|
||
create view test.projects_view_with_all_triggers_without_pk as
|
||
select distinct name, client_id from test.projects;
|
||
|
||
create trigger projects_view_with_all_triggers_without_pk_insert
|
||
instead of insert on test.projects_view_with_all_triggers_without_pk
|
||
for each row execute procedure test_for_views_with_triggers();
|
||
|
||
create trigger projects_view_with_all_triggers_without_pk_update
|
||
instead of update on test.projects_view_with_all_triggers_without_pk
|
||
for each row execute procedure test_for_views_with_triggers();
|
||
|
||
create trigger projects_view_with_all_triggers_without_pk_delete
|
||
instead of delete on test.projects_view_with_all_triggers_without_pk
|
||
for each row execute procedure test_for_views_with_triggers();
|
||
|
||
create view test.projects_view_with_insert_trigger as
|
||
select distinct id, name, client_id from test.projects;
|
||
|
||
create trigger projects_view_with_insert_trigger_insert
|
||
instead of insert on test.projects_view_with_insert_trigger
|
||
for each row execute procedure test_for_views_with_triggers();
|
||
|
||
create view test.projects_view_with_update_trigger as
|
||
select distinct id, name, client_id from test.projects;
|
||
|
||
create trigger projects_view_with_update_trigger_update
|
||
instead of update on test.projects_view_with_update_trigger
|
||
for each row execute procedure test_for_views_with_triggers();
|
||
|
||
create view test.projects_view_with_delete_trigger as
|
||
select distinct id, name, client_id from test.projects;
|
||
|
||
create trigger projects_view_with_delete_trigger_delete
|
||
instead of delete on test.projects_view_with_delete_trigger
|
||
for each row execute procedure test_for_views_with_triggers();
|
||
|
||
create or replace function test."quotedFunction"("user" text, "fullName" text, "SSN" text)
|
||
returns jsonb AS $$
|
||
select format('{"user": "%s", "fullName": "%s", "SSN": "%s"}', "user", "fullName", "SSN")::jsonb;
|
||
$$ language sql;
|
||
|
||
create table private.player (
|
||
id integer not null,
|
||
first_name text not null,
|
||
last_name text not null,
|
||
birth_date date,
|
||
primary key (last_name, id, first_name, birth_date) -- just for testing a long compound pk
|
||
);
|
||
|
||
create table test.contract (
|
||
tournament text not null,
|
||
time tsrange not null,
|
||
purchase_price int not null,
|
||
id integer not null,
|
||
first_name text not null,
|
||
last_name text not null,
|
||
birth_date date,
|
||
foreign key (last_name, id, first_name, birth_date) references private.player
|
||
);
|
||
|
||
create view test.player_view as select * from private.player;
|
||
|
||
create view test.contract_view as select * from test.contract;
|
||
|
||
create type public.my_type AS enum ('something');
|
||
|
||
create function test.test_arg(my_arg public.my_type) returns text as $$
|
||
select 'foobar'::text;
|
||
$$ language sql;
|
||
|
||
create extension if not exists ltree with schema public;
|
||
|
||
create table test.ltree_sample (
|
||
path public.ltree
|
||
);
|
||
|
||
CREATE FUNCTION test.number_of_labels(test.ltree_sample) RETURNS integer AS $$
|
||
SELECT nlevel($1.path)
|
||
$$ language sql;
|
||
|
||
create extension if not exists isn with schema extensions;
|
||
|
||
create table test.isn_sample (
|
||
id extensions.isbn,
|
||
name text
|
||
);
|
||
|
||
create function test.is_valid_isbn(input text) returns boolean as $$
|
||
select is_valid(input::isbn);
|
||
$$ language sql;
|
||
|
||
create table "Server Today"(
|
||
"cHostname" text,
|
||
"Just A Server Model" text
|
||
);
|
||
|
||
create table test.pgrst_reserved_chars (
|
||
"*id*" integer,
|
||
":arr->ow::cast" text,
|
||
"(inside,parens)" text,
|
||
"a.dotted.column" text,
|
||
" col w space " text
|
||
);
|
||
|
||
CREATE TABLE test.openapi_types(
|
||
"a_character_varying" character varying,
|
||
"a_character" character(1),
|
||
"a_text" text,
|
||
"a_boolean" boolean,
|
||
"a_smallint" smallint,
|
||
"a_integer" integer,
|
||
"a_bigint" bigint,
|
||
"a_numeric" numeric,
|
||
"a_real" real,
|
||
"a_double_precision" double precision,
|
||
"a_json" json,
|
||
"a_jsonb" jsonb,
|
||
"a_text_arr" text[],
|
||
"a_int_arr" int[],
|
||
"a_bool_arr" boolean[],
|
||
"a_char_arr" char[],
|
||
"a_varchar_arr" varchar[],
|
||
"a_bigint_arr" bigint[],
|
||
"a_numeric_arr" numeric[],
|
||
"a_json_arr" json[],
|
||
"a_jsonb_arr" jsonb[]
|
||
);
|
||
|
||
CREATE TABLE test.openapi_defaults(
|
||
"text" text default 'default',
|
||
"boolean" boolean default false,
|
||
"integer" integer default 42,
|
||
"numeric" numeric default 42.2,
|
||
"date" date default '1900-01-01'::date,
|
||
"time" time default '13:00:00'::time without time zone
|
||
);
|
||
|
||
create function add_them(a integer, b integer)
|
||
returns integer as $$
|
||
select a + b;
|
||
$$ language sql;
|
||
|
||
create or replace function root() returns "application/openapi+json" as $_$
|
||
declare
|
||
openapi json = $$
|
||
{
|
||
"swagger": "2.0",
|
||
"info":{
|
||
"title":"PostgREST API",
|
||
"description":"This is a dynamic API generated by PostgREST"
|
||
}
|
||
}
|
||
$$;
|
||
begin
|
||
return openapi;
|
||
end
|
||
$_$ language plpgsql;
|
||
|
||
create or replace function welcome() returns "text/plain" as $$
|
||
select 'Welcome to PostgREST'::"text/plain";
|
||
$$ language sql;
|
||
|
||
create or replace function welcome_twice() returns setof "text/plain" as $$
|
||
select 'Welcome to PostgREST'
|
||
union all
|
||
select 'Welcome to PostgREST';
|
||
$$ language sql;
|
||
|
||
create or replace function "welcome.html"() returns "text/html" as $_$
|
||
select $$
|
||
<html>
|
||
<head>
|
||
<title>PostgREST</title>
|
||
</head>
|
||
<body>
|
||
<h1>Welcome to PostgREST</h1>
|
||
</body>
|
||
</html>
|
||
$$::"text/html";
|
||
$_$ language sql;
|
||
|
||
create view getallprojects_view as
|
||
select * from getallprojects();
|
||
|
||
create view get_projects_above_view as
|
||
select * from get_projects_above(1);
|
||
|
||
CREATE TABLE web_content (
|
||
id integer,
|
||
name text,
|
||
p_web_id integer references web_content(id),
|
||
primary key (id)
|
||
);
|
||
|
||
CREATE FUNCTION getallusers() RETURNS SETOF users AS $$
|
||
SELECT * FROM test.users;
|
||
$$ LANGUAGE sql STABLE;
|
||
|
||
create table app_users (
|
||
id integer primary key,
|
||
email text unique not null,
|
||
password text not null
|
||
);
|
||
|
||
create table private.pages (
|
||
link int not null unique
|
||
, url text
|
||
);
|
||
|
||
create table private.referrals (
|
||
site text
|
||
, link int references private.pages(link) not null
|
||
);
|
||
|
||
create view test.pages as select * from private.pages;
|
||
|
||
create view test.referrals as select * from private.referrals;
|
||
|
||
create table big_projects (
|
||
big_project_id serial primary key,
|
||
name text
|
||
);
|
||
|
||
create table sites (
|
||
site_id serial primary key
|
||
, name text
|
||
, main_project_id int null references big_projects (big_project_id)
|
||
);
|
||
alter table sites rename constraint sites_main_project_id_fkey to main_project;
|
||
|
||
create table jobs (
|
||
job_id uuid
|
||
, name text
|
||
, site_id int not null references sites (site_id)
|
||
, big_project_id int not null references big_projects (big_project_id)
|
||
, primary key(job_id, site_id, big_project_id)
|
||
);
|
||
|
||
create view main_jobs as
|
||
select * from jobs
|
||
where site_id in (select site_id from sites where main_project_id is not null);
|
||
|
||
-- junction in a private schema, just to make sure we don't leak it on resource embedding
|
||
-- if it leaks it would show on the disambiguation error tests
|
||
create view private.priv_jobs as
|
||
select * from jobs;
|
||
|
||
-- tables to show our limitation when trying to do an m2m embed
|
||
-- with a junction table that has more than two foreign keys
|
||
create table whatev_projects (
|
||
id serial primary key,
|
||
name text
|
||
);
|
||
|
||
create table whatev_sites (
|
||
id serial primary key
|
||
, name text
|
||
);
|
||
|
||
create table whatev_jobs (
|
||
job_id uuid
|
||
, name text
|
||
, site_id_1 int not null references whatev_sites (id)
|
||
, project_id_1 int not null references whatev_projects (id)
|
||
, site_id_2 int not null references whatev_sites (id)
|
||
, project_id_2 int not null references whatev_projects (id)
|
||
, primary key(job_id, site_id_1, project_id_1, site_id_2, project_id_2)
|
||
);
|
||
|
||
-- circular reference
|
||
create table agents (
|
||
id int primary key
|
||
, name text
|
||
, department_id int
|
||
);
|
||
|
||
create table departments (
|
||
id int primary key
|
||
, name text
|
||
, head_id int references agents(id)
|
||
);
|
||
|
||
ALTER TABLE agents
|
||
ADD CONSTRAINT agents_department_id_fkey foreign key (department_id) REFERENCES departments(id);
|
||
|
||
-- composite key disambiguation
|
||
create table schedules (
|
||
id int primary key
|
||
, name text
|
||
, start_at timetz
|
||
, end_at timetz
|
||
);
|
||
|
||
create table activities (
|
||
id int
|
||
, schedule_id int
|
||
, car_id text
|
||
, camera_id text
|
||
, primary key (id, schedule_id)
|
||
);
|
||
alter table activities
|
||
add constraint schedule foreign key (schedule_id)
|
||
references schedules (id);
|
||
|
||
create table unit_workdays (
|
||
unit_id int
|
||
, day date
|
||
, fst_shift_activity_id int
|
||
, fst_shift_schedule_id int
|
||
, snd_shift_activity_id int
|
||
, snd_shift_schedule_id int
|
||
, primary key (unit_id, day)
|
||
);
|
||
alter table unit_workdays
|
||
add constraint fst_shift foreign key (fst_shift_activity_id, fst_shift_schedule_id)
|
||
references activities (id, schedule_id),
|
||
add constraint snd_shift foreign key (snd_shift_activity_id, snd_shift_schedule_id)
|
||
references activities (id, schedule_id);
|
||
|
||
create view unit_workdays_fst_shift as
|
||
select unit_id, day, fst_shift_activity_id, fst_shift_schedule_id
|
||
from unit_workdays
|
||
where fst_shift_activity_id is not null
|
||
and fst_shift_schedule_id is not null;
|
||
|
||
-- for a pre-request function
|
||
create or replace function custom_headers() returns void as $$
|
||
declare
|
||
user_agent text := current_setting('request.headers', true)::json->>'user-agent';
|
||
req_path text := current_setting('request.path', true);
|
||
req_accept text := current_setting('request.headers', true)::json->>'accept';
|
||
req_method text := current_setting('request.method', true);
|
||
begin
|
||
if user_agent similar to 'MSIE (6.0|7.0)' then
|
||
perform set_config('response.headers',
|
||
'[{"Cache-Control": "no-cache, no-store, must-revalidate"}]', true);
|
||
elsif req_path similar to '/(items|projects)' and req_accept = 'text/csv' then
|
||
perform set_config('response.headers',
|
||
format('[{"Content-Disposition": "attachment; filename=%s.csv"}]', trim('/' from req_path)), true);
|
||
elsif req_path similar to '/(clients|rpc/getallprojects)' then
|
||
perform set_config('response.headers',
|
||
'[{"Content-Type": "application/custom+json"}]', true);
|
||
elsif req_path = '/items' and
|
||
req_method similar to 'POST|PATCH|PUT|DELETE' then
|
||
perform set_config('response.headers',
|
||
'[{"X-Custom-Header": "mykey=myval"}]', true);
|
||
end if;
|
||
end; $$ language plpgsql;
|
||
|
||
create table private.stuff(
|
||
id integer primary key
|
||
, name text
|
||
);
|
||
|
||
create view test.stuff as select * from private.stuff;
|
||
|
||
create or replace function location_for_stuff() returns trigger as $$
|
||
begin
|
||
insert into private.stuff values (new.id, new.name);
|
||
if new.id is not null
|
||
then
|
||
perform set_config(
|
||
'response.headers'
|
||
, format('[{"Location": "/%s?id=eq.%s&overriden=true"}]', tg_table_name, new.id)
|
||
, true
|
||
);
|
||
end if;
|
||
return new;
|
||
end
|
||
$$ language plpgsql security definer;
|
||
create trigger location_for_stuff instead of insert on test.stuff for each row execute procedure test.location_for_stuff();
|
||
|
||
create or replace function status_205_for_updated_stuff() returns trigger as $$
|
||
begin
|
||
update private.stuff set id = new.id, name = new.name;
|
||
perform set_config('response.status' , '205' , true);
|
||
return new;
|
||
end
|
||
$$ language plpgsql security definer;
|
||
create trigger status_205_for_updated_stuff instead of update on test.stuff for each row execute procedure test.status_205_for_updated_stuff();
|
||
|
||
create table loc_test (
|
||
id int primary key
|
||
, c text
|
||
);
|
||
|
||
-- tables to test multi schema access in one instance
|
||
create table v1.parents (
|
||
id int primary key
|
||
, name text
|
||
);
|
||
|
||
create table v1.children (
|
||
id int primary key
|
||
, name text
|
||
, parent_id int
|
||
, constraint parent foreign key(parent_id)
|
||
references v1.parents(id)
|
||
);
|
||
|
||
create function v1.get_parents_below(id int)
|
||
returns setof v1.parents as $$
|
||
select * from v1.parents where id < $1;
|
||
$$ language sql;
|
||
|
||
create table v2.parents (
|
||
id int primary key
|
||
, name text
|
||
);
|
||
|
||
create table v2.children (
|
||
id int primary key
|
||
, name text
|
||
, parent_id int
|
||
, constraint parent foreign key(parent_id)
|
||
references v2.parents(id)
|
||
);
|
||
|
||
create table v2.another_table (
|
||
id int primary key
|
||
, another_value text
|
||
);
|
||
|
||
create function v2.get_parents_below(id int)
|
||
returns setof v2.parents as $$
|
||
select * from v2.parents where id < $1;
|
||
$$ language sql;
|
||
|
||
create function v2.get_plain_text()
|
||
returns test."text/plain" as $$
|
||
select 'plain'::test."text/plain";
|
||
$$ language sql;
|
||
|
||
create domain v2."text/special" as text;
|
||
|
||
create function v2.get_special_text()
|
||
returns v2."text/special" as $$
|
||
select 'special'::v2."text/special";
|
||
$$ language sql;
|
||
|
||
create or replace function v2.special_trans (state v2."text/special", next v2.another_table)
|
||
returns v2."text/special" as $$
|
||
select 'special'::v2."text/special";
|
||
$$ language sql;
|
||
|
||
drop aggregate if exists v2.special_agg(v2.another_table);
|
||
create aggregate v2.special_agg (v2.another_table) (
|
||
initcond = ''
|
||
, stype = v2."text/special"
|
||
, sfunc = v2.special_trans
|
||
);
|
||
|
||
create or replace function v2.plain_trans (state test."text/plain", next v2.another_table)
|
||
returns test."text/plain" as $$
|
||
select 'plain'::test."text/plain";
|
||
$$ language sql;
|
||
|
||
drop aggregate if exists v2.plain_agg(v2.another_table);
|
||
create aggregate v2.plain_agg (v2.another_table) (
|
||
initcond = ''
|
||
, stype = test."text/plain"
|
||
, sfunc = v2.plain_trans
|
||
);
|
||
|
||
create table private.screens (
|
||
id serial primary key,
|
||
name text not null default 'new screen'
|
||
);
|
||
|
||
create table private.labels (
|
||
id serial primary key,
|
||
name text not null default 'new label'
|
||
);
|
||
|
||
create table private.label_screen (
|
||
label_id int not null references private.labels(id) on update cascade on delete cascade,
|
||
screen_id int not null references private.screens(id) on update cascade on delete cascade,
|
||
constraint label_screen_pkey primary key (label_id, screen_id)
|
||
);
|
||
|
||
create view test.labels as
|
||
select * from private.labels;
|
||
|
||
create view test.screens as
|
||
select * from private.screens;
|
||
|
||
create view test.label_screen as
|
||
select * from private.label_screen;
|
||
|
||
create table private.actors (
|
||
id int,
|
||
name text,
|
||
constraint actors_id primary key (id)
|
||
);
|
||
|
||
create table private.films (
|
||
id integer,
|
||
title text,
|
||
constraint films_id primary key (id)
|
||
);
|
||
|
||
create table private.personnages (
|
||
film_id int not null,
|
||
role_id int not null,
|
||
character text not null,
|
||
constraint personnages_film_id_role_id primary key (film_id, role_id),
|
||
constraint personnages_film_id_fkey foreign key (film_id) references private.films(id) not deferrable,
|
||
constraint personnages_role_id_fkey foreign key (role_id) references private.actors(id) not deferrable
|
||
);
|
||
|
||
create view test.actors as
|
||
select * from private.actors;
|
||
|
||
create view test.films as
|
||
select * from private.films;
|
||
|
||
create view test.personnages as
|
||
select * from private.personnages;
|
||
|
||
create table test.end_1(
|
||
id int primary key,
|
||
name text
|
||
);
|
||
|
||
create table test.end_2(
|
||
id int primary key,
|
||
name text
|
||
);
|
||
|
||
create table private.junction(
|
||
end_1_id int not null references test.end_1(id) on update cascade on delete cascade,
|
||
end_2_id int not null references test.end_2(id) on update cascade on delete cascade,
|
||
primary key (end_1_id, end_2_id)
|
||
);
|
||
|
||
create table test.schauspieler (
|
||
id int primary key,
|
||
name text
|
||
);
|
||
|
||
create table test.filme (
|
||
id int primary key,
|
||
titel text
|
||
);
|
||
|
||
create table test.rollen ();
|
||
|
||
create table private.rollen (
|
||
film_id int not null,
|
||
rolle_id int not null,
|
||
charakter text not null,
|
||
primary key (film_id, rolle_id),
|
||
foreign key (film_id) references test.filme(id),
|
||
foreign key (rolle_id) references test.schauspieler(id)
|
||
);
|
||
|
||
-- Tables used for testing embedding between partitioned tables
|
||
|
||
do $do$begin
|
||
-- partitioned tables using the PARTITION syntax are supported from pg v10
|
||
if (select current_setting('server_version_num')::int >= 100000) then
|
||
create table test.car_models(
|
||
name varchar(64) not null,
|
||
year int not null
|
||
) partition by list (year);
|
||
|
||
comment on table test.car_models is
|
||
$$A partitioned table
|
||
|
||
A test for partitioned tables$$;
|
||
|
||
create table test.car_models_2021 partition of test.car_models
|
||
for values in (2021);
|
||
create table test.car_models_default partition of test.car_models
|
||
for values in (1981,1997,2001,2013);
|
||
end if;
|
||
|
||
-- primary keys for partitioned tables are supported from pg v11
|
||
if (select current_setting('server_version_num')::int >= 110000) then
|
||
create table test.car_brands (
|
||
name varchar(64) primary key
|
||
);
|
||
|
||
alter table test.car_models add primary key (name, year);
|
||
alter table test.car_models add column car_brand_name varchar(64) references test.car_brands(name);
|
||
end if;
|
||
|
||
-- foreign keys referencing partitioned tables are supported from pg v12
|
||
if (select current_setting('server_version_num')::int >= 120000) then
|
||
create table test.car_model_sales(
|
||
date varchar(64) not null,
|
||
quantity int not null,
|
||
car_model_name varchar(64),
|
||
car_model_year int,
|
||
primary key (date, car_model_name, car_model_year),
|
||
foreign key (car_model_name, car_model_year) references test.car_models (name, year)
|
||
) partition by range (date);
|
||
|
||
create table test.car_model_sales_202101 partition of test.car_model_sales
|
||
for values from ('2021-01-01') to ('2021-01-31');
|
||
|
||
create table test.car_model_sales_default partition of test.car_model_sales
|
||
default;
|
||
|
||
create table test.car_racers (
|
||
name varchar(64) not null primary key,
|
||
car_model_name varchar(64),
|
||
car_model_year int,
|
||
foreign key (car_model_name, car_model_year) references test.car_models (name, year)
|
||
);
|
||
|
||
create table test.car_dealers (
|
||
name varchar(64) not null,
|
||
city varchar(64) not null,
|
||
primary key (name, city)
|
||
) partition by list (city);
|
||
|
||
create table test.car_dealers_springfield partition of test.car_dealers
|
||
for values in ('Springfield');
|
||
|
||
create table test.car_dealers_default partition of test.car_dealers
|
||
default;
|
||
|
||
create table test.car_models_car_dealers (
|
||
car_model_name varchar(64) not null,
|
||
car_model_year int not null,
|
||
car_dealer_name varchar(64) not null,
|
||
car_dealer_city varchar(64) not null,
|
||
quantity int not null,
|
||
foreign key (car_model_name, car_model_year) references test.car_models (name, year),
|
||
foreign key (car_dealer_name, car_dealer_city) references test.car_dealers (name, city),
|
||
primary key (car_model_name, car_model_year, car_dealer_name, car_dealer_city, quantity)
|
||
) partition by range (quantity);
|
||
|
||
create table test.car_models_car_dealers_10to20 partition of test.car_models_car_dealers
|
||
for values from (10) to (20);
|
||
|
||
create table test.car_models_car_dealers_default partition of test.car_models_car_dealers
|
||
default;
|
||
end if;
|
||
end$do$;
|
||
|
||
create or replace function test.unnamed_json_param(json) returns json as $$
|
||
select $1;
|
||
$$ language sql;
|
||
|
||
create or replace function test.unnamed_text_param(text) returns "text/plain" as $$
|
||
select $1::"text/plain";
|
||
$$ language sql;
|
||
|
||
create or replace function test.unnamed_xml_param(pg_catalog.xml) returns "text/xml" as $$
|
||
select $1::"text/xml";
|
||
$$ language sql;
|
||
|
||
create or replace function test.unnamed_bytea_param(bytea) returns "application/octet-stream" as $$
|
||
select $1::"application/octet-stream";
|
||
$$ language sql;
|
||
|
||
create or replace function test.unnamed_int_param(int) returns int as $$
|
||
select $1;
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_unnamed_param(json) returns json as $$
|
||
select $1;
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_unnamed_param(bytea) returns "application/octet-stream" as $$
|
||
select $1::"application/octet-stream";
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_unnamed_param(text) returns "text/plain" as $$
|
||
select $1::"text/plain";
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_unnamed_param() returns int as $$
|
||
select 1;
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_unnamed_param(x int, y int) returns int as $$
|
||
select x + y;
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_unnamed_json_jsonb_param(json) returns json as $$
|
||
select $1;
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_unnamed_json_jsonb_param(jsonb) returns jsonb as $$
|
||
select $1;
|
||
$$ language sql;
|
||
|
||
create or replace function test.overloaded_unnamed_json_jsonb_param(x int, y int) returns int as $$
|
||
select x + y;
|
||
$$ language sql;
|
||
|
||
create table products(
|
||
id int primary key
|
||
, name text
|
||
);
|
||
|
||
create table suppliers(
|
||
id int primary key
|
||
, name text
|
||
);
|
||
|
||
create table products_suppliers(
|
||
product_id int references products(id),
|
||
supplier_id int references suppliers(id),
|
||
primary key (product_id, supplier_id)
|
||
);
|
||
|
||
create table trade_unions(
|
||
id int primary key
|
||
, name text
|
||
);
|
||
|
||
create table suppliers_trade_unions(
|
||
supplier_id int references suppliers(id),
|
||
trade_union_id int references trade_unions(id),
|
||
primary key (supplier_id, trade_union_id)
|
||
);
|
||
|
||
|
||
CREATE TABLE client (
|
||
id int primary key
|
||
, name text
|
||
);
|
||
|
||
CREATE TABLE contact (
|
||
id int primary key
|
||
, name text
|
||
, clientid int references client(id)
|
||
);
|
||
|
||
CREATE TABLE clientinfo (
|
||
id serial primary key
|
||
, clientid int references client(id)
|
||
, other text
|
||
);
|
||
|
||
CREATE TABLE chores (
|
||
id int primary key
|
||
, name text
|
||
, done bool
|
||
);
|
||
|
||
CREATE TABLE deferrable_unique_constraint (
|
||
col INT UNIQUE DEFERRABLE INITIALLY IMMEDIATE
|
||
);
|
||
|
||
CREATE FUNCTION raise_constraint(deferred BOOL DEFAULT FALSE) RETURNS void
|
||
LANGUAGE plpgsql AS $$
|
||
BEGIN
|
||
IF deferred THEN
|
||
SET CONSTRAINTS ALL DEFERRED;
|
||
END IF;
|
||
|
||
INSERT INTO deferrable_unique_constraint VALUES (1), (1);
|
||
END$$;
|
||
|
||
-- This view is not used in any requests but just parsed by the pfkSourceColumns query.
|
||
-- XMLTABLE is only supported from PG 10 on
|
||
DO $do$
|
||
BEGIN
|
||
IF current_setting('server_version_num')::INT >= 100000 THEN
|
||
CREATE VIEW test.xml AS
|
||
SELECT *
|
||
FROM (SELECT ''::xml AS data) _,
|
||
XMLTABLE(
|
||
''
|
||
PASSING data
|
||
COLUMNS id int PATH '@id',
|
||
premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified'
|
||
);
|
||
END IF;
|
||
END
|
||
$do$;
|
||
|
||
-- https://github.com/PostgREST/postgrest/issues/1543
|
||
CREATE TYPE complex AS (
|
||
r double precision,
|
||
i double precision
|
||
);
|
||
|
||
CREATE TABLE test.fav_numbers (
|
||
num complex,
|
||
person text
|
||
);
|
||
|
||
-- https://github.com/PostgREST/postgrest/issues/2075
|
||
create table test.arrays (
|
||
id int primary key,
|
||
numbers int[],
|
||
numbers_mult int[][]
|
||
);
|
||
|
||
-- This procedure is to confirm that procedures don't show up in the OpenAPI output right now.
|
||
-- Procedures are not supported, yet.
|
||
do $do$begin
|
||
if (select current_setting('server_version_num')::int >= 110000) then
|
||
CREATE PROCEDURE test.unsupported_proc ()
|
||
LANGUAGE SQL AS '';
|
||
end if;
|
||
end $do$;
|
||
|
||
CREATE FUNCTION public.dummy(int) RETURNS int
|
||
LANGUAGE SQL AS $$ SELECT 1 $$;
|
||
|
||
-- This aggregate is to confirm that aggregates don't show up in the OpenAPI output.
|
||
CREATE AGGREGATE test.unsupported_agg (*) (
|
||
SFUNC = public.dummy,
|
||
STYPE = int
|
||
);
|
||
|
||
create table limited_update_items(
|
||
id int primary key
|
||
, name text
|
||
);
|
||
|
||
create table limited_update_items_cpk(
|
||
id int
|
||
, name text
|
||
, primary key (id, name)
|
||
);
|
||
|
||
create table limited_update_items_no_pk(
|
||
id int
|
||
, name text
|
||
);
|
||
|
||
create view limited_update_items_view as
|
||
select * from limited_update_items;
|
||
|
||
create view limited_update_items_wnonuniq_view as
|
||
select *, 'static'::text as static from limited_update_items;
|
||
|
||
create view limited_update_items_cpk_view as
|
||
select * from limited_update_items_cpk;
|
||
|
||
create table limited_delete_items(
|
||
id int primary key
|
||
, name text
|
||
);
|
||
|
||
create table limited_delete_items_cpk(
|
||
id int
|
||
, name text
|
||
, primary key (id, name)
|
||
);
|
||
|
||
create table limited_delete_items_no_pk(
|
||
id int
|
||
, name text
|
||
);
|
||
|
||
create view limited_delete_items_view as
|
||
select * from limited_delete_items;
|
||
|
||
create view limited_delete_items_wnonuniq_view as
|
||
select *, 'static'::text as static from limited_delete_items;
|
||
|
||
create view limited_delete_items_cpk_view as
|
||
select * from limited_delete_items_cpk;
|
||
|
||
create function reset_table(tbl_name text default '', tbl_data json default '[]') returns void as $_$ begin
|
||
execute format(
|
||
$$
|
||
delete from %I where true; -- WHERE is required for pg-safeupdate tests
|
||
insert into %I
|
||
select * from json_populate_recordset(null::%I, $1);
|
||
$$::text,
|
||
tbl_name, tbl_name, tbl_name)
|
||
using tbl_data;
|
||
end; $_$ language plpgsql volatile;
|
||
|
||
-- tables for ensuring we generate real junctions for many-to-many relationships
|
||
create table plate (
|
||
plate_id int primary key
|
||
);
|
||
|
||
create table well (
|
||
well_id int primary key,
|
||
plate_id int not null,
|
||
parent_well_id int,
|
||
CONSTRAINT well_parent_well_id_fkey
|
||
FOREIGN KEY(parent_well_id)
|
||
REFERENCES well(well_id),
|
||
CONSTRAINT well_plate_id_fkey
|
||
FOREIGN KEY(plate_id)
|
||
REFERENCES plate(plate_id)
|
||
);
|
||
|
||
create table plate_plan_step (
|
||
plate_plan_step_id int primary key,
|
||
from_well_id int,
|
||
to_well_id int,
|
||
to_plate_id int,
|
||
CONSTRAINT plate_plan_step_from_well_id_fkey
|
||
FOREIGN KEY(from_well_id)
|
||
REFERENCES well(well_id),
|
||
CONSTRAINT plate_plan_step_to_plate_id_fkey
|
||
FOREIGN KEY(to_plate_id)
|
||
REFERENCES plate(plate_id),
|
||
CONSTRAINT plate_plan_step_to_well_id_fkey
|
||
FOREIGN KEY(to_well_id)
|
||
REFERENCES well(well_id)
|
||
);
|
||
|
||
CREATE FUNCTION test.return_scalar_xml() RETURNS "text/xml"
|
||
LANGUAGE sql AS $$
|
||
SELECT '<my-xml-tag/>'::"text/xml"
|
||
$$;
|
||
|
||
CREATE OR REPLACE FUNCTION "welcome.xml"() RETURNS "text/xml"
|
||
LANGUAGE sql AS $_$
|
||
select $$
|
||
<html>
|
||
<head>
|
||
<title>PostgREST</title>
|
||
</head>
|
||
<body>
|
||
<h1>Welcome to PostgREST</h1>
|
||
</body>
|
||
</html>$$::"text/xml";
|
||
$_$;
|
||
|
||
CREATE TABLE test.xmltest (
|
||
id integer primary key,
|
||
xml pg_catalog.xml NOT NULL
|
||
);
|
||
|
||
create or replace function test.xml_handler_transition (state "text/xml", next test.xmltest)
|
||
returns "text/xml" as $$
|
||
select xmlconcat2(state, next.xml)::"text/xml";
|
||
$$ language sql;
|
||
|
||
create or replace function test.xml_handler_final (data "text/xml")
|
||
returns "text/xml" as $$
|
||
select data;
|
||
$$ language sql;
|
||
|
||
drop aggregate if exists test.text_xml_agg(test.xmltest);
|
||
create aggregate test.text_xml_agg (test.xmltest) (
|
||
stype = "text/xml"
|
||
, sfunc = test.xml_handler_transition
|
||
, finalfunc = test.xml_handler_final
|
||
);
|
||
|
||
CREATE TABLE oid_test(
|
||
id int,
|
||
oid_col oid,
|
||
oid_array_col oid[]);
|
||
|
||
CREATE TABLE private.internal_job
|
||
(
|
||
id integer NOT NULL,
|
||
parent_id integer,
|
||
CONSTRAINT internal_job_pkey PRIMARY KEY (id),
|
||
CONSTRAINT parent_fk FOREIGN KEY (parent_id) REFERENCES private.internal_job (id)
|
||
);
|
||
|
||
CREATE VIEW test.job AS
|
||
SELECT j.id, j.parent_id
|
||
FROM private.internal_job j;
|
||
|
||
-- https://github.com/PostgREST/postgrest/issues/2238
|
||
CREATE TABLE series (
|
||
id bigint PRIMARY KEY,
|
||
title text NOT NULL
|
||
);
|
||
|
||
CREATE TABLE adaptation_notifications (
|
||
id bigint PRIMARY KEY,
|
||
series bigint REFERENCES series(id),
|
||
status text
|
||
);
|
||
|
||
CREATE VIEW series_popularity AS
|
||
SELECT id, random() AS popularity_score
|
||
FROM series;
|
||
|
||
-- https://github.com/PostgREST/postgrest/issues/1643
|
||
CREATE TABLE test.test (
|
||
id BIGINT NOT NULL PRIMARY KEY,
|
||
parent_id BIGINT CONSTRAINT parent_test REFERENCES test(id)
|
||
);
|
||
|
||
CREATE OR REPLACE VIEW test.view_test AS
|
||
SELECT id FROM test.test;
|
||
|
||
create extension if not exists postgis with schema extensions;
|
||
|
||
create table shops (
|
||
id int primary key
|
||
, address text
|
||
, shop_geom extensions.geometry(POINT, 4326)
|
||
);
|
||
|
||
create table shop_bles (
|
||
id int primary key
|
||
, name text
|
||
, coords extensions.geometry(POINT, 4326)
|
||
, range_area extensions.geometry(POLYGON, 4326)
|
||
, shop_id int references shops(id)
|
||
);
|
||
|
||
create function get_shop(id int) returns shops as $$
|
||
select * from shops where id = $1;
|
||
$$ language sql;
|
||
|
||
CREATE TABLE "SPECIAL ""@/\#~_-".languages(
|
||
id INT PRIMARY KEY,
|
||
name TEXT
|
||
);
|
||
|
||
CREATE TABLE "SPECIAL ""@/\#~_-".names(
|
||
id INT PRIMARY KEY,
|
||
name TEXT,
|
||
language_id INT REFERENCES "SPECIAL ""@/\#~_-".languages(id)
|
||
);
|
||
|
||
CREATE FUNCTION "SPECIAL ""@/\#~_-".computed_languages("SPECIAL ""@/\#~_-".names) RETURNS SETOF "SPECIAL ""@/\#~_-".languages ROWS 1 AS $$
|
||
SELECT * FROM "SPECIAL ""@/\#~_-".languages where id = $1.language_id;
|
||
$$ LANGUAGE sql;
|
||
|
||
CREATE FUNCTION "EXTRA ""@/\#~_-".get_val_special(val text) RETURNS text AS $$
|
||
SELECT val;
|
||
$$ LANGUAGE sql;
|
||
|
||
CREATE FUNCTION test.special_extended_schema(val text) RETURNS text AS $$
|
||
SELECT get_val_special(val);
|
||
$$ LANGUAGE sql;
|
||
|
||
CREATE TABLE do$llar$s (
|
||
a$num$ numeric
|
||
);
|
||
|
||
-- Tables and functions to test the pg-safeupdate library
|
||
|
||
CREATE TABLE test.safe_update_items(
|
||
id INT PRIMARY KEY,
|
||
name TEXT,
|
||
observation TEXT
|
||
);
|
||
|
||
CREATE TABLE test.safe_delete_items(
|
||
id INT PRIMARY KEY,
|
||
name TEXT,
|
||
observation TEXT
|
||
);
|
||
|
||
CREATE TABLE test.unsafe_update_items(
|
||
id INT PRIMARY KEY,
|
||
name TEXT,
|
||
observation TEXT
|
||
);
|
||
|
||
CREATE TABLE test.unsafe_delete_items(
|
||
id INT PRIMARY KEY,
|
||
name TEXT,
|
||
observation TEXT
|
||
);
|
||
|
||
CREATE OR REPLACE FUNCTION test.load_safeupdate() RETURNS VOID AS $$
|
||
BEGIN
|
||
LOAD 'safeupdate';
|
||
END; $$ LANGUAGE plpgsql SECURITY DEFINER;
|
||
|
||
-- This tests data representations over computed joins: even a lower case title should come back title cased.
|
||
DROP DOMAIN IF EXISTS public.titlecasetext CASCADE;
|
||
CREATE DOMAIN public.titlecasetext AS text;
|
||
|
||
CREATE OR REPLACE FUNCTION json(public.titlecasetext) RETURNS json AS $$
|
||
SELECT to_json(INITCAP($1::text));
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE CAST (public.titlecasetext AS json) WITH FUNCTION json(public.titlecasetext) AS IMPLICIT;
|
||
-- End of data representations specific stuff except for where the domain is used in the table.
|
||
|
||
CREATE TABLE designers (
|
||
id int primary key
|
||
, name public.titlecasetext
|
||
);
|
||
|
||
CREATE TABLE videogames (
|
||
id int primary key
|
||
, name text
|
||
, designer_id int references designers(id)
|
||
);
|
||
|
||
-- computed relationships
|
||
CREATE FUNCTION test.computed_designers(test.videogames) RETURNS SETOF test.designers AS $$
|
||
SELECT * FROM test.designers WHERE id = $1.designer_id;
|
||
$$ LANGUAGE sql STABLE ROWS 1;
|
||
|
||
CREATE FUNCTION test.computed_designers_noset(test.videogames) RETURNS test.designers AS $$
|
||
SELECT * FROM test.designers WHERE id = $1.designer_id;
|
||
$$ LANGUAGE sql STABLE;
|
||
|
||
CREATE FUNCTION test.computed_videogames(test.designers) RETURNS SETOF test.videogames AS $$
|
||
SELECT * FROM test.videogames WHERE designer_id = $1.id;
|
||
$$ LANGUAGE sql STABLE;
|
||
|
||
CREATE FUNCTION test.getallvideogames() RETURNS SETOF test.videogames AS $$
|
||
SELECT * FROM test.videogames;
|
||
$$ LANGUAGE sql STABLE;
|
||
|
||
CREATE FUNCTION test.getalldesigners() RETURNS SETOF test.designers AS $$
|
||
SELECT * FROM test.designers;
|
||
$$ LANGUAGE sql STABLE;
|
||
|
||
-- self join for computed relationships
|
||
CREATE FUNCTION test.child_web_content(test.web_content) RETURNS SETOF test.web_content AS $$
|
||
SELECT * FROM test.web_content WHERE $1.id = p_web_id;
|
||
$$ LANGUAGE sql STABLE;
|
||
|
||
CREATE FUNCTION test.parent_web_content(test.web_content) RETURNS SETOF test.web_content AS $$
|
||
SELECT * FROM test.web_content WHERE $1.p_web_id = id;
|
||
$$ LANGUAGE sql STABLE ROWS 1;
|
||
|
||
-- overriding computed rels that empty the results
|
||
CREATE FUNCTION test.designers(test.videogames) RETURNS SETOF test.designers AS $$
|
||
SELECT * FROM test.designers WHERE FALSE;
|
||
$$ LANGUAGE sql STABLE ROWS 1;
|
||
|
||
CREATE FUNCTION test.videogames(test.designers) RETURNS SETOF test.videogames AS $$
|
||
SELECT * FROM test.videogames WHERE FALSE;
|
||
$$ LANGUAGE sql STABLE;
|
||
|
||
CREATE TABLE test.students(
|
||
id int
|
||
, code text
|
||
, name text
|
||
, primary key(id, code)
|
||
);
|
||
|
||
CREATE TABLE test.students_info(
|
||
id int
|
||
, code text
|
||
, address text
|
||
, primary key(id, code)
|
||
, foreign key (code, id) references test.students(code, id) on delete cascade
|
||
);
|
||
|
||
CREATE TABLE test.country(
|
||
id int primary key
|
||
, name text
|
||
);
|
||
|
||
CREATE TABLE test.capital(
|
||
id int primary key
|
||
, name text
|
||
, country_id int unique
|
||
, foreign key (country_id) references test.country(id)
|
||
);
|
||
|
||
CREATE FUNCTION test.allcountries() RETURNS SETOF test.country AS $$
|
||
SELECT * FROM test.country;
|
||
$$ LANGUAGE sql STABLE;
|
||
|
||
CREATE FUNCTION test.allcapitals() RETURNS SETOF test.capital AS $$
|
||
SELECT * FROM test.capital;
|
||
$$ LANGUAGE sql STABLE;
|
||
|
||
create view students_view as
|
||
select * from students;
|
||
|
||
create view students_info_view as
|
||
select * from students_info;
|
||
|
||
create table test.second (
|
||
id int primary key,
|
||
name text
|
||
);
|
||
|
||
create table test.first (
|
||
id int primary key,
|
||
name text,
|
||
second_id_1 int references test.second unique,
|
||
second_id_2 int references test.second unique
|
||
);
|
||
|
||
create table test.second_1 (
|
||
id int primary key,
|
||
name text
|
||
);
|
||
|
||
create table test.first_1 (
|
||
id int primary key,
|
||
name text,
|
||
second_id_1 int references test.second unique,
|
||
second_id_2 int references test.second unique
|
||
);
|
||
|
||
CREATE FUNCTION test.second_1(test.first_1) RETURNS SETOF test.second_1 AS $$
|
||
SELECT * FROM test.second_1 WHERE id = $1.second_id_1;
|
||
$$ LANGUAGE sql STABLE ROWS 1;
|
||
|
||
CREATE FUNCTION test.first_1(test.second_1) RETURNS SETOF test.first_1 AS $$
|
||
SELECT * FROM test.first_1 WHERE second_id_1 = $1.id;
|
||
$$ LANGUAGE sql STABLE ROWS 1;
|
||
|
||
|
||
create table fee (
|
||
fee_id int primary key
|
||
);
|
||
create table baz (
|
||
baz_id int primary key
|
||
);
|
||
|
||
create table janedoe (
|
||
janedoe_id int primary key,
|
||
baz_id int references baz(baz_id)
|
||
);
|
||
|
||
create table johnsmith (
|
||
johnsmith_id int primary key,
|
||
fee_id int references fee(fee_id),
|
||
baz_id int references baz(baz_id)
|
||
);
|
||
|
||
create or replace function jsbaz(fee) returns setof baz as $$
|
||
select b.*
|
||
from baz b
|
||
join johnsmith js on js.baz_id = b.baz_id
|
||
where js.fee_id = $1.fee_id
|
||
$$ stable language sql;
|
||
|
||
|
||
-- issue https://github.com/PostgREST/postgrest/issues/2518
|
||
create table a (
|
||
primary key (c1, c2),
|
||
c1 int,
|
||
c2 bool
|
||
);
|
||
|
||
create table b (
|
||
c2 bool,
|
||
c1 int,
|
||
foreign key (c1, c2) references a
|
||
);
|
||
|
||
create view test.v1 as table test.a;
|
||
|
||
create view test.v2 as table test.b;
|
||
|
||
-- issue https://github.com/PostgREST/postgrest/issues/2458
|
||
create table with_pk1 (pk1 int primary key);
|
||
create table with_pk2 (pk2 int primary key);
|
||
|
||
create view with_multiple_pks as
|
||
select * from with_pk1, with_pk2;
|
||
|
||
create function with_multiple_pks_insert() returns trigger
|
||
language plpgsql as $$
|
||
begin
|
||
insert into with_pk1 values (new.pk1) on conflict do nothing;
|
||
insert into with_pk2 values (new.pk2) on conflict do nothing;
|
||
return new;
|
||
end
|
||
$$;
|
||
|
||
create trigger ins instead of insert on with_multiple_pks
|
||
for each row execute procedure with_multiple_pks_insert();
|
||
|
||
-- issue https://github.com/PostgREST/postgrest/issues/2283
|
||
create view self_recursive_view as table projects;
|
||
create or replace view self_recursive_view as table self_recursive_view;
|
||
|
||
CREATE FUNCTION test.computed_clients(test.projects) RETURNS SETOF test.clients ROWS 1 AS $$
|
||
SELECT * FROM test.clients WHERE id = $1.client_id;
|
||
$$ LANGUAGE sql STABLE;
|
||
|
||
CREATE FUNCTION test.computed_projects(test.clients) RETURNS SETOF test.projects ROWS 1 AS $$
|
||
SELECT * FROM test.projects WHERE client_id = $1.id;
|
||
$$ LANGUAGE sql STABLE;
|
||
|
||
-- issue https://github.com/PostgREST/postgrest/issues/2459
|
||
create table public.i2459_simple_t1 (
|
||
id int primary key
|
||
);
|
||
|
||
create table public.i2459_simple_t2 (
|
||
t1_id int references public.i2459_simple_t1
|
||
);
|
||
|
||
create view i2459_simple_v1 as table public.i2459_simple_t1;
|
||
|
||
create view i2459_simple_v2 as
|
||
select t1_id as t1_id1, t1_id as t1_id2 from public.i2459_simple_t2;
|
||
|
||
|
||
create table public.i2459_composite_t1 (
|
||
primary key (a,b),
|
||
a int,
|
||
b int
|
||
);
|
||
|
||
create table public.i2459_composite_t2 (
|
||
t1_a int,
|
||
t1_b int,
|
||
constraint i2459_composite_t2_t1_a_t1_b_fkey foreign key (t1_a, t1_b) references public.i2459_composite_t1
|
||
);
|
||
|
||
create view i2459_composite_v1 as table public.i2459_composite_t1;
|
||
|
||
create view i2459_composite_v2 as
|
||
select t1_a as t1_a1,
|
||
t1_b as t1_b1,
|
||
t1_a as t1_a2,
|
||
t1_b as t1_b2
|
||
from public.i2459_composite_t2;
|
||
|
||
|
||
create table public.i2459_self_t (
|
||
id int primary key,
|
||
parent int references public.i2459_self_t,
|
||
type text
|
||
);
|
||
|
||
|
||
create view i2459_self_v1 as
|
||
select parent.parent as grandparent,
|
||
child.parent,
|
||
child.id
|
||
from public.i2459_self_t as parent
|
||
join public.i2459_self_t as child
|
||
on child.parent = parent.id
|
||
where child.type = 'A';
|
||
|
||
create view i2459_self_v2 as
|
||
select parent.parent as grandparent,
|
||
child.parent,
|
||
child.id
|
||
from public.i2459_self_t as parent
|
||
join public.i2459_self_t as child
|
||
on child.parent = parent.id
|
||
where child.type = 'B';
|
||
|
||
-- issue https://github.com/PostgREST/postgrest/issues/2548
|
||
CREATE TABLE public.ta (
|
||
a1 INT PRIMARY KEY,
|
||
a2 INT,
|
||
UNIQUE (a1, a2)
|
||
);
|
||
|
||
CREATE TABLE public.tb (
|
||
b1 INT REFERENCES public.ta (a1),
|
||
b2 INT,
|
||
FOREIGN KEY (b1, b2) REFERENCES public.ta (a1, a2)
|
||
);
|
||
|
||
CREATE VIEW test.va AS SELECT a1 FROM public.ta;
|
||
CREATE VIEW test.vb AS SELECT b1 FROM public.tb;
|
||
|
||
create table test.trash(
|
||
id int primary key
|
||
);
|
||
|
||
create table test.trash_details(
|
||
id int primary key references test.trash(id),
|
||
jsonb_col jsonb
|
||
);
|
||
|
||
CREATE TABLE test.groups (
|
||
name text PRIMARY KEY
|
||
);
|
||
|
||
CREATE TABLE test.yards (
|
||
id bigint PRIMARY KEY
|
||
);
|
||
|
||
CREATE TABLE test.group_yard (
|
||
id bigint NOT NULL,
|
||
group_id text NOT NULL REFERENCES test.groups(name),
|
||
yard_id bigint NOT NULL REFERENCES test.yards(id),
|
||
PRIMARY KEY (id, group_id, yard_id)
|
||
);
|
||
|
||
CREATE FUNCTION test.get_yards() RETURNS SETOF test.yards
|
||
LANGUAGE sql
|
||
AS $$
|
||
select * from test.yards;
|
||
$$;
|
||
|
||
create table test.posters(
|
||
id int primary key,
|
||
name text
|
||
);
|
||
|
||
create table test.subscriptions(
|
||
subscriber int references test.posters(id),
|
||
subscribed int references test.posters(id),
|
||
primary key(subscriber, subscribed)
|
||
);
|
||
|
||
-- Data representations feature
|
||
DROP DOMAIN IF EXISTS public.color CASCADE;
|
||
CREATE DOMAIN public.color AS INTEGER CHECK (VALUE >= 0 AND VALUE <= 16777215);
|
||
|
||
CREATE OR REPLACE FUNCTION color(json) RETURNS public.color AS $$
|
||
SELECT color($1 #>> '{}');
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE OR REPLACE FUNCTION color(text) RETURNS public.color AS $$
|
||
SELECT (('x' || lpad((CASE WHEN SUBSTRING($1::text, 1, 1) = '#' THEN SUBSTRING($1::text, 2) ELSE $1::text END), 8, '0'))::bit(32)::int)::public.color;
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE OR REPLACE FUNCTION json(public.color) RETURNS json AS $$
|
||
SELECT
|
||
CASE WHEN $1 IS NULL THEN to_json(''::text)
|
||
ELSE to_json('#' || lpad(upper(to_hex($1)), 6, '0'))
|
||
END;
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE CAST (public.color AS json) WITH FUNCTION json(public.color) AS IMPLICIT;
|
||
CREATE CAST (json AS public.color) WITH FUNCTION color(json) AS IMPLICIT;
|
||
CREATE CAST (text AS public.color) WITH FUNCTION color(text) AS IMPLICIT;
|
||
|
||
DROP DOMAIN IF EXISTS public.isodate CASCADE;
|
||
CREATE DOMAIN public.isodate AS timestamp with time zone;
|
||
|
||
CREATE OR REPLACE FUNCTION isodate(json) RETURNS public.isodate AS $$
|
||
SELECT isodate($1 #>> '{}');
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE OR REPLACE FUNCTION isodate(text) RETURNS public.isodate AS $$
|
||
SELECT (replace($1, 'Z', '+00:00')::timestamp with time zone)::public.isodate;
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE OR REPLACE FUNCTION json(public.isodate) RETURNS json AS $$
|
||
SELECT to_json(replace(to_json($1)#>>'{}', '+00:00', 'Z'));
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE CAST (public.isodate AS json) WITH FUNCTION json(public.isodate) AS IMPLICIT;
|
||
CREATE CAST (json AS public.isodate) WITH FUNCTION isodate(json) AS IMPLICIT;
|
||
-- We intentionally don't have this in order to test query string parsing doesn't try to fall back on JSON parsing.
|
||
-- CREATE CAST (text AS public.isodate) WITH FUNCTION isodate(text) AS IMPLICIT;
|
||
|
||
-- bytea_b64 is a base64-encoded binary string
|
||
DROP DOMAIN IF EXISTS public.bytea_b64 CASCADE;
|
||
CREATE DOMAIN public.bytea_b64 AS bytea;
|
||
|
||
CREATE OR REPLACE FUNCTION bytea_b64(json) RETURNS public.bytea_b64 AS $$
|
||
SELECT bytea_b64($1 #>> '{}');
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE OR REPLACE FUNCTION bytea_b64(text) RETURNS public.bytea_b64 AS $$
|
||
-- allow unpadded base64
|
||
SELECT decode($1 || repeat('=', 4 - (length($1) % 4)), 'base64')::public.bytea_b64;
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE OR REPLACE FUNCTION json(public.bytea_b64) RETURNS json AS $$
|
||
SELECT to_json(translate(encode($1, 'base64'), E'\n', ''));
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE CAST (public.bytea_b64 AS json) WITH FUNCTION json(public.bytea_b64) AS IMPLICIT;
|
||
CREATE CAST (json AS public.bytea_b64) WITH FUNCTION bytea_b64(json) AS IMPLICIT;
|
||
CREATE CAST (text AS public.bytea_b64) WITH FUNCTION bytea_b64(text) AS IMPLICIT;
|
||
|
||
-- unixtz is a timestamptz represented as an integer number of seconds since the Unix epoch
|
||
DROP DOMAIN IF EXISTS public.unixtz CASCADE;
|
||
CREATE DOMAIN public.unixtz AS timestamp with time zone;
|
||
|
||
CREATE OR REPLACE FUNCTION unixtz(json) RETURNS public.unixtz AS $$
|
||
SELECT unixtz($1 #>> '{}');
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE OR REPLACE FUNCTION unixtz(text) RETURNS public.unixtz AS $$
|
||
SELECT (to_timestamp($1::numeric)::public.unixtz);
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE OR REPLACE FUNCTION json(public.unixtz) RETURNS json AS $$
|
||
SELECT to_json(extract(epoch from $1)::bigint);
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
|
||
CREATE CAST (public.unixtz AS json) WITH FUNCTION json(public.unixtz) AS IMPLICIT;
|
||
CREATE CAST (json AS public.unixtz) WITH FUNCTION unixtz(json) AS IMPLICIT;
|
||
CREATE CAST (text AS public.unixtz) WITH FUNCTION unixtz(text) AS IMPLICIT;
|
||
|
||
DROP DOMAIN IF EXISTS public.monetary CASCADE;
|
||
CREATE DOMAIN public.monetary AS numeric(17,2);
|
||
|
||
CREATE OR REPLACE FUNCTION monetary(json) RETURNS public.monetary AS $$
|
||
SELECT monetary($1 #>> '{}');
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE OR REPLACE FUNCTION monetary(text) RETURNS public.monetary AS $$
|
||
SELECT ($1::numeric)::public.monetary;
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE OR REPLACE FUNCTION json(public.monetary) RETURNS json AS $$
|
||
SELECT to_json($1::text);
|
||
$$ LANGUAGE SQL IMMUTABLE;
|
||
|
||
CREATE CAST (public.monetary AS json) WITH FUNCTION json(public.monetary) AS IMPLICIT;
|
||
CREATE CAST (json AS public.monetary) WITH FUNCTION monetary(json) AS IMPLICIT;
|
||
CREATE CAST (text AS public.monetary) WITH FUNCTION monetary(text) AS IMPLICIT;
|
||
|
||
CREATE TABLE datarep_todos (
|
||
id bigint primary key,
|
||
name text,
|
||
label_color public.color default 0,
|
||
due_at public.isodate default '2018-01-01'::date,
|
||
icon_image public.bytea_b64,
|
||
created_at public.unixtz default '2017-12-14 01:02:30'::timestamptz,
|
||
budget public.monetary default 0
|
||
);
|
||
|
||
CREATE TABLE datarep_next_two_todos (
|
||
id bigint primary key,
|
||
first_item_id bigint references datarep_todos(id),
|
||
second_item_id bigint references datarep_todos(id),
|
||
name text
|
||
);
|
||
|
||
CREATE VIEW datarep_todos_computed as (
|
||
SELECT id,
|
||
name,
|
||
label_color,
|
||
due_at,
|
||
(label_color / 2)::public.color as dark_color
|
||
FROM datarep_todos
|
||
);
|
||
|
||
-- view's name is alphabetically before projects
|
||
create view test.alpha_projects as
|
||
select c.id, p.name as pro_name, c.name as cli_name
|
||
from projects p join clients c on p.client_id = c.id;
|
||
|
||
-- view's name is alphabetically after projects
|
||
create view test.zeta_projects as
|
||
select c.id, p.name as pro_name, c.name as cli_name
|
||
from projects p join clients c on p.client_id = c.id;
|
||
|
||
CREATE VIEW test.complex_items_view AS
|
||
SELECT * FROM test.complex_items;
|
||
|
||
ALTER VIEW test.complex_items_view ALTER COLUMN name SET DEFAULT 'Default';
|
||
|
||
create table test.tbl_w_json(
|
||
id int,
|
||
data json
|
||
);
|
||
|
||
DO $do$
|
||
BEGIN
|
||
IF current_setting('server_version_num')::INT >= 100000 THEN
|
||
CREATE TABLE test.channels (
|
||
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||
data jsonb DEFAULT '{"foo": "bar"}',
|
||
slug text
|
||
);
|
||
END IF;
|
||
END
|
||
$do$;
|
||
|
||
CREATE FUNCTION test.is_superuser() RETURNS boolean
|
||
LANGUAGE sql
|
||
AS $$
|
||
select current_setting('is_superuser')::boolean;
|
||
$$;
|
||
|
||
DO $do$
|
||
BEGIN
|
||
IF current_setting('server_version_num')::INT >= 120000 THEN
|
||
CREATE TABLE test.foo (
|
||
a text,
|
||
b text GENERATED ALWAYS AS (
|
||
case WHEN a = 'telegram' THEN 'im'
|
||
WHEN a = 'proton' THEN 'email'
|
||
WHEN a = 'infinity' THEN 'idea'
|
||
ELSE 'bad idea'
|
||
end) stored
|
||
);
|
||
END IF;
|
||
END
|
||
$do$;
|
||
|
||
create domain devil_int as int
|
||
default 666;
|
||
|
||
create table evil_friends(
|
||
id devil_int
|
||
, name text
|
||
);
|
||
|
||
create table evil_friends_with_column_default(
|
||
id devil_int default 420
|
||
, name text
|
||
);
|
||
|
||
create table bets (
|
||
id int
|
||
, data_json json
|
||
, data_jsonb jsonb
|
||
);
|
||
|
||
create index bets_data_json on bets ((data_json ->>'contractId'));
|
||
create index bets_data_jsonb on bets ((data_jsonb ->>'contractId'));
|
||
|
||
--- https://github.com/PostgREST/postgrest/issues/2862
|
||
create table profiles (
|
||
id uuid primary key,
|
||
username text null
|
||
);
|
||
|
||
create table user_friend (
|
||
id bigint primary key,
|
||
user1 uuid references profiles (id),
|
||
user2 uuid references profiles (id)
|
||
);
|
||
|
||
create table status(
|
||
id bigint primary key
|
||
);
|
||
|
||
create table tournaments(
|
||
id bigint primary key,
|
||
status bigint references status(id)
|
||
);
|
||
|
||
-- https://github.com/PostgREST/postgrest/issues/2861
|
||
CREATE TABLE bitchar_with_length (
|
||
bit bit(5),
|
||
char char(5),
|
||
bit_arr bit(5)[],
|
||
char_arr char(5)[]
|
||
);
|
||
|
||
-- https://github.com/PostgREST/postgrest/issues/1586
|
||
create or replace function char_param_select(char_ char(4), char_arr char(4)[])
|
||
returns table(char_ char, char_arr char[]) as $$
|
||
select $1, $2;
|
||
$$ language sql;
|
||
|
||
create or replace function bit_param_select(bit_ char(4), bit_arr char(4)[])
|
||
returns table(bit_ char, bit_arr char[]) as $$
|
||
select $1, $2;
|
||
$$ language sql;
|
||
|
||
create or replace function char_param_insert(char_ char(4), char_arr char(4)[])
|
||
returns void as $$
|
||
insert into bitchar_with_length(char, char_arr) values($1, $2);
|
||
$$ language sql;
|
||
|
||
create or replace function bit_param_insert(bit_ bit(4), bit_arr bit(4)[])
|
||
returns void as $$
|
||
insert into bitchar_with_length(bit, bit_arr) values($1, $2);
|
||
$$ language sql;
|
||
|
||
create function returns_record() returns record as $$
|
||
select * from projects limit 1;
|
||
$$ language sql;
|
||
|
||
create function returns_record_params(id int, name text) returns record as $$
|
||
select * from projects p where p.id = $1 and p.name like $2;
|
||
$$ language sql;
|
||
|
||
create function returns_setof_record() returns setof record as $$
|
||
select * from projects limit 2;
|
||
$$ language sql;
|
||
|
||
create function returns_setof_record_params(id int, name text) returns setof record as $$
|
||
select * from projects p where p.id >= $1 and p.name like $2;
|
||
$$ language sql;
|
||
|
||
create function raise_sqlstate_test1() returns void
|
||
language plpgsql
|
||
as $$
|
||
begin
|
||
raise sqlstate 'PGRST' USING
|
||
message = '{"code":"123","message":"ABC","details":"DEF","hint":"XYZ"}',
|
||
detail = '{"status":332,"status_text":"My Custom Status","headers":{"X-Header":"str"}}';
|
||
end
|
||
$$;
|
||
|
||
create function raise_sqlstate_test2() returns void
|
||
language plpgsql
|
||
as $$
|
||
begin
|
||
raise sqlstate 'PGRST' USING
|
||
message = '{"code":"123","message":"ABC"}',
|
||
detail = '{"status":332,"headers":{"X-Header":"str"}}';
|
||
end
|
||
$$;
|
||
|
||
create function raise_sqlstate_test3() returns void
|
||
language plpgsql
|
||
as $$
|
||
begin
|
||
raise sqlstate 'PGRST' USING
|
||
message = '{"code":"123","message":"ABC"}',
|
||
detail = '{"status":404,"headers":{"X-Header":"str"}}';
|
||
end
|
||
$$;
|
||
|
||
create function raise_sqlstate_test4() returns void
|
||
language plpgsql
|
||
as $$
|
||
begin
|
||
raise sqlstate 'PGRST' USING
|
||
message = '{"code":"123","message":"ABC"}',
|
||
detail = '{"status":404,"status_text":"My Not Found","headers":{"X-Header":"str"}}';
|
||
end
|
||
$$;
|
||
|
||
create function raise_sqlstate_invalid_json_message() returns void
|
||
language plpgsql
|
||
as $$
|
||
begin
|
||
raise sqlstate 'PGRST' USING
|
||
message = 'INVALID',
|
||
detail = '{"status":332,"headers":{"X-Header":"str"}}';
|
||
end
|
||
$$;
|
||
|
||
create function raise_sqlstate_invalid_json_details() returns void
|
||
language plpgsql
|
||
as $$
|
||
begin
|
||
raise sqlstate 'PGRST' USING
|
||
message = '{"code":"123","message":"ABC","details":"DEF"}',
|
||
detail = 'INVALID';
|
||
end
|
||
$$;
|
||
|
||
create function raise_sqlstate_missing_details() returns void
|
||
language plpgsql
|
||
as $$
|
||
begin
|
||
raise sqlstate 'PGRST' USING
|
||
message = '{"code":"123","message":"ABC","details":"DEF"}';
|
||
end
|
||
$$;
|
||
|
||
create table table_a (
|
||
id int primary key,
|
||
name text
|
||
);
|
||
|
||
create table table_b (
|
||
table_a_id int references table_a(id),
|
||
name text
|
||
);
|
||
|
||
create or replace function test.returns_complex()
|
||
returns table(id int, val complex) as $$
|
||
select 1, row(0.1, 0.5)::complex as val
|
||
union
|
||
select 2, row(0.2, 0.6)::complex as val
|
||
union
|
||
select 3, row(0.3, 0.7)::complex as val;
|
||
$$ language sql;
|
||
|
||
create function computed_rel_overload(items) returns setof items2 as $$
|
||
select * from items2 limit 1
|
||
$$ language sql;
|
||
|
||
create function computed_rel_overload(items2) returns setof items2 as $$
|
||
select * from items2 limit 2
|
||
$$ language sql;
|
||
|
||
create function search2(id bigint) returns setof items2
|
||
language plpgsql
|
||
stable
|
||
as $$ begin
|
||
return query select items2.id from items2 where items2.id=search2.id;
|
||
end$$;
|
||
|
||
create table test.lines (
|
||
id int primary key
|
||
, name text
|
||
, geom extensions.geometry(LINESTRING, 4326)
|
||
);
|
||
|
||
create or replace function test.get_lines ()
|
||
returns setof test.lines as $$
|
||
select * from lines;
|
||
$$ language sql;
|
||
|
||
create or replace function test.get_line (id int)
|
||
returns "application/vnd.twkb" as $$
|
||
select extensions.st_astwkb(geom)::"application/vnd.twkb" from lines where id = get_line.id;
|
||
$$ language sql;
|
||
|
||
create or replace function test.get_shop_bles ()
|
||
returns setof test.shop_bles as $$
|
||
select * from shop_bles;
|
||
$$ language sql;
|
||
|
||
-- it can work without a final function too if the stype is already the media type
|
||
create or replace function test.twkb_handler_transition (state "application/vnd.twkb", next test.lines)
|
||
returns "application/vnd.twkb" as $$
|
||
select (state || extensions.st_astwkb(next.geom)) :: "application/vnd.twkb";
|
||
$$ language sql;
|
||
|
||
drop aggregate if exists test.twkb_agg(test.lines);
|
||
create aggregate test.twkb_agg (test.lines) (
|
||
initcond = ''
|
||
, stype = "application/vnd.twkb"
|
||
, sfunc = test.twkb_handler_transition
|
||
);
|
||
|
||
create or replace function test.geo2json_trans (state "application/vnd.geo2+json", next anyelement)
|
||
returns "application/vnd.geo2+json" as $$
|
||
select (state || extensions.ST_AsGeoJSON(next)::jsonb)::"application/vnd.geo2+json";
|
||
$$ language sql;
|
||
|
||
create or replace function test.geo2json_final (data "application/vnd.geo2+json")
|
||
returns "application/vnd.geo2+json" as $$
|
||
select (jsonb_build_object('type', 'FeatureCollection', 'hello', 'world'))::"application/vnd.geo2+json";
|
||
$$ language sql;
|
||
|
||
drop aggregate if exists test.geo2json_agg_any(anyelement);
|
||
create aggregate test.geo2json_agg_any(anyelement) (
|
||
initcond = '[]'
|
||
, stype = "application/vnd.geo2+json"
|
||
, sfunc = geo2json_trans
|
||
, finalfunc = geo2json_final
|
||
);
|
||
|
||
create or replace function test.geo2json_trans (state "application/vnd.geo2+json", next test.shop_bles)
|
||
returns "application/vnd.geo2+json" as $$
|
||
select '"anyelement overridden"'::"application/vnd.geo2+json";
|
||
$$ language sql;
|
||
|
||
drop aggregate if exists test.geo2json_agg(test.shop_bles);
|
||
create aggregate test.geo2json_agg(test.shop_bles) (
|
||
initcond = '[]'
|
||
, stype = "application/vnd.geo2+json"
|
||
, sfunc = geo2json_trans
|
||
);
|
||
|
||
create table ov_json ();
|
||
|
||
-- override application/json
|
||
create or replace function test.ov_json_trans (state "application/json", next ov_json)
|
||
returns "application/json" as $$
|
||
select null;
|
||
$$ language sql;
|
||
|
||
drop aggregate if exists test.ov_json_agg(ov_json);
|
||
create aggregate test.ov_json_agg(ov_json) (
|
||
initcond = '{"overridden": "true"}'
|
||
, stype = "application/json"
|
||
, sfunc = ov_json_trans
|
||
);
|
||
|
||
-- override application/geo+json
|
||
create or replace function test.lines_geojson_trans (state jsonb, next test.lines)
|
||
returns "application/geo+json" as $$
|
||
select (state || extensions.ST_AsGeoJSON(next)::jsonb)::"application/geo+json";
|
||
$$ language sql;
|
||
|
||
create or replace function test.lines_geojson_final (data jsonb)
|
||
returns "application/geo+json" as $$
|
||
select jsonb_build_object(
|
||
'type', 'FeatureCollection',
|
||
'crs', json_build_object(
|
||
'type', 'name',
|
||
'properties', json_build_object(
|
||
'name', 'EPSG:4326'
|
||
)
|
||
),
|
||
'features', data
|
||
)::"application/geo+json";
|
||
$$ language sql;
|
||
|
||
drop aggregate if exists test.lines_geojson_agg(test.lines);
|
||
create aggregate test.lines_geojson_agg (test.lines) (
|
||
initcond = '[]'
|
||
, stype = "application/geo+json"
|
||
, sfunc = lines_geojson_trans
|
||
, finalfunc = lines_geojson_final
|
||
);
|
||
|
||
-- override application/vnd.pgrst.object
|
||
create or replace function test.pgrst_obj_json_trans (state "application/vnd.pgrst.object", next anyelement)
|
||
returns "application/vnd.pgrst.object" as $$
|
||
select null;
|
||
$$ language sql;
|
||
|
||
drop aggregate if exists test.pgrst_obj_agg(anyelement);
|
||
create aggregate test.pgrst_obj_agg(anyelement) (
|
||
initcond = '{"overridden": "true"}'
|
||
, stype = "application/vnd.pgrst.object"
|
||
, sfunc = pgrst_obj_json_trans
|
||
);
|
||
|
||
-- create a "text/tab-separated-values" media type
|
||
create or replace function test.tsv_trans (state text, next test.projects)
|
||
returns "text/tab-separated-values" as $$
|
||
select (state || next.id::text || E'\t' || next.name || E'\t' || coalesce(next.client_id::text, '') || E'\n')::"text/tab-separated-values";
|
||
$$ language sql;
|
||
|
||
|
||
create or replace function test.tsv_final (data "text/tab-separated-values")
|
||
returns "text/tab-separated-values" as $$
|
||
select (E'id\tname\tclient_id\n' || data)::"text/tab-separated-values";
|
||
$$ language sql;
|
||
|
||
drop aggregate if exists test.tsv_agg(test.projects);
|
||
create aggregate test.tsv_agg (test.projects) (
|
||
initcond = ''
|
||
, stype = "text/tab-separated-values"
|
||
, sfunc = tsv_trans
|
||
, finalfunc = tsv_final
|
||
);
|
||
|
||
-- override CSV with BOM plus attachment
|
||
create or replace function test.bom_csv_trans (state text, next test.lines)
|
||
returns "text/csv" as $$
|
||
select (state || next.id::text || ',' || next.name || ',' || next.geom::text || E'\n')::"text/csv";
|
||
$$ language sql;
|
||
|
||
create or replace function test.bom_csv_final (data "text/csv")
|
||
returns "text/csv" as $$
|
||
select set_config('response.headers', '[{"Content-Disposition": "attachment; filename=\"lines.csv\""}]', true);
|
||
-- EFBBBF is the BOM in UTF8 https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8
|
||
select (convert_from (decode (E'EFBBBF', 'hex'),'UTF8') || (E'id,name,geom\n' || data))::"text/csv";
|
||
$$ language sql;
|
||
|
||
drop aggregate if exists test.bom_csv_agg(test.lines);
|
||
create aggregate test.bom_csv_agg (test.lines) (
|
||
initcond = ''
|
||
, stype = "text/csv"
|
||
, sfunc = bom_csv_trans
|
||
, finalfunc = bom_csv_final
|
||
);
|
||
|
||
create table empty_string as select 1 as id, ''::text as string;
|
||
|
||
create table timestamps (
|
||
t timestamp with time zone
|
||
);
|
||
|
||
create table project_invoices (
|
||
id int primary key
|
||
, invoice_total numeric
|
||
, project_id integer references projects(id)
|
||
);
|
||
|
||
create table budget_categories (
|
||
id int primary key
|
||
, category_name text
|
||
, budget_owner text
|
||
, budget_amount numeric
|
||
);
|
||
|
||
create table budget_expenses (
|
||
id int primary key
|
||
, expense_amount numeric
|
||
, budget_category_id integer references budget_categories(id)
|
||
);
|
||
|
||
create or replace function ret_any_mt ()
|
||
returns "*/*" as $$
|
||
select 'any'::"*/*";
|
||
$$ language sql;
|
||
|
||
create or replace function ret_some_mt ()
|
||
returns "*/*" as $$
|
||
declare
|
||
req_accept text := current_setting('request.headers', true)::json->>'accept';
|
||
resp bytea;
|
||
begin
|
||
case req_accept
|
||
when 'app/chico' then
|
||
perform set_config('response.headers', json_build_array(json_build_object('Content-Type', req_accept))::text, true);
|
||
resp := 'chico';
|
||
when 'app/harpo' then
|
||
perform set_config('response.headers', json_build_array(json_build_object('Content-Type', req_accept))::text, true);
|
||
resp := 'harpo';
|
||
when '*/*' then
|
||
perform set_config('response.headers', json_build_array(json_build_object('Content-Type', 'app/groucho'))::text, true);
|
||
resp := 'groucho';
|
||
else
|
||
raise sqlstate 'PT406' using message = 'Not Acceptable';
|
||
end case;
|
||
return resp;
|
||
end; $$ language plpgsql;
|
||
|
||
create table some_numbers as select x::int as val from generate_series(1,10) x;
|
||
|
||
create or replace function some_trans (state "*/*", next some_numbers)
|
||
returns "*/*" as $$
|
||
select (state || E'\n' || next.val::text::bytea)::"*/*";
|
||
$$ language sql;
|
||
|
||
create or replace function some_final (data "*/*")
|
||
returns "*/*" as $$
|
||
declare
|
||
req_accept text := current_setting('request.headers', true)::json->>'accept';
|
||
prefix bytea;
|
||
begin
|
||
case req_accept
|
||
when 'magic/number' then
|
||
perform set_config('response.headers', json_build_array(json_build_object('Content-Type', req_accept))::text, true);
|
||
prefix := 'magic';
|
||
when 'crazy/bingo' then
|
||
perform set_config('response.headers', json_build_array(json_build_object('Content-Type', req_accept))::text, true);
|
||
prefix := 'crazy';
|
||
else
|
||
prefix := 'anything';
|
||
end case;
|
||
return (prefix || data)::"*/*";
|
||
end; $$ language plpgsql;
|
||
|
||
drop aggregate if exists some_agg (some_numbers);
|
||
create aggregate test.some_agg (some_numbers) (
|
||
initcond = ''
|
||
, stype = "*/*"
|
||
, sfunc = some_trans
|
||
, finalfunc = some_final
|
||
);
|
||
|
||
create view bad_subquery as
|
||
select * from projects where id = (select id from projects);
|
||
|
||
-- custom generic mimetype
|
||
create domain "pg/outfunc" as text;
|
||
create function test.outfunc_trans (state text, next anyelement)
|
||
returns "pg/outfunc" as $$
|
||
select (state || next::text || E'\n')::"pg/outfunc";
|
||
$$ language sql;
|
||
|
||
create aggregate test.outfunc_agg (anyelement) (
|
||
initcond = ''
|
||
, stype = "pg/outfunc"
|
||
, sfunc = outfunc_trans
|
||
);
|
||
|
||
-- used for manual testing
|
||
create or replace function test.sleep(seconds double precision default 5) returns void as $$
|
||
select pg_sleep(seconds);
|
||
$$ language sql;
|
||
|
||
-- https://github.com/PostgREST/postgrest/issues/3256
|
||
create view test.infinite_recursion as
|
||
select * from test.projects;
|
||
|
||
create or replace view test.infinite_recursion as
|
||
select * from test.infinite_recursion;
|
||
|
||
|
||
create or replace function temp_file_limit()
|
||
returns bigint as $$
|
||
select COUNT(*) FROM generate_series('-infinity'::TIMESTAMP, 'epoch'::TIMESTAMP, INTERVAL '1 DAY');
|
||
$$ language sql security definer set temp_file_limit to '1kB';
|
||
|
||
-- https://github.com/PostgREST/postgrest/issues/3255
|
||
create table test.infinite_inserts(
|
||
id int
|
||
, name text
|
||
);
|
||
|
||
create or replace function infinite_inserts()
|
||
returns trigger as $$ begin
|
||
insert into infinite_inserts values (NEW.id, NEW.name);
|
||
end $$ language plpgsql;
|
||
|
||
create trigger do_infinite_inserts
|
||
after insert
|
||
on infinite_inserts
|
||
for each row
|
||
execute procedure infinite_inserts();
|