From 27dc62f9ec430f0ad6949e6d18c3c7a69f537444 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Wed, 3 Jan 2018 18:21:20 -0500 Subject: [PATCH 1/2] Add prokind column, replacing proisagg and proiswindow --- doc/src/sgml/catalogs.sgml | 23 +++++------ src/backend/catalog/objectaddress.c | 6 +-- src/backend/catalog/pg_aggregate.c | 3 +- src/backend/catalog/pg_proc.c | 36 +++-------------- src/backend/catalog/system_views.sql | 8 ++-- src/backend/commands/functioncmds.c | 29 +++++--------- src/backend/commands/proclang.c | 9 ++--- src/backend/commands/typecmds.c | 3 +- src/backend/parser/parse_coerce.c | 3 +- src/backend/parser/parse_func.c | 27 +++++++++---- src/backend/utils/adt/ruleutils.c | 6 +-- src/backend/utils/cache/lsyscache.c | 4 +- src/bin/pg_dump/t/002_pg_dump.pl | 6 +-- src/bin/psql/describe.c | 60 +++++++++++++++++++++++------ src/bin/psql/tab-complete.c | 2 +- src/include/catalog/pg_class.h | 2 +- src/include/catalog/pg_proc.h | 54 ++++++++++++++------------ src/include/catalog/pg_proc_fn.h | 3 +- src/test/regress/expected/alter_generic.out | 2 +- src/test/regress/expected/opr_sanity.out | 36 ++++++++--------- src/test/regress/expected/rules.out | 8 ++-- src/test/regress/sql/alter_generic.sql | 2 +- src/test/regress/sql/opr_sanity.sql | 36 ++++++++--------- 23 files changed, 191 insertions(+), 177 deletions(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 3f02202caf..2a50dec06d 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -5039,15 +5039,17 @@ <structname>pg_proc</structname> - The catalog pg_proc stores information about functions (or procedures). + The catalog pg_proc stores information about + functions, procedures, aggregate functions, and window functions + (collectively also known as routines). See and for more information. - The table contains data for aggregate functions as well as plain functions. - If proisagg is true, there should be a matching - row in pg_aggregate. + If prokind indicates that the entry is for an + aggregate function, there should be a matching row in + pg_aggregate. @@ -5134,17 +5136,12 @@ <structname>pg_proc</structname> Columns - proisagg + prokind bool - Function is an aggregate function - - - - proiswindow - bool - - Function is a window function + f for a normal function, p + for a procedure, a for an aggregate function, + w for a window function diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index bc999ca3c4..4397ef932d 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -4031,11 +4031,11 @@ getProcedureTypeDescription(StringInfo buffer, Oid procid) elog(ERROR, "cache lookup failed for procedure %u", procid); procForm = (Form_pg_proc) GETSTRUCT(procTup); - if (procForm->proisagg) + if (procForm->prokind == PROKIND_AGGREGATE) appendStringInfoString(buffer, "aggregate"); - else if (procForm->prorettype == InvalidOid) + else if (procForm->prokind == PROKIND_PROCEDURE) appendStringInfoString(buffer, "procedure"); - else + else /* function or window function */ appendStringInfoString(buffer, "function"); ReleaseSysCache(procTup); diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index e801c1ed5c..0080ed4d6d 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -616,8 +616,7 @@ AggregateCreate(const char *aggName, InvalidOid, /* no validator */ "aggregate_dummy", /* placeholder proc */ NULL, /* probin */ - true, /* isAgg */ - false, /* isWindowFunc */ + PROKIND_AGGREGATE, false, /* security invoker (currently not * definable for agg) */ false, /* isLeakProof */ diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 39d5172e97..a5c8bf1b3f 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -74,8 +74,7 @@ ProcedureCreate(const char *procedureName, Oid languageValidator, const char *prosrc, const char *probin, - bool isAgg, - bool isWindowFunc, + char prokind, bool security_definer, bool isLeakProof, bool isStrict, @@ -335,8 +334,7 @@ ProcedureCreate(const char *procedureName, values[Anum_pg_proc_prorows - 1] = Float4GetDatum(prorows); values[Anum_pg_proc_provariadic - 1] = ObjectIdGetDatum(variadicType); values[Anum_pg_proc_protransform - 1] = ObjectIdGetDatum(InvalidOid); - values[Anum_pg_proc_proisagg - 1] = BoolGetDatum(isAgg); - values[Anum_pg_proc_proiswindow - 1] = BoolGetDatum(isWindowFunc); + values[Anum_pg_proc_prokind - 1] = CharGetDatum(prokind); values[Anum_pg_proc_prosecdef - 1] = BoolGetDatum(security_definer); values[Anum_pg_proc_proleakproof - 1] = BoolGetDatum(isLeakProof); values[Anum_pg_proc_proisstrict - 1] = BoolGetDatum(isStrict); @@ -536,32 +534,10 @@ ProcedureCreate(const char *procedureName, } /* Can't change aggregate or window-function status, either */ - if (oldproc->proisagg != isAgg) - { - if (oldproc->proisagg) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("function \"%s\" is an aggregate function", - procedureName))); - else - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("function \"%s\" is not an aggregate function", - procedureName))); - } - if (oldproc->proiswindow != isWindowFunc) - { - if (oldproc->proiswindow) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("function \"%s\" is a window function", - procedureName))); - else - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("function \"%s\" is not a window function", - procedureName))); - } + if (oldproc->prokind != prokind) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot change routine type"))); /* * Do not change existing ownership or permissions, either. Note diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 5652e9ee6d..5e6e8a64f6 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -332,9 +332,11 @@ CREATE VIEW pg_seclabels AS UNION ALL SELECT l.objoid, l.classoid, l.objsubid, - CASE WHEN pro.proisagg = true THEN 'aggregate'::text - WHEN pro.proisagg = false THEN 'function'::text - END AS objtype, + CASE pro.prokind + WHEN 'a' THEN 'aggregate'::text + WHEN 'f' THEN 'function'::text + WHEN 'p' THEN 'procedure'::text + WHEN 'w' THEN 'window'::text END AS objtype, pro.pronamespace AS objnamespace, CASE WHEN pg_function_is_visible(pro.oid) THEN quote_ident(pro.proname) diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 12ab33f418..9d4036da8d 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -1151,8 +1151,7 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt) languageValidator, prosrc_str, /* converted to text later */ probin_str, /* converted to text later */ - false, /* not an aggregate */ - isWindowFunc, + stmt->is_procedure ? PROKIND_PROCEDURE : (isWindowFunc ? PROKIND_WINDOW : PROKIND_FUNCTION), security, isLeakProof, isStrict, @@ -1180,7 +1179,7 @@ RemoveFunctionById(Oid funcOid) { Relation relation; HeapTuple tup; - bool isagg; + char prokind; /* * Delete the pg_proc tuple. @@ -1191,7 +1190,7 @@ RemoveFunctionById(Oid funcOid) if (!HeapTupleIsValid(tup)) /* should not happen */ elog(ERROR, "cache lookup failed for function %u", funcOid); - isagg = ((Form_pg_proc) GETSTRUCT(tup))->proisagg; + prokind = ((Form_pg_proc) GETSTRUCT(tup))->prokind; CatalogTupleDelete(relation, &tup->t_self); @@ -1202,7 +1201,7 @@ RemoveFunctionById(Oid funcOid) /* * If there's a pg_aggregate tuple, delete that too. */ - if (isagg) + if (prokind == PROKIND_AGGREGATE) { relation = heap_open(AggregateRelationId, RowExclusiveLock); @@ -1257,13 +1256,13 @@ AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, NameListToString(stmt->func->objname)); - if (procForm->proisagg) + if (procForm->prokind == PROKIND_AGGREGATE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is an aggregate function", NameListToString(stmt->func->objname)))); - is_procedure = (procForm->prorettype == InvalidOid); + is_procedure = (procForm->prokind == PROKIND_PROCEDURE); /* Examine requested actions. */ foreach(l, stmt->actions) @@ -1579,14 +1578,10 @@ CreateCast(CreateCastStmt *stmt) (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("cast function must not be volatile"))); #endif - if (procstruct->proisagg) + if (procstruct->prokind != PROKIND_FUNCTION) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("cast function must not be an aggregate function"))); - if (procstruct->proiswindow) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("cast function must not be a window function"))); + errmsg("cast function must be a normal function"))); if (procstruct->proretset) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), @@ -1831,14 +1826,10 @@ check_transform_function(Form_pg_proc procstruct) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("transform function must not be volatile"))); - if (procstruct->proisagg) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("transform function must not be an aggregate function"))); - if (procstruct->proiswindow) + if (procstruct->prokind != PROKIND_FUNCTION) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("transform function must not be a window function"))); + errmsg("transform function must be a normal function"))); if (procstruct->proretset) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 9783a162d7..3ee3c4fdea 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -129,8 +129,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) F_FMGR_C_VALIDATOR, pltemplate->tmplhandler, pltemplate->tmpllibrary, - false, /* isAgg */ - false, /* isWindowFunc */ + PROKIND_FUNCTION, false, /* security_definer */ false, /* isLeakProof */ false, /* isStrict */ @@ -169,8 +168,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) F_FMGR_C_VALIDATOR, pltemplate->tmplinline, pltemplate->tmpllibrary, - false, /* isAgg */ - false, /* isWindowFunc */ + PROKIND_FUNCTION, false, /* security_definer */ false, /* isLeakProof */ true, /* isStrict */ @@ -212,8 +210,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) F_FMGR_C_VALIDATOR, pltemplate->tmplvalidator, pltemplate->tmpllibrary, - false, /* isAgg */ - false, /* isWindowFunc */ + PROKIND_FUNCTION, false, /* security_definer */ false, /* isLeakProof */ true, /* isStrict */ diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index a40b3cf752..b368f15d85 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -1672,8 +1672,7 @@ makeRangeConstructors(const char *name, Oid namespace, F_FMGR_INTERNAL_VALIDATOR, /* language validator */ prosrc[i], /* prosrc */ NULL, /* probin */ - false, /* isAgg */ - false, /* isWindowFunc */ + PROKIND_FUNCTION, false, /* security_definer */ false, /* leakproof */ false, /* isStrict */ diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 085aa8766c..665d3327a0 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -834,8 +834,7 @@ build_coercion_expression(Node *node, */ /* Assert(targetTypeId == procstruct->prorettype); */ Assert(!procstruct->proretset); - Assert(!procstruct->proisagg); - Assert(!procstruct->proiswindow); + Assert(procstruct->prokind == PROKIND_FUNCTION); nargs = procstruct->pronargs; Assert(nargs >= 1 && nargs <= 3); /* Assert(procstruct->proargtypes.values[0] == exprType(node)); */ diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index ffae0f3cf3..e120c0cd84 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -1614,14 +1614,25 @@ func_get_detail(List *funcname, *argdefaults = defaults; } } - if (pform->proisagg) - result = FUNCDETAIL_AGGREGATE; - else if (pform->proiswindow) - result = FUNCDETAIL_WINDOWFUNC; - else if (pform->prorettype == InvalidOid) - result = FUNCDETAIL_PROCEDURE; - else - result = FUNCDETAIL_NORMAL; + + switch (pform->prokind) + { + case PROKIND_AGGREGATE: + result = FUNCDETAIL_AGGREGATE; + break; + case PROKIND_FUNCTION: + result = FUNCDETAIL_NORMAL; + break; + case PROKIND_PROCEDURE: + result = FUNCDETAIL_PROCEDURE; + break; + case PROKIND_WINDOW: + result = FUNCDETAIL_WINDOWFUNC; + break; + default: + elog(ERROR, "unrecognized prokind: %c", pform->prokind); + } + ReleaseSysCache(ftup); return result; } diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 9cdbb06add..51acd44517 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -2464,7 +2464,7 @@ pg_get_functiondef(PG_FUNCTION_ARGS) proc = (Form_pg_proc) GETSTRUCT(proctup); name = NameStr(proc->proname); - if (proc->proisagg) + if (proc->prokind == PROKIND_AGGREGATE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is an aggregate function", name))); @@ -2488,7 +2488,7 @@ pg_get_functiondef(PG_FUNCTION_ARGS) /* Emit some miscellaneous options on one line */ oldlen = buf.len; - if (proc->proiswindow) + if (proc->prokind == PROKIND_WINDOW) appendStringInfoString(&buf, " WINDOW"); switch (proc->provolatile) { @@ -2791,7 +2791,7 @@ print_function_arguments(StringInfo buf, HeapTuple proctup, } /* Check for special treatment of ordered-set aggregates */ - if (proc->proisagg) + if (proc->prokind == PROKIND_AGGREGATE) { HeapTuple aggtup; Form_pg_aggregate agg; diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index e8aa179347..d9463402f2 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -1616,7 +1616,7 @@ func_parallel(Oid funcid) /* * get_func_isagg - * Given procedure id, return the function's proisagg field. + * Given procedure id, return whether the function is an aggregate. */ bool get_func_isagg(Oid funcid) @@ -1628,7 +1628,7 @@ get_func_isagg(Oid funcid) if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for function %u", funcid); - result = ((Form_pg_proc) GETSTRUCT(tp))->proisagg; + result = ((Form_pg_proc) GETSTRUCT(tp))->prokind == PROKIND_AGGREGATE; ReleaseSysCache(tp); return result; } diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl index 7cf9bdadb2..95f0b32eee 100644 --- a/src/bin/pg_dump/t/002_pg_dump.pl +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -6083,8 +6083,7 @@ prorows, provariadic, protransform, - proisagg, - proiswindow, + prokind, prosecdef, proleakproof, proisstrict, @@ -6116,8 +6115,7 @@ \QGRANT SELECT(prorows) ON TABLE pg_proc TO PUBLIC;\E\n.* \QGRANT SELECT(provariadic) ON TABLE pg_proc TO PUBLIC;\E\n.* \QGRANT SELECT(protransform) ON TABLE pg_proc TO PUBLIC;\E\n.* - \QGRANT SELECT(proisagg) ON TABLE pg_proc TO PUBLIC;\E\n.* - \QGRANT SELECT(proiswindow) ON TABLE pg_proc TO PUBLIC;\E\n.* + \QGRANT SELECT(prokind) ON TABLE pg_proc TO PUBLIC;\E\n.* \QGRANT SELECT(prosecdef) ON TABLE pg_proc TO PUBLIC;\E\n.* \QGRANT SELECT(proleakproof) ON TABLE pg_proc TO PUBLIC;\E\n.* \QGRANT SELECT(proisstrict) ON TABLE pg_proc TO PUBLIC;\E\n.* diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index f2e62946d8..102001baff 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -100,12 +100,20 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem) " pg_catalog.format_type(p.proargtypes[0], NULL) AS \"%s\",\n", gettext_noop("Argument data types")); - appendPQExpBuffer(&buf, - " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n" - "FROM pg_catalog.pg_proc p\n" - " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" - "WHERE p.proisagg\n", - gettext_noop("Description")); + if (pset.sversion >= 110000) + appendPQExpBuffer(&buf, + " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n" + "FROM pg_catalog.pg_proc p\n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" + "WHERE p.prokind = 'a'\n", + gettext_noop("Description")); + else + appendPQExpBuffer(&buf, + " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n" + "FROM pg_catalog.pg_proc p\n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" + "WHERE p.proisagg\n", + gettext_noop("Description")); if (!showSystem && !pattern) appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" @@ -346,7 +354,25 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool gettext_noop("Schema"), gettext_noop("Name")); - if (pset.sversion >= 80400) + if (pset.sversion >= 110000) + appendPQExpBuffer(&buf, + " pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n" + " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n" + " CASE p.prokind\n" + " WHEN 'a' THEN '%s'\n" + " WHEN 'w' THEN '%s'\n" + " WHEN 'p' THEN '%s'\n" + " ELSE '%s'\n" + " END as \"%s\"", + gettext_noop("Result data type"), + gettext_noop("Argument data types"), + /* translator: "agg" is short for "aggregate" */ + gettext_noop("agg"), + gettext_noop("window"), + gettext_noop("proc"), + gettext_noop("func"), + gettext_noop("Type")); + else if (pset.sversion >= 80400) appendPQExpBuffer(&buf, " pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n" " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n" @@ -494,7 +520,10 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool appendPQExpBufferStr(&buf, "WHERE "); have_where = true; } - appendPQExpBufferStr(&buf, "NOT p.proisagg\n"); + if (pset.sversion >= 110000) + appendPQExpBufferStr(&buf, "p.prokind <> 'a'\n"); + else + appendPQExpBufferStr(&buf, "NOT p.proisagg\n"); } if (!showTrigger) { @@ -516,7 +545,10 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool appendPQExpBufferStr(&buf, "WHERE "); have_where = true; } - appendPQExpBufferStr(&buf, "NOT p.proiswindow\n"); + if (pset.sversion >= 110000) + appendPQExpBufferStr(&buf, "p.prokind <> 'w'\n"); + else + appendPQExpBufferStr(&buf, "NOT p.proiswindow\n"); } } else @@ -528,7 +560,10 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool /* Note: at least one of these must be true ... */ if (showAggregate) { - appendPQExpBufferStr(&buf, "p.proisagg\n"); + if (pset.sversion >= 110000) + appendPQExpBufferStr(&buf, "p.prokind = 'a'\n"); + else + appendPQExpBufferStr(&buf, "p.proisagg\n"); needs_or = true; } if (showTrigger) @@ -543,7 +578,10 @@ describeFunctions(const char *functypes, const char *pattern, bool verbose, bool { if (needs_or) appendPQExpBufferStr(&buf, " OR "); - appendPQExpBufferStr(&buf, "p.proiswindow\n"); + if (pset.sversion >= 110000) + appendPQExpBufferStr(&buf, "p.prokind = 'w'\n"); + else + appendPQExpBufferStr(&buf, "p.proiswindow\n"); needs_or = true; } appendPQExpBufferStr(&buf, " )\n"); diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index b51098deca..1146e82719 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -349,7 +349,7 @@ static const SchemaQuery Query_for_list_of_aggregates = { /* catname */ "pg_catalog.pg_proc p", /* selcondition */ - "p.proisagg", + "p.prokind = 'a'", /* viscondition */ "pg_catalog.pg_function_is_visible(p.oid)", /* namespace */ diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index e7049438eb..2e395a3938 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -151,7 +151,7 @@ DATA(insert OID = 1247 ( pg_type PGNSP 71 0 PGUID 0 0 0 0 0 0 0 f f p r 30 0 t DESCR(""); DATA(insert OID = 1249 ( pg_attribute PGNSP 75 0 PGUID 0 0 0 0 0 0 0 f f p r 22 0 f f f f f f f t n f 3 1 _null_ _null_ _null_)); DESCR(""); -DATA(insert OID = 1255 ( pg_proc PGNSP 81 0 PGUID 0 0 0 0 0 0 0 f f p r 29 0 t f f f f f f t n f 3 1 _null_ _null_ _null_)); +DATA(insert OID = 1255 ( pg_proc PGNSP 81 0 PGUID 0 0 0 0 0 0 0 f f p r 28 0 t f f f f f f t n f 3 1 _null_ _null_ _null_)); DESCR(""); DATA(insert OID = 1259 ( pg_class PGNSP 83 0 PGUID 0 0 0 0 0 0 0 f f p r 33 0 t f f f f f f t n f 3 1 _null_ _null_ _null_)); DESCR(""); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 298e0ae2f0..dfe7900341 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -43,8 +43,7 @@ CATALOG(pg_proc,1255) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81) BKI_SCHEMA_MACRO float4 prorows; /* estimated # of rows out (if proretset) */ Oid provariadic; /* element type of variadic array, or 0 */ regproc protransform; /* transforms calls to it during planning */ - bool proisagg; /* is it an aggregate? */ - bool proiswindow; /* is it a window function? */ + char prokind; /* see PROKIND_ categories below */ bool prosecdef; /* security definer */ bool proleakproof; /* is it a leak-proof function? */ bool proisstrict; /* strict with respect to NULLs? */ @@ -86,7 +85,7 @@ typedef FormData_pg_proc *Form_pg_proc; * compiler constants for pg_proc * ---------------- */ -#define Natts_pg_proc 29 +#define Natts_pg_proc 28 #define Anum_pg_proc_proname 1 #define Anum_pg_proc_pronamespace 2 #define Anum_pg_proc_proowner 3 @@ -95,27 +94,26 @@ typedef FormData_pg_proc *Form_pg_proc; #define Anum_pg_proc_prorows 6 #define Anum_pg_proc_provariadic 7 #define Anum_pg_proc_protransform 8 -#define Anum_pg_proc_proisagg 9 -#define Anum_pg_proc_proiswindow 10 -#define Anum_pg_proc_prosecdef 11 -#define Anum_pg_proc_proleakproof 12 -#define Anum_pg_proc_proisstrict 13 -#define Anum_pg_proc_proretset 14 -#define Anum_pg_proc_provolatile 15 -#define Anum_pg_proc_proparallel 16 -#define Anum_pg_proc_pronargs 17 -#define Anum_pg_proc_pronargdefaults 18 -#define Anum_pg_proc_prorettype 19 -#define Anum_pg_proc_proargtypes 20 -#define Anum_pg_proc_proallargtypes 21 -#define Anum_pg_proc_proargmodes 22 -#define Anum_pg_proc_proargnames 23 -#define Anum_pg_proc_proargdefaults 24 -#define Anum_pg_proc_protrftypes 25 -#define Anum_pg_proc_prosrc 26 -#define Anum_pg_proc_probin 27 -#define Anum_pg_proc_proconfig 28 -#define Anum_pg_proc_proacl 29 +#define Anum_pg_proc_prokind 9 +#define Anum_pg_proc_prosecdef 10 +#define Anum_pg_proc_proleakproof 11 +#define Anum_pg_proc_proisstrict 12 +#define Anum_pg_proc_proretset 13 +#define Anum_pg_proc_provolatile 14 +#define Anum_pg_proc_proparallel 15 +#define Anum_pg_proc_pronargs 16 +#define Anum_pg_proc_pronargdefaults 17 +#define Anum_pg_proc_prorettype 18 +#define Anum_pg_proc_proargtypes 19 +#define Anum_pg_proc_proallargtypes 20 +#define Anum_pg_proc_proargmodes 21 +#define Anum_pg_proc_proargnames 22 +#define Anum_pg_proc_proargdefaults 23 +#define Anum_pg_proc_protrftypes 24 +#define Anum_pg_proc_prosrc 25 +#define Anum_pg_proc_probin 26 +#define Anum_pg_proc_proconfig 27 +#define Anum_pg_proc_proacl 28 /* ---------------- * initial contents of pg_proc @@ -5531,6 +5529,14 @@ DESCR("list of files in the WAL directory"); DATA(insert OID = 5028 ( satisfies_hash_partition PGNSP PGUID 12 1 0 2276 0 f f f f f f i s 4 0 16 "26 23 23 2276" _null_ "{i,i,i,v}" _null_ _null_ _null_ satisfies_hash_partition _null_ _null_ _null_ )); DESCR("hash partition CHECK constraint"); +/* + * Symbolic values for prokind column + */ +#define PROKIND_FUNCTION 'f' +#define PROKIND_AGGREGATE 'a' +#define PROKIND_WINDOW 'w' +#define PROKIND_PROCEDURE 'p' + /* * Symbolic values for provolatile column: these indicate whether the result * of a function is dependent *only* on the values of its explicit arguments, diff --git a/src/include/catalog/pg_proc_fn.h b/src/include/catalog/pg_proc_fn.h index 098e2e6f07..b66871bc46 100644 --- a/src/include/catalog/pg_proc_fn.h +++ b/src/include/catalog/pg_proc_fn.h @@ -27,8 +27,7 @@ extern ObjectAddress ProcedureCreate(const char *procedureName, Oid languageValidator, const char *prosrc, const char *probin, - bool isAgg, - bool isWindowFunc, + char prokind, bool security_definer, bool isLeakProof, bool isStrict, diff --git a/src/test/regress/expected/alter_generic.out b/src/test/regress/expected/alter_generic.out index 767c09bec5..c4641af276 100644 --- a/src/test/regress/expected/alter_generic.out +++ b/src/test/regress/expected/alter_generic.out @@ -83,7 +83,7 @@ ERROR: must be owner of function alt_agg3 ALTER AGGREGATE alt_agg2(int) SET SCHEMA alt_nsp2; -- failed (name conflict) ERROR: function alt_agg2(integer) already exists in schema "alt_nsp2" RESET SESSION AUTHORIZATION; -SELECT n.nspname, proname, prorettype::regtype, proisagg, a.rolname +SELECT n.nspname, proname, prorettype::regtype, prokind = 'a' AS proisagg, a.rolname FROM pg_proc p, pg_namespace n, pg_authid a WHERE p.pronamespace = n.oid AND p.proowner = a.oid AND n.nspname IN ('alt_nsp1', 'alt_nsp2') diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index 684f7f20a8..25518c9faa 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -88,10 +88,10 @@ WHERE prosrc IS NULL OR prosrc = '' OR prosrc = '-'; -----+--------- (0 rows) --- proiswindow shouldn't be set together with proisagg or proretset +-- proretset should only be set for normal functions SELECT p1.oid, p1.proname FROM pg_proc AS p1 -WHERE proiswindow AND (proisagg OR proretset); +WHERE proretset AND prokind != 'f'; oid | proname -----+--------- (0 rows) @@ -154,9 +154,9 @@ FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid < p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - (p1.proisagg = false OR p2.proisagg = false) AND + (p1.prokind != 'a' OR p2.prokind != 'a') AND (p1.prolang != p2.prolang OR - p1.proisagg != p2.proisagg OR + p1.prokind != p2.prokind OR p1.prosecdef != p2.prosecdef OR p1.proleakproof != p2.proleakproof OR p1.proisstrict != p2.proisstrict OR @@ -182,7 +182,7 @@ FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND p1.prosrc NOT LIKE E'range\\_constructor_' AND p2.prosrc NOT LIKE E'range\\_constructor_' AND (p1.prorettype < p2.prorettype) @@ -198,7 +198,7 @@ FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND p1.prosrc NOT LIKE E'range\\_constructor_' AND p2.prosrc NOT LIKE E'range\\_constructor_' AND (p1.proargtypes[0] < p2.proargtypes[0]) @@ -216,7 +216,7 @@ FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND p1.prosrc NOT LIKE E'range\\_constructor_' AND p2.prosrc NOT LIKE E'range\\_constructor_' AND (p1.proargtypes[1] < p2.proargtypes[1]) @@ -233,7 +233,7 @@ FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND (p1.proargtypes[2] < p2.proargtypes[2]) ORDER BY 1, 2; proargtypes | proargtypes @@ -246,7 +246,7 @@ FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND (p1.proargtypes[3] < p2.proargtypes[3]) ORDER BY 1, 2; proargtypes | proargtypes @@ -259,7 +259,7 @@ FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND (p1.proargtypes[4] < p2.proargtypes[4]) ORDER BY 1, 2; proargtypes | proargtypes @@ -271,7 +271,7 @@ FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND (p1.proargtypes[5] < p2.proargtypes[5]) ORDER BY 1, 2; proargtypes | proargtypes @@ -283,7 +283,7 @@ FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND (p1.proargtypes[6] < p2.proargtypes[6]) ORDER BY 1, 2; proargtypes | proargtypes @@ -295,7 +295,7 @@ FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND (p1.proargtypes[7] < p2.proargtypes[7]) ORDER BY 1, 2; proargtypes | proargtypes @@ -1286,7 +1286,7 @@ WHERE aggfnoid = 0 OR aggtransfn = 0 OR SELECT a.aggfnoid::oid, p.proname FROM pg_aggregate as a, pg_proc as p WHERE a.aggfnoid = p.oid AND - (NOT p.proisagg OR p.proretset OR p.pronargs < a.aggnumdirectargs); + (p.prokind != 'a' OR p.proretset OR p.pronargs < a.aggnumdirectargs); aggfnoid | proname ----------+--------- (0 rows) @@ -1294,7 +1294,7 @@ WHERE a.aggfnoid = p.oid AND -- Make sure there are no proisagg pg_proc entries without matches. SELECT oid, proname FROM pg_proc as p -WHERE p.proisagg AND +WHERE p.prokind = 'a' AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid); oid | proname -----+--------- @@ -1633,7 +1633,7 @@ ORDER BY 1, 2; SELECT p1.oid::regprocedure, p2.oid::regprocedure FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid < p2.oid AND p1.proname = p2.proname AND - p1.proisagg AND p2.proisagg AND + p1.prokind = 'a' AND p2.prokind = 'a' AND array_dims(p1.proargtypes) != array_dims(p2.proargtypes) ORDER BY 1; oid | oid @@ -1644,7 +1644,7 @@ ORDER BY 1; -- For the same reason, built-in aggregates with default arguments are no good. SELECT oid, proname FROM pg_proc AS p -WHERE proisagg AND proargdefaults IS NOT NULL; +WHERE prokind = 'a' AND proargdefaults IS NOT NULL; oid | proname -----+--------- (0 rows) @@ -1654,7 +1654,7 @@ WHERE proisagg AND proargdefaults IS NOT NULL; -- that is not subject to the misplaced ORDER BY issue). SELECT p.oid, proname FROM pg_proc AS p JOIN pg_aggregate AS a ON a.aggfnoid = p.oid -WHERE proisagg AND provariadic != 0 AND a.aggkind = 'n'; +WHERE prokind = 'a' AND provariadic != 0 AND a.aggkind = 'n'; oid | proname -----+--------- (0 rows) diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index f1c1b44d6f..fea84a5415 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1521,9 +1521,11 @@ UNION ALL SELECT l.objoid, l.classoid, l.objsubid, - CASE - WHEN (pro.proisagg = true) THEN 'aggregate'::text - WHEN (pro.proisagg = false) THEN 'function'::text + CASE pro.prokind + WHEN 'a'::"char" THEN 'aggregate'::text + WHEN 'f'::"char" THEN 'function'::text + WHEN 'p'::"char" THEN 'procedure'::text + WHEN 'w'::"char" THEN 'window'::text ELSE NULL::text END AS objtype, pro.pronamespace AS objnamespace, diff --git a/src/test/regress/sql/alter_generic.sql b/src/test/regress/sql/alter_generic.sql index 311812e351..eb61a69a82 100644 --- a/src/test/regress/sql/alter_generic.sql +++ b/src/test/regress/sql/alter_generic.sql @@ -81,7 +81,7 @@ CREATE AGGREGATE alt_agg2 ( RESET SESSION AUTHORIZATION; -SELECT n.nspname, proname, prorettype::regtype, proisagg, a.rolname +SELECT n.nspname, proname, prorettype::regtype, prokind = 'a' AS proisagg, a.rolname FROM pg_proc p, pg_namespace n, pg_authid a WHERE p.pronamespace = n.oid AND p.proowner = a.oid AND n.nspname IN ('alt_nsp1', 'alt_nsp2') diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index e8fdf8454d..590257390a 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -90,10 +90,10 @@ FROM pg_proc as p1 WHERE prosrc IS NULL OR prosrc = '' OR prosrc = '-'; --- proiswindow shouldn't be set together with proisagg or proretset +-- proretset should only be set for normal functions SELECT p1.oid, p1.proname FROM pg_proc AS p1 -WHERE proiswindow AND (proisagg OR proretset); +WHERE proretset AND prokind != 'f'; -- currently, no built-in functions should be SECURITY DEFINER; -- this might change in future, but there will probably never be many. @@ -140,9 +140,9 @@ WHERE p1.oid < p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - (p1.proisagg = false OR p2.proisagg = false) AND + (p1.prokind != 'a' OR p2.prokind != 'a') AND (p1.prolang != p2.prolang OR - p1.proisagg != p2.proisagg OR + p1.prokind != p2.prokind OR p1.prosecdef != p2.prosecdef OR p1.proleakproof != p2.proleakproof OR p1.proisstrict != p2.proisstrict OR @@ -166,7 +166,7 @@ WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND p1.prosrc NOT LIKE E'range\\_constructor_' AND p2.prosrc NOT LIKE E'range\\_constructor_' AND (p1.prorettype < p2.prorettype) @@ -177,7 +177,7 @@ WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND p1.prosrc NOT LIKE E'range\\_constructor_' AND p2.prosrc NOT LIKE E'range\\_constructor_' AND (p1.proargtypes[0] < p2.proargtypes[0]) @@ -188,7 +188,7 @@ WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND p1.prosrc NOT LIKE E'range\\_constructor_' AND p2.prosrc NOT LIKE E'range\\_constructor_' AND (p1.proargtypes[1] < p2.proargtypes[1]) @@ -199,7 +199,7 @@ WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND (p1.proargtypes[2] < p2.proargtypes[2]) ORDER BY 1, 2; @@ -208,7 +208,7 @@ WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND (p1.proargtypes[3] < p2.proargtypes[3]) ORDER BY 1, 2; @@ -217,7 +217,7 @@ WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND (p1.proargtypes[4] < p2.proargtypes[4]) ORDER BY 1, 2; @@ -226,7 +226,7 @@ WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND (p1.proargtypes[5] < p2.proargtypes[5]) ORDER BY 1, 2; @@ -235,7 +235,7 @@ WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND (p1.proargtypes[6] < p2.proargtypes[6]) ORDER BY 1, 2; @@ -244,7 +244,7 @@ WHERE p1.oid != p2.oid AND p1.prosrc = p2.prosrc AND p1.prolang = 12 AND p2.prolang = 12 AND - NOT p1.proisagg AND NOT p2.proisagg AND + p1.prokind != 'a' AND p2.prokind != 'a' AND (p1.proargtypes[7] < p2.proargtypes[7]) ORDER BY 1, 2; @@ -804,13 +804,13 @@ SELECT a.aggfnoid::oid, p.proname FROM pg_aggregate as a, pg_proc as p WHERE a.aggfnoid = p.oid AND - (NOT p.proisagg OR p.proretset OR p.pronargs < a.aggnumdirectargs); + (p.prokind != 'a' OR p.proretset OR p.pronargs < a.aggnumdirectargs); -- Make sure there are no proisagg pg_proc entries without matches. SELECT oid, proname FROM pg_proc as p -WHERE p.proisagg AND +WHERE p.prokind = 'a' AND NOT EXISTS (SELECT 1 FROM pg_aggregate a WHERE a.aggfnoid = p.oid); -- If there is no finalfn then the output type must be the transtype. @@ -1089,7 +1089,7 @@ SELECT p1.oid::regprocedure, p2.oid::regprocedure FROM pg_proc AS p1, pg_proc AS p2 WHERE p1.oid < p2.oid AND p1.proname = p2.proname AND - p1.proisagg AND p2.proisagg AND + p1.prokind = 'a' AND p2.prokind = 'a' AND array_dims(p1.proargtypes) != array_dims(p2.proargtypes) ORDER BY 1; @@ -1097,7 +1097,7 @@ SELECT oid, proname FROM pg_proc AS p -WHERE proisagg AND proargdefaults IS NOT NULL; +WHERE prokind = 'a' AND proargdefaults IS NOT NULL; -- For the same reason, we avoid creating built-in variadic aggregates, except -- that variadic ordered-set aggregates are OK (since they have special syntax @@ -1105,7 +1105,7 @@ SELECT p.oid, proname FROM pg_proc AS p JOIN pg_aggregate AS a ON a.aggfnoid = p.oid -WHERE proisagg AND provariadic != 0 AND a.aggkind = 'n'; +WHERE prokind = 'a' AND provariadic != 0 AND a.aggkind = 'n'; -- **************** pg_opfamily **************** base-commit: e35dba475a440f73dccf9ed1fd61e3abc6ee61db -- 2.15.1