--- /dev/null
+\set ECHO none
+drop role if exists londiste_test_part1;
+drop role if exists londiste_test_part2;
+create group londiste_test_part1;
+create group londiste_test_part2;
+create table events (
+ id int4 primary key,
+ txt text not null,
+ ctime timestamptz not null default now(),
+ someval int4 check (someval > 0)
+);
+create index ctime_idx on events (ctime);
+create rule ignore_dups AS
+ on insert to events
+ where (exists (select 1 from events
+ where (events.id = new.id)))
+ do instead nothing;
+grant select,delete on events to londiste_test_part1;
+grant select,update,delete on events to londiste_test_part2 with grant option;
+grant select,insert on events to public;
+select londiste.create_partition('events', 'events_2011_01', 'id', 'ctime', '2011-01-01', 'month');
+ create_partition
+------------------
+ 1
+(1 row)
+
+select londiste.create_partition('events', 'events_2011_01', 'id', 'ctime', '2011-01-01'::timestamptz, 'month');
+ create_partition
+------------------
+ 0
+(1 row)
+
+select londiste.create_partition('events', 'events_2011_01', 'id', 'ctime', '2011-01-01'::timestamp, 'month');
+ create_partition
+------------------
+ 0
+(1 row)
+
+select count(*) from pg_indexes where schemaname='public' and tablename = 'events_2011_01';
+ count
+-------
+ 2
+(1 row)
+
+select count(*) from pg_constraint where conrelid = 'public.events_2011_01'::regclass;
+ count
+-------
+ 3
+(1 row)
+
+select count(*) from pg_rules where schemaname = 'public' and tablename = 'events_2011_01';
+ count
+-------
+ 1
+(1 row)
+
+-- test weird quoting
+create table "Bad "" table '.' name!" (
+ id int4 primary key,
+ txt text not null,
+ ctime timestamptz not null default now(),
+ someval int4 check (someval > 0)
+);
+create rule "Ignore Dups" AS
+ on insert to "Bad "" table '.' name!"
+ where (exists (select 1 from "Bad "" table '.' name!"
+ where ("Bad "" table '.' name!".id = new.id)))
+ do instead nothing;
+alter table "Bad "" table '.' name!" ENABLE ALWAYS RULE "Ignore Dups";
+select londiste.create_partition('public.Bad " table ''.'' name!', 'public.Bad " table ''.'' part!', 'id', 'ctime', '2011-01-01', 'month');
+ create_partition
+------------------
+ 1
+(1 row)
+
+select count(*) from pg_rules where schemaname = 'public' and tablename ilike 'bad%';
+ count
+-------
+ 2
+(1 row)
+
+-- \d events_2011_01
+-- \dp events
+-- \dp events_2011_01
-- Creates child table for aggregation function for either monthly or daily if it does not exist yet.
-- Locks parent table for child table creating.
--
+-- Problem:
+-- Grants and rules should be part of CREATE TABLE x (LIKE y INCLUDING ALL)'.
+--
-- Parameters:
-- i_table - name of parent table
-- i_part - name of partition table to create
r record;
sql text;
pgver integer;
+ r_oldtbl text;
+ r_extra text;
+ r_sql text;
begin
if i_table is null or i_part is null then
raise exception 'need table and part';
-- copy rules
for r in
- select rulename, definition,
- substring(definition from ' TO (([a-z0-9._]+|"([^"]+|"")+")+)') as oldtbl
- from pg_catalog.pg_rules
- where schemaname = parent_schema
- and tablename = parent_name
+ select rw.rulename, rw.ev_enabled, pg_get_ruledef(rw.oid) as definition
+ from pg_catalog.pg_rewrite rw
+ where rw.ev_class = fq_table::regclass::oid
+ and rw.rulename <> '_RETURN'::name
loop
- sql := replace(r.definition, r.oldtbl, fq_part);
+ -- try to skip rule name
+ r_extra := 'CREATE RULE ' || quote_ident(r.rulename) || ' AS';
+ r_sql := substr(r.definition, 1, char_length(r_extra));
+ if r_sql = r_extra then
+ r_sql := substr(r.definition, char_length(r_extra));
+ else
+ raise exception 'failed to match rule name';
+ end if;
+
+ -- no clue what name was used in defn, so find it from sql
+ r_oldtbl := substring(r_sql from ' TO (([[:alnum:]_.]+|"([^"]+|"")+")+)[[:space:]]');
+ if char_length(r_oldtbl) > 0 then
+ sql := replace(r.definition, r_oldtbl, fq_part);
+ else
+ raise exception 'failed to find original table name';
+ end if;
execute sql;
+
+ -- rule flags
+ r_extra := NULL;
+ if r.ev_enabled = 'R' then
+ r_extra = ' ENABLE REPLICA RULE ';
+ elsif r.ev_enabled = 'A' then
+ r_extra = ' ENABLE ALWAYS RULE ';
+ elsif r.ev_enabled = 'D' then
+ r_extra = ' DISABLE RULE ';
+ elsif r.ev_enabled <> 'O' then
+ raise exception 'unknown rule option: %', r.ev_enabled;
+ end if;
+ if r_extra is not null then
+ sql := 'ALTER TABLE ' || fq_part || r_extra
+ || quote_ident(r.rulename);
+ end if;
end loop;
return 1;
--- /dev/null
+
+
+\set ECHO none
+set log_error_verbosity = 'terse';
+set client_min_messages = 'warning';
+\set ECHO all
+
+drop role if exists londiste_test_part1;
+drop role if exists londiste_test_part2;
+create group londiste_test_part1;
+create group londiste_test_part2;
+
+create table events (
+ id int4 primary key,
+ txt text not null,
+ ctime timestamptz not null default now(),
+ someval int4 check (someval > 0)
+);
+create index ctime_idx on events (ctime);
+
+create rule ignore_dups AS
+ on insert to events
+ where (exists (select 1 from events
+ where (events.id = new.id)))
+ do instead nothing;
+
+
+
+grant select,delete on events to londiste_test_part1;
+grant select,update,delete on events to londiste_test_part2 with grant option;
+grant select,insert on events to public;
+
+select londiste.create_partition('events', 'events_2011_01', 'id', 'ctime', '2011-01-01', 'month');
+select londiste.create_partition('events', 'events_2011_01', 'id', 'ctime', '2011-01-01'::timestamptz, 'month');
+select londiste.create_partition('events', 'events_2011_01', 'id', 'ctime', '2011-01-01'::timestamp, 'month');
+
+select count(*) from pg_indexes where schemaname='public' and tablename = 'events_2011_01';
+select count(*) from pg_constraint where conrelid = 'public.events_2011_01'::regclass;
+select count(*) from pg_rules where schemaname = 'public' and tablename = 'events_2011_01';
+
+-- test weird quoting
+
+create table "Bad "" table '.' name!" (
+ id int4 primary key,
+ txt text not null,
+ ctime timestamptz not null default now(),
+ someval int4 check (someval > 0)
+);
+create rule "Ignore Dups" AS
+ on insert to "Bad "" table '.' name!"
+ where (exists (select 1 from "Bad "" table '.' name!"
+ where ("Bad "" table '.' name!".id = new.id)))
+ do instead nothing;
+alter table "Bad "" table '.' name!" ENABLE ALWAYS RULE "Ignore Dups";
+select londiste.create_partition('public.Bad " table ''.'' name!', 'public.Bad " table ''.'' part!', 'id', 'ctime', '2011-01-01', 'month');
+select count(*) from pg_rules where schemaname = 'public' and tablename ilike 'bad%';
+
+-- \d events_2011_01
+-- \dp events
+-- \dp events_2011_01
+