Index: src/backend/catalog/heap.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/catalog/heap.c,v retrieving revision 1.324 diff -c -r1.324 heap.c *** src/backend/catalog/heap.c 12 Oct 2007 18:55:11 -0000 1.324 --- src/backend/catalog/heap.c 28 Oct 2007 21:04:59 -0000 *************** *** 1722,1727 **** --- 1722,1736 ---- atp->atttypid, atp->atttypmod, NameStr(atp->attname)); + /* + * If the expression is just a NULL constant, we do not bother + * to make an explicit pg_attrdef entry, since the default behavior + * is equivalent. + */ + if (expr == NULL || + (IsA(expr, Const) && ((Const *) expr)->constisnull)) + continue; + StoreAttrDefault(rel, colDef->attnum, nodeToString(expr)); cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint)); Index: src/backend/commands/typecmds.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/commands/typecmds.c,v retrieving revision 1.108 diff -c -r1.108 typecmds.c *** src/backend/commands/typecmds.c 29 Sep 2007 17:18:58 -0000 1.108 --- src/backend/commands/typecmds.c 28 Oct 2007 21:04:59 -0000 *************** *** 765,784 **** domainName); /* ! * Expression must be stored as a nodeToString result, but ! * we also require a valid textual representation (mainly ! * to make life easier for pg_dump). */ ! defaultValue = ! deparse_expression(defaultExpr, ! deparse_context_for(domainName, ! InvalidOid), ! false, false); ! defaultValueBin = nodeToString(defaultExpr); } else { ! /* DEFAULT NULL is same as not having a default */ defaultValue = NULL; defaultValueBin = NULL; } --- 765,798 ---- domainName); /* ! * If the expression is just a NULL constant, we treat ! * it like not having a default. */ ! if (defaultExpr == NULL || ! (IsA(defaultExpr, Const) && ! ((Const *) defaultExpr)->constisnull)) ! { ! defaultValue = NULL; ! defaultValueBin = NULL; ! } ! else ! { ! /* ! * Expression must be stored as a nodeToString result, ! * but we also require a valid textual representation ! * (mainly to make life easier for pg_dump). ! */ ! defaultValue = ! deparse_expression(defaultExpr, ! deparse_context_for(domainName, ! InvalidOid), ! false, false); ! defaultValueBin = nodeToString(defaultExpr); ! } } else { ! /* No default (can this still happen?) */ defaultValue = NULL; defaultValueBin = NULL; } *************** *** 1443,1449 **** MemSet(new_record_nulls, ' ', sizeof(new_record_nulls)); MemSet(new_record_repl, ' ', sizeof(new_record_repl)); ! /* Store the new default, if null then skip this step */ if (defaultRaw) { /* Create a dummy ParseState for transformExpr */ --- 1457,1463 ---- MemSet(new_record_nulls, ' ', sizeof(new_record_nulls)); MemSet(new_record_repl, ' ', sizeof(new_record_repl)); ! /* Store the new default into the tuple */ if (defaultRaw) { /* Create a dummy ParseState for transformExpr */ *************** *** 1459,1488 **** NameStr(typTup->typname)); /* ! * Expression must be stored as a nodeToString result, but we also ! * require a valid textual representation (mainly to make life easier ! * for pg_dump). */ ! defaultValue = deparse_expression(defaultExpr, deparse_context_for(NameStr(typTup->typname), InvalidOid), false, false); ! /* ! * Form an updated tuple with the new default and write it back. ! */ ! new_record[Anum_pg_type_typdefaultbin - 1] = DirectFunctionCall1(textin, ! CStringGetDatum( ! nodeToString(defaultExpr))); ! new_record_repl[Anum_pg_type_typdefaultbin - 1] = 'r'; ! new_record[Anum_pg_type_typdefault - 1] = DirectFunctionCall1(textin, CStringGetDatum(defaultValue)); ! new_record_repl[Anum_pg_type_typdefault - 1] = 'r'; } else - /* Default is NULL, drop it */ { new_record_nulls[Anum_pg_type_typdefaultbin - 1] = 'n'; new_record_repl[Anum_pg_type_typdefaultbin - 1] = 'r'; new_record_nulls[Anum_pg_type_typdefault - 1] = 'n'; --- 1473,1517 ---- NameStr(typTup->typname)); /* ! * If the expression is just a NULL constant, we treat the command ! * like ALTER ... DROP DEFAULT. */ ! if (defaultExpr == NULL || ! (IsA(defaultExpr, Const) && ((Const *) defaultExpr)->constisnull)) ! { ! /* Default is NULL, drop it */ ! new_record_nulls[Anum_pg_type_typdefaultbin - 1] = 'n'; ! new_record_repl[Anum_pg_type_typdefaultbin - 1] = 'r'; ! new_record_nulls[Anum_pg_type_typdefault - 1] = 'n'; ! new_record_repl[Anum_pg_type_typdefault - 1] = 'r'; ! } ! else ! { ! /* ! * Expression must be stored as a nodeToString result, but we also ! * require a valid textual representation (mainly to make life ! * easier for pg_dump). ! */ ! defaultValue = deparse_expression(defaultExpr, deparse_context_for(NameStr(typTup->typname), InvalidOid), false, false); ! /* ! * Form an updated tuple with the new default and write it back. ! */ ! new_record[Anum_pg_type_typdefaultbin - 1] = DirectFunctionCall1(textin, ! CStringGetDatum(nodeToString(defaultExpr))); ! new_record_repl[Anum_pg_type_typdefaultbin - 1] = 'r'; ! new_record[Anum_pg_type_typdefault - 1] = DirectFunctionCall1(textin, CStringGetDatum(defaultValue)); ! new_record_repl[Anum_pg_type_typdefault - 1] = 'r'; ! } } else { + /* ALTER ... DROP DEFAULT */ new_record_nulls[Anum_pg_type_typdefaultbin - 1] = 'n'; new_record_repl[Anum_pg_type_typdefaultbin - 1] = 'r'; new_record_nulls[Anum_pg_type_typdefault - 1] = 'n'; Index: src/backend/parser/gram.y =================================================================== RCS file: /cvsroot/pgsql/src/backend/parser/gram.y,v retrieving revision 2.603 diff -c -r2.603 gram.y *** src/backend/parser/gram.y 24 Sep 2007 01:29:28 -0000 2.603 --- src/backend/parser/gram.y 28 Oct 2007 21:05:00 -0000 *************** *** 1685,1698 **** ; alter_column_default: ! SET DEFAULT a_expr ! { ! /* Treat SET DEFAULT NULL the same as DROP DEFAULT */ ! if (exprIsNullConstant($3)) ! $$ = NULL; ! else ! $$ = $3; ! } | DROP DEFAULT { $$ = NULL; } ; --- 1685,1691 ---- ; alter_column_default: ! SET DEFAULT a_expr { $$ = $3; } | DROP DEFAULT { $$ = NULL; } ; *************** *** 2080,2094 **** Constraint *n = makeNode(Constraint); n->contype = CONSTR_DEFAULT; n->name = NULL; ! if (exprIsNullConstant($2)) ! { ! /* DEFAULT NULL should be reported as empty expr */ ! n->raw_expr = NULL; ! } ! else ! { ! n->raw_expr = $2; ! } n->cooked_expr = NULL; n->keys = NULL; n->indexspace = NULL; --- 2073,2079 ---- Constraint *n = makeNode(Constraint); n->contype = CONSTR_DEFAULT; n->name = NULL; ! n->raw_expr = $2; n->cooked_expr = NULL; n->keys = NULL; n->indexspace = NULL; *************** *** 9763,9785 **** QueryIsRule = FALSE; } - /* exprIsNullConstant() - * Test whether an a_expr is a plain NULL constant or not. - */ - bool - exprIsNullConstant(Node *arg) - { - if (arg && IsA(arg, A_Const)) - { - A_Const *con = (A_Const *) arg; - - if (con->val.type == T_Null && - con->typename == NULL) - return TRUE; - } - return FALSE; - } - /* doNegate() * Handle negation of a numeric constant. * --- 9748,9753 ---- Index: src/backend/parser/parse_expr.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v retrieving revision 1.221 diff -c -r1.221 parse_expr.c *** src/backend/parser/parse_expr.c 23 Jun 2007 22:12:51 -0000 1.221 --- src/backend/parser/parse_expr.c 28 Oct 2007 21:05:00 -0000 *************** *** 606,611 **** --- 606,626 ---- return (Node *) param; } + /* Test whether an a_expr is a plain NULL constant or not */ + static bool + exprIsNullConstant(Node *arg) + { + if (arg && IsA(arg, A_Const)) + { + A_Const *con = (A_Const *) arg; + + if (con->val.type == T_Null && + con->typename == NULL) + return true; + } + return false; + } + static Node * transformAExprOp(ParseState *pstate, A_Expr *a) { Index: src/backend/parser/parse_utilcmd.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/parser/parse_utilcmd.c,v retrieving revision 2.3 diff -c -r2.3 parse_utilcmd.c *** src/backend/parser/parse_utilcmd.c 27 Aug 2007 03:36:08 -0000 2.3 --- src/backend/parser/parse_utilcmd.c 28 Oct 2007 21:05:00 -0000 *************** *** 440,446 **** (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple default values specified for column \"%s\" of table \"%s\"", column->colname, cxt->relation->relname))); - /* Note: DEFAULT NULL maps to constraint->raw_expr == NULL */ column->raw_default = constraint->raw_expr; Assert(constraint->cooked_expr == NULL); saw_default = true; --- 440,445 ---- Index: src/include/parser/gramparse.h =================================================================== RCS file: /cvsroot/pgsql/src/include/parser/gramparse.h,v retrieving revision 1.38 diff -c -r1.38 gramparse.h *** src/include/parser/gramparse.h 5 Jan 2007 22:19:56 -0000 1.38 --- src/include/parser/gramparse.h 28 Oct 2007 21:05:00 -0000 *************** *** 54,59 **** extern int base_yyparse(void); extern List *SystemFuncName(char *name); extern TypeName *SystemTypeName(char *name); - extern bool exprIsNullConstant(Node *arg); #endif /* GRAMPARSE_H */ --- 54,58 ----