Re: [GENERAL] trouble with pg_upgrade 9.0 -> 9.1

Поиск
Список
Период
Сортировка
От Bruce Momjian
Тема Re: [GENERAL] trouble with pg_upgrade 9.0 -> 9.1
Дата
Msg-id 20121220185726.GK20015@momjian.us
обсуждение исходный текст
Ответ на Re: [GENERAL] trouble with pg_upgrade 9.0 -> 9.1  (Bruce Momjian <bruce@momjian.us>)
Список pgsql-hackers
Applied.  We can mark this report closed.  Groshev, let us know if you
have any further problems.

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

On Thu, Dec 20, 2012 at 07:19:48AM -0500, Bruce Momjian wrote:
> On Wed, Dec 19, 2012 at 10:19:30PM -0500, Bruce Momjian wrote:
> > On Wed, Dec 19, 2012 at 12:56:05PM -0500, Kevin Grittner wrote:
> > > Groshev Andrey wrote:
> > > 
> > > > >>>>>   Mismatch of relation names: database "database", old rel
public.lob.ВерсияВнешнегоДокумента$Документ_pkey,new rel public.plob.ВерсияВнешнегоДокумента$Документ
 
> > > 
> > > There is a limit on identifiers of 63 *bytes* (not characters)
> > > after which the name is truncated. In UTF8 encoding, the underscore
> > > would be in the 64th position.
> > 
> > OK, Kevin is certainly pointing out a bug in the pg_upgrade code, though
> > I am unclear how it would exhibit the mismatch error reported.
> > 
> > pg_upgrade uses NAMEDATALEN for database, schema, and relation name
> > storage lengths.  While NAMEDATALEN works fine in the backend, it is
> > possible that a frontend client, like pg_upgrade, could retrieve a name
> > in the client encoding whose length exceeds NAMEDATALEN if the client
> > encoding did not match the database encoding (or is it the cluster
> > encoding for system tables).  This would cause truncation of these
> > values.  The truncation would not cause crashes, but might cause
> > failures by not being able to connect to overly-long database names, and
> > it weakens the checking of relation/schema names --- the same check that
> > is reported above.
> > 
> > (I believe initdb.c also erroneously uses NAMEDATALEN.)
> 
> I have developed the attached patch to pg_strdup() the string returned
> from libpq, rather than use a fixed NAMEDATALEN buffer to store the
> value.  I am only going to apply this to 9.3 because I can't see this
> causing problems except for weaker comparisons for very long identifiers
> where the client encoding is longer than the server encoding, and
> failures for very long database names, no of which we have gotten bug
> reports about.
> 
> Turns out initdb.c was fine because it expects only collation names to
> be only in ASCII;   I added a comment to that effect.
> 
> -- 
>   Bruce Momjian  <bruce@momjian.us>        http://momjian.us
>   EnterpriseDB                             http://enterprisedb.com
> 
>   + It's impossible for everything to be true. +

> diff --git a/contrib/pg_upgrade/info.c b/contrib/pg_upgrade/info.c
> new file mode 100644
> index 2250442..5cb9b61
> *** a/contrib/pg_upgrade/info.c
> --- b/contrib/pg_upgrade/info.c
> *************** static void get_db_infos(ClusterInfo *cl
> *** 23,29 ****
>   static void get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo);
>   static void free_rel_infos(RelInfoArr *rel_arr);
>   static void print_db_infos(DbInfoArr *dbinfo);
> ! static void print_rel_infos(RelInfoArr *arr);
>   
>   
>   /*
> --- 23,29 ----
>   static void get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo);
>   static void free_rel_infos(RelInfoArr *rel_arr);
>   static void print_db_infos(DbInfoArr *dbinfo);
> ! static void print_rel_infos(RelInfoArr *rel_arr);
>   
>   
>   /*
> *************** create_rel_filename_map(const char *old_
> *** 127,134 ****
>       map->new_relfilenode = new_rel->relfilenode;
>   
>       /* used only for logging and error reporing, old/new are identical */
> !     snprintf(map->nspname, sizeof(map->nspname), "%s", old_rel->nspname);
> !     snprintf(map->relname, sizeof(map->relname), "%s", old_rel->relname);
>   }
>   
>   
> --- 127,134 ----
>       map->new_relfilenode = new_rel->relfilenode;
>   
>       /* used only for logging and error reporing, old/new are identical */
> !     map->nspname = old_rel->nspname;
> !     map->relname = old_rel->relname;
>   }
>   
>   
> *************** get_db_infos(ClusterInfo *cluster)
> *** 220,227 ****
>       for (tupnum = 0; tupnum < ntups; tupnum++)
>       {
>           dbinfos[tupnum].db_oid = atooid(PQgetvalue(res, tupnum, i_oid));
> !         snprintf(dbinfos[tupnum].db_name, sizeof(dbinfos[tupnum].db_name), "%s",
> !                  PQgetvalue(res, tupnum, i_datname));
>           snprintf(dbinfos[tupnum].db_tblspace, sizeof(dbinfos[tupnum].db_tblspace), "%s",
>                    PQgetvalue(res, tupnum, i_spclocation));
>       }
> --- 220,226 ----
>       for (tupnum = 0; tupnum < ntups; tupnum++)
>       {
>           dbinfos[tupnum].db_oid = atooid(PQgetvalue(res, tupnum, i_oid));
> !         dbinfos[tupnum].db_name = pg_strdup(PQgetvalue(res, tupnum, i_datname));
>           snprintf(dbinfos[tupnum].db_tblspace, sizeof(dbinfos[tupnum].db_tblspace), "%s",
>                    PQgetvalue(res, tupnum, i_spclocation));
>       }
> *************** get_rel_infos(ClusterInfo *cluster, DbIn
> *** 346,355 ****
>           curr->reloid = atooid(PQgetvalue(res, relnum, i_oid));
>   
>           nspname = PQgetvalue(res, relnum, i_nspname);
> !         strlcpy(curr->nspname, nspname, sizeof(curr->nspname));
>   
>           relname = PQgetvalue(res, relnum, i_relname);
> !         strlcpy(curr->relname, relname, sizeof(curr->relname));
>   
>           curr->relfilenode = atooid(PQgetvalue(res, relnum, i_relfilenode));
>   
> --- 345,354 ----
>           curr->reloid = atooid(PQgetvalue(res, relnum, i_oid));
>   
>           nspname = PQgetvalue(res, relnum, i_nspname);
> !         curr->nspname = pg_strdup(nspname);
>   
>           relname = PQgetvalue(res, relnum, i_relname);
> !         curr->relname = pg_strdup(relname);
>   
>           curr->relfilenode = atooid(PQgetvalue(res, relnum, i_relfilenode));
>   
> *************** free_db_and_rel_infos(DbInfoArr *db_arr)
> *** 377,383 ****
> --- 376,385 ----
>       int            dbnum;
>   
>       for (dbnum = 0; dbnum < db_arr->ndbs; dbnum++)
> +     {
>           free_rel_infos(&db_arr->dbs[dbnum].rel_arr);
> +         pg_free(db_arr->dbs[dbnum].db_name);
> +     }
>       pg_free(db_arr->dbs);
>       db_arr->dbs = NULL;
>       db_arr->ndbs = 0;
> *************** free_db_and_rel_infos(DbInfoArr *db_arr)
> *** 387,392 ****
> --- 389,401 ----
>   static void
>   free_rel_infos(RelInfoArr *rel_arr)
>   {
> +     int            relnum;
> + 
> +     for (relnum = 0; relnum < rel_arr->nrels; relnum++)
> +     {
> +         pg_free(rel_arr->rels[relnum].nspname);
> +         pg_free(rel_arr->rels[relnum].relname);
> +     }
>       pg_free(rel_arr->rels);
>       rel_arr->nrels = 0;
>   }
> *************** print_db_infos(DbInfoArr *db_arr)
> *** 407,418 ****
>   
>   
>   static void
> ! print_rel_infos(RelInfoArr *arr)
>   {
>       int            relnum;
>   
> !     for (relnum = 0; relnum < arr->nrels; relnum++)
>           pg_log(PG_VERBOSE, "relname: %s.%s: reloid: %u reltblspace: %s\n",
> !                arr->rels[relnum].nspname, arr->rels[relnum].relname,
> !                arr->rels[relnum].reloid, arr->rels[relnum].tablespace);
>   }
> --- 416,427 ----
>   
>   
>   static void
> ! print_rel_infos(RelInfoArr *rel_arr)
>   {
>       int            relnum;
>   
> !     for (relnum = 0; relnum < rel_arr->nrels; relnum++)
>           pg_log(PG_VERBOSE, "relname: %s.%s: reloid: %u reltblspace: %s\n",
> !                rel_arr->rels[relnum].nspname, rel_arr->rels[relnum].relname,
> !                rel_arr->rels[relnum].reloid, rel_arr->rels[relnum].tablespace);
>   }
> diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
> new file mode 100644
> index 972e8e9..cae1e46
> *** a/contrib/pg_upgrade/pg_upgrade.h
> --- b/contrib/pg_upgrade/pg_upgrade.h
> *************** extern char *output_files[];
> *** 114,121 ****
>    */
>   typedef struct
>   {
> !     char        nspname[NAMEDATALEN];    /* namespace name */
> !     char        relname[NAMEDATALEN];    /* relation name */
>       Oid            reloid;            /* relation oid */
>       Oid            relfilenode;    /* relation relfile node */
>       /* relation tablespace path, or "" for the cluster default */
> --- 114,122 ----
>    */
>   typedef struct
>   {
> !     /* Can't use NAMEDATALEN;  not guaranteed to fit on client */
> !     char        *nspname;        /* namespace name */
> !     char        *relname;        /* relation name */
>       Oid            reloid;            /* relation oid */
>       Oid            relfilenode;    /* relation relfile node */
>       /* relation tablespace path, or "" for the cluster default */
> *************** typedef struct
> *** 143,150 ****
>       Oid            old_relfilenode;
>       Oid            new_relfilenode;
>       /* the rest are used only for logging and error reporting */
> !     char        nspname[NAMEDATALEN];    /* namespaces */
> !     char        relname[NAMEDATALEN];
>   } FileNameMap;
>   
>   /*
> --- 144,151 ----
>       Oid            old_relfilenode;
>       Oid            new_relfilenode;
>       /* the rest are used only for logging and error reporting */
> !     char        *nspname;        /* namespaces */
> !     char        *relname;
>   } FileNameMap;
>   
>   /*
> *************** typedef struct
> *** 153,159 ****
>   typedef struct
>   {
>       Oid            db_oid;            /* oid of the database */
> !     char        db_name[NAMEDATALEN];    /* database name */
>       char        db_tblspace[MAXPGPATH]; /* database default tablespace path */
>       RelInfoArr    rel_arr;        /* array of all user relinfos */
>   } DbInfo;
> --- 154,160 ----
>   typedef struct
>   {
>       Oid            db_oid;            /* oid of the database */
> !     char        *db_name;        /* database name */
>       char        db_tblspace[MAXPGPATH]; /* database default tablespace path */
>       RelInfoArr    rel_arr;        /* array of all user relinfos */
>   } DbInfo;
> diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
> new file mode 100644
> index 40740dc..3e05ac3
> *** a/src/bin/initdb/initdb.c
> --- b/src/bin/initdb/initdb.c
> *************** setup_collation(void)
> *** 1836,1842 ****
>   #if defined(HAVE_LOCALE_T) && !defined(WIN32)
>       int            i;
>       FILE       *locale_a_handle;
> !     char        localebuf[NAMEDATALEN];
>       int            count = 0;
>   
>       PG_CMD_DECL;
> --- 1836,1842 ----
>   #if defined(HAVE_LOCALE_T) && !defined(WIN32)
>       int            i;
>       FILE       *locale_a_handle;
> !     char        localebuf[NAMEDATALEN]; /* we assume ASCII so this is fine */
>       int            count = 0;
>   
>       PG_CMD_DECL;

> 
> -- 
> Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-hackers


--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +



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

Предыдущее
От: Robert Haas
Дата:
Сообщение: Re: Set visibility map bit after HOT prune
Следующее
От: Bruce Momjian
Дата:
Сообщение: Re: Feature Request: pg_replication_master()