Re: pg_migrator issue with contrib - Mailing list pgsql-hackers
From | Bruce Momjian |
---|---|
Subject | Re: pg_migrator issue with contrib |
Date | |
Msg-id | 200906082133.n58LXXc26014@momjian.us Whole thread Raw |
In response to | Re: pg_migrator issue with contrib (Tom Lane <tgl@sss.pgh.pa.us>) |
List | pgsql-hackers |
Tom Lane wrote: > Bruce Momjian <bruce@momjian.us> writes: > > Tom Lane wrote: > >> I've spent some time thinking about possible workarounds for this, and > >> not really come up with any. The only feasible thing I can think of > >> to do is teach pg_migrator to refuse to migrate if (a) the old DB > >> contains contrib/isn, and (b) the new DB has FLOAT8PASSYVAL (which > >> can be checked in pg_control). One question here is how you decide > >> if the old DB contains contrib/isn. I don't think looking for the > >> type name per se is a hot idea. The best plan that has come to mind > >> is to look through pg_proc to see if there are any C-language functions > >> that reference "$libdir/isn". > > > Sure, pg_migrator is good at checking. Please confirm you want this > > added to pg_migrator. > > Yeah, I'd suggest it. Even if we later come up with a workaround for > contrib/isn, you're going to want to have the infrastructure in place > for this type of check, because there will surely be cases that need it. > > Note that I think the FLOAT8PASSYVAL check is a must. There is no > reason to forbid migrating isn on 32-bit machines, for example. Done, with patch attached, and pg_migrator beta6 released. -- Bruce Momjian <bruce@momjian.us> http://momjian.us EnterpriseDB http://enterprisedb.com + If your life is a hard drive, Christ can be your backup. + ? tools ? log ? src/pg_migrator Index: src/controldata.c =================================================================== RCS file: /cvsroot/pg-migrator/pg_migrator/src/controldata.c,v retrieving revision 1.14 diff -c -r1.14 controldata.c *** src/controldata.c 13 May 2009 15:19:16 -0000 1.14 --- src/controldata.c 8 Jun 2009 21:29:31 -0000 *************** *** 23,29 **** */ void get_control_data(migratorContext *ctx, const char *bindir, ! const char *datadir, ControlData *ctrl) { char cmd[MAXPGPATH]; char bufin[MAX_STRING]; --- 23,30 ---- */ void get_control_data(migratorContext *ctx, const char *bindir, ! const char *datadir, ControlData *ctrl, ! const uint32 pg_version) { char cmd[MAXPGPATH]; char bufin[MAX_STRING]; *************** *** 43,48 **** --- 44,50 ---- bool got_index = false; bool got_toast = false; bool got_date_is_int = false; + bool got_float8_pass_by_value = false; char *lang = NULL; /* Because we test the pg_resetxlog output strings, it has to be in English. */ *************** *** 65,71 **** /* Only pre-8.4 has these so if they are not set below we will check later */ ctrl->lc_collate = NULL; ctrl->lc_ctype = NULL; ! /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { --- 67,80 ---- /* Only pre-8.4 has these so if they are not set below we will check later */ ctrl->lc_collate = NULL; ctrl->lc_ctype = NULL; ! ! /* Not in pre-8.4 */ ! if (pg_version < 80400) ! { ! ctrl->float8_pass_by_value = false; ! got_float8_pass_by_value = true; ! } ! /* we have the result of cmd in "output". so parse it line by line now */ while (fgets(bufin, sizeof(bufin), output)) { *************** *** 249,254 **** --- 258,275 ---- ctrl->date_is_int = strstr(p, "64-bit integers") != NULL; got_date_is_int = true; } + else if ((p = strstr(bufin, "Float8 argument passing:")) != NULL) + { + p = strchr(p, ':'); + + if (p == NULL || strlen(p) <= 1) + pg_log(ctx, PG_FATAL, "%d: pg_resetxlog problem\n", __LINE__); + + p++; /* removing ':' char */ + /* used later for /contrib check */ + ctrl->float8_pass_by_value = strstr(p, "by value") != NULL; + got_float8_pass_by_value = true; + } /* In pre-8.4 only */ else if ((p = strstr(bufin, "LC_COLLATE:")) != NULL) { *************** *** 305,311 **** if (!got_xid || !got_oid || !got_log_id || !got_log_seg || !got_tli || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || ! !got_date_is_int) { pg_log(ctx, PG_REPORT, "Some required control information is missing; cannot find:\n"); --- 326,332 ---- if (!got_xid || !got_oid || !got_log_id || !got_log_seg || !got_tli || !got_align || !got_blocksz || !got_largesz || !got_walsz || !got_walseg || !got_ident || !got_index || !got_toast || ! !got_date_is_int || !got_float8_pass_by_value) { pg_log(ctx, PG_REPORT, "Some required control information is missing; cannot find:\n"); *************** *** 352,357 **** --- 373,382 ---- if (!got_date_is_int) pg_log(ctx, PG_REPORT, " dates/times are integers?\n"); + /* value added in Postgres 8.4 */ + if (!got_float8_pass_by_value) + pg_log(ctx, PG_REPORT, " float8 argument passing method\n"); + pg_log(ctx, PG_FATAL, "Unable to continue without required control information, terminating\n"); } Index: src/pg_migrator.c =================================================================== RCS file: /cvsroot/pg-migrator/pg_migrator/src/pg_migrator.c,v retrieving revision 1.42 diff -c -r1.42 pg_migrator.c *** src/pg_migrator.c 4 Jun 2009 22:01:55 -0000 1.42 --- src/pg_migrator.c 8 Jun 2009 21:29:31 -0000 *************** *** 71,76 **** --- 71,77 ---- { v8_3_check_for_name_data_type_usage(&ctx, CLUSTER_OLD); v8_3_check_for_tsquery_usage(&ctx, CLUSTER_OLD); + v8_3_check_for_isn_and_int8_passing_mismatch(&ctx, CLUSTER_OLD); if (ctx.check) { v8_3_rebuild_tsvector_tables(&ctx, true, CLUSTER_OLD); *************** *** 560,568 **** /* get/check pg_control data of servers */ get_control_data(ctx, ctx->old.bindir, ctx->old.pgdata, ! &ctx->old.controldata); get_control_data(ctx, ctx->new.bindir, ctx->new.pgdata, ! &ctx->new.controldata); check_control_data(ctx, &ctx->old.controldata, &ctx->new.controldata); } --- 561,569 ---- /* get/check pg_control data of servers */ get_control_data(ctx, ctx->old.bindir, ctx->old.pgdata, ! &ctx->old.controldata, ctx->old.pg_version); get_control_data(ctx, ctx->new.bindir, ctx->new.pgdata, ! &ctx->new.controldata, ctx->new.pg_version); check_control_data(ctx, &ctx->old.controldata, &ctx->new.controldata); } Index: src/pg_migrator.h =================================================================== RCS file: /cvsroot/pg-migrator/pg_migrator/src/pg_migrator.h,v retrieving revision 1.51 diff -c -r1.51 pg_migrator.h *** src/pg_migrator.h 8 Jun 2009 18:33:32 -0000 1.51 --- src/pg_migrator.h 8 Jun 2009 21:29:31 -0000 *************** *** 145,150 **** --- 145,151 ---- uint32 index; uint32 toast; bool date_is_int; + bool float8_pass_by_value; char *lc_collate; char *lc_ctype; char *encoding; *************** *** 244,250 **** /* controldata.c */ void get_control_data(migratorContext *ctx, const char *bindir, ! const char *datadir, ControlData *ctrl); void check_control_data(migratorContext *ctx, ControlData *oldctrl, ControlData *newctrl); void set_locale_and_encoding(migratorContext *ctx, Cluster whichCluster); --- 245,252 ---- /* controldata.c */ void get_control_data(migratorContext *ctx, const char *bindir, ! const char *datadir, ControlData *ctrl, ! const uint32 pg_version); void check_control_data(migratorContext *ctx, ControlData *oldctrl, ControlData *newctrl); void set_locale_and_encoding(migratorContext *ctx, Cluster whichCluster); *************** *** 375,380 **** --- 377,384 ---- Cluster whichCluster); void v8_3_check_for_tsquery_usage(migratorContext *ctx, Cluster whichCluster); + void v8_3_check_for_isn_and_int8_passing_mismatch(migratorContext *ctx, + Cluster whichCluster); void v8_3_rebuild_tsvector_tables(migratorContext *ctx, bool check_mode, Cluster whichCluster); void v8_3_invalidate_hash_gin_indexes(migratorContext *ctx, Index: src/version.c =================================================================== RCS file: /cvsroot/pg-migrator/pg_migrator/src/version.c,v retrieving revision 1.17 diff -c -r1.17 version.c *** src/version.c 31 May 2009 20:25:48 -0000 1.17 --- src/version.c 8 Jun 2009 21:29:31 -0000 *************** *** 89,95 **** "| Your installation uses the \"name\" data type in user tables.\n" "| This data type changed its internal alignment between your old and\n" "| new clusters so this cluster cannot currently be upgraded.\n" ! "| You can remove the problem tables and restart this program.\n" "| Simply dropping the offending columns will not work.\n" "| A list of the problem columns is in the file\n" "| \"%s\".\n\n", output_path); --- 89,95 ---- "| Your installation uses the \"name\" data type in user tables.\n" "| This data type changed its internal alignment between your old and\n" "| new clusters so this cluster cannot currently be upgraded.\n" ! "| You can remove the problem tables and restart the migration.\n" "| Simply dropping the offending columns will not work.\n" "| A list of the problem columns is in the file\n" "| \"%s\".\n\n", output_path); *************** *** 178,184 **** "| Your installation uses the \"tsquery\" data type.\n" "| This data type added a new internal field between your old and\n" "| new clusters so this cluster cannot currently be upgraded.\n" ! "| You can remove the problem columns and restart this program.\n" "| A list of the problem columns is in the file\n" "| \"%s\".\n\n", output_path); } --- 178,184 ---- "| Your installation uses the \"tsquery\" data type.\n" "| This data type added a new internal field between your old and\n" "| new clusters so this cluster cannot currently be upgraded.\n" ! "| You can remove the problem columns and restart the migration.\n" "| A list of the problem columns is in the file\n" "| \"%s\".\n\n", output_path); } *************** *** 188,193 **** --- 188,286 ---- /* + * v8_3_check_for_isn_and_int8_passing_mismatch() + * + * /contrib/isn relies on data type bigint, and the CREATE TYPE + * PASSEDBYVALUE setting might not match in the old and new servers, + * so the new shared object file would work unreliably. Passing int8 + * by value is new in Postgres 8.4. + */ + void + v8_3_check_for_isn_and_int8_passing_mismatch(migratorContext *ctx, Cluster whichCluster) + { + ClusterInfo *active_cluster = (whichCluster == CLUSTER_OLD) ? + &ctx->old : &ctx->new; + int dbnum; + FILE *script = NULL; + bool found = false; + char output_path[MAXPGPATH]; + + prep_status(ctx, "Checking for /contrib/isn with bigint-passing mismatch"); + + if (ctx->old.controldata.float8_pass_by_value == + ctx->new.controldata.float8_pass_by_value) + { + /* no mismatch */ + check_ok(ctx); + return; + } + + snprintf(output_path, sizeof(output_path), "%s/contrib_isn_and_int8_pass_by_value.txt", + ctx->home_dir); + + for (dbnum = 0; dbnum < active_cluster->dbarr.ndbs; dbnum++) + { + PGresult *res; + bool db_used = false; + int ntups; + int rowno; + int i_nspname, i_proname; + DbInfo *active_db = &active_cluster->dbarr.dbs[dbnum]; + PGconn *conn = connectToServer(ctx, active_db->db_name, whichCluster); + + /* Find any user-defined tsquery columns */ + res = executeQueryOrDie(ctx, conn, + "SELECT n.nspname, p.proname " + "FROM pg_catalog.pg_proc p, " + " pg_catalog.pg_namespace n " + "WHERE p.pronamespace = n.oid AND " + " p.probin = '$libdir/isn' AND " + " n.nspname != 'pg_catalog' AND " + " n.nspname != 'information_schema'"); + + ntups = PQntuples(res); + i_nspname = PQfnumber(res, "nspname"); + i_proname = PQfnumber(res, "proname"); + for (rowno = 0; rowno < ntups; rowno++) + { + found = true; + if (script == NULL && (script = fopen(output_path, "w")) == NULL) + pg_log(ctx, PG_FATAL, "Could not create necessary file: %s\n", output_path); + if (!db_used) + { + fprintf(script, "Database: %s\n", active_db->db_name); + db_used = true; + } + fprintf(script, " %s.%s\n", + PQgetvalue(res, rowno, i_nspname), + PQgetvalue(res, rowno, i_proname)); + } + + PQclear(res); + + PQfinish(conn); + } + + if (found) + { + fclose(script); + pg_log(ctx, PG_REPORT, "fatal\n"); + pg_log(ctx, PG_FATAL, + "| Your installation uses \"/contrib/isn\" functions\n" + "| which rely on the bigint data type. Your old and new\n" + "| clusters pass bigint values differently so this cluster\n" + "| cannot currently be upgraded. You can manually migrate\n" + "| data that use \"/contrib/isn\" facilities and remove\n" + "| \"/contrib/isn\" from the old cluster and restart the\n" + "| migration. A list of the problem functions is in the\n" + "| file \"%s\".\n\n", output_path); + } + else + check_ok(ctx); + } + + + /* * v8_3_rebuild_tsvector_tables() * * 8.3 sorts lexemes by its length and if lengths are the same then it uses
pgsql-hackers by date: