From a2a3192802e12e056806d5921c3fc4a7a6df8b09 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 23 Aug 2002 16:41:38 +0000 Subject: [PATCH] Further cleanup around the edges of OPAQUE/pseudotype changes. Correct the declarations of some index access method support functions. Support SQL functions returning VOID. --- doc/src/sgml/xfunc.sgml | 18 +++-- src/backend/catalog/pg_proc.c | 48 ++++++-------- src/backend/commands/typecmds.c | 34 ++++++---- src/backend/executor/functions.c | 45 ++++++------- src/include/catalog/pg_proc.h | 84 ++++++++++++------------ src/test/regress/expected/opr_sanity.out | 13 ++++ src/test/regress/sql/opr_sanity.sql | 11 ++++ 7 files changed, 140 insertions(+), 113 deletions(-) diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 9b7c42d251..a38305ce0b 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1,5 +1,5 @@ @@ -170,22 +170,26 @@ CREATE FUNCTION tp1 (integer, numeric) RETURNS numeric AS ' DELETE) as well as SELECT queries. However, the final command must be a SELECT that returns whatever is - specified as the function's return type. + specified as the function's return type. Alternatively, if you + want to define a SQL function that performs actions but has no + useful value to return, you can define it as returning void. + In that case it must not end with a SELECT. + For example: -CREATE FUNCTION clean_EMP () RETURNS integer AS ' +CREATE FUNCTION clean_EMP () RETURNS void AS ' DELETE FROM EMP WHERE EMP.salary <= 0; - SELECT 1 AS ignore_this; ' LANGUAGE SQL; SELECT clean_EMP(); - x ---- - 1 + clean_emp +----------- + +(1 row) diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 9f14f78099..1bdb3796e6 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.89 2002/08/22 00:01:41 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.90 2002/08/23 16:41:37 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -266,24 +266,18 @@ ProcedureCreate(const char *procedureName, recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); /* dependency on return type */ - if (OidIsValid(returnType)) - { - referenced.classId = RelOid_pg_type; - referenced.objectId = returnType; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - } + referenced.classId = RelOid_pg_type; + referenced.objectId = returnType; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); /* dependency on input types */ for (i = 0; i < parameterCount; i++) { - if (OidIsValid(typev[i])) - { - referenced.classId = RelOid_pg_type; - referenced.objectId = typev[i]; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - } + referenced.classId = RelOid_pg_type; + referenced.objectId = typev[i]; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } heap_freetuple(tup); @@ -324,10 +318,10 @@ checkretval(Oid rettype, char fn_typtype, List *queryTreeList) int rellogcols; /* # of nondeleted columns in rel */ int colindex; /* physical column index */ - /* guard against empty function body; OK only if no return type */ + /* guard against empty function body; OK only if void return type */ if (queryTreeList == NIL) { - if (rettype != InvalidOid) + if (rettype != VOIDOID) elog(ERROR, "function declared to return %s, but no SELECT provided", format_type_be(rettype)); return; @@ -340,13 +334,12 @@ checkretval(Oid rettype, char fn_typtype, List *queryTreeList) tlist = parse->targetList; /* - * The last query must be a SELECT if and only if there is a return - * type. + * The last query must be a SELECT if and only if return type isn't VOID. */ - if (rettype == InvalidOid) + if (rettype == VOIDOID) { if (cmd == CMD_SELECT) - elog(ERROR, "function declared with no return type, but final statement is a SELECT"); + elog(ERROR, "function declared to return void, but final statement is a SELECT"); return; } @@ -573,13 +566,15 @@ fmgr_sql_validator(PG_FUNCTION_ARGS) tuple = SearchSysCache(PROCOID, funcoid, 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup of function %u failed", funcoid); - proc = (Form_pg_proc) GETSTRUCT(tuple); + functyptype = get_typtype(proc->prorettype); + /* Disallow pseudotypes in arguments and result */ - /* except that return type can be RECORD */ - if (get_typtype(proc->prorettype) == 'p' && - proc->prorettype != RECORDOID) + /* except that return type can be RECORD or VOID */ + if (functyptype == 'p' && + proc->prorettype != RECORDOID && + proc->prorettype != VOIDOID) elog(ERROR, "SQL functions cannot return type %s", format_type_be(proc->prorettype)); @@ -596,9 +591,6 @@ fmgr_sql_validator(PG_FUNCTION_ARGS) prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp)); - /* check typtype to see if we have a predetermined return type */ - functyptype = get_typtype(proc->prorettype); - querytree_list = pg_parse_and_rewrite(prosrc, proc->proargtypes, proc->pronargs); checkretval(proc->prorettype, functyptype, querytree_list); diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index bfca9c7c8f..02e5a686e7 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.10 2002/08/22 00:01:42 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.11 2002/08/23 16:41:37 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -203,19 +203,27 @@ DefineType(List *names, List *parameters) outputOid = findTypeIOFunction(outputName, typoid, true); /* - * Verify that I/O procs return the expected thing. OPAQUE is an allowed - * (but deprecated) alternative to the fully type-safe choices. + * Verify that I/O procs return the expected thing. OPAQUE is an allowed, + * but deprecated, alternative to the fully type-safe choices. */ resulttype = get_func_rettype(inputOid); - if (!((OidIsValid(typoid) && resulttype == typoid) || - resulttype == OPAQUEOID)) - elog(ERROR, "Type input function %s must return %s or OPAQUE", - NameListToString(inputName), typeName); + if (!(OidIsValid(typoid) && resulttype == typoid)) + { + if (resulttype == OPAQUEOID) + elog(NOTICE, "DefineType: OPAQUE is deprecated, instead declare I/O functions using their true datatypes"); + else + elog(ERROR, "Type input function %s must return %s", + NameListToString(inputName), typeName); + } resulttype = get_func_rettype(outputOid); - if (!(resulttype == CSTRINGOID || - resulttype == OPAQUEOID)) - elog(ERROR, "Type output function %s must return CSTRING or OPAQUE", - NameListToString(outputName)); + if (resulttype != CSTRINGOID) + { + if (resulttype == OPAQUEOID) + elog(NOTICE, "DefineType: OPAQUE is deprecated, instead declare I/O functions using their true datatypes"); + else + elog(ERROR, "Type output function %s must return cstring", + NameListToString(outputName)); + } /* * now have TypeCreate do all the real work. @@ -671,6 +679,10 @@ findTypeIOFunction(List *procname, Oid typeOid, bool isOutput) * or two arguments (data value, element OID). The signature * may use OPAQUE in place of the actual type name; this is the * only possibility if the type doesn't yet exist as a shell. + * + * Note: although we could throw a NOTICE in this routine if OPAQUE + * is used, we do not because of the probability that it'd be + * duplicate with a notice issued in DefineType. */ if (OidIsValid(typeOid)) { diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 784bd94b0a..eba919b8b6 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.54 2002/08/05 02:30:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.55 2002/08/23 16:41:37 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -86,36 +86,35 @@ static void ShutdownSQLFunction(Datum arg); static execution_state * init_execution_state(char *src, Oid *argOidVect, int nargs) { - execution_state *newes; - execution_state *nextes; + execution_state *firstes; execution_state *preves; List *queryTree_list, *qtl_item; - newes = (execution_state *) palloc(sizeof(execution_state)); - nextes = newes; - preves = (execution_state *) NULL; - queryTree_list = pg_parse_and_rewrite(src, argOidVect, nargs); + firstes = NULL; + preves = NULL; + foreach(qtl_item, queryTree_list) { Query *queryTree = lfirst(qtl_item); Plan *planTree; + execution_state *newes; EState *estate; planTree = pg_plan_query(queryTree); - if (!nextes) - nextes = (execution_state *) palloc(sizeof(execution_state)); + newes = (execution_state *) palloc(sizeof(execution_state)); if (preves) - preves->next = nextes; + preves->next = newes; + else + firstes = newes; - nextes->next = NULL; - nextes->status = F_EXEC_START; - - nextes->qd = CreateQueryDesc(queryTree, planTree, None, NULL); - estate = CreateExecutorState(); + newes->next = NULL; + newes->status = F_EXEC_START; + newes->qd = CreateQueryDesc(queryTree, planTree, None, NULL); + newes->estate = estate = CreateExecutorState(); if (nargs > 0) { @@ -124,7 +123,7 @@ init_execution_state(char *src, Oid *argOidVect, int nargs) paramLI = (ParamListInfo) palloc((nargs + 1) * sizeof(ParamListInfoData)); - MemSet(paramLI, 0, nargs * sizeof(ParamListInfoData)); + MemSet(paramLI, 0, (nargs + 1) * sizeof(ParamListInfoData)); estate->es_param_list_info = paramLI; @@ -139,12 +138,11 @@ init_execution_state(char *src, Oid *argOidVect, int nargs) } else estate->es_param_list_info = (ParamListInfo) NULL; - nextes->estate = estate; - preves = nextes; - nextes = (execution_state *) NULL; + + preves = newes; } - return newes; + return firstes; } @@ -195,7 +193,7 @@ init_sql_fcache(FmgrInfo *finfo) */ fcache->typlen = typeStruct->typlen; - if (typeStruct->typtype == 'b' || typeStruct->typtype == 'd') + if (typeStruct->typtype != 'c') { /* The return type is not a relation, so just use byval */ fcache->typbyval = typeStruct->typbyval; @@ -484,7 +482,6 @@ fmgr_sql(PG_FUNCTION_ARGS) fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra; } es = fcache->func_state; - Assert(es); /* * Find first unfinished query in function. @@ -492,14 +489,12 @@ fmgr_sql(PG_FUNCTION_ARGS) while (es && es->status == F_EXEC_DONE) es = es->next; - Assert(es); - /* * Execute each command in the function one after another until we're * executing the final command and get a result or we run out of * commands. */ - while (es != (execution_state *) NULL) + while (es) { result = postquel_execute(es, fcinfo, fcache); if (es->status != F_EXEC_DONE) diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 6fc56d439a..4129ea73b4 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_proc.h,v 1.263 2002/08/22 04:45:11 momjian Exp $ + * $Id: pg_proc.h,v 1.264 2002/08/23 16:41:37 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -396,17 +396,17 @@ DATA(insert OID = 192 ( box_contained PGNSP PGUID 12 f f t f i 2 16 "603 603 DESCR("contained in"); DATA(insert OID = 193 ( rt_box_union PGNSP PGUID 12 f f t f i 2 603 "603 603" rt_box_union - _null_ )); DESCR("r-tree"); -DATA(insert OID = 194 ( rt_box_inter PGNSP PGUID 12 f f t f i 2 603 "603 603" rt_box_inter - _null_ )); +DATA(insert OID = 194 ( rt_box_inter PGNSP PGUID 12 f f t f i 2 2278 "603 603" rt_box_inter - _null_ )); DESCR("r-tree"); -DATA(insert OID = 195 ( rt_box_size PGNSP PGUID 12 f f t f i 2 700 "603 700" rt_box_size - _null_ )); +DATA(insert OID = 195 ( rt_box_size PGNSP PGUID 12 f f t f i 2 2278 "603 2281" rt_box_size - _null_ )); DESCR("r-tree"); -DATA(insert OID = 196 ( rt_bigbox_size PGNSP PGUID 12 f f t f i 2 700 "603 700" rt_bigbox_size - _null_ )); +DATA(insert OID = 196 ( rt_bigbox_size PGNSP PGUID 12 f f t f i 2 2278 "603 2281" rt_bigbox_size - _null_ )); DESCR("r-tree"); DATA(insert OID = 197 ( rt_poly_union PGNSP PGUID 12 f f t f i 2 604 "604 604" rt_poly_union - _null_ )); DESCR("r-tree"); -DATA(insert OID = 198 ( rt_poly_inter PGNSP PGUID 12 f f t f i 2 604 "604 604" rt_poly_inter - _null_ )); +DATA(insert OID = 198 ( rt_poly_inter PGNSP PGUID 12 f f t f i 2 2278 "604 604" rt_poly_inter - _null_ )); DESCR("r-tree"); -DATA(insert OID = 199 ( rt_poly_size PGNSP PGUID 12 f f t f i 2 23 "604 700" rt_poly_size - _null_ )); +DATA(insert OID = 199 ( rt_poly_size PGNSP PGUID 12 f f t f i 2 2278 "604 2281" rt_poly_size - _null_ )); DESCR("r-tree"); /* OIDS 200 - 299 */ @@ -665,44 +665,44 @@ DESCR("convert int4 to float4"); DATA(insert OID = 319 ( int4 PGNSP PGUID 12 f f t f i 1 23 "700" ftoi4 - _null_ )); DESCR("convert float4 to int4"); -DATA(insert OID = 320 ( rtinsert PGNSP PGUID 12 f f t f v 6 23 "2281 2281 2281 2281 2281 2281" rtinsert - _null_ )); +DATA(insert OID = 320 ( rtinsert PGNSP PGUID 12 f f t f v 6 2281 "2281 2281 2281 2281 2281 2281" rtinsert - _null_ )); DESCR("r-tree(internal)"); -DATA(insert OID = 322 ( rtgettuple PGNSP PGUID 12 f f t f v 2 23 "2281 2281" rtgettuple - _null_ )); +DATA(insert OID = 322 ( rtgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" rtgettuple - _null_ )); DESCR("r-tree(internal)"); -DATA(insert OID = 323 ( rtbuild PGNSP PGUID 12 f f t f v 3 23 "2281 2281 2281" rtbuild - _null_ )); +DATA(insert OID = 323 ( rtbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" rtbuild - _null_ )); DESCR("r-tree(internal)"); -DATA(insert OID = 324 ( rtbeginscan PGNSP PGUID 12 f f t f v 3 23 "2281 2281 2281" rtbeginscan - _null_ )); +DATA(insert OID = 324 ( rtbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" rtbeginscan - _null_ )); DESCR("r-tree(internal)"); -DATA(insert OID = 325 ( rtendscan PGNSP PGUID 12 f f t f v 1 23 "2281" rtendscan - _null_ )); +DATA(insert OID = 325 ( rtendscan PGNSP PGUID 12 f f t f v 1 2278 "2281" rtendscan - _null_ )); DESCR("r-tree(internal)"); -DATA(insert OID = 326 ( rtmarkpos PGNSP PGUID 12 f f t f v 1 23 "2281" rtmarkpos - _null_ )); +DATA(insert OID = 326 ( rtmarkpos PGNSP PGUID 12 f f t f v 1 2278 "2281" rtmarkpos - _null_ )); DESCR("r-tree(internal)"); -DATA(insert OID = 327 ( rtrestrpos PGNSP PGUID 12 f f t f v 1 23 "2281" rtrestrpos - _null_ )); +DATA(insert OID = 327 ( rtrestrpos PGNSP PGUID 12 f f t f v 1 2278 "2281" rtrestrpos - _null_ )); DESCR("r-tree(internal)"); -DATA(insert OID = 328 ( rtrescan PGNSP PGUID 12 f f t f v 2 23 "2281 2281" rtrescan - _null_ )); +DATA(insert OID = 328 ( rtrescan PGNSP PGUID 12 f f t f v 2 2278 "2281 2281" rtrescan - _null_ )); DESCR("r-tree(internal)"); -DATA(insert OID = 321 ( rtbulkdelete PGNSP PGUID 12 f f t f v 3 23 "2281 2281 2281" rtbulkdelete - _null_ )); +DATA(insert OID = 321 ( rtbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" rtbulkdelete - _null_ )); DESCR("r-tree(internal)"); DATA(insert OID = 1265 ( rtcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" rtcostestimate - _null_ )); DESCR("r-tree(internal)"); -DATA(insert OID = 330 ( btgettuple PGNSP PGUID 12 f f t f v 2 23 "2281 2281" btgettuple - _null_ )); +DATA(insert OID = 330 ( btgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" btgettuple - _null_ )); DESCR("btree(internal)"); -DATA(insert OID = 331 ( btinsert PGNSP PGUID 12 f f t f v 6 23 "2281 2281 2281 2281 2281 2281" btinsert - _null_ )); +DATA(insert OID = 331 ( btinsert PGNSP PGUID 12 f f t f v 6 2281 "2281 2281 2281 2281 2281 2281" btinsert - _null_ )); DESCR("btree(internal)"); -DATA(insert OID = 333 ( btbeginscan PGNSP PGUID 12 f f t f v 3 23 "2281 2281 2281" btbeginscan - _null_ )); +DATA(insert OID = 333 ( btbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" btbeginscan - _null_ )); DESCR("btree(internal)"); -DATA(insert OID = 334 ( btrescan PGNSP PGUID 12 f f t f v 2 23 "2281 2281" btrescan - _null_ )); +DATA(insert OID = 334 ( btrescan PGNSP PGUID 12 f f t f v 2 2278 "2281 2281" btrescan - _null_ )); DESCR("btree(internal)"); -DATA(insert OID = 335 ( btendscan PGNSP PGUID 12 f f t f v 1 23 "2281" btendscan - _null_ )); +DATA(insert OID = 335 ( btendscan PGNSP PGUID 12 f f t f v 1 2278 "2281" btendscan - _null_ )); DESCR("btree(internal)"); -DATA(insert OID = 336 ( btmarkpos PGNSP PGUID 12 f f t f v 1 23 "2281" btmarkpos - _null_ )); +DATA(insert OID = 336 ( btmarkpos PGNSP PGUID 12 f f t f v 1 2278 "2281" btmarkpos - _null_ )); DESCR("btree(internal)"); -DATA(insert OID = 337 ( btrestrpos PGNSP PGUID 12 f f t f v 1 23 "2281" btrestrpos - _null_ )); +DATA(insert OID = 337 ( btrestrpos PGNSP PGUID 12 f f t f v 1 2278 "2281" btrestrpos - _null_ )); DESCR("btree(internal)"); -DATA(insert OID = 338 ( btbuild PGNSP PGUID 12 f f t f v 3 23 "2281 2281 2281" btbuild - _null_ )); +DATA(insert OID = 338 ( btbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" btbuild - _null_ )); DESCR("btree(internal)"); -DATA(insert OID = 332 ( btbulkdelete PGNSP PGUID 12 f f t f v 3 23 "2281 2281 2281" btbulkdelete - _null_ )); +DATA(insert OID = 332 ( btbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" btbulkdelete - _null_ )); DESCR("btree(internal)"); DATA(insert OID = 1268 ( btcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" btcostestimate - _null_ )); DESCR("btree(internal)"); @@ -789,23 +789,23 @@ DESCR("convert name to char()"); DATA(insert OID = 409 ( name PGNSP PGUID 12 f f t f i 1 19 "1042" bpchar_name - _null_ )); DESCR("convert char() to name"); -DATA(insert OID = 440 ( hashgettuple PGNSP PGUID 12 f f t f v 2 23 "2281 2281" hashgettuple - _null_ )); +DATA(insert OID = 440 ( hashgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" hashgettuple - _null_ )); DESCR("hash(internal)"); -DATA(insert OID = 441 ( hashinsert PGNSP PGUID 12 f f t f v 6 23 "2281 2281 2281 2281 2281 2281" hashinsert - _null_ )); +DATA(insert OID = 441 ( hashinsert PGNSP PGUID 12 f f t f v 6 2281 "2281 2281 2281 2281 2281 2281" hashinsert - _null_ )); DESCR("hash(internal)"); -DATA(insert OID = 443 ( hashbeginscan PGNSP PGUID 12 f f t f v 3 23 "2281 2281 2281" hashbeginscan - _null_ )); +DATA(insert OID = 443 ( hashbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" hashbeginscan - _null_ )); DESCR("hash(internal)"); -DATA(insert OID = 444 ( hashrescan PGNSP PGUID 12 f f t f v 2 23 "2281 2281" hashrescan - _null_ )); +DATA(insert OID = 444 ( hashrescan PGNSP PGUID 12 f f t f v 2 2278 "2281 2281" hashrescan - _null_ )); DESCR("hash(internal)"); -DATA(insert OID = 445 ( hashendscan PGNSP PGUID 12 f f t f v 1 23 "2281" hashendscan - _null_ )); +DATA(insert OID = 445 ( hashendscan PGNSP PGUID 12 f f t f v 1 2278 "2281" hashendscan - _null_ )); DESCR("hash(internal)"); -DATA(insert OID = 446 ( hashmarkpos PGNSP PGUID 12 f f t f v 1 23 "2281" hashmarkpos - _null_ )); +DATA(insert OID = 446 ( hashmarkpos PGNSP PGUID 12 f f t f v 1 2278 "2281" hashmarkpos - _null_ )); DESCR("hash(internal)"); -DATA(insert OID = 447 ( hashrestrpos PGNSP PGUID 12 f f t f v 1 23 "2281" hashrestrpos - _null_ )); +DATA(insert OID = 447 ( hashrestrpos PGNSP PGUID 12 f f t f v 1 2278 "2281" hashrestrpos - _null_ )); DESCR("hash(internal)"); -DATA(insert OID = 448 ( hashbuild PGNSP PGUID 12 f f t f v 3 23 "2281 2281 2281" hashbuild - _null_ )); +DATA(insert OID = 448 ( hashbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" hashbuild - _null_ )); DESCR("hash(internal)"); -DATA(insert OID = 442 ( hashbulkdelete PGNSP PGUID 12 f f t f v 3 23 "2281 2281 2281" hashbulkdelete - _null_ )); +DATA(insert OID = 442 ( hashbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" hashbulkdelete - _null_ )); DESCR("hash(internal)"); DATA(insert OID = 438 ( hashcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" hashcostestimate - _null_ )); DESCR("hash(internal)"); @@ -1015,23 +1015,23 @@ DESCR("larger of two"); DATA(insert OID = 771 ( int2smaller PGNSP PGUID 12 f f t f i 2 21 "21 21" int2smaller - _null_ )); DESCR("smaller of two"); -DATA(insert OID = 774 ( gistgettuple PGNSP PGUID 12 f f t f v 2 23 "2281 2281" gistgettuple - _null_ )); +DATA(insert OID = 774 ( gistgettuple PGNSP PGUID 12 f f t f v 2 16 "2281 2281" gistgettuple - _null_ )); DESCR("gist(internal)"); -DATA(insert OID = 775 ( gistinsert PGNSP PGUID 12 f f t f v 6 23 "2281 2281 2281 2281 2281 2281" gistinsert - _null_ )); +DATA(insert OID = 775 ( gistinsert PGNSP PGUID 12 f f t f v 6 2281 "2281 2281 2281 2281 2281 2281" gistinsert - _null_ )); DESCR("gist(internal)"); -DATA(insert OID = 777 ( gistbeginscan PGNSP PGUID 12 f f t f v 3 23 "2281 2281 2281" gistbeginscan - _null_ )); +DATA(insert OID = 777 ( gistbeginscan PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" gistbeginscan - _null_ )); DESCR("gist(internal)"); -DATA(insert OID = 778 ( gistrescan PGNSP PGUID 12 f f t f v 2 23 "2281 2281" gistrescan - _null_ )); +DATA(insert OID = 778 ( gistrescan PGNSP PGUID 12 f f t f v 2 2278 "2281 2281" gistrescan - _null_ )); DESCR("gist(internal)"); -DATA(insert OID = 779 ( gistendscan PGNSP PGUID 12 f f t f v 1 23 "2281" gistendscan - _null_ )); +DATA(insert OID = 779 ( gistendscan PGNSP PGUID 12 f f t f v 1 2278 "2281" gistendscan - _null_ )); DESCR("gist(internal)"); -DATA(insert OID = 780 ( gistmarkpos PGNSP PGUID 12 f f t f v 1 23 "2281" gistmarkpos - _null_ )); +DATA(insert OID = 780 ( gistmarkpos PGNSP PGUID 12 f f t f v 1 2278 "2281" gistmarkpos - _null_ )); DESCR("gist(internal)"); -DATA(insert OID = 781 ( gistrestrpos PGNSP PGUID 12 f f t f v 1 23 "2281" gistrestrpos - _null_ )); +DATA(insert OID = 781 ( gistrestrpos PGNSP PGUID 12 f f t f v 1 2278 "2281" gistrestrpos - _null_ )); DESCR("gist(internal)"); -DATA(insert OID = 782 ( gistbuild PGNSP PGUID 12 f f t f v 3 23 "2281 2281 2281" gistbuild - _null_ )); +DATA(insert OID = 782 ( gistbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" gistbuild - _null_ )); DESCR("gist(internal)"); -DATA(insert OID = 776 ( gistbulkdelete PGNSP PGUID 12 f f t f v 3 23 "2281 2281 2281" gistbulkdelete - _null_ )); +DATA(insert OID = 776 ( gistbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" gistbulkdelete - _null_ )); DESCR("gist(internal)"); DATA(insert OID = 772 ( gistcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" gistcostestimate - _null_ )); DESCR("gist(internal)"); diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index efdc8c6a50..66a2b71cac 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -187,6 +187,19 @@ WHERE p1.oid != p2.oid AND -------------+------------- (0 rows) +-- Look for functions that return type "internal" and do not have any +-- "internal" argument. Such a function would be a security hole since +-- it might be used to call an internal function from an SQL command. +-- As of 7.3 this query should find only internal_in. +SELECT p1.oid, p1.proname +FROM pg_proc as p1 +WHERE p1.prorettype = 'internal'::regtype AND NOT + ('(' || oidvectortypes(p1.proargtypes) || ')') ~ '[^a-z0-9_]internal[^a-z0-9_]'; + oid | proname +------+------------- + 2304 | internal_in +(1 row) + -- **************** pg_cast **************** -- Look for casts from and to the same type. This is not harmful, but -- useless. diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index d9be98a5fd..531a5523e0 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -148,6 +148,17 @@ WHERE p1.oid != p2.oid AND NOT p1.proisagg AND NOT p2.proisagg AND (p1.proargtypes[7] < p2.proargtypes[7]); +-- Look for functions that return type "internal" and do not have any +-- "internal" argument. Such a function would be a security hole since +-- it might be used to call an internal function from an SQL command. +-- As of 7.3 this query should find only internal_in. + +SELECT p1.oid, p1.proname +FROM pg_proc as p1 +WHERE p1.prorettype = 'internal'::regtype AND NOT + ('(' || oidvectortypes(p1.proargtypes) || ')') ~ '[^a-z0-9_]internal[^a-z0-9_]'; + + -- **************** pg_cast **************** -- Look for casts from and to the same type. This is not harmful, but