diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/access/transam/clog.c | 4 | ||||
| -rw-r--r-- | src/backend/access/transam/varsup.c | 5 | ||||
| -rw-r--r-- | src/backend/access/transam/xact.c | 7 | ||||
| -rw-r--r-- | src/backend/access/transam/xlog.c | 9 | ||||
| -rw-r--r-- | src/backend/catalog/information_schema.sql | 4 | ||||
| -rw-r--r-- | src/backend/commands/cluster.c | 19 | ||||
| -rw-r--r-- | src/backend/commands/indexcmds.c | 20 | ||||
| -rw-r--r-- | src/backend/optimizer/plan/subselect.c | 5 | ||||
| -rw-r--r-- | src/backend/optimizer/prep/prepjointree.c | 41 | ||||
| -rw-r--r-- | src/backend/parser/gram.y | 31 | ||||
| -rw-r--r-- | src/backend/postmaster/autovacuum.c | 1 | ||||
| -rw-r--r-- | src/backend/storage/lmgr/predicate.c | 3 | ||||
| -rw-r--r-- | src/backend/tsearch/spell.c | 2 | ||||
| -rw-r--r-- | src/backend/utils/adt/datetime.c | 31 | ||||
| -rw-r--r-- | src/backend/utils/init/postinit.c | 2 | ||||
| -rw-r--r-- | src/backend/utils/misc/guc-file.l | 41 | ||||
| -rw-r--r-- | src/backend/utils/misc/guc.c | 33 | ||||
| -rw-r--r-- | src/backend/utils/misc/postgresql.conf.sample | 6 | ||||
| -rw-r--r-- | src/backend/utils/mmgr/aset.c | 25 |
19 files changed, 195 insertions, 94 deletions
diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index df0f15679f..d3de8934ee 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -431,8 +431,8 @@ CLOGShmemInit(void) /* * This func must be called ONCE on system install. It creates * the initial CLOG segment. (The CLOG directory is assumed to - * have been created by the initdb shell script, and CLOGShmemInit - * must have been called already.) + * have been created by initdb, and CLOGShmemInit must have been + * called already.) */ void BootStrapCLOG(void) diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c index 500335bd6f..555bb134f5 100644 --- a/src/backend/access/transam/varsup.c +++ b/src/backend/access/transam/varsup.c @@ -21,7 +21,6 @@ #include "miscadmin.h" #include "postmaster/autovacuum.h" #include "storage/pmsignal.h" -#include "storage/predicate.h" #include "storage/proc.h" #include "utils/builtins.h" #include "utils/syscache.h" @@ -162,10 +161,6 @@ GetNewTransactionId(bool isSubXact) ExtendCLOG(xid); ExtendSUBTRANS(xid); - /* If it's top level, the predicate locking system also needs to know. */ - if (!isSubXact) - RegisterPredicateLockingXid(xid); - /* * Now advance the nextXid counter. This must not happen until after we * have successfully completed ExtendCLOG() --- if that routine fails, we diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 8a4c4eccd7..2ca1c14549 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -455,6 +455,13 @@ AssignTransactionId(TransactionState s) SubTransSetParent(s->transactionId, s->parent->transactionId, false); /* + * If it's a top-level transaction, the predicate locking system needs to + * be told about it too. + */ + if (!isSubXact) + RegisterPredicateLockingXid(s->transactionId); + + /* * Acquire lock on the transaction XID. (We assume this cannot block.) We * have to ensure that the lock is assigned to the transaction's own * ResourceOwner. diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index b0e4c41d6f..e71090f71b 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -6611,12 +6611,11 @@ StartupXLOG(void) } /* - * If we launched a WAL receiver, it should be gone by now. It will trump - * over the startup checkpoint and subsequent records if it's still alive, - * so be extra sure that it's gone. + * Kill WAL receiver, if it's still running, before we continue to write + * the startup checkpoint record. It will trump over the checkpoint and + * subsequent records if it's still alive when we start writing WAL. */ - if (WalRcvInProgress()) - elog(PANIC, "wal receiver still active"); + ShutdownWalRcv(); /* * We don't need the latch anymore. It's not strictly necessary to disown diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql index c623fb7e75..452a0ead44 100644 --- a/src/backend/catalog/information_schema.sql +++ b/src/backend/catalog/information_schema.sql @@ -2557,8 +2557,8 @@ CREATE VIEW _pg_foreign_tables AS WHERE w.oid = s.srvfdw AND u.oid = c.relowner AND (pg_has_role(c.relowner, 'USAGE') - OR has_table_privilege(c.oid, 'SELECT') - OR has_any_column_privilege(c.oid, 'SELECT')) + OR has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') + OR has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES')) AND n.oid = c.relnamespace AND c.oid = t.ftrelid AND c.relkind = 'f' diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 191ef543cd..dc0f6059b0 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -38,6 +38,7 @@ #include "miscadmin.h" #include "optimizer/planner.h" #include "storage/bufmgr.h" +#include "storage/lmgr.h" #include "storage/procarray.h" #include "storage/smgr.h" #include "utils/acl.h" @@ -751,8 +752,24 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, isnull = (bool *) palloc(natts * sizeof(bool)); /* + * If the OldHeap has a toast table, get lock on the toast table to keep + * it from being vacuumed. This is needed because autovacuum processes + * toast tables independently of their main tables, with no lock on the + * latter. If an autovacuum were to start on the toast table after we + * compute our OldestXmin below, it would use a later OldestXmin, and then + * possibly remove as DEAD toast tuples belonging to main tuples we think + * are only RECENTLY_DEAD. Then we'd fail while trying to copy those + * tuples. + * + * We don't need to open the toast relation here, just lock it. The lock + * will be held till end of transaction. + */ + if (OldHeap->rd_rel->reltoastrelid) + LockRelationOid(OldHeap->rd_rel->reltoastrelid, AccessExclusiveLock); + + /* * We need to log the copied data in WAL iff WAL archiving/streaming is - * enabled AND it's not a WAL-logged rel. + * enabled AND it's a WAL-logged rel. */ use_wal = XLogIsNeeded() && RelationNeedsWAL(NewHeap); diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index ff84045d4f..b91e4a4bd2 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -183,10 +183,22 @@ DefineIndex(RangeVar *heapRelation, /* Note: during bootstrap may see uncataloged relation */ if (rel->rd_rel->relkind != RELKIND_RELATION && rel->rd_rel->relkind != RELKIND_UNCATALOGED) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table", - heapRelation->relname))); + { + if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE) + /* + * Custom error message for FOREIGN TABLE since the term is + * close to a regular table and can confuse the user. + */ + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot create index on foreign table \"%s\"", + heapRelation->relname))); + else + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a table", + heapRelation->relname))); + } /* * Don't try to CREATE INDEX on temp tables of other backends. diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 493bc86299..45eaa03fda 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -1065,6 +1065,11 @@ SS_process_ctes(PlannerInfo *root) * (Notionally, we replace the SubLink with a constant TRUE, then elide the * redundant constant from the qual.) * + * On success, the caller is also responsible for recursively applying + * pull_up_sublinks processing to the rarg and quals of the returned JoinExpr. + * (On failure, there is no need to do anything, since pull_up_sublinks will + * be applied when we recursively plan the sub-select.) + * * Side effects of a successful conversion include adding the SubLink's * subselect to the query's rangetable, so that it can be referenced in * the JoinExpr's rarg. diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c index a70439cc67..5d163292c5 100644 --- a/src/backend/optimizer/prep/prepjointree.c +++ b/src/backend/optimizer/prep/prepjointree.c @@ -318,6 +318,7 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node, { SubLink *sublink = (SubLink *) node; JoinExpr *j; + Relids child_rels; /* Is it a convertible ANY or EXISTS clause? */ if (sublink->subLinkType == ANY_SUBLINK) @@ -326,7 +327,18 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node, available_rels); if (j) { - /* Yes, insert the new join node into the join tree */ + /* Yes; recursively process what we pulled up */ + j->rarg = pull_up_sublinks_jointree_recurse(root, + j->rarg, + &child_rels); + /* Pulled-up ANY/EXISTS quals can use those rels too */ + child_rels = bms_add_members(child_rels, available_rels); + /* ... and any inserted joins get stacked onto j->rarg */ + j->quals = pull_up_sublinks_qual_recurse(root, + j->quals, + child_rels, + &j->rarg); + /* Now insert the new join node into the join tree */ j->larg = *jtlink; *jtlink = (Node *) j; /* and return NULL representing constant TRUE */ @@ -339,7 +351,18 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node, available_rels); if (j) { - /* Yes, insert the new join node into the join tree */ + /* Yes; recursively process what we pulled up */ + j->rarg = pull_up_sublinks_jointree_recurse(root, + j->rarg, + &child_rels); + /* Pulled-up ANY/EXISTS quals can use those rels too */ + child_rels = bms_add_members(child_rels, available_rels); + /* ... and any inserted joins get stacked onto j->rarg */ + j->quals = pull_up_sublinks_qual_recurse(root, + j->quals, + child_rels, + &j->rarg); + /* Now insert the new join node into the join tree */ j->larg = *jtlink; *jtlink = (Node *) j; /* and return NULL representing constant TRUE */ @@ -354,6 +377,7 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node, /* If the immediate argument of NOT is EXISTS, try to convert */ SubLink *sublink = (SubLink *) get_notclausearg((Expr *) node); JoinExpr *j; + Relids child_rels; if (sublink && IsA(sublink, SubLink)) { @@ -363,7 +387,18 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node, available_rels); if (j) { - /* Yes, insert the new join node into the join tree */ + /* Yes; recursively process what we pulled up */ + j->rarg = pull_up_sublinks_jointree_recurse(root, + j->rarg, + &child_rels); + /* Pulled-up ANY/EXISTS quals can use those rels too */ + child_rels = bms_add_members(child_rels, available_rels); + /* ... and any inserted joins get stacked onto j->rarg */ + j->quals = pull_up_sublinks_qual_recurse(root, + j->quals, + child_rels, + &j->rarg); + /* Now insert the new join node into the join tree */ j->larg = *jtlink; *jtlink = (Node *) j; /* and return NULL representing constant TRUE */ diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 34ecd292cb..cc0d6f5557 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -597,7 +597,8 @@ static void SplitColQualList(List *qualList, * have any bad effects since obviously the keywords will still behave the * same as if they weren't keywords). We need to do this for PARTITION, * RANGE, ROWS to support opt_existing_window_name; and for RANGE, ROWS - * so that they can follow a_expr without creating + * so that they can follow a_expr without creating postfix-operator problems; + * and for NULL so that it can follow b_expr in ColQualList without creating * postfix-operator problems. * * The frame_bound productions UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING @@ -610,16 +611,16 @@ static void SplitColQualList(List *qualList, * blame any funny behavior of UNBOUNDED on the SQL standard, though. */ %nonassoc UNBOUNDED /* ideally should have same precedence as IDENT */ -%nonassoc IDENT PARTITION RANGE ROWS PRECEDING FOLLOWING +%nonassoc IDENT NULL_P PARTITION RANGE ROWS PRECEDING FOLLOWING %left Op OPERATOR /* multi-character ops and user-defined operators */ %nonassoc NOTNULL %nonassoc ISNULL -%nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN /* sets precedence for IS NULL, etc */ +%nonassoc IS /* sets precedence for IS NULL, etc */ %left '+' '-' %left '*' '/' '%' %left '^' /* Unary Operators */ -%left AT ZONE /* sets precedence for AT TIME ZONE */ +%left AT /* sets precedence for AT TIME ZONE */ %left COLLATE %right UMINUS %left '[' ']' @@ -4125,9 +4126,7 @@ TriggerFuncArg: } | FCONST { $$ = makeString($1); } | Sconst { $$ = makeString($1); } - | BCONST { $$ = makeString($1); } - | XCONST { $$ = makeString($1); } - | ColId { $$ = makeString($1); } + | ColLabel { $$ = makeString($1); } ; OptConstrFromTable: @@ -9714,7 +9713,7 @@ a_expr: c_expr { $$ = $1; } n->location = @2; $$ = (Node *) n; } - | a_expr AT TIME ZONE a_expr + | a_expr AT TIME ZONE a_expr %prec AT { FuncCall *n = makeNode(FuncCall); n->funcname = SystemFuncName("timezone"); @@ -9896,7 +9895,7 @@ a_expr: c_expr { $$ = $1; } * a ISNULL * a NOTNULL */ - | a_expr IS NULL_P + | a_expr IS NULL_P %prec IS { NullTest *n = makeNode(NullTest); n->arg = (Expr *) $1; @@ -9910,7 +9909,7 @@ a_expr: c_expr { $$ = $1; } n->nulltesttype = IS_NULL; $$ = (Node *)n; } - | a_expr IS NOT NULL_P + | a_expr IS NOT NULL_P %prec IS { NullTest *n = makeNode(NullTest); n->arg = (Expr *) $1; @@ -9928,42 +9927,42 @@ a_expr: c_expr { $$ = $1; } { $$ = (Node *)makeOverlaps($1, $3, @2, yyscanner); } - | a_expr IS TRUE_P + | a_expr IS TRUE_P %prec IS { BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_TRUE; $$ = (Node *)b; } - | a_expr IS NOT TRUE_P + | a_expr IS NOT TRUE_P %prec IS { BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_NOT_TRUE; $$ = (Node *)b; } - | a_expr IS FALSE_P + | a_expr IS FALSE_P %prec IS { BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_FALSE; $$ = (Node *)b; } - | a_expr IS NOT FALSE_P + | a_expr IS NOT FALSE_P %prec IS { BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_NOT_FALSE; $$ = (Node *)b; } - | a_expr IS UNKNOWN + | a_expr IS UNKNOWN %prec IS { BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_UNKNOWN; $$ = (Node *)b; } - | a_expr IS NOT UNKNOWN + | a_expr IS NOT UNKNOWN %prec IS { BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 9fa63a4e6e..fcc912f8e3 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -1108,6 +1108,7 @@ do_start_worker(void) recentXid = ReadNewTransactionId(); xidForceLimit = recentXid - autovacuum_freeze_max_age; /* ensure it's a "normal" XID, else TransactionIdPrecedes misbehaves */ + /* this can cause the limit to go backwards by 3, but that's OK */ if (xidForceLimit < FirstNormalTransactionId) xidForceLimit -= FirstNormalTransactionId; diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index 48ff9cc151..3b3158efe5 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -2283,6 +2283,9 @@ PredicateLockTupleRowVersionLink(const Relation relation, * locks. Even if a serializable transaction starts concurrently, * we know it can't take any SIREAD locks on the modified tuple * because the caller is holding the associated buffer page lock. + * Memory reordering isn't an issue; the memory barrier in the + * LWLock acquisition guarantees that this read occurs while the + * buffer page lock is held. */ if (!TransactionIdIsValid(PredXact->SxactGlobalXmin)) return; diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c index 8c0eaa78a7..be1663cd88 100644 --- a/src/backend/tsearch/spell.c +++ b/src/backend/tsearch/spell.c @@ -75,7 +75,7 @@ NIFinishBuild(IspellDict *Conf) * doesn't need that. The cpalloc and cpalloc0 macros are just documentation * to indicate which allocations actually require zeroing. */ -#define COMPACT_ALLOC_CHUNK 8192 /* must be > aset.c's allocChunkLimit */ +#define COMPACT_ALLOC_CHUNK 8192 /* amount to get from palloc at once */ #define COMPACT_MAX_REQ 1024 /* must be < COMPACT_ALLOC_CHUNK */ static void * diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index db0a6487ac..0a12a9b2e1 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -3569,24 +3569,27 @@ DateTimeParseError(int dterr, const char *str, const char *datatype) static const datetkn * datebsearch(const char *key, const datetkn *base, int nel) { - const datetkn *last = base + nel - 1, - *position; - int result; - - while (last >= base) + if (nel > 0) { - position = base + ((last - base) >> 1); - result = key[0] - position->token[0]; - if (result == 0) + const datetkn *last = base + nel - 1, + *position; + int result; + + while (last >= base) { - result = strncmp(key, position->token, TOKMAXLEN); + position = base + ((last - base) >> 1); + result = key[0] - position->token[0]; if (result == 0) - return position; + { + result = strncmp(key, position->token, TOKMAXLEN); + if (result == 0) + return position; + } + if (result < 0) + last = position - 1; + else + base = position + 1; } - if (result < 0) - last = position - 1; - else - base = position + 1; } return NULL; } diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 1f6fba5f75..3ac3254afb 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -324,7 +324,7 @@ CheckMyDatabase(const char *name, bool am_superuser) PGC_INTERNAL, PGC_S_OVERRIDE); /* If we have no other source of client_encoding, use server encoding */ SetConfigOption("client_encoding", GetDatabaseEncodingName(), - PGC_BACKEND, PGC_S_DEFAULT); + PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT); /* assign locale variables */ collate = NameStr(dbform->datcollate); diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l index 10ef12eb24..78907b939d 100644 --- a/src/backend/utils/misc/guc-file.l +++ b/src/backend/utils/misc/guc-file.l @@ -14,6 +14,7 @@ #include <ctype.h> #include <unistd.h> +#include "mb/pg_wchar.h" #include "miscadmin.h" #include "storage/fd.h" #include "utils/guc.h" @@ -109,7 +110,6 @@ ProcessConfigFile(GucContext context) *tail; char *cvc = NULL; struct config_string *cvc_struct; - const char *envvar; int i; Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP); @@ -265,7 +265,7 @@ ProcessConfigFile(GucContext context) stack->source = PGC_S_DEFAULT; } - /* Now we can re-apply the wired-in default */ + /* Now we can re-apply the wired-in default (i.e., the boot_val) */ set_config_option(gconf->name, NULL, context, PGC_S_DEFAULT, GUC_ACTION_SET, true); if (context == PGC_SIGHUP) @@ -275,25 +275,28 @@ ProcessConfigFile(GucContext context) } /* - * Restore any variables determined by environment variables. This - * is a no-op except in the case where one of these had been in the - * config file and is now removed. PGC_S_ENV_VAR will override the - * wired-in default we just applied, but cannot override any other source. + * Restore any variables determined by environment variables or + * dynamically-computed defaults. This is a no-op except in the case + * where one of these had been in the config file and is now removed. * - * Keep this list in sync with InitializeGUCOptions()! - * PGPORT can be ignored, because it cannot be changed without restart. - * We assume rlimit hasn't changed, either. + * In particular, we *must not* do this during the postmaster's + * initial loading of the file, since the timezone functions in + * particular should be run only after initialization is complete. + * + * XXX this is an unmaintainable crock, because we have to know how + * to set (or at least what to call to set) every variable that could + * potentially have PGC_S_DYNAMIC_DEFAULT or PGC_S_ENV_VAR source. + * However, there's no time to redesign it for 9.1. */ - envvar = getenv("PGDATESTYLE"); - if (envvar != NULL) - set_config_option("datestyle", envvar, PGC_POSTMASTER, - PGC_S_ENV_VAR, GUC_ACTION_SET, true); - - envvar = getenv("PGCLIENTENCODING"); - if (envvar != NULL) - set_config_option("client_encoding", envvar, PGC_POSTMASTER, - PGC_S_ENV_VAR, GUC_ACTION_SET, true); - + if (context == PGC_SIGHUP) + { + InitializeGUCOptionsFromEnvironment(); + pg_timezone_initialize(); + pg_timezone_abbrev_initialize(); + /* this selects SQL_ASCII in processes not connected to a database */ + SetConfigOption("client_encoding", GetDatabaseEncodingName(), + PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT); + } /* If we got here all the options checked out okay, so apply them. */ for (item = head; item; item = item->next) diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 738e2152ba..92391eda2f 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -502,6 +502,7 @@ const char *const GucContext_Names[] = const char *const GucSource_Names[] = { /* PGC_S_DEFAULT */ "default", + /* PGC_S_DYNAMIC_DEFAULT */ "default", /* PGC_S_ENV_VAR */ "environment variable", /* PGC_S_FILE */ "configuration file", /* PGC_S_ARGV */ "command line", @@ -3269,6 +3270,7 @@ static int GUCNestLevel = 0; /* 1 when in main transaction */ static int guc_var_compare(const void *a, const void *b); static int guc_name_compare(const char *namea, const char *nameb); +static void InitializeGUCOptionsFromEnvironment(void); static void InitializeOneGUCOption(struct config_generic * gconf); static void push_old_value(struct config_generic * gconf, GucAction action); static void ReportGUCOption(struct config_generic * record); @@ -3812,8 +3814,6 @@ void InitializeGUCOptions(void) { int i; - char *env; - long stack_rlimit; /* * Before log_line_prefix could possibly receive a nonempty setting, make @@ -3852,9 +3852,25 @@ InitializeGUCOptions(void) /* * For historical reasons, some GUC parameters can receive defaults from - * environment variables. Process those settings. NB: if you add or - * remove anything here, see also ProcessConfigFile(). + * environment variables. Process those settings. */ + InitializeGUCOptionsFromEnvironment(); +} + +/* + * Assign any GUC values that can come from the server's environment. + * + * This is called from InitializeGUCOptions, and also from ProcessConfigFile + * to deal with the possibility that a setting has been removed from + * postgresql.conf and should now get a value from the environment. + * (The latter is a kludge that should probably go away someday; if so, + * fold this back into InitializeGUCOptions.) + */ +static void +InitializeGUCOptionsFromEnvironment(void) +{ + char *env; + long stack_rlimit; env = getenv("PGPORT"); if (env != NULL) @@ -6334,6 +6350,7 @@ define_custom_variable(struct config_generic * variable) switch (pHolder->gen.source) { case PGC_S_DEFAULT: + case PGC_S_DYNAMIC_DEFAULT: case PGC_S_ENV_VAR: case PGC_S_FILE: case PGC_S_ARGV: @@ -8420,15 +8437,13 @@ assign_timezone_abbreviations(const char *newval, void *extra) * * This is called after initial loading of postgresql.conf. If no * timezone_abbreviations setting was found therein, select default. + * If a non-default value is already installed, nothing will happen. */ void pg_timezone_abbrev_initialize(void) { - if (timezone_abbreviations_string == NULL) - { - SetConfigOption("timezone_abbreviations", "Default", - PGC_POSTMASTER, PGC_S_DEFAULT); - } + SetConfigOption("timezone_abbreviations", "Default", + PGC_POSTMASTER, PGC_S_DYNAMIC_DEFAULT); } static const char * diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index b8a1582eaa..655dad42c7 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -390,8 +390,7 @@ #log_temp_files = -1 # log temporary files equal or larger # than the specified size in kilobytes; # -1 disables, 0 logs all temp files -#log_timezone = unknown # actually, defaults to TZ environment - # setting +#log_timezone = '(defaults to server environment setting)' #------------------------------------------------------------------------------ @@ -471,8 +470,7 @@ #datestyle = 'iso, mdy' #intervalstyle = 'postgres' -#timezone = unknown # actually, defaults to TZ environment - # setting +#timezone = '(defaults to server environment setting)' #timezone_abbreviations = 'Default' # Select the set of available time zone # abbreviations. Currently, there are # Default diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c index e95dcb6b7c..140b0c74d9 100644 --- a/src/backend/utils/mmgr/aset.c +++ b/src/backend/utils/mmgr/aset.c @@ -89,7 +89,9 @@ * * With the current parameters, request sizes up to 8K are treated as chunks, * larger requests go into dedicated blocks. Change ALLOCSET_NUM_FREELISTS - * to adjust the boundary point. + * to adjust the boundary point. (But in contexts with small maxBlockSize, + * we may set the allocChunkLimit to less than 8K, so as to avoid space + * wastage.) *-------------------- */ @@ -97,6 +99,8 @@ #define ALLOCSET_NUM_FREELISTS 11 #define ALLOC_CHUNK_LIMIT (1 << (ALLOCSET_NUM_FREELISTS-1+ALLOC_MINBITS)) /* Size of largest chunk that we use a fixed size for */ +#define ALLOC_CHUNK_FRACTION 4 +/* We allow chunks to be at most 1/4 of maxBlockSize (less overhead) */ /*-------------------- * The first block allocated for an allocset has size initBlockSize. @@ -380,15 +384,20 @@ AllocSetContextCreate(MemoryContext parent, /* * Compute the allocation chunk size limit for this context. It can't be * more than ALLOC_CHUNK_LIMIT because of the fixed number of freelists. - * If maxBlockSize is small then requests exceeding the maxBlockSize - * should be treated as large chunks, too. We have to have - * allocChunkLimit a power of two, because the requested and - * actually-allocated sizes of any chunk must be on the same side of the - * limit, else we get confused about whether the chunk is "big". + * If maxBlockSize is small then requests exceeding the maxBlockSize, or + * even a significant fraction of it, should be treated as large chunks + * too. For the typical case of maxBlockSize a power of 2, the chunk size + * limit will be at most 1/8th maxBlockSize, so that given a stream of + * requests that are all the maximum chunk size we will waste at most + * 1/8th of the allocated space. + * + * We have to have allocChunkLimit a power of two, because the requested + * and actually-allocated sizes of any chunk must be on the same side of + * the limit, else we get confused about whether the chunk is "big". */ context->allocChunkLimit = ALLOC_CHUNK_LIMIT; - while (context->allocChunkLimit > - (Size) (maxBlockSize - ALLOC_BLOCKHDRSZ - ALLOC_CHUNKHDRSZ)) + while ((Size) (context->allocChunkLimit + ALLOC_CHUNKHDRSZ) > + (Size) ((maxBlockSize - ALLOC_BLOCKHDRSZ) / ALLOC_CHUNK_FRACTION)) context->allocChunkLimit >>= 1; /* |
