[HACKERS] [HACHERS] privilege check: column level only?

2007-06-04 Thread Golden Liu

Hello

I'm one of the Google SoC's students for PostgreSQL. While reading sql92
standard, I found something like this:

11.36  
General Rules
3) For every identified privilege descriptor whose action is
   SELECT, INSERT, UPDATE, or REFERENCES without a column name,
   privilege descriptors are also created for each column C in O
   for which A holds the corresponding privilege with grant op-
   tion. For each such column, a privilege descriptor is created
   that specifies the identical , the identical ,
   object C, and grantor A.

According to this, column privilege descriptors are created automatically
while table privilege descriptor is created. Then, while checking privilege,
can I JUST check column level privilege?

Here is some examples.

(1)
  CREATE TABLE t1 (c1 int, c2 int);
  GRANT SELECT ON t1 TO grantee;
  REVOKE SELECT ON t1 (c1) FROM grantee;
  Now grantee has privilege on t1(c2) but NOT on t1(c1). Although grantee
has privilege on t1, he still has no privilege on t1(c1). So checking column
privilege is enough. We don't need to check table privilege.
(2)
  CREATE TABLE t1 (c1 int, c2 int);
  REVOKE SELECT ON t1 FROM grantee;
  GRANT SELECT ON t1(c2) TO grantee;
  Here, still, grantee has privilege on t1(c2) but NOT on t1(c1). (Is this
right?) Although grantee has no privilege on t1, he can has privilege on
t1(c1). Here, again, checking column privilege is enough.

Table privilege is useful when you add columns to a table. Whether grantee
has privilege on the new columns depends on whether he has privilege on the
table.

Any and all help and/or comment is appreciated. From sql standard, I found
no information on how privilege check should be done.

Thanks.
Dong

--
Guodong Liu
Database Lab, School of EECS, Peking University
Room 314, Building 42, Peking University, Beijing, 100871, China


Re: [HACKERS] Google SoC: column-level privilege subsystem

2007-04-24 Thread Golden Liu

Dear August

Thank you for your reply.

On 4/25/07, August Zajonc <[EMAIL PROTECTED]> wrote:

Golden Liu wrote:
> 3. Before evaluating a SQL command, check column-level privilege.
> This is done AFTER checking table-level privilege. As I mentioned
> before, if table-level privilege is granted, it's not necessary to
> check column-level privilege.

Golden, this sounds good. I'm just a user.

It sounds like table || column is the check, so table implies all of
columns. ie, revoking a column permission does nothing unless TABLE
permission is also revoked.

It also might be nice to specify some of the failure / usage modes.

ie, how does "SELECT * FROM Students" work if I don't have permission to
a column. Return all values except for forbidden ones? How does "SELECT
ForbiddenColumn FROM Students" work.


For "SELECT * FROM Students", I think this will just raise an error.
In PG, if you commit a command like "SELECT * FROM T1, T2" but do not
have permission to T2, PG will raise an error. For column, we should
do the same thing.
"SELECT ForbiddenColumn FROM Students" will raise an error too.


For INSERTS, they probably need to fail if you don't have permission to
non-null columns. What about columns with default values? Are inserts
permitted if you don't have permission to a column with default values?


For INSERTS, privilege check will just do on columns specified. For
table T with two columns, say C1 and C2, and C2 has a default value.
If you just have INSERT permission on C1, this will be right:
   INSERT INTO T(C1) VALUES (V1)
since you just specified C1. But this will raise an error:
   INSERT INTO T VALUES (V1, default)
since you specified C2 which you do not have permission to insert into.


Do you have a project page up somewhere? I wouldn't mind helping with
some of the documentation for example.

Good luck!

- August





Golden

---(end of broadcast)---
TIP 9: In versions below 8.0, the planner will ignore your desire to
  choose an index scan if your joining column's datatypes do not
  match


[HACKERS] Google SoC: column-level privilege subsystem

2007-04-24 Thread Golden Liu

Hi all,

I'm one of the Google SoC's students for PostgreSQL. My project is
to implement column-level privilege in PG. Here is a description of my
project. Any and all help and/or comment is appreciated.

