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

Commit739a056

Browse files
committed
This should be a slighly more complete patch for commands/command.c
AlterTableAddConstraint. The major changes from the last patchare that it should hopefully check for references to temp tables(not in the shadow case, but at defination time) from permanent tables inforeign keys and refuse them and that it doesn't allow the table(s)being constrained to be views (because those cases don't currentlywork).Stephan SzaboThis should be a slighly more complete patch for commands/command.cAlterTableAddConstraint. The major changes from the last patchare that it should hopefully check for references to temp tables(not in the shadow case, but at defination time) from permanent tables inforeign keys and refuse them and that it doesn't allow the table(s)being constrained to be views (because those cases don't currentlywork).Stephan Szabo
1 parentf2e3f62 commit739a056

File tree

1 file changed

+188
-4
lines changed

1 file changed

+188
-4
lines changed

‎src/backend/commands/command.c

Lines changed: 188 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.89 2000/07/14 22:17:42 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.90 2000/07/15 12:37:14 momjian Exp $
1212
*
1313
* NOTES
1414
* The PerformAddAttribute() code, like most of the relation
@@ -33,6 +33,18 @@
3333
#include"utils/acl.h"
3434
#include"utils/fmgroids.h"
3535
#include"commands/trigger.h"
36+
37+
#include"parser/parse_expr.h"
38+
#include"parser/parse_clause.h"
39+
#include"parser/parse_relation.h"
40+
#include"nodes/makefuncs.h"
41+
#include"optimizer/planmain.h"
42+
#include"optimizer/clauses.h"
43+
#include"rewrite/rewriteSupport.h"
44+
#include"commands/view.h"
45+
#include"utils/temprel.h"
46+
#include"executor/spi_priv.h"
47+
3648
#ifdef_DROP_COLUMN_HACK__
3749
#include"catalog/pg_index.h"
3850
#include"parser/parse.h"
@@ -1067,13 +1079,158 @@ void
10671079
AlterTableAddConstraint(constchar*relationName,
10681080
boolinh,Node*newConstraint)
10691081
{
1082+
charrulequery[41+NAMEDATALEN];
1083+
void*qplan;
1084+
charnulls[1]="";
1085+
10701086
if (newConstraint==NULL)
10711087
elog(ERROR,"ALTER TABLE / ADD CONSTRAINT passed invalid constraint.");
10721088

1089+
#ifndefNO_SECURITY
1090+
if (!pg_ownercheck(UserName,relationName,RELNAME))
1091+
elog(ERROR,"ALTER TABLE: permission denied");
1092+
#endif
1093+
1094+
/* check to see if the table to be constrained is a view. */
1095+
sprintf(rulequery,"select * from pg_views where viewname='%s'",relationName);
1096+
if (SPI_connect()!=SPI_OK_CONNECT)
1097+
elog(ERROR,"ALTER TABLE: Unable to determine if %s is a view - SPI_connect failure..",relationName);
1098+
qplan=SPI_prepare(rulequery,0,NULL);
1099+
if (!qplan)
1100+
elog(ERROR,"ALTER TABLE: Unable to determine if %s is a view - SPI_prepare failure.",relationName);
1101+
qplan=SPI_saveplan(qplan);
1102+
if (SPI_execp(qplan,NULL,nulls,1)!=SPI_OK_SELECT)
1103+
elog(ERROR,"ALTER TABLE: Unable to determine if %s is a view - SPI_execp failure.",relationName);
1104+
if (SPI_processed!=0)
1105+
elog(ERROR,"ALTER TABLE: Cannot add constraints to views.");
1106+
if (SPI_finish()!=SPI_OK_FINISH)
1107+
elog(NOTICE,"SPI_finish() failed in ALTER TABLE");
1108+
10731109
switch (nodeTag(newConstraint))
10741110
{
10751111
caseT_Constraint:
1076-
elog(ERROR,"ALTER TABLE / ADD CONSTRAINT is not implemented");
1112+
{
1113+
Constraint*constr=(Constraint*)newConstraint;
1114+
switch (constr->contype) {
1115+
caseCONSTR_CHECK:
1116+
{
1117+
ParseState*pstate;
1118+
boolsuccessful=TRUE;
1119+
HeapScanDescscan;
1120+
ExprContext*econtext;
1121+
TupleTableSlot*slot=makeNode(TupleTableSlot);
1122+
HeapTupletuple;
1123+
RangeTblEntry*rte=makeNode(RangeTblEntry);
1124+
List*rtlist;
1125+
List*qual;
1126+
List*constlist;
1127+
Relationrel;
1128+
Node*expr;
1129+
char*name;
1130+
if (constr->name)
1131+
name=constr->name;
1132+
else
1133+
name="<unnamed>";
1134+
1135+
rel=heap_openr(relationName,AccessExclusiveLock);
1136+
1137+
/*
1138+
* Scan all of the rows, looking for a false match
1139+
*/
1140+
scan=heap_beginscan(rel, false,SnapshotNow,0,NULL);
1141+
AssertState(scan!=NULL);
1142+
1143+
/*
1144+
*We need to make a parse state and range table to allow us
1145+
* to transformExpr and fix_opids to get a version of the
1146+
* expression we can pass to ExecQual
1147+
*/
1148+
pstate=make_parsestate(NULL);
1149+
makeRangeTable(pstate,NULL);
1150+
addRangeTableEntry(pstate,relationName,
1151+
makeAttr(relationName,NULL), false, true,true);
1152+
constlist=lcons(constr,NIL);
1153+
1154+
/* Convert the A_EXPR in raw_expr into an EXPR */
1155+
expr=transformExpr(pstate,constr->raw_expr,EXPR_COLUMN_FIRST);
1156+
1157+
/*
1158+
* Make sure it yields a boolean result.
1159+
*/
1160+
if (exprType(expr)!=BOOLOID)
1161+
elog(ERROR,"CHECK '%s' does not yield boolean result",
1162+
name);
1163+
1164+
/*
1165+
* Make sure no outside relations are referred to.
1166+
*/
1167+
if (length(pstate->p_rtable)!=1)
1168+
elog(ERROR,"Only relation '%s' can be referenced in CHECK",
1169+
relationName);
1170+
1171+
/*
1172+
* Might as well try to reduce any constant expressions.
1173+
*/
1174+
expr=eval_const_expressions(expr);
1175+
1176+
/* And fix the opids */
1177+
fix_opids(expr);
1178+
1179+
qual=lcons(expr,NIL);
1180+
rte->relname=relationName;
1181+
rte->ref=makeNode(Attr);
1182+
rte->ref->relname=rte->relname;
1183+
rte->relid=RelationGetRelid(rel);
1184+
rtlist=lcons(rte,NIL);
1185+
1186+
/*
1187+
* Scan through the rows now, making the necessary things for
1188+
* ExecQual, and then call it to evaluate the expression.
1189+
*/
1190+
while (HeapTupleIsValid(tuple=heap_getnext(scan,0)))
1191+
{
1192+
slot->val=tuple;
1193+
slot->ttc_shouldFree= false;
1194+
slot->ttc_descIsNew= true;
1195+
slot->ttc_tupleDescriptor=rel->rd_att;
1196+
slot->ttc_buffer=InvalidBuffer;
1197+
slot->ttc_whichplan=-1;
1198+
1199+
econtext=MakeExprContext(slot,CurrentMemoryContext);
1200+
econtext->ecxt_range_table=rtlist;/* range table */
1201+
if (!ExecQual(qual,econtext, true)) {
1202+
successful=false;
1203+
break;
1204+
}
1205+
FreeExprContext(econtext);
1206+
}
1207+
1208+
pfree(slot);
1209+
pfree(rtlist);
1210+
pfree(rte);
1211+
1212+
heap_endscan(scan);
1213+
heap_close(rel,NoLock);
1214+
1215+
if (!successful)
1216+
{
1217+
elog(ERROR,"AlterTableAddConstraint: rejected due to CHECK constraint %s",name);
1218+
}
1219+
/*
1220+
* Call AddRelationRawConstraints to do the real adding -- It duplicates some
1221+
* of the above, but does not check the validity of the constraint against
1222+
* tuples already in the table.
1223+
*/
1224+
AddRelationRawConstraints(rel,NIL,constlist);
1225+
pfree(constlist);
1226+
1227+
break;
1228+
}
1229+
default:
1230+
elog(ERROR,"ALTER TABLE / ADD CONSTRAINT is not implemented for that constraint type.");
1231+
}
1232+
}
1233+
break;
10771234
caseT_FkConstraint:
10781235
{
10791236
FkConstraint*fkconstraint= (FkConstraint*)newConstraint;
@@ -1084,6 +1241,26 @@ AlterTableAddConstraint(const char *relationName,
10841241
List*list;
10851242
intcount;
10861243

1244+
if (get_temp_rel_by_username(fkconstraint->pktable_name)!=NULL&&
1245+
get_temp_rel_by_username(relationName)==NULL) {
1246+
elog(ERROR,"ALTER TABLE / ADD CONSTRAINT: Unable to reference temporary table from permanent table constraint.");
1247+
}
1248+
1249+
/* check to see if the referenced table is a view. */
1250+
sprintf(rulequery,"select * from pg_views where viewname='%s'",fkconstraint->pktable_name);
1251+
if (SPI_connect()!=SPI_OK_CONNECT)
1252+
elog(ERROR,"ALTER TABLE: Unable to determine if %s is a view.",relationName);
1253+
qplan=SPI_prepare(rulequery,0,NULL);
1254+
if (!qplan)
1255+
elog(ERROR,"ALTER TABLE: Unable to determine if %s is a view.",relationName);
1256+
qplan=SPI_saveplan(qplan);
1257+
if (SPI_execp(qplan,NULL,nulls,1)!=SPI_OK_SELECT)
1258+
elog(ERROR,"ALTER TABLE: Unable to determine if %s is a view.",relationName);
1259+
if (SPI_processed!=0)
1260+
elog(ERROR,"ALTER TABLE: Cannot add constraints to views.");
1261+
if (SPI_finish()!=SPI_OK_FINISH)
1262+
elog(NOTICE,"SPI_finish() failed in RI_FKey_check()");
1263+
10871264
/*
10881265
* Grab an exclusive lock on the pk table, so that someone
10891266
* doesn't delete rows out from under us.
@@ -1101,7 +1278,10 @@ AlterTableAddConstraint(const char *relationName,
11011278
*/
11021279
rel=heap_openr(relationName,AccessExclusiveLock);
11031280
trig.tgoid=0;
1104-
trig.tgname="<unknown>";
1281+
if (fkconstraint->constr_name)
1282+
trig.tgname=fkconstraint->constr_name;
1283+
else
1284+
trig.tgname="<unknown>";
11051285
trig.tgfoid=0;
11061286
trig.tgtype=0;
11071287
trig.tgenabled= TRUE;
@@ -1113,7 +1293,10 @@ AlterTableAddConstraint(const char *relationName,
11131293
sizeof(char*)* (4+length(fkconstraint->fk_attrs)
11141294
+length(fkconstraint->pk_attrs)));
11151295

1116-
trig.tgargs[0]="<unnamed>";
1296+
if (fkconstraint->constr_name)
1297+
trig.tgargs[0]=fkconstraint->constr_name;
1298+
else
1299+
trig.tgargs[0]="<unknown>";
11171300
trig.tgargs[1]= (char*)relationName;
11181301
trig.tgargs[2]=fkconstraint->pktable_name;
11191302
trig.tgargs[3]=fkconstraint->match_type;
@@ -1446,3 +1629,4 @@ LockTableCommand(LockStmt *lockstmt)
14461629

14471630
heap_close(rel,NoLock);/* close rel, keep lock */
14481631
}
1632+

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp