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

Commit3a82bc6

Browse files
committed
Add pageinspect functions for inspecting GIN indexes.
Patch by me, Peter Geoghegan and Michael Paquier, reviewed by Amit Kapila.
1 parentadbfab1 commit3a82bc6

File tree

5 files changed

+451
-4
lines changed

5 files changed

+451
-4
lines changed

‎contrib/pageinspect/Makefile

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
# contrib/pageinspect/Makefile
22

33
MODULE_big= pageinspect
4-
OBJS= rawpage.o heapfuncs.o btreefuncs.o fsmfuncs.o brinfuncs.o$(WIN32RES)
4+
OBJS= rawpage.o heapfuncs.o btreefuncs.o fsmfuncs.o\
5+
brinfuncs.o ginfuncs.o$(WIN32RES)
56

67
EXTENSION = pageinspect
7-
DATA = pageinspect--1.3.sql pageinspect--1.0--1.1.sql\
8-
pageinspect--1.2--1.3.sql\
9-
pageinspect--1.1--1.2.sql pageinspect--unpackaged--1.0.sql
8+
DATA = pageinspect--1.3.sql pageinspect--1.2--1.3.sql\
9+
pageinspect--1.1--1.2.sql pageinspect--1.0--1.1.sql\
10+
pageinspect--unpackaged--1.0.sql
1011
PGFILEDESC = "pageinspect - functions to inspect contents of database pages"
1112

1213
ifdefUSE_PGXS

‎contrib/pageinspect/ginfuncs.c

Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
/*
2+
* ginfuncs.c
3+
*Functions to investigate the content of GIN indexes
4+
*
5+
* Copyright (c) 2014, PostgreSQL Global Development Group
6+
*
7+
* IDENTIFICATION
8+
*contrib/pageinspect/ginfuncs.c
9+
*/
10+
#include"postgres.h"
11+
12+
#include"access/gin.h"
13+
#include"access/gin_private.h"
14+
#include"access/htup_details.h"
15+
#include"catalog/namespace.h"
16+
#include"catalog/pg_type.h"
17+
#include"funcapi.h"
18+
#include"miscadmin.h"
19+
#include"utils/array.h"
20+
#include"utils/builtins.h"
21+
#include"utils/rel.h"
22+
23+
#defineDatumGetItemPointer(X) ((ItemPointer) DatumGetPointer(X))
24+
#defineItemPointerGetDatum(X) PointerGetDatum(X)
25+
26+
27+
PG_FUNCTION_INFO_V1(gin_metapage_info);
28+
PG_FUNCTION_INFO_V1(gin_page_opaque_info);
29+
PG_FUNCTION_INFO_V1(gin_leafpage_items);
30+
31+
Datum
32+
gin_metapage_info(PG_FUNCTION_ARGS)
33+
{
34+
bytea*raw_page=PG_GETARG_BYTEA_P(0);
35+
intraw_page_size;
36+
TupleDesctupdesc;
37+
Pagepage;
38+
GinPageOpaqueopaq;
39+
GinMetaPageData*metadata;
40+
HeapTupleresultTuple;
41+
Datumvalues[10];
42+
boolnulls[10];
43+
44+
if (!superuser())
45+
ereport(ERROR,
46+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
47+
(errmsg("must be superuser to use raw page functions"))));
48+
49+
raw_page_size=VARSIZE(raw_page)-VARHDRSZ;
50+
if (raw_page_size<BLCKSZ)
51+
ereport(ERROR,
52+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
53+
errmsg("input page too small (%d bytes)",raw_page_size)));
54+
page=VARDATA(raw_page);
55+
56+
opaq= (GinPageOpaque)PageGetSpecialPointer(page);
57+
if (opaq->flags!=GIN_META)
58+
ereport(ERROR,
59+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
60+
errmsg("input page is not a GIN metapage"),
61+
errdetail("Flags %04X, expected %04X",
62+
opaq->flags,GIN_META)));
63+
64+
/* Build a tuple descriptor for our result type */
65+
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
66+
elog(ERROR,"return type must be a row type");
67+
68+
metadata=GinPageGetMeta(page);
69+
70+
memset(nulls,0,sizeof(nulls));
71+
72+
values[0]=Int64GetDatum(metadata->head);
73+
values[1]=Int64GetDatum(metadata->tail);
74+
values[2]=Int32GetDatum(metadata->tailFreeSize);
75+
values[3]=Int64GetDatum(metadata->nPendingPages);
76+
values[4]=Int64GetDatum(metadata->nPendingHeapTuples);
77+
78+
/* statistics, updated by VACUUM */
79+
values[5]=Int64GetDatum(metadata->nTotalPages);
80+
values[6]=Int64GetDatum(metadata->nEntryPages);
81+
values[7]=Int64GetDatum(metadata->nDataPages);
82+
values[8]=Int64GetDatum(metadata->nEntries);
83+
84+
values[9]=Int32GetDatum(metadata->ginVersion);
85+
86+
/* Build and return the result tuple. */
87+
resultTuple=heap_form_tuple(tupdesc,values,nulls);
88+
89+
returnHeapTupleGetDatum(resultTuple);
90+
}
91+
92+
93+
Datum
94+
gin_page_opaque_info(PG_FUNCTION_ARGS)
95+
{
96+
bytea*raw_page=PG_GETARG_BYTEA_P(0);
97+
intraw_page_size;
98+
TupleDesctupdesc;
99+
Pagepage;
100+
GinPageOpaqueopaq;
101+
HeapTupleresultTuple;
102+
Datumvalues[3];
103+
boolnulls[10];
104+
Datumflags[16];
105+
intnflags=0;
106+
uint16flagbits;
107+
108+
if (!superuser())
109+
ereport(ERROR,
110+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
111+
(errmsg("must be superuser to use raw page functions"))));
112+
113+
raw_page_size=VARSIZE(raw_page)-VARHDRSZ;
114+
if (raw_page_size<BLCKSZ)
115+
ereport(ERROR,
116+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
117+
errmsg("input page too small (%d bytes)",raw_page_size)));
118+
page=VARDATA(raw_page);
119+
120+
opaq= (GinPageOpaque)PageGetSpecialPointer(page);
121+
122+
/* Build a tuple descriptor for our result type */
123+
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
124+
elog(ERROR,"return type must be a row type");
125+
126+
/* Convert the flags bitmask to an array of human-readable names */
127+
flagbits=opaq->flags;
128+
if (flagbits&GIN_DATA)
129+
flags[nflags++]=CStringGetTextDatum("data");
130+
if (flagbits&GIN_LEAF)
131+
flags[nflags++]=CStringGetTextDatum("leaf");
132+
if (flagbits&GIN_DELETED)
133+
flags[nflags++]=CStringGetTextDatum("deleted");
134+
if (flagbits&GIN_META)
135+
flags[nflags++]=CStringGetTextDatum("meta");
136+
if (flagbits&GIN_LIST)
137+
flags[nflags++]=CStringGetTextDatum("list");
138+
if (flagbits&GIN_LIST_FULLROW)
139+
flags[nflags++]=CStringGetTextDatum("list_fullrow");
140+
if (flagbits&GIN_INCOMPLETE_SPLIT)
141+
flags[nflags++]=CStringGetTextDatum("incomplete_split");
142+
if (flagbits&GIN_COMPRESSED)
143+
flags[nflags++]=CStringGetTextDatum("compressed");
144+
flagbits &= ~(GIN_DATA |GIN_LEAF |GIN_DELETED |GIN_META |GIN_LIST |
145+
GIN_LIST_FULLROW |GIN_INCOMPLETE_SPLIT |GIN_COMPRESSED);
146+
if (flagbits)
147+
{
148+
/* any flags we don't recognize are printed in hex */
149+
flags[nflags++]=DirectFunctionCall1(to_hex32,Int32GetDatum(flagbits));
150+
}
151+
152+
memset(nulls,0,sizeof(nulls));
153+
154+
values[0]=Int64GetDatum(opaq->rightlink);
155+
values[1]=Int64GetDatum(opaq->maxoff);
156+
values[2]=PointerGetDatum(
157+
construct_array(flags,nflags,TEXTOID,-1, false,'i'));
158+
159+
/* Build and return the result tuple. */
160+
resultTuple=heap_form_tuple(tupdesc,values,nulls);
161+
162+
returnHeapTupleGetDatum(resultTuple);
163+
}
164+
165+
typedefstructgin_leafpage_items_state
166+
{
167+
TupleDesctupd;
168+
GinPostingList*seg;
169+
GinPostingList*lastseg;
170+
}gin_leafpage_items_state;
171+
172+
Datum
173+
gin_leafpage_items(PG_FUNCTION_ARGS)
174+
{
175+
bytea*raw_page=PG_GETARG_BYTEA_P(0);
176+
intraw_page_size;
177+
FuncCallContext*fctx;
178+
gin_leafpage_items_state*inter_call_data;
179+
180+
if (!superuser())
181+
ereport(ERROR,
182+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
183+
(errmsg("must be superuser to use raw page functions"))));
184+
185+
raw_page_size=VARSIZE(raw_page)-VARHDRSZ;
186+
187+
if (SRF_IS_FIRSTCALL())
188+
{
189+
TupleDesctupdesc;
190+
MemoryContextmctx;
191+
Pagepage;
192+
GinPageOpaqueopaq;
193+
194+
if (raw_page_size<BLCKSZ)
195+
ereport(ERROR,
196+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
197+
errmsg("input page too small (%d bytes)",raw_page_size)));
198+
page=VARDATA(raw_page);
199+
200+
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(GinPageOpaqueData)))
201+
ereport(ERROR,
202+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
203+
errmsg("input page is not a valid GIN data leaf page"),
204+
errdetail("Special size %d, expected %d",
205+
(int)PageGetSpecialSize(page),
206+
(int)MAXALIGN(sizeof(GinPageOpaqueData)))));
207+
208+
opaq= (GinPageOpaque)PageGetSpecialPointer(page);
209+
if (opaq->flags!= (GIN_DATA |GIN_LEAF |GIN_COMPRESSED))
210+
ereport(ERROR,
211+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
212+
errmsg("input page is not a compressed GIN data leaf page"),
213+
errdetail("Flags %04X, expected %04X",
214+
opaq->flags,
215+
(GIN_DATA |GIN_LEAF |GIN_COMPRESSED))));
216+
217+
fctx=SRF_FIRSTCALL_INIT();
218+
mctx=MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
219+
220+
inter_call_data=palloc(sizeof(gin_leafpage_items_state));
221+
222+
/* Build a tuple descriptor for our result type */
223+
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
224+
elog(ERROR,"return type must be a row type");
225+
226+
inter_call_data->tupd=tupdesc;
227+
228+
inter_call_data->seg=GinDataLeafPageGetPostingList(page);
229+
inter_call_data->lastseg= (GinPostingList*)
230+
(((char*)inter_call_data->seg)+
231+
GinDataLeafPageGetPostingListSize(page));
232+
233+
fctx->user_fctx=inter_call_data;
234+
235+
MemoryContextSwitchTo(mctx);
236+
}
237+
238+
fctx=SRF_PERCALL_SETUP();
239+
inter_call_data=fctx->user_fctx;
240+
241+
if (inter_call_data->seg!=inter_call_data->lastseg)
242+
{
243+
GinPostingList*cur=inter_call_data->seg;
244+
HeapTupleresultTuple;
245+
Datumresult;
246+
Datumvalues[3];
247+
boolnulls[3];
248+
intndecoded,
249+
i;
250+
ItemPointertids;
251+
Datum*tids_datum;
252+
253+
memset(nulls,0,sizeof(nulls));
254+
255+
values[0]=ItemPointerGetDatum(&cur->first);
256+
values[1]=UInt16GetDatum(cur->nbytes);
257+
258+
/* build an array of decoded item pointers */
259+
tids=ginPostingListDecode(cur,&ndecoded);
260+
tids_datum= (Datum*)palloc(ndecoded*sizeof(Datum));
261+
for (i=0;i<ndecoded;i++)
262+
tids_datum[i]=ItemPointerGetDatum(&tids[i]);
263+
values[2]=PointerGetDatum(construct_array(tids_datum,
264+
ndecoded,
265+
TIDOID,
266+
sizeof(ItemPointerData),
267+
false,'s'));
268+
pfree(tids_datum);
269+
pfree(tids);
270+
271+
/* Build and return the result tuple. */
272+
resultTuple=heap_form_tuple(inter_call_data->tupd,values,nulls);
273+
result=HeapTupleGetDatum(resultTuple);
274+
275+
inter_call_data->seg=GinNextPostingListSegment(cur);
276+
277+
SRF_RETURN_NEXT(fctx,result);
278+
}
279+
else
280+
SRF_RETURN_DONE(fctx);
281+
}

‎contrib/pageinspect/pageinspect--1.2--1.3.sql

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,41 @@ CREATE FUNCTION brin_page_items(IN page bytea, IN index_oid regclass,
4141
RETURNS SETOF record
4242
AS'MODULE_PATHNAME','brin_page_items'
4343
LANGUAGE C STRICT;
44+
45+
--
46+
-- gin_metapage_info()
47+
--
48+
CREATEFUNCTIONgin_metapage_info(IN pagebytea,
49+
OUT pending_headbigint,
50+
OUT pending_tailbigint,
51+
OUT tail_free_size int4,
52+
OUT n_pending_pagesbigint,
53+
OUT n_pending_tuplesbigint,
54+
OUT n_total_pagesbigint,
55+
OUT n_entry_pagesbigint,
56+
OUT n_data_pagesbigint,
57+
OUT n_entriesbigint,
58+
OUT version int4)
59+
AS'MODULE_PATHNAME','gin_metapage_info'
60+
LANGUAGE C STRICT;
61+
62+
--
63+
-- gin_page_opaque_info()
64+
--
65+
CREATEFUNCTIONgin_page_opaque_info(IN pagebytea,
66+
OUT rightlinkbigint,
67+
OUT maxoff int4,
68+
OUT flagstext[])
69+
AS'MODULE_PATHNAME','gin_page_opaque_info'
70+
LANGUAGE C STRICT;
71+
72+
--
73+
-- gin_leafpage_items()
74+
--
75+
CREATEFUNCTIONgin_leafpage_items(IN pagebytea,
76+
OUT first_tid tid,
77+
OUT nbytes int2,
78+
OUT tids tid[])
79+
RETURNS SETOF record
80+
AS'MODULE_PATHNAME','gin_leafpage_items'
81+
LANGUAGE C STRICT;

‎contrib/pageinspect/pageinspect--1.3.sql

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,45 @@ CREATE FUNCTION fsm_page_contents(IN page bytea)
144144
RETURNStext
145145
AS'MODULE_PATHNAME','fsm_page_contents'
146146
LANGUAGE C STRICT;
147+
148+
--
149+
-- GIN functions
150+
--
151+
152+
--
153+
-- gin_metapage_info()
154+
--
155+
CREATEFUNCTIONgin_metapage_info(IN pagebytea,
156+
OUT pending_headbigint,
157+
OUT pending_tailbigint,
158+
OUT tail_free_size int4,
159+
OUT n_pending_pagesbigint,
160+
OUT n_pending_tuplesbigint,
161+
OUT n_total_pagesbigint,
162+
OUT n_entry_pagesbigint,
163+
OUT n_data_pagesbigint,
164+
OUT n_entriesbigint,
165+
OUT version int4)
166+
AS'MODULE_PATHNAME','gin_metapage_info'
167+
LANGUAGE C STRICT;
168+
169+
--
170+
-- gin_page_opaque_info()
171+
--
172+
CREATEFUNCTIONgin_page_opaque_info(IN pagebytea,
173+
OUT rightlinkbigint,
174+
OUT maxoff int4,
175+
OUT flagstext[])
176+
AS'MODULE_PATHNAME','gin_page_opaque_info'
177+
LANGUAGE C STRICT;
178+
179+
--
180+
-- gin_leafpage_items()
181+
--
182+
CREATEFUNCTIONgin_leafpage_items(IN pagebytea,
183+
OUT first_tid tid,
184+
OUT nbytes int2,
185+
OUT tids tid[])
186+
RETURNS SETOF record
187+
AS'MODULE_PATHNAME','gin_leafpage_items'
188+
LANGUAGE C STRICT;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp