--
-- 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';

--
-- 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'
);


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 = case when current_setting('server_version_num')::int >= 140000
              then current_setting('request.jwt.claims')::json->>'id'
              else current_setting('request.jwt.claim.id')
              end;
  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 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 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 = case when current_setting('server_version_num')::int >= 140000
            then (current_setting('request.jwt.claims')::json->>'id')::text
            else current_setting('request.jwt.claim.id')::text
            end;
  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
    )
    LANGUAGE plpgsql SECURITY DEFINER
    STABLE
    AS $$
    BEGIN
    -- JWT claims are set in JSON format since v14
    IF (current_setting('server_version_num')::INT >= 140000) THEN
        RETURN QUERY
        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";
    ELSE
        RETURN QUERY
        SELECT current_setting('request.jwt.claim.iss') as iss,
               current_setting('request.jwt.claim.sub') as sub,
               current_setting('request.jwt.claim.exp')::bigint as exp,
               current_setting('request.jwt.claim.nbf')::bigint as nbf,
               current_setting('request.jwt.claim.iat')::bigint as iat,
               current_setting('request.jwt.claim.jti') as jti,
               current_setting('request.jwt.claim.http://postgrest.com/foo')::boolean
                 as "http://postgrest.com/foo";
    END IF;
END;
$$;


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_base64_bin() returns text as $$
  select i.img from test.images_base64 i where i.name = 'A.png';
$$ language sql;

create function test.ret_rows_with_base64_bin() returns setof test.images_base64 as $$
  select i.name, i.img from test.images_base64 i;
$$ 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 GUC values for Postgres v14.0 and up
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
);

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 json as $_$
declare
openapi json = $$
  {
    "swagger": "2.0",
    "info":{
      "title":"PostgREST API",
      "description":"This is a dynamic API generated by PostgREST"
    }
  }
$$;
accept text;
begin
accept = case when current_setting('server_version_num')::int >= 140000
         then current_setting('request.headers', true)::json->>'accept'
         else current_setting('request.header.accept', true)
         end;
case accept
  when 'application/openapi+json' then
    return openapi;
  when 'application/json' then
    return (current_setting('request.spec', true)::json)->'dbRelationships'->0->0;
  else
    return openapi;
  end case;
end
$_$ language plpgsql;

create or replace function welcome() returns text as $$
select 'Welcome to PostgREST'::text;
$$ language sql;

create or replace function welcome_twice() returns setof text as $$
select 'Welcome to PostgREST'
union all
select 'Welcome to PostgREST';
$$ language sql;

create or replace function "welcome.html"() returns text as $_$
select $$
<html>
  <head>
    <title>PostgREST</title>
  </head>
  <body>
    <h1>Welcome to PostgREST</h1>
  </body>
</html>
$$::text;
$_$ 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 := case when current_setting('server_version_num')::int >= 140000
                     then current_setting('request.headers', true)::json->>'user-agent'
                     else current_setting('request.header.user-agent', true)
                     end;
  req_path   text := current_setting('request.path', true);
  req_accept text := case when current_setting('server_version_num')::int >= 140000
                     then current_setting('request.headers', true)::json->>'accept'
                     else current_setting('request.header.accept', true)
                     end;
  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 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 as $$
  select $1;
$$ language sql;

create or replace function test.unnamed_xml_param(pg_catalog.xml) returns pg_catalog.xml as $$
  select $1;
$$ language sql;

create or replace function test.unnamed_bytea_param(bytea) returns bytea as $$
  select $1::bytea;
$$ 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 bytea as $$
select $1;
$$ language sql;

create or replace function test.overloaded_unnamed_param(text) returns text as $$
select $1;
$$ 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 pg_catalog.xml
LANGUAGE sql AS $$
  SELECT '<my-xml-tag/>'::pg_catalog.xml
$$;

CREATE OR REPLACE FUNCTION "welcome.xml"() RETURNS pg_catalog.xml
LANGUAGE sql AS $_$
select $$
<html>
  <head>
    <title>PostgREST</title>
  </head>
  <body>
    <h1>Welcome to PostgREST</h1>
  </body>
</html>$$::pg_catalog.xml;
$_$;

CREATE TABLE test.xmltest (
    id integer primary key,
    xml pg_catalog.xml NOT NULL
);

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;

CREATE TABLE designers (
  id int primary key
, name text
);

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
);
