Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit15cb32d

Browse files
committed
This is the final state of the rule system for 6.4 after the
patch is applied:Rewrite rules on relation level work fine now.Event qualifications on insert/update/delete rules workfine now.I added the new keyword OLD to reference the CURRENTtuple. CURRENT will be removed in 6.5.Update rules can reference NEW and OLD in the rulequalification and the actions.Insert/update/delete rules on views can be established tolet them behave like real tables.For insert/update/delete rules multiple actions aresupported now. The actions can also be surrounded byparantheses to make psql happy. Multiple actions arerequired if update to a view requires updates to multipletables.Regular users are permitted to create/drop rules ontables they have RULE permissions for(DefineQueryRewrite() is now able to get around theaccess restrictions on pg_rewrite). This enables viewcreation for regular users too. This required an extraboolean parameter to pg_parse_and_plan() that tells toset skipAcl on all rangetable entries of the resultingqueries. There is a new functionpg_exec_query_acl_override() that could be used bybackend utilities to use this facility.All rule actions (not only views) inherit the permissionsof the event relations owner. Sample: User A createstables T1 and T2, creates rules that logINSERT/UPDATE/DELETE on T1 in T2 (like in the regressiontests for rules I created) and grants ALL but RULE on T1to user B. User B can now fully access T1 and thelogging happens in T2. But user B cannot access T2 atall, only the rule actions can. And due to missing RULEpermissions on T1, user B cannot disable logging.Rules on the attribute level are disabled (they don'twork properly and since regular users are now permittedto create rules I decided to disable them).Rules on select must have exactly one action that is aselect (so select rules must be a view definition).UPDATE NEW/OLD rules are disabled (still broken, buttriggers can do it).There are two new system views (pg_rule and pg_view) thatshow the definition of the rules or views so the db admincan see what the users do. They use two new functionspg_get_ruledef() and pg_get_viewdef() that are builtins.The functions pg_get_ruledef() and pg_get_viewdef() couldbe used to implement rule and view support in pg_dump.PostgreSQL is now the only database system I know, thathas rewrite rules on the query level. All others (where Ifound a rule statement at all) use stored databaseprocedures or the like (triggers as we call them) foractive rules (as some call them). Future of the rule system:The now disabled parts of the rule system (attributelevel, multiple actions on select and update new stuff)require a complete new rewrite handler from scratch. Theold one is too badly wired up.After 6.4 I'll start to work on a new rewrite handler,that fully supports the attribute level rules, multipleactions on select and update new. This will be availablefor 6.5 so we get full rewrite rule capabilities.Jan
1 parentf92994b commit15cb32d

File tree

17 files changed

+1719
-125
lines changed

17 files changed

+1719
-125
lines changed

‎src/backend/catalog/heap.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.59 1998/08/20 22:07:32 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.60 1998/08/24 01:37:46 momjian Exp $
1111
*
1212
* INTERFACE ROUTINES
1313
*heap_create()- Create an uncataloged heap relation
@@ -1448,7 +1448,7 @@ start:;
14481448
sprintf(str,"select %s%s from %.*s",attrdef->adsrc,cast,
14491449
NAMEDATALEN,rel->rd_rel->relname.data);
14501450
setheapoverride(true);
1451-
planTree_list= (List*)pg_parse_and_plan(str,NULL,0,&queryTree_list,None);
1451+
planTree_list= (List*)pg_parse_and_plan(str,NULL,0,&queryTree_list,None, FALSE);
14521452
setheapoverride(false);
14531453
query= (Query*) (queryTree_list->qtrees[0]);
14541454

@@ -1519,7 +1519,7 @@ StoreRelCheck(Relation rel, ConstrCheck *check)
15191519
sprintf(str,"select 1 from %.*s where %s",
15201520
NAMEDATALEN,rel->rd_rel->relname.data,check->ccsrc);
15211521
setheapoverride(true);
1522-
planTree_list= (List*)pg_parse_and_plan(str,NULL,0,&queryTree_list,None);
1522+
planTree_list= (List*)pg_parse_and_plan(str,NULL,0,&queryTree_list,None, FALSE);
15231523
setheapoverride(false);
15241524
query= (Query*) (queryTree_list->qtrees[0]);
15251525

‎src/backend/catalog/pg_proc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.19 1998/08/19 02:01:37 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.20 1998/08/2401:37:47 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -214,7 +214,7 @@ ProcedureCreate(char *procedureName,
214214
if (strcmp(languageName,"sql")==0)
215215
{
216216
plan_list=pg_parse_and_plan(prosrc,typev,parameterCount,
217-
&querytree_list,dest);
217+
&querytree_list,dest, FALSE);
218218

219219
/* typecheck return value */
220220
pg_checkretval(typeObjectId,querytree_list);

‎src/backend/executor/functions.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.17 1998/06/15 19:28:20 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.18 1998/08/24 01:37:48 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -113,7 +113,7 @@ init_execution_state(FunctionCachePtr fcache,
113113

114114

115115
planTree_list= (List*)
116-
pg_parse_and_plan(fcache->src,fcache->argOidVect,nargs,&queryTree_list,None);
116+
pg_parse_and_plan(fcache->src,fcache->argOidVect,nargs,&queryTree_list,None, FALSE);
117117

118118
for (i=0;i<queryTree_list->len;i++)
119119
{

‎src/backend/executor/spi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
642642
argtypes=plan->argtypes;
643643
}
644644
ptlist=planTree_list= (List*)
645-
pg_parse_and_plan(src,argtypes,nargs,&queryTree_list,None);
645+
pg_parse_and_plan(src,argtypes,nargs,&queryTree_list,None, FALSE);
646646

647647
_SPI_current->qtlist=queryTree_list;
648648

‎src/backend/libpq/be-pqexec.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-pqexec.c,v 1.17 1998/06/15 19:28:25 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-pqexec.c,v 1.18 1998/08/24 01:37:52 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -137,7 +137,7 @@ PQexec(char *query)
137137
*end up on the top of the portal stack.
138138
* ----------------
139139
*/
140-
pg_exec_query_dest(query,Local);
140+
pg_exec_query_dest(query,Local, FALSE);
141141

142142
/* ----------------
143143
*pop the portal off the portal stack and return the

‎src/backend/optimizer/path/xfunc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/xfunc.c,v 1.19 1998/08/19 02:02:13 momjian Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/xfunc.c,v 1.20 1998/08/24 01:37:53 momjian Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -528,7 +528,7 @@ xfunc_func_expense(LispValue node, LispValue args)
528528
if (nargs>0)
529529
argOidVect=proc->proargtypes;
530530
planlist= (List)pg_parse_and_plan(pq_src,argOidVect,nargs,
531-
&parseTree_list,None);
531+
&parseTree_list,None, FALSE);
532532
if (IsA(node,Func))
533533
set_func_planlist((Func)node,planlist);
534534

‎src/backend/parser/keywords.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.38 1998/07/2403:31:24 scrappy Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.39 1998/08/2401:37:55 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -66,7 +66,12 @@ static ScanKeyword ScanKeywords[] = {
6666
{"createdb",CREATEDB},
6767
{"createuser",CREATEUSER},
6868
{"cross",CROSS},
69-
{"current",CURRENT},
69+
{"current",CURRENT},/*
70+
* 6.4 to 6.5 is migration time!
71+
* CURRENT will be removed in 6.5!
72+
* Use OLD keyword in rules.
73+
* Jan
74+
*/
7075
{"current_date",CURRENT_DATE},
7176
{"current_time",CURRENT_TIME},
7277
{"current_timestamp",CURRENT_TIMESTAMP},
@@ -152,6 +157,7 @@ static ScanKeyword ScanKeywords[] = {
152157
{"null",NULL_P},
153158
{"numeric",NUMERIC},
154159
{"oids",OIDS},
160+
{"old",OLD},
155161
{"on",ON},
156162
{"operator",OPERATOR},
157163
{"option",OPTION},

‎src/backend/rewrite/locks.c

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
*
88
* IDENTIFICATION
9-
* $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.10 1998/06/15 19:29:06 momjian Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.11 1998/08/24 01:37:56 momjian Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -18,6 +18,14 @@
1818
#include"utils/syscache.h"/* for SearchSysCache */
1919
#include"rewrite/locks.h"/* for rewrite specific lock defns */
2020

21+
#include"access/heapam.h"/* for ACL checking */
22+
#include"utils/syscache.h"
23+
#include"utils/acl.h"
24+
#include"utils/builtins.h"
25+
#include"catalog/pg_shadow.h"
26+
27+
staticvoidcheckLockPerms(List*locks,Query*parsetree,intrt_index);
28+
2129
/*
2230
* ThisLockWasTriggered
2331
*
@@ -156,5 +164,98 @@ matchLocks(CmdType event,
156164
}
157165
}
158166

167+
checkLockPerms(real_locks,parsetree,varno);
168+
159169
return (real_locks);
160170
}
171+
172+
173+
staticvoid
174+
checkLockPerms(List*locks,Query*parsetree,intrt_index)
175+
{
176+
Relationev_rel;
177+
HeapTupleusertup;
178+
char*evowner;
179+
RangeTblEntry*rte;
180+
int32reqperm;
181+
int32aclcheck_res;
182+
inti;
183+
List*l;
184+
185+
if (locks==NIL)
186+
return;
187+
188+
/*
189+
* Get the usename of the rules event relation owner
190+
*/
191+
rte= (RangeTblEntry*)nth(rt_index-1,parsetree->rtable);
192+
ev_rel=heap_openr(rte->relname);
193+
usertup=SearchSysCacheTuple(USESYSID,
194+
ObjectIdGetDatum(ev_rel->rd_rel->relowner),
195+
0,0,0);
196+
if (!HeapTupleIsValid(usertup))
197+
{
198+
elog(ERROR,"cache lookup for userid %d failed",
199+
ev_rel->rd_rel->relowner);
200+
}
201+
heap_close(ev_rel);
202+
evowner=nameout(&(((Form_pg_shadow)GETSTRUCT(usertup))->usename));
203+
204+
/*
205+
* Check all the locks, that should get fired on this query
206+
*/
207+
foreach (l,locks) {
208+
RewriteRule*onelock= (RewriteRule*)lfirst(l);
209+
List*action;
210+
211+
/*
212+
* In each lock check every action
213+
*/
214+
foreach (action,onelock->actions) {
215+
Query*query= (Query*)lfirst(action);
216+
217+
/*
218+
* In each action check every rangetable entry
219+
* for read/write permission of the event relations
220+
* owner depending on if it's the result relation
221+
* (write) or not (read)
222+
*/
223+
for (i=2;i<length(query->rtable);i++) {
224+
if (i+1==query->resultRelation)
225+
switch (query->resultRelation) {
226+
caseCMD_INSERT:
227+
reqperm=ACL_AP;
228+
break;
229+
default:
230+
reqperm=ACL_WR;
231+
break;
232+
}
233+
else
234+
reqperm=ACL_RD;
235+
236+
rte= (RangeTblEntry*)nth(i,query->rtable);
237+
aclcheck_res=pg_aclcheck(rte->relname,
238+
evowner,reqperm);
239+
if (aclcheck_res!=ACLCHECK_OK) {
240+
elog(ERROR,"%s: %s",
241+
rte->relname,
242+
aclcheck_error_strings[aclcheck_res]);
243+
}
244+
245+
/*
246+
* So this is allowed due to the permissions
247+
* of the rules event relation owner. But
248+
* let's see if the next one too
249+
*/
250+
rte->skipAcl= TRUE;
251+
}
252+
}
253+
}
254+
255+
/*
256+
* Phew, that was close
257+
*/
258+
return;
259+
}
260+
261+

‎src/backend/rewrite/rewriteDefine.c

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.18 1998/08/19 02:02:29 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.19 1998/08/24 01:37:58 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -131,7 +131,7 @@ InsertRule(char *rulname,
131131
rulname,evtype,eventrel_oid,evslot_index,actionbuf,
132132
qualbuf,is_instead);
133133

134-
pg_exec_query(rulebuf);
134+
pg_exec_query_acl_override(rulebuf);
135135

136136
return (LastOidProcessed);
137137
}
@@ -192,12 +192,61 @@ DefineQueryRewrite(RuleStmt *stmt)
192192
Oidevent_attype=0;
193193
char*actionP,
194194
*event_qualP;
195-
195+
List*l;
196+
Query*query;
197+
198+
/* ----------
199+
* The current rewrite handler is known to work on relation level
200+
* rules only. And for SELECT events, it expects one non-nothing
201+
* action that is instead. Since we now hand out views and rules
202+
* to regular users, we must deny anything else.
203+
*
204+
* I know that I must write a new rewrite handler from scratch
205+
* for 6.5 so we can remove these checks and allow all the rules.
206+
*
207+
* Jan
208+
* ----------
209+
*/
196210
if (event_obj->attrs)
211+
elog(ERROR,"attribute level rules currently not supported");
212+
/*
197213
eslot_string = strVal(lfirst(event_obj->attrs));
214+
*/
198215
else
199216
eslot_string=NULL;
200217

218+
if (action!=NIL)
219+
foreach (l,action) {
220+
query= (Query*)lfirst(l);
221+
if (query->resultRelation==1) {
222+
elog(NOTICE,"rule actions on OLD currently not supported");
223+
elog(ERROR," use views or triggers instead");
224+
}
225+
if (query->resultRelation==2) {
226+
elog(NOTICE,"rule actions on NEW currently not supported");
227+
elog(ERROR," use triggers instead");
228+
}
229+
}
230+
231+
if (event_type==CMD_SELECT) {
232+
if (length(action)==0) {
233+
elog(NOTICE,"instead nothing rules on select currently not supported");
234+
elog(ERROR," use views instead");
235+
}
236+
if (length(action)>1) {
237+
elog(ERROR,"multiple action rules on select currently not supported");
238+
}
239+
query= (Query*)lfirst(action);
240+
if (!is_instead||query->commandType!=CMD_SELECT) {
241+
elog(ERROR,"only instead-select rules currently supported on select");
242+
}
243+
}
244+
/*
245+
* This rule is currently allowed - too restricted I know -
246+
* but women and children first
247+
* Jan
248+
*/
249+
201250
event_relation=heap_openr(event_obj->relname);
202251
if (event_relation==NULL)
203252
elog(ERROR,"virtual relations not supported yet");

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp