1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-09 06:21:09 +03:00

Back out domain patch until it works properly.

This commit is contained in:
Bruce Momjian
2002-03-07 16:35:41 +00:00
parent 609f71b760
commit b976b8af80
32 changed files with 270 additions and 1654 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.185 2002/03/06 20:34:45 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.186 2002/03/07 16:35:33 momjian Exp $
*
*
* INTERFACE ROUTINES
@@ -698,15 +698,10 @@ AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid)
"oidin", /* receive procedure */
"oidout", /* send procedure */
NULL, /* array element type - irrelevant */
NULL, /* baseType Name -- typically for domiains */
NULL, /* default type value - none */
NULL, /* default type binary representation */
true, /* passed by value */
'i', /* default alignment - same as for OID */
'p', /* Not TOASTable */
-1, /* Type mod length */
0, /* array dimensions for typBaseType */
false); /* Type NOT NULL */
'p'); /* Not TOASTable */
}
/* --------------------------------
@@ -1589,10 +1584,6 @@ AddRelationRawConstraints(Relation rel,
int numchecks;
List *listptr;
/* Probably shouldn't be null by default */
Node *expr = NULL;
/*
* Get info about existing constraints.
*/
@@ -1623,13 +1614,68 @@ AddRelationRawConstraints(Relation rel,
foreach(listptr, rawColDefaults)
{
RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
Node *expr;
Oid type_id;
Assert(colDef->raw_default != NULL);
Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
/*
* Transform raw parsetree to executable expression.
*/
expr = transformExpr(pstate, colDef->raw_default, EXPR_COLUMN_FIRST);
expr = cookDefault(pstate, colDef->raw_default
, atp->atttypid, atp->atttypmod
, NameStr(atp->attname));
/*
* Make sure default expr does not refer to any vars.
*/
if (contain_var_clause(expr))
elog(ERROR, "cannot use column references in DEFAULT clause");
/*
* No subplans or aggregates, either...
*/
if (contain_subplans(expr))
elog(ERROR, "cannot use subselects in DEFAULT clause");
if (contain_agg_clause(expr))
elog(ERROR, "cannot use aggregate functions in DEFAULT clause");
/*
* Check that it will be possible to coerce the expression to the
* column's type. We store the expression without coercion,
* however, to avoid premature coercion in cases like
*
* CREATE TABLE tbl (fld datetime DEFAULT 'now'::text);
*
* NB: this should match the code in optimizer/prep/preptlist.c that
* will actually do the coercion, to ensure we don't accept an
* unusable default expression.
*/
type_id = exprType(expr);
if (type_id != InvalidOid)
{
Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
if (type_id != atp->atttypid)
{
if (CoerceTargetExpr(NULL, expr, type_id,
atp->atttypid, atp->atttypmod) == NULL)
elog(ERROR, "Column \"%s\" is of type %s"
" but default expression is of type %s"
"\n\tYou will need to rewrite or cast the expression",
NameStr(atp->attname),
format_type_be(atp->atttypid),
format_type_be(type_id));
}
}
/*
* Might as well try to reduce any constant expressions.
*/
expr = eval_const_expressions(expr);
/*
* Must fix opids, in case any operators remain...
*/
fix_opids(expr);
/*
* OK, store it.
@@ -1846,88 +1892,6 @@ SetRelationNumChecks(Relation rel, int numchecks)
heap_close(relrel, RowExclusiveLock);
}
/*
* Take a raw default and convert it to a cooked format ready for
* storage.
*
* Parse state, attypid, attypmod and attname are required for
* CoerceTargetExpr() and more importantly transformExpr().
*/
Node *
cookDefault(ParseState *pstate
, Node *raw_default
, Oid atttypid
, int32 atttypmod
, char *attname) {
Oid type_id;
Node *expr;
Assert(raw_default != NULL);
/*
* Transform raw parsetree to executable expression.
*/
expr = transformExpr(pstate, raw_default, EXPR_COLUMN_FIRST);
/*
* Make sure default expr does not refer to any vars.
*/
if (contain_var_clause(expr))
elog(ERROR, "cannot use column references in DEFAULT clause");
/*
* No subplans or aggregates, either...
*/
if (contain_subplans(expr))
elog(ERROR, "cannot use subselects in DEFAULT clause");
if (contain_agg_clause(expr))
elog(ERROR, "cannot use aggregate functions in DEFAULT clause");
/*
* Check that it will be possible to coerce the expression to the
* column's type. We store the expression without coercion,
* however, to avoid premature coercion in cases like
*
* CREATE TABLE tbl (fld datetime DEFAULT 'now'::text);
*
* NB: this should match the code in optimizer/prep/preptlist.c that
* will actually do the coercion, to ensure we don't accept an
* unusable default expression.
*/
type_id = exprType(expr);
if (type_id != InvalidOid && atttypid != InvalidOid) {
if (type_id != atttypid) {
/* Try coercing to the base type of the domain if available */
if (CoerceTargetExpr(pstate, expr, type_id,
getBaseType(atttypid),
atttypmod) == NULL) {
elog(ERROR, "Column \"%s\" is of type %s"
" but default expression is of type %s"
"\n\tYou will need to rewrite or cast the expression",
attname,
format_type_be(atttypid),
format_type_be(type_id));
}
}
}
/*
* Might as well try to reduce any constant expressions.
*/
expr = eval_const_expressions(expr);
/*
* Must fix opids, in case any operators remain...
*/
fix_opids(expr);
return(expr);
}
static void
RemoveAttrDefaults(Relation rel)
{

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.66 2002/03/06 20:34:46 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.67 2002/03/07 16:35:33 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -178,13 +178,8 @@ TypeShellMakeWithOpenRelation(Relation pg_type_desc, char *typeName)
values[i++] = ObjectIdGetDatum(InvalidOid); /* 14 */
values[i++] = CharGetDatum('i'); /* 15 */
values[i++] = CharGetDatum('p'); /* 16 */
values[i++] = BoolGetDatum(false); /* 17 */
values[i++] = Int32GetDatum(-1); /* 18 */
values[i++] = DirectFunctionCall1(textin,
CStringGetDatum(typeName)); /* 19 */
values[i++] = DirectFunctionCall1(textin,
CStringGetDatum(typeName)); /* 20 */
CStringGetDatum(typeName)); /* 17 */
/*
* create a new type tuple with FormHeapTuple
@@ -269,7 +264,7 @@ TypeShellMake(char *typeName)
Oid
TypeCreate(char *typeName,
Oid assignedTypeOid,
Oid relationOid, /* only for 'c'atalog typeTypes */
Oid relationOid, /* only for 'c'atalog typeTypes */
int16 internalSize,
int16 externalSize,
char typeType,
@@ -279,15 +274,10 @@ TypeCreate(char *typeName,
char *receiveProcedure,
char *sendProcedure,
char *elementTypeName,
char *baseTypeName,
char *defaultTypeValue, /* human readable rep */
char *defaultTypeBin, /* cooked rep */
char *defaultTypeValue, /* internal rep */
bool passedByValue,
char alignment,
char storage,
int32 typeMod,
int32 typNDims, /* Array dimensions for baseTypeName */
bool typeNotNull) /* binary default representation (cooked) */
char storage)
{
int i,
j;
@@ -295,7 +285,6 @@ TypeCreate(char *typeName,
HeapScanDesc pg_type_scan;
Oid typeObjectId;
Oid elementObjectId = InvalidOid;
Oid baseObjectId = InvalidOid;
HeapTuple tup;
char nulls[Natts_pg_type];
char replaces[Natts_pg_type];
@@ -328,17 +317,6 @@ TypeCreate(char *typeName,
elog(ERROR, "type %s does not exist", elementTypeName);
}
/*
* if this type has an associated baseType, then we check that it
* is defined.
*/
if (baseTypeName)
{
baseObjectId = TypeGet(baseTypeName, &defined);
if (!defined)
elog(ERROR, "type %s does not exist", baseTypeName);
}
/*
* validate size specifications: either positive (fixed-length) or -1
* (variable-length).
@@ -410,7 +388,7 @@ TypeCreate(char *typeName,
* signature is 0,OIDOID,INT4OID. The output procedures may
* take 2 args (data value, element OID).
*/
if (OidIsValid(elementObjectId) || OidIsValid(baseObjectId))
if (OidIsValid(elementObjectId))
{
int nargs;
@@ -433,7 +411,6 @@ TypeCreate(char *typeName,
PointerGetDatum(argList),
0);
}
if (!OidIsValid(procOid))
func_error("TypeCreate", procname, 1, argList, NULL);
}
@@ -451,34 +428,6 @@ TypeCreate(char *typeName,
*/
values[i++] = CharGetDatum(storage); /* 16 */
/*
* set the typenotnull value
*/
values[i++] = BoolGetDatum(typeNotNull); /* 17 */
/*
* set the typemod value
*/
values[i++] = Int32GetDatum(typeMod); /* 18 */
values[i++] = ObjectIdGetDatum(baseObjectId); /* 19 */
/*
* Dimension number for an array base type
*/
values[i++] = Int32GetDatum(typNDims); /* 20 */
/*
* initialize the default binary value for this type. Check for
* nulls of course.
*/
if (defaultTypeBin)
values[i] = DirectFunctionCall1(textin,
CStringGetDatum(defaultTypeBin));
else
nulls[i] = 'n';
i++; /* 21 */
/*
* initialize the default value for this type.
*/
@@ -487,7 +436,7 @@ TypeCreate(char *typeName,
CStringGetDatum(defaultTypeValue));
else
nulls[i] = 'n';
i++; /* 22 */
i++; /* 17 */
/*
* open pg_type and begin a scan for the type name.

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.84 2002/03/06 20:34:46 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.85 2002/03/07 16:35:34 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -39,7 +39,7 @@ static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno);
static void StoreCatalogInheritance(Oid relationId, List *supers);
static int findAttrByName(const char *attributeName, List *schema);
static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
static List *MergeDomainAttributes(List *schema);
/* ----------------------------------------------------------------
* DefineRelation
@@ -69,13 +69,6 @@ DefineRelation(CreateStmt *stmt, char relkind)
*/
StrNCpy(relname, stmt->relname, NAMEDATALEN);
/*
* Merge domain attributes into the known columns before inheritance
* applies it's changes otherwise we risk adding double constraints
* to a domain thats inherited.
*/
schema = MergeDomainAttributes(schema);
/*
* Look up inheritance ancestors and generate relation schema,
* including inherited attributes.
@@ -244,88 +237,6 @@ TruncateRelation(char *name)
heap_truncate(name);
}
/*
* MergeDomainAttributes
* Returns a new schema with the constraints, types, and other
* attributes of the domain resolved.
*
* Defaults are processed at execution time by taking the default of
* the type (domain) if it is null. This does not need to be merged
* here.
*/
static List *
MergeDomainAttributes(List *schema)
{
List *entry;
/*
* Loop through the table elements supplied. These should
* never include inherited domains else they'll be
* double (or more) processed.
*/
foreach(entry, schema)
{
ColumnDef *coldef = lfirst(entry);
HeapTuple tuple;
Form_pg_type typeTup;
tuple = SearchSysCache(TYPENAME,
CStringGetDatum(coldef->typename->name),
0,0,0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "MergeDomainAttributes: Type %s does not exist",
coldef->typename->name);
typeTup = (Form_pg_type) GETSTRUCT(tuple);
if (typeTup->typtype == 'd') {
/*
* This is a domain, lets force the properties of the domain on to
* the new column.
*/
/* Enforce the typmod value */
coldef->typename->typmod = typeTup->typmod;
/* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */
coldef->is_not_null |= typeTup->typnotnull;
/* Enforce the element type in the event the domain is an array
*
* BUG: How do we fill out arrayBounds and attrname from typelem and typNDimms?
*/
}
ReleaseSysCache(tuple);
//typedef struct TypeName
//{
//NodeTag type;
//char *name; /* name of the type */
//bool timezone; /* timezone specified? */
//bool setof; /* is a set? */
//int32 typmod; /* type modifier */
//List *arrayBounds; /* array bounds */
//char *attrname; /* field name when using %TYPE */
//} TypeName;
// ColumnDef
// NodeTag type;
// char *colname; /* name of column */
// TypeName *typename; /* type of column */
// bool is_not_null; /* NOT NULL constraint specified? */
// Node *raw_default; /* default value (untransformed parse
// * tree) */
// char *cooked_default; /* nodeToString representation */
// List *constraints; /* other constraints on column */
}
return schema;
}
/*----------
* MergeAttributes
* Returns new schema given initial schema and superclasses.

View File

@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.68 2002/03/06 20:34:47 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.69 2002/03/07 16:35:34 momjian Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -40,7 +40,6 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/heap.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_language.h"
#include "catalog/pg_operator.h"
@@ -476,322 +475,6 @@ DefineAggregate(char *aggName, List *parameters)
initval); /* initial condition */
}
/*
* DefineDomain
* Registers a new domain.
*/
void
DefineDomain(CreateDomainStmt *stmt)
{
int16 internalLength = -1; /* int2 */
int16 externalLength = -1; /* int2 */
char *inputName = NULL;
char *outputName = NULL;
char *sendName = NULL;
char *receiveName = NULL;
/*
* Domains store the external representation in defaultValue
* and the interal Node representation in defaultValueBin
*/
char *defaultValue = NULL;
char *defaultValueBin = NULL;
bool byValue = false;
char delimiter = DEFAULT_TYPDELIM;
char alignment = 'i'; /* default alignment */
char storage = 'p'; /* default TOAST storage method */
char typtype;
Datum datum;
bool typNotNull = false;
char *elemName = NULL;
int32 typNDims = 0; /* No array dimensions by default */
bool isnull;
Relation pg_type_rel;
TupleDesc pg_type_dsc;
HeapTuple typeTup;
char *typeName = stmt->typename->name;
List *listptr;
List *schema = stmt->constraints;
/*
* Domainnames, unlike typenames don't need to account for the '_'
* prefix. So they can be one character longer.
*/
if (strlen(stmt->domainname) > (NAMEDATALEN - 1))
elog(ERROR, "CREATE DOMAIN: domain names must be %d characters or less",
NAMEDATALEN - 1);
/* Test for existing Domain (or type) of that name */
typeTup = SearchSysCache( TYPENAME
, PointerGetDatum(stmt->domainname)
, 0, 0, 0
);
if (HeapTupleIsValid(typeTup))
{
elog(ERROR, "CREATE DOMAIN: domain or type %s already exists",
stmt->domainname);
}
/*
* Get the information about old types
*/
pg_type_rel = heap_openr(TypeRelationName, RowExclusiveLock);
pg_type_dsc = RelationGetDescr(pg_type_rel);
/*
* When the type is an array for some reason we don't actually receive
* the name here. We receive the base types name. Lets set Dims while
* were at it.
*/
if (stmt->typename->arrayBounds > 0) {
typeName = makeArrayTypeName(stmt->typename->name);
typNDims = length(stmt->typename->arrayBounds);
}
typeTup = SearchSysCache( TYPENAME
, PointerGetDatum(typeName)
, 0, 0, 0
);
if (!HeapTupleIsValid(typeTup))
{
elog(ERROR, "CREATE DOMAIN: type %s does not exist",
stmt->typename->name);
}
/* Check that this is a basetype */
typtype = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typtype, pg_type_dsc, &isnull));
Assert(!isnull);
/*
* What we really don't want is domains of domains. This could cause all sorts
* of neat issues if we allow that.
*
* With testing, we may determine complex types should be allowed
*/
if (typtype != 'b') {
elog(ERROR, "DefineDomain: %s is not a basetype", stmt->typename->name);
}
/* passed by value */
byValue = DatumGetBool(heap_getattr(typeTup, Anum_pg_type_typbyval, pg_type_dsc, &isnull));
Assert(!isnull);
/* Required Alignment */
alignment = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typalign, pg_type_dsc, &isnull));
Assert(!isnull);
/* Storage Length */
internalLength = DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typlen, pg_type_dsc, &isnull));
Assert(!isnull);
/* External Length (unused) */
externalLength = DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typprtlen, pg_type_dsc, &isnull));
Assert(!isnull);
/* Array element Delimiter */
delimiter = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typdelim, pg_type_dsc, &isnull));
Assert(!isnull);
/* Input Function Name */
datum = heap_getattr(typeTup, Anum_pg_type_typinput, pg_type_dsc, &isnull);
Assert(!isnull);
inputName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
/* Output Function Name */
datum = heap_getattr(typeTup, Anum_pg_type_typoutput, pg_type_dsc, &isnull);
Assert(!isnull);
outputName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
/* ReceiveName */
datum = heap_getattr(typeTup, Anum_pg_type_typreceive, pg_type_dsc, &isnull);
Assert(!isnull);
receiveName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
/* SendName */
datum = heap_getattr(typeTup, Anum_pg_type_typsend, pg_type_dsc, &isnull);
Assert(!isnull);
sendName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
/* TOAST Strategy */
storage = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typstorage, pg_type_dsc, &isnull));
Assert(!isnull);
/* Inherited default value */
datum = heap_getattr(typeTup, Anum_pg_type_typdefault, pg_type_dsc, &isnull);
if (!isnull) {
defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum));
}
/*
* Pull out the typelem name of the parent OID.
*
* This is what enables us to make a domain of an array
*/
datum = heap_getattr(typeTup, Anum_pg_type_typelem, pg_type_dsc, &isnull);
Assert(!isnull);
if (DatumGetObjectId(datum) != InvalidOid) {
HeapTuple tup;
tup = SearchSysCache( TYPEOID
, datum
, 0, 0, 0
);
elemName = NameStr(((Form_pg_type) GETSTRUCT(tup))->typname);
ReleaseSysCache(tup);
}
/*
* Run through constraints manually avoids the additional
* processing conducted by DefineRelation() and friends.
*
* Besides, we don't want any constraints to be cooked. We'll
* do that when the table is created via MergeDomainAttributes().
*/
foreach(listptr, schema)
{
bool nullDefined = false;
Node *expr;
Constraint *colDef = lfirst(listptr);
/* Used for the statement transformation */
ParseState *pstate;
/*
* Create a dummy ParseState and insert the target relation as its
* sole rangetable entry. We need a ParseState for transformExpr.
*/
pstate = make_parsestate(NULL);
switch(colDef->contype) {
/*
* The inherited default value may be overridden by the user
* with the DEFAULT <expr> statement.
*
* We have to search the entire constraint tree returned as we
* don't want to cook or fiddle too much.
*/
case CONSTR_DEFAULT:
/*
* Cook the colDef->raw_expr into an expression to ensure
* that it can be done. We store the text version of the
* raw value.
*
* Note: Name is strictly for error message
*/
expr = cookDefault(pstate, colDef->raw_expr
, typeTup->t_data->t_oid
, stmt->typename->typmod
, stmt->typename->name);
/* Binary default required */
defaultValue = deparse_expression(expr,
deparse_context_for(stmt->domainname,
InvalidOid),
false);
defaultValueBin = nodeToString(expr);
break;
/*
* Find the NULL constraint.
*/
case CONSTR_NOTNULL:
if (nullDefined) {
elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
} else {
typNotNull = true;
nullDefined = true;
}
break;
case CONSTR_NULL:
if (nullDefined) {
elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
} else {
typNotNull = false;
nullDefined = true;
}
break;
case CONSTR_UNIQUE:
elog(ERROR, "CREATE DOMAIN / UNIQUE indecies not supported");
break;
case CONSTR_PRIMARY:
elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indecies not supported");
break;
case CONSTR_CHECK:
elog(ERROR, "defineDomain: CHECK Constraints not supported");
break;
case CONSTR_ATTR_DEFERRABLE:
case CONSTR_ATTR_NOT_DEFERRABLE:
case CONSTR_ATTR_DEFERRED:
case CONSTR_ATTR_IMMEDIATE:
elog(ERROR, "defineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported");
break;
}
}
/*
* Have TypeCreate do all the real work.
*/
TypeCreate(stmt->domainname, /* type name */
InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */
internalLength, /* internal size */
externalLength, /* external size */
'd', /* type-type (domain type) */
delimiter, /* array element delimiter */
inputName, /* input procedure */
outputName, /* output procedure */
receiveName, /* receive procedure */
sendName, /* send procedure */
elemName, /* element type name */
typeName, /* base type name */
defaultValue, /* default type value */
defaultValueBin, /* default type value */
byValue, /* passed by value */
alignment, /* required alignment */
storage, /* TOAST strategy */
stmt->typename->typmod, /* typeMod value */
typNDims, /* Array dimensions for base type */
typNotNull); /* Type NOT NULL */
/*
* Now we can clean up.
*/
ReleaseSysCache(typeTup);
heap_close(pg_type_rel, NoLock);
}
/*
* DefineType
* Registers a new type.
@@ -807,8 +490,6 @@ DefineType(char *typeName, List *parameters)
char *sendName = NULL;
char *receiveName = NULL;
char *defaultValue = NULL;
char *defaultValueBin = NULL;
Node *defaultRaw = (Node *) NULL;
bool byValue = false;
char delimiter = DEFAULT_TYPDELIM;
char *shadow_type;
@@ -850,7 +531,7 @@ DefineType(char *typeName, List *parameters)
else if (strcasecmp(defel->defname, "element") == 0)
elemName = defGetString(defel);
else if (strcasecmp(defel->defname, "default") == 0)
defaultRaw = defel->arg;
defaultValue = defGetString(defel);
else if (strcasecmp(defel->defname, "passedbyvalue") == 0)
byValue = true;
else if (strcasecmp(defel->defname, "alignment") == 0)
@@ -910,32 +591,6 @@ DefineType(char *typeName, List *parameters)
if (outputName == NULL)
elog(ERROR, "Define: \"output\" unspecified");
if (defaultRaw) {
Node *expr;
ParseState *pstate;
/*
* Create a dummy ParseState and insert the target relation as its
* sole rangetable entry. We need a ParseState for transformExpr.
*/
pstate = make_parsestate(NULL);
expr = cookDefault(pstate, defaultRaw,
InvalidOid,
-1,
typeName);
/* Binary default required */
defaultValue = deparse_expression(expr,
deparse_context_for(typeName,
InvalidOid),
false);
defaultValueBin = nodeToString(expr);
}
/*
* now have TypeCreate do all the real work.
*/
@@ -951,15 +606,10 @@ DefineType(char *typeName, List *parameters)
receiveName, /* receive procedure */
sendName, /* send procedure */
elemName, /* element type name */
NULL, /* base type name (Non-zero for domains) */
defaultValue, /* default type value */
defaultValueBin, /* default type value (Binary form) */
byValue, /* passed by value */
alignment, /* required alignment */
storage, /* TOAST strategy */
-1, /* typMod (Domains only) */
0, /* Array Dimensions of typbasetype */
'f'); /* Type NOT NULL */
storage); /* TOAST strategy */
/*
* When we create a base type (as opposed to a complex type) we need
@@ -982,15 +632,10 @@ DefineType(char *typeName, List *parameters)
"array_in", /* receive procedure */
"array_out", /* send procedure */
typeName, /* element type name */
NULL, /* base type name */
NULL, /* never a default type value */
NULL, /* binary default isn't sent either */
false, /* never passed by value */
alignment, /* see above */
'x', /* ARRAY is always toastable */
-1, /* typMod (Domains only) */
0, /* Array dimensions of typbasetype */
'f'); /* Type NOT NULL */
'x'); /* ARRAY is always toastable */
pfree(shadow_type);
}

View File

@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* remove.c
* POSTGRES remove (domain | function | type | operator ) utilty code.
* POSTGRES remove (function | type | operator ) utilty code.
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.67 2002/03/06 20:34:47 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.68 2002/03/07 16:35:34 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,7 +22,6 @@
#include "commands/comment.h"
#include "commands/defrem.h"
#include "miscadmin.h"
#include "parser/parse.h"
#include "parser/parse_agg.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
@@ -276,60 +275,6 @@ RemoveType(char *typeName) /* type name to be removed */
heap_close(relation, RowExclusiveLock);
}
/*
* RemoveDomain
* Removes the domain 'typeName' and all attributes and relations that
* use it.
*/
void
RemoveDomain(char *domainName, int behavior) /* domain name to be removed */
{
Relation relation;
HeapTuple tup;
TupleDesc description;
char typtype;
bool isnull;
/* Domains are stored as types. Check for permissions on the type */
if (!pg_ownercheck(GetUserId(), domainName, TYPENAME))
elog(ERROR, "RemoveDomain: type '%s': permission denied",
domainName);
relation = heap_openr(TypeRelationName, RowExclusiveLock);
description = RelationGetDescr(relation);
tup = SearchSysCache(TYPENAME,
PointerGetDatum(domainName),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "RemoveType: type '%s' does not exist", domainName);
/* Check that this is actually a domain */
typtype = DatumGetChar(heap_getattr(tup, Anum_pg_type_typtype, description, &isnull));
Assert(!isnull);
if (typtype != 'd') {
elog(ERROR, "%s is not a domain", domainName);
}
/* CASCADE unsupported */
if (behavior == CASCADE) {
elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword");
}
/* Delete any comments associated with this type */
DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
simple_heap_delete(relation, &tup->t_self);
ReleaseSysCache(tup);
heap_close(relation, RowExclusiveLock);
}
/*
* RemoveFunction
* Deletes a function.

View File

@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.166 2002/03/06 20:34:47 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.167 2002/03/07 16:35:34 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2227,19 +2227,6 @@ _copyLoadStmt(LoadStmt *from)
return newnode;
}
static CreateDomainStmt *
_copyCreateDomainStmt(CreateDomainStmt *from)
{
CreateDomainStmt *newnode = makeNode(CreateDomainStmt);
if (from->domainname)
newnode->domainname = pstrdup(from->domainname);
if (from->typename)
newnode->typename = from->typename;
return newnode;
}
static CreatedbStmt *
_copyCreatedbStmt(CreatedbStmt *from)
{

View File

@@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.114 2002/03/06 20:34:48 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.115 2002/03/07 16:35:34 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1095,17 +1095,6 @@ _equalLoadStmt(LoadStmt *a, LoadStmt *b)
return true;
}
static bool
_equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b)
{
if (!equalstr(a->domainname, b->domainname))
return false;
if (!equal(a->typename, b->typename))
return false;
return true;
}
static bool
_equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
{
@@ -2022,9 +2011,6 @@ equal(void *a, void *b)
case T_LoadStmt:
retval = _equalLoadStmt(a, b);
break;
case T_CreateDomainStmt:
retval = _equalCreateDomainStmt(a, b);
break;
case T_CreatedbStmt:
retval = _equalCreatedbStmt(a, b);
break;

View File

@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.47 2002/03/06 20:34:49 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.48 2002/03/07 16:35:35 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -355,6 +355,7 @@ build_column_default(Relation rel, int attrno)
Form_pg_attribute att_tup = rd_att->attrs[attrno - 1];
Oid atttype = att_tup->atttypid;
int32 atttypmod = att_tup->atttypmod;
bool hasdefault;
Datum typedefault;
int16 typlen;
bool typbyval;
@@ -391,7 +392,7 @@ build_column_default(Relation rel, int attrno)
if (type_id != atttype)
{
expr = CoerceTargetExpr(NULL, expr, type_id,
getBaseType(atttype), atttypmod);
atttype, atttypmod);
/*
* This really shouldn't fail; should have checked the
@@ -429,53 +430,41 @@ build_column_default(Relation rel, int attrno)
* element type is, and the element type's default is irrelevant
* too.
*/
hasdefault = false;
typedefault = (Datum) 0;
typlen = sizeof(Oid);
typbyval = true;
expr = (Node *) makeConst(atttype,
typlen,
(Datum) 0,
true,
typbyval,
false, /* not a set */
false);
}
else
{
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(att_tup))
{
expr = (Node *) makeConst(atttype,
typlen,
(Datum) 0,
true,
typbyval,
false, /* not a set */
false);
hasdefault = false;
typedefault = (Datum) 0;
}
else
#endif /* _DROP_COLUMN_HACK__ */
expr = get_typdefault(atttype, atttypmod);
hasdefault = get_typdefault(atttype, &typedefault);
if (expr == NULL) {
expr = (Node *) makeConst(atttype,
typlen,
(Datum) 0,
true,
typbyval,
false, /* not a set */
false);
}
get_typlenbyval(atttype, &typlen, &typbyval);
}
expr = (Node *) makeConst(atttype,
typlen,
typedefault,
!hasdefault,
typbyval,
false, /* not a set */
false);
/*
* If the column is a fixed-length type, it may need a length coercion
* as well as a type coercion, as well as direction to the final type.
* as well as a type coercion. But NULLs don't need that.
*/
expr = coerce_type_typmod(NULL, expr,
atttype, atttypmod);
if (hasdefault)
expr = coerce_type_typmod(NULL, expr,
atttype, atttypmod);
return expr;
}

View File

@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.286 2002/03/06 20:34:49 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.287 2002/03/07 16:35:35 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -135,8 +135,7 @@ static void doNegateFloat(Value *v);
ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt,
CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
CreateUserStmt, CreateDomainStmt, CreatedbStmt, CursorStmt,
DefineStmt, DeleteStmt,
CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
@@ -290,8 +289,6 @@ static void doNegateFloat(Value *v);
%type <list> constraints_set_namelist
%type <boolean> constraints_set_mode
%type <boolean> opt_as
/*
* If you make any token changes, remember to:
* - use "yacc -d" and update parse.h
@@ -346,7 +343,7 @@ static void doNegateFloat(Value *v);
WITHOUT
/* Keywords (in SQL92 non-reserved words) */
%token COMMITTED, SERIALIZABLE, TYPE_P, DOMAIN_P
%token COMMITTED, SERIALIZABLE, TYPE_P
/* Keywords for Postgres support (not in SQL92 reserved words)
*
@@ -449,7 +446,6 @@ stmt : AlterDatabaseSetStmt
| CopyStmt
| CreateStmt
| CreateAsStmt
| CreateDomainStmt
| CreateSchemaStmt
| CreateGroupStmt
| CreateSeqStmt
@@ -780,11 +776,8 @@ DropSchemaStmt: DROP SCHEMA UserId
n->dbname = $3;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
* Set PG internal variable
@@ -1468,10 +1461,7 @@ ColConstraintElem:
n->name = NULL;
if (exprIsNullConstant($2))
{
/*
* DEFAULT NULL should be reported as empty expr
* Required for NOT NULL Domain overrides
*/
/* DEFAULT NULL should be reported as empty expr */
n->raw_expr = NULL;
}
else
@@ -2053,16 +2043,7 @@ def_list: def_elem { $$ = makeList1($1); }
| def_list ',' def_elem { $$ = lappend($1, $3); }
;
def_elem: DEFAULT '=' b_expr
{
$$ = makeNode(DefElem);
$$->defname = "default";
if (exprIsNullConstant($3))
$$->arg = (Node *)NULL;
else
$$->arg = $3;
}
| ColLabel '=' def_arg
def_elem: ColLabel '=' def_arg
{
$$ = makeNode(DefElem);
$$->defname = $1;
@@ -2097,15 +2078,6 @@ DropStmt: DROP drop_type name_list
DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
n->names = $3;
n->behavior = RESTRICT; /* Restricted by default */
$$ = (Node *)n;
}
| DROP DOMAIN_P name_list drop_behavior
{
DropStmt *n = makeNode(DropStmt);
n->removeType = DROP_DOMAIN_P;
n->names = $3;
n->behavior = $4;
$$ = (Node *)n;
}
;
@@ -2138,7 +2110,7 @@ TruncateStmt: TRUNCATE opt_table relation_name
* The COMMENT ON statement can take different forms based upon the type of
* the object associated with the comment. The form of the statement is:
*
* COMMENT ON [ [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]
* COMMENT ON [ [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]
* <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION
* <funcname> (arg1, arg2, ...) | OPERATOR <op>
* (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
@@ -2224,7 +2196,6 @@ comment_type: DATABASE { $$ = DATABASE; }
| RULE { $$ = RULE; }
| SEQUENCE { $$ = SEQUENCE; }
| TABLE { $$ = TABLE; }
| DOMAIN_P { $$ = TYPE_P; }
| TYPE_P { $$ = TYPE_P; }
| VIEW { $$ = VIEW; }
;
@@ -3251,30 +3222,6 @@ AlterDatabaseSetStmt: ALTER DATABASE database_name VariableSetStmt
}
;
/*****************************************************************************
*
* Manipulate a domain
*
*
*****************************************************************************/
CreateDomainStmt: CREATE DOMAIN_P name opt_as Typename ColQualList opt_collate
{
CreateDomainStmt *n = makeNode(CreateDomainStmt);
n->domainname = $3;
n->typename = $5;
n->constraints = $6;
if ($7 != NULL)
elog(NOTICE,"CREATE DOMAIN / COLLATE %s not yet "
"implemented; clause ignored", $7);
$$ = (Node *)n;
}
;
opt_as: AS {$$ = TRUE; }
| /* EMPTY */ {$$ = FALSE; }
;
/*****************************************************************************
*
@@ -5932,7 +5879,6 @@ unreserved_keyword:
| DEFERRED { $$ = "deferred"; }
| DELETE { $$ = "delete"; }
| DELIMITERS { $$ = "delimiters"; }
| DOMAIN_P { $$ = "domain"; }
| DOUBLE { $$ = "double"; }
| DROP { $$ = "drop"; }
| EACH { $$ = "each"; }

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.102 2002/03/06 20:34:50 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.103 2002/03/07 16:35:35 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -97,7 +97,6 @@ static ScanKeyword ScanKeywords[] = {
{"desc", DESC},
{"distinct", DISTINCT},
{"do", DO},
{"domain", DOMAIN_P},
{"double", DOUBLE},
{"drop", DROP},
{"each", EACH},

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.65 2002/03/06 20:34:51 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.66 2002/03/07 16:35:35 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -38,7 +38,6 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
{
Node *result;
if (targetTypeId == inputTypeId ||
targetTypeId == InvalidOid ||
node == NULL)
@@ -606,32 +605,3 @@ PreferredType(CATEGORY category, Oid type)
}
return result;
} /* PreferredType() */
/*
* If the targetTypeId is a domain, we really want to coerce
* the tuple to the domain type -- not the domain itself
*/
Oid
getBaseType(Oid inType)
{
HeapTuple tup;
Form_pg_type typTup;
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(inType),
0, 0, 0);
typTup = ((Form_pg_type) GETSTRUCT(tup));
/*
* Assume that typbasetype exists and is a base type, where inType
* was a domain
*/
if (typTup->typtype == 'd')
inType = typTup->typbasetype;
ReleaseSysCache(tup);
return inType;
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.106 2002/03/06 20:34:52 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.107 2002/03/07 16:35:36 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1027,8 +1027,7 @@ parser_typecast_expression(ParseState *pstate,
if (inputType != targetType)
{
expr = CoerceTargetExpr(pstate, expr, inputType,
getBaseType(targetType),
typename->typmod);
targetType, typename->typmod);
if (expr == NULL)
elog(ERROR, "Cannot cast type '%s' to '%s'",
format_type_be(inputType),
@@ -1040,7 +1039,7 @@ parser_typecast_expression(ParseState *pstate,
* as well as a type coercion.
*/
expr = coerce_type_typmod(pstate, expr,
getBaseType(targetType), typename->typmod);
targetType, typename->typmod);
return expr;
}

View File

@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.131 2002/03/06 21:49:52 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.132 2002/03/07 16:35:36 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -282,11 +282,6 @@ ProcessUtility(Node *parsetree,
/* RemoveType does its own permissions checks */
RemoveType(relname);
break;
case DROP_DOMAIN_P:
/* RemoveDomain does its own permissions checks */
RemoveDomain(relname, stmt->behavior);
break;
}
/*
@@ -731,10 +726,6 @@ ProcessUtility(Node *parsetree,
DropProceduralLanguage((DropPLangStmt *) parsetree);
break;
case T_CreateDomainStmt:
DefineDomain((CreateDomainStmt *) parsetree);
break;
case T_CreateUserStmt:
CreateUser((CreateUserStmt *) parsetree);
break;

View File

@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.25 2002/03/06 20:34:53 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.26 2002/03/07 16:35:36 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -126,7 +126,6 @@ format_type_internal(Oid type_oid, int32 typemod,
bool is_array;
char *name;
char *buf;
char typtype;
if (type_oid == InvalidOid && allow_invalid)
return pstrdup("-");
@@ -145,31 +144,6 @@ format_type_internal(Oid type_oid, int32 typemod,
array_base_type = ((Form_pg_type) GETSTRUCT(tuple))->typelem;
typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen;
typtype = ((Form_pg_type) GETSTRUCT(tuple))->typtype;
/*
* Domains look alot like arrays, so lets process them first, and return
* back to avoid the array and 'standard' formatting procedures that are
* use for base types.
*/
if (typtype == 'd') {
name = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname);
/*
* Double-quote the name if it's not a standard identifier.
* Note this is *necessary* for ruleutils.c's use.
*/
if (strspn(name, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(name)
|| isdigit((unsigned char) name[0]))
buf = psnprintf(strlen(name) + 3, "\"%s\"", name);
else
buf = pstrdup(name);
ReleaseSysCache(tuple);
return buf;
}
if (array_base_type != InvalidOid && typlen < 0)
{
/* Switch our attention to the array element type */

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.61 2002/03/06 20:34:54 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.62 2002/03/07 16:35:36 momjian Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -23,7 +23,6 @@
#include "catalog/pg_shadow.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
#include "parser/parse_coerce.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
@@ -823,17 +822,16 @@ get_typstorage(Oid typid)
* Returns FALSE if there is no default (effectively, default is NULL).
* The result points to palloc'd storage for pass-by-reference types.
*/
Node *
get_typdefault(Oid typid, int32 atttypmod)
bool
get_typdefault(Oid typid, Datum *defaultValue)
{
HeapTuple typeTuple;
Form_pg_type type;
Oid typinput;
Oid typbasetype;
char typtype;
Datum datum;
Oid typinput,
typelem;
Datum textDefaultVal;
bool isNull;
Node *expr;
char *strDefaultVal;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typid),
@@ -845,41 +843,38 @@ get_typdefault(Oid typid, int32 atttypmod)
type = (Form_pg_type) GETSTRUCT(typeTuple);
typinput = type->typinput;
typbasetype = type->typbasetype;
typtype = type->typtype;
typelem = type->typelem;
/*
* typdefaultbin is potentially null, so don't try to access it as a
* typdefault is potentially null, so don't try to access it as a
* struct field. Must do it the hard way with SysCacheGetAttr.
*/
datum = SysCacheGetAttr(TYPEOID,
typeTuple,
Anum_pg_type_typdefaultbin,
&isNull);
textDefaultVal = SysCacheGetAttr(TYPEOID,
typeTuple,
Anum_pg_type_typdefault,
&isNull);
ReleaseSysCache(typeTuple);
if (isNull)
return (Node *) NULL;
/* Convert Datum to a Node */
expr = stringToNode(DatumGetCString(
DirectFunctionCall1(textout, datum)));
/*
* Ensure we goto the basetype before the domain type.
*
* Prevents scenarios like the below from failing:
* CREATE DOMAIN dom text DEFAULT random();
*
*/
if (typbasetype != InvalidOid) {
expr = coerce_type(NULL, expr, typid,
typbasetype, atttypmod);
{
ReleaseSysCache(typeTuple);
*defaultValue = (Datum) 0;
return false;
}
/* Convert text datum to C string */
strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
textDefaultVal));
return expr;
/* Convert C string to a value of the given type */
*defaultValue = OidFunctionCall3(typinput,
CStringGetDatum(strDefaultVal),
ObjectIdGetDatum(typelem),
Int32GetDatum(-1));
pfree(strDefaultVal);
ReleaseSysCache(typeTuple);
return true;
}
/*

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.155 2002/03/06 20:34:54 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.156 2002/03/07 16:35:36 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -512,12 +512,8 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
(char *) attp,
ATTRIBUTE_TUPLE_SIZE);
/*
* Update constraint/default info
*/
if (attp->attnotnull)
/* Update constraint/default info */
if (attp->attnotnull)
constr->has_not_null = true;
if (attp->atthasdef)