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

Commit247b3f9

Browse files
committed
SELECT FOR UPDATE is implemented...
1 parent443e24b commit247b3f9

File tree

7 files changed

+715
-581
lines changed

7 files changed

+715
-581
lines changed

‎src/backend/executor/execMain.c

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.62 1998/12/18 09:10:21 vadim Exp $
29+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.63 1999/01/25 12:01:03 vadim Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -363,6 +363,32 @@ ExecCheckPerms(CmdType operation,
363363
}
364364
if (!ok)
365365
elog(ERROR,"%s: %s",rname.data,aclcheck_error_strings[aclcheck_result]);
366+
367+
if (parseTree->rowMark!=NULL)
368+
{
369+
foreach(lp,parseTree->rowMark)
370+
{
371+
RowMark*rm=lfirst(lp);
372+
373+
if (!(rm->info&ROW_ACL_FOR_UPDATE))
374+
continue;
375+
376+
relid= ((RangeTblEntry*)nth(rm->rti-1,rangeTable))->relid;
377+
htup=SearchSysCacheTuple(RELOID,
378+
ObjectIdGetDatum(relid),
379+
0,0,0);
380+
if (!HeapTupleIsValid(htup))
381+
elog(ERROR,"ExecCheckPerms: bogus RT relid: %d",
382+
relid);
383+
StrNCpy(rname.data,
384+
((Form_pg_class)GETSTRUCT(htup))->relname.data,
385+
NAMEDATALEN);
386+
ok= ((aclcheck_result=CHECK(ACL_WR))==ACLCHECK_OK);
387+
opstr="write";
388+
if (!ok)
389+
elog(ERROR,"%s: %s",rname.data,aclcheck_error_strings[aclcheck_result]);
390+
}
391+
}
366392
}
367393

368394
/* ===============================================================
@@ -372,6 +398,11 @@ ExecCheckPerms(CmdType operation,
372398
* ===============================================================
373399
*/
374400

401+
typedefstructexecRowMark
402+
{
403+
Relationrelation;
404+
charresname[32];
405+
}execRowMark;
375406

376407
/* ----------------------------------------------------------------
377408
*InitPlan
@@ -398,6 +429,10 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
398429
rangeTable=parseTree->rtable;
399430
resultRelation=parseTree->resultRelation;
400431

432+
#ifndefNO_SECURITY
433+
ExecCheckPerms(operation,resultRelation,rangeTable,parseTree);
434+
#endif
435+
401436
/******************
402437
*initialize the node's execution state
403438
******************
@@ -468,9 +503,32 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
468503
estate->es_result_relation_info=NULL;
469504
}
470505

471-
#ifndefNO_SECURITY
472-
ExecCheckPerms(operation,resultRelation,rangeTable,parseTree);
473-
#endif
506+
/*
507+
* Have to lock relations selected for update
508+
*/
509+
estate->es_rowMark=NULL;
510+
if (parseTree->rowMark!=NULL)
511+
{
512+
Relationrelation;
513+
Oidrelid;
514+
RowMark*rm;
515+
List*l;
516+
execRowMark*erm;
517+
518+
foreach(l,parseTree->rowMark)
519+
{
520+
rm=lfirst(l);
521+
relid= ((RangeTblEntry*)nth(rm->rti-1,rangeTable))->relid;
522+
relation=heap_open(relid);
523+
LockRelation(relation,RowShareLock);
524+
if (!(rm->info&ROW_MARK_FOR_UPDATE))
525+
continue;
526+
erm= (execRowMark*)palloc(sizeof(execRowMark));
527+
erm->relation=relation;
528+
sprintf(erm->resname,"ctid%u",rm->rti);
529+
estate->es_rowMark=lappend(estate->es_rowMark,erm);
530+
}
531+
}
474532

475533
/******************
476534
* initialize the executor "tuple" table.
@@ -777,6 +835,49 @@ ExecutePlan(EState *estate,
777835
* ctid!! */
778836
tupleid=&tuple_ctid;
779837
}
838+
elseif (estate->es_rowMark!=NULL)
839+
{
840+
List*l;
841+
execRowMark*erm;
842+
Bufferbuffer;
843+
HeapTupleDatatuple;
844+
inttest;
845+
846+
foreach (l,estate->es_rowMark)
847+
{
848+
erm=lfirst(l);
849+
if (!ExecGetJunkAttribute(junkfilter,
850+
slot,
851+
erm->resname,
852+
&datum,
853+
&isNull))
854+
elog(ERROR,"ExecutePlan: NO (junk) `%s' was found!",erm->resname);
855+
856+
if (isNull)
857+
elog(ERROR,"ExecutePlan: (junk) `%s' is NULL!",erm->resname);
858+
859+
tuple.t_self=*((ItemPointer)DatumGetPointer(datum));
860+
test=heap_mark4update(erm->relation,&tuple,&buffer);
861+
ReleaseBuffer(buffer);
862+
switch (test)
863+
{
864+
caseHeapTupleSelfUpdated:
865+
caseHeapTupleMayBeUpdated:
866+
break;
867+
868+
caseHeapTupleUpdated:
869+
if (XactIsoLevel==XACT_SERIALIZABLE)
870+
elog(ERROR,"Can't serialize access due to concurrent update");
871+
else
872+
elog(ERROR,"Isolation level %u is not supported",XactIsoLevel);
873+
return(NULL);
874+
875+
default:
876+
elog(ERROR,"Unknown status %u from heap_mark4update",test);
877+
return(NULL);
878+
}
879+
}
880+
}
780881

781882
/******************
782883
* Finally create a new "clean" tuple with all junk attributes

‎src/backend/optimizer/plan/planner.c

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.36 1999/01/18 00:09:47 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.37 1999/01/25 12:01:04 vadim Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -20,6 +20,8 @@
2020
#include"nodes/plannodes.h"
2121
#include"nodes/parsenodes.h"
2222
#include"nodes/relation.h"
23+
#include"nodes/makefuncs.h"
24+
#include"catalog/pg_type.h"
2325
#include"parser/parse_expr.h"
2426

2527
#include"utils/elog.h"
@@ -119,6 +121,8 @@ union_planner(Query *parse)
119121
elseif ((rt_index=
120122
first_inherit_rt_entry(rangetable))!=-1)
121123
{
124+
if (parse->rowMark!=NULL)
125+
elog(ERROR,"SELECT FOR UPDATE is not supported for inherit queries");
122126
result_plan= (Plan*)plan_inherit_queries(parse,rt_index);
123127
/* XXX do we need to do this? bjm 12/19/97 */
124128
tlist=preprocess_targetlist(tlist,
@@ -148,17 +152,49 @@ union_planner(Query *parse)
148152
* a new entry and attaches it to the list 'new_tlist' (consisting of the
149153
* VAR node and the RESDOM node as usual with tlists :-) ) */
150154
if (parse->hasAggs)
151-
{
155+
{
152156
if (parse->havingQual!=NULL)
153-
{
154-
new_tlist=check_having_qual_for_vars(parse->havingQual,new_tlist);
155-
}
156-
}
157+
{
158+
new_tlist=check_having_qual_for_vars(parse->havingQual,new_tlist);
159+
}
160+
}
157161

158162
new_tlist=preprocess_targetlist(new_tlist,
159163
parse->commandType,
160164
parse->resultRelation,
161165
parse->rtable);
166+
167+
/* FOR UPDATE ... */
168+
if (parse->rowMark!=NULL)
169+
{
170+
List*l;
171+
TargetEntry*ctid;
172+
Resdom*resdom;
173+
Var*var;
174+
char*resname;
175+
176+
foreach (l,parse->rowMark)
177+
{
178+
if (!(((RowMark*)lfirst(l))->info&ROW_MARK_FOR_UPDATE))
179+
continue;
180+
181+
resname= (char*)palloc(32);
182+
sprintf(resname,"ctid%u", ((RowMark*)lfirst(l))->rti);
183+
resdom=makeResdom(length(new_tlist)+1,
184+
TIDOID,
185+
-1,
186+
resname,
187+
0,
188+
0,
189+
1);
190+
191+
var=makeVar(((RowMark*)lfirst(l))->rti,-1,TIDOID,
192+
-1,0, ((RowMark*)lfirst(l))->rti,-1);
193+
194+
ctid=makeTargetEntry(resdom, (Node*)var);
195+
new_tlist=lappend(new_tlist,ctid);
196+
}
197+
}
162198

163199
/* Here starts the original (pre having) code */
164200
tlist=preprocess_targetlist(tlist,
@@ -290,7 +326,7 @@ union_planner(Query *parse)
290326
pfree(vpm);
291327
}
292328
}
293-
329+
294330
/*
295331
* For now, before we hand back the plan, check to see if there is a
296332
* user-specified sort that needs to be done. Eventually, this will

‎src/backend/parser/analyze.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright (c) 1994, Regents of the University of California
77
*
8-
* $Id: analyze.c,v 1.94 1999/01/21 22:48:07 momjian Exp $
8+
* $Id: analyze.c,v 1.95 1999/01/25 12:01:05 vadim Exp $
99
*
1010
*-------------------------------------------------------------------------
1111
*/
@@ -45,7 +45,8 @@ static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
4545
staticQuery*transformCursorStmt(ParseState*pstate,SelectStmt*stmt);
4646
staticQuery*transformCreateStmt(ParseState*pstate,CreateStmt*stmt);
4747

48-
staticvoidtransformForUpdate(Query*qry,List*forUpdate);
48+
staticvoidtransformForUpdate(Query*qry,List*forUpdate);
49+
voidCheckSelectForUpdate(Query*qry);
4950

5051
List*extras_before=NIL;
5152
List*extras_after=NIL;
@@ -1134,6 +1135,19 @@ Node *A_Expr_to_Expr(Node *ptr, bool *intersect_present)
11341135
returnresult;
11351136
}
11361137

1138+
void
1139+
CheckSelectForUpdate(Query*qry)
1140+
{
1141+
if (qry->unionClause!=NULL)
1142+
elog(ERROR,"SELECT FOR UPDATE is not allowed with UNION/INTERSECT/EXCEPT clause");
1143+
if (qry->uniqueFlag!=NULL)
1144+
elog(ERROR,"SELECT FOR UPDATE is not allowed with DISTINCT clause");
1145+
if (qry->groupClause!=NULL)
1146+
elog(ERROR,"SELECT FOR UPDATE is not allowed with GROUP BY clause");
1147+
if (qry->hasAggs)
1148+
elog(ERROR,"SELECT FOR UPDATE is not allowed with AGGREGATE");
1149+
}
1150+
11371151
staticvoid
11381152
transformForUpdate(Query*qry,List*forUpdate)
11391153
{
@@ -1142,6 +1156,8 @@ transformForUpdate(Query *qry, List *forUpdate)
11421156
List*l;
11431157
Indexi;
11441158

1159+
CheckSelectForUpdate(qry);
1160+
11451161
if (lfirst(forUpdate)==NULL)/* all tables */
11461162
{
11471163
i=1;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp