Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0e01f5d

Browse files
committed
Support amproperty method.
Query select pg_index_column_has_property('index_name'::regclass,1,'distance_orderable') returns value 'true' instead of null now.
1 parent 7386406 commit 0e01f5d

File tree

4 files changed

+143
-0
lines changed

4 files changed

+143
-0
lines changed

expected/rum.out

+39
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,45 @@ CREATE TRIGGER tsvectorupdate
4747
BEFORE UPDATE OR INSERT ON test_rum
4848
FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('a', 'pg_catalog.english', 't');
4949
CREATE INDEX rumidx ON test_rum USING rum (a rum_tsvector_ops);
50+
-- Access method properties
51+
SELECT a.amname, p.name, pg_indexam_has_property(a.oid,p.name)
52+
FROM pg_am a, unnest(array['can_order','can_unique','can_multi_col','can_exclude']) p(name)
53+
WHERE a.amname = 'rum' ORDER BY a.amname;
54+
amname | name | pg_indexam_has_property
55+
--------+---------------+-------------------------
56+
rum | can_order | f
57+
rum | can_unique | f
58+
rum | can_multi_col | t
59+
rum | can_exclude | t
60+
(4 rows)
61+
62+
-- Index properties
63+
SELECT p.name, pg_index_has_property('rumidx'::regclass,p.name)
64+
FROM unnest(array['clusterable','index_scan','bitmap_scan','backward_scan']) p(name);
65+
name | pg_index_has_property
66+
---------------+-----------------------
67+
clusterable | f
68+
index_scan | t
69+
bitmap_scan | t
70+
backward_scan | f
71+
(4 rows)
72+
73+
-- Index column properties
74+
SELECT p.name, pg_index_column_has_property('rumidx'::regclass,1,p.name)
75+
FROM unnest(array['asc','desc','nulls_first','nulls_last','orderable','distance_orderable','returnable','search_array','search_nulls']) p(name);
76+
name | pg_index_column_has_property
77+
--------------------+------------------------------
78+
asc | f
79+
desc | f
80+
nulls_first | f
81+
nulls_last | f
82+
orderable | f
83+
distance_orderable | t
84+
returnable | f
85+
search_array | f
86+
search_nulls | f
87+
(9 rows)
88+
5089
\copy test_rum(t) from 'data/rum.data';
5190
CREATE INDEX failed_rumidx ON test_rum USING rum (a rum_tsvector_addon_ops);
5291
ERROR: additional information attribute "a" is not found in index

sql/rum.sql

+13
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ BEFORE UPDATE OR INSERT ON test_rum
1313
FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger('a', 'pg_catalog.english', 't');
1414
CREATE INDEX rumidx ON test_rum USING rum (a rum_tsvector_ops);
1515

16+
-- Access method properties
17+
SELECT a.amname, p.name, pg_indexam_has_property(a.oid,p.name)
18+
FROM pg_am a, unnest(array['can_order','can_unique','can_multi_col','can_exclude']) p(name)
19+
WHERE a.amname = 'rum' ORDER BY a.amname;
20+
21+
-- Index properties
22+
SELECT p.name, pg_index_has_property('rumidx'::regclass,p.name)
23+
FROM unnest(array['clusterable','index_scan','bitmap_scan','backward_scan']) p(name);
24+
25+
-- Index column properties
26+
SELECT p.name, pg_index_column_has_property('rumidx'::regclass,1,p.name)
27+
FROM unnest(array['asc','desc','nulls_first','nulls_last','orderable','distance_orderable','returnable','search_array','search_nulls']) p(name);
28+
1629
\copy test_rum(t) from 'data/rum.data';
1730

1831
CREATE INDEX failed_rumidx ON test_rum USING rum (a rum_tsvector_addon_ops);

src/rum.h

+3
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,9 @@ typedef struct RumState
400400

401401
/* rumutil.c */
402402
extern bytea *rumoptions(Datum reloptions, bool validate);
403+
extern bool rumproperty(Oid index_oid, int attno,
404+
IndexAMProperty prop, const char *propname,
405+
bool *res, bool *isnull);
403406
extern Datum rumhandler(PG_FUNCTION_ARGS);
404407
extern void initRumState(RumState * state, Relation index);
405408
extern Buffer RumNewBuffer(Relation index);

src/rumutil.c

+88
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313

1414
#include "postgres.h"
1515

16+
#include "access/htup_details.h"
1617
#include "access/reloptions.h"
1718
#include "catalog/pg_collation.h"
19+
#include "catalog/pg_opclass.h"
1820
#include "catalog/pg_type.h"
1921
#include "miscadmin.h"
2022
#include "storage/indexfsm.h"
@@ -23,6 +25,7 @@
2325
#include "utils/guc.h"
2426
#include "utils/index_selfuncs.h"
2527
#include "utils/lsyscache.h"
28+
#include "utils/syscache.h"
2629
#include "utils/typcache.h"
2730

2831
#include "rum.h"
@@ -111,6 +114,9 @@ rumhandler(PG_FUNCTION_ARGS)
111114
amroutine->amstorage = true;
112115
amroutine->amclusterable = false;
113116
amroutine->ampredlocks = true;
117+
#if PG_VERSION_NUM >= 100000
118+
amroutine->amcanparallel = false;
119+
#endif
114120
amroutine->amkeytype = InvalidOid;
115121

116122
amroutine->ambuild = rumbuild;
@@ -121,6 +127,7 @@ rumhandler(PG_FUNCTION_ARGS)
121127
amroutine->amcanreturn = NULL;
122128
amroutine->amcostestimate = gincostestimate;
123129
amroutine->amoptions = rumoptions;
130+
amroutine->amproperty = rumproperty;
124131
amroutine->amvalidate = rumvalidate;
125132
amroutine->ambeginscan = rumbeginscan;
126133
amroutine->amrescan = rumrescan;
@@ -129,6 +136,11 @@ rumhandler(PG_FUNCTION_ARGS)
129136
amroutine->amendscan = rumendscan;
130137
amroutine->ammarkpos = NULL;
131138
amroutine->amrestrpos = NULL;
139+
#if PG_VERSION_NUM >= 100000
140+
amroutine->amestimateparallelscan = NULL;
141+
amroutine->aminitparallelscan = NULL;
142+
amroutine->amparallelrescan = NULL;
143+
#endif
132144

133145
PG_RETURN_POINTER(amroutine);
134146
}
@@ -877,6 +889,82 @@ rumoptions(Datum reloptions, bool validate)
877889
return (bytea *) rdopts;
878890
}
879891

892+
bool
893+
rumproperty(Oid index_oid, int attno,
894+
IndexAMProperty prop, const char *propname,
895+
bool *res, bool *isnull)
896+
{
897+
HeapTuple tuple;
898+
Form_pg_index rd_index PG_USED_FOR_ASSERTS_ONLY;
899+
Form_pg_opclass rd_opclass;
900+
Datum datum;
901+
bool disnull;
902+
oidvector *indclass;
903+
Oid opclass,
904+
opfamily,
905+
opcintype;
906+
int16 procno;
907+
908+
/* Only answer column-level inquiries */
909+
if (attno == 0)
910+
return false;
911+
912+
switch (prop)
913+
{
914+
case AMPROP_DISTANCE_ORDERABLE:
915+
procno = RUM_ORDERING_PROC;
916+
break;
917+
default:
918+
return false;
919+
}
920+
921+
/* First we need to know the column's opclass. */
922+
923+
tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
924+
if (!HeapTupleIsValid(tuple))
925+
{
926+
*isnull = true;
927+
return true;
928+
}
929+
rd_index = (Form_pg_index) GETSTRUCT(tuple);
930+
931+
/* caller is supposed to guarantee this */
932+
Assert(attno > 0 && attno <= rd_index->indnatts);
933+
934+
datum = SysCacheGetAttr(INDEXRELID, tuple,
935+
Anum_pg_index_indclass, &disnull);
936+
Assert(!disnull);
937+
938+
indclass = ((oidvector *) DatumGetPointer(datum));
939+
opclass = indclass->values[attno - 1];
940+
941+
ReleaseSysCache(tuple);
942+
943+
/* Now look up the opclass family and input datatype. */
944+
945+
tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
946+
if (!HeapTupleIsValid(tuple))
947+
{
948+
*isnull = true;
949+
return true;
950+
}
951+
rd_opclass = (Form_pg_opclass) GETSTRUCT(tuple);
952+
953+
opfamily = rd_opclass->opcfamily;
954+
opcintype = rd_opclass->opcintype;
955+
956+
ReleaseSysCache(tuple);
957+
958+
/* And now we can check whether the function is provided. */
959+
960+
*res = SearchSysCacheExists4(AMPROCNUM,
961+
ObjectIdGetDatum(opfamily),
962+
ObjectIdGetDatum(opcintype),
963+
ObjectIdGetDatum(opcintype),
964+
Int16GetDatum(procno));
965+
return true;
966+
}
967+
880968
/*
881969
* Fetch index's statistical data into *stats
882970
*

0 commit comments

Comments
 (0)