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

Commitab3dc66

Browse files
committed
Simplify parsing of column constraints by treating constraint attributes
as independent clauses in the grammar. analyze.c takes care of puttingthe data where it belongs and complaining about invalid combinations.Also, make TEMP (and TEMPORARY) non-reserved words.
1 parentea8cadb commitab3dc66

File tree

3 files changed

+338
-283
lines changed

3 files changed

+338
-283
lines changed

‎src/backend/parser/analyze.c

Lines changed: 131 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
*$Id: analyze.c,v 1.138 2000/02/29 12:28:25 wieck Exp $
9+
*$Id: analyze.c,v 1.139 2000/03/01 05:18:20 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -44,6 +44,7 @@ static Query *transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt);
4444

4545
staticvoidtransformForUpdate(Query*qry,List*forUpdate);
4646
staticvoidtransformFkeyGetPrimaryKey(FkConstraint*fkconstraint);
47+
staticvoidtransformConstraintAttrs(List*constraintList);
4748
staticvoidtransformColumnType(ParseState*pstate,ColumnDef*column);
4849

4950
/* kluge to return extra info from transformCreateStmt() */
@@ -589,6 +590,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
589590
IndexStmt*index,
590591
*pkey=NULL;
591592
IndexElem*iparam;
593+
boolsaw_nullable;
592594

593595
q=makeNode(Query);
594596
q->commandType=CMD_UTILITY;
@@ -621,6 +623,12 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
621623
FuncCall*funccallnode;
622624
CreateSeqStmt*sequence;
623625

626+
/*
627+
* Create appropriate constraints for SERIAL. We do this
628+
* in full, rather than shortcutting, so that we will
629+
* detect any conflicting constraints the user wrote
630+
* (like a different DEFAULT).
631+
*/
624632
sname=makeObjectName(stmt->relname,column->colname,
625633
"seq");
626634
/*
@@ -644,27 +652,37 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
644652
constraint->raw_expr= (Node*)funccallnode;
645653
constraint->cooked_expr=NULL;
646654
constraint->keys=NULL;
647-
648-
column->constraints=lappend(column->constraints,constraint);
655+
column->constraints=lappend(column->constraints,
656+
constraint);
649657

650658
constraint=makeNode(Constraint);
651659
constraint->contype=CONSTR_UNIQUE;
652660
constraint->name=makeObjectName(stmt->relname,
653661
column->colname,
654662
"key");
655-
column->constraints=lappend(column->constraints,constraint);
663+
column->constraints=lappend(column->constraints,
664+
constraint);
665+
666+
constraint=makeNode(Constraint);
667+
constraint->contype=CONSTR_NOTNULL;
668+
column->constraints=lappend(column->constraints,
669+
constraint);
656670

657671
sequence=makeNode(CreateSeqStmt);
658672
sequence->seqname=pstrdup(sname);
659673
sequence->options=NIL;
660674

661675
elog(NOTICE,"CREATE TABLE will create implicit sequence '%s' for SERIAL column '%s.%s'",
662-
sequence->seqname,stmt->relname,column->colname);
676+
sequence->seqname,stmt->relname,column->colname);
663677

664678
blist=lcons(sequence,NIL);
665679
}
666680

667681
/* Process column constraints, if any... */
682+
transformConstraintAttrs(column->constraints);
683+
684+
saw_nullable= false;
685+
668686
foreach(clist,column->constraints)
669687
{
670688
constraint=lfirst(clist);
@@ -676,7 +694,7 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
676694
* to be processed later.
677695
* ----------
678696
*/
679-
if (nodeTag(constraint)==T_FkConstraint)
697+
if (IsA(constraint,FkConstraint))
680698
{
681699
Ident*id=makeNode(Ident);
682700
id->name=column->colname;
@@ -693,23 +711,19 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
693711
switch (constraint->contype)
694712
{
695713
caseCONSTR_NULL:
696-
697-
/*
698-
* We should mark this explicitly, so we
699-
* can tell if NULL and NOT NULL are both
700-
* specified
701-
*/
702-
if (column->is_not_null)
714+
if (saw_nullable&&column->is_not_null)
703715
elog(ERROR,"CREATE TABLE/(NOT) NULL conflicting declaration"
704716
" for '%s.%s'",stmt->relname,column->colname);
705717
column->is_not_null= FALSE;
718+
saw_nullable= true;
706719
break;
707720

708721
caseCONSTR_NOTNULL:
709-
if (column->is_not_null)
710-
elog(ERROR,"CREATE TABLE/NOT NULLalready specified"
722+
if (saw_nullable&& !column->is_not_null)
723+
elog(ERROR,"CREATE TABLE/(NOT) NULLconflicting declaration"
711724
" for '%s.%s'",stmt->relname,column->colname);
712725
column->is_not_null= TRUE;
726+
saw_nullable= true;
713727
break;
714728

715729
caseCONSTR_DEFAULT:
@@ -742,6 +756,13 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
742756
constraints=lappend(constraints,constraint);
743757
break;
744758

759+
caseCONSTR_ATTR_DEFERRABLE:
760+
caseCONSTR_ATTR_NOT_DEFERRABLE:
761+
caseCONSTR_ATTR_DEFERRED:
762+
caseCONSTR_ATTR_IMMEDIATE:
763+
/* transformConstraintAttrs took care of these */
764+
break;
765+
745766
default:
746767
elog(ERROR,"parser: unrecognized constraint (internal error)");
747768
break;
@@ -767,10 +788,16 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt)
767788
constraints=lappend(constraints,constraint);
768789
break;
769790

791+
caseCONSTR_NULL:
770792
caseCONSTR_NOTNULL:
771793
caseCONSTR_DEFAULT:
794+
caseCONSTR_ATTR_DEFERRABLE:
795+
caseCONSTR_ATTR_NOT_DEFERRABLE:
796+
caseCONSTR_ATTR_DEFERRED:
797+
caseCONSTR_ATTR_IMMEDIATE:
772798
elog(ERROR,"parser: illegal context for constraint (internal error)");
773799
break;
800+
774801
default:
775802
elog(ERROR,"parser: unrecognized constraint (internal error)");
776803
break;
@@ -1999,6 +2026,95 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint)
19992026
heap_close(pkrel,AccessShareLock);
20002027
}
20012028

2029+
/*
2030+
* Preprocess a list of column constraint clauses
2031+
* to attach constraint attributes to their primary constraint nodes
2032+
* and detect inconsistent/misplaced constraint attributes.
2033+
*
2034+
* NOTE: currently, attributes are only supported for FOREIGN KEY primary
2035+
* constraints, but someday they ought to be supported for other constraints.
2036+
*/
2037+
staticvoid
2038+
transformConstraintAttrs(List*constraintList)
2039+
{
2040+
Node*lastprimarynode=NULL;
2041+
boolsaw_deferrability= false;
2042+
boolsaw_initially= false;
2043+
List*clist;
2044+
2045+
foreach(clist,constraintList)
2046+
{
2047+
Node*node=lfirst(clist);
2048+
2049+
if (!IsA(node,Constraint))
2050+
{
2051+
lastprimarynode=node;
2052+
/* reset flags for new primary node */
2053+
saw_deferrability= false;
2054+
saw_initially= false;
2055+
}
2056+
else
2057+
{
2058+
Constraint*con= (Constraint*)node;
2059+
2060+
switch (con->contype)
2061+
{
2062+
caseCONSTR_ATTR_DEFERRABLE:
2063+
if (lastprimarynode==NULL||
2064+
!IsA(lastprimarynode,FkConstraint))
2065+
elog(ERROR,"Misplaced DEFERRABLE clause");
2066+
if (saw_deferrability)
2067+
elog(ERROR,"Multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed");
2068+
saw_deferrability= true;
2069+
((FkConstraint*)lastprimarynode)->deferrable= true;
2070+
break;
2071+
caseCONSTR_ATTR_NOT_DEFERRABLE:
2072+
if (lastprimarynode==NULL||
2073+
!IsA(lastprimarynode,FkConstraint))
2074+
elog(ERROR,"Misplaced NOT DEFERRABLE clause");
2075+
if (saw_deferrability)
2076+
elog(ERROR,"Multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed");
2077+
saw_deferrability= true;
2078+
((FkConstraint*)lastprimarynode)->deferrable= false;
2079+
if (saw_initially&&
2080+
((FkConstraint*)lastprimarynode)->initdeferred)
2081+
elog(ERROR,"INITIALLY DEFERRED constraint must be DEFERRABLE");
2082+
break;
2083+
caseCONSTR_ATTR_DEFERRED:
2084+
if (lastprimarynode==NULL||
2085+
!IsA(lastprimarynode,FkConstraint))
2086+
elog(ERROR,"Misplaced INITIALLY DEFERRED clause");
2087+
if (saw_initially)
2088+
elog(ERROR,"Multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed");
2089+
saw_initially= true;
2090+
((FkConstraint*)lastprimarynode)->initdeferred= true;
2091+
/* If only INITIALLY DEFERRED appears, assume DEFERRABLE */
2092+
if (!saw_deferrability)
2093+
((FkConstraint*)lastprimarynode)->deferrable= true;
2094+
elseif (! ((FkConstraint*)lastprimarynode)->deferrable)
2095+
elog(ERROR,"INITIALLY DEFERRED constraint must be DEFERRABLE");
2096+
break;
2097+
caseCONSTR_ATTR_IMMEDIATE:
2098+
if (lastprimarynode==NULL||
2099+
!IsA(lastprimarynode,FkConstraint))
2100+
elog(ERROR,"Misplaced INITIALLY IMMEDIATE clause");
2101+
if (saw_initially)
2102+
elog(ERROR,"Multiple INITIALLY IMMEDIATE/DEFERRED clauses not allowed");
2103+
saw_initially= true;
2104+
((FkConstraint*)lastprimarynode)->initdeferred= false;
2105+
break;
2106+
default:
2107+
/* Otherwise it's not an attribute */
2108+
lastprimarynode=node;
2109+
/* reset flags for new primary node */
2110+
saw_deferrability= false;
2111+
saw_initially= false;
2112+
break;
2113+
}
2114+
}
2115+
}
2116+
}
2117+
20022118
/*
20032119
* Special handling of type definition for a column
20042120
*/
@@ -2027,4 +2143,3 @@ transformColumnType(ParseState *pstate, ColumnDef *column)
20272143
}
20282144
}
20292145
}
2030-

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp