Re: [GENERAL] Many Pl/PgSQL parameters -> AllocSetAlloc(128)?

Поиск
Список
Период
Сортировка
От Tom Lane
Тема Re: [GENERAL] Many Pl/PgSQL parameters -> AllocSetAlloc(128)?
Дата
Msg-id 15931.1056571890@sss.pgh.pa.us
обсуждение исходный текст
Ответ на Re: [GENERAL] Many Pl/PgSQL parameters -> AllocSetAlloc(128)?  (Tom Lane <tgl@sss.pgh.pa.us>)
Ответы Re: [GENERAL] Many Pl/PgSQL parameters -> AllocSetAlloc(128)?  ("Reuven M. Lerner" <reuven@lerner.co.il>)
Список pgsql-hackers
I said:
> It might work to get rid of the "wild card" case (line 1115), which'd
> reduce the number of outputs to product(nsupers+1).  I doubt we really
> want any wild cards in there anymore.

I've fixed the problem along the above lines.  The patch against 7.3
branch is attached in case Reuven would like to apply it locally.

            regards, tom lane

*** src/backend/parser/parse_func.c.orig    Wed Apr 23 14:20:10 2003
--- src/backend/parser/parse_func.c    Wed Jun 25 15:32:52 2003
***************
*** 904,926 ****
   *    argtype_inherit() -- Construct an argtype vector reflecting the
   *                         inheritance properties of the supplied argv.
   *
!  *        This function is used to disambiguate among functions with the
!  *        same name but different signatures.  It takes an array of input
!  *        type ids.  For each type id in the array that's a complex type
!  *        (a class), it walks up the inheritance tree, finding all
!  *        superclasses of that type.    A vector of new Oid type arrays
!  *        is returned to the caller, reflecting the structure of the
!  *        inheritance tree above the supplied arguments.
   *
   *        The order of this vector is as follows:  all superclasses of the
   *        rightmost complex class are explored first.  The exploration
   *        continues from right to left.  This policy means that we favor
   *        keeping the leftmost argument type as low in the inheritance tree
   *        as possible.  This is intentional; it is exactly what we need to
!  *        do for method dispatch.  The last type array we return is all
!  *        zeroes.  This will match any functions for which return types are
!  *        not defined.  There are lots of these (mostly builtins) in the
!  *        catalogs.
   */
  static Oid **
  argtype_inherit(int nargs, Oid *argtypes)
--- 904,932 ----
   *    argtype_inherit() -- Construct an argtype vector reflecting the
   *                         inheritance properties of the supplied argv.
   *
!  *        This function is used to handle resolution of function calls when
!  *        there is no match to the given argument types, but there might be
!  *        matches based on considering complex types as members of their
!  *        superclass types (parent classes).
!  *
!  *        It takes an array of input type ids.  For each type id in the array
!  *        that's a complex type (a class), it walks up the inheritance tree,
!  *        finding all superclasses of that type. A vector of new Oid type
!  *        arrays is returned to the caller, listing possible alternative
!  *        interpretations of the input typeids as members of their superclasses
!  *        rather than the actually given argument types.  The vector is
!  *        terminated by a NULL pointer.
   *
   *        The order of this vector is as follows:  all superclasses of the
   *        rightmost complex class are explored first.  The exploration
   *        continues from right to left.  This policy means that we favor
   *        keeping the leftmost argument type as low in the inheritance tree
   *        as possible.  This is intentional; it is exactly what we need to
!  *        do for method dispatch.
!  *
!  *        The vector does not include the case where no complex classes have
!  *        been promoted, since that was already tried before this routine
!  *        got called.
   */
  static Oid **
  argtype_inherit(int nargs, Oid *argtypes)
***************
*** 929,950 ****
      int            i;
      InhPaths    arginh[FUNC_MAX_ARGS];

!     for (i = 0; i < FUNC_MAX_ARGS; i++)
      {
!         if (i < nargs)
!         {
!             arginh[i].self = argtypes[i];
!             if ((relid = typeidTypeRelid(argtypes[i])) != InvalidOid)
!                 arginh[i].nsupers = find_inheritors(relid, &(arginh[i].supervec));
!             else
!             {
!                 arginh[i].nsupers = 0;
!                 arginh[i].supervec = (Oid *) NULL;
!             }
!         }
          else
          {
-             arginh[i].self = InvalidOid;
              arginh[i].nsupers = 0;
              arginh[i].supervec = (Oid *) NULL;
          }
--- 935,947 ----
      int            i;
      InhPaths    arginh[FUNC_MAX_ARGS];

!     for (i = 0; i < nargs; i++)
      {
!         arginh[i].self = argtypes[i];
!         if ((relid = typeidTypeRelid(argtypes[i])) != InvalidOid)
!             arginh[i].nsupers = find_inheritors(relid, &(arginh[i].supervec));
          else
          {
              arginh[i].nsupers = 0;
              arginh[i].supervec = (Oid *) NULL;
          }
***************
*** 954,959 ****
--- 951,963 ----
      return gen_cross_product(arginh, nargs);
  }

+ /*
+  * Look up the parent superclass(es) of the given relation.
+  *
+  * *supervec is set to an array of the type OIDs (not the relation OIDs)
+  * of the parents, with nearest ancestors listed first.  It's set to NULL
+  * if there are no parents.  The return value is the number of parents.
+  */
  static int
  find_inheritors(Oid relid, Oid **supervec)
  {
***************
*** 1047,1105 ****
      return nvisited;
  }

  static Oid **
  gen_cross_product(InhPaths *arginh, int nargs)
  {
      int            nanswers;
!     Oid          **result,
!               **iter;
      Oid           *oneres;
      int            i,
                  j;
      int            cur[FUNC_MAX_ARGS];

      nanswers = 1;
      for (i = 0; i < nargs; i++)
!     {
!         nanswers *= (arginh[i].nsupers + 2);
!         cur[i] = 0;
!     }

!     iter = result = (Oid **) palloc(sizeof(Oid *) * nanswers);

-     /* compute the cross product from right to left */
      for (;;)
      {
!         oneres = (Oid *) palloc(FUNC_MAX_ARGS * sizeof(Oid));
!         MemSet(oneres, 0, FUNC_MAX_ARGS * sizeof(Oid));
!
!         for (i = nargs - 1; i >= 0 && cur[i] > arginh[i].nsupers; i--)
!             continue;

!         /* if we're done, terminate with NULL pointer */
          if (i < 0)
!         {
!             *iter = NULL;
!             return result;
!         }

!         /* no, increment this column and zero the ones after it */
!         cur[i] = cur[i] + 1;
!         for (j = nargs - 1; j > i; j--)
!             cur[j] = 0;

          for (i = 0; i < nargs; i++)
          {
              if (cur[i] == 0)
                  oneres[i] = arginh[i].self;
-             else if (cur[i] > arginh[i].nsupers)
-                 oneres[i] = 0;    /* wild card */
              else
                  oneres[i] = arginh[i].supervec[cur[i] - 1];
          }

!         *iter++ = oneres;
      }
  }


--- 1051,1132 ----
      return nvisited;
  }

+ /*
+  * Generate the ordered list of substitute argtype vectors to try.
+  *
+  * See comments for argtype_inherit.
+  */
  static Oid **
  gen_cross_product(InhPaths *arginh, int nargs)
  {
      int            nanswers;
!     Oid          **result;
      Oid           *oneres;
      int            i,
                  j;
      int            cur[FUNC_MAX_ARGS];

+     /*
+      * At each position we want to try the original datatype, plus each
+      * supertype.  So the number of possible combinations is this:
+      */
      nanswers = 1;
      for (i = 0; i < nargs; i++)
!         nanswers *= (arginh[i].nsupers + 1);

!     /*
!      * We also need an extra slot for the terminating NULL in the result
!      * array, but that cancels out with the fact that we don't want to
!      * generate the zero-changes case.  So we need exactly nanswers slots.
!      */
!     result = (Oid **) palloc(sizeof(Oid *) * nanswers);
!     j = 0;
!
!     /*
!      * Compute the cross product from right to left.  When cur[i] == 0,
!      * generate the original input type at position i.  When cur[i] == k
!      * for k > 0, generate its k'th supertype.
!      */
!     MemSet(cur, 0, sizeof(cur));

      for (;;)
      {
!         /*
!          * Find a column we can increment.  All the columns after it get
!          * reset to zero.  (Essentially, we're adding one to the multi-
!          * digit number represented by cur[].)
!          */
!         for (i = nargs - 1; i >= 0 && cur[i] >= arginh[i].nsupers; i--)
!             cur[i] = 0;

!         /* if none, we're done */
          if (i < 0)
!             break;

!         /* increment this column */
!         cur[i] += 1;
!
!         /* Generate the proper output type-OID vector */
!         oneres = (Oid *) palloc(FUNC_MAX_ARGS * sizeof(Oid));
!         MemSet(oneres, 0, FUNC_MAX_ARGS * sizeof(Oid));

          for (i = 0; i < nargs; i++)
          {
              if (cur[i] == 0)
                  oneres[i] = arginh[i].self;
              else
                  oneres[i] = arginh[i].supervec[cur[i] - 1];
          }

!         result[j++] = oneres;
      }
+
+     /* terminate result vector with NULL pointer */
+     result[j++] = NULL;
+
+     Assert(j == nanswers);
+
+     return result;
  }



В списке pgsql-hackers по дате отправления:

Предыдущее
От: nolan@celery.tssi.com
Дата:
Сообщение: Re: [GENERAL] Physical Database Configuration
Следующее
От: Bruce Momjian
Дата:
Сообщение: Re: Updating psql for features of new FE/BE protocol