diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-12-30 21:21:56 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-12-30 21:21:56 +0000 |
commit | 5725b9d9afc8c3ba24e94cbc7020889fe8ad7ef9 (patch) | |
tree | e1c8a77dbb660fa0de36528f19dc4f3cb81829d2 /src/backend/commands/typecmds.c | |
parent | 24b1f14eae0b83ef5d6b269ebf1ecae2f3acbb8c (diff) | |
download | postgresql-5725b9d9afc8c3ba24e94cbc7020889fe8ad7ef9.tar.gz postgresql-5725b9d9afc8c3ba24e94cbc7020889fe8ad7ef9.zip |
Support type modifiers for user-defined types, and pull most knowledge
about typmod representation for standard types out into type-specific
typmod I/O functions. Teodor Sigaev, with some editorialization by
Tom Lane.
Diffstat (limited to 'src/backend/commands/typecmds.c')
-rw-r--r-- | src/backend/commands/typecmds.c | 104 |
1 files changed, 99 insertions, 5 deletions
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 53cca73a9dd..2b26f2dfa14 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.97 2006/10/04 00:29:51 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.98 2006/12/30 21:21:53 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -75,6 +75,8 @@ static Oid findTypeInputFunction(List *procname, Oid typeOid); static Oid findTypeOutputFunction(List *procname, Oid typeOid); static Oid findTypeReceiveFunction(List *procname, Oid typeOid); static Oid findTypeSendFunction(List *procname, Oid typeOid); +static Oid findTypeTypmodinFunction(List *procname); +static Oid findTypeTypmodoutFunction(List *procname); static Oid findTypeAnalyzeFunction(List *procname, Oid typeOid); static List *get_rels_with_domain(Oid domainOid, LOCKMODE lockmode); static void checkDomainOwner(HeapTuple tup, TypeName *typename); @@ -100,6 +102,8 @@ DefineType(List *names, List *parameters) List *outputName = NIL; List *receiveName = NIL; List *sendName = NIL; + List *typmodinName = NIL; + List *typmodoutName = NIL; List *analyzeName = NIL; char *defaultValue = NULL; bool byValue = false; @@ -110,6 +114,8 @@ DefineType(List *names, List *parameters) Oid outputOid; Oid receiveOid = InvalidOid; Oid sendOid = InvalidOid; + Oid typmodinOid = InvalidOid; + Oid typmodoutOid = InvalidOid; Oid analyzeOid = InvalidOid; char *shadow_type; ListCell *pl; @@ -182,6 +188,10 @@ DefineType(List *names, List *parameters) receiveName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "send") == 0) sendName = defGetQualifiedName(defel); + else if (pg_strcasecmp(defel->defname, "typmod_in") == 0) + typmodinName = defGetQualifiedName(defel); + else if (pg_strcasecmp(defel->defname, "typmod_out") == 0) + typmodoutName = defGetQualifiedName(defel); else if (pg_strcasecmp(defel->defname, "analyze") == 0 || pg_strcasecmp(defel->defname, "analyse") == 0) analyzeName = defGetQualifiedName(defel); @@ -268,6 +278,11 @@ DefineType(List *names, List *parameters) (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("type output function must be specified"))); + if (typmodinName == NIL && typmodoutName != NIL) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("type modifier output function is useless without a type modifier input function"))); + /* * Convert I/O proc names to OIDs */ @@ -336,6 +351,14 @@ DefineType(List *names, List *parameters) } /* + * Convert typmodin/out function proc names to OIDs. + */ + if (typmodinName) + typmodinOid = findTypeTypmodinFunction(typmodinName); + if (typmodoutName) + typmodoutOid = findTypeTypmodoutFunction(typmodoutName); + + /* * Convert analysis function proc name to an OID. If no analysis function * is specified, we'll use zero to select the built-in default algorithm. */ @@ -362,6 +385,12 @@ DefineType(List *names, List *parameters) if (sendOid && !pg_proc_ownercheck(sendOid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(sendName)); + if (typmodinOid && !pg_proc_ownercheck(typmodinOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, + NameListToString(typmodinName)); + if (typmodoutOid && !pg_proc_ownercheck(typmodoutOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, + NameListToString(typmodoutName)); if (analyzeOid && !pg_proc_ownercheck(analyzeOid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(analyzeName)); @@ -381,6 +410,8 @@ DefineType(List *names, List *parameters) outputOid, /* output procedure */ receiveOid, /* receive procedure */ sendOid, /* send procedure */ + typmodinOid, /* typmodin procedure */ + typmodoutOid,/* typmodout procedure */ analyzeOid, /* analyze procedure */ elemType, /* element type ID */ InvalidOid, /* base type ID (only for domains) */ @@ -413,6 +444,8 @@ DefineType(List *names, List *parameters) F_ARRAY_OUT, /* output procedure */ F_ARRAY_RECV, /* receive procedure */ F_ARRAY_SEND, /* send procedure */ + typmodinOid, /* typmodin procedure */ + typmodoutOid, /* typmodout procedure */ InvalidOid, /* analyze procedure - default */ typoid, /* element type ID */ InvalidOid, /* base type ID */ @@ -552,6 +585,7 @@ DefineDomain(CreateDomainStmt *stmt) Oid basetypeoid; Oid domainoid; Form_pg_type baseType; + int32 basetypeMod; /* Convert list of names to a name and namespace */ domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname, @@ -581,9 +615,9 @@ DefineDomain(CreateDomainStmt *stmt) * Look up the base type. */ typeTup = typenameType(NULL, stmt->typename); - baseType = (Form_pg_type) GETSTRUCT(typeTup); basetypeoid = HeapTupleGetOid(typeTup); + basetypeMod = typenameTypeMod(NULL, stmt->typename, basetypeoid); /* * Base type must be a plain base type or another domain. Domains over @@ -621,6 +655,8 @@ DefineDomain(CreateDomainStmt *stmt) receiveProcedure = F_DOMAIN_RECV; sendProcedure = baseType->typsend; + /* Domains never accept typmods, so no typmodin/typmodout needed */ + /* Analysis function */ analyzeProcedure = baseType->typanalyze; @@ -681,7 +717,7 @@ DefineDomain(CreateDomainStmt *stmt) */ defaultExpr = cookDefault(pstate, constr->raw_expr, basetypeoid, - stmt->typename->typmod, + basetypeMod, domainName); /* @@ -768,6 +804,8 @@ DefineDomain(CreateDomainStmt *stmt) outputProcedure, /* output procedure */ receiveProcedure, /* receive procedure */ sendProcedure, /* send procedure */ + InvalidOid, /* typmodin procedure - none */ + InvalidOid, /* typmodout procedure - none */ analyzeProcedure, /* analyze procedure */ typelem, /* element type ID */ basetypeoid, /* base type ID */ @@ -776,7 +814,7 @@ DefineDomain(CreateDomainStmt *stmt) byValue, /* passed by value */ alignment, /* required alignment */ storage, /* TOAST strategy */ - stmt->typename->typmod, /* typeMod value */ + basetypeMod, /* typeMod value */ typNDims, /* Array dimensions for base type */ typNotNull); /* Type NOT NULL */ @@ -793,7 +831,7 @@ DefineDomain(CreateDomainStmt *stmt) { case CONSTR_CHECK: domainAddConstraint(domainoid, domainNamespace, - basetypeoid, stmt->typename->typmod, + basetypeoid, basetypeMod, constr, domainName); break; @@ -1068,6 +1106,60 @@ findTypeSendFunction(List *procname, Oid typeOid) } static Oid +findTypeTypmodinFunction(List *procname) +{ + Oid argList[1]; + Oid procOid; + + /* + * typmodin functions always take one int4[] argument and return int4. + */ + argList[0] = INT4ARRAYOID; + + procOid = LookupFuncName(procname, 1, argList, true); + if (!OidIsValid(procOid)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("function %s does not exist", + func_signature_string(procname, 1, argList)))); + + if (get_func_rettype(procOid) != INT4OID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("typmod_in function %s must return type \"integer\"", + NameListToString(procname)))); + + return procOid; +} + +static Oid +findTypeTypmodoutFunction(List *procname) +{ + Oid argList[1]; + Oid procOid; + + /* + * typmodout functions always take one int4 argument and return cstring. + */ + argList[0] = INT4OID; + + procOid = LookupFuncName(procname, 1, argList, true); + if (!OidIsValid(procOid)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("function %s does not exist", + func_signature_string(procname, 1, argList)))); + + if (get_func_rettype(procOid) != CSTRINGOID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("typmod_out function %s must return type \"cstring\"", + NameListToString(procname)))); + + return procOid; +} + +static Oid findTypeAnalyzeFunction(List *procname, Oid typeOid) { Oid argList[1]; @@ -1244,6 +1336,8 @@ AlterDomainDefault(List *names, Node *defaultRaw) typTup->typoutput, typTup->typreceive, typTup->typsend, + typTup->typmodin, + typTup->typmodout, typTup->typanalyze, typTup->typelem, typTup->typbasetype, |