Re: several minor cleanups - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: several minor cleanups
Date
Msg-id 200206262159.g5QLxeg18099@candle.pha.pa.us
Whole thread Raw
In response to Re: several minor cleanups  (nconway@klamath.dyndns.org (Neil Conway))
List pgsql-patches
OK, I have applied this patch, except for the changes that effect the
elog messages. I will have to take a poll on general before I can make
those changes.

Thanks.

---------------------------------------------------------------------------

Neil Conway wrote:
> On Mon, Jun 24, 2002 at 04:53:17PM -0400, Tom Lane wrote:
> > Neil Conway <nconway@klamath.dyndns.org> writes:
> > ***************
> > *** 251,257 ****
> >       ExecCheckRTPerms(parseTree->rtable, operation);
> >
> >       /*
> > !      * Search for subplans and APPEND nodes to check their rangetables.
> >        */
> >       ExecCheckPlanPerms(plan, parseTree->rtable, operation);
> >   }
> > --- 251,257 ----
> >       ExecCheckRTPerms(parseTree->rtable, operation);
> >
> >       /*
> > !      * Search for subplans and INSERT nodes to check their rangetables.
> >        */
> >       ExecCheckPlanPerms(plan, parseTree->rtable, operation);
> >   }
> > ***************
> >
> > This comment was right beforehand and is so no longer :-(.
>
> Woops, s/append/insert/g was a bit over-enthusiastic. A revised
> patch is attached (it's also updated for CVS HEAD).
>
> > Otherwise I'm okay with this, if we don't mind the probability of
> > breaking existing client applications that are looking for ExecAppend:
> > messages.
>
> I would be skeptical of any client application that tries to
> divine information about the result of an operation by inspecting
> error messages. IMHO, such an approach is hopelessly fragile
> without error codes (or at least a well-defined set of
> possible errors for a given query).

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
Index: src/backend/executor/execMain.c
===================================================================
RCS file: /var/lib/cvs/pgsql/src/backend/executor/execMain.c,v
retrieving revision 1.165
diff -c -r1.165 execMain.c
*** src/backend/executor/execMain.c    20 Jun 2002 20:29:27 -0000    1.165
--- src/backend/executor/execMain.c    25 Jun 2002 14:09:22 -0000
***************
*** 62,75 ****
              long numberTuples,
              ScanDirection direction,
              DestReceiver *destfunc);
! static void ExecRetrieve(TupleTableSlot *slot,
               DestReceiver *destfunc,
               EState *estate);
! static void ExecAppend(TupleTableSlot *slot, ItemPointer tupleid,
             EState *estate);
  static void ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
             EState *estate);
! static void ExecReplace(TupleTableSlot *slot, ItemPointer tupleid,
              EState *estate);
  static TupleTableSlot *EvalPlanQualNext(EState *estate);
  static void EndEvalPlanQual(EState *estate);
--- 62,75 ----
              long numberTuples,
              ScanDirection direction,
              DestReceiver *destfunc);
! static void ExecSelect(TupleTableSlot *slot,
               DestReceiver *destfunc,
               EState *estate);
! static void ExecInsert(TupleTableSlot *slot, ItemPointer tupleid,
             EState *estate);
  static void ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
             EState *estate);
! static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
              EState *estate);
  static TupleTableSlot *EvalPlanQualNext(EState *estate);
  static void EndEvalPlanQual(EState *estate);
***************
*** 583,589 ****
      /*
       * Get the tuple descriptor describing the type of tuples to return.
       * (this is especially important if we are creating a relation with
!      * "retrieve into")
       */
      tupType = ExecGetTupType(plan);        /* tuple descriptor */

--- 583,589 ----
      /*
       * Get the tuple descriptor describing the type of tuples to return.
       * (this is especially important if we are creating a relation with
!      * "SELECT INTO")
       */
      tupType = ExecGetTupType(plan);        /* tuple descriptor */

***************
*** 892,898 ****
   *        Retrieves all tuples if numberTuples is 0
   *
   *        result is either a slot containing the last tuple in the case
!  *        of a RETRIEVE or NULL otherwise.
   *
   * Note: the ctid attribute is a 'junk' attribute that is removed before the
   * user can see it
--- 892,898 ----
   *        Retrieves all tuples if numberTuples is 0
   *
   *        result is either a slot containing the last tuple in the case
!  *        of a SELECT or NULL otherwise.
   *
   * Note: the ctid attribute is a 'junk' attribute that is removed before the
   * user can see it
***************
*** 1068,1096 ****

              slot = ExecStoreTuple(newTuple,        /* tuple to store */
                                    junkfilter->jf_resultSlot,    /* dest slot */
!                                   InvalidBuffer,        /* this tuple has no
!                                                          * buffer */
                                    true);        /* tuple should be pfreed */
!         }                        /* if (junkfilter... */

          /*
           * now that we have a tuple, do the appropriate thing with it..
           * either return it to the user, add it to a relation someplace,
           * delete it from a relation, or modify some of its attributes.
           */
-
          switch (operation)
          {
              case CMD_SELECT:
!                 ExecRetrieve(slot,        /* slot containing tuple */
!                              destfunc,    /* destination's tuple-receiver
!                                          * obj */
!                              estate);    /* */
                  result = slot;
                  break;

              case CMD_INSERT:
!                 ExecAppend(slot, tupleid, estate);
                  result = NULL;
                  break;

--- 1068,1093 ----

              slot = ExecStoreTuple(newTuple,        /* tuple to store */
                                    junkfilter->jf_resultSlot,    /* dest slot */
!                                   InvalidBuffer,    /* this tuple has no buffer */
                                    true);        /* tuple should be pfreed */
!         }

          /*
           * now that we have a tuple, do the appropriate thing with it..
           * either return it to the user, add it to a relation someplace,
           * delete it from a relation, or modify some of its attributes.
           */
          switch (operation)
          {
              case CMD_SELECT:
!                 ExecSelect(slot,        /* slot containing tuple */
!                            destfunc,    /* destination's tuple-receiver obj */
!                            estate);
                  result = slot;
                  break;

              case CMD_INSERT:
!                 ExecInsert(slot, tupleid, estate);
                  result = NULL;
                  break;

***************
*** 1100,1106 ****
                  break;

              case CMD_UPDATE:
!                 ExecReplace(slot, tupleid, estate);
                  result = NULL;
                  break;

--- 1097,1103 ----
                  break;

              case CMD_UPDATE:
!                 ExecUpdate(slot, tupleid, estate);
                  result = NULL;
                  break;

***************
*** 1121,1145 ****

      /*
       * here, result is either a slot containing a tuple in the case of a
!      * RETRIEVE or NULL otherwise.
       */
      return result;
  }

  /* ----------------------------------------------------------------
!  *        ExecRetrieve
   *
!  *        RETRIEVEs are easy.. we just pass the tuple to the appropriate
   *        print function.  The only complexity is when we do a
!  *        "retrieve into", in which case we insert the tuple into
   *        the appropriate relation (note: this is a newly created relation
   *        so we don't need to worry about indices or locks.)
   * ----------------------------------------------------------------
   */
  static void
! ExecRetrieve(TupleTableSlot *slot,
!              DestReceiver *destfunc,
!              EState *estate)
  {
      HeapTuple    tuple;
      TupleDesc    attrtype;
--- 1118,1142 ----

      /*
       * here, result is either a slot containing a tuple in the case of a
!      * SELECT or NULL otherwise.
       */
      return result;
  }

  /* ----------------------------------------------------------------
!  *        ExecSelect
   *
!  *        SELECTs are easy.. we just pass the tuple to the appropriate
   *        print function.  The only complexity is when we do a
!  *        "SELECT INTO", in which case we insert the tuple into
   *        the appropriate relation (note: this is a newly created relation
   *        so we don't need to worry about indices or locks.)
   * ----------------------------------------------------------------
   */
  static void
! ExecSelect(TupleTableSlot *slot,
!            DestReceiver *destfunc,
!            EState *estate)
  {
      HeapTuple    tuple;
      TupleDesc    attrtype;
***************
*** 1169,1184 ****
  }

  /* ----------------------------------------------------------------
!  *        ExecAppend
   *
!  *        APPENDs are trickier.. we have to insert the tuple into
   *        the base relation and insert appropriate tuples into the
   *        index relations.
   * ----------------------------------------------------------------
   */
-
  static void
! ExecAppend(TupleTableSlot *slot,
             ItemPointer tupleid,
             EState *estate)
  {
--- 1166,1180 ----
  }

  /* ----------------------------------------------------------------
!  *        ExecInsert
   *
!  *        INSERTs are trickier.. we have to insert the tuple into
   *        the base relation and insert appropriate tuples into the
   *        index relations.
   * ----------------------------------------------------------------
   */
  static void
! ExecInsert(TupleTableSlot *slot,
             ItemPointer tupleid,
             EState *estate)
  {
***************
*** 1227,1233 ****
       * Check the constraints of the tuple
       */
      if (resultRelationDesc->rd_att->constr)
!         ExecConstraints("ExecAppend", resultRelInfo, slot, estate);

      /*
       * insert the tuple
--- 1223,1229 ----
       * Check the constraints of the tuple
       */
      if (resultRelationDesc->rd_att->constr)
!         ExecConstraints("ExecInsert", resultRelInfo, slot, estate);

      /*
       * insert the tuple
***************
*** 1259,1265 ****
  /* ----------------------------------------------------------------
   *        ExecDelete
   *
!  *        DELETE is like append, we delete the tuple and its
   *        index tuples.
   * ----------------------------------------------------------------
   */
--- 1255,1261 ----
  /* ----------------------------------------------------------------
   *        ExecDelete
   *
!  *        DELETE is like UPDATE, we delete the tuple and its
   *        index tuples.
   * ----------------------------------------------------------------
   */
***************
*** 1346,1363 ****
  }

  /* ----------------------------------------------------------------
!  *        ExecReplace
   *
!  *        note: we can't run replace queries with transactions
!  *        off because replaces are actually appends and our
!  *        scan will mistakenly loop forever, replacing the tuple
!  *        it just appended..    This should be fixed but until it
   *        is, we don't want to get stuck in an infinite loop
   *        which corrupts your database..
   * ----------------------------------------------------------------
   */
  static void
! ExecReplace(TupleTableSlot *slot,
              ItemPointer tupleid,
              EState *estate)
  {
--- 1342,1359 ----
  }

  /* ----------------------------------------------------------------
!  *        ExecUpdate
   *
!  *        note: we can't run UPDATE queries with transactions
!  *        off because UPDATEs are actually INSERTs and our
!  *        scan will mistakenly loop forever, updating the tuple
!  *        it just inserted..    This should be fixed but until it
   *        is, we don't want to get stuck in an infinite loop
   *        which corrupts your database..
   * ----------------------------------------------------------------
   */
  static void
! ExecUpdate(TupleTableSlot *slot,
              ItemPointer tupleid,
              EState *estate)
  {
***************
*** 1472,1478 ****
      /*
       * Note: instead of having to update the old index tuples associated
       * with the heap tuple, all we do is form and insert new index tuples.
!      * This is because replaces are actually deletes and inserts and index
       * tuple deletion is done automagically by the vacuum daemon. All we
       * do is insert new index tuples.  -cim 9/27/89
       */
--- 1468,1474 ----
      /*
       * Note: instead of having to update the old index tuples associated
       * with the heap tuple, all we do is form and insert new index tuples.
!      * This is because UPDATEs are actually DELETEs and INSERTs and index
       * tuple deletion is done automagically by the vacuum daemon. All we
       * do is insert new index tuples.  -cim 9/27/89
       */
***************
*** 1481,1487 ****
       * process indices
       *
       * heap_update updates a tuple in the base relation by invalidating it
!      * and then appending a new tuple to the relation.    As a side effect,
       * the tupleid of the new tuple is placed in the new tuple's t_ctid
       * field.  So we now insert index tuples using the new tupleid stored
       * there.
--- 1477,1483 ----
       * process indices
       *
       * heap_update updates a tuple in the base relation by invalidating it
!      * and then inserting a new tuple to the relation.    As a side effect,
       * the tupleid of the new tuple is placed in the new tuple's t_ctid
       * field.  So we now insert index tuples using the new tupleid stored
       * there.
***************
*** 1554,1560 ****
  }

  void
! ExecConstraints(char *caller, ResultRelInfo *resultRelInfo,
                  TupleTableSlot *slot, EState *estate)
  {
      Relation    rel = resultRelInfo->ri_RelationDesc;
--- 1550,1556 ----
  }

  void
! ExecConstraints(const char *caller, ResultRelInfo *resultRelInfo,
                  TupleTableSlot *slot, EState *estate)
  {
      Relation    rel = resultRelInfo->ri_RelationDesc;
Index: src/backend/executor/execUtils.c
===================================================================
RCS file: /var/lib/cvs/pgsql/src/backend/executor/execUtils.c,v
retrieving revision 1.83
diff -c -r1.83 execUtils.c
*** src/backend/executor/execUtils.c    20 Jun 2002 20:29:28 -0000    1.83
--- src/backend/executor/execUtils.c    25 Jun 2002 14:09:22 -0000
***************
*** 18,24 ****
   *
   *        ExecOpenIndices            \
   *        ExecCloseIndices         | referenced by InitPlan, EndPlan,
!  *        ExecInsertIndexTuples    /  ExecAppend, ExecReplace
   *
   *        RegisterExprContextCallback    Register function shutdown callback
   *        UnregisterExprContextCallback  Deregister function shutdown callback
--- 18,24 ----
   *
   *        ExecOpenIndices            \
   *        ExecCloseIndices         | referenced by InitPlan, EndPlan,
!  *        ExecInsertIndexTuples    /  ExecInsert, ExecUpdate
   *
   *        RegisterExprContextCallback    Register function shutdown callback
   *        UnregisterExprContextCallback  Deregister function shutdown callback
Index: src/backend/optimizer/path/costsize.c
===================================================================
RCS file: /var/lib/cvs/pgsql/src/backend/optimizer/path/costsize.c,v
retrieving revision 1.85
diff -c -r1.85 costsize.c
*** src/backend/optimizer/path/costsize.c    20 Jun 2002 20:29:29 -0000    1.85
--- src/backend/optimizer/path/costsize.c    25 Jun 2002 14:09:22 -0000
***************
*** 154,164 ****
   *
   * Given a guesstimated cache size, we estimate the actual I/O cost per page
   * with the entirely ad-hoc equations:
!  *    for rel_size <= effective_cache_size:
!  *        1 + (random_page_cost/2-1) * (rel_size/effective_cache_size) ** 2
!  *    for rel_size >= effective_cache_size:
!  *        random_page_cost * (1 - (effective_cache_size/rel_size)/2)
!  * These give the right asymptotic behavior (=> 1.0 as rel_size becomes
   * small, => random_page_cost as it becomes large) and meet in the middle
   * with the estimate that the cache is about 50% effective for a relation
   * of the same size as effective_cache_size.  (XXX this is probably all
--- 154,164 ----
   *
   * Given a guesstimated cache size, we estimate the actual I/O cost per page
   * with the entirely ad-hoc equations:
!  *    if relpages >= effective_cache_size:
!  *        random_page_cost * (1 - (effective_cache_size/relpages)/2)
!  *    if relpages < effective_cache_size:
!  *        1 + (random_page_cost/2-1) * (relpages/effective_cache_size) ** 2
!  * These give the right asymptotic behavior (=> 1.0 as relpages becomes
   * small, => random_page_cost as it becomes large) and meet in the middle
   * with the estimate that the cache is about 50% effective for a relation
   * of the same size as effective_cache_size.  (XXX this is probably all
Index: src/backend/optimizer/prep/_deadcode/prepkeyset.c
===================================================================
RCS file: /var/lib/cvs/pgsql/src/backend/optimizer/prep/_deadcode/prepkeyset.c,v
retrieving revision 1.2
diff -c -r1.2 prepkeyset.c
*** src/backend/optimizer/prep/_deadcode/prepkeyset.c    20 Jun 2002 20:29:31 -0000    1.2
--- src/backend/optimizer/prep/_deadcode/prepkeyset.c    25 Jun 2002 14:09:22 -0000
***************
*** 1,7 ****
  /*-------------------------------------------------------------------------
   *
   * prepkeyset.c
!  *      Special preperation for keyset queries.
   *
   * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
--- 1,7 ----
  /*-------------------------------------------------------------------------
   *
   * prepkeyset.c
!  *      Special preparation for keyset queries (KSQO).
   *
   * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
   * Portions Copyright (c) 1994, Regents of the University of California
***************
*** 14,25 ****
  #include "postgres.h"
  #include "optimizer/planmain.h"

- /*
-  * Node_Copy
-  *          a macro to simplify calling of copyObject on the specified field
-  */
- #define Node_Copy(from, newnode, field) newnode->field = copyObject(from->field)
-
  bool        _use_keyset_query_optimizer = FALSE;

  #ifdef ENABLE_KEY_SET_QUERY
--- 14,19 ----
***************
*** 55,67 ****
   *     a HAVING, or a GROUP BY.    It must be a single table and have KSQO
   *     set to 'on'.
   *
!  *     The primary use of this transformation is to avoid the exponrntial
   *     memory consumption of cnfify() and to make use of index access
   *     methods.
   *
   *          daveh@insightdist.com   1998-08-31
   *
   *     May want to also prune out duplicate terms.
   **********************************************************************/
  void
  transformKeySetQuery(Query *origNode)
--- 49,68 ----
   *     a HAVING, or a GROUP BY.    It must be a single table and have KSQO
   *     set to 'on'.
   *
!  *     The primary use of this transformation is to avoid the exponential
   *     memory consumption of cnfify() and to make use of index access
   *     methods.
   *
   *          daveh@insightdist.com   1998-08-31
   *
   *     May want to also prune out duplicate terms.
+  *
+  *     XXX: this code is currently not compiled because it has not been
+  *     updated to work with the re-implementation of UNION/INTERSECT/EXCEPT
+  *     in PostgreSQL 7.1. However, it is of questionable value in any
+  *     case, because it changes the semantics of the original query:
+  *     UNION will add an implicit SELECT DISTINCT, which might change
+  *     the results that are returned.
   **********************************************************************/
  void
  transformKeySetQuery(Query *origNode)
Index: src/include/executor/executor.h
===================================================================
RCS file: /var/lib/cvs/pgsql/src/include/executor/executor.h,v
retrieving revision 1.66
diff -c -r1.66 executor.h
*** src/include/executor/executor.h    20 Jun 2002 20:29:49 -0000    1.66
--- src/include/executor/executor.h    25 Jun 2002 14:09:22 -0000
***************
*** 52,58 ****
  extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, EState *estate,
                                     ScanDirection direction, long count);
  extern void ExecutorEnd(QueryDesc *queryDesc, EState *estate);
! extern void ExecConstraints(char *caller, ResultRelInfo *resultRelInfo,
                  TupleTableSlot *slot, EState *estate);
  extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
               ItemPointer tid);
--- 52,58 ----
  extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, EState *estate,
                                     ScanDirection direction, long count);
  extern void ExecutorEnd(QueryDesc *queryDesc, EState *estate);
! extern void ExecConstraints(const char *caller, ResultRelInfo *resultRelInfo,
                  TupleTableSlot *slot, EState *estate);
  extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
               ItemPointer tid);
Index: src/test/regress/expected/create_misc.out
===================================================================
RCS file: /var/lib/cvs/pgsql/src/test/regress/expected/create_misc.out,v
retrieving revision 1.13
diff -c -r1.13 create_misc.out
*** src/test/regress/expected/create_misc.out    6 Mar 2002 06:10:52 -0000    1.13
--- src/test/regress/expected/create_misc.out    25 Jun 2002 14:09:23 -0000
***************
*** 151,153 ****
--- 151,163 ----
   force | 100
  (3 rows)

+ CREATE SEQUENCE sequence_test;
+ BEGIN;
+ SELECT nextval('sequence_test');
+  nextval
+ ---------
+        1
+ (1 row)
+
+ DROP SEQUENCE sequence_test;
+ END;
Index: src/test/regress/expected/select_having.out
===================================================================
RCS file: /var/lib/cvs/pgsql/src/test/regress/expected/select_having.out,v
retrieving revision 1.4
diff -c -r1.4 select_having.out
*** src/test/regress/expected/select_having.out    6 Jan 2000 06:40:54 -0000    1.4
--- src/test/regress/expected/select_having.out    25 Jun 2002 14:09:23 -0000
***************
*** 21,26 ****
--- 21,35 ----
   3 | bbbb
  (2 rows)

+ -- HAVING is equivalent to WHERE in this case
+ SELECT b, c FROM test_having
+     GROUP BY b, c HAVING b = 3;
+  b |    c
+ ---+----------
+  3 | BBBB
+  3 | bbbb
+ (2 rows)
+
  SELECT lower(c), count(c) FROM test_having
      GROUP BY lower(c) HAVING count(*) > 2 OR min(a) = max(a);
    lower   | count
Index: src/test/regress/sql/create_misc.sql
===================================================================
RCS file: /var/lib/cvs/pgsql/src/test/regress/sql/create_misc.sql,v
retrieving revision 1.9
diff -c -r1.9 create_misc.sql
*** src/test/regress/sql/create_misc.sql    21 May 2001 16:54:46 -0000    1.9
--- src/test/regress/sql/create_misc.sql    25 Jun 2002 14:09:23 -0000
***************
*** 217,219 ****
--- 217,226 ----
  INSERT INTO serialTest VALUES ('wrong', NULL);

  SELECT * FROM serialTest;
+
+ CREATE SEQUENCE sequence_test;
+
+ BEGIN;
+ SELECT nextval('sequence_test');
+ DROP SEQUENCE sequence_test;
+ END;
Index: src/test/regress/sql/select_having.sql
===================================================================
RCS file: /var/lib/cvs/pgsql/src/test/regress/sql/select_having.sql,v
retrieving revision 1.4
diff -c -r1.4 select_having.sql
*** src/test/regress/sql/select_having.sql    6 Jan 2000 06:41:55 -0000    1.4
--- src/test/regress/sql/select_having.sql    25 Jun 2002 14:09:23 -0000
***************
*** 18,23 ****
--- 18,27 ----
  SELECT b, c FROM test_having
      GROUP BY b, c HAVING count(*) = 1;

+ -- HAVING is equivalent to WHERE in this case
+ SELECT b, c FROM test_having
+     GROUP BY b, c HAVING b = 3;
+
  SELECT lower(c), count(c) FROM test_having
      GROUP BY lower(c) HAVING count(*) > 2 OR min(a) = max(a);


pgsql-patches by date:

Previous
From: Peter Eisentraut
Date:
Subject: Re: show() function
Next
From: Tom Lane
Date:
Subject: Re: show() function