Previously using a generic mimetype handler failed when any kind of select= was given, because we tried to cast the select-result to the original table type. With this change, this cast is only applied when select=* is given implicitly or explicitly. This is the only case where this makes sense, because this guarantees that correct columns are selected in the correct order for this cast to succeed. Resolves #3160
3771 lines
99 KiB
PL/PgSQL
3771 lines
99 KiB
PL/PgSQL
--
|
|
-- PostgreSQL database dump
|
|
--
|
|
|
|
-- Dumped from database version 9.5beta1
|
|
-- Dumped by pg_dump version 9.5beta1
|
|
|
|
SET statement_timeout = 0;
|
|
SET lock_timeout = 0;
|
|
SET client_encoding = 'UTF8';
|
|
SET standard_conforming_strings = on;
|
|
SET check_function_bodies = false;
|
|
SET client_min_messages = warning;
|
|
|
|
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 (id, code) references test.students(id, code) 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 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
|
|
);
|