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

Commit23d0b48

Browse files
committed
Remove hardcoded hash opclass function signature exceptions
hashvalidate(), which validates the signatures of support functionsfor the hash AM, contained several hardcoded exceptions. For example,hash/date_ops support function 1 was hashint4(), which wouldordinarily fail validation because the function argument is int4, notdate. But this works internally because int4 and date are of the samesize. There are several more exceptions like this that happen to workand were allowed historically but would now fail the functionsignature validation.This patch removes those exceptions by providing new support functionsthat have the proper declared signatures. They internally share mostof the code with the "wrong" functions they replace, so the behavioris still the same.With the exceptions gone, hashvalidate() is now simplified and reliesfully on check_amproc_signature().hashvarlena() and hashvarlenaextended() are kept in pg_proc.datbecause some extensions currently use them to build hash functions fortheir own types, and we need to keep exposing these functions as"LANGUAGE internal" functions for that to continue to work.Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>Discussion:https://www.postgresql.org/message-id/flat/29c3b746-69e7-482a-b37c-dbbf7e5b009b@eisentraut.org
1 parent5bb9ba2 commit23d0b48

File tree

9 files changed

+174
-122
lines changed

9 files changed

+174
-122
lines changed

‎src/backend/access/hash/hashfunc.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,11 @@ hashtextextended(PG_FUNCTION_ARGS)
376376
/*
377377
* hashvarlena() can be used for any varlena datatype in which there are
378378
* no non-significant bits, ie, distinct bitpatterns never compare as equal.
379+
*
380+
* (However, you need to define an SQL-level wrapper function around it with
381+
* the concrete input data type; otherwise hashvalidate() won't accept it.
382+
* Moreover, at least for built-in types, a C-level wrapper function is also
383+
* recommended; otherwise, the opr_sanity test will get upset.)
379384
*/
380385
Datum
381386
hashvarlena(PG_FUNCTION_ARGS)
@@ -406,3 +411,15 @@ hashvarlenaextended(PG_FUNCTION_ARGS)
406411

407412
returnresult;
408413
}
414+
415+
Datum
416+
hashbytea(PG_FUNCTION_ARGS)
417+
{
418+
returnhashvarlena(fcinfo);
419+
}
420+
421+
Datum
422+
hashbyteaextended(PG_FUNCTION_ARGS)
423+
{
424+
returnhashvarlenaextended(fcinfo);
425+
}

‎src/backend/access/hash/hashvalidate.c

Lines changed: 25 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,13 @@
2222
#include"catalog/pg_amproc.h"
2323
#include"catalog/pg_opclass.h"
2424
#include"catalog/pg_opfamily.h"
25-
#include"catalog/pg_proc.h"
2625
#include"catalog/pg_type.h"
27-
#include"parser/parse_coerce.h"
2826
#include"utils/builtins.h"
29-
#include"utils/fmgroids.h"
3027
#include"utils/lsyscache.h"
3128
#include"utils/regproc.h"
3229
#include"utils/syscache.h"
3330

3431

35-
staticboolcheck_hash_func_signature(Oidfuncid,int16amprocnum,Oidargtype);
36-
37-
3832
/*
3933
* Validator for a hash opclass.
4034
*
@@ -90,6 +84,7 @@ hashvalidate(Oid opclassoid)
9084
{
9185
HeapTupleproctup=&proclist->members[i]->tuple;
9286
Form_pg_amprocprocform= (Form_pg_amproc)GETSTRUCT(proctup);
87+
boolok;
9388

9489
/*
9590
* All hash functions should be registered with matching left/right
@@ -109,29 +104,15 @@ hashvalidate(Oid opclassoid)
109104
switch (procform->amprocnum)
110105
{
111106
caseHASHSTANDARD_PROC:
107+
ok=check_amproc_signature(procform->amproc,INT4OID, true,
108+
1,1,procform->amproclefttype);
109+
break;
112110
caseHASHEXTENDED_PROC:
113-
if (!check_hash_func_signature(procform->amproc,procform->amprocnum,
114-
procform->amproclefttype))
115-
{
116-
ereport(INFO,
117-
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
118-
errmsg("operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d",
119-
opfamilyname,"hash",
120-
format_procedure(procform->amproc),
121-
procform->amprocnum)));
122-
result= false;
123-
}
124-
else
125-
{
126-
/* Remember which types we can hash */
127-
hashabletypes=
128-
list_append_unique_oid(hashabletypes,
129-
procform->amproclefttype);
130-
}
111+
ok=check_amproc_signature(procform->amproc,INT8OID, true,
112+
2,2,procform->amproclefttype,INT8OID);
131113
break;
132114
caseHASHOPTIONS_PROC:
133-
if (!check_amoptsproc_signature(procform->amproc))
134-
result= false;
115+
ok=check_amoptsproc_signature(procform->amproc);
135116
break;
136117
default:
137118
ereport(INFO,
@@ -141,7 +122,24 @@ hashvalidate(Oid opclassoid)
141122
format_procedure(procform->amproc),
142123
procform->amprocnum)));
143124
result= false;
144-
break;
125+
continue;/* don't want additional message */
126+
}
127+
128+
if (!ok)
129+
{
130+
ereport(INFO,
131+
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
132+
errmsg("operator family \"%s\" of access method %s contains function %s with wrong signature for support number %d",
133+
opfamilyname,"hash",
134+
format_procedure(procform->amproc),
135+
procform->amprocnum)));
136+
result= false;
137+
}
138+
139+
/* Remember which types we can hash */
140+
if (ok&& (procform->amprocnum==HASHSTANDARD_PROC||procform->amprocnum==HASHEXTENDED_PROC))
141+
{
142+
hashabletypes=list_append_unique_oid(hashabletypes,procform->amproclefttype);
145143
}
146144
}
147145

@@ -267,84 +265,6 @@ hashvalidate(Oid opclassoid)
267265
}
268266

269267

270-
/*
271-
* We need a custom version of check_amproc_signature because of assorted
272-
* hacks in the core hash opclass definitions.
273-
*/
274-
staticbool
275-
check_hash_func_signature(Oidfuncid,int16amprocnum,Oidargtype)
276-
{
277-
boolresult= true;
278-
Oidrestype;
279-
int16nargs;
280-
HeapTupletp;
281-
Form_pg_procprocform;
282-
283-
switch (amprocnum)
284-
{
285-
caseHASHSTANDARD_PROC:
286-
restype=INT4OID;
287-
nargs=1;
288-
break;
289-
290-
caseHASHEXTENDED_PROC:
291-
restype=INT8OID;
292-
nargs=2;
293-
break;
294-
295-
default:
296-
elog(ERROR,"invalid amprocnum");
297-
}
298-
299-
tp=SearchSysCache1(PROCOID,ObjectIdGetDatum(funcid));
300-
if (!HeapTupleIsValid(tp))
301-
elog(ERROR,"cache lookup failed for function %u",funcid);
302-
procform= (Form_pg_proc)GETSTRUCT(tp);
303-
304-
if (procform->prorettype!=restype||procform->proretset||
305-
procform->pronargs!=nargs)
306-
result= false;
307-
308-
if (!IsBinaryCoercible(argtype,procform->proargtypes.values[0]))
309-
{
310-
/*
311-
* Some of the built-in hash opclasses cheat by using hash functions
312-
* that are different from but physically compatible with the opclass
313-
* datatype. In some of these cases, even a "binary coercible" check
314-
* fails because there's no relevant cast. For the moment, fix it by
315-
* having a list of allowed cases. Test the specific function
316-
* identity, not just its input type, because hashvarlena() takes
317-
* INTERNAL and allowing any such function seems too scary.
318-
*/
319-
if ((funcid==F_HASHINT4||funcid==F_HASHINT4EXTENDED)&&
320-
(argtype==DATEOID||
321-
argtype==XIDOID||argtype==CIDOID))
322-
/* okay, allowed use of hashint4() */ ;
323-
elseif ((funcid==F_HASHINT8||funcid==F_HASHINT8EXTENDED)&&
324-
(argtype==XID8OID))
325-
/* okay, allowed use of hashint8() */ ;
326-
elseif ((funcid==F_TIMESTAMP_HASH||
327-
funcid==F_TIMESTAMP_HASH_EXTENDED)&&
328-
argtype==TIMESTAMPTZOID)
329-
/* okay, allowed use of timestamp_hash() */ ;
330-
elseif ((funcid==F_HASHCHAR||funcid==F_HASHCHAREXTENDED)&&
331-
argtype==BOOLOID)
332-
/* okay, allowed use of hashchar() */ ;
333-
elseif ((funcid==F_HASHVARLENA||funcid==F_HASHVARLENAEXTENDED)&&
334-
argtype==BYTEAOID)
335-
/* okay, allowed use of hashvarlena() */ ;
336-
else
337-
result= false;
338-
}
339-
340-
/* If function takes a second argument, it must be for a 64-bit salt. */
341-
if (nargs==2&&procform->proargtypes.values[1]!=INT8OID)
342-
result= false;
343-
344-
ReleaseSysCache(tp);
345-
returnresult;
346-
}
347-
348268
/*
349269
* Prechecking function for adding operators/functions to a hash opfamily.
350270
*/

‎src/backend/utils/adt/bool.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include<ctype.h>
1919

20+
#include"common/hashfn.h"
2021
#include"libpq/pqformat.h"
2122
#include"utils/builtins.h"
2223

@@ -273,6 +274,18 @@ boolge(PG_FUNCTION_ARGS)
273274
PG_RETURN_BOOL(arg1 >=arg2);
274275
}
275276

277+
Datum
278+
hashbool(PG_FUNCTION_ARGS)
279+
{
280+
returnhash_uint32((int32)PG_GETARG_BOOL(0));
281+
}
282+
283+
Datum
284+
hashboolextended(PG_FUNCTION_ARGS)
285+
{
286+
returnhash_uint32_extended((int32)PG_GETARG_BOOL(0),PG_GETARG_INT64(1));
287+
}
288+
276289
/*
277290
* boolean-and and boolean-or aggregates.
278291
*/

‎src/backend/utils/adt/date.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,18 @@ date_sortsupport(PG_FUNCTION_ARGS)
455455
PG_RETURN_VOID();
456456
}
457457

458+
Datum
459+
hashdate(PG_FUNCTION_ARGS)
460+
{
461+
returnhash_uint32(PG_GETARG_DATEADT(0));
462+
}
463+
464+
Datum
465+
hashdateextended(PG_FUNCTION_ARGS)
466+
{
467+
returnhash_uint32_extended(PG_GETARG_DATEADT(0),PG_GETARG_INT64(1));
468+
}
469+
458470
Datum
459471
date_finite(PG_FUNCTION_ARGS)
460472
{

‎src/backend/utils/adt/timestamp.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,6 +2298,18 @@ timestamp_hash_extended(PG_FUNCTION_ARGS)
22982298
returnhashint8extended(fcinfo);
22992299
}
23002300

2301+
Datum
2302+
timestamptz_hash(PG_FUNCTION_ARGS)
2303+
{
2304+
returnhashint8(fcinfo);
2305+
}
2306+
2307+
Datum
2308+
timestamptz_hash_extended(PG_FUNCTION_ARGS)
2309+
{
2310+
returnhashint8extended(fcinfo);
2311+
}
2312+
23012313
/*
23022314
* Cross-type comparison functions for timestamp vs timestamptz
23032315
*/

‎src/backend/utils/adt/xid.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include"access/multixact.h"
2020
#include"access/transam.h"
2121
#include"access/xact.h"
22+
#include"common/hashfn.h"
2223
#include"common/int.h"
2324
#include"libpq/pqformat.h"
2425
#include"utils/builtins.h"
@@ -97,6 +98,18 @@ xidneq(PG_FUNCTION_ARGS)
9798
PG_RETURN_BOOL(!TransactionIdEquals(xid1,xid2));
9899
}
99100

101+
Datum
102+
hashxid(PG_FUNCTION_ARGS)
103+
{
104+
returnhash_uint32(PG_GETARG_TRANSACTIONID(0));
105+
}
106+
107+
Datum
108+
hashxidextended(PG_FUNCTION_ARGS)
109+
{
110+
returnhash_uint32_extended(PG_GETARG_TRANSACTIONID(0),PG_GETARG_INT64(1));
111+
}
112+
100113
/*
101114
*xid_age- compute age of an XID (relative to latest stable xid)
102115
*/
@@ -287,6 +300,18 @@ xid8cmp(PG_FUNCTION_ARGS)
287300
PG_RETURN_INT32(-1);
288301
}
289302

303+
Datum
304+
hashxid8(PG_FUNCTION_ARGS)
305+
{
306+
returnhashint8(fcinfo);
307+
}
308+
309+
Datum
310+
hashxid8extended(PG_FUNCTION_ARGS)
311+
{
312+
returnhashint8extended(fcinfo);
313+
}
314+
290315
Datum
291316
xid8_larger(PG_FUNCTION_ARGS)
292317
{
@@ -374,3 +399,15 @@ cideq(PG_FUNCTION_ARGS)
374399

375400
PG_RETURN_BOOL(arg1==arg2);
376401
}
402+
403+
Datum
404+
hashcid(PG_FUNCTION_ARGS)
405+
{
406+
returnhash_uint32(PG_GETARG_COMMANDID(0));
407+
}
408+
409+
Datum
410+
hashcidextended(PG_FUNCTION_ARGS)
411+
{
412+
returnhash_uint32_extended(PG_GETARG_COMMANDID(0),PG_GETARG_INT64(1));
413+
}

‎src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@
5757
*/
5858

5959
/*yyyymmddN */
60-
#defineCATALOG_VERSION_NO202409102
60+
#defineCATALOG_VERSION_NO202409121
6161

6262
#endif

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp