handlers.dispatch: Move grants into sql function
authorMarko Kreen <markokr@gmail.com>
Fri, 30 Dec 2011 11:51:37 +0000 (13:51 +0200)
committerMarko Kreen <markokr@gmail.com>
Fri, 30 Dec 2011 11:51:37 +0000 (13:51 +0200)
The grants can be loaded via information_schema,
thus no need to do it in Python.

python/londiste/handlers/dispatch.py
sql/dispatch/create_partition.sql
sql/dispatch/expected/test_create_part.out
sql/dispatch/sql/test_create_part.sql

index 8954d2bfeb4fdb0817040ec7b843f0ee8dadf781..95d08e726e0c5f2cf10ed60b0d6fb5ec3fc8c5f9 100644 (file)
@@ -886,10 +886,6 @@ class Dispatcher(BaseHandler):
             if skytools.exists_function(curs, self.conf.part_func, len(PART_FUNC_ARGS)):
                 self.log.debug('check_part.exec: func:%s, args: %s' % (pfcall, vals))
                 curs.execute(pfcall, vals)
-
-                # load grants from master table
-                struct = TableStruct(curs, self.dest_table)
-                struct.create(curs, T_GRANT, dst)
             else:
                 self.log.debug('part func %s not found, cloning table' % self.conf.part_func)
                 struct = TableStruct(curs, self.dest_table)
index cfe7225089d0ff460572d3bffafe1034287b8dd7..bd2c851681c9c4b1860e7fd5019e94632339de39 100644 (file)
@@ -1,12 +1,5 @@
 -- drop old function with timestamp
-DROP FUNCTION IF EXISTS public.create_partition(
-    text,
-    text,
-    text,
-    text,
-    timestamp,
-    text
-);
+DROP FUNCTION IF EXISTS public.create_partition(text, text, text, text, timestamp, text);
 
 CREATE OR REPLACE FUNCTION public.create_partition(
     i_table text,
@@ -15,9 +8,7 @@ CREATE OR REPLACE FUNCTION public.create_partition(
     i_part_field text,
     i_part_time timestamptz,
     i_part_period text
-) RETURNS int
-AS $$
-
+) RETURNS int AS $$
 ------------------------------------------------------------------------
 -- Function: public.create_partition
 --
@@ -40,24 +31,30 @@ declare
     chk_start       text;
     chk_end         text;
     part_start      timestamptz;
-    table_schema    text;
-    table_name      text;
+    parent_schema   text;
+    parent_name     text;
     part_schema     text;
     part_name       text;
     pos             int4;
     fq_table        text;
     fq_part         text;
+    g               record;
+    sql             text;
+    pgver           integer;
 begin
+    -- load postgres version (XYYZZ).
+    show server_version_num into pgver;
+
     -- parent table schema and name + quoted name
     pos := position('.' in i_table);
     if pos > 0 then
-        table_schema := substring(i_table for pos - 1);
-        table_name := substring(i_table from pos + 1);
+        parent_schema := substring(i_table for pos - 1);
+        parent_name := substring(i_table from pos + 1);
     else
-        table_schema := 'public';
-        table_name := i_table;
+        parent_schema := 'public';
+        parent_name := i_table;
     end if;
-    fq_table := quote_ident(table_schema) || '.' || quote_ident(table_name);
+    fq_table := quote_ident(parent_schema) || '.' || quote_ident(parent_name);
 
     -- part table schema and name + quoted name
     pos := position('.' in i_part);
@@ -80,24 +77,46 @@ begin
           and t.relname = part_name;
     if found then
         return 0;
+    end if;
+
+    -- need to use 'like' to get indexes
+    sql := 'create table ' || fq_part || ' (like ' || fq_table;
+    if pgver >= 90000 then
+        sql := sql || ' including all';
     else
-        -- need to use 'like' to get indexes
-        execute 'create table ' || fq_part
-            || ' (like ' || fq_table || ' including indexes including constraints)'
-            -- || ' () '
-            || ' inherits (' || fq_table || ')';
+        sql := sql || ' including indexes including constraints';
+    end if;
+    sql := sql || ') inherits (' || fq_table || ')';
+    execute sql;
 
-        if i_part_field != '' then
-            part_start := date_trunc(i_part_period, i_part_time);
-            chk_start := to_char(part_start, 'YYYY-MM-DD HH24:MI:SS');
-            chk_end := to_char(part_start + ('1 '||i_part_period)::interval,
-                              'YYYY-MM-DD HH24:MI:SS');
-            execute 'alter table '|| fq_part ||' add check(' || i_part_field || ' >= '''
-            || chk_start ||''' and ' || i_part_field || ' < ''' || chk_end || ''')';
-        end if;
+    if i_part_field != '' then
+        part_start := date_trunc(i_part_period, i_part_time);
+        chk_start := to_char(part_start, 'YYYY-MM-DD HH24:MI:SS');
+        chk_end := to_char(part_start + ('1 '||i_part_period)::interval,
+                           'YYYY-MM-DD HH24:MI:SS');
+        sql := 'alter table '|| fq_part || ' add check('
+            || i_part_field || ' >= ''' || chk_start || ''' and '
+            || i_part_field || ' < ''' || chk_end || ''')';
+        execute sql;
     end if;
+
+    -- load grants from parent table
+    for g in
+        select grantor, grantee, privilege_type, is_grantable
+            from information_schema.table_privileges
+            where table_schema = parent_schema
+                and table_name = parent_name
+    loop
+        sql := 'grant ' || g.privilege_type || ' on ' || fq_part
+            || ' to ' || quote_ident(g.grantee);
+        if g.is_grantable = 'YES' and g.grantor <> g.grantee then
+            sql := sql || ' with grant option';
+        end if;
+        execute sql;
+    end loop;
+
     return 1;
 end;
 
-$$
-LANGUAGE plpgsql;
+$$ language plpgsql;
+
index 13dfb7c4a853f678a53cb49164397851ede34b20..20a9ef21f767b1df93ad856e88b8e65ddcc677b9 100644 (file)
@@ -1,4 +1,8 @@
 \set ECHO none
+drop role if exists ptest1;
+drop role if exists ptest2;
+create group ptest1;
+create group ptest2;
 create table events (
     id int4 primary key,
     txt text not null,
@@ -6,6 +10,8 @@ create table events (
     someval int4 check (someval > 0)
 );
 create index ctime_idx on events (ctime);
+grant select,delete on events to ptest1;
+grant select,update,delete on events to ptest2 with grant option;
 select create_partition('events', 'events_2011_01', 'id', 'ctime', '2011-01-01', 'month');
  create_partition 
 ------------------
@@ -37,3 +43,5 @@ select count(*) from pg_constraint where conrelid = 'public.events_2011_01'::reg
 (1 row)
 
 -- \d events_2011_01
+-- \dp events
+-- \dp events_2011_01
index f04a9eff719b7d34f62cc1b81901d90fc36c1e5e..71a552a1c2048b591be4c18aee9c85b87305a932 100644 (file)
@@ -7,6 +7,11 @@ set client_min_messages = 'warning';
 \i create_partition.sql
 \set ECHO all
 
+drop role if exists ptest1;
+drop role if exists ptest2;
+create group ptest1;
+create group ptest2;
+
 create table events (
     id int4 primary key,
     txt text not null,
@@ -15,6 +20,9 @@ create table events (
 );
 create index ctime_idx on events (ctime);
 
+grant select,delete on events to ptest1;
+grant select,update,delete on events to ptest2 with grant option;
+
 select create_partition('events', 'events_2011_01', 'id', 'ctime', '2011-01-01', 'month');
 select create_partition('events', 'events_2011_01', 'id', 'ctime', '2011-01-01'::timestamptz, 'month');
 
@@ -24,4 +32,6 @@ select count(*) from pg_indexes where schemaname='public' and tablename = 'event
 select count(*) from pg_constraint where conrelid = 'public.events_2011_01'::regclass;
 
 -- \d events_2011_01
+-- \dp events
+-- \dp events_2011_01