FOR UPDATE is in parser & rules.

This commit is contained in:
Vadim B. Mikheev 1999-01-21 16:08:55 +00:00
parent c8ae6afd13
commit 12be3e08f1
10 changed files with 763 additions and 609 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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 ')'
{

View File

@ -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);

View File

@ -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

View File

@ -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;
/*

View File

@ -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 */