pax_global_header00006660000000000000000000000064132611355520014515gustar00rootroot0000000000000052 comment=256a62fee25a974e80f1cb9a92e231ebfc8e63a6 toastinfo-1.1/000077500000000000000000000000001326113555200133645ustar00rootroot00000000000000toastinfo-1.1/.travis.yml000066400000000000000000000034651326113555200155050ustar00rootroot00000000000000# run the testsuite on travis-ci.com --- # versions to run on env: - PG_SUPPORTED_VERSIONS=9.1 - PG_SUPPORTED_VERSIONS=9.2 - PG_SUPPORTED_VERSIONS=9.3 - PG_SUPPORTED_VERSIONS=9.4 - PG_SUPPORTED_VERSIONS=9.5 - PG_SUPPORTED_VERSIONS=9.6 - PG_SUPPORTED_VERSIONS=10 - PG_SUPPORTED_VERSIONS=11 language: C dist: trusty sudo: required before_install: # apt.postgresql.org is already configured, we just need to add devel - | DIST=trusty-pgdg case $PG_SUPPORTED_VERSIONS in 11) # update pgdg-source.list sudo sed -i -e "s/pgdg.*/pgdg-testing main $PG_SUPPORTED_VERSIONS/" /etc/apt/sources.list.d/pgdg*.list DIST=trusty-pgdg-testing ;; esac - sudo apt-get -qq update install: - export DEBIAN_FRONTEND=noninteractive # suppress warnings about deprecated PostgreSQL versions # trusty's pg_buildext doesn't cope with PG version numbers >= 10, so upgrade that to -pgdg - sudo apt-get install postgresql-server-dev-$PG_SUPPORTED_VERSIONS postgresql-server-dev-all/$DIST # install PostgreSQL $PG_SUPPORTED_VERSIONS if not there yet - | if [ ! -x /usr/lib/postgresql/$PG_SUPPORTED_VERSIONS/bin/postgres ]; then sudo apt-get install postgresql-common # upgrade pg-common first ... sudo /etc/init.d/postgresql stop # ... so we can stop postgresql again before installing the server sudo apt-get install postgresql-$PG_SUPPORTED_VERSIONS fi # stop the travis-provided cluster - sudo /etc/init.d/postgresql stop - pg_lsclusters - dpkg -l postgresql\* | cat script: - PG_CONFIG=/usr/lib/postgresql/$PG_SUPPORTED_VERSIONS/bin/pg_config - make clean PG_CONFIG=$PG_CONFIG - make PG_CONFIG=$PG_CONFIG - sudo make install PG_CONFIG=$PG_CONFIG - pg_virtualenv -v $PG_SUPPORTED_VERSIONS make installcheck PG_CONFIG=$PG_CONFIG || cat regression.diffs toastinfo-1.1/Makefile000066400000000000000000000002711326113555200150240ustar00rootroot00000000000000MODULES = toastinfo EXTENSION = toastinfo DATA = toastinfo--1.sql REGRESS = toastinfo ifndef PG_CONFIG PG_CONFIG = pg_config endif PGXS = $(shell $(PG_CONFIG) --pgxs) include $(PGXS) toastinfo-1.1/README.md000066400000000000000000000076731326113555200146600ustar00rootroot00000000000000PostgreSQL toastinfo Extension ============================== This PostgreSQL extension exposes the internal storage structure of variable-length datatypes, called `varlena`. The function `pg_toastinfo` describes the storage form of a datum: * `null` for NULLs * `ordinary` for non-varlena datatypes * `short inline varlena` for varlena values up to 126 bytes (1 byte header) * `long inline varlena, (un)compressed` for varlena values up to 1GiB (4 bytes header) * `toasted varlena, (un)compressed` for varlena values up to 1GiB stored in TOAST tables The function `pg_toastpointer` returns a varlena's `chunk_id` oid in the corresponding TOAST table. It returns NULL on non-varlena input. PostgreSQL versions 9.1 and later are supported. [![Build Status](https://travis-ci.org/credativ/toastinfo.svg?branch=master)](https://travis-ci.org/credativ/toastinfo) Example ------- ``` CREATE EXTENSION toastinfo; CREATE TABLE t ( a text, b text ); INSERT INTO t VALUES ('null', NULL); INSERT INTO t VALUES ('default', 'default'); ALTER TABLE t ALTER COLUMN b SET STORAGE EXTERNAL; INSERT INTO t VALUES ('external-10', 'external'); -- inline INSERT INTO t VALUES ('external-10000', repeat('1',10000)); -- toast uncompressed INSERT INTO t VALUES ('external-1000000', repeat('2',1000000)); -- toast uncompressed ALTER TABLE t ALTER COLUMN b SET STORAGE EXTENDED; INSERT INTO t VALUES ('extended-10', 'extended'); -- inline INSERT INTO t VALUES ('extended-10000', repeat('3',10000)); -- inline compressed INSERT INTO t VALUES ('extended-1000000', repeat('4',1000000)); -- toast compressed SELECT a, length(b), pg_column_size(b), pg_toastinfo(b), pg_toastpointer(b) FROM t; a │ length │ pg_column_size │ pg_toastinfo │ pg_toastpointer ──────────────────┼─────────┼────────────────┼─────────────────────────────────┼───────────────── null │ ∅ │ ∅ │ null │ ∅ default │ 7 │ 8 │ short inline varlena │ ∅ external-10 │ 8 │ 9 │ short inline varlena │ ∅ external-10000 │ 10000 │ 10000 │ toasted varlena, uncompressed │ 24599 external-1000000 │ 1000000 │ 1000000 │ toasted varlena, uncompressed │ 24600 extended-10 │ 8 │ 9 │ short inline varlena │ ∅ extended-10000 │ 10000 │ 125 │ long inline varlena, compressed │ ∅ extended-1000000 │ 1000000 │ 11452 │ toasted varlena, compressed │ 24601 (8 rows) ``` License ------- Author: Christoph Berg Copyright (c) 1996-2017, The PostgreSQL Global Development Group Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. toastinfo-1.1/SPECS/000077500000000000000000000000001326113555200142415ustar00rootroot00000000000000toastinfo-1.1/SPECS/PGDG/000077500000000000000000000000001326113555200147625ustar00rootroot00000000000000toastinfo-1.1/SPECS/PGDG/README000066400000000000000000000004751326113555200156500ustar00rootroot00000000000000The SPEC file found here is intended to be used with PGDG PostgreSQL packages. To build a toastinfo package, you have to specify the target PostgreSQL PGDG release and the installation directory, where the packages can be found. Example: rpmbuild -D"pgdgversion 10" -D "pginstdir /usr/pgsql-10/" -ba toastinfo.spec toastinfo-1.1/SPECS/PGDG/toastinfo.spec000066400000000000000000000017241326113555200176500ustar00rootroot00000000000000Name: toastinfo Version: 1.0 Release: 1%{?dist} Summary: A PostgreSQL extension module to view toast value information. Group: database License: BSD URL: https://github.com/credativ/toastinfo Source0: https://github.com/credativ/toastinfo/archive/v%{version}.tar.gz BuildRequires: postgresql%{pgdgversion}-devel Requires: postgresql%{pgdgversion} %description This PostgreSQL extension exposes the internal storage structure of variable-length datatypes, called varlena. %prep %setup -q %build PG_CONFIG=%{pginstdir}/bin/pg_config USE_PGXS=1 make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT PG_CONFIG=%{pginstdir}/bin/pg_config USE_PGXS=1 make install DESTDIR=$RPM_BUILD_ROOT %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %{pginstdir}/lib/toastinfo.so %{pginstdir}/share/extension/toastinfo--1.sql %{pginstdir}/share/extension/toastinfo.control %changelog * Tue Apr 03 2018 - Bernd Helmle 1.0-1 - Upstream release 1.0 toastinfo-1.1/debian/000077500000000000000000000000001326113555200146065ustar00rootroot00000000000000toastinfo-1.1/debian/changelog000066400000000000000000000006001326113555200164540ustar00rootroot00000000000000toastinfo (1.1-1) unstable; urgency=medium * New upstream release with rpm spec files. * Use source format 1.0 to ease building snapshots. * Update Vcs URLs. -- Christoph Berg Wed, 04 Apr 2018 13:32:49 +0200 toastinfo (1.0-1) unstable; urgency=medium * Initial release. -- Christoph Berg Sat, 18 Nov 2017 19:04:28 +0100 toastinfo-1.1/debian/compat000066400000000000000000000000021326113555200160040ustar00rootroot000000000000009 toastinfo-1.1/debian/control000066400000000000000000000023521326113555200162130ustar00rootroot00000000000000Source: toastinfo Section: database Priority: optional Maintainer: Debian PostgreSQL Maintainers Uploaders: Christoph Berg Build-Depends: debhelper (>= 9), postgresql-server-dev-all (>= 153~) Standards-Version: 4.1.3 Homepage: https://github.com/credativ/toastinfo Vcs-Browser: https://github.com/credativ/toastinfo Vcs-Git: https://github.com/credativ/toastinfo.git Package: postgresql-10-toastinfo Architecture: any Depends: postgresql-10, ${misc:Depends}, ${shlibs:Depends} Description: Show storage structure of varlena datatypes in PostgreSQL This PostgreSQL extension exposes the internal storage structure of variable-length datatypes, called varlena. . The function pg_toastinfo describes the storage form of a datum: . * null for NULLs * ordinary for non-varlena datatypes * short inline varlena for varlena values up to 126 bytes (1 byte header) * long inline varlena, (un)compressed for varlena values up to 1GiB (4 bytes header) * toasted varlena, (un)compressed for varlena values up to 1GiB stored in TOAST tables . The function pg_toastpointer returns a varlena's chunk_id oid in the corresponding TOAST table. It returns NULL on non-varlena input. toastinfo-1.1/debian/control.in000066400000000000000000000023671326113555200166260ustar00rootroot00000000000000Source: toastinfo Section: database Priority: optional Maintainer: Debian PostgreSQL Maintainers Uploaders: Christoph Berg Build-Depends: debhelper (>= 9), postgresql-server-dev-all (>= 153~) Standards-Version: 4.1.3 Homepage: https://github.com/credativ/toastinfo Vcs-Browser: https://github.com/credativ/toastinfo Vcs-Git: https://github.com/credativ/toastinfo.git Package: postgresql-PGVERSION-toastinfo Architecture: any Depends: postgresql-PGVERSION, ${misc:Depends}, ${shlibs:Depends} Description: Show storage structure of varlena datatypes in PostgreSQL This PostgreSQL extension exposes the internal storage structure of variable-length datatypes, called varlena. . The function pg_toastinfo describes the storage form of a datum: . * null for NULLs * ordinary for non-varlena datatypes * short inline varlena for varlena values up to 126 bytes (1 byte header) * long inline varlena, (un)compressed for varlena values up to 1GiB (4 bytes header) * toasted varlena, (un)compressed for varlena values up to 1GiB stored in TOAST tables . The function pg_toastpointer returns a varlena's chunk_id oid in the corresponding TOAST table. It returns NULL on non-varlena input. toastinfo-1.1/debian/copyright000066400000000000000000000023151326113555200165420ustar00rootroot00000000000000Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: toastinfo Source: https://github.com/credativ/toastinfo Files: * Copyright: Copyright (c) 1996-2017, The PostgreSQL Global Development Group License: PostgreSQL Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies. . IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. . THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. toastinfo-1.1/debian/pgversions000066400000000000000000000000041326113555200167220ustar00rootroot00000000000000all toastinfo-1.1/debian/rules000077500000000000000000000006341326113555200156710ustar00rootroot00000000000000#!/usr/bin/make -f include /usr/share/postgresql-common/pgxs_debian_control.mk override_dh_auto_build: +pg_buildext build build-%v override_dh_auto_test: # nothing to do here, see debian/tests/* instead override_dh_auto_install: +pg_buildext install build-%v postgresql-%v-toastinfo override_dh_installdocs: dh_installdocs --all README.* override_dh_auto_clean: +pg_buildext clean build-%v %: dh $@ toastinfo-1.1/debian/source/000077500000000000000000000000001326113555200161065ustar00rootroot00000000000000toastinfo-1.1/debian/source/format000066400000000000000000000000041326113555200173130ustar00rootroot000000000000001.0 toastinfo-1.1/debian/source/lintian-overrides000066400000000000000000000001751326113555200214720ustar00rootroot00000000000000# don't bug people uploading from @work source: changelog-should-mention-nmu source: source-nmu-has-incorrect-version-number toastinfo-1.1/debian/tests/000077500000000000000000000000001326113555200157505ustar00rootroot00000000000000toastinfo-1.1/debian/tests/control000066400000000000000000000001251326113555200173510ustar00rootroot00000000000000Depends: @, postgresql-server-dev-all Tests: installcheck Restrictions: allow-stderr toastinfo-1.1/debian/tests/installcheck000077500000000000000000000000431326113555200203370ustar00rootroot00000000000000#!/bin/sh pg_buildext installcheck toastinfo-1.1/debian/watch000066400000000000000000000001111326113555200156300ustar00rootroot00000000000000version=4 https://github.com/credativ/toastinfo/releases .*/v(.*).tar.gz toastinfo-1.1/expected/000077500000000000000000000000001326113555200151655ustar00rootroot00000000000000toastinfo-1.1/expected/toastinfo.out000066400000000000000000000067631326113555200177400ustar00rootroot00000000000000CREATE EXTENSION toastinfo; CREATE TABLE x ( int int, bigint bigint, float float, numeric numeric, text text, bytea bytea ); INSERT INTO x VALUES(1, 1, 1, 1, '', ''); SELECT pg_toastinfo(int) AS int, pg_toastinfo(bigint) AS bigint, pg_toastinfo(float) AS float, pg_toastinfo(numeric) AS numeric, pg_toastinfo(text) AS text, pg_toastinfo(bytea) AS bytea FROM x; int | bigint | float | numeric | text | bytea ----------+----------+----------+----------------------+----------------------+---------------------- ordinary | ordinary | ordinary | short inline varlena | short inline varlena | short inline varlena (1 row) SELECT pg_toastpointer(int) AS int, pg_toastpointer(bigint) AS bigint, pg_toastpointer(float) AS float, pg_toastpointer(numeric) AS numeric, pg_toastpointer(text) AS text, pg_toastpointer(bytea) AS bytea FROM x; int | bigint | float | numeric | text | bytea -----+--------+-------+---------+------+------- | | | | | (1 row) CREATE TABLE t ( a text, b text ); INSERT INTO t VALUES ('null', NULL); INSERT INTO t VALUES ('default', 'default'); ALTER TABLE t ALTER COLUMN b SET STORAGE EXTERNAL; INSERT INTO t VALUES ('external-10', 'external'); -- inline INSERT INTO t VALUES ('external-10000', repeat('1',10000)); -- toast uncompressed INSERT INTO t VALUES ('external-1000000', repeat('2',1000000)); -- toast uncompressed ALTER TABLE t ALTER COLUMN b SET STORAGE EXTENDED; INSERT INTO t VALUES ('extended-10', 'extended'); -- inline INSERT INTO t VALUES ('extended-10000', repeat('3',10000)); -- inline compressed INSERT INTO t VALUES ('extended-1000000', repeat('4',1000000)); -- toast compressed -- call pg_toastinfo and pg_toastpointer twice in parallel to check the typlen caching -- for pg_toastinfo, just show if an oid was returned or now SELECT a, pg_toastinfo(a) a, pg_toastpointer(a) > 0 aptr, pg_toastinfo(b) b, pg_toastpointer(b) > 0 bptr FROM t; a | a | aptr | b | bptr ------------------+----------------------+------+---------------------------------+------ null | short inline varlena | | null | default | short inline varlena | | short inline varlena | external-10 | short inline varlena | | short inline varlena | external-10000 | short inline varlena | | toasted varlena, uncompressed | t external-1000000 | short inline varlena | | toasted varlena, uncompressed | t extended-10 | short inline varlena | | short inline varlena | extended-10000 | short inline varlena | | long inline varlena, compressed | extended-1000000 | short inline varlena | | toasted varlena, compressed | t (8 rows) -- give t's toast table a predictable name we can use below DO $$ DECLARE o oid; BEGIN SELECT oid INTO o FROM pg_class WHERE relname = 't'; EXECUTE format('CREATE VIEW t_toast AS SELECT * FROM pg_toast.pg_toast_%s', o); END; $$ LANGUAGE plpgsql; -- manually retrieve the toast content for some datums SELECT a, substr(chunk_data, 1, 10) FROM t JOIN t_toast ON pg_toastpointer(t.b) = t_toast.chunk_id WHERE a ~ 'external' AND chunk_seq = 1 ORDER BY a; a | substr ------------------+------------------------ external-10000 | \x31313131313131313131 external-1000000 | \x32323232323232323232 (2 rows) toastinfo-1.1/sql/000077500000000000000000000000001326113555200141635ustar00rootroot00000000000000toastinfo-1.1/sql/toastinfo.sql000066400000000000000000000040101326113555200167050ustar00rootroot00000000000000CREATE EXTENSION toastinfo; CREATE TABLE x ( int int, bigint bigint, float float, numeric numeric, text text, bytea bytea ); INSERT INTO x VALUES(1, 1, 1, 1, '', ''); SELECT pg_toastinfo(int) AS int, pg_toastinfo(bigint) AS bigint, pg_toastinfo(float) AS float, pg_toastinfo(numeric) AS numeric, pg_toastinfo(text) AS text, pg_toastinfo(bytea) AS bytea FROM x; SELECT pg_toastpointer(int) AS int, pg_toastpointer(bigint) AS bigint, pg_toastpointer(float) AS float, pg_toastpointer(numeric) AS numeric, pg_toastpointer(text) AS text, pg_toastpointer(bytea) AS bytea FROM x; CREATE TABLE t ( a text, b text ); INSERT INTO t VALUES ('null', NULL); INSERT INTO t VALUES ('default', 'default'); ALTER TABLE t ALTER COLUMN b SET STORAGE EXTERNAL; INSERT INTO t VALUES ('external-10', 'external'); -- inline INSERT INTO t VALUES ('external-10000', repeat('1',10000)); -- toast uncompressed INSERT INTO t VALUES ('external-1000000', repeat('2',1000000)); -- toast uncompressed ALTER TABLE t ALTER COLUMN b SET STORAGE EXTENDED; INSERT INTO t VALUES ('extended-10', 'extended'); -- inline INSERT INTO t VALUES ('extended-10000', repeat('3',10000)); -- inline compressed INSERT INTO t VALUES ('extended-1000000', repeat('4',1000000)); -- toast compressed -- call pg_toastinfo and pg_toastpointer twice in parallel to check the typlen caching -- for pg_toastinfo, just show if an oid was returned or now SELECT a, pg_toastinfo(a) a, pg_toastpointer(a) > 0 aptr, pg_toastinfo(b) b, pg_toastpointer(b) > 0 bptr FROM t; -- give t's toast table a predictable name we can use below DO $$ DECLARE o oid; BEGIN SELECT oid INTO o FROM pg_class WHERE relname = 't'; EXECUTE format('CREATE VIEW t_toast AS SELECT * FROM pg_toast.pg_toast_%s', o); END; $$ LANGUAGE plpgsql; -- manually retrieve the toast content for some datums SELECT a, substr(chunk_data, 1, 10) FROM t JOIN t_toast ON pg_toastpointer(t.b) = t_toast.chunk_id WHERE a ~ 'external' AND chunk_seq = 1 ORDER BY a; toastinfo-1.1/toastinfo--1.sql000066400000000000000000000003171326113555200163270ustar00rootroot00000000000000CREATE FUNCTION pg_toastinfo("any") RETURNS cstring AS '$libdir/toastinfo' LANGUAGE C IMMUTABLE; CREATE FUNCTION pg_toastpointer("any") RETURNS oid AS '$libdir/toastinfo' LANGUAGE C IMMUTABLE STRICT; toastinfo-1.1/toastinfo.c000066400000000000000000000125351326113555200155440ustar00rootroot00000000000000/* Author: Christoph Berg Copyright: Copyright (c) 1996-2017, The PostgreSQL Global Development Group Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ #include #include #include #include #if PG_VERSION_NUM >= 90500 #include #endif #if PG_VERSION_NUM < 90400 /* * Macro to fetch the possibly-unaligned contents of an EXTERNAL datum * into a local "struct varatt_external" toast pointer. This should be * just a memcpy, but some versions of gcc seem to produce broken code * that assumes the datum contents are aligned. Introducing an explicit * intermediate "varattrib_1b_e *" variable seems to fix it. */ #define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr) \ do { \ varattrib_1b_e *attre = (varattrib_1b_e *) (attr); \ Assert(VARATT_IS_EXTERNAL(attre)); \ Assert(VARSIZE_EXTERNAL(attre) == sizeof(toast_pointer) + VARHDRSZ_EXTERNAL); \ memcpy(&(toast_pointer), VARDATA_EXTERNAL(attre), sizeof(toast_pointer)); \ } while (0) #endif PG_MODULE_MAGIC; char *toast_datum_info(Datum value); char * toast_datum_info(Datum value) { struct varlena *attr = (struct varlena *) DatumGetPointer(value); #if PG_VERSION_NUM >= 90400 if (VARATT_IS_EXTERNAL_ONDISK(attr)) #else if (VARATT_IS_EXTERNAL(attr)) #endif { struct varatt_external toast_pointer; VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr); if (toast_pointer.va_extsize < toast_pointer.va_rawsize - VARHDRSZ) return "toasted varlena, compressed"; else return "toasted varlena, uncompressed"; } #if PG_VERSION_NUM >= 90400 else if (VARATT_IS_EXTERNAL_INDIRECT(attr)) { struct varatt_indirect toast_pointer; VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr); return "indirect in-memory varlena"; } #endif #if PG_VERSION_NUM >= 90500 else if (VARATT_IS_EXTERNAL_EXPANDED(attr)) { return "expanded in-memory varlena"; } #endif else if (VARATT_IS_SHORT(attr)) { return "short inline varlena"; } else { if (VARATT_IS_COMPRESSED(attr)) return "long inline varlena, compressed"; else return "long inline varlena, uncompressed"; } } PG_FUNCTION_INFO_V1 (pg_toastinfo); Datum pg_toastinfo (PG_FUNCTION_ARGS); Datum pg_toastinfo (PG_FUNCTION_ARGS) { Datum value; char *result; int typlen; /* On first call, get the input type's typlen, and save at *fn_extra */ if (fcinfo->flinfo->fn_extra == NULL) { /* Lookup the datatype of the supplied argument */ Oid argtypeid = get_fn_expr_argtype(fcinfo->flinfo, 0); typlen = get_typlen(argtypeid); if (typlen == 0) /* should not happen */ elog(ERROR, "cache lookup failed for type %u", argtypeid); fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(int)); *((int *) fcinfo->flinfo->fn_extra) = typlen; } else typlen = *((int *) fcinfo->flinfo->fn_extra); if (PG_ARGISNULL(0)) result = "null"; else { value = PG_GETARG_DATUM(0); if (typlen == -1) { /* varlena type, possibly toasted */ result = toast_datum_info(value); } else if (typlen == -2) { /* cstring */ result = "cstring"; } else { /* ordinary fixed-width type */ result = "ordinary"; } } PG_RETURN_CSTRING(result); } PG_FUNCTION_INFO_V1 (pg_toastpointer); Datum pg_toastpointer (PG_FUNCTION_ARGS); Datum pg_toastpointer (PG_FUNCTION_ARGS) { Datum value = PG_GETARG_DATUM(0); int typlen; struct varlena *attr; struct varatt_external toast_pointer; /* On first call, get the input type's typlen, and save at *fn_extra */ if (fcinfo->flinfo->fn_extra == NULL) { /* Lookup the datatype of the supplied argument */ Oid argtypeid = get_fn_expr_argtype(fcinfo->flinfo, 0); typlen = get_typlen(argtypeid); if (typlen == 0) /* should not happen */ elog(ERROR, "cache lookup failed for type %u", argtypeid); fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(int)); *((int *) fcinfo->flinfo->fn_extra) = typlen; } else typlen = *((int *) fcinfo->flinfo->fn_extra); if (typlen != -1) /* not a varlena, return NULL */ PG_RETURN_NULL(); attr = (struct varlena *) DatumGetPointer(value); #if PG_VERSION_NUM >= 90400 if (!VARATT_IS_EXTERNAL_ONDISK(attr)) /* non-toasted varlena, return NULL */ #else if (!VARATT_IS_EXTERNAL(attr)) /* non-toasted varlena, return NULL */ #endif PG_RETURN_NULL(); VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr); PG_RETURN_OID(toast_pointer.va_valueid); } toastinfo-1.1/toastinfo.control000066400000000000000000000001241326113555200167710ustar00rootroot00000000000000default_version = '1' comment = 'show details on toasted datums' relocatable = true