diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 60 | ||||
-rw-r--r-- | src/backend/utils/cache/relcache.c | 171 |
2 files changed, 174 insertions, 57 deletions
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 182d3cf1072..2ddbb64763c 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -2,7 +2,7 @@ * ruleutils.c - Functions to convert stored expressions/querytrees * back to source text * - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.224 2006/06/16 18:42:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.225 2006/07/02 02:23:21 momjian Exp $ **********************************************************************/ #include "postgres.h" @@ -187,6 +187,7 @@ static char *generate_relation_name(Oid relid); static char *generate_function_name(Oid funcid, int nargs, Oid *argtypes); static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2); static text *string_to_text(char *str); +static char *flatten_reloptions(Oid relid); #define only_marker(rte) ((rte)->inh ? "" : "ONLY ") @@ -756,9 +757,20 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags) } if (!colno) - { appendStringInfoChar(&buf, ')'); + /* + * If it has options, append "WITH (options)" + */ + str = flatten_reloptions(indexrelid); + if (str) + { + appendStringInfo(&buf, " WITH (%s)", str); + pfree(str); + } + + if (!colno) + { /* * If it's a partial index, decompile and append the predicate */ @@ -1004,6 +1016,17 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand, decompile_column_index_array(val, conForm->conrelid, &buf); appendStringInfo(&buf, ")"); + + if (fullCommand && OidIsValid(conForm->conrelid)) + { + char *options = flatten_reloptions(conForm->conrelid); + if (options) + { + appendStringInfo(&buf, " WITH (%s)", options); + pfree(options); + } + } + break; } case CONSTRAINT_CHECK: @@ -4913,3 +4936,36 @@ string_to_text(char *str) return result; } + +static char * +flatten_reloptions(Oid relid) +{ + HeapTuple tuple; + char *result = NULL; + + tuple = SearchSysCache(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); + if (tuple) + { + bool isnull; + Datum reloptions; + reloptions = SysCacheGetAttr(RELOID, tuple, + Anum_pg_class_reloptions, &isnull); + if (!isnull) + { + Datum sep, + txt; + sep = DirectFunctionCall1(textin, CStringGetDatum(", ")); + /* + * OID 395 = array_to_text. + * DirectFunctionCall2(array_to_text) is not available here. + */ + txt = OidFunctionCall2(395, reloptions, sep); + result = DatumGetCString(DirectFunctionCall1(textout, txt)); + } + ReleaseSysCache(tuple); + } + + return result; +} diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 82de42020e8..50edf7691a4 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.242 2006/06/16 18:42:22 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.243 2006/07/02 02:23:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -47,6 +47,8 @@ #include "catalog/pg_proc.h" #include "catalog/pg_rewrite.h" #include "catalog/pg_type.h" +#include "catalog/heap.h" +#include "catalog/index.h" #include "commands/trigger.h" #include "miscadmin.h" #include "optimizer/clauses.h" @@ -54,6 +56,7 @@ #include "optimizer/prep.h" #include "storage/fd.h" #include "storage/smgr.h" +#include "utils/array.h" #include "utils/builtins.h" #include "utils/catcache.h" #include "utils/fmgroids.h" @@ -71,7 +74,7 @@ */ #define RELCACHE_INIT_FILENAME "pg_internal.init" -#define RELCACHE_INIT_FILEMAGIC 0x573262 /* version ID value */ +#define RELCACHE_INIT_FILEMAGIC 0x573263 /* version ID value */ /* * hardcoded tuple descriptors. see include/catalog/pg_attribute.h @@ -183,6 +186,7 @@ static void RelationClearRelation(Relation relation, bool rebuild); static void RelationReloadClassinfo(Relation relation); static void RelationFlushRelation(Relation relation); static bool load_relcache_init_file(void); +static void write_item(const void *data, Size len, FILE *fp); static void write_relcache_init_file(void); static void formrdesc(const char *relationName, Oid relationReltype, @@ -206,6 +210,7 @@ static void IndexSupportInitialize(oidvector *indclass, static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numStrats, StrategyNumber numSupport); +static void RelationParseOptions(Relation relation, HeapTuple tuple); /* @@ -309,6 +314,7 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp) /* initialize relation tuple form */ relation->rd_rel = relationForm; + relation->rd_options = NULL; /* and allocate attribute tuple form storage */ relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts, @@ -322,6 +328,53 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp) } /* + * RelationParseOptions + */ +static void +RelationParseOptions(Relation relation, HeapTuple tuple) +{ + ArrayType *options; + + Assert(tuple); + + switch (relation->rd_rel->relkind) + { + case RELKIND_RELATION: + case RELKIND_TOASTVALUE: + case RELKIND_UNCATALOGED: + case RELKIND_INDEX: + break; + default: + /* other relation should not have options. */ + relation->rd_options = NULL; + return; + } + + /* SysCacheGetAttr is not available here. */ + if (heap_attisnull(tuple, Anum_pg_class_reloptions)) + options = NULL; + else + options = (ArrayType *) ((Form_pg_class) GETSTRUCT(tuple))->reloptions; + + switch (relation->rd_rel->relkind) + { + case RELKIND_RELATION: + case RELKIND_TOASTVALUE: + case RELKIND_UNCATALOGED: + relation->rd_options = heap_option( + relation->rd_rel->relkind, options); + break; + case RELKIND_INDEX: + relation->rd_options = index_option( + relation->rd_am->amoption, options); + break; + default: + /* should not happen */ + break; + } +} + +/* * RelationBuildTupleDesc * * Form the relation's tuple descriptor from information in @@ -726,11 +779,6 @@ RelationBuildDesc(Oid targetRelId, Relation oldrelation) relation = AllocateRelationDesc(oldrelation, relp); /* - * now we can free the memory allocated for pg_class_tuple - */ - heap_freetuple(pg_class_tuple); - - /* * initialize the relation's relation id (relation->rd_id) */ RelationGetRelid(relation) = relid; @@ -785,6 +833,14 @@ RelationBuildDesc(Oid targetRelId, Relation oldrelation) /* make sure relation is marked as having no open file yet */ relation->rd_smgr = NULL; + /* Build AM-specific fields. */ + RelationParseOptions(relation, pg_class_tuple); + + /* + * now we can free the memory allocated for pg_class_tuple + */ + heap_freetuple(pg_class_tuple); + /* * Insert newly created relation into relcache hash tables. */ @@ -1210,6 +1266,7 @@ formrdesc(const char *relationName, Oid relationReltype, * data from pg_class and replace what we've done here. */ relation->rd_rel = (Form_pg_class) palloc0(CLASS_TUPLE_SIZE); + relation->rd_options = NULL; namestrcpy(&relation->rd_rel->relname, relationName); relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE; @@ -1298,6 +1355,11 @@ formrdesc(const char *relationName, Oid relationReltype, } /* + * initialize the rd_options field to default value + */ + relation->rd_options = heap_option(RELKIND_RELATION, NULL); + + /* * add new reldesc to relcache */ RelationCacheInsert(relation); @@ -1475,6 +1537,9 @@ RelationReloadClassinfo(Relation relation) RelationGetRelid(relation)); relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); memcpy(relation->rd_rel, relp, CLASS_TUPLE_SIZE); + if (relation->rd_options) + pfree(relation->rd_options); + RelationParseOptions(relation, pg_class_tuple); heap_freetuple(pg_class_tuple); /* We must recalculate physical address in case it changed */ RelationInitPhysicalAddr(relation); @@ -1581,6 +1646,8 @@ RelationClearRelation(Relation relation, bool rebuild) pfree(relation->rd_am); if (relation->rd_rel) pfree(relation->rd_rel); + if (relation->rd_options) + pfree(relation->rd_options); list_free(relation->rd_indexlist); if (relation->rd_indexcxt) MemoryContextDelete(relation->rd_indexcxt); @@ -2111,6 +2178,7 @@ RelationBuildLocalRelation(const char *relname, * initialize relation tuple form (caller may add/override data later) */ rel->rd_rel = (Form_pg_class) palloc0(CLASS_TUPLE_SIZE); + rel->rd_options = NULL; namestrcpy(&rel->rd_rel->relname, relname); rel->rd_rel->relnamespace = relnamespace; @@ -3032,6 +3100,22 @@ load_relcache_init_file(void) has_not_null |= rel->rd_att->attrs[i]->attnotnull; } + /* next read the access method specific field */ + if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len)) + goto read_failed; + if (len > 0) + { + rel->rd_options = palloc(len); + if ((nread = fread(rel->rd_options, 1, len, fp)) != len) + goto read_failed; + if (len != VARATT_SIZE(rel->rd_options)) + goto read_failed; + } + else + { + rel->rd_options = NULL; + } + /* mark not-null status */ if (has_not_null) { @@ -3215,6 +3299,15 @@ read_failed: return false; } +static void +write_item(const void *data, Size len, FILE *fp) +{ + if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len)) + elog(FATAL, "could not write init file"); + if (fwrite(data, 1, len, fp) != len) + elog(FATAL, "could not write init file"); +} + /* * Write out a new initialization file with the current contents * of the relcache. @@ -3277,39 +3370,24 @@ write_relcache_init_file(void) { Relation rel = idhentry->reldesc; Form_pg_class relform = rel->rd_rel; - Size len; - - /* - * first write the relcache entry proper - */ - len = sizeof(RelationData); - /* first, write the relation descriptor length */ - if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len)) - elog(FATAL, "could not write init file"); - - /* next, write out the Relation structure */ - if (fwrite(rel, 1, len, fp) != len) - elog(FATAL, "could not write init file"); + /* first write the relcache entry proper */ + write_item(rel, sizeof(RelationData), fp); /* next write the relation tuple form */ - len = sizeof(FormData_pg_class); - if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len)) - elog(FATAL, "could not write init file"); - - if (fwrite(relform, 1, len, fp) != len) - elog(FATAL, "could not write init file"); + write_item(relform, CLASS_TUPLE_SIZE, fp); /* next, do all the attribute tuple form data entries */ for (i = 0; i < relform->relnatts; i++) { - len = ATTRIBUTE_TUPLE_SIZE; - if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len)) - elog(FATAL, "could not write init file"); - if (fwrite(rel->rd_att->attrs[i], 1, len, fp) != len) - elog(FATAL, "could not write init file"); + write_item(rel->rd_att->attrs[i], + ATTRIBUTE_TUPLE_SIZE, fp); } + /* next, do the access method specific field */ + write_item(rel->rd_options, + (rel->rd_options ? VARATT_SIZE(rel->rd_options) : 0), fp); + /* If it's an index, there's more to do */ if (rel->rd_rel->relkind == RELKIND_INDEX) { @@ -3317,36 +3395,19 @@ write_relcache_init_file(void) /* write the pg_index tuple */ /* we assume this was created by heap_copytuple! */ - len = HEAPTUPLESIZE + rel->rd_indextuple->t_len; - if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len)) - elog(FATAL, "could not write init file"); - - if (fwrite(rel->rd_indextuple, 1, len, fp) != len) - elog(FATAL, "could not write init file"); + write_item(rel->rd_indextuple, + HEAPTUPLESIZE + rel->rd_indextuple->t_len, fp); /* next, write the access method tuple form */ - len = sizeof(FormData_pg_am); - if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len)) - elog(FATAL, "could not write init file"); - - if (fwrite(am, 1, len, fp) != len) - elog(FATAL, "could not write init file"); + write_item(am, sizeof(FormData_pg_am), fp); /* next, write the vector of operator OIDs */ - len = relform->relnatts * (am->amstrategies * sizeof(Oid)); - if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len)) - elog(FATAL, "could not write init file"); - - if (fwrite(rel->rd_operator, 1, len, fp) != len) - elog(FATAL, "could not write init file"); + write_item(rel->rd_operator, relform->relnatts * + (am->amstrategies * sizeof(Oid)), fp); /* finally, write the vector of support procedures */ - len = relform->relnatts * (am->amsupport * sizeof(RegProcedure)); - if (fwrite(&len, 1, sizeof(len), fp) != sizeof(len)) - elog(FATAL, "could not write init file"); - - if (fwrite(rel->rd_support, 1, len, fp) != len) - elog(FATAL, "could not write init file"); + write_item(rel->rd_support, relform->relnatts * + (am->amsupport * sizeof(RegProcedure)), fp); } /* also make a list of their OIDs, for RelationIdIsInInitFile */ |