diff options
author | Robert Haas <rhaas@postgresql.org> | 2010-01-05 21:54:00 +0000 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2010-01-05 21:54:00 +0000 |
commit | d86d51a95810caebcea587498068ff32fe28293e (patch) | |
tree | 031fb02a2ef325762250b163acd215cd7c31c2bb /src | |
parent | 72559b49c051ff7dc860068c96324ddf07d7955d (diff) | |
download | postgresql-d86d51a95810caebcea587498068ff32fe28293e.tar.gz postgresql-d86d51a95810caebcea587498068ff32fe28293e.zip |
Support ALTER TABLESPACE name SET/RESET ( tablespace_options ).
This patch only supports seq_page_cost and random_page_cost as parameters,
but it provides the infrastructure to scalably support many more.
In particular, we may want to add support for effective_io_concurrency,
but I'm leaving that as future work for now.
Thanks to Tom Lane for design help and Alvaro Herrera for the review.
Diffstat (limited to 'src')
26 files changed, 557 insertions, 99 deletions
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c index 2e3fa5bcae5..28eacb4e478 100644 --- a/src/backend/access/common/reloptions.c +++ b/src/backend/access/common/reloptions.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.30 2010/01/02 16:57:33 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.31 2010/01/05 21:53:58 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,7 @@ #include "access/reloptions.h" #include "catalog/pg_type.h" #include "commands/defrem.h" +#include "commands/tablespace.h" #include "nodes/makefuncs.h" #include "utils/array.h" #include "utils/builtins.h" @@ -179,6 +180,22 @@ static relopt_real realRelOpts[] = }, -1, 0.0, 100.0 }, + { + { + "seq_page_cost", + "Sets the planner's estimate of the cost of a sequentially fetched disk page.", + RELOPT_KIND_TABLESPACE + }, + -1, 0.0, DBL_MAX + }, + { + { + "random_page_cost", + "Sets the planner's estimate of the cost of a nonsequentially fetched disk page.", + RELOPT_KIND_TABLESPACE + }, + -1, 0.0, DBL_MAX + }, /* list terminator */ {{NULL}} }; @@ -1168,3 +1185,34 @@ index_reloptions(RegProcedure amoptions, Datum reloptions, bool validate) return DatumGetByteaP(result); } + +/* + * Option parser for tablespace reloptions + */ +bytea * +tablespace_reloptions(Datum reloptions, bool validate) +{ + relopt_value *options; + TableSpaceOpts *tsopts; + int numoptions; + static const relopt_parse_elt tab[] = { + {"random_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, random_page_cost)}, + {"seq_page_cost", RELOPT_TYPE_REAL, offsetof(TableSpaceOpts, seq_page_cost)} + }; + + options = parseRelOptions(reloptions, validate, RELOPT_KIND_TABLESPACE, + &numoptions); + + /* if none set, we're done */ + if (numoptions == 0) + return NULL; + + tsopts = allocateReloptStruct(sizeof(TableSpaceOpts), options, numoptions); + + fillRelOptions((void *) tsopts, sizeof(TableSpaceOpts), options, numoptions, + validate, tab, lengthof(tab)); + + pfree(options); + + return (bytea *) tsopts; +} diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index d98ebdda4f8..6c16fd6a6e2 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.159 2010/01/02 16:57:36 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.160 2010/01/05 21:53:58 rhaas Exp $ * * NOTES * See acl.h. @@ -2783,18 +2783,11 @@ ExecGrant_Tablespace(InternalGrant *istmt) int nnewmembers; Oid *oldmembers; Oid *newmembers; - ScanKeyData entry[1]; - SysScanDesc scan; HeapTuple tuple; - /* There's no syscache for pg_tablespace, so must look the hard way */ - ScanKeyInit(&entry[0], - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(tblId)); - scan = systable_beginscan(relation, TablespaceOidIndexId, true, - SnapshotNow, 1, entry); - tuple = systable_getnext(scan); + /* Search syscache for pg_tablespace */ + tuple = SearchSysCache(TABLESPACEOID, ObjectIdGetDatum(tblId), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for tablespace %u", tblId); @@ -2865,8 +2858,7 @@ ExecGrant_Tablespace(InternalGrant *istmt) noldmembers, oldmembers, nnewmembers, newmembers); - systable_endscan(scan); - + ReleaseSysCache(tuple); pfree(new_acl); /* prevent error when processing duplicate objects */ @@ -3696,9 +3688,6 @@ pg_tablespace_aclmask(Oid spc_oid, Oid roleid, AclMode mask, AclMaskHow how) { AclMode result; - Relation pg_tablespace; - ScanKeyData entry[1]; - SysScanDesc scan; HeapTuple tuple; Datum aclDatum; bool isNull; @@ -3711,17 +3700,9 @@ pg_tablespace_aclmask(Oid spc_oid, Oid roleid, /* * Get the tablespace's ACL from pg_tablespace - * - * There's no syscache for pg_tablespace, so must look the hard way */ - pg_tablespace = heap_open(TableSpaceRelationId, AccessShareLock); - ScanKeyInit(&entry[0], - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(spc_oid)); - scan = systable_beginscan(pg_tablespace, TablespaceOidIndexId, true, - SnapshotNow, 1, entry); - tuple = systable_getnext(scan); + tuple = SearchSysCache(TABLESPACEOID, ObjectIdGetDatum(spc_oid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), @@ -3729,8 +3710,9 @@ pg_tablespace_aclmask(Oid spc_oid, Oid roleid, ownerId = ((Form_pg_tablespace) GETSTRUCT(tuple))->spcowner; - aclDatum = heap_getattr(tuple, Anum_pg_tablespace_spcacl, - RelationGetDescr(pg_tablespace), &isNull); + aclDatum = SysCacheGetAttr(TABLESPACEOID, tuple, + Anum_pg_tablespace_spcacl, + &isNull); if (isNull) { @@ -3750,8 +3732,7 @@ pg_tablespace_aclmask(Oid spc_oid, Oid roleid, if (acl && (Pointer) acl != DatumGetPointer(aclDatum)) pfree(acl); - systable_endscan(scan); - heap_close(pg_tablespace, AccessShareLock); + ReleaseSysCache(tuple); return result; } @@ -4338,9 +4319,6 @@ pg_namespace_ownercheck(Oid nsp_oid, Oid roleid) bool pg_tablespace_ownercheck(Oid spc_oid, Oid roleid) { - Relation pg_tablespace; - ScanKeyData entry[1]; - SysScanDesc scan; HeapTuple spctuple; Oid spcowner; @@ -4348,17 +4326,9 @@ pg_tablespace_ownercheck(Oid spc_oid, Oid roleid) if (superuser_arg(roleid)) return true; - /* There's no syscache for pg_tablespace, so must look the hard way */ - pg_tablespace = heap_open(TableSpaceRelationId, AccessShareLock); - ScanKeyInit(&entry[0], - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(spc_oid)); - scan = systable_beginscan(pg_tablespace, TablespaceOidIndexId, true, - SnapshotNow, 1, entry); - - spctuple = systable_getnext(scan); - + /* Search syscache for pg_tablespace */ + spctuple = SearchSysCache(TABLESPACEOID, ObjectIdGetDatum(spc_oid), + 0, 0, 0); if (!HeapTupleIsValid(spctuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), @@ -4366,8 +4336,7 @@ pg_tablespace_ownercheck(Oid spc_oid, Oid roleid) spcowner = ((Form_pg_tablespace) GETSTRUCT(spctuple))->spcowner; - systable_endscan(scan); - heap_close(pg_tablespace, AccessShareLock); + ReleaseSysCache(spctuple); return has_privs_of_role(roleid, spcowner); } diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 927711eed27..0da15569f36 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.65 2010/01/02 16:57:37 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.66 2010/01/05 21:53:58 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -49,6 +49,7 @@ #include <sys/stat.h> #include "access/heapam.h" +#include "access/reloptions.h" #include "access/sysattr.h" #include "access/transam.h" #include "access/xact.h" @@ -57,6 +58,7 @@ #include "catalog/indexing.h" #include "catalog/pg_tablespace.h" #include "commands/comment.h" +#include "commands/defrem.h" #include "commands/tablespace.h" #include "miscadmin.h" #include "postmaster/bgwriter.h" @@ -70,6 +72,7 @@ #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/rel.h" +#include "utils/syscache.h" #include "utils/tqual.h" @@ -290,6 +293,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) values[Anum_pg_tablespace_spclocation - 1] = CStringGetTextDatum(location); nulls[Anum_pg_tablespace_spcacl - 1] = true; + nulls[Anum_pg_tablespace_spcoptions - 1] = true; tuple = heap_form_tuple(rel->rd_att, values, nulls); @@ -913,6 +917,73 @@ AlterTableSpaceOwner(const char *name, Oid newOwnerId) /* + * Alter table space options + */ +void +AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt) +{ + Relation rel; + ScanKeyData entry[1]; + HeapScanDesc scandesc; + HeapTuple tup; + Datum datum; + Datum newOptions; + Datum repl_val[Natts_pg_tablespace]; + bool isnull; + bool repl_null[Natts_pg_tablespace]; + bool repl_repl[Natts_pg_tablespace]; + HeapTuple newtuple; + + /* Search pg_tablespace */ + rel = heap_open(TableSpaceRelationId, RowExclusiveLock); + + ScanKeyInit(&entry[0], + Anum_pg_tablespace_spcname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(stmt->tablespacename)); + scandesc = heap_beginscan(rel, SnapshotNow, 1, entry); + tup = heap_getnext(scandesc, ForwardScanDirection); + if (!HeapTupleIsValid(tup)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tablespace \"%s\" does not exist", + stmt->tablespacename))); + + /* Must be owner of the existing object */ + if (!pg_tablespace_ownercheck(HeapTupleGetOid(tup), GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE, + stmt->tablespacename); + + /* Generate new proposed spcoptions (text array) */ + datum = heap_getattr(tup, Anum_pg_tablespace_spcoptions, + RelationGetDescr(rel), &isnull); + newOptions = transformRelOptions(isnull ? (Datum) 0 : datum, + stmt->options, NULL, NULL, false, + stmt->isReset); + (void) tablespace_reloptions(newOptions, true); + + /* Build new tuple. */ + memset(repl_null, false, sizeof(repl_null)); + memset(repl_repl, false, sizeof(repl_repl)); + if (newOptions != (Datum) 0) + repl_val[Anum_pg_tablespace_spcoptions - 1] = newOptions; + else + repl_null[Anum_pg_tablespace_spcoptions - 1] = true; + repl_repl[Anum_pg_tablespace_spcoptions - 1] = true; + newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, + repl_null, repl_repl); + + /* Update system catalog. */ + simple_heap_update(rel, &newtuple->t_self, newtuple); + CatalogUpdateIndexes(rel, newtuple); + heap_freetuple(newtuple); + + /* Conclude heap scan. */ + heap_endscan(scandesc); + heap_close(rel, NoLock); +} + +/* * Routines for handling the GUC variable 'default_tablespace'. */ diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 7cbbb1f913d..8d1f1641d7c 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.458 2010/01/02 16:57:45 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.459 2010/01/05 21:53:58 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -3064,6 +3064,18 @@ _copyDropTableSpaceStmt(DropTableSpaceStmt *from) return newnode; } +static AlterTableSpaceOptionsStmt * +_copyAlterTableSpaceOptionsStmt(AlterTableSpaceOptionsStmt *from) +{ + AlterTableSpaceOptionsStmt *newnode = makeNode(AlterTableSpaceOptionsStmt); + + COPY_STRING_FIELD(tablespacename); + COPY_NODE_FIELD(options); + COPY_SCALAR_FIELD(isReset); + + return newnode; +} + static CreateFdwStmt * _copyCreateFdwStmt(CreateFdwStmt *from) { @@ -4028,6 +4040,9 @@ copyObject(void *from) case T_DropTableSpaceStmt: retval = _copyDropTableSpaceStmt(from); break; + case T_AlterTableSpaceOptionsStmt: + retval = _copyAlterTableSpaceOptionsStmt(from); + break; case T_CreateFdwStmt: retval = _copyCreateFdwStmt(from); break; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 20abee3898d..24e53773077 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -22,7 +22,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.379 2010/01/02 16:57:46 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.380 2010/01/05 21:53:58 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -1569,6 +1569,17 @@ _equalDropTableSpaceStmt(DropTableSpaceStmt *a, DropTableSpaceStmt *b) } static bool +_equalAlterTableSpaceOptionsStmt(AlterTableSpaceOptionsStmt *a, + AlterTableSpaceOptionsStmt *b) +{ + COMPARE_STRING_FIELD(tablespacename); + COMPARE_NODE_FIELD(options); + COMPARE_SCALAR_FIELD(isReset); + + return true; +} + +static bool _equalCreateFdwStmt(CreateFdwStmt *a, CreateFdwStmt *b) { COMPARE_STRING_FIELD(fdwname); @@ -2720,6 +2731,9 @@ equal(void *a, void *b) case T_DropTableSpaceStmt: retval = _equalDropTableSpaceStmt(a, b); break; + case T_AlterTableSpaceOptionsStmt: + retval = _equalAlterTableSpaceOptionsStmt(a, b); + break; case T_CreateFdwStmt: retval = _equalCreateFdwStmt(a, b); break; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 0342e66b515..5bd092eae25 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.379 2010/01/02 16:57:46 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.380 2010/01/05 21:53:58 rhaas Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -1590,6 +1590,7 @@ _outRelOptInfo(StringInfo str, RelOptInfo *node) WRITE_NODE_FIELD(cheapest_total_path); WRITE_NODE_FIELD(cheapest_unique_path); WRITE_UINT_FIELD(relid); + WRITE_UINT_FIELD(reltablespace); WRITE_ENUM_FIELD(rtekind, RTEKind); WRITE_INT_FIELD(min_attr); WRITE_INT_FIELD(max_attr); diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index bc028ee1473..f92c944925f 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -27,6 +27,11 @@ * detail. Note that all of these parameters are user-settable, in case * the default values are drastically off for a particular platform. * + * seq_page_cost and random_page_cost can also be overridden for an individual + * tablespace, in case some data is on a fast disk and other data is on a slow + * disk. Per-tablespace overrides never apply to temporary work files such as + * an external sort or a materialize node that overflows work_mem. + * * We compute two separate costs for each path: * total_cost: total estimated cost to fetch all tuples * startup_cost: cost that is expended before first tuple is fetched @@ -54,7 +59,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.213 2010/01/02 16:57:46 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.214 2010/01/05 21:53:58 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -76,6 +81,7 @@ #include "parser/parsetree.h" #include "utils/lsyscache.h" #include "utils/selfuncs.h" +#include "utils/spccache.h" #include "utils/tuplesort.h" @@ -164,6 +170,7 @@ void cost_seqscan(Path *path, PlannerInfo *root, RelOptInfo *baserel) { + double spc_seq_page_cost; Cost startup_cost = 0; Cost run_cost = 0; Cost cpu_per_tuple; @@ -175,10 +182,15 @@ cost_seqscan(Path *path, PlannerInfo *root, if (!enable_seqscan) startup_cost += disable_cost; + /* fetch estimated page cost for tablespace containing table */ + get_tablespace_page_costs(baserel->reltablespace, + NULL, + &spc_seq_page_cost); + /* * disk costs */ - run_cost += seq_page_cost * baserel->pages; + run_cost += spc_seq_page_cost * baserel->pages; /* CPU costs */ startup_cost += baserel->baserestrictcost.startup; @@ -226,6 +238,8 @@ cost_index(IndexPath *path, PlannerInfo *root, Selectivity indexSelectivity; double indexCorrelation, csquared; + double spc_seq_page_cost, + spc_random_page_cost; Cost min_IO_cost, max_IO_cost; Cost cpu_per_tuple; @@ -272,13 +286,18 @@ cost_index(IndexPath *path, PlannerInfo *root, /* estimate number of main-table tuples fetched */ tuples_fetched = clamp_row_est(indexSelectivity * baserel->tuples); + /* fetch estimated page costs for tablespace containing table */ + get_tablespace_page_costs(baserel->reltablespace, + &spc_random_page_cost, + &spc_seq_page_cost); + /*---------- * Estimate number of main-table pages fetched, and compute I/O cost. * * When the index ordering is uncorrelated with the table ordering, * we use an approximation proposed by Mackert and Lohman (see * index_pages_fetched() for details) to compute the number of pages - * fetched, and then charge random_page_cost per page fetched. + * fetched, and then charge spc_random_page_cost per page fetched. * * When the index ordering is exactly correlated with the table ordering * (just after a CLUSTER, for example), the number of pages fetched should @@ -286,7 +305,7 @@ cost_index(IndexPath *path, PlannerInfo *root, * will be sequential fetches, not the random fetches that occur in the * uncorrelated case. So if the number of pages is more than 1, we * ought to charge - * random_page_cost + (pages_fetched - 1) * seq_page_cost + * spc_random_page_cost + (pages_fetched - 1) * spc_seq_page_cost * For partially-correlated indexes, we ought to charge somewhere between * these two estimates. We currently interpolate linearly between the * estimates based on the correlation squared (XXX is that appropriate?). @@ -309,7 +328,7 @@ cost_index(IndexPath *path, PlannerInfo *root, (double) index->pages, root); - max_IO_cost = (pages_fetched * random_page_cost) / num_scans; + max_IO_cost = (pages_fetched * spc_random_page_cost) / num_scans; /* * In the perfectly correlated case, the number of pages touched by @@ -328,7 +347,7 @@ cost_index(IndexPath *path, PlannerInfo *root, (double) index->pages, root); - min_IO_cost = (pages_fetched * random_page_cost) / num_scans; + min_IO_cost = (pages_fetched * spc_random_page_cost) / num_scans; } else { @@ -342,13 +361,13 @@ cost_index(IndexPath *path, PlannerInfo *root, root); /* max_IO_cost is for the perfectly uncorrelated case (csquared=0) */ - max_IO_cost = pages_fetched * random_page_cost; + max_IO_cost = pages_fetched * spc_random_page_cost; /* min_IO_cost is for the perfectly correlated case (csquared=1) */ pages_fetched = ceil(indexSelectivity * (double) baserel->pages); - min_IO_cost = random_page_cost; + min_IO_cost = spc_random_page_cost; if (pages_fetched > 1) - min_IO_cost += (pages_fetched - 1) * seq_page_cost; + min_IO_cost += (pages_fetched - 1) * spc_seq_page_cost; } /* @@ -553,6 +572,8 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, Cost cost_per_page; double tuples_fetched; double pages_fetched; + double spc_seq_page_cost, + spc_random_page_cost; double T; /* Should only be applied to base relations */ @@ -571,6 +592,11 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, startup_cost += indexTotalCost; + /* Fetch estimated page costs for tablespace containing table. */ + get_tablespace_page_costs(baserel->reltablespace, + &spc_random_page_cost, + &spc_seq_page_cost); + /* * Estimate number of main-table pages fetched. */ @@ -609,17 +635,18 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel, pages_fetched = ceil(pages_fetched); /* - * For small numbers of pages we should charge random_page_cost apiece, + * For small numbers of pages we should charge spc_random_page_cost apiece, * while if nearly all the table's pages are being read, it's more - * appropriate to charge seq_page_cost apiece. The effect is nonlinear, + * appropriate to charge spc_seq_page_cost apiece. The effect is nonlinear, * too. For lack of a better idea, interpolate like this to determine the * cost per page. */ if (pages_fetched >= 2.0) - cost_per_page = random_page_cost - - (random_page_cost - seq_page_cost) * sqrt(pages_fetched / T); + cost_per_page = spc_random_page_cost - + (spc_random_page_cost - spc_seq_page_cost) + * sqrt(pages_fetched / T); else - cost_per_page = random_page_cost; + cost_per_page = spc_random_page_cost; run_cost += pages_fetched * cost_per_page; @@ -783,6 +810,7 @@ cost_tidscan(Path *path, PlannerInfo *root, QualCost tid_qual_cost; int ntuples; ListCell *l; + double spc_random_page_cost; /* Should only be applied to base relations */ Assert(baserel->relid > 0); @@ -835,8 +863,13 @@ cost_tidscan(Path *path, PlannerInfo *root, */ cost_qual_eval(&tid_qual_cost, tidquals, root); + /* fetch estimated page cost for tablespace containing table */ + get_tablespace_page_costs(baserel->reltablespace, + &spc_random_page_cost, + NULL); + /* disk costs --- assume each tuple on a different page */ - run_cost += random_page_cost * ntuples; + run_cost += spc_random_page_cost * ntuples; /* CPU costs */ startup_cost += baserel->baserestrictcost.startup + diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 16831811072..fdce5bb5a3f 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.161 2010/01/02 16:57:48 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.162 2010/01/05 21:53:58 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -91,6 +91,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, rel->min_attr = FirstLowInvalidHeapAttributeNumber + 1; rel->max_attr = RelationGetNumberOfAttributes(relation); + rel->reltablespace = RelationGetForm(relation)->reltablespace; Assert(rel->max_attr >= rel->min_attr); rel->attr_needed = (Relids *) @@ -183,6 +184,8 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, info = makeNode(IndexOptInfo); info->indexoid = index->indexrelid; + info->reltablespace = + RelationGetForm(indexRelation)->reltablespace; info->rel = rel; info->ncolumns = ncolumns = index->indnatts; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index ed906c1fedc..2ea08893f3b 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.701 2010/01/02 16:57:48 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.702 2010/01/05 21:53:58 rhaas Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -5687,6 +5687,24 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name n->newname = $6; $$ = (Node *)n; } + | ALTER TABLESPACE name SET reloptions + { + AlterTableSpaceOptionsStmt *n = + makeNode(AlterTableSpaceOptionsStmt); + n->tablespacename = $3; + n->options = $5; + n->isReset = FALSE; + $$ = (Node *)n; + } + | ALTER TABLESPACE name RESET reloptions + { + AlterTableSpaceOptionsStmt *n = + makeNode(AlterTableSpaceOptionsStmt); + n->tablespacename = $3; + n->options = $5; + n->isReset = TRUE; + $$ = (Node *)n; + } | ALTER TEXT_P SEARCH PARSER any_name RENAME TO name { RenameStmt *n = makeNode(RenameStmt); diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 3bdc6e7819c..3da89ba08a7 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.326 2010/01/02 16:57:53 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.327 2010/01/05 21:53:58 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -218,6 +218,7 @@ check_xact_readonly(Node *parsetree) case T_CreateUserMappingStmt: case T_AlterUserMappingStmt: case T_DropUserMappingStmt: + case T_AlterTableSpaceOptionsStmt: ereport(ERROR, (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION), errmsg("transaction is read-only"))); @@ -528,6 +529,10 @@ standard_ProcessUtility(Node *parsetree, DropTableSpace((DropTableSpaceStmt *) parsetree); break; + case T_AlterTableSpaceOptionsStmt: + AlterTableSpaceOptions((AlterTableSpaceOptionsStmt *) parsetree); + break; + case T_CreateFdwStmt: CreateForeignDataWrapper((CreateFdwStmt *) parsetree); break; @@ -1456,6 +1461,10 @@ CreateCommandTag(Node *parsetree) tag = "DROP TABLESPACE"; break; + case T_AlterTableSpaceOptionsStmt: + tag = "ALTER TABLESPACE"; + break; + case T_CreateFdwStmt: tag = "CREATE FOREIGN DATA WRAPPER"; break; @@ -2238,6 +2247,10 @@ GetCommandLogLevel(Node *parsetree) lev = LOGSTMT_DDL; break; + case T_AlterTableSpaceOptionsStmt: + lev = LOGSTMT_DDL; + break; + case T_CreateFdwStmt: case T_AlterFdwStmt: case T_DropFdwStmt: diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 2506eaaf82d..4bd302eab51 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.267 2010/01/04 02:44:39 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.268 2010/01/05 21:53:59 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -119,6 +119,7 @@ #include "utils/nabstime.h" #include "utils/pg_locale.h" #include "utils/selfuncs.h" +#include "utils/spccache.h" #include "utils/syscache.h" #include "utils/tqual.h" @@ -5648,6 +5649,7 @@ genericcostestimate(PlannerInfo *root, QualCost index_qual_cost; double qual_op_cost; double qual_arg_cost; + double spc_random_page_cost; List *selectivityQuals; ListCell *l; @@ -5756,6 +5758,11 @@ genericcostestimate(PlannerInfo *root, else numIndexPages = 1.0; + /* fetch estimated page cost for schema containing index */ + get_tablespace_page_costs(index->reltablespace, + &spc_random_page_cost, + NULL); + /* * Now compute the disk access costs. * @@ -5802,15 +5809,16 @@ genericcostestimate(PlannerInfo *root, * share for each outer scan. (Don't pro-rate for ScalarArrayOpExpr, * since that's internal to the indexscan.) */ - *indexTotalCost = (pages_fetched * random_page_cost) / num_outer_scans; + *indexTotalCost = (pages_fetched * spc_random_page_cost) + / num_outer_scans; } else { /* - * For a single index scan, we just charge random_page_cost per page - * touched. + * For a single index scan, we just charge spc_random_page_cost per + * page touched. */ - *indexTotalCost = numIndexPages * random_page_cost; + *indexTotalCost = numIndexPages * spc_random_page_cost; } /* @@ -5825,11 +5833,11 @@ genericcostestimate(PlannerInfo *root, * * We can deal with this by adding a very small "fudge factor" that * depends on the index size. The fudge factor used here is one - * random_page_cost per 100000 index pages, which should be small enough - * to not alter index-vs-seqscan decisions, but will prevent indexes of - * different sizes from looking exactly equally attractive. + * spc_random_page_cost per 100000 index pages, which should be small + * enough to not alter index-vs-seqscan decisions, but will prevent + * indexes of different sizes from looking exactly equally attractive. */ - *indexTotalCost += index->pages * random_page_cost / 100000.0; + *indexTotalCost += index->pages * spc_random_page_cost / 100000.0; /* * CPU cost: any complex expressions in the indexquals will need to be diff --git a/src/backend/utils/cache/Makefile b/src/backend/utils/cache/Makefile index 1766c0315f8..1a3d2cc482e 100644 --- a/src/backend/utils/cache/Makefile +++ b/src/backend/utils/cache/Makefile @@ -4,7 +4,7 @@ # Makefile for utils/cache # # IDENTIFICATION -# $PostgreSQL: pgsql/src/backend/utils/cache/Makefile,v 1.23 2008/02/19 10:30:08 petere Exp $ +# $PostgreSQL: pgsql/src/backend/utils/cache/Makefile,v 1.24 2010/01/05 21:53:59 rhaas Exp $ # #------------------------------------------------------------------------- @@ -13,6 +13,6 @@ top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global OBJS = catcache.o inval.o plancache.o relcache.o \ - syscache.o lsyscache.o typcache.o ts_cache.o + spccache.o syscache.o lsyscache.o typcache.o ts_cache.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/utils/cache/spccache.c b/src/backend/utils/cache/spccache.c new file mode 100644 index 00000000000..00629c09f06 --- /dev/null +++ b/src/backend/utils/cache/spccache.c @@ -0,0 +1,183 @@ +/*------------------------------------------------------------------------- + * + * spccache.c + * Tablespace cache management. + * + * We cache the parsed version of spcoptions for each tablespace to avoid + * needing to reparse on every lookup. Right now, there doesn't appear to + * be a measurable performance gain from doing this, but that might change + * in the future as we add more options. + * + * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * $PostgreSQL: pgsql/src/backend/utils/cache/spccache.c,v 1.1 2010/01/05 21:53:59 rhaas Exp $ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "access/reloptions.h" +#include "catalog/pg_tablespace.h" +#include "commands/tablespace.h" +#include "miscadmin.h" +#include "optimizer/cost.h" +#include "utils/catcache.h" +#include "utils/hsearch.h" +#include "utils/inval.h" +#include "utils/spccache.h" +#include "utils/syscache.h" + +static HTAB *TableSpaceCacheHash = NULL; + +typedef struct { + Oid oid; + TableSpaceOpts *opts; +} TableSpace; + +/* + * InvalidateTableSpaceCacheCallback + * Flush all cache entries when pg_tablespace is updated. + * + * When pg_tablespace is updated, we must flush the cache entry at least + * for that tablespace. Currently, we just flush them all. This is quick + * and easy and doesn't cost much, since there shouldn't be terribly many + * tablespaces, nor do we expect them to be frequently modified. + */ +static void +InvalidateTableSpaceCacheCallback(Datum arg, int cacheid, ItemPointer tuplePtr) +{ + HASH_SEQ_STATUS status; + TableSpace *spc; + + hash_seq_init(&status, TableSpaceCacheHash); + while ((spc = (TableSpace *) hash_seq_search(&status)) != NULL) + { + if (hash_search(TableSpaceCacheHash, (void *) &spc->oid, HASH_REMOVE, + NULL) == NULL) + elog(ERROR, "hash table corrupted"); + if (spc->opts) + pfree(spc->opts); + } +} + +/* + * InitializeTableSpaceCache + * Initiate the tablespace cache. + */ +static void +InitializeTableSpaceCache(void) +{ + HASHCTL ctl; + + /* Initialize the hash table. */ + MemSet(&ctl, 0, sizeof(ctl)); + ctl.keysize = sizeof(Oid); + ctl.entrysize = sizeof(TableSpace); + ctl.hash = tag_hash; + TableSpaceCacheHash = + hash_create("TableSpace cache", 16, &ctl, + HASH_ELEM | HASH_FUNCTION); + + /* Make sure we've initialized CacheMemoryContext. */ + if (!CacheMemoryContext) + CreateCacheMemoryContext(); + + /* Watch for invalidation events. */ + CacheRegisterSyscacheCallback(TABLESPACEOID, + InvalidateTableSpaceCacheCallback, + (Datum) 0); +} + +/* + * get_tablespace + * Fetch TableSpace structure for a specified table OID. + * + * Pointers returned by this function should not be stored, since a cache + * flush will invalidate them. + */ +static TableSpace * +get_tablespace(Oid spcid) +{ + HeapTuple tp; + TableSpace *spc; + bool found; + + /* + * Since spcid is always from a pg_class tuple, InvalidOid implies the + * default. + */ + if (spcid == InvalidOid) + spcid = MyDatabaseTableSpace; + + /* Find existing cache entry, or create a new one. */ + if (!TableSpaceCacheHash) + InitializeTableSpaceCache(); + spc = (TableSpace *) hash_search(TableSpaceCacheHash, (void *) &spcid, + HASH_ENTER, &found); + if (found) + return spc; + + /* + * Not found in TableSpace cache. Check catcache. If we don't find a + * valid HeapTuple, it must mean someone has managed to request tablespace + * details for a non-existent tablespace. We'll just treat that case as if + * no options were specified. + */ + tp = SearchSysCache(TABLESPACEOID, ObjectIdGetDatum(spcid), 0, 0, 0); + if (!HeapTupleIsValid(tp)) + spc->opts = NULL; + else + { + Datum datum; + bool isNull; + MemoryContext octx; + + datum = SysCacheGetAttr(TABLESPACEOID, + tp, + Anum_pg_tablespace_spcoptions, + &isNull); + if (isNull) + spc->opts = NULL; + else + { + octx = MemoryContextSwitchTo(CacheMemoryContext); + spc->opts = (TableSpaceOpts *) tablespace_reloptions(datum, false); + MemoryContextSwitchTo(octx); + } + ReleaseSysCache(tp); + } + + /* Update new TableSpace cache entry with results of option parsing. */ + return spc; +} + +/* + * get_tablespace_page_costs + * Return random and sequential page costs for a given tablespace. + */ +void +get_tablespace_page_costs(Oid spcid, double *spc_random_page_cost, + double *spc_seq_page_cost) +{ + TableSpace *spc = get_tablespace(spcid); + + Assert(spc != NULL); + + if (spc_random_page_cost) + { + if (!spc->opts || spc->opts->random_page_cost < 0) + *spc_random_page_cost = random_page_cost; + else + *spc_random_page_cost = spc->opts->random_page_cost; + } + + if (spc_seq_page_cost) + { + if (!spc->opts || spc->opts->seq_page_cost < 0) + *spc_seq_page_cost = seq_page_cost; + else + *spc_seq_page_cost = spc->opts->seq_page_cost; + } +} diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index bd747abc80c..f35712732b2 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.123 2010/01/02 16:57:56 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.124 2010/01/05 21:53:59 rhaas Exp $ * * NOTES * These routines allow the parser/planner/executor to perform @@ -43,6 +43,7 @@ #include "catalog/pg_proc.h" #include "catalog/pg_rewrite.h" #include "catalog/pg_statistic.h" +#include "catalog/pg_tablespace.h" #include "catalog/pg_ts_config.h" #include "catalog/pg_ts_config_map.h" #include "catalog/pg_ts_dict.h" @@ -609,6 +610,18 @@ static const struct cachedesc cacheinfo[] = { }, 1024 }, + {TableSpaceRelationId, /* TABLESPACEOID */ + TablespaceOidIndexId, + 0, + 1, + { + ObjectIdAttributeNumber, + 0, + 0, + 0, + }, + 16 + }, {TSConfigMapRelationId, /* TSCONFIGMAP */ TSConfigMapIndexId, 0, diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index 8ddc0384789..f46a29586cb 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.129 2010/01/02 16:57:59 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.130 2010/01/05 21:53:59 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -956,19 +956,28 @@ dumpTablespaces(PGconn *conn) * Get all tablespaces except built-in ones (which we assume are named * pg_xxx) */ - if (server_version >= 80200) + if (server_version >= 80500) res = executeQuery(conn, "SELECT spcname, " "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " "spclocation, spcacl, " + "array_to_string(spcoptions, ', ')," "pg_catalog.shobj_description(oid, 'pg_tablespace') " "FROM pg_catalog.pg_tablespace " "WHERE spcname !~ '^pg_' " "ORDER BY 1"); + else if (server_version >= 80200) + res = executeQuery(conn, "SELECT spcname, " + "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " + "spclocation, spcacl, null, " + "pg_catalog.shobj_description(oid, 'pg_tablespace'), " + "FROM pg_catalog.pg_tablespace " + "WHERE spcname !~ '^pg_' " + "ORDER BY 1"); else res = executeQuery(conn, "SELECT spcname, " "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, " "spclocation, spcacl, " - "null " + "null, null " "FROM pg_catalog.pg_tablespace " "WHERE spcname !~ '^pg_' " "ORDER BY 1"); @@ -983,7 +992,8 @@ dumpTablespaces(PGconn *conn) char *spcowner = PQgetvalue(res, i, 1); char *spclocation = PQgetvalue(res, i, 2); char *spcacl = PQgetvalue(res, i, 3); - char *spccomment = PQgetvalue(res, i, 4); + char *spcoptions = PQgetvalue(res, i, 4); + char *spccomment = PQgetvalue(res, i, 5); char *fspcname; /* needed for buildACLCommands() */ @@ -996,6 +1006,10 @@ dumpTablespaces(PGconn *conn) appendStringLiteralConn(buf, spclocation, conn); appendPQExpBuffer(buf, ";\n"); + if (spcoptions && spcoptions[0] != '\0') + appendPQExpBuffer(buf, "ALTER TABLESPACE %s SET (%s);\n", + fspcname, spcoptions); + if (!skip_acls && !buildACLCommands(fspcname, NULL, "TABLESPACE", spcacl, spcowner, "", server_version, buf)) diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h index a845c1d83cf..f7f5587f7c1 100644 --- a/src/include/access/reloptions.h +++ b/src/include/access/reloptions.h @@ -1,7 +1,8 @@ /*------------------------------------------------------------------------- * * reloptions.h - * Core support for relation options (pg_class.reloptions) + * Core support for relation and tablespace options (pg_class.reloptions + * and pg_tablespace.spcoptions) * * Note: the functions dealing with text-array reloptions values declare * them as Datum, not ArrayType *, to avoid needing to include array.h @@ -11,7 +12,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.17 2010/01/02 16:58:00 momjian Exp $ + * $PostgreSQL: pgsql/src/include/access/reloptions.h,v 1.18 2010/01/05 21:53:59 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -39,8 +40,9 @@ typedef enum relopt_kind RELOPT_KIND_HASH = (1 << 3), RELOPT_KIND_GIN = (1 << 4), RELOPT_KIND_GIST = (1 << 5), + RELOPT_KIND_TABLESPACE = (1 << 6), /* if you add a new kind, make sure you update "last_default" too */ - RELOPT_KIND_LAST_DEFAULT = RELOPT_KIND_GIST, + RELOPT_KIND_LAST_DEFAULT = RELOPT_KIND_TABLESPACE, /* some compilers treat enums as signed ints, so we can't use 1 << 31 */ RELOPT_KIND_MAX = (1 << 30) } relopt_kind; @@ -264,5 +266,6 @@ extern bytea *default_reloptions(Datum reloptions, bool validate, extern bytea *heap_reloptions(char relkind, Datum reloptions, bool validate); extern bytea *index_reloptions(RegProcedure amoptions, Datum reloptions, bool validate); +extern bytea *tablespace_reloptions(Datum reloptions, bool validate); #endif /* RELOPTIONS_H */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 49bb9198183..6e7a8c33fc4 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.566 2010/01/04 12:50:49 heikki Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.567 2010/01/05 21:53:59 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201001041 +#define CATALOG_VERSION_NO 201001051 #endif diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h index 1d15cdfa789..1c189f56510 100644 --- a/src/include/catalog/pg_tablespace.h +++ b/src/include/catalog/pg_tablespace.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_tablespace.h,v 1.14 2010/01/05 01:06:57 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_tablespace.h,v 1.15 2010/01/05 21:53:59 rhaas Exp $ * * NOTES * the genbki.pl script reads this file and generates .bki @@ -34,6 +34,7 @@ CATALOG(pg_tablespace,1213) BKI_SHARED_RELATION Oid spcowner; /* owner of tablespace */ text spclocation; /* physical location (VAR LENGTH) */ aclitem spcacl[1]; /* access permissions (VAR LENGTH) */ + text spcoptions[1]; /* per-tablespace options */ } FormData_pg_tablespace; /* ---------------- @@ -48,14 +49,15 @@ typedef FormData_pg_tablespace *Form_pg_tablespace; * ---------------- */ -#define Natts_pg_tablespace 4 +#define Natts_pg_tablespace 5 #define Anum_pg_tablespace_spcname 1 #define Anum_pg_tablespace_spcowner 2 #define Anum_pg_tablespace_spclocation 3 #define Anum_pg_tablespace_spcacl 4 +#define Anum_pg_tablespace_spcoptions 5 -DATA(insert OID = 1663 ( pg_default PGUID "" _null_ )); -DATA(insert OID = 1664 ( pg_global PGUID "" _null_ )); +DATA(insert OID = 1663 ( pg_default PGUID "" _null_ _null_ )); +DATA(insert OID = 1664 ( pg_global PGUID "" _null_ _null_ )); #define DEFAULTTABLESPACE_OID 1663 #define GLOBALTABLESPACE_OID 1664 diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h index 332bf46f0ae..9330a1f81fe 100644 --- a/src/include/commands/tablespace.h +++ b/src/include/commands/tablespace.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.21 2010/01/02 16:58:03 momjian Exp $ + * $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.22 2010/01/05 21:53:59 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -32,11 +32,17 @@ typedef struct xl_tblspc_drop_rec Oid ts_id; } xl_tblspc_drop_rec; +typedef struct TableSpaceOpts +{ + float8 random_page_cost; + float8 seq_page_cost; +} TableSpaceOpts; extern void CreateTableSpace(CreateTableSpaceStmt *stmt); extern void DropTableSpace(DropTableSpaceStmt *stmt); extern void RenameTableSpace(const char *oldname, const char *newname); extern void AlterTableSpaceOwner(const char *name, Oid newOwnerId); +extern void AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt); extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo); diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index a84de410963..e1da4954390 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.232 2010/01/02 16:58:04 momjian Exp $ + * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.233 2010/01/05 21:53:59 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -346,6 +346,7 @@ typedef enum NodeTag T_CreateUserMappingStmt, T_AlterUserMappingStmt, T_DropUserMappingStmt, + T_AlterTableSpaceOptionsStmt, /* * TAGS FOR PARSE TREE NODES (parsenodes.h) diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index d94c6f99086..18673ec30d8 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -13,7 +13,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.421 2010/01/02 16:58:04 momjian Exp $ + * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.422 2010/01/05 21:53:59 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -1477,6 +1477,14 @@ typedef struct DropTableSpaceStmt bool missing_ok; /* skip error if missing? */ } DropTableSpaceStmt; +typedef struct AlterTableSpaceOptionsStmt +{ + NodeTag type; + char *tablespacename; + List *options; + bool isReset; +} AlterTableSpaceOptionsStmt; + /* ---------------------- * Create/Drop FOREIGN DATA WRAPPER Statements * ---------------------- diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index df8f4afc8d4..fd93dfcce34 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.182 2010/01/02 16:58:07 momjian Exp $ + * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.183 2010/01/05 21:54:00 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -371,6 +371,7 @@ typedef struct RelOptInfo /* information about a base rel (not set for join rels!) */ Index relid; + Oid reltablespace; /* containing tablespace */ RTEKind rtekind; /* RELATION, SUBQUERY, or FUNCTION */ AttrNumber min_attr; /* smallest attrno of rel (often <0) */ AttrNumber max_attr; /* largest attrno of rel */ @@ -435,6 +436,7 @@ typedef struct IndexOptInfo NodeTag type; Oid indexoid; /* OID of the index relation */ + Oid reltablespace; /* tablespace of index (not table) */ RelOptInfo *rel; /* back-link to index's table */ /* statistics from pg_class */ diff --git a/src/include/utils/spccache.h b/src/include/utils/spccache.h new file mode 100644 index 00000000000..73b9f7370d9 --- /dev/null +++ b/src/include/utils/spccache.h @@ -0,0 +1,19 @@ +/*------------------------------------------------------------------------- + * + * spccache.h + * Tablespace cache. + * + * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $PostgreSQL: pgsql/src/include/utils/spccache.h,v 1.1 2010/01/05 21:54:00 rhaas Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef SPCCACHE_H +#define SPCCACHE_H + +void get_tablespace_page_costs(Oid spcid, float8 *spc_random_page_cost, + float8 *spc_seq_page_cost); + +#endif /* SPCCACHE_H */ diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h index 6b12c84da2e..8cdd7e79ee1 100644 --- a/src/include/utils/syscache.h +++ b/src/include/utils/syscache.h @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.77 2010/01/02 16:58:10 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.78 2010/01/05 21:54:00 rhaas Exp $ * *------------------------------------------------------------------------- */ @@ -71,6 +71,7 @@ enum SysCacheIdentifier RELOID, RULERELNAME, STATRELATTINH, + TABLESPACEOID, TSCONFIGMAP, TSCONFIGNAMENSP, TSCONFIGOID, diff --git a/src/test/regress/input/tablespace.source b/src/test/regress/input/tablespace.source index df5479d5893..dba96f4547f 100644 --- a/src/test/regress/input/tablespace.source +++ b/src/test/regress/input/tablespace.source @@ -1,6 +1,12 @@ -- create a tablespace we can use CREATE TABLESPACE testspace LOCATION '@testtablespace@'; +-- try setting and resetting some properties for the new tablespace +ALTER TABLESPACE testspace SET (random_page_cost = 1.0); +ALTER TABLESPACE testspace SET (some_nonexistent_parameter = true); -- fail +ALTER TABLESPACE testspace RESET (random_page_cost = 2.0); -- fail +ALTER TABLESPACE testspace RESET (random_page_cost, seq_page_cost); -- ok + -- create a schema we can use CREATE SCHEMA testschema; diff --git a/src/test/regress/output/tablespace.source b/src/test/regress/output/tablespace.source index e57ad2b2174..79b12a86986 100644 --- a/src/test/regress/output/tablespace.source +++ b/src/test/regress/output/tablespace.source @@ -1,5 +1,12 @@ -- create a tablespace we can use CREATE TABLESPACE testspace LOCATION '@testtablespace@'; +-- try setting and resetting some properties for the new tablespace +ALTER TABLESPACE testspace SET (random_page_cost = 1.0); +ALTER TABLESPACE testspace SET (some_nonexistent_parameter = true); -- fail +ERROR: unrecognized parameter "some_nonexistent_parameter" +ALTER TABLESPACE testspace RESET (random_page_cost = 2.0); -- fail +ERROR: RESET must not include values for parameters +ALTER TABLESPACE testspace RESET (random_page_cost, seq_page_cost); -- ok -- create a schema we can use CREATE SCHEMA testschema; -- try a table |