Skip to content

Commit f9d1963

Browse files
committed
0 parents  commit f9d1963

File tree

5 files changed

+155
-0
lines changed

5 files changed

+155
-0
lines changed

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
MODULES = pg_dirtyread
2+
3+
EXTENSION = pg_dirtyread
4+
DATA = pg_dirtyread--1.0.sql
5+
6+
PG_CONFIG = pg_config
7+
PGXS := $(shell $(PG_CONFIG) --pgxs)
8+
include $(PGXS)

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
pg_dirtyread 1.0
2+
================
3+
4+
The pg_dirtyread extension provides the ability to read dead but unvacuumed
5+
rows from a relation.
6+
7+
Building
8+
--------
9+
10+
To build pg_dirtyread, just do this:
11+
12+
make
13+
make install
14+
15+
If you encounter an error such as:
16+
17+
make: pg_config: Command not found
18+
19+
Be sure that you have `pg_config` installed and in your path. If you used a
20+
package management system such as RPM to install PostgreSQL, be sure that the
21+
`-devel` package is also installed. If necessary tell the build process where
22+
to find it:
23+
24+
env PG_CONFIG=/path/to/pg_config make && make install
25+
26+
Loading
27+
-------
28+
29+
Once pg_dirtyread is built and installed, you can add it to a database. Loading
30+
pg_dirtyread is as simple as connecting to a database as a super user and
31+
running:
32+
33+
CREATE EXTENSION pg_dirtyread;
34+
35+
Using
36+
-----
37+
38+
SELECT * FROM pg_dirtyread('foo'::regclass) as t(bar bigint, baz text);
39+
40+
Where the schema of `foo` is `(bar bigint, baz text)`.

pg_dirtyread--1.0.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CREATE FUNCTION pg_dirtyread(oid)
2+
RETURNS setof record
3+
AS 'MODULE_PATHNAME'
4+
LANGUAGE C;

pg_dirtyread.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (c) 2012, OmniTI Computer Consulting, Inc.
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are
7+
* met:
8+
*
9+
* * Redistributions of source code must retain the above copyright
10+
* notice, this list of conditions and the following disclaimer.
11+
* * Redistributions in binary form must reproduce the above
12+
* copyright notice, this list of conditions and the following
13+
* disclaimer in the documentation and/or other materials provided
14+
* with the distribution.
15+
* * Neither the name OmniTI Computer Consulting, Inc. nor the names
16+
* of its contributors may be used to endorse or promote products
17+
* derived from this software without specific prior written
18+
* permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
*
32+
*/
33+
34+
#include "postgres.h"
35+
#include "funcapi.h"
36+
#include "utils/tqual.h"
37+
#include "utils/rel.h"
38+
#include "catalog/pg_type.h"
39+
#include "access/tupconvert.h"
40+
41+
typedef struct
42+
{
43+
Relation rel;
44+
HeapScanDesc scan;
45+
TupleDesc reltupdesc;
46+
TupleConversionMap *map;
47+
} pg_dirtyread_ctx;
48+
49+
PG_MODULE_MAGIC;
50+
51+
PG_FUNCTION_INFO_V1(pg_dirtyread);
52+
Datum pg_dirtyread(PG_FUNCTION_ARGS);
53+
54+
Datum
55+
pg_dirtyread(PG_FUNCTION_ARGS)
56+
{
57+
FuncCallContext *funcctx;
58+
MemoryContext oldcontext;
59+
pg_dirtyread_ctx *usr_ctx;
60+
Oid relid;
61+
HeapTuple tuplein, tupleout;
62+
TupleDesc tupdesc;
63+
64+
if (SRF_IS_FIRSTCALL())
65+
{
66+
relid = PG_GETARG_OID(0);
67+
68+
if (OidIsValid(relid))
69+
{
70+
funcctx = SRF_FIRSTCALL_INIT();
71+
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
72+
usr_ctx = (pg_dirtyread_ctx *) palloc(sizeof(pg_dirtyread_ctx));
73+
usr_ctx->rel = heap_open(relid, AccessShareLock);
74+
usr_ctx->reltupdesc = RelationGetDescr(usr_ctx->rel);
75+
get_call_result_type(fcinfo, NULL, &tupdesc);
76+
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
77+
usr_ctx->map = convert_tuples_by_position(usr_ctx->reltupdesc, funcctx->tuple_desc, "Error converting tuple descriptors!");
78+
usr_ctx->scan = heap_beginscan(usr_ctx->rel, SnapshotAny, 0, NULL);
79+
funcctx->user_fctx = (void *) usr_ctx;
80+
MemoryContextSwitchTo(oldcontext);
81+
}
82+
}
83+
84+
funcctx = SRF_PERCALL_SETUP();
85+
usr_ctx = (pg_dirtyread_ctx *) funcctx->user_fctx;
86+
87+
if ((tuplein = heap_getnext(usr_ctx->scan, ForwardScanDirection)) != NULL)
88+
{
89+
tupleout = do_convert_tuple(tuplein, usr_ctx->map);
90+
SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tupleout));
91+
}
92+
else
93+
{
94+
heap_endscan(usr_ctx->scan);
95+
heap_close(usr_ctx->rel, AccessShareLock);
96+
SRF_RETURN_DONE(funcctx);
97+
}
98+
}

pg_dirtyread.control

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# pg_dirtyread
2+
default_version = '1.0'
3+
comment = 'Read dead but unvacuumed rows from table'
4+
module_pathname = '$libdir/pg_dirtyread'
5+
relocatable = true

0 commit comments

Comments
 (0)