aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-03-20 19:45:13 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-03-20 19:45:13 +0000
commit337b22cb473f1c5cca011a511c488d20e153eec4 (patch)
treebfec217a7ac7672d796217bfd9dce348a255e1b0 /src/backend/commands
parent251282d4b7bf7593cece7c4ce5669beb778604e3 (diff)
downloadpostgresql-337b22cb473f1c5cca011a511c488d20e153eec4.tar.gz
postgresql-337b22cb473f1c5cca011a511c488d20e153eec4.zip
Code review for DOMAIN patch.
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/creatinh.c43
-rw-r--r--src/backend/commands/define.c236
-rw-r--r--src/backend/commands/indexcmds.c10
-rw-r--r--src/backend/commands/remove.c16
4 files changed, 107 insertions, 198 deletions
diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c
index d6af805715c..c9dee0cbbed 100644
--- a/src/backend/commands/creatinh.c
+++ b/src/backend/commands/creatinh.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.87 2002/03/19 02:58:19 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.88 2002/03/20 19:43:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -42,6 +42,7 @@ static int findAttrByName(const char *attributeName, List *schema);
static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
static List *MergeDomainAttributes(List *schema);
+
/* ----------------------------------------------------------------
* DefineRelation
* Creates a new relation.
@@ -71,9 +72,9 @@ DefineRelation(CreateStmt *stmt, char relkind)
StrNCpy(relname, stmt->relname, NAMEDATALEN);
/*
- * Inherit domain attributes into the known columns before table inheritance
- * applies it's changes otherwise we risk adding double constraints
- * to a domain thats inherited.
+ * Merge domain attributes into the known columns before processing table
+ * inheritance. Otherwise we risk adding double constraints to a
+ * domain-type column that's inherited.
*/
schema = MergeDomainAttributes(schema);
@@ -273,11 +274,8 @@ TruncateRelation(const char *relname)
/*
* MergeDomainAttributes
* Returns a new table schema with the constraints, types, and other
- * attributes of the domain resolved for fields using the domain as
- * their type.
- *
- * Defaults are pulled out by the table attribute as required, similar to
- * how all types defaults are processed.
+ * attributes of domains resolved for fields using a domain as
+ * their type.
*/
static List *
MergeDomainAttributes(List *schema)
@@ -295,34 +293,25 @@ MergeDomainAttributes(List *schema)
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;
+ if (typeTup->typtype == 'd')
+ {
+ /* Force the column to have the correct typmod. */
+ coldef->typename->typmod = typeTup->typtypmod;
+ /* XXX more to do here? */
+ }
- /* 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?
- */
+ /* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */
+ /* Currently only used for domains, but could be valid for all */
+ coldef->is_not_null |= typeTup->typnotnull;
- }
ReleaseSysCache(tuple);
}
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index 72aa7a3a15f..2441e49bcaa 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.70 2002/03/19 02:18:15 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.71 2002/03/20 19:43:44 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -483,38 +483,29 @@ DefineAggregate(char *aggName, List *parameters)
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 */
+ int16 internalLength;
+ int16 externalLength;
+ char *inputName;
+ char *outputName;
+ char *sendName;
+ char *receiveName;
+ bool byValue;
+ char delimiter;
+ char alignment;
+ char storage;
char typtype;
Datum datum;
+ bool isnull;
+ char *defaultValue = NULL;
+ char *defaultValueBin = NULL;
bool typNotNull = false;
+ Oid basetypelem;
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;
+ List *listptr;
/*
* Domainnames, unlike typenames don't need to account for the '_'
@@ -524,25 +515,13 @@ DefineDomain(CreateDomainStmt *stmt)
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
- );
-
+ typeTup = SearchSysCache(TYPENAME,
+ PointerGetDatum(stmt->domainname),
+ 0, 0, 0);
if (HeapTupleIsValid(typeTup))
- {
- elog(ERROR, "CREATE DOMAIN: domain or type %s already exists",
+ 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
@@ -555,22 +534,12 @@ DefineDomain(CreateDomainStmt *stmt)
typNDims = length(stmt->typename->arrayBounds);
}
-
- typeTup = SearchSysCache( TYPENAME
- , PointerGetDatum(typeName)
- , 0, 0, 0
- );
-
+ 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
@@ -578,9 +547,10 @@ DefineDomain(CreateDomainStmt *stmt)
*
* With testing, we may determine complex types should be allowed
*/
- if (typtype != 'b') {
- elog(ERROR, "DefineDomain: %s is not a basetype", stmt->typename->name);
- }
+ typtype = ((Form_pg_type) GETSTRUCT(typeTup))->typtype;
+ if (typtype != 'b')
+ elog(ERROR, "DefineDomain: %s is not a basetype",
+ stmt->typename->name);
/* passed by value */
byValue = ((Form_pg_type) GETSTRUCT(typeTup))->typbyval;
@@ -588,6 +558,9 @@ DefineDomain(CreateDomainStmt *stmt)
/* Required Alignment */
alignment = ((Form_pg_type) GETSTRUCT(typeTup))->typalign;
+ /* TOAST Strategy */
+ storage = ((Form_pg_type) GETSTRUCT(typeTup))->typstorage;
+
/* Storage Length */
internalLength = ((Form_pg_type) GETSTRUCT(typeTup))->typlen;
@@ -597,70 +570,66 @@ DefineDomain(CreateDomainStmt *stmt)
/* Array element Delimiter */
delimiter = ((Form_pg_type) GETSTRUCT(typeTup))->typdelim;
+ /*
+ * XXX this is pretty bogus: should be passing function OIDs to
+ * TypeCreate, not names which aren't unique.
+ */
+
/* Input Function Name */
- datum = heap_getattr(typeTup, Anum_pg_type_typinput, pg_type_dsc, &isnull);
+ datum = SysCacheGetAttr(TYPENAME, typeTup, Anum_pg_type_typinput, &isnull);
Assert(!isnull);
inputName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
/* Output Function Name */
- datum = heap_getattr(typeTup, Anum_pg_type_typoutput, pg_type_dsc, &isnull);
+ datum = SysCacheGetAttr(TYPENAME, typeTup, Anum_pg_type_typoutput, &isnull);
Assert(!isnull);
outputName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
/* ReceiveName */
- datum = heap_getattr(typeTup, Anum_pg_type_typreceive, pg_type_dsc, &isnull);
+ datum = SysCacheGetAttr(TYPENAME, typeTup, Anum_pg_type_typreceive, &isnull);
Assert(!isnull);
receiveName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
/* SendName */
- datum = heap_getattr(typeTup, Anum_pg_type_typsend, pg_type_dsc, &isnull);
+ datum = SysCacheGetAttr(TYPENAME, typeTup, Anum_pg_type_typsend, &isnull);
Assert(!isnull);
sendName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
- /* TOAST Strategy */
- storage = ((Form_pg_type) GETSTRUCT(typeTup))->typstorage;
- Assert(!isnull);
-
/* Inherited default value */
- datum = heap_getattr(typeTup, Anum_pg_type_typdefault, pg_type_dsc, &isnull);
- if (!isnull) {
- defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum));
- }
+ datum = SysCacheGetAttr(TYPENAME, typeTup,
+ Anum_pg_type_typdefault, &isnull);
+ if (!isnull)
+ defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum));
/* Inherited default binary value */
- datum = heap_getattr(typeTup, Anum_pg_type_typdefaultbin, pg_type_dsc, &isnull);
- if (!isnull) {
- defaultValueBin = DatumGetCString(DirectFunctionCall1(textout, datum));
- }
+ datum = SysCacheGetAttr(TYPENAME, typeTup,
+ Anum_pg_type_typdefaultbin, &isnull);
+ if (!isnull)
+ defaultValueBin = 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) {
+ basetypelem = ((Form_pg_type) GETSTRUCT(typeTup))->typelem;
+ if (basetypelem != InvalidOid)
+ {
HeapTuple tup;
- tup = SearchSysCache( TYPEOID
- , datum
- , 0, 0, 0
- );
-
- elemName = NameStr(((Form_pg_type) GETSTRUCT(tup))->typname);
-
+ tup = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(basetypelem),
+ 0, 0, 0);
+ elemName = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(tup))->typname));
ReleaseSysCache(tup);
}
-
/*
- * Run through constraints manually avoids the additional
+ * Run through constraints manually to avoid the additional
* processing conducted by DefineRelation() and friends.
*
* Besides, we don't want any constraints to be cooked. We'll
@@ -668,20 +637,13 @@ DefineDomain(CreateDomainStmt *stmt)
*/
foreach(listptr, schema)
{
+ Constraint *colDef = lfirst(listptr);
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) {
+ switch (colDef->contype)
+ {
/*
* The inherited default value may be overridden by the user
* with the DEFAULT <expr> statement.
@@ -690,27 +652,26 @@ DefineDomain(CreateDomainStmt *stmt)
* don't want to cook or fiddle too much.
*/
case CONSTR_DEFAULT:
-
+ /* Create a dummy ParseState for transformExpr */
+ pstate = make_parsestate(NULL);
/*
- * Cook the colDef->raw_expr into an expression to ensure
- * that it can be done. We store the text version of the
- * raw value.
- *
+ * Cook the colDef->raw_expr into an expression.
* 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 */
+ expr = cookDefault(pstate, colDef->raw_expr,
+ typeTup->t_data->t_oid,
+ stmt->typename->typmod,
+ stmt->typename->name);
+ /*
+ * 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(expr,
deparse_context_for(stmt->domainname,
InvalidOid),
false);
-
defaultValueBin = nodeToString(expr);
-
break;
/*
@@ -723,7 +684,6 @@ DefineDomain(CreateDomainStmt *stmt)
typNotNull = true;
nullDefined = true;
}
-
break;
case CONSTR_NULL:
@@ -733,31 +693,31 @@ DefineDomain(CreateDomainStmt *stmt)
typNotNull = false;
nullDefined = true;
}
-
break;
case CONSTR_UNIQUE:
- elog(ERROR, "CREATE DOMAIN / UNIQUE indecies not supported");
+ elog(ERROR, "CREATE DOMAIN / UNIQUE indexes not supported");
break;
case CONSTR_PRIMARY:
- elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indecies not supported");
+ elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indexes not supported");
break;
-
case CONSTR_CHECK:
-
- elog(ERROR, "defineDomain: CHECK Constraints not supported");
+ 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");
+ elog(ERROR, "DefineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported");
break;
- }
+ default:
+ elog(ERROR, "DefineDomain: unrecognized constraint node type");
+ break;
+ }
}
/*
@@ -776,8 +736,8 @@ DefineDomain(CreateDomainStmt *stmt)
sendName, /* send procedure */
elemName, /* element type name */
typeName, /* base type name */
- defaultValue, /* default type value */
- defaultValueBin, /* default type value */
+ defaultValue, /* default type value (text) */
+ defaultValueBin, /* default type value (binary) */
byValue, /* passed by value */
alignment, /* required alignment */
storage, /* TOAST strategy */
@@ -789,10 +749,8 @@ DefineDomain(CreateDomainStmt *stmt)
* Now we can clean up.
*/
ReleaseSysCache(typeTup);
- heap_close(pg_type_rel, NoLock);
}
-
/*
* DefineType
* Registers a new type.
@@ -808,8 +766,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;
@@ -851,7 +807,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)
@@ -911,32 +867,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.
*/
@@ -952,9 +882,9 @@ DefineType(char *typeName, List *parameters)
receiveName, /* receive procedure */
sendName, /* send procedure */
elemName, /* element type name */
- NULL, /* base type name (Non-zero for domains) */
+ NULL, /* base type name (only for domains) */
defaultValue, /* default type value */
- defaultValueBin, /* default type value (Binary form) */
+ NULL, /* no binary form available */
byValue, /* passed by value */
alignment, /* required alignment */
storage, /* TOAST strategy */
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index b04ec8a9b41..677f1306376 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.63 2002/03/06 06:09:33 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.64 2002/03/20 19:43:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -314,8 +314,7 @@ FuncIndexArgs(IndexInfo *indexInfo,
for (i = 0; i < nargs; i++)
{
- if (argTypes[i] != true_typeids[i] &&
- !IS_BINARY_COMPATIBLE(argTypes[i], true_typeids[i]))
+ if (!IsBinaryCompatible(argTypes[i], true_typeids[i]))
func_error("DefineIndex", funcIndex->name, nargs, argTypes,
"Index function must be binary-compatible with table datatype");
}
@@ -418,8 +417,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
opInputType = ((Form_pg_opclass) GETSTRUCT(tuple))->opcintype;
ReleaseSysCache(tuple);
- if (attrType != opInputType &&
- !IS_BINARY_COMPATIBLE(attrType, opInputType))
+ if (!IsBinaryCompatible(attrType, opInputType))
elog(ERROR, "operator class \"%s\" does not accept data type %s",
attribute->class, format_type_be(attrType));
@@ -470,7 +468,7 @@ GetDefaultOpClass(Oid attrType, Oid accessMethodId)
nexact++;
exactOid = tuple->t_data->t_oid;
}
- else if (IS_BINARY_COMPATIBLE(opclass->opcintype, attrType))
+ else if (IsBinaryCompatible(opclass->opcintype, attrType))
{
ncompatible++;
compatibleOid = tuple->t_data->t_oid;
diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c
index 297b351df83..99b243ed4fd 100644
--- a/src/backend/commands/remove.c
+++ b/src/backend/commands/remove.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.69 2002/03/19 02:18:16 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.70 2002/03/20 19:43:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -282,23 +282,18 @@ RemoveType(char *typeName) /* type name to be removed */
* use it.
*/
void
-RemoveDomain(char *domainName, int behavior) /* domain name to be removed */
+RemoveDomain(char *domainName, int behavior)
{
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),
@@ -306,14 +301,11 @@ RemoveDomain(char *domainName, int behavior) /* domain name to be removed */
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);
+ typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype;
- if (typtype != 'd') {
+ if (typtype != 'd')
elog(ERROR, "%s is not a domain", domainName);
- }
/* CASCADE unsupported */
if (behavior == CASCADE) {