Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9d7726c

Browse files
committed
Recommend wrappers of PG_DETOAST_DATUM_PACKED().
When commit3e23b68 introducedsingle-byte varlena headers, its fmgr.h changes presentedPG_GETARG_TEXT_PP() and PG_GETARG_TEXT_P() as equals. Its postgres.hchanges presented PG_DETOAST_DATUM_PACKED() and VARDATA_ANY() as theexceptional case. Now, instead, firmly recommend PG_GETARG_TEXT_PP()over PG_GETARG_TEXT_P(); likewise for other ...PP() macros. This shavescycles and invites consistency of style.
1 parent944a026 commit9d7726c

File tree

6 files changed

+76
-59
lines changed

6 files changed

+76
-59
lines changed

‎doc/src/sgml/xfunc.sgml

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,18 +2388,23 @@ PG_FUNCTION_INFO_V1(copytext);
23882388
Datum
23892389
copytext(PG_FUNCTION_ARGS)
23902390
{
2391-
text *t = PG_GETARG_TEXT_P(0);
2391+
text *t = PG_GETARG_TEXT_PP(0);
2392+
23922393
/*
2393-
* VARSIZE is the total size of the struct in bytes.
2394+
* VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the
2395+
* VARHDRSZ or VARHDRSZ_SHORT of its header. Construct the copy with a
2396+
* full-length header.
23942397
*/
2395-
text *new_t = (text *) palloc(VARSIZE(t));
2396-
SET_VARSIZE(new_t, VARSIZE(t));
2398+
text *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);
2399+
SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);
2400+
23972401
/*
2398-
* VARDATA is a pointer to the data region of the struct.
2402+
* VARDATA is a pointer to the data region of the new struct. The source
2403+
* could be a short datum, so retrieve its data through VARDATA_ANY.
23992404
*/
24002405
memcpy((void *) VARDATA(new_t), /* destination */
2401-
(void *)VARDATA(t), /* source */
2402-
VARSIZE(t) - VARHDRSZ); /* how many bytes */
2406+
(void *)VARDATA_ANY(t), /* source */
2407+
VARSIZE_ANY_EXHDR(t)); /* how many bytes */
24032408
PG_RETURN_TEXT_P(new_t);
24042409
}
24052410

@@ -2408,15 +2413,16 @@ PG_FUNCTION_INFO_V1(concat_text);
24082413
Datum
24092414
concat_text(PG_FUNCTION_ARGS)
24102415
{
2411-
text *arg1 = PG_GETARG_TEXT_P(0);
2412-
text *arg2 = PG_GETARG_TEXT_P(1);
2413-
int32 new_text_size = VARSIZE(arg1) + VARSIZE(arg2) - VARHDRSZ;
2416+
text *arg1 = PG_GETARG_TEXT_PP(0);
2417+
text *arg2 = PG_GETARG_TEXT_PP(1);
2418+
int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);
2419+
int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);
2420+
int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;
24142421
text *new_text = (text *) palloc(new_text_size);
24152422

24162423
SET_VARSIZE(new_text, new_text_size);
2417-
memcpy(VARDATA(new_text), VARDATA(arg1), VARSIZE(arg1) - VARHDRSZ);
2418-
memcpy(VARDATA(new_text) + (VARSIZE(arg1) - VARHDRSZ),
2419-
VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ);
2424+
memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);
2425+
memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);
24202426
PG_RETURN_TEXT_P(new_text);
24212427
}
24222428
]]>

‎src/include/c.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -429,10 +429,11 @@ typedef struct
429429
* may be compressed or moved out-of-line. However datatype-specific routines
430430
* are mostly content to deal with de-TOASTed values only, and of course
431431
* client-side routines should never see a TOASTed value. But even in a
432-
* de-TOASTed value, beware of touching vl_len_ directly, as its representation
433-
* is no longer convenient. It's recommended that code always use the VARDATA,
434-
* VARSIZE, and SET_VARSIZE macros instead of relying on direct mentions of
435-
* the struct fields. See postgres.h for details of the TOASTed form.
432+
* de-TOASTed value, beware of touching vl_len_ directly, as its
433+
* representation is no longer convenient. It's recommended that code always
434+
* use macros VARDATA_ANY, VARSIZE_ANY, VARSIZE_ANY_EXHDR, VARDATA, VARSIZE,
435+
* and SET_VARSIZE instead of relying on direct mentions of the struct fields.
436+
* See postgres.h for details of the TOASTed form.
436437
* ----------------
437438
*/
438439
structvarlena

‎src/include/fmgr.h

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,12 @@ extern void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo,
178178
* The resulting datum can be accessed using VARSIZE_ANY() and VARDATA_ANY()
179179
* (beware of multiple evaluations in those macros!)
180180
*
181-
* WARNING: It is only safe to use pg_detoast_datum_packed() and
182-
* VARDATA_ANY() if you really don't care about the alignment. Either because
183-
* you're working with something like text where the alignment doesn't matter
184-
* or because you're not going to access its constituent parts and just use
185-
* things like memcpy on it anyways.
181+
* In consumers oblivious to data alignment, call PG_DETOAST_DATUM_PACKED(),
182+
* VARDATA_ANY(), VARSIZE_ANY() and VARSIZE_ANY_EXHDR(). Elsewhere, call
183+
* PG_DETOAST_DATUM(), VARDATA() and VARSIZE(). Directly fetching an int16,
184+
* int32 or wider field in the struct representing the datum layout requires
185+
* aligned data. memcpy() is alignment-oblivious, as are most operations on
186+
* datatypes, such as text, whose layout struct contains only char fields.
186187
*
187188
* Note: it'd be nice if these could be macros, but I see no way to do that
188189
* without evaluating the arguments multiple times, which is NOT acceptable.
@@ -243,13 +244,9 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena * datum);
243244
/* and this if you can handle 1-byte-header datums: */
244245
#definePG_GETARG_VARLENA_PP(n) PG_DETOAST_DATUM_PACKED(PG_GETARG_DATUM(n))
245246
/* DatumGetFoo macros for varlena types will typically look like this: */
246-
#defineDatumGetByteaP(X)((bytea *) PG_DETOAST_DATUM(X))
247247
#defineDatumGetByteaPP(X)((bytea *) PG_DETOAST_DATUM_PACKED(X))
248-
#defineDatumGetTextP(X)((text *) PG_DETOAST_DATUM(X))
249248
#defineDatumGetTextPP(X)((text *) PG_DETOAST_DATUM_PACKED(X))
250-
#defineDatumGetBpCharP(X)((BpChar *) PG_DETOAST_DATUM(X))
251249
#defineDatumGetBpCharPP(X)((BpChar *) PG_DETOAST_DATUM_PACKED(X))
252-
#defineDatumGetVarCharP(X)((VarChar *) PG_DETOAST_DATUM(X))
253250
#defineDatumGetVarCharPP(X)((VarChar *) PG_DETOAST_DATUM_PACKED(X))
254251
#defineDatumGetHeapTupleHeader(X)((HeapTupleHeader) PG_DETOAST_DATUM(X))
255252
/* And we also offer variants that return an OK-to-write copy */
@@ -264,13 +261,9 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena * datum);
264261
#defineDatumGetBpCharPSlice(X,m,n) ((BpChar *) PG_DETOAST_DATUM_SLICE(X,m,n))
265262
#defineDatumGetVarCharPSlice(X,m,n) ((VarChar *) PG_DETOAST_DATUM_SLICE(X,m,n))
266263
/* GETARG macros for varlena types will typically look like this: */
267-
#definePG_GETARG_BYTEA_P(n)DatumGetByteaP(PG_GETARG_DATUM(n))
268264
#definePG_GETARG_BYTEA_PP(n)DatumGetByteaPP(PG_GETARG_DATUM(n))
269-
#definePG_GETARG_TEXT_P(n)DatumGetTextP(PG_GETARG_DATUM(n))
270265
#definePG_GETARG_TEXT_PP(n)DatumGetTextPP(PG_GETARG_DATUM(n))
271-
#definePG_GETARG_BPCHAR_P(n)DatumGetBpCharP(PG_GETARG_DATUM(n))
272266
#definePG_GETARG_BPCHAR_PP(n)DatumGetBpCharPP(PG_GETARG_DATUM(n))
273-
#definePG_GETARG_VARCHAR_P(n)DatumGetVarCharP(PG_GETARG_DATUM(n))
274267
#definePG_GETARG_VARCHAR_PP(n)DatumGetVarCharPP(PG_GETARG_DATUM(n))
275268
#definePG_GETARG_HEAPTUPLEHEADER(n)DatumGetHeapTupleHeader(PG_GETARG_DATUM(n))
276269
/* And we also offer variants that return an OK-to-write copy */
@@ -284,6 +277,21 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena * datum);
284277
#definePG_GETARG_TEXT_P_SLICE(n,a,b) DatumGetTextPSlice(PG_GETARG_DATUM(n),a,b)
285278
#definePG_GETARG_BPCHAR_P_SLICE(n,a,b) DatumGetBpCharPSlice(PG_GETARG_DATUM(n),a,b)
286279
#definePG_GETARG_VARCHAR_P_SLICE(n,a,b) DatumGetVarCharPSlice(PG_GETARG_DATUM(n),a,b)
280+
/*
281+
* Obsolescent variants that guarantee INT alignment for the return value.
282+
* Few operations on these particular types need alignment, mainly operations
283+
* that cast the VARDATA pointer to a type like int16[]. Most code should use
284+
* the ...PP(X) counterpart. Nonetheless, these appear frequently in code
285+
* predating the PostgreSQL 8.3 introduction of the ...PP(X) variants.
286+
*/
287+
#defineDatumGetByteaP(X)((bytea *) PG_DETOAST_DATUM(X))
288+
#defineDatumGetTextP(X)((text *) PG_DETOAST_DATUM(X))
289+
#defineDatumGetBpCharP(X)((BpChar *) PG_DETOAST_DATUM(X))
290+
#defineDatumGetVarCharP(X)((VarChar *) PG_DETOAST_DATUM(X))
291+
#definePG_GETARG_BYTEA_P(n)DatumGetByteaP(PG_GETARG_DATUM(n))
292+
#definePG_GETARG_TEXT_P(n)DatumGetTextP(PG_GETARG_DATUM(n))
293+
#definePG_GETARG_BPCHAR_P(n)DatumGetBpCharP(PG_GETARG_DATUM(n))
294+
#definePG_GETARG_VARCHAR_P(n)DatumGetVarCharP(PG_GETARG_DATUM(n))
287295

288296
/* To return a NULL do this: */
289297
#definePG_RETURN_NULL() \

‎src/include/postgres.h

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -287,20 +287,18 @@ typedef struct
287287
/* Externally visible macros */
288288

289289
/*
290-
* VARDATA, VARSIZE, and SET_VARSIZE are the recommended API for most code
291-
* for varlena datatypes. Note that they only work on untoasted,
292-
* 4-byte-header Datums!
293-
*
294-
* Code that wants to use 1-byte-header values without detoasting should
295-
* use VARSIZE_ANY/VARSIZE_ANY_EXHDR/VARDATA_ANY. The other macros here
296-
* should usually be used only by tuple assembly/disassembly code and
297-
* code that specifically wants to work with still-toasted Datums.
298-
*
299-
* WARNING: It is only safe to use VARDATA_ANY() -- typically with
300-
* PG_DETOAST_DATUM_PACKED() -- if you really don't care about the alignment.
301-
* Either because you're working with something like text where the alignment
302-
* doesn't matter or because you're not going to access its constituent parts
303-
* and just use things like memcpy on it anyways.
290+
* In consumers oblivious to data alignment, call PG_DETOAST_DATUM_PACKED(),
291+
* VARDATA_ANY(), VARSIZE_ANY() and VARSIZE_ANY_EXHDR(). Elsewhere, call
292+
* PG_DETOAST_DATUM(), VARDATA() and VARSIZE(). Directly fetching an int16,
293+
* int32 or wider field in the struct representing the datum layout requires
294+
* aligned data. memcpy() is alignment-oblivious, as are most operations on
295+
* datatypes, such as text, whose layout struct contains only char fields.
296+
*
297+
* Code assembling a new datum should call VARDATA() and SET_VARSIZE().
298+
* (Datums begin life untoasted.)
299+
*
300+
* Other macros here should usually be used only by tuple assembly/disassembly
301+
* code and code that specifically wants to work with still-toasted Datums.
304302
*/
305303
#defineVARDATA(PTR)VARDATA_4B(PTR)
306304
#defineVARSIZE(PTR)VARSIZE_4B(PTR)

‎src/include/utils/inet.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,13 @@ typedef struct macaddr
104104
/*
105105
* fmgr interface macros
106106
*/
107-
#defineDatumGetInetP(X)((inet *) PG_DETOAST_DATUM(X))
108107
#defineDatumGetInetPP(X)((inet *) PG_DETOAST_DATUM_PACKED(X))
109108
#defineInetPGetDatum(X)PointerGetDatum(X)
110-
#definePG_GETARG_INET_P(n) DatumGetInetP(PG_GETARG_DATUM(n))
111109
#definePG_GETARG_INET_PP(n) DatumGetInetPP(PG_GETARG_DATUM(n))
112110
#definePG_RETURN_INET_P(x) return InetPGetDatum(x)
111+
/* obsolescent variants */
112+
#defineDatumGetInetP(X)((inet *) PG_DETOAST_DATUM(X))
113+
#definePG_GETARG_INET_P(n) DatumGetInetP(PG_GETARG_DATUM(n))
113114
/* macaddr is a fixed-length pass-by-reference datatype */
114115
#defineDatumGetMacaddrP(X) ((macaddr *) DatumGetPointer(X))
115116
#defineMacaddrPGetDatum(X) PointerGetDatum(X)

‎src/tutorial/funcs_new.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,21 +66,24 @@ PG_FUNCTION_INFO_V1(copytext);
6666
Datum
6767
copytext(PG_FUNCTION_ARGS)
6868
{
69-
text*t=PG_GETARG_TEXT_P(0);
69+
text*t=PG_GETARG_TEXT_PP(0);
7070

7171
/*
72-
* VARSIZE is the total size of the struct in bytes.
72+
* VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the
73+
* VARHDRSZ or VARHDRSZ_SHORT of its header. Construct the copy with a
74+
* full-length header.
7375
*/
74-
text*new_t= (text*)palloc(VARSIZE(t));
76+
text*new_t= (text*)palloc(VARSIZE_ANY_EXHDR(t)+VARHDRSZ);
7577

76-
SET_VARSIZE(new_t,VARSIZE(t));
78+
SET_VARSIZE(new_t,VARSIZE_ANY_EXHDR(t)+VARHDRSZ);
7779

7880
/*
79-
* VARDATA is a pointer to the data region of the struct.
81+
* VARDATA is a pointer to the data region of the new struct. The source
82+
* could be a short datum, so retrieve its data through VARDATA_ANY.
8083
*/
8184
memcpy((void*)VARDATA(new_t),/* destination */
82-
(void*)VARDATA(t),/* source */
83-
VARSIZE(t)-VARHDRSZ);/* how many bytes */
85+
(void*)VARDATA_ANY(t),/* source */
86+
VARSIZE_ANY_EXHDR(t));/* how many bytes */
8487
PG_RETURN_TEXT_P(new_t);
8588
}
8689

@@ -89,16 +92,16 @@ PG_FUNCTION_INFO_V1(concat_text);
8992
Datum
9093
concat_text(PG_FUNCTION_ARGS)
9194
{
92-
text*arg1=PG_GETARG_TEXT_P(0);
93-
text*arg2=PG_GETARG_TEXT_P(1);
94-
int32arg1_size=VARSIZE(arg1)-VARHDRSZ;
95-
int32arg2_size=VARSIZE(arg2)-VARHDRSZ;
95+
text*arg1=PG_GETARG_TEXT_PP(0);
96+
text*arg2=PG_GETARG_TEXT_PP(1);
97+
int32arg1_size=VARSIZE_ANY_EXHDR(arg1);
98+
int32arg2_size=VARSIZE_ANY_EXHDR(arg2);
9699
int32new_text_size=arg1_size+arg2_size+VARHDRSZ;
97100
text*new_text= (text*)palloc(new_text_size);
98101

99102
SET_VARSIZE(new_text,new_text_size);
100-
memcpy(VARDATA(new_text),VARDATA(arg1),arg1_size);
101-
memcpy(VARDATA(new_text)+arg1_size,VARDATA(arg2),arg2_size);
103+
memcpy(VARDATA(new_text),VARDATA_ANY(arg1),arg1_size);
104+
memcpy(VARDATA(new_text)+arg1_size,VARDATA_ANY(arg2),arg2_size);
102105
PG_RETURN_TEXT_P(new_text);
103106
}
104107

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp