mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
FOR UPDATE is in parser & rules.
This commit is contained in:
parent
c8ae6afd13
commit
12be3e08f1
@ -34,7 +34,7 @@
|
||||
#
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/Makefile,v 1.35 1999/01/17 06:18:11 momjian Exp $
|
||||
# $Header: /cvsroot/pgsql/src/backend/Makefile,v 1.36 1999/01/21 16:08:36 vadim Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -111,9 +111,6 @@ catalog/global1.description catalog/local1_template1.description:
|
||||
postgres.o: $(OBJS)
|
||||
$(CC) -r -o postgres.o $(OBJS) $(LDFLAGS)
|
||||
|
||||
fast:
|
||||
$(CC) -r -o postgres.o $(OBJS) $(LDFLAGS)
|
||||
|
||||
############################################################################
|
||||
# The following targets are specified in make commands that appear in the
|
||||
# make files in our subdirectories.
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: outfuncs.c,v 1.59 1999/01/18 00:09:45 momjian Exp $
|
||||
* $Id: outfuncs.c,v 1.60 1999/01/21 16:08:36 vadim Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||
@ -162,6 +162,7 @@ _outIndexElem(StringInfo str, IndexElem *node)
|
||||
static void
|
||||
_outQuery(StringInfo str, Query *node)
|
||||
{
|
||||
|
||||
appendStringInfo(str, " QUERY :command %d ", node->commandType);
|
||||
|
||||
if (node->utilityStmt)
|
||||
@ -235,6 +236,10 @@ _outQuery(StringInfo str, Query *node)
|
||||
|
||||
appendStringInfo(str, " :limitCount ");
|
||||
_outNode(str, node->limitCount);
|
||||
|
||||
appendStringInfo(str, " :rowMark ");
|
||||
_outNode(str, node->rowMark);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@ -907,6 +912,12 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
|
||||
node->skipAcl ? "true" : "false");
|
||||
}
|
||||
|
||||
static void
|
||||
_outRowMark(StringInfo str, RowMark *node)
|
||||
{
|
||||
appendStringInfo(str, " ROWMARK :rti %u :info %u", node->rti, node->info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Path is a subclass of Node.
|
||||
*/
|
||||
@ -1528,6 +1539,9 @@ _outNode(StringInfo str, void *obj)
|
||||
case T_RangeTblEntry:
|
||||
_outRangeTblEntry(str, obj);
|
||||
break;
|
||||
case T_RowMark:
|
||||
_outRowMark(str, obj);
|
||||
break;
|
||||
case T_Path:
|
||||
_outPath(str, obj);
|
||||
break;
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.41 1999/01/18 00:09:46 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.42 1999/01/21 16:08:37 vadim Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Most of the read functions for plan nodes are tested. (In fact, they
|
||||
@ -174,6 +174,9 @@ _readQuery()
|
||||
token = lsptok(NULL, &length); /* skip :limitCount */
|
||||
local_node->limitCount = nodeRead(true);
|
||||
|
||||
token = lsptok(NULL, &length); /* skip :rowMark */
|
||||
local_node->rowMark = nodeRead(true);
|
||||
|
||||
return local_node;
|
||||
}
|
||||
|
||||
@ -1427,6 +1430,24 @@ _readRangeTblEntry()
|
||||
return local_node;
|
||||
}
|
||||
|
||||
static RowMark *
|
||||
_readRowMark()
|
||||
{
|
||||
RowMark *local_node = makeNode(RowMark);
|
||||
char *token;
|
||||
int length;
|
||||
|
||||
token = lsptok(NULL, &length); /* eat :rti */
|
||||
token = lsptok(NULL, &length); /* get :rti */
|
||||
local_node->rti = strtoul(token, NULL, 10);
|
||||
|
||||
token = lsptok(NULL, &length); /* eat :info */
|
||||
token = lsptok(NULL, &length); /* get :info */
|
||||
local_node->info = strtoul(token, NULL, 10);
|
||||
|
||||
return local_node;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* _readPath
|
||||
*
|
||||
@ -2090,6 +2111,8 @@ parsePlanString(void)
|
||||
return_value = _readCaseExpr();
|
||||
else if (!strncmp(token, "WHEN", length))
|
||||
return_value = _readCaseWhen();
|
||||
else if (!strncmp(token, "ROWMARK", length))
|
||||
return_value = _readRowMark();
|
||||
else
|
||||
elog(ERROR, "badly formatted planstring \"%.10s\"...\n", token);
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: analyze.c,v 1.92 1999/01/18 00:09:49 momjian Exp $
|
||||
* $Id: analyze.c,v 1.93 1999/01/21 16:08:38 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -45,6 +45,8 @@ static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
|
||||
static Query *transformCursorStmt(ParseState *pstate, SelectStmt *stmt);
|
||||
static Query *transformCreateStmt(ParseState *pstate, CreateStmt *stmt);
|
||||
|
||||
static void transformForUpdate(Query *qry, List *forUpdate);
|
||||
|
||||
List *extras_before = NIL;
|
||||
List *extras_after = NIL;
|
||||
|
||||
@ -387,7 +389,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
|
||||
/*
|
||||
* The INSERT INTO ... SELECT ... could have a UNION in child, so
|
||||
* unionClause may be false
|
||||
*/
|
||||
, */
|
||||
qry->unionall = stmt->unionall;
|
||||
|
||||
/***S*I***/
|
||||
@ -408,6 +410,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
|
||||
return (Query *) NIL;
|
||||
}
|
||||
|
||||
if (stmt->forUpdate != NULL)
|
||||
transformForUpdate(qry, stmt->forUpdate);
|
||||
|
||||
return (Query *) qry;
|
||||
}
|
||||
|
||||
@ -971,6 +976,9 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
|
||||
return (Query *) NIL;
|
||||
}
|
||||
|
||||
if (stmt->forUpdate != NULL)
|
||||
transformForUpdate(qry, stmt->forUpdate);
|
||||
|
||||
return (Query *) qry;
|
||||
}
|
||||
|
||||
@ -1121,3 +1129,59 @@ Node *A_Expr_to_Expr(Node *ptr, bool *intersect_present)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
transformForUpdate(Query *qry, List *forUpdate)
|
||||
{
|
||||
List *rowMark = NULL;
|
||||
RowMark *newrm;
|
||||
List *l;
|
||||
Index i;
|
||||
|
||||
if (lfirst(forUpdate) == NULL) /* all tables */
|
||||
{
|
||||
i = 1;
|
||||
foreach (l, qry->rtable)
|
||||
{
|
||||
newrm = makeNode(RowMark);
|
||||
newrm->rti = i++;
|
||||
newrm->info = ROW_MARK_FOR_UPDATE|ROW_ACL_FOR_UPDATE;
|
||||
rowMark = lappend(rowMark, newrm);
|
||||
}
|
||||
qry->rowMark = nconc(qry->rowMark, rowMark);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (l, forUpdate)
|
||||
{
|
||||
List *l2;
|
||||
List *l3;
|
||||
|
||||
i = 1;
|
||||
foreach (l2, qry->rtable)
|
||||
{
|
||||
if (strcmp(((RangeTblEntry*)lfirst(l2))->refname, lfirst(l)) == 0)
|
||||
{
|
||||
foreach (l3, rowMark)
|
||||
{
|
||||
if (((RowMark*)lfirst(l3))->rti == i) /* duplicate */
|
||||
break;
|
||||
}
|
||||
if (l3 == NULL)
|
||||
{
|
||||
newrm = makeNode(RowMark);
|
||||
newrm->rti = i;
|
||||
newrm->info = ROW_MARK_FOR_UPDATE|ROW_ACL_FOR_UPDATE;
|
||||
rowMark = lappend(rowMark, newrm);
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (l2 == NULL)
|
||||
elog(ERROR, "FOR UPDATE: relation %s not found in FROM clause", lfirst(l));
|
||||
}
|
||||
|
||||
qry->rowMark = rowMark;
|
||||
return;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.46 1999/01/20 19:48:13 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.47 1999/01/21 16:08:46 vadim Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -2496,6 +2496,7 @@ insert_rest: VALUES '(' res_target_list2 ')'
|
||||
$$->havingClause = n->havingClause;
|
||||
$$->unionClause = n->unionClause;
|
||||
$$->intersectClause = n->intersectClause;
|
||||
$$->forUpdate = n->forUpdate;
|
||||
}
|
||||
| '(' columnList ')' VALUES '(' res_target_list2 ')'
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.28 1999/01/18 00:09:54 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.29 1999/01/21 16:08:48 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1799,7 +1799,8 @@ ApplyRetrieveRule(Query *parsetree,
|
||||
Query *rule_action = NULL;
|
||||
Node *rule_qual;
|
||||
List *rtable,
|
||||
*rt;
|
||||
*rt,
|
||||
*l;
|
||||
int nothing,
|
||||
rt_length;
|
||||
int badsql = FALSE;
|
||||
@ -1834,6 +1835,43 @@ ApplyRetrieveRule(Query *parsetree,
|
||||
rtable = nconc(rtable, copyObject(rule_action->rtable));
|
||||
parsetree->rtable = rtable;
|
||||
|
||||
/* FOR UPDATE of view... */
|
||||
foreach (l, parsetree->rowMark)
|
||||
{
|
||||
if (((RowMark*)lfirst(l))->rti == rt_index)
|
||||
break;
|
||||
}
|
||||
if (l != NULL) /* oh, hell -:) */
|
||||
{
|
||||
RowMark *newrm;
|
||||
Index rti = 1;
|
||||
List *l2;
|
||||
|
||||
/*
|
||||
* We believe that rt_index is VIEW - nothing should be
|
||||
* marked for VIEW, but ACL check must be done.
|
||||
* As for real tables of VIEW - their rows must be marked, but
|
||||
* we have to skip ACL check for them.
|
||||
*/
|
||||
((RowMark*)lfirst(l))->info &= ~ROW_MARK_FOR_UPDATE;
|
||||
foreach (l2, rule_action->rtable)
|
||||
{
|
||||
/*
|
||||
* RTable of VIEW has two entries of VIEW itself -
|
||||
* we use relid to skip them.
|
||||
*/
|
||||
if (relation->rd_id != ((RangeTblEntry*)lfirst(l2))->relid)
|
||||
{
|
||||
newrm = makeNode(RowMark);
|
||||
newrm->rti = rti + rt_length;
|
||||
newrm->info = ROW_MARK_FOR_UPDATE;
|
||||
lnext(l) = lcons(newrm, lnext(l));
|
||||
l = lnext(l);
|
||||
}
|
||||
rti++;
|
||||
}
|
||||
}
|
||||
|
||||
rule_action->rtable = rtable;
|
||||
OffsetVarNodes((Node *) rule_qual, rt_length, 0);
|
||||
OffsetVarNodes((Node *) rule_action, rt_length, 0);
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.37 1999/01/17 03:28:37 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.38 1999/01/21 16:08:51 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -63,6 +63,9 @@
|
||||
#include "utils/builtins.h" /* for ftod() prototype */
|
||||
#include "utils/palloc.h"
|
||||
|
||||
#ifndef NAN
|
||||
#define NAN (0.0/0.0)
|
||||
#endif
|
||||
|
||||
#ifndef SHRT_MAX
|
||||
#define SHRT_MAX 32767
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: nodes.h,v 1.33 1998/12/18 09:09:53 vadim Exp $
|
||||
* $Id: nodes.h,v 1.34 1999/01/21 16:08:53 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -216,7 +216,8 @@ typedef enum NodeTag
|
||||
T_SubSelect,
|
||||
T_JoinUsing,
|
||||
T_CaseExpr,
|
||||
T_CaseWhen
|
||||
T_CaseWhen,
|
||||
T_RowMark
|
||||
} NodeTag;
|
||||
|
||||
/*
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parsenodes.h,v 1.66 1999/01/18 00:10:06 momjian Exp $
|
||||
* $Id: parsenodes.h,v 1.67 1999/01/21 16:08:55 vadim Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -53,6 +53,7 @@ typedef struct Query
|
||||
List *rtable; /* list of range table entries */
|
||||
List *targetList; /* target list (of TargetEntry) */
|
||||
Node *qual; /* qualifications */
|
||||
List *rowMark; /* list of RowMark entries */
|
||||
|
||||
List *groupClause; /* list of columns to specified in GROUP
|
||||
* BY */
|
||||
@ -608,9 +609,10 @@ typedef struct InsertStmt
|
||||
List *groupClause; /* group by clause */
|
||||
Node *havingClause; /* having conditional-expression */
|
||||
List *unionClause; /* union subselect parameters */
|
||||
bool unionall; /* union without unique sort */
|
||||
/***S*I***/
|
||||
List *intersectClause;
|
||||
bool unionall; /* union without unique sort */
|
||||
/***S*I***/
|
||||
List *intersectClause;
|
||||
List *forUpdate; /* FOR UPDATE clause */
|
||||
} InsertStmt;
|
||||
|
||||
/* ----------------------
|
||||
@ -651,10 +653,10 @@ typedef struct SelectStmt
|
||||
Node *whereClause; /* qualifications */
|
||||
List *groupClause; /* group by clause */
|
||||
Node *havingClause; /* having conditional-expression */
|
||||
/***S*I***/
|
||||
List *intersectClause;
|
||||
List *exceptClause;
|
||||
|
||||
/***S*I***/
|
||||
List *intersectClause;
|
||||
List *exceptClause;
|
||||
|
||||
List *unionClause; /* union subselect parameters */
|
||||
List *sortClause; /* sort clause (a list of SortGroupBy's) */
|
||||
char *portalname; /* the portal (cursor) to create */
|
||||
@ -958,4 +960,14 @@ typedef struct GroupClause
|
||||
Oid grpOpoid; /* the sort operator to use */
|
||||
} GroupClause;
|
||||
|
||||
#define ROW_MARK_FOR_UPDATE (1 << 0)
|
||||
#define ROW_ACL_FOR_UPDATE (1 << 1)
|
||||
|
||||
typedef struct RowMark
|
||||
{
|
||||
NodeTag type;
|
||||
Index rti; /* index in Query->rtable */
|
||||
bits8 info; /* as above */
|
||||
} RowMark;
|
||||
|
||||
#endif /* PARSENODES_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user