Further cleanup around the edges of OPAQUE/pseudotype changes. Correct
authorTom Lane
Fri, 23 Aug 2002 16:41:38 +0000 (16:41 +0000)
committerTom Lane
Fri, 23 Aug 2002 16:41:38 +0000 (16:41 +0000)
the declarations of some index access method support functions.  Support
SQL functions returning VOID.

doc/src/sgml/xfunc.sgml
src/backend/catalog/pg_proc.c
src/backend/commands/typecmds.c
src/backend/executor/functions.c
src/include/catalog/pg_proc.h
src/test/regress/expected/opr_sanity.out
src/test/regress/sql/opr_sanity.sql

index 9b7c42d251f7417fca616ca078085a23ebbf974b..a38305ce0bc64880684ad496d430ec4a9711d15e 100644 (file)
@@ -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)
 
     
 
index 9f14f78099435059815d9015f8589ab10bea03ee..1bdb3796e6670cdd04fde0ebb269dcab356f7089 100644 (file)
@@ -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);
 
index bfca9c7c8f2f2248464a2493c6b067cbb0f45d4e..02e5a686e7758cba5bcd44a16dd09583c1bef044 100644 (file)
@@ -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))
        {
index 784bd94b0a747e117ef69ef67497fa140fd32071..eba919b8b66f8c650dbf11d63375dddb8693e621 100644 (file)
@@ -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;
-
-       nextes->next = NULL;
-       nextes->status = F_EXEC_START;
+           preves->next = newes;
+       else
+           firstes = newes;
 
-       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)
index 6fc56d439a384b18d4d942c4c16989218a88c31f..4129ea73b40ae16a3d93b6dfb95ccd82d1fe1be0 100644 (file)
@@ -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)");
index efdc8c6a5006a99c1f594a34e5dc282b6e2322bc..66a2b71cac510478a191052164a51280ba0b5412 100644 (file)
@@ -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.
index d9be98a5fd3d0b478d439858c51754d60334114d..531a5523e0abf3f2bb709e8cfd2c21896a9ec0d5 100644 (file)
@@ -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