2 * contrib/hstore/hstore_compat.c
4 * Notes on old/new hstore format disambiguation.
6 * There are three formats to consider:
7 * 1) old contrib/hstore (referred to as hstore-old)
8 * 2) prerelease pgfoundry hstore
9 * 3) new contrib/hstore
11 * (2) and (3) are identical except for the HS_FLAG_NEWVERSION
12 * bit, which is set in (3) but not (2).
14 * Values that are already in format (3), or which are
15 * unambiguously in format (2), are handled by the first
16 * "return immediately" test in hstoreUpgrade().
18 * To stress a point: we ONLY get here with possibly-ambiguous
19 * values if we're doing some sort of in-place migration from an
20 * old prerelease pgfoundry hstore-new; and we explicitly don't
21 * support that without fixing up any potentially padded values
22 * first. Most of the code here is serious overkill, but the
23 * performance penalty isn't serious (especially compared to the
24 * palloc() that we have to do anyway) and the belt-and-braces
25 * validity checks provide some reassurance. (If for some reason
26 * we get a value that would have worked on the old code, but
27 * which would be botched by the conversion code, the validity
28 * checks will fail it first so we get an error rather than bad
31 * Note also that empty hstores are the same in (2) and (3), so
32 * there are some special-case paths for them.
34 * We tell the difference between formats (2) and (3) as follows (but
35 * note that there are some edge cases where we can't tell; see
36 * comments in hstoreUpgrade):
38 * First, since there must be at least one entry, we look at
39 * how the bits line up. The new format looks like:
41 * 10kkkkkkkkkkkkkkkkkkkkkkkkkkkkkk (k..k = keylen)
42 * 0nvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv (v..v = keylen+vallen)
44 * The old format looks like one of these, depending on endianness
45 * and bitfield layout: (k..k = keylen, v..v = vallen, p..p = pos,
48 * kkkkkkkkkkkkkkkkvvvvvvvvvvvvvvvv
49 * nppppppppppppppppppppppppppppppp
51 * kkkkkkkkkkkkkkkkvvvvvvvvvvvvvvvv
52 * pppppppppppppppppppppppppppppppn
54 * vvvvvvvvvvvvvvvvkkkkkkkkkkkkkkkk
55 * nppppppppppppppppppppppppppppppp
57 * vvvvvvvvvvvvvvvvkkkkkkkkkkkkkkkk
58 * pppppppppppppppppppppppppppppppn (usual i386 format)
60 * If the entry is in old format, for the first entry "pos" must be 0.
61 * We can obviously see that either keylen or vallen must be >32768
62 * for there to be any ambiguity (which is why lengths less than that
63 * are fasttracked in hstore.h) Since "pos"==0, the "v" field in the
64 * new-format interpretation can only be 0 or 1, which constrains all
65 * but three bits of the old-format's k and v fields. But in addition
66 * to all of this, the data length implied by the keylen and vallen
67 * must fit in the varlena size. So the only ambiguous edge case for
68 * hstores with only one entry occurs between a new-format entry with
69 * an excess (~32k) of padding, and an old-format entry. But we know
70 * which format to use in that case based on how we were compiled, so
71 * no actual data corruption can occur.
73 * If there is more than one entry, the requirement that keys do not
74 * decrease in length, and that positions increase contiguously, and
75 * that the end of the data not be beyond the end of the varlena
76 * itself, disambiguates in almost all other cases. There is a small
77 * set of ambiguous cases which could occur if the old-format value
78 * has a large excess of padding and just the right pattern of key
79 * sizes, but these are also handled based on how we were compiled.
81 * The otherwise undocumented function hstore_version_diag is provided
82 * for testing purposes.
90 * This is the structure used for entries in the old contrib/hstore
91 * implementation. Notice that this is the same size as the new entry
92 * (two 32-bit words per key/value pair) and that the header is the
93 * same, so the old and new versions of ARRPTR, STRPTR, CALCDATASIZE
94 * etc. are compatible.
96 * If the above statement isn't true on some bizarre platform, we're
97 * a bit hosed (see StaticAssertStmt in hstoreValidOldFormat).
113 * Validity test for a new-format hstore.
115 * 1 = valid but with "slop" in the length
123 int buflen = (count) ?
HSE_ENDPOS(entries[2 * (count) - 1]) : 0;
139 /* entry position must be nondecreasing */
141 for (
i = 1;
i < 2 * count; ++
i)
148 /* key length must be nondecreasing and keys must not be null */
150 for (
i = 1;
i < count; ++
i)
165 * Validity test for an old-format hstore.
167 * 1 = valid but with "slop" in the length
173 int count = hs->
size_;
182 /* New format uses an HEntry for key and another for value */
184 "old hstore format is not upward-compatible");
189 if (count > 0xFFFFFFF)
195 if (entries[0].pos != 0)
198 /* key length must be nondecreasing */
200 for (
i = 1;
i < count; ++
i)
202 if (entries[
i].keylen < entries[
i - 1].keylen)
207 * entry position must be strictly increasing, except for the first entry
208 * (which can be ""=>"" and thus zero-length); and all entries must be
209 * properly contiguous
212 for (
i = 0;
i < count; ++
i)
214 if (entries[
i].pos != lastpos)
217 + ((entries[
i].
valisnull) ? 0 : entries[
i].vallen));
233 * hstoreUpgrade: PG_DETOAST_DATUM plus support for conversion of old hstores
242 /* Return immediately if no conversion needed */
246 /* Do we have a writable copy? If not, make one. */
250 if (hs->
size_ == 0 ||
261 if (!valid_old || hs->
size_ == 0)
266 * force the "new version" flag and the correct varlena length.
274 elog(
ERROR,
"invalid hstore value found");
279 * this is the tricky edge case. It is only possible in some quite extreme
280 * cases (the hstore must have had a lot of wasted padding space at the
281 * end). But the only way a "new" hstore value could get here is if we're
282 * upgrading in place from a pre-release version of hstore-new (NOT
283 * contrib/hstore), so we work off the following assumptions: 1. If you're
284 * moving from old contrib/hstore to hstore-new, you're required to fix up
285 * any potential conflicts first, e.g. by running ALTER TABLE ... USING
286 * col::text::hstore; on all hstore columns before upgrading. 2. If you're
287 * moving from old contrib/hstore to new contrib/hstore, then "new" values
288 * are impossible here 3. If you're moving from pre-release hstore-new to
289 * hstore-new, then "old" values are impossible here 4. If you're moving
290 * from pre-release hstore-new to new contrib/hstore, you're not doing so
291 * as an in-place upgrade, so there is no issue So the upshot of all this
292 * is that we can treat all the edge cases as "new" if we're being built
293 * as hstore-new, and "old" if we're being built as contrib/hstore.
295 * XXX the WARNING can probably be downgraded to DEBUG1 once this has been
296 * beta-tested. But for now, it would be very useful to know if anyone can
297 * actually reach this case in a non-contrived setting.
302#ifdef HSTORE_IS_HSTORE_NEW
303 elog(
WARNING,
"ambiguous hstore value resolved as hstore-new");
306 * force the "new version" flag and the correct varlena length.
312 elog(
WARNING,
"ambiguous hstore value resolved as hstore-old");
317 * must have an old-style value. Overwrite it in place as a new-style one.
320 int count = hs->
size_;
325 for (
i = 0;
i < count; ++
i)
#define StaticAssertStmt(condition, errmessage)
#define PG_DETOAST_DATUM_COPY(datum)
#define PG_GETARG_DATUM(n)
#define PG_DETOAST_DATUM(datum)
#define PG_RETURN_INT32(x)
#define CALCDATASIZE(x, lenstr)
#define HS_FIXSIZE(hsp_, count_)
#define HS_FLAG_NEWVERSION
#define HSTORE_KEYLEN(arr_, i_)
#define HS_SETCOUNT(hsp_, c_)
PG_FUNCTION_INFO_V1(hstore_version_diag)
static int hstoreValidOldFormat(HStore *hs)
HStore * hstoreUpgrade(Datum orig)
Datum hstore_version_diag(PG_FUNCTION_ARGS)
static int hstoreValidNewFormat(HStore *hs)
static Pointer DatumGetPointer(Datum X)
static Size VARSIZE(const void *PTR)