Table-level privilege subsystem in PG is now used like this:
GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER }
  [,...] | ALL [ PRIVILEGES ] }
  ON [ TABLE ] tablename [, ...]
  TO { username | GROUP groupname | PUBLIC } [, ...] [ WITH GRANT OPTION ]
REVOKE [ GRANT OPTION FOR ]
  { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER }
  [,...] | ALL [ PRIVILEGES ] }
  ON [ TABLE ] tablename [, ...]
  FROM { username | GROUP groupname | PUBLIC } [, ...]
  [ CASCADE | RESTRICT ]

According to this and SQL92 standard, I'll define the grammar of
column-level privilege as follows:
GRANT { { SELECT | INSERT | UPDATE | REFERENCES }
  [,...] | ALL [ PRIVILEGES ] }
  ON [ TABLE ] tablename[ '(' columnname [, ...] ')' ] [, ...]
  TO { username | GROUP groupname | PUBLIC } [, ...] [ WITH GRANT OPTION ]
REVOKE [ GRANT OPTION FOR ]
  { { SELECT | INSERT | UPDATE | REFERENCES }
  [,...] | ALL [ PRIVILEGES ] }
  ON [ TABLE ] tablename[ '(' columnname [, ...] ')' ] [, ...]
  FROM { username | GROUP groupname | PUBLIC } [, ...]
  [ CASCADE | RESTRICT ]


According to SQL92, if TABLE privilege is granted to a grantee,
he/she will also get the privilege of ALL columns added to the table.
That is to say, if you commit this command:
GRANT SELECT ON student TO Tom;
Then Tom can select all columns of the student table. This is also
true for UPDATE, INSERT and REFERENCES. So, if Tom can see the name
column of the student table but has no right to see other columns, a
superuser should commit some commands like these:
REVOKE SELECT ON student FROM Tom;
GRANT SELECT ON student(name) TO Tom;


Here is a plan of my project:
1. Modifying the parser for supporting column-level Grant/Revoke
grammar. The grammar is defined as before. This will change gram.y and
some relative data structures.
2. Add codes to record column-level privilege information as
meta-data in system catalog pg_attribute. This will add a column named
'attacl' in pg_attribute. The format of this column is just the same
as 'pg_class.relacl'.
3. Before evaluating a SQL command, check column-level privilege.
This is done AFTER checking table-level privilege. As I mentioned
before, if table-level privilege is granted, it's not necessary to
check column-level privilege.

---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


Re: [HACKERS] Unique index: update error

2006-09-18 Thread Golden Liu

On 9/18/06, Tom Lane <[EMAIL PROTECTED]> wrote:

Jim Nasby <[EMAIL PROTECTED]> writes:
> On Sep 14, 2006, at 9:16 PM, Golden Liu wrote:
>> I try to solve this problem this way:
>> First, update the table t but DON'T update the index.
>> Next, find all the tuples updated by this command and insert them into
>> the unique index.

> I suspect that your change adds a non-trivial overhead, which means
> we don't want it to be the normal case.

There's a bigger problem:

begin;
update tab set col1 = ... where unique_key = ...;
update tab set col2 = ... where unique_key = ...;
commit;

If the first update doesn't insert index entries into unique_key's
index, then the second update won't find the tuples it needs to update
(unless we hack the planner to not trust the index as valid ... and
then it'd fall back on a seqscan, which is hardly acceptable anyway).


The first update DOES insert index entries into unique_key's index. In
fact, index entries will be inserted after each command, not each
transaction. Is this right? Or should we insert index entries after each
transaction?


The scheme that I've thought about involves inserting index entries as
usual, but instead of having the aminsert code error out immediately
upon finding a duplicate, have it make an entry in a list of things
that need to be rechecked before commit.  This wins as long as potential
conflicts are uncommon.  Performance could suck if the list gets too
large --- but we have more or less the same hazard now for foreign-key
checks, and it mostly works well enough.  (In fact, maybe the existing
deferred trigger event list is the thing to use for the deferred
conflict rechecks.)

regards, tom lane



---(end of broadcast)---
TIP 2: Don't 'kill -9' the postmaster


[HACKERS] Unique index: update error

2006-09-14 Thread Golden Liu

Suppose there are too tuples in a table t, named
id
---
1
2

and there is a unique index on id. Now we do an update on table t
update t set id=id+1

Since PG executes the update one tuple at a time, it updates tuple "1"
to "2" and insert it into the index. Before insert into the index, it
check whether the id is still "unique" or not. No, it's not, old tuple
"2" is still in the table. So an error is raised.

I try to solve this problem this way:
First, update the table t but DON'T update the index.
Next, find all the tuples updated by this command and insert them into
the unique index.

By doing so, the problem seemed to be solved. My modifications focus
on the function "ExecutePlan". Here is my patch for PG8.1.4.
Tuplestore is used to record all the tuples being updated by this
command.

Is there any problom with it? Thanks.



Index: backend/executor/execMain.c
== =
RCS file: /home/gdliu/cvsroot/postgresql/src/backend/executor/execMain .c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 execMain.c
*** backend/executor/execMain.c 5 Sep 2006 07:19:08 - 1.1.1.1
--- backend/executor/execMain.c 7 Sep 2006 08:28:34 -
***
*** 1068,1073 
--- 1068,1092 
   long  current_tuple_count;
   TupleTableSlot *result;

+
+  MemoryContext holdCtidContext = NULL;
+  Tuplestorestate *holdCtidStore = NULL;
+  MemoryContext oldcxt = NULL;
+  if(operation == CMD_UPDATE) {
+holdCtidContext =
+   AllocSetContextCreate(CurrentMemoryContext,
+  "HoldUpdateCTIDContext",
+  ALLOCSET_DEFAULT_MINSIZE,
+  ALLOCSET_DEFAULT_INITSIZE,
+  ALLOCSET_DEFAULT_MAXSIZE);
+
+oldcxt = MemoryContextSwitchTo(holdCtidContext);
+holdCtidStore = tuplestore_begin_heap(false, false, work_mem);
+MemoryContextSwitchTo(oldcxt);
+  }
+
   /*
* initialize local variables
*/
***
*** 1287,1293 
--- 1306,1319 
  break;

 case CMD_UPDATE:
  ExecUpdate(slot, tupleid, estate);
+
+ oldcxt = MemoryContextSwitchTo(holdCtidContext);
+ slot->tts_tuple->t_data->t_ ctid = slot->tts_tuple->t_self;
+tuplestore_puttuple(holdCtidStore,slot->tts_tuple);
+ MemoryContextSwitchTo(oldcxt);
  result = NULL;
  break;

***
*** 1308,1313 
--- 1334,1372 
 break;
   }

+
+  //insert index
+  if(operation == CMD_UPDATE &&
+ estate->es_result_relation_info->ri_NumIndices > 0) {
+HeapTuple tuple = NULL;
+bool should_free = false;
+
+oldcxt = MemoryContextSwitchTo(holdCtidContext);
+
+tuplestore_rescan(holdCtidStore);
+for(;;) {
+   tuple = (HeapTuple)tuplestore_gettuple(holdCtidStore,true,&shoul d_free);
+   if(!tuple)
+ break;
+   tuple->t_self = tuple->t_data->t_ctid;
+   ItemPointerSetInvalid(&(tuple->t_data-> ;t_ctid));
+   if(!ItemPointerIsValid(&(tuple->t_self))) {
+ elog(ERROR, "Insert Index: ctid is invalid.");
+   }
+   ExecStoreTuple(tuple, slot, InvalidBuffer, false);
+   ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
+   if(should_free)
+ pfree(tuple);
+}
+tuplestore_end(holdCtidStore);
+MemoryContextSwitchTo(holdCtidStore);
+holdCtidContext->methods->delete(holdCtidContext);
+  }
+  //*/
   /*
* Process AFTER EACH STATEMENT triggers
*/

---(end of broadcast)---
TIP 4: Have you searched our list archives?

  http://archives.postgresql.org


[HACKERS] UPDATE/DELETE XXX WHERE CURRENT OF cursor_name

2006-07-24 Thread Golden Liu

Updateable cursors are used as follows:

begin;
declare foo cursor for select * from bar for update;
fetch foo;
update bar set abc='def' where current of foo;
fetch foo;
delete from bar where current of foo;
commit;


PostgreSQL doesn't support this feature now ( 8.1.4). Will PGSQL
support it recently? Does anyone work on this?


thanks
Golden
 7.24

---(end of broadcast)---
TIP 4: Have you searched our list archives?

  http://archives.postgresql.org