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

Commitb17b7fa

Browse files
committed
Remove the hack in the grammar that "optimized away" DEFAULT NULL clauses.
Instead put in a test to drop a NULL default at the last moment beforestoring the catalog entry. This changes the behavior in a couple of ways:* Specifying DEFAULT NULL when creating an inheritance child table will successfully suppress inheritance of any default expression from the parent's column, where formerly it failed to do so.* Specifying DEFAULT NULL for a column of a domain type will correctly override any default belonging to the domain; likewise for a sub-domain.The latter change happens because by the time the clause is checked,it won't be a simple null Const but a CoerceToDomain expression.Personally I think this should be back-patched, but there doesn't seem tobe consensus for that on pgsql-hackers, so refraining.
1 parentbf5ccf3 commitb17b7fa

File tree

8 files changed

+115
-69
lines changed

8 files changed

+115
-69
lines changed

‎src/backend/catalog/heap.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.324 2007/10/12 18:55:11 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.325 2007/10/29 19:40:39 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1722,6 +1722,21 @@ AddRelationRawConstraints(Relation rel,
17221722
atp->atttypid,atp->atttypmod,
17231723
NameStr(atp->attname));
17241724

1725+
/*
1726+
* If the expression is just a NULL constant, we do not bother
1727+
* to make an explicit pg_attrdef entry, since the default behavior
1728+
* is equivalent.
1729+
*
1730+
* Note a nonobvious property of this test: if the column is of a
1731+
* domain type, what we'll get is not a bare null Const but a
1732+
* CoerceToDomain expr, so we will not discard the default. This is
1733+
* critical because the column default needs to be retained to
1734+
* override any default that the domain might have.
1735+
*/
1736+
if (expr==NULL||
1737+
(IsA(expr,Const)&& ((Const*)expr)->constisnull))
1738+
continue;
1739+
17251740
StoreAttrDefault(rel,colDef->attnum,nodeToString(expr));
17261741

17271742
cooked= (CookedConstraint*)palloc(sizeof(CookedConstraint));

‎src/backend/commands/typecmds.c

Lines changed: 62 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.108 2007/09/2917:18:58 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.109 2007/10/2919:40:39 tgl Exp $
1212
*
1313
* DESCRIPTION
1414
* The "DefineFoo" routines take the parse tree and pick out the
@@ -765,20 +765,40 @@ DefineDomain(CreateDomainStmt *stmt)
765765
domainName);
766766

767767
/*
768-
* Expression must be stored as a nodeToString result, but
769-
* we also require a valid textual representation (mainly
770-
* to make life easier for pg_dump).
768+
* If the expression is just a NULL constant, we treat
769+
* it like not having a default.
770+
*
771+
* Note that if the basetype is another domain, we'll see
772+
* a CoerceToDomain expr here and not discard the default.
773+
* This is critical because the domain default needs to be
774+
* retained to override any default that the base domain
775+
* might have.
771776
*/
772-
defaultValue=
773-
deparse_expression(defaultExpr,
774-
deparse_context_for(domainName,
775-
InvalidOid),
776-
false, false);
777-
defaultValueBin=nodeToString(defaultExpr);
777+
if (defaultExpr==NULL||
778+
(IsA(defaultExpr,Const)&&
779+
((Const*)defaultExpr)->constisnull))
780+
{
781+
defaultValue=NULL;
782+
defaultValueBin=NULL;
783+
}
784+
else
785+
{
786+
/*
787+
* Expression must be stored as a nodeToString result,
788+
* but we also require a valid textual representation
789+
* (mainly to make life easier for pg_dump).
790+
*/
791+
defaultValue=
792+
deparse_expression(defaultExpr,
793+
deparse_context_for(domainName,
794+
InvalidOid),
795+
false, false);
796+
defaultValueBin=nodeToString(defaultExpr);
797+
}
778798
}
779799
else
780800
{
781-
/*DEFAULT NULL is same as not having a default */
801+
/*No default (can this still happen?) */
782802
defaultValue=NULL;
783803
defaultValueBin=NULL;
784804
}
@@ -1443,7 +1463,7 @@ AlterDomainDefault(List *names, Node *defaultRaw)
14431463
MemSet(new_record_nulls,' ',sizeof(new_record_nulls));
14441464
MemSet(new_record_repl,' ',sizeof(new_record_repl));
14451465

1446-
/* Store the new default, if null then skip this step */
1466+
/* Store the new default into the tuple */
14471467
if (defaultRaw)
14481468
{
14491469
/* Create a dummy ParseState for transformExpr */
@@ -1459,30 +1479,46 @@ AlterDomainDefault(List *names, Node *defaultRaw)
14591479
NameStr(typTup->typname));
14601480

14611481
/*
1462-
*Expression must be stored as anodeToString result, butwealso
1463-
*require a valid textual representation (mainly to make life easier
1464-
*for pg_dump).
1482+
*If the expression is just aNULL constant,wetreat the command
1483+
*like ALTER ... DROP DEFAULT. (But see note for same test in
1484+
*DefineDomain.)
14651485
*/
1466-
defaultValue=deparse_expression(defaultExpr,
1486+
if (defaultExpr==NULL||
1487+
(IsA(defaultExpr,Const)&& ((Const*)defaultExpr)->constisnull))
1488+
{
1489+
/* Default is NULL, drop it */
1490+
new_record_nulls[Anum_pg_type_typdefaultbin-1]='n';
1491+
new_record_repl[Anum_pg_type_typdefaultbin-1]='r';
1492+
new_record_nulls[Anum_pg_type_typdefault-1]='n';
1493+
new_record_repl[Anum_pg_type_typdefault-1]='r';
1494+
}
1495+
else
1496+
{
1497+
/*
1498+
* Expression must be stored as a nodeToString result, but we also
1499+
* require a valid textual representation (mainly to make life
1500+
* easier for pg_dump).
1501+
*/
1502+
defaultValue=deparse_expression(defaultExpr,
14671503
deparse_context_for(NameStr(typTup->typname),
14681504
InvalidOid),
14691505
false, false);
14701506

1471-
/*
1472-
* Form an updated tuple with the new default and write it back.
1473-
*/
1474-
new_record[Anum_pg_type_typdefaultbin-1]=DirectFunctionCall1(textin,
1475-
CStringGetDatum(
1476-
nodeToString(defaultExpr)));
1507+
/*
1508+
* Form an updated tuple with the new default and write it back.
1509+
*/
1510+
new_record[Anum_pg_type_typdefaultbin-1]=DirectFunctionCall1(textin,
1511+
CStringGetDatum(nodeToString(defaultExpr)));
14771512

1478-
new_record_repl[Anum_pg_type_typdefaultbin-1]='r';
1479-
new_record[Anum_pg_type_typdefault-1]=DirectFunctionCall1(textin,
1513+
new_record_repl[Anum_pg_type_typdefaultbin-1]='r';
1514+
new_record[Anum_pg_type_typdefault-1]=DirectFunctionCall1(textin,
14801515
CStringGetDatum(defaultValue));
1481-
new_record_repl[Anum_pg_type_typdefault-1]='r';
1516+
new_record_repl[Anum_pg_type_typdefault-1]='r';
1517+
}
14821518
}
14831519
else
1484-
/* Default is NULL, drop it */
14851520
{
1521+
/* ALTER ... DROP DEFAULT */
14861522
new_record_nulls[Anum_pg_type_typdefaultbin-1]='n';
14871523
new_record_repl[Anum_pg_type_typdefaultbin-1]='r';
14881524
new_record_nulls[Anum_pg_type_typdefault-1]='n';

‎src/backend/parser/gram.y

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.603 2007/09/24 01:29:28 adunstan Exp $
14+
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.604 2007/10/29 19:40:39 tgl Exp $
1515
*
1616
* HISTORY
1717
* AUTHORDATEMAJOR EVENT
@@ -1685,14 +1685,7 @@ alter_rel_cmd:
16851685
;
16861686

16871687
alter_column_default:
1688-
SETDEFAULTa_expr
1689-
{
1690-
/* Treat SET DEFAULT NULL the same as DROP DEFAULT*/
1691-
if (exprIsNullConstant($3))
1692-
$$ =NULL;
1693-
else
1694-
$$ =$3;
1695-
}
1688+
SETDEFAULTa_expr{$$ =$3; }
16961689
|DROPDEFAULT{$$ =NULL; }
16971690
;
16981691

@@ -2080,15 +2073,7 @@ ColConstraintElem:
20802073
Constraint *n = makeNode(Constraint);
20812074
n->contype = CONSTR_DEFAULT;
20822075
n->name =NULL;
2083-
if (exprIsNullConstant($2))
2084-
{
2085-
/* DEFAULT NULL should be reported as empty expr*/
2086-
n->raw_expr =NULL;
2087-
}
2088-
else
2089-
{
2090-
n->raw_expr =$2;
2091-
}
2076+
n->raw_expr =$2;
20922077
n->cooked_expr =NULL;
20932078
n->keys =NULL;
20942079
n->indexspace =NULL;
@@ -9763,23 +9748,6 @@ parser_init(void)
97639748
QueryIsRule = FALSE;
97649749
}
97659750

9766-
/* exprIsNullConstant()
9767-
* Test whether an a_expr is a plain NULL constant or not.
9768-
*/
9769-
bool
9770-
exprIsNullConstant(Node *arg)
9771-
{
9772-
if (arg && IsA(arg, A_Const))
9773-
{
9774-
A_Const *con = (A_Const *) arg;
9775-
9776-
if (con->val.type == T_Null &&
9777-
con->typename == NULL)
9778-
return TRUE;
9779-
}
9780-
return FALSE;
9781-
}
9782-
97839751
/* doNegate()
97849752
* Handle negation of a numeric constant.
97859753
*

‎src/backend/parser/parse_expr.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.221 2007/06/23 22:12:51 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.222 2007/10/29 19:40:40 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -606,6 +606,21 @@ transformParamRef(ParseState *pstate, ParamRef *pref)
606606
return (Node*)param;
607607
}
608608

609+
/* Test whether an a_expr is a plain NULL constant or not */
610+
staticbool
611+
exprIsNullConstant(Node*arg)
612+
{
613+
if (arg&&IsA(arg,A_Const))
614+
{
615+
A_Const*con= (A_Const*)arg;
616+
617+
if (con->val.type==T_Null&&
618+
con->typename==NULL)
619+
return true;
620+
}
621+
return false;
622+
}
623+
609624
staticNode*
610625
transformAExprOp(ParseState*pstate,A_Expr*a)
611626
{

‎src/backend/parser/parse_utilcmd.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
2020
* Portions Copyright (c) 1994, Regents of the University of California
2121
*
22-
*$PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.3 2007/08/27 03:36:08 tgl Exp $
22+
*$PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.4 2007/10/29 19:40:40 tgl Exp $
2323
*
2424
*-------------------------------------------------------------------------
2525
*/
@@ -440,7 +440,6 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
440440
(errcode(ERRCODE_SYNTAX_ERROR),
441441
errmsg("multiple default values specified for column \"%s\" of table \"%s\"",
442442
column->colname,cxt->relation->relname)));
443-
/* Note: DEFAULT NULL maps to constraint->raw_expr == NULL */
444443
column->raw_default=constraint->raw_expr;
445444
Assert(constraint->cooked_expr==NULL);
446445
saw_default= true;

‎src/include/parser/gramparse.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.38 2007/01/05 22:19:56 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/parser/gramparse.h,v 1.39 2007/10/2919:40:40 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -54,6 +54,5 @@ extern void parser_init(void);
5454
externintbase_yyparse(void);
5555
externList*SystemFuncName(char*name);
5656
externTypeName*SystemTypeName(char*name);
57-
externboolexprIsNullConstant(Node*arg);
5857

5958
#endif/* GRAMPARSE_H */

‎src/test/regress/expected/domain.out

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,15 @@ create table defaulttest
205205
, col8 ddef5
206206
);
207207
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "defaulttest_pkey" for table "defaulttest"
208-
insert into defaulttest default values;
208+
insert into defaulttest(col4) values(0); -- fails, col5 defaults to null
209+
ERROR: null value in column "col5" violates not-null constraint
210+
alter table defaulttest alter column col5 drop default;
211+
insert into defaulttest default values; -- succeeds, inserts domain default
212+
-- We used to treat SET DEFAULT NULL as equivalent to DROP DEFAULT; wrong
213+
alter table defaulttest alter column col5 set default null;
214+
insert into defaulttest(col4) values(0); -- fails
215+
ERROR: null value in column "col5" violates not-null constraint
216+
alter table defaulttest alter column col5 drop default;
209217
insert into defaulttest default values;
210218
insert into defaulttest default values;
211219
-- Test defaults with copy

‎src/test/regress/sql/domain.sql

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,13 @@ create table defaulttest
168168
, col7 ddef4 DEFAULT8000
169169
, col8 ddef5
170170
);
171-
insert into defaulttest defaultvalues;
171+
insert into defaulttest(col4)values(0);-- fails, col5 defaults to null
172+
altertable defaulttest alter column col5 drop default;
173+
insert into defaulttest defaultvalues;-- succeeds, inserts domain default
174+
-- We used to treat SET DEFAULT NULL as equivalent to DROP DEFAULT; wrong
175+
altertable defaulttest alter column col5set defaultnull;
176+
insert into defaulttest(col4)values(0);-- fails
177+
altertable defaulttest alter column col5 drop default;
172178
insert into defaulttest defaultvalues;
173179
insert into defaulttest defaultvalues;
174180

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp