Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "postgres.h"
00018
00019 #include "access/reloptions.h"
00020 #include "utils/attoptcache.h"
00021 #include "utils/catcache.h"
00022 #include "utils/hsearch.h"
00023 #include "utils/inval.h"
00024 #include "utils/syscache.h"
00025
00026
00027
00028 static HTAB *AttoptCacheHash = NULL;
00029
00030
00031 typedef struct
00032 {
00033 Oid attrelid;
00034 int attnum;
00035 } AttoptCacheKey;
00036
00037 typedef struct
00038 {
00039 AttoptCacheKey key;
00040 AttributeOpts *opts;
00041 } AttoptCacheEntry;
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 static void
00054 InvalidateAttoptCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
00055 {
00056 HASH_SEQ_STATUS status;
00057 AttoptCacheEntry *attopt;
00058
00059 hash_seq_init(&status, AttoptCacheHash);
00060 while ((attopt = (AttoptCacheEntry *) hash_seq_search(&status)) != NULL)
00061 {
00062 if (attopt->opts)
00063 pfree(attopt->opts);
00064 if (hash_search(AttoptCacheHash,
00065 (void *) &attopt->key,
00066 HASH_REMOVE,
00067 NULL) == NULL)
00068 elog(ERROR, "hash table corrupted");
00069 }
00070 }
00071
00072
00073
00074
00075
00076 static void
00077 InitializeAttoptCache(void)
00078 {
00079 HASHCTL ctl;
00080
00081
00082 MemSet(&ctl, 0, sizeof(ctl));
00083 ctl.keysize = sizeof(AttoptCacheKey);
00084 ctl.entrysize = sizeof(AttoptCacheEntry);
00085 ctl.hash = tag_hash;
00086 AttoptCacheHash =
00087 hash_create("Attopt cache", 256, &ctl,
00088 HASH_ELEM | HASH_FUNCTION);
00089
00090
00091 if (!CacheMemoryContext)
00092 CreateCacheMemoryContext();
00093
00094
00095 CacheRegisterSyscacheCallback(ATTNUM,
00096 InvalidateAttoptCacheCallback,
00097 (Datum) 0);
00098 }
00099
00100
00101
00102
00103
00104 AttributeOpts *
00105 get_attribute_options(Oid attrelid, int attnum)
00106 {
00107 AttoptCacheKey key;
00108 AttoptCacheEntry *attopt;
00109 AttributeOpts *result;
00110 HeapTuple tp;
00111
00112
00113 if (!AttoptCacheHash)
00114 InitializeAttoptCache();
00115 memset(&key, 0, sizeof(key));
00116
00117 key.attrelid = attrelid;
00118 key.attnum = attnum;
00119 attopt =
00120 (AttoptCacheEntry *) hash_search(AttoptCacheHash,
00121 (void *) &key,
00122 HASH_FIND,
00123 NULL);
00124
00125
00126 if (!attopt)
00127 {
00128 AttributeOpts *opts;
00129
00130 tp = SearchSysCache2(ATTNUM,
00131 ObjectIdGetDatum(attrelid),
00132 Int16GetDatum(attnum));
00133
00134
00135
00136
00137
00138
00139 if (!HeapTupleIsValid(tp))
00140 opts = NULL;
00141 else
00142 {
00143 Datum datum;
00144 bool isNull;
00145
00146 datum = SysCacheGetAttr(ATTNUM,
00147 tp,
00148 Anum_pg_attribute_attoptions,
00149 &isNull);
00150 if (isNull)
00151 opts = NULL;
00152 else
00153 {
00154 bytea *bytea_opts = attribute_reloptions(datum, false);
00155
00156 opts = MemoryContextAlloc(CacheMemoryContext,
00157 VARSIZE(bytea_opts));
00158 memcpy(opts, bytea_opts, VARSIZE(bytea_opts));
00159 }
00160 ReleaseSysCache(tp);
00161 }
00162
00163
00164
00165
00166
00167 attopt = (AttoptCacheEntry *) hash_search(AttoptCacheHash,
00168 (void *) &key,
00169 HASH_ENTER,
00170 NULL);
00171 attopt->opts = opts;
00172 }
00173
00174
00175 if (attopt->opts == NULL)
00176 return NULL;
00177 result = palloc(VARSIZE(attopt->opts));
00178 memcpy(result, attopt->opts, VARSIZE(attopt->opts));
00179 return result;
00180 }