Skip to content

Commit

Permalink
Import original pg_dirtyread from https://github.com/omniti-labs/pgtr…
Browse files Browse the repository at this point in the history
  • Loading branch information
df7cb committed Apr 9, 2017
0 parents commit f9d1963
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MODULES = pg_dirtyread

EXTENSION = pg_dirtyread
DATA = pg_dirtyread--1.0.sql

PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
pg_dirtyread 1.0
================

The pg_dirtyread extension provides the ability to read dead but unvacuumed
rows from a relation.

Building
--------

To build pg_dirtyread, just do this:

make
make install

If you encounter an error such as:

make: pg_config: Command not found

Be sure that you have `pg_config` installed and in your path. If you used a
package management system such as RPM to install PostgreSQL, be sure that the
`-devel` package is also installed. If necessary tell the build process where
to find it:

env PG_CONFIG=/path/to/pg_config make && make install

Loading
-------

Once pg_dirtyread is built and installed, you can add it to a database. Loading
pg_dirtyread is as simple as connecting to a database as a super user and
running:

CREATE EXTENSION pg_dirtyread;

Using
-----

SELECT * FROM pg_dirtyread('foo'::regclass) as t(bar bigint, baz text);

Where the schema of `foo` is `(bar bigint, baz text)`.
4 changes: 4 additions & 0 deletions pg_dirtyread--1.0.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CREATE FUNCTION pg_dirtyread(oid)
RETURNS setof record
AS 'MODULE_PATHNAME'
LANGUAGE C;
98 changes: 98 additions & 0 deletions pg_dirtyread.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright (c) 2012, OmniTI Computer Consulting, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name OmniTI Computer Consulting, Inc. nor the names
* of its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

#include "postgres.h"
#include "funcapi.h"
#include "utils/tqual.h"
#include "utils/rel.h"
#include "catalog/pg_type.h"
#include "access/tupconvert.h"

typedef struct
{
Relation rel;
HeapScanDesc scan;
TupleDesc reltupdesc;
TupleConversionMap *map;
} pg_dirtyread_ctx;

PG_MODULE_MAGIC;

PG_FUNCTION_INFO_V1(pg_dirtyread);
Datum pg_dirtyread(PG_FUNCTION_ARGS);

Datum
pg_dirtyread(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
MemoryContext oldcontext;
pg_dirtyread_ctx *usr_ctx;
Oid relid;
HeapTuple tuplein, tupleout;
TupleDesc tupdesc;

if (SRF_IS_FIRSTCALL())
{
relid = PG_GETARG_OID(0);

if (OidIsValid(relid))
{
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
usr_ctx = (pg_dirtyread_ctx *) palloc(sizeof(pg_dirtyread_ctx));
usr_ctx->rel = heap_open(relid, AccessShareLock);
usr_ctx->reltupdesc = RelationGetDescr(usr_ctx->rel);
get_call_result_type(fcinfo, NULL, &tupdesc);
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
usr_ctx->map = convert_tuples_by_position(usr_ctx->reltupdesc, funcctx->tuple_desc, "Error converting tuple descriptors!");
usr_ctx->scan = heap_beginscan(usr_ctx->rel, SnapshotAny, 0, NULL);
funcctx->user_fctx = (void *) usr_ctx;
MemoryContextSwitchTo(oldcontext);
}
}

funcctx = SRF_PERCALL_SETUP();
usr_ctx = (pg_dirtyread_ctx *) funcctx->user_fctx;

if ((tuplein = heap_getnext(usr_ctx->scan, ForwardScanDirection)) != NULL)
{
tupleout = do_convert_tuple(tuplein, usr_ctx->map);
SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tupleout));
}
else
{
heap_endscan(usr_ctx->scan);
heap_close(usr_ctx->rel, AccessShareLock);
SRF_RETURN_DONE(funcctx);
}
}
5 changes: 5 additions & 0 deletions pg_dirtyread.control
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# pg_dirtyread
default_version = '1.0'
comment = 'Read dead but unvacuumed rows from table'
module_pathname = '$libdir/pg_dirtyread'
relocatable = true

0 comments on commit f9d1963

Please sign in to comment.