diff options
author | Heikki Linnakangas | 2009-02-23 07:53:26 +0000 |
---|---|---|
committer | Heikki Linnakangas | 2009-02-23 07:53:26 +0000 |
commit | 30f96acd1a4ca704100c7b836a58e9ef3dc17b95 (patch) | |
tree | f4011ddafe610f4a9898962ab4785093629607b5 | |
parent | 4fd212090fd1bbdb5631001f9e96564f8fffe9fd (diff) | |
parent | e05ec7efd152c05691510e72c19b3326710e61f9 (diff) |
Merge commit 'origin/master' into recoveryinfra
Conflicts:
src/backend/access/transam/xlog.c
src/backend/postmaster/postmaster.c
src/include/storage/pmsignal.h
25 files changed, 352 insertions, 151 deletions
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 5cc395efa2..223911c7c6 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -3361,11 +3361,19 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv; <listitem> <para> Enables tracking of function call counts and time used. Specify - <literal>pl</literal> to count only procedural language functions, + <literal>pl</literal> to track only procedural-language functions, <literal>all</literal> to also track SQL and C language functions. - The default is <literal>none</literal>. - Only superusers can change this setting. + The default is <literal>none</literal>, which disables function + statistics tracking. Only superusers can change this setting. </para> + + <note> + <para> + SQL-language functions that are simple enough to be <quote>inlined</> + into the calling query will not be tracked, regardless of this + setting. + </para> + </note> </listitem> </varlistentry> diff --git a/doc/src/sgml/ref/vacuumdb.sgml b/doc/src/sgml/ref/vacuumdb.sgml index 6a00946827..bd44f71c25 100644 --- a/doc/src/sgml/ref/vacuumdb.sgml +++ b/doc/src/sgml/ref/vacuumdb.sgml @@ -26,6 +26,7 @@ PostgreSQL documentation <group><arg>--full</arg><arg>-f</arg></group> <group><arg>--verbose</arg><arg>-v</arg></group> <group><arg>--analyze</arg><arg>-z</arg></group> + <group><arg>--freeze</arg><arg>-F</arg></group> <arg>--table | -t <replaceable>table</replaceable> <arg>( <replaceable class="parameter">column</replaceable> [,...] )</arg> </arg> @@ -37,6 +38,7 @@ PostgreSQL documentation <group><arg>--full</arg><arg>-f</arg></group> <group><arg>--verbose</arg><arg>-v</arg></group> <group><arg>--analyze</arg><arg>-z</arg></group> + <group><arg>--freeze</arg><arg>-F</arg></group> </cmdsynopsis> </refsynopsisdiv> @@ -161,6 +163,16 @@ PostgreSQL documentation </para> </listitem> </varlistentry> + + <varlistentry> + <term><option>-F</option></term> + <term><option>--freeze</option></term> + <listitem> + <para> + Aggressively <quote>freeze</quote> tuples. + </para> + </listitem> + </varlistentry> </variablelist> </para> diff --git a/src/Makefile.global.in b/src/Makefile.global.in index ff27dd903d..829ce7218d 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -468,6 +468,9 @@ TAS = @TAS@ # # Global targets and rules +%.i: %.c + $(CPP) $(CPPFLAGS) -o $@ $< + %.gz: % $(GZIP) -f --best $< diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 747379f61e..bc8372ce3a 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -2818,7 +2818,7 @@ RestoreArchivedFile(char *path, const char *xlogfname, * On SIGTERM, assume we have received a fast shutdown request, and exit * cleanly. It's pure chance whether we receive the SIGTERM first, or the * child process. If we receive it first, the signal handler will call - * proc_exit(1), otherwise we do it here. If we or the child process + * proc_exit, otherwise we do it here. If we or the child process * received SIGTERM for any other reason than a fast shutdown request, * postmaster will perform an immediate shutdown when it sees us exiting * unexpectedly. diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 1f1309771f..fdf322a386 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -424,9 +424,27 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, create_unique_path(root, rel2, rel2->cheapest_total_path, sjinfo) != NULL) { - /* + /*---------- * For a semijoin, we can join the RHS to anything else by * unique-ifying the RHS (if the RHS can be unique-ified). + * We will only get here if we have the full RHS but less + * than min_lefthand on the LHS. + * + * The reason to consider such a join path is exemplified by + * SELECT ... FROM a,b WHERE (a.x,b.y) IN (SELECT c1,c2 FROM c) + * If we insist on doing this as a semijoin we will first have + * to form the cartesian product of A*B. But if we unique-ify + * C then the semijoin becomes a plain innerjoin and we can join + * in any order, eg C to A and then to B. When C is much smaller + * than A and B this can be a huge win. So we allow C to be + * joined to just A or just B here, and then make_join_rel has + * to handle the case properly. + * + * Note that actually we'll allow unique-ified C to be joined to + * some other relation D here, too. That is legal, if usually not + * very sane, and this routine is only concerned with legality not + * with whether the join is good strategy. + *---------- */ if (match_sjinfo) return false; /* invalid join path */ @@ -648,8 +666,10 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2) break; case JOIN_SEMI: /* - * Do these steps only if we actually have a regular semijoin, - * as opposed to a case where we should unique-ify the RHS. + * We might have a normal semijoin, or a case where we don't have + * enough rels to do the semijoin but can unique-ify the RHS and + * then do an innerjoin (see comments in join_is_legal). In the + * latter case we can't apply JOIN_SEMI joining. */ if (bms_is_subset(sjinfo->min_lefthand, rel1->relids) && bms_is_subset(sjinfo->min_righthand, rel2->relids)) diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index b4dc2ed62f..1e126a5a12 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -725,6 +725,9 @@ make_outerjoininfo(PlannerInfo *root, * 'qualscope' identifies what level of JOIN the qual came from syntactically. * 'ojscope' is needed if we decide to force the qual up to the outer-join * level, which will be ojscope not necessarily qualscope. + * + * At the time this is called, root->join_info_list must contain entries for + * all and only those special joins that are syntactically below this qual. */ static void distribute_qual_to_rels(PlannerInfo *root, Node *clause, @@ -1209,7 +1212,6 @@ check_redundant_nullability_qual(PlannerInfo *root, Node *clause) { Var *forced_null_var; Index forced_null_rel; - SpecialJoinInfo *match_sjinfo = NULL; ListCell *lc; /* Check for IS NULL, and identify the Var forced to NULL */ @@ -1219,47 +1221,19 @@ check_redundant_nullability_qual(PlannerInfo *root, Node *clause) forced_null_rel = forced_null_var->varno; /* - * Search to see if there's a matching antijoin that is not masked by - * a higher outer join. Because we have to scan the join info bottom-up, - * we have to continue looking after finding a match to check for masking - * joins. This logic should agree with reduce_outer_joins's code - * to detect antijoins on the basis of IS NULL clauses. (It's tempting - * to consider adding some data structures to avoid redundant work, - * but in practice this code shouldn't get executed often enough to - * make it worth the trouble.) + * If the Var comes from the nullable side of a lower antijoin, the + * IS NULL condition is necessarily true. */ foreach(lc, root->join_info_list) { SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc); - /* Check for match ... */ if (sjinfo->jointype == JOIN_ANTI && bms_is_member(forced_null_rel, sjinfo->syn_righthand)) - { - List *nonnullable_vars; - - nonnullable_vars = find_nonnullable_vars((Node *) sjinfo->join_quals); - if (list_member(nonnullable_vars, forced_null_var)) - { - match_sjinfo = sjinfo; - continue; - } - } - /* - * Else, if we had a lower match, check to see if the target var is - * from the nullable side of this OJ. If so, this OJ masks the - * lower one and we can no longer consider the IS NULL as redundant - * with the lower antijoin. - */ - if (!match_sjinfo) - continue; - if (bms_is_member(forced_null_rel, sjinfo->syn_righthand) || - (sjinfo->jointype == JOIN_FULL && - bms_is_member(forced_null_rel, sjinfo->syn_lefthand))) - match_sjinfo = NULL; + return true; } - return (match_sjinfo != NULL); + return false; } /* diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index bd3601c608..19b570d9c4 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -576,9 +576,7 @@ float4um(PG_FUNCTION_ARGS) float4 arg1 = PG_GETARG_FLOAT4(0); float4 result; - result = ((arg1 != 0) ? -(arg1) : arg1); - - CHECKFLOATVAL(result, isinf(arg1), true); + result = -arg1; PG_RETURN_FLOAT4(result); } @@ -645,9 +643,7 @@ float8um(PG_FUNCTION_ARGS) float8 arg1 = PG_GETARG_FLOAT8(0); float8 result; - result = ((arg1 != 0) ? -(arg1) : arg1); - - CHECKFLOATVAL(result, isinf(arg1), true); + result = -arg1; PG_RETURN_FLOAT8(result); } @@ -703,16 +699,16 @@ float8smaller(PG_FUNCTION_ARGS) Datum float4pl(PG_FUNCTION_ARGS) { - float8 arg1 = PG_GETARG_FLOAT4(0); - float8 arg2 = PG_GETARG_FLOAT4(1); + float4 arg1 = PG_GETARG_FLOAT4(0); + float4 arg2 = PG_GETARG_FLOAT4(1); float4 result; result = arg1 + arg2; /* * There isn't any way to check for underflow of addition/subtraction - * because numbers near the underflow value have been already been to the - * point where we can't detect the that the two values were originally + * because numbers near the underflow value have already been rounded to + * the point where we can't detect that the two values were originally * different, e.g. on x86, '1e-45'::float4 == '2e-45'::float4 == * 1.4013e-45. */ @@ -757,7 +753,6 @@ float4div(PG_FUNCTION_ARGS) (errcode(ERRCODE_DIVISION_BY_ZERO), errmsg("division by zero"))); - /* Do division in float8, then check for overflow */ result = arg1 / arg2; CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2), arg1 == 0); @@ -2693,7 +2688,7 @@ width_bucket_float8(PG_FUNCTION_ARGS) errmsg("operand, lower bound and upper bound cannot be NaN"))); /* Note that we allow "operand" to be infinite */ - if (is_infinite(bound1) || is_infinite(bound2)) + if (isinf(bound1) || isinf(bound2)) ereport(ERROR, (errcode(ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION), errmsg("lower and upper bounds must be finite"))); diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 6cf171d455..5eda359a3e 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -487,6 +487,7 @@ restore_toc_entry(ArchiveHandle *AH, TocEntry *te, { ahlog(AH, 1, "connecting to new database \"%s\"\n", te->tag); _reconnectToDB(AH, te->tag); + ropt->dbname = strdup(te->tag); } } diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 43843c97ed..32a8ae6c2f 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -1585,6 +1585,7 @@ dumpDatabase(Archive *AH) i_encoding, i_collate, i_ctype, + i_frozenxid, i_tablespace; CatalogId dbCatId; DumpId dbDumpId; @@ -1594,6 +1595,7 @@ dumpDatabase(Archive *AH) *collate, *ctype, *tablespace; + uint32 frozenxid; datname = PQdb(g_conn); @@ -1609,7 +1611,7 @@ dumpDatabase(Archive *AH) appendPQExpBuffer(dbQry, "SELECT tableoid, oid, " "(%s datdba) AS dba, " "pg_encoding_to_char(encoding) AS encoding, " - "datcollate, datctype, " + "datcollate, datctype, datfrozenxid, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " "shobj_description(oid, 'pg_database') AS description " @@ -1623,7 +1625,7 @@ dumpDatabase(Archive *AH) appendPQExpBuffer(dbQry, "SELECT tableoid, oid, " "(%s datdba) AS dba, " "pg_encoding_to_char(encoding) AS encoding, " - "NULL AS datcollate, NULL AS datctype, " + "NULL AS datcollate, NULL AS datctype, datfrozenxid, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " "shobj_description(oid, 'pg_database') AS description " @@ -1637,7 +1639,7 @@ dumpDatabase(Archive *AH) appendPQExpBuffer(dbQry, "SELECT tableoid, oid, " "(%s datdba) AS dba, " "pg_encoding_to_char(encoding) AS encoding, " - "NULL AS datcollate, NULL AS datctype, " + "NULL AS datcollate, NULL AS datctype, datfrozenxid, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace " "FROM pg_database " "WHERE datname = ", @@ -1650,6 +1652,7 @@ dumpDatabase(Archive *AH) "(%s datdba) AS dba, " "pg_encoding_to_char(encoding) AS encoding, " "NULL AS datcollate, NULL AS datctype, " + "0 AS datfrozenxid, " "NULL AS tablespace " "FROM pg_database " "WHERE datname = ", @@ -1664,6 +1667,7 @@ dumpDatabase(Archive *AH) "(%s datdba) AS dba, " "pg_encoding_to_char(encoding) AS encoding, " "NULL AS datcollate, NULL AS datctype, " + "0 AS datfrozenxid, " "NULL AS tablespace " "FROM pg_database " "WHERE datname = ", @@ -1696,6 +1700,7 @@ dumpDatabase(Archive *AH) i_encoding = PQfnumber(res, "encoding"); i_collate = PQfnumber(res, "datcollate"); i_ctype = PQfnumber(res, "datctype"); + i_frozenxid = PQfnumber(res, "datfrozenxid"); i_tablespace = PQfnumber(res, "tablespace"); dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid)); @@ -1704,6 +1709,7 @@ dumpDatabase(Archive *AH) encoding = PQgetvalue(res, 0, i_encoding); collate = PQgetvalue(res, 0, i_collate); ctype = PQgetvalue(res, 0, i_ctype); + frozenxid = atooid(PQgetvalue(res, 0, i_frozenxid)); tablespace = PQgetvalue(res, 0, i_tablespace); appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0", @@ -1728,6 +1734,15 @@ dumpDatabase(Archive *AH) fmtId(tablespace)); appendPQExpBuffer(creaQry, ";\n"); + if (binary_upgrade) + { + appendPQExpBuffer(creaQry, "\n-- For binary upgrade, set datfrozenxid.\n"); + appendPQExpBuffer(creaQry, "UPDATE pg_database\n" + "SET datfrozenxid = '%u'\n" + "WHERE datname = '%s';\n", + frozenxid, datname); + } + appendPQExpBuffer(delQry, "DROP DATABASE %s;\n", fmtId(datname)); @@ -3114,6 +3129,7 @@ getTables(int *numTables) int i_relhasindex; int i_relhasrules; int i_relhasoids; + int i_relfrozenxid; int i_owning_tab; int i_owning_col; int i_reltablespace; @@ -3155,6 +3171,7 @@ getTables(int *numTables) "(%s c.relowner) AS rolname, " "c.relchecks, c.relhastriggers, " "c.relhasindex, c.relhasrules, c.relhasoids, " + "c.relfrozenxid, " "d.refobjid AS owning_tab, " "d.refobjsubid AS owning_col, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " @@ -3186,6 +3203,7 @@ getTables(int *numTables) "(%s relowner) AS rolname, " "relchecks, (reltriggers <> 0) AS relhastriggers, " "relhasindex, relhasrules, relhasoids, " + "relfrozenxid, " "d.refobjid AS owning_tab, " "d.refobjsubid AS owning_col, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " @@ -3216,6 +3234,7 @@ getTables(int *numTables) "(%s relowner) AS rolname, " "relchecks, (reltriggers <> 0) AS relhastriggers, " "relhasindex, relhasrules, relhasoids, " + "0 AS relfrozenxid, " "d.refobjid AS owning_tab, " "d.refobjsubid AS owning_col, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " @@ -3246,6 +3265,7 @@ getTables(int *numTables) "(%s relowner) AS rolname, " "relchecks, (reltriggers <> 0) AS relhastriggers, " "relhasindex, relhasrules, relhasoids, " + "0 AS relfrozenxid, " "d.refobjid AS owning_tab, " "d.refobjsubid AS owning_col, " "NULL AS reltablespace, " @@ -3272,6 +3292,7 @@ getTables(int *numTables) "(%s relowner) AS rolname, " "relchecks, (reltriggers <> 0) AS relhastriggers, " "relhasindex, relhasrules, relhasoids, " + "0 AS relfrozenxid, " "NULL::oid AS owning_tab, " "NULL::int4 AS owning_col, " "NULL AS reltablespace, " @@ -3293,6 +3314,7 @@ getTables(int *numTables) "relchecks, (reltriggers <> 0) AS relhastriggers, " "relhasindex, relhasrules, " "'t'::bool AS relhasoids, " + "0 AS relfrozenxid, " "NULL::oid AS owning_tab, " "NULL::int4 AS owning_col, " "NULL AS reltablespace, " @@ -3324,6 +3346,7 @@ getTables(int *numTables) "relchecks, (reltriggers <> 0) AS relhastriggers, " "relhasindex, relhasrules, " "'t'::bool AS relhasoids, " + "0 as relfrozenxid, " "NULL::oid AS owning_tab, " "NULL::int4 AS owning_col, " "NULL AS reltablespace, " @@ -3367,6 +3390,7 @@ getTables(int *numTables) i_relhasindex = PQfnumber(res, "relhasindex"); i_relhasrules = PQfnumber(res, "relhasrules"); i_relhasoids = PQfnumber(res, "relhasoids"); + i_relfrozenxid = PQfnumber(res, "relfrozenxid"); i_owning_tab = PQfnumber(res, "owning_tab"); i_owning_col = PQfnumber(res, "owning_col"); i_reltablespace = PQfnumber(res, "reltablespace"); @@ -3404,6 +3428,7 @@ getTables(int *numTables) tblinfo[i].hasrules = (strcmp(PQgetvalue(res, i, i_relhasrules), "t") == 0); tblinfo[i].hastriggers = (strcmp(PQgetvalue(res, i, i_relhastriggers), "t") == 0); tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0); + tblinfo[i].frozenxid = atooid(PQgetvalue(res, i, i_relfrozenxid)); tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks)); if (PQgetisnull(res, i, i_owning_tab)) { @@ -9860,6 +9885,15 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) tbinfo->dobj.name); } } + appendPQExpBuffer(q, "\n-- For binary upgrade, set relfrozenxid.\n"); + appendPQExpBuffer(q, "UPDATE pg_class\n" + "SET relfrozenxid = '%u'\n" + "WHERE relname = '%s'\n" + " AND relnamespace = " + "(SELECT oid FROM pg_namespace " + "WHERE nspname = CURRENT_SCHEMA);\n", + tbinfo->frozenxid, + tbinfo->dobj.name); } /* Loop dumping statistics and storage statements */ diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 8869a5146a..8949f01482 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -226,6 +226,7 @@ typedef struct _tableInfo bool hasrules; /* does it have any rules? */ bool hastriggers; /* does it have any triggers? */ bool hasoids; /* does it have OIDs? */ + uint32 frozenxid; /* for restore frozen xid */ int ncheck; /* # of CHECK expressions */ /* these two are set only if table is a sequence owned by a column: */ Oid owning_tab; /* OID of table owning sequence */ diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 55d15e9e18..2255a6716b 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -27,7 +27,7 @@ int optreset; #endif #include "dumputils.h" - +#include "pg_backup.h" /* version string we expect back from pg_dump */ #define PGDUMP_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n" @@ -71,6 +71,8 @@ static int server_version; static FILE *OPF; static char *filename = NULL; +static int binary_upgrade = 0; + int main(int argc, char *argv[]) { @@ -90,7 +92,6 @@ main(int argc, char *argv[]) const char *std_strings; int c, ret; - int binary_upgrade = 0; struct option long_options[] = { {"binary-upgrade", no_argument, &binary_upgrade, 1}, /* not documented */ @@ -937,7 +938,7 @@ dumpCreateDB(PGconn *conn) "SELECT datname, " "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), " "pg_encoding_to_char(d.encoding), " - "datcollate, datctype, " + "datcollate, datctype, datfrozenxid, " "datistemplate, datacl, datconnlimit, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) " @@ -947,7 +948,7 @@ dumpCreateDB(PGconn *conn) "SELECT datname, " "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), " "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, " + "null::text AS datcollate, null::text AS datctype, datfrozenxid, " "datistemplate, datacl, datconnlimit, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) " @@ -957,7 +958,7 @@ dumpCreateDB(PGconn *conn) "SELECT datname, " "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, " + "null::text AS datcollate, null::text AS datctype, datfrozenxid, " "datistemplate, datacl, -1 as datconnlimit, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) " @@ -967,7 +968,7 @@ dumpCreateDB(PGconn *conn) "SELECT datname, " "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, " + "null::text AS datcollate, null::text AS datctype, datfrozenxid, " "datistemplate, datacl, -1 as datconnlimit, " "'pg_default' AS dattablespace " "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) " @@ -979,7 +980,7 @@ dumpCreateDB(PGconn *conn) "(select usename from pg_shadow where usesysid=datdba), " "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, " + "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid" "datistemplate, '' as datacl, -1 as datconnlimit, " "'pg_default' AS dattablespace " "FROM pg_database d " @@ -994,7 +995,7 @@ dumpCreateDB(PGconn *conn) "SELECT datname, " "(select usename from pg_shadow where usesysid=datdba), " "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, " + "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid" "'f' as datistemplate, " "'' as datacl, -1 as datconnlimit, " "'pg_default' AS dattablespace " @@ -1009,10 +1010,11 @@ dumpCreateDB(PGconn *conn) char *dbencoding = PQgetvalue(res, i, 2); char *dbcollate = PQgetvalue(res, i, 3); char *dbctype = PQgetvalue(res, i, 4); - char *dbistemplate = PQgetvalue(res, i, 5); - char *dbacl = PQgetvalue(res, i, 6); - char *dbconnlimit = PQgetvalue(res, i, 7); - char *dbtablespace = PQgetvalue(res, i, 8); + uint32 dbfrozenxid = atooid(PQgetvalue(res, i, 5)); + char *dbistemplate = PQgetvalue(res, i, 6); + char *dbacl = PQgetvalue(res, i, 7); + char *dbconnlimit = PQgetvalue(res, i, 8); + char *dbtablespace = PQgetvalue(res, i, 9); char *fdbname; fdbname = strdup(fmtId(dbname)); @@ -1076,6 +1078,15 @@ dumpCreateDB(PGconn *conn) appendStringLiteralConn(buf, dbname, conn); appendPQExpBuffer(buf, ";\n"); } + + if (binary_upgrade) + { + appendPQExpBuffer(buf, "\n-- For binary upgrade, set datfrozenxid.\n"); + appendPQExpBuffer(buf, "UPDATE pg_database\n" + "SET datfrozenxid = '%u'\n" + "WHERE datname = '%s';\n", + dbfrozenxid, fdbname); + } } if (!skip_acls && diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c index c0f78a1e05..55f1f415dd 100644 --- a/src/bin/scripts/vacuumdb.c +++ b/src/bin/scripts/vacuumdb.c @@ -15,11 +15,11 @@ static void vacuum_one_database(const char *dbname, bool full, bool verbose, bool analyze, - const char *table, + bool freeze, const char *table, const char *host, const char *port, const char *username, bool password, const char *progname, bool echo); -static void vacuum_all_databases(bool full, bool verbose, bool analyze, +static void vacuum_all_databases(bool full, bool verbose, bool analyze, bool freeze, const char *host, const char *port, const char *username, bool password, const char *progname, bool echo, bool quiet); @@ -39,6 +39,7 @@ main(int argc, char *argv[]) {"quiet", no_argument, NULL, 'q'}, {"dbname", required_argument, NULL, 'd'}, {"analyze", no_argument, NULL, 'z'}, + {"freeze", no_argument, NULL, 'F'}, {"all", no_argument, NULL, 'a'}, {"table", required_argument, NULL, 't'}, {"full", no_argument, NULL, 'f'}, @@ -58,6 +59,7 @@ main(int argc, char *argv[]) bool echo = false; bool quiet = false; bool analyze = false; + bool freeze = false; bool alldb = false; char *table = NULL; bool full = false; @@ -68,7 +70,7 @@ main(int argc, char *argv[]) handle_help_version_opts(argc, argv, "vacuumdb", help); - while ((c = getopt_long(argc, argv, "h:p:U:Weqd:zat:fv", long_options, &optindex)) != -1) + while ((c = getopt_long(argc, argv, "h:p:U:Weqd:zaFt:fv", long_options, &optindex)) != -1) { switch (c) { @@ -96,6 +98,9 @@ main(int argc, char *argv[]) case 'z': analyze = true; break; + case 'F': + freeze = true; + break; case 'a': alldb = true; break; @@ -145,7 +150,7 @@ main(int argc, char *argv[]) exit(1); } - vacuum_all_databases(full, verbose, analyze, + vacuum_all_databases(full, verbose, analyze, freeze, host, port, username, password, progname, echo, quiet); } @@ -161,7 +166,7 @@ main(int argc, char *argv[]) dbname = get_user_name(progname); } - vacuum_one_database(dbname, full, verbose, analyze, table, + vacuum_one_database(dbname, full, verbose, analyze, freeze, table, host, port, username, password, progname, echo); } @@ -172,7 +177,7 @@ main(int argc, char *argv[]) static void vacuum_one_database(const char *dbname, bool full, bool verbose, bool analyze, - const char *table, + bool freeze, const char *table, const char *host, const char *port, const char *username, bool password, const char *progname, bool echo) @@ -190,6 +195,8 @@ vacuum_one_database(const char *dbname, bool full, bool verbose, bool analyze, appendPQExpBuffer(&sql, " VERBOSE"); if (analyze) appendPQExpBuffer(&sql, " ANALYZE"); + if (freeze) + appendPQExpBuffer(&sql, " FREEZE"); if (table) appendPQExpBuffer(&sql, " %s", table); appendPQExpBuffer(&sql, ";\n"); @@ -212,7 +219,7 @@ vacuum_one_database(const char *dbname, bool full, bool verbose, bool analyze, static void -vacuum_all_databases(bool full, bool verbose, bool analyze, +vacuum_all_databases(bool full, bool verbose, bool analyze, bool freeze, const char *host, const char *port, const char *username, bool password, const char *progname, bool echo, bool quiet) @@ -235,7 +242,7 @@ vacuum_all_databases(bool full, bool verbose, bool analyze, fflush(stdout); } - vacuum_one_database(dbname, full, verbose, analyze, NULL, + vacuum_one_database(dbname, full, verbose, analyze, freeze, NULL, host, port, username, password, progname, echo); } @@ -256,6 +263,7 @@ help(const char *progname) printf(_(" -t, --table='TABLE[(COLUMNS)]' vacuum specific table only\n")); printf(_(" -f, --full do full vacuuming\n")); printf(_(" -z, --analyze update optimizer hints\n")); + printf(_(" -F, --freeze freeze row transaction information\n")); printf(_(" -e, --echo show the commands being sent to the server\n")); printf(_(" -q, --quiet don't write any messages\n")); printf(_(" -v, --verbose write a lot of output\n")); diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index 7509332d59..53a5c055ad 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -138,8 +138,12 @@ typedef struct PROC_HDR /* * We set aside some extra PGPROC structures for auxiliary processes, * ie things that aren't full-fledged backends but need shmem access. + * + * Background writer, WAL writer, and autovacuum launcher run during + * normal operation. When recovery has just finished, the startup + * process can co-exist with them for a brief period before it exits. */ -#define NUM_AUXILIARY_PROCS 3 +#define NUM_AUXILIARY_PROCS 4 /* configurable options */ diff --git a/src/pl/plperl/expected/plperl.out b/src/pl/plperl/expected/plperl.out index 708723d3e5..e1b0c75108 100644 --- a/src/pl/plperl/expected/plperl.out +++ b/src/pl/plperl/expected/plperl.out @@ -121,9 +121,9 @@ CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$ ]; $$ LANGUAGE plperl; SELECT perl_set(); -ERROR: setof-composite-returning Perl function must call return_next with reference to hash +ERROR: SETOF-composite-returning PL/Perl function must call return_next with reference to hash SELECT * FROM perl_set(); -ERROR: setof-composite-returning Perl function must call return_next with reference to hash +ERROR: SETOF-composite-returning PL/Perl function must call return_next with reference to hash CREATE OR REPLACE FUNCTION perl_set() RETURNS SETOF testrowperl AS $$ return [ { f1 => 1, f2 => 'Hello', f3 => 'World' }, @@ -209,7 +209,7 @@ ERROR: a column definition list is required for functions returning "record" LINE 1: SELECT * FROM perl_record_set(); ^ SELECT * FROM perl_record_set() AS (f1 integer, f2 text, f3 text); -ERROR: setof-composite-returning Perl function must call return_next with reference to hash +ERROR: SETOF-composite-returning PL/Perl function must call return_next with reference to hash CREATE OR REPLACE FUNCTION perl_record_set() RETURNS SETOF record AS $$ return [ { f1 => 1, f2 => 'Hello', f3 => 'World' }, @@ -312,7 +312,7 @@ CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$ return 42; $$ LANGUAGE plperl; SELECT * FROM foo_bad(); -ERROR: composite-returning Perl function must return reference to hash +ERROR: composite-returning PL/Perl function must return reference to hash CREATE OR REPLACE FUNCTION foo_bad() RETURNS footype AS $$ return [ [1, 2], @@ -320,17 +320,17 @@ return [ ]; $$ LANGUAGE plperl; SELECT * FROM foo_bad(); -ERROR: composite-returning Perl function must return reference to hash +ERROR: composite-returning PL/Perl function must return reference to hash CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$ return 42; $$ LANGUAGE plperl; SELECT * FROM foo_set_bad(); -ERROR: set-returning Perl function must return reference to array or use return_next +ERROR: set-returning PL/Perl function must return reference to array or use return_next CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$ return {y => 3, z => 4}; $$ LANGUAGE plperl; SELECT * FROM foo_set_bad(); -ERROR: set-returning Perl function must return reference to array or use return_next +ERROR: set-returning PL/Perl function must return reference to array or use return_next CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$ return [ [1, 2], @@ -338,7 +338,7 @@ return [ ]; $$ LANGUAGE plperl; SELECT * FROM foo_set_bad(); -ERROR: setof-composite-returning Perl function must call return_next with reference to hash +ERROR: SETOF-composite-returning PL/Perl function must call return_next with reference to hash CREATE OR REPLACE FUNCTION foo_set_bad() RETURNS SETOF footype AS $$ return [ {y => 3, z => 4} diff --git a/src/pl/plperl/nls.mk b/src/pl/plperl/nls.mk index 0064ff8d4f..84891d2f53 100644 --- a/src/pl/plperl/nls.mk +++ b/src/pl/plperl/nls.mk @@ -1,5 +1,5 @@ # $PostgreSQL$ CATALOG_NAME := plperl AVAIL_LANGUAGES := -GETTEXT_FILES := plperl.c SPI.xs -GETTEXT_TRIGGERS:= _ errmsg errdetail errdetail_log errhint errcontext croak Perl_croak +GETTEXT_FILES := plperl.c SPI.c +GETTEXT_TRIGGERS:= errmsg errdetail errdetail_log errhint errcontext diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index 5f33ca6e47..2127a2369f 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -199,7 +199,7 @@ _PG_init(void) pg_bindtextdomain(TEXTDOMAIN); DefineCustomBoolVariable("plperl.use_strict", - gettext_noop("If true, will compile trusted and untrusted perl code in strict mode"), + gettext_noop("If true, trusted and untrusted Perl code will be compiled in strict mode."), NULL, &plperl_use_strict, false, @@ -913,7 +913,7 @@ plperl_validator(PG_FUNCTION_ARGS) proc->prorettype != VOIDOID) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("plperl functions cannot return type %s", + errmsg("PL/Perl functions cannot return type %s", format_type_be(proc->prorettype)))); } @@ -925,7 +925,7 @@ plperl_validator(PG_FUNCTION_ARGS) if (get_typtype(argtypes[i]) == TYPTYPE_PSEUDO) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("plperl functions cannot take type %s", + errmsg("PL/Perl functions cannot accept type %s", format_type_be(argtypes[i])))); } @@ -1280,7 +1280,7 @@ plperl_func_handler(PG_FUNCTION_ARGS) { ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("set-returning Perl function must return " + errmsg("set-returning PL/Perl function must return " "reference to array or use return_next"))); } @@ -1313,7 +1313,7 @@ plperl_func_handler(PG_FUNCTION_ARGS) { ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("composite-returning Perl function " + errmsg("composite-returning PL/Perl function " "must return reference to hash"))); } @@ -1438,7 +1438,7 @@ plperl_trigger_handler(PG_FUNCTION_ARGS) { ereport(WARNING, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), - errmsg("ignoring modified tuple in DELETE trigger"))); + errmsg("ignoring modified row in DELETE trigger"))); trv = NULL; } } @@ -1446,8 +1446,8 @@ plperl_trigger_handler(PG_FUNCTION_ARGS) { ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), - errmsg("result of Perl trigger function must be undef, " - "\"SKIP\" or \"MODIFY\""))); + errmsg("result of PL/Perl trigger function must be undef, " + "\"SKIP\", or \"MODIFY\""))); trv = NULL; } retval = PointerGetDatum(trv); @@ -1612,7 +1612,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger) free(prodesc); ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("plperl functions cannot return type %s", + errmsg("PL/Perl functions cannot return type %s", format_type_be(procStruct->prorettype)))); } } @@ -1659,7 +1659,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger) free(prodesc); ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("plperl functions cannot take type %s", + errmsg("PL/Perl functions cannot accept type %s", format_type_be(procStruct->proargtypes.values[i])))); } @@ -1902,7 +1902,7 @@ plperl_return_next(SV *sv) !(SvOK(sv) && SvTYPE(sv) == SVt_RV && SvTYPE(SvRV(sv)) == SVt_PVHV)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("setof-composite-returning Perl function " + errmsg("SETOF-composite-returning PL/Perl function " "must call return_next with reference to hash"))); if (!current_call_data->ret_tdesc) diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y index 5599a4bd90..b8815c5dd1 100644 --- a/src/pl/plpgsql/src/gram.y +++ b/src/pl/plpgsql/src/gram.y @@ -1043,7 +1043,7 @@ for_control : if ($2.scalar && $2.row) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("cursor FOR loop must have just one target variable"))); + errmsg("cursor FOR loop must have only one target variable"))); /* create loop's private RECORD variable */ plpgsql_convert_ident($2.name, &varname, 1); @@ -1131,7 +1131,7 @@ for_control : if ($2.scalar && $2.row) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("integer FOR loop must have just one target variable"))); + errmsg("integer FOR loop must have only one target variable"))); /* create loop's private variable */ plpgsql_convert_ident($2.name, &varname, 1); @@ -1570,7 +1570,7 @@ stmt_open : K_OPEN lno cursor_variable (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error at \"%s\"", yytext), - errdetail("Expected FOR to open a reference cursor."))); + errdetail("Expected \"FOR\", to open a reference cursor."))); } tok = yylex(); @@ -1664,7 +1664,7 @@ cursor_variable : T_SCALAR plpgsql_error_lineno = plpgsql_scanner_lineno(); ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("\"%s\" must be of type cursor or refcursor", + errmsg("variable \"%s\" must be of type cursor or refcursor", ((PLpgSQL_var *) yylval.scalar)->refname))); } $$ = (PLpgSQL_var *) yylval.scalar; @@ -2094,7 +2094,7 @@ read_datatype(int tok) if (parenlevel != 0) yyerror("mismatched parentheses"); else - yyerror("incomplete datatype declaration"); + yyerror("incomplete data type declaration"); } /* Possible followers for datatype in a declaration */ if (tok == K_NOT || tok == K_ASSIGN || tok == K_DEFAULT) @@ -2119,7 +2119,7 @@ read_datatype(int tok) type_name = plpgsql_dstring_get(&ds); if (type_name[0] == '\0') - yyerror("missing datatype declaration"); + yyerror("missing data type declaration"); plpgsql_error_lineno = lno; /* in case of error in parse_datatype */ @@ -2375,11 +2375,11 @@ make_return_stmt(int lineno) break; default: - yyerror("RETURN must specify a record or row variable in function returning tuple"); + yyerror("RETURN must specify a record or row variable in function returning row"); break; } if (yylex() != ';') - yyerror("RETURN must specify a record or row variable in function returning tuple"); + yyerror("RETURN must specify a record or row variable in function returning row"); } else { @@ -2428,11 +2428,11 @@ make_return_next_stmt(int lineno) break; default: - yyerror("RETURN NEXT must specify a record or row variable in function returning tuple"); + yyerror("RETURN NEXT must specify a record or row variable in function returning row"); break; } if (yylex() != ';') - yyerror("RETURN NEXT must specify a record or row variable in function returning tuple"); + yyerror("RETURN NEXT must specify a record or row variable in function returning row"); } else new->expr = plpgsql_read_expression(';', ";"); @@ -2745,7 +2745,7 @@ check_label(const char *yytxt) plpgsql_convert_ident(yytxt, &label_name, 1); if (plpgsql_ns_lookup_label(label_name) == NULL) - yyerror("no such label"); + yyerror("label does not exist"); return label_name; } diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index 768daf98f1..9f9d30eb3f 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -415,7 +415,7 @@ do_compile(FunctionCallInfo fcinfo, argdtype->ttype != PLPGSQL_TTYPE_ROW) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("plpgsql functions cannot take type %s", + errmsg("PL/pgSQL functions cannot accept type %s", format_type_be(argtypeid)))); /* Build variable and add to datum list */ @@ -534,7 +534,7 @@ do_compile(FunctionCallInfo fcinfo, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("plpgsql functions cannot return type %s", + errmsg("PL/pgSQL functions cannot return type %s", format_type_be(rettypeid)))); } @@ -576,7 +576,7 @@ do_compile(FunctionCallInfo fcinfo, ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("trigger functions cannot have declared arguments"), - errhint("You probably want to use TG_NARGS and TG_ARGV instead."))); + errhint("The arguments of the trigger can be accessed through TG_NARGS and TG_ARGV instead."))); /* Add the record for referencing NEW */ rec = plpgsql_build_record("new", 0, true); @@ -766,7 +766,7 @@ plpgsql_compile_error_callback(void *arg) } if (plpgsql_error_funcname) - errcontext("compile of PL/pgSQL function \"%s\" near line %d", + errcontext("compilation of PL/pgSQL function \"%s\" near line %d", plpgsql_error_funcname, plpgsql_error_lineno); } diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 21e76020cc..538efc6e30 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -706,7 +706,7 @@ plpgsql_exec_trigger(PLpgSQL_function *func, { validate_tupdesc_compat(trigdata->tg_relation->rd_att, estate.rettupdesc, - "returned tuple structure does not match table of trigger event"); + "returned row structure does not match the structure of the triggering table"); /* Copy tuple to upper executor memory */ rettup = SPI_copytuple((HeapTuple) DatumGetPointer(estate.retval)); } @@ -765,24 +765,18 @@ plpgsql_exec_error_callback(void *arg) */ if (estate->err_stmt != NULL) { - /* - * translator: last %s is a phrase such as "during statement block - * local variable initialization" - */ + /* translator: last %s is a phrase such as "during statement block local variable initialization" */ errcontext("PL/pgSQL function \"%s\" line %d %s", estate->err_func->fn_name, estate->err_stmt->lineno, - gettext(estate->err_text)); + _(estate->err_text)); } else { - /* - * translator: last %s is a phrase such as "while storing call - * arguments into local variables" - */ + /* translator: last %s is a phrase such as "while storing call arguments into local variables" */ errcontext("PL/pgSQL function \"%s\" %s", estate->err_func->fn_name, - gettext(estate->err_text)); + _(estate->err_text)); } } else if (estate->err_stmt != NULL) @@ -1677,7 +1671,7 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt) if (isnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("lower bound of FOR loop cannot be NULL"))); + errmsg("lower bound of FOR loop cannot be null"))); loop_value = DatumGetInt32(value); exec_eval_cleanup(estate); @@ -1692,7 +1686,7 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt) if (isnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("upper bound of FOR loop cannot be NULL"))); + errmsg("upper bound of FOR loop cannot be null"))); end_value = DatumGetInt32(value); exec_eval_cleanup(estate); @@ -1709,7 +1703,7 @@ exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt) if (isnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("BY value of FOR loop cannot be NULL"))); + errmsg("BY value of FOR loop cannot be null"))); step_value = DatumGetInt32(value); exec_eval_cleanup(estate); if (step_value <= 0) @@ -2470,7 +2464,7 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt) if (optionisnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("RAISE statement option cannot be NULL"))); + errmsg("RAISE statement option cannot be null"))); extval = convert_value_to_string(optionvalue, optiontypeid); @@ -2916,7 +2910,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate, if (isnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("cannot EXECUTE a null querystring"))); + errmsg("query string argument of EXECUTE is null"))); /* Get the C-String representation */ querystr = convert_value_to_string(query, restype); @@ -2981,7 +2975,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate, if (*ptr == 'S' || *ptr == 's') ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("EXECUTE of SELECT ... INTO is not implemented yet"))); + errmsg("EXECUTE of SELECT ... INTO is not implemented"))); break; } @@ -3166,7 +3160,7 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt) if (isnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("cannot EXECUTE a null querystring"))); + errmsg("query string argument of EXECUTE is null"))); /* Get the C-String representation */ querystr = convert_value_to_string(queryD, restype); @@ -3300,7 +3294,7 @@ exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt) if (curvar->isnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("cursor variable \"%s\" is NULL", curvar->refname))); + errmsg("cursor variable \"%s\" is null", curvar->refname))); curname = TextDatumGetCString(curvar->value); portal = SPI_cursor_find(curname); @@ -3321,7 +3315,7 @@ exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt) if (isnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("relative or absolute cursor position is NULL"))); + errmsg("relative or absolute cursor position is null"))); exec_eval_cleanup(estate); } @@ -3396,7 +3390,7 @@ exec_stmt_close(PLpgSQL_execstate *estate, PLpgSQL_stmt_close *stmt) if (curvar->isnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("cursor variable \"%s\" is NULL", curvar->refname))); + errmsg("cursor variable \"%s\" is null", curvar->refname))); curname = TextDatumGetCString(curvar->value); portal = SPI_cursor_find(curname); @@ -3463,7 +3457,7 @@ exec_assign_value(PLpgSQL_execstate *estate, if (*isNull && var->notnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("NULL cannot be assigned to variable \"%s\" declared NOT NULL", + errmsg("null value cannot be assigned to variable \"%s\" declared NOT NULL", var->refname))); /* @@ -3720,8 +3714,8 @@ exec_assign_value(PLpgSQL_execstate *estate, if (nsubscripts >= MAXDIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("number of array dimensions exceeds the maximum allowed, %d", - MAXDIM))); + errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)", + nsubscripts, MAXDIM))); subscripts[nsubscripts++] = arrayelem->subscript; target = estate->datums[arrayelem->arrayparentno]; } while (target->dtype == PLPGSQL_DTYPE_ARRAYELEM); @@ -3757,7 +3751,7 @@ exec_assign_value(PLpgSQL_execstate *estate, if (subisnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("array subscript in assignment must not be NULL"))); + errmsg("array subscript in assignment must not be null"))); } /* Coerce source value to match array element type. */ @@ -5129,7 +5123,7 @@ static void validate_tupdesc_compat(TupleDesc expected, TupleDesc returned, const char *msg) { int i; - const char *dropped_column_type = gettext_noop("n/a (dropped column)"); + const char *dropped_column_type = gettext_noop("N/A (dropped column)"); if (!expected || !returned) ereport(ERROR, @@ -5402,7 +5396,7 @@ exec_dynquery_with_params(PLpgSQL_execstate *estate, PLpgSQL_expr *dynquery, if (isnull) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("cannot EXECUTE a null querystring"))); + errmsg("query string argument of EXECUTE is null"))); /* Get the C-String representation */ querystr = convert_value_to_string(query, restype); diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c index c91bd6b8d9..c64c22c625 100644 --- a/src/pl/plpgsql/src/pl_funcs.c +++ b/src/pl/plpgsql/src/pl_funcs.c @@ -356,7 +356,7 @@ plpgsql_ns_rename(char *oldname, char *newname) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("there is no variable \"%s\" in the current block", + errmsg("variable \"%s\" does not exist in the current block", oldname))); } @@ -412,7 +412,7 @@ plpgsql_convert_ident(const char *s, char **output, int numidents) if (*s != '"') /* should not happen if lexer checked */ ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("unterminated \" in name: %s", sstart))); + errmsg("unterminated \" in identifier: %s", sstart))); s++; *cp = '\0'; /* Truncate to NAMEDATALEN */ diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c index 9d21fbdf82..ec8c02d7a1 100644 --- a/src/pl/plpgsql/src/pl_handler.c +++ b/src/pl/plpgsql/src/pl_handler.c @@ -159,7 +159,7 @@ plpgsql_validator(PG_FUNCTION_ARGS) !IsPolymorphicType(proc->prorettype)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("plpgsql functions cannot return type %s", + errmsg("PL/pgSQL functions cannot return type %s", format_type_be(proc->prorettype)))); } @@ -174,7 +174,7 @@ plpgsql_validator(PG_FUNCTION_ARGS) if (!IsPolymorphicType(argtypes[i])) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("plpgsql functions cannot take type %s", + errmsg("PL/pgSQL functions cannot accept type %s", format_type_be(argtypes[i])))); } } diff --git a/src/pl/plpgsql/src/scan.l b/src/pl/plpgsql/src/scan.l index b5b0adb16d..99eb934dfc 100644 --- a/src/pl/plpgsql/src/scan.l +++ b/src/pl/plpgsql/src/scan.l @@ -254,7 +254,7 @@ dump { return O_DUMP; } plpgsql_error_lineno = start_lineno; ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("unterminated comment"))); + errmsg("unterminated /* comment"))); } /* ---------- @@ -293,7 +293,7 @@ dump { return O_DUMP; } plpgsql_error_lineno = start_lineno; ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("unterminated string"))); + errmsg("unterminated quoted string"))); } {dolqdelim} { diff --git a/src/test/regress/expected/numerology.out b/src/test/regress/expected/numerology.out index d404d9db68..0a2e66e919 100644 --- a/src/test/regress/expected/numerology.out +++ b/src/test/regress/expected/numerology.out @@ -92,7 +92,7 @@ SELECT f1 AS two, max(f3) AS max_float, min(f3) as min_float ORDER BY two, max_float, min_float; two | max_float | min_float -----+----------------------+----------------------- - 1 | 1.2345678901234e+200 | 0 + 1 | 1.2345678901234e+200 | -0 2 | 0 | -1.2345678901234e+200 (2 rows) @@ -104,7 +104,7 @@ SELECT f1 AS two, max(f3) AS max_float, min(f3) AS min_float ORDER BY two, max_float, min_float; two | max_float | min_float -----+----------------------+----------------------- - 1 | 1.2345678901234e+200 | 0 + 1 | 1.2345678901234e+200 | -0 2 | 0 | -1.2345678901234e+200 (2 rows) diff --git a/src/test/regress/expected/numerology_1.out b/src/test/regress/expected/numerology_1.out new file mode 100644 index 0000000000..d404d9db68 --- /dev/null +++ b/src/test/regress/expected/numerology_1.out @@ -0,0 +1,136 @@ +-- +-- NUMEROLOGY +-- Test various combinations of numeric types and functions. +-- +-- +-- Test implicit type conversions +-- This fails for Postgres v6.1 (and earlier?) +-- so let's try explicit conversions for now - tgl 97/05/07 +-- +CREATE TABLE TEMP_FLOAT (f1 FLOAT8); +INSERT INTO TEMP_FLOAT (f1) + SELECT float8(f1) FROM INT4_TBL; +INSERT INTO TEMP_FLOAT (f1) + SELECT float8(f1) FROM INT2_TBL; +SELECT '' AS ten, f1 FROM TEMP_FLOAT + ORDER BY f1; + ten | f1 +-----+------------- + | -2147483647 + | -123456 + | -32767 + | -1234 + | 0 + | 0 + | 1234 + | 32767 + | 123456 + | 2147483647 +(10 rows) + +-- int4 +CREATE TABLE TEMP_INT4 (f1 INT4); +INSERT INTO TEMP_INT4 (f1) + SELECT int4(f1) FROM FLOAT8_TBL + WHERE (f1 > -2147483647) AND (f1 < 2147483647); +INSERT INTO TEMP_INT4 (f1) + SELECT int4(f1) FROM INT2_TBL; +SELECT '' AS nine, f1 FROM TEMP_INT4 + ORDER BY f1; + nine | f1 +------+-------- + | -32767 + | -1234 + | -1004 + | -35 + | 0 + | 0 + | 0 + | 1234 + | 32767 +(9 rows) + +-- int2 +CREATE TABLE TEMP_INT2 (f1 INT2); +INSERT INTO TEMP_INT2 (f1) + SELECT int2(f1) FROM FLOAT8_TBL + WHERE (f1 >= -32767) AND (f1 <= 32767); +INSERT INTO TEMP_INT2 (f1) + SELECT int2(f1) FROM INT4_TBL + WHERE (f1 >= -32767) AND (f1 <= 32767); +SELECT '' AS five, f1 FROM TEMP_INT2 + ORDER BY f1; + five | f1 +------+------- + | -1004 + | -35 + | 0 + | 0 + | 0 +(5 rows) + +-- +-- Group-by combinations +-- +CREATE TABLE TEMP_GROUP (f1 INT4, f2 INT4, f3 FLOAT8); +INSERT INTO TEMP_GROUP + SELECT 1, (- i.f1), (- f.f1) + FROM INT4_TBL i, FLOAT8_TBL f; +INSERT INTO TEMP_GROUP + SELECT 2, i.f1, f.f1 + FROM INT4_TBL i, FLOAT8_TBL f; +SELECT DISTINCT f1 AS two FROM TEMP_GROUP ORDER BY 1; + two +----- + 1 + 2 +(2 rows) + +SELECT f1 AS two, max(f3) AS max_float, min(f3) as min_float + FROM TEMP_GROUP + GROUP BY f1 + ORDER BY two, max_float, min_float; + two | max_float | min_float +-----+----------------------+----------------------- + 1 | 1.2345678901234e+200 | 0 + 2 | 0 | -1.2345678901234e+200 +(2 rows) + +-- GROUP BY a result column name is not legal per SQL92, but we accept it +-- anyway (if the name is not the name of any column exposed by FROM). +SELECT f1 AS two, max(f3) AS max_float, min(f3) AS min_float + FROM TEMP_GROUP + GROUP BY two + ORDER BY two, max_float, min_float; + two | max_float | min_float +-----+----------------------+----------------------- + 1 | 1.2345678901234e+200 | 0 + 2 | 0 | -1.2345678901234e+200 +(2 rows) + +SELECT f1 AS two, (max(f3) + 1) AS max_plus_1, (min(f3) - 1) AS min_minus_1 + FROM TEMP_GROUP + GROUP BY f1 + ORDER BY two, min_minus_1; + two | max_plus_1 | min_minus_1 +-----+----------------------+----------------------- + 1 | 1.2345678901234e+200 | -1 + 2 | 1 | -1.2345678901234e+200 +(2 rows) + +SELECT f1 AS two, + max(f2) + min(f2) AS max_plus_min, + min(f3) - 1 AS min_minus_1 + FROM TEMP_GROUP + GROUP BY f1 + ORDER BY two, min_minus_1; + two | max_plus_min | min_minus_1 +-----+--------------+----------------------- + 1 | 0 | -1 + 2 | 0 | -1.2345678901234e+200 +(2 rows) + +DROP TABLE TEMP_INT2; +DROP TABLE TEMP_INT4; +DROP TABLE TEMP_FLOAT; +DROP TABLE TEMP_GROUP; diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index 0fe279493f..66bd895f70 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -2700,7 +2700,7 @@ begin end loop flbl1; end; $$ language plpgsql; -ERROR: no such label at or near "flbl1" +ERROR: label does not exist at or near "flbl1" LINE 5: end loop flbl1; ^ -- should fail: end label does not match start label @@ -2714,7 +2714,7 @@ begin end; $$ language plpgsql; ERROR: end label "outer_label" differs from block's label "inner_label" -CONTEXT: compile of PL/pgSQL function "end_label3" near line 6 +CONTEXT: compilation of PL/pgSQL function "end_label3" near line 6 -- should fail: end label on a block without a start label create function end_label4() returns void as $$ <<outer_label>> @@ -2725,7 +2725,7 @@ begin end; $$ language plpgsql; ERROR: end label "outer_label" specified for unlabelled block -CONTEXT: compile of PL/pgSQL function "end_label4" near line 5 +CONTEXT: compilation of PL/pgSQL function "end_label4" near line 5 -- using list of scalars in fori and fore stmts create function for_vect() returns void as $proc$ <<lbl>>declare a integer; b varchar; c varchar; r record; @@ -3266,7 +3266,7 @@ begin end; $$ language plpgsql; ERROR: cursor FOR loop must use a bound cursor variable -CONTEXT: compile of PL/pgSQL function "forc_bad" near line 4 +CONTEXT: compilation of PL/pgSQL function "forc_bad" near line 4 -- test RETURN QUERY EXECUTE create or replace function return_dquery() returns setof int as $$ |