Thread: Possible problem with pg_get_viewdef on Postgres V8.0.0 rc4

Possible problem with pg_get_viewdef on Postgres V8.0.0 rc4

From
laurie.burrow@powerconv.alstom.com
Date:
I have a view  definition  that creates a view on both Postgres 7 and
Postgres 8. The view definition works OK in that it does not return an
error and the resulting view seems to operate correctly on both versions of
Postgres.

However Pgadmin 1.2.0 works fine with the Postgres 7 database containing
the view but fails with the same database created on Postgres 8.0.0.rc4.

The cause of the pgadmin failure appears to be a call to
pg_get_viewdef(c.oid, true) used by pgadmin to populate its view display.
This function applied to my view works correctly on Postgres 7 but
generates the error Bogus Varno: 3
in Postgres 8.

The original query definition (as generated by Pgadmin 1.2.0 from Postgres
7.4.2) causing the problem was:

CREATE OR REPLACE VIEW full_product_view AS
 SELECT slimprdmgrrspperid AS _prd_slimprdmgrrspperid_,
( SELECT (rspper.lstnme::text || ' '::text) || rspper.frstnme::text
           FROM rspper
          WHERE rspper.rspperid = slimprdmgrrspperid) AS
_prd_slimprdmgrrspperid_d,
prdid AS _prd_prdid_, slimprdnmgnnmeid AS _prd_slimprdnmgnnmeid_,
actvle AS _slimprdnmgnnmeid_gennme_actvle_, catnmeclssid AS
_slimprdnmgnnmeid_gennme_catnmeclssid_
   FROM prd
   JOIN gennme ON gennme.gennmeid = prd.slimprdnmgnnmeid;


AFAICT the pg_get_viewdef function called by pgadmin objects to the scalar
subselect in the above view defintion. Rewriting my view query to include
the table qualification on the scalar sub select cures the problem with
pg_get_viewdef(c.oid, true).

The rewritten query definition is:

CREATE OR REPLACE VIEW full_product_view AS
 SELECT slimprdmgrrspperid AS _prd_slimprdmgrrspperid_,
( SELECT (rspper.lstnme::text || ' '::text) || rspper.frstnme::text
           FROM rspper
          WHERE rspper.rspperid = prd.slimprdmgrrspperid) AS
_prd_slimprdmgrrspperid_d,
prdid AS _prd_prdid_, slimprdnmgnnmeid AS _prd_slimprdnmgnnmeid_,
actvle AS _slimprdnmgnnmeid_gennme_actvle_, catnmeclssid AS
_slimprdnmgnnmeid_gennme_catnmeclssid_
   FROM prd
   JOIN gennme ON gennme.gennmeid = prd.slimprdnmgnnmeid;

   I don't know if this behaviour is expected.

   Regards
   Laurie



   :.________________
   CONFIDENTIALITY : This  e-mail  and  any attachments are confidential
   and may be privileged. If  you are not a named recipient, please notify
   the sender immediately and do not disclose the contents to another
   person, use it for any purpose or store or copy the information in any
   medium.

Re: Possible problem with pg_get_viewdef on Postgres V8.0.0 rc4

From
Tom Lane
Date:
laurie.burrow@powerconv.alstom.com writes:
> The cause of the pgadmin failure appears to be a call to
> pg_get_viewdef(c.oid, true) used by pgadmin to populate its view display.
> This function applied to my view works correctly on Postgres 7 but
> generates the error Bogus Varno: 3
> in Postgres 8.

Could we see a full example?  The view definition is of little use when
you didn't provide the definitions of the tables it references.

            regards, tom lane

Re: Possible problem with pg_get_viewdef on Postgres V8.0.0 rc4

From
laurie.burrow@powerconv.alstom.com
Date:
Tom Lane wrote:

> Could we see a full example?  The view definition is of little use when
> you didn't provide the definitions of the tables it references.

   Mea Culpa!

   The view references prd, and rspper tables whose defintions are shown
   below.

   I've included the gennme table as it is referenced by prd, and the
   nmeclss table as it is referenced by gennme

   CREATE TABLE prd
(
  slimprdmgrrspperid int4,
  prdid int4 NOT NULL DEFAULT nextval('PrdPrdID_seq'::text),
  slimprdnmgnnmeid int4 NOT NULL,
  CONSTRAINT prdpk PRIMARY KEY (prdid),
  CONSTRAINT gennmefk5 FOREIGN KEY (slimprdnmgnnmeid) REFERENCES gennme
(gennmeid) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT rspperfk2 FOREIGN KEY (slimprdmgrrspperid) REFERENCES rspper
(rspperid) ON UPDATE CASCADE ON DELETE NO ACTION
)
WITH OIDS;

CREATE TABLE rspper
(
  rspperid int4 NOT NULL DEFAULT nextval('RspPerRspPerID_seq'::text),
  ctctnt text,
  lstnme varchar(100) NOT NULL,
  eml varchar(100),
  frstnme varchar(100) NOT NULL,
  addr varchar(200),
  phn varchar(100),
  mob varchar(100),
  CONSTRAINT rspperpk PRIMARY KEY (rspperid),
  CONSTRAINT rspperak1_uc2 UNIQUE (frstnme, lstnme, phn)
)
WITH OIDS;

CREATE TABLE gennme
(
  gennmeid int4 NOT NULL DEFAULT nextval('GenNmeGenNmeID_seq'::text),
  actvle varchar(200) NOT NULL,
  lblloc varchar(1000),
  catnmeclssid varchar(200) NOT NULL,
  CONSTRAINT gennmepk PRIMARY KEY (gennmeid),
  CONSTRAINT nmeclssfk1 FOREIGN KEY (catnmeclssid) REFERENCES nmeclss
(nmeclssid) ON UPDATE CASCADE ON DELETE NO ACTION
)

CREATE TABLE nmeclss
(
  nmeclssid varchar(200) NOT NULL DEFAULT nextval
('NmeClssNmeClssID_seq'::text),
  CONSTRAINT nmeclsspk PRIMARY KEY (nmeclssid)
)
WITH OIDS;

Regards
Laurie

:.________________
CONFIDENTIALITY : This  e-mail  and  any attachments are confidential and
may be privileged. If  you are not a named recipient, please notify the
sender immediately and do not disclose the contents to another person, use
it for any purpose or store or copy the information in any medium.

Re: Possible problem with pg_get_viewdef on Postgres V8.0.0 rc4

From
Tom Lane
Date:
laurie.burrow@powerconv.alstom.com writes:
> Tom Lane wrote:
>> Could we see a full example?  The view definition is of little use when
>> you didn't provide the definitions of the tables it references.

>    Mea Culpa!

>    The view references prd, and rspper tables whose defintions are shown
>    below.

OK, I found the problem.  If you need a patch right away, it's attached.

            regards, tom lane


*** src/backend/utils/adt/ruleutils.c.orig    Sun Dec 12 19:33:06 2004
--- src/backend/utils/adt/ruleutils.c    Thu Jan 13 12:19:10 2005
***************
*** 182,188 ****
  static Node *get_rule_sortgroupclause(SortClause *srt, List *tlist,
                           bool force_colno,
                           deparse_context *context);
! static void get_names_for_var(Var *var, deparse_context *context,
                    char **schemaname, char **refname, char **attname);
  static RangeTblEntry *find_rte_by_refname(const char *refname,
                      deparse_context *context);
--- 182,188 ----
  static Node *get_rule_sortgroupclause(SortClause *srt, List *tlist,
                           bool force_colno,
                           deparse_context *context);
! static void get_names_for_var(Var *var, int levelsup, deparse_context *context,
                    char **schemaname, char **refname, char **attname);
  static RangeTblEntry *find_rte_by_refname(const char *refname,
                      deparse_context *context);
***************
*** 1998,2004 ****
                  char       *refname;
                  char       *attname;

!                 get_names_for_var(var, context,
                                    &schemaname, &refname, &attname);
                  tell_as = (attname == NULL ||
                             strcmp(attname, colname) != 0);
--- 1998,2004 ----
                  char       *refname;
                  char       *attname;

!                 get_names_for_var(var, 0, context,
                                    &schemaname, &refname, &attname);
                  tell_as = (attname == NULL ||
                             strcmp(attname, colname) != 0);
***************
*** 2392,2397 ****
--- 2392,2401 ----
  /*
   * Get the schemaname, refname and attname for a (possibly nonlocal) Var.
   *
+  * In some cases (currently only when recursing into an unnamed join)
+  * the Var's varlevelsup has to be interpreted with respect to a context
+  * above the current one; levelsup indicates the offset.
+  *
   * schemaname is usually returned as NULL.    It will be non-null only if
   * use of the unqualified refname would find the wrong RTE.
   *
***************
*** 2404,2420 ****
   * distinguish this case.)
   */
  static void
! get_names_for_var(Var *var, deparse_context *context,
                    char **schemaname, char **refname, char **attname)
  {
      deparse_namespace *dpns;
      RangeTblEntry *rte;

      /* Find appropriate nesting depth */
!     if (var->varlevelsup >= list_length(context->namespaces))
!         elog(ERROR, "bogus varlevelsup: %d", var->varlevelsup);
      dpns = (deparse_namespace *) list_nth(context->namespaces,
!                                           var->varlevelsup);

      /* Find the relevant RTE */
      if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
--- 2408,2427 ----
   * distinguish this case.)
   */
  static void
! get_names_for_var(Var *var, int levelsup, deparse_context *context,
                    char **schemaname, char **refname, char **attname)
  {
+     int            netlevelsup;
      deparse_namespace *dpns;
      RangeTblEntry *rte;

      /* Find appropriate nesting depth */
!     netlevelsup = var->varlevelsup + levelsup;
!     if (netlevelsup >= list_length(context->namespaces))
!         elog(ERROR, "bogus varlevelsup: %d offset %d",
!              var->varlevelsup, levelsup);
      dpns = (deparse_namespace *) list_nth(context->namespaces,
!                                           netlevelsup);

      /* Find the relevant RTE */
      if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
***************
*** 2467,2473 ****
                                              var->varattno-1);
                  if (IsA(aliasvar, Var))
                  {
!                     get_names_for_var(aliasvar, context,
                                        schemaname, refname, attname);
                      return;
                  }
--- 2474,2480 ----
                                              var->varattno-1);
                  if (IsA(aliasvar, Var))
                  {
!                     get_names_for_var(aliasvar, netlevelsup, context,
                                        schemaname, refname, attname);
                      return;
                  }
***************
*** 2867,2873 ****
                  char       *refname;
                  char       *attname;

!                 get_names_for_var(var, context,
                                    &schemaname, &refname, &attname);
                  if (refname && (context->varprefix || attname == NULL))
                  {
--- 2874,2880 ----
                  char       *refname;
                  char       *attname;

!                 get_names_for_var(var, 0, context,
                                    &schemaname, &refname, &attname);
                  if (refname && (context->varprefix || attname == NULL))
                  {