diff --git a/META.in.json b/META.in.json index 6be26e2..461556b 100644 --- a/META.in.json +++ b/META.in.json @@ -2,7 +2,7 @@ "name": "test_factory", "abstract": "Framework for managing test data", "description": "Provides functions for registering commands to create test data and obtaining data during testing", - "version": "0.5.0", + "version": "1.0.0", "maintainer": "Jim Nasby ", "license": {"BSD 2 Clause": "http://opensource.org/licenses/bsd-license.php"}, @@ -12,31 +12,31 @@ "abstract": "Framework for managing test data", "file": "sql/test_factory.sql", "docfile": "doc/test_factory.asc", - "version": "0.5.0" + "version": "1.0.0" }, "test_factory_pgtap": { "abstract": "pgTap extension for test_factory", "file": "sql/test_factory_pgtap.sql", "docfile": "doc/test_factory.asc", - "version": "0.1.0" + "version": "1.0.0" } }, "release_status": "stable", - "generated_by": "Jim Nasby ", + "generated_by": "Jim Nasby ", "tags": [ "testing", "unit test", "tests", "test data", "test factory" ], "resources": { - "homepage": "http://github.com/BlueTreble/test_factory/", + "homepage": "http://github.com/Postgres-Extensions/test_factory/", "bugtracker": { - "web": "http://github.com/BlueTreble/test_factory/issues" + "web": "http://github.com/Postgres-Extensions/test_factory/issues" }, "repository": { - "url": "git://github.com/BlueTreble/test_factory.git", - "web": "http://github.com/BlueTreble/test_factory/", + "url": "git://github.com/Postgres-Extensions/test_factory.git", + "web": "http://github.com/Postgres-Extensions/test_factory/", "type": "git" } }, diff --git a/META.json b/META.json index c8db504..3378791 100644 --- a/META.json +++ b/META.json @@ -5,7 +5,7 @@ "name": "test_factory", "abstract": "Framework for managing test data", "description": "Provides functions for registering commands to create test data and obtaining data during testing", - "version": "0.5.0", + "version": "1.0.0", "maintainer": "Jim Nasby ", "license": {"BSD 2 Clause": "http://opensource.org/licenses/bsd-license.php"}, @@ -15,31 +15,31 @@ "abstract": "Framework for managing test data", "file": "sql/test_factory.sql", "docfile": "doc/test_factory.asc", - "version": "0.5.0" + "version": "1.0.0" }, "test_factory_pgtap": { "abstract": "pgTap extension for test_factory", "file": "sql/test_factory_pgtap.sql", "docfile": "doc/test_factory.asc", - "version": "0.1.0" + "version": "1.0.0" } }, "release_status": "stable", - "generated_by": "Jim Nasby ", + "generated_by": "Jim Nasby ", "tags": [ "testing", "unit test", "tests", "test data", "test factory" ], "resources": { - "homepage": "http://github.com/BlueTreble/test_factory/", + "homepage": "http://github.com/Postgres-Extensions/test_factory/", "bugtracker": { - "web": "http://github.com/BlueTreble/test_factory/issues" + "web": "http://github.com/Postgres-Extensions/test_factory/issues" }, "repository": { - "url": "git://github.com/BlueTreble/test_factory.git", - "web": "http://github.com/BlueTreble/test_factory/", + "url": "git://github.com/Postgres-Extensions/test_factory.git", + "web": "http://github.com/Postgres-Extensions/test_factory/", "type": "git" } }, diff --git a/pgxntool/HISTORY.asc b/pgxntool/HISTORY.asc index bedc0b5..d577192 100644 --- a/pgxntool/HISTORY.asc +++ b/pgxntool/HISTORY.asc @@ -1,3 +1,12 @@ +1.1.0 +----- +== Use unique database names for tests +Tests now use a unique database name based on the project name and a hash of the current directory. This prevents test conflicts when running tests for multiple projects in parallel. + +== Add 3-way merge support for setup files after pgxntool-sync +New `update-setup-files.sh` script handles merging changes to files initially copied by `setup.sh` (`.gitignore`, `test/deps.sql`). After running `make pgxntool-sync`, the script performs a 3-way merge if both you and pgxntool have modified the same file, using git's native conflict markers for resolution. + + 1.0.0 ----- == Fix broken multi-extension support diff --git a/pgxntool/base.mk b/pgxntool/base.mk index b03a5cc..5a4e232 100644 --- a/pgxntool/base.mk +++ b/pgxntool/base.mk @@ -64,6 +64,13 @@ TEST__SOURCE__SQL_FILES = $(patsubst $(TESTDIR)/input/%.source,$(TESTDIR)/sql/% TEST__SOURCE__EXPECTED_FILES = $(patsubst $(TESTDIR)/output/%.source,$(TESTDIR)/expected/%.out,$(TEST__SOURCE__OUTPUT_FILES)) REGRESS = $(sort $(notdir $(subst .source,,$(TEST_FILES:.sql=)))) # Sort is to get unique list REGRESS_OPTS = --inputdir=$(TESTDIR) --outputdir=$(TESTOUT) # See additional setup below + +# Generate unique database name for tests to prevent conflicts across projects +# Uses project name + first 5 chars of md5 hash of current directory +# This prevents multiple test runs in different directories from clobbering each other +REGRESS_DBHASH := $(shell echo $(CURDIR) | (md5 2>/dev/null || md5sum) | cut -c1-5) +REGRESS_DBNAME := $(or $(PGXN),regression)_$(REGRESS_DBHASH) +REGRESS_OPTS += --dbname=$(REGRESS_DBNAME) MODULES = $(patsubst %.c,%,$(wildcard src/*.c)) ifeq ($(strip $(MODULES)),) MODULES =# Set to NUL so PGXS doesn't puke @@ -291,17 +298,25 @@ print-% : ; $(info $* is $(flavor $*) variable set to "$($*)") @true # # This is setup to allow any number of pull targets by defining special # variables. pgxntool-sync-release is an example of this. -.PHONY: pgxn-sync-% +# +# After the subtree pull, we run update-setup-files.sh to handle files that +# were initially copied by setup.sh (like .gitignore). This script does a +# 3-way merge if both you and pgxntool changed the file. +.PHONY: pgxntool-sync-% pgxntool-sync-%: - git subtree pull -P pgxntool --squash -m "Pull pgxntool from $($@)" $($@) + @old_commit=$$(git log -1 --format=%H -- pgxntool/); \ + git subtree pull -P pgxntool --squash -m "Pull pgxntool from $($@)" $($@); \ + pgxntool/update-setup-files.sh "$$old_commit" pgxntool-sync: pgxntool-sync-release # DANGER! Use these with caution. They may add extra crap to your history and # could make resolving merges difficult! pgxntool-sync-release := git@github.com:decibel/pgxntool.git release pgxntool-sync-stable := git@github.com:decibel/pgxntool.git stable +pgxntool-sync-master := git@github.com:decibel/pgxntool.git master pgxntool-sync-local := ../pgxntool release # Not the same as PGXNTOOL_DIR! pgxntool-sync-local-stable := ../pgxntool stable # Not the same as PGXNTOOL_DIR! +pgxntool-sync-local-master := ../pgxntool master # Not the same as PGXNTOOL_DIR! distclean: rm -f $(PGXNTOOL_distclean) diff --git a/pgxntool/lib.sh b/pgxntool/lib.sh index c3eb88e..41de512 100644 --- a/pgxntool/lib.sh +++ b/pgxntool/lib.sh @@ -4,6 +4,23 @@ # This file is meant to be sourced by other scripts, not executed directly. # Usage: source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" +# ============================================================================= +# SETUP FILES CONFIGURATION +# ============================================================================= +# Files copied by setup.sh and tracked by update-setup-files.sh for sync updates. +# Format: "source_in_pgxntool:destination_in_project" +# ============================================================================= +SETUP_FILES=( + "_.gitignore:.gitignore" + "test/deps.sql:test/deps.sql" +) + +# Symlinks created by setup.sh and verified by update-setup-files.sh +# Format: "destination:target" +SETUP_SYMLINKS=( + "test/pgxntool:../pgxntool/test/pgxntool" +) + # Error function - outputs to stderr but doesn't exit # Usage: error "message" error() { diff --git a/pgxntool/setup.sh b/pgxntool/setup.sh index 08751f1..0a67f0e 100755 --- a/pgxntool/setup.sh +++ b/pgxntool/setup.sh @@ -39,21 +39,44 @@ safecp () { fi } -safecp pgxntool/_.gitignore .gitignore -safecp pgxntool/META.in.json META.in.json +# ============================================================================= +# SETUP FILES +# ============================================================================= +# SETUP_FILES and SETUP_SYMLINKS are defined in lib.sh +# These are also used by update-setup-files.sh for sync updates. +# ============================================================================= + +# Copy tracked setup files (defined in lib.sh) +for entry in "${SETUP_FILES[@]}"; do + src="pgxntool/${entry%%:*}" + dest="${entry##*:}" + # Create parent directory if needed + mkdir -p "$(dirname "$dest")" + safecp "$src" "$dest" +done +# Create tracked symlinks (defined in lib.sh) +for entry in "${SETUP_SYMLINKS[@]}"; do + dest="${entry%%:*}" + target="${entry##*:}" + mkdir -p "$(dirname "$dest")" + if [ ! -e "$dest" ]; then + echo "Creating symlink $dest -> $target" + ln -s "$target" "$dest" + git add "$dest" + else + echo "$dest already exists" + fi +done + +# META.in.json and Makefile are NOT in SETUP_FILES because users heavily customize them +safecp pgxntool/META.in.json META.in.json safecreate Makefile include pgxntool/base.mk make META.json git add META.json -mkdir -p sql test src - -cd test -mkdir -p sql -safecp ../pgxntool/test/deps.sql deps.sql -[ -d pgxntool ] || ln -s ../pgxntool/test/pgxntool . -git add pgxntool +mkdir -p sql test/sql src git status echo "If you won't be creating C code then you can: diff --git a/pgxntool/update-setup-files.sh b/pgxntool/update-setup-files.sh new file mode 100755 index 0000000..94ae75d --- /dev/null +++ b/pgxntool/update-setup-files.sh @@ -0,0 +1,176 @@ +#!/usr/bin/env bash +# +# update-setup-files.sh - Update files that were initially copied by setup.sh +# +# This script handles the 3-way merge of setup files after a pgxntool subtree +# update. It compares the old pgxntool version, new pgxntool version, and +# user's current file to determine the appropriate action: +# +# 1. If pgxntool didn't change the file: skip (nothing to do) +# 2. If user hasn't modified the file: auto-update +# 3. If both changed: 3-way merge with conflict markers +# +# Usage: update-setup-files.sh +# +# The old commit is the pgxntool subtree commit BEFORE the sync. + +set -o errexit -o errtrace -o pipefail +trap 'echo "Error on line ${LINENO}"' ERR + +PGXNTOOL_DIR="$(dirname "${BASH_SOURCE[0]}")" +source "$PGXNTOOL_DIR/lib.sh" + +# SETUP_FILES and SETUP_SYMLINKS are defined in lib.sh + +# ============================================================================= +# Functions +# ============================================================================= + +usage() { + echo "Usage: $0 " + echo + echo "Updates setup files after a pgxntool subtree sync." + echo + echo "Arguments:" + echo " old-pgxntool-commit The pgxntool commit hash BEFORE the sync" + exit 1 +} + +# Get file content from a specific commit +# Usage: get_old_content +get_old_content() { + local commit=$1 + local path=$2 + git show "${commit}:pgxntool/${path}" 2>/dev/null +} + +# Get current file content from pgxntool directory +# Usage: get_new_content +get_new_content() { + local path=$1 + cat "pgxntool/${path}" 2>/dev/null +} + +# Process a single setup file +# Usage: process_file +process_file() { + local source=$1 + local dest=$2 + local old_commit=$3 + + # Get the three versions + local old_content new_content user_content + + old_content=$(get_old_content "$old_commit" "$source") || { + debug 20 "Could not get old version of $source (new file in pgxntool?)" + old_content="" + } + + new_content=$(get_new_content "$source") || { + error "Could not read pgxntool/$source" + return 1 + } + + # Check if destination exists + if [[ ! -e "$dest" ]]; then + echo " $dest: creating (file was missing)" + cp "pgxntool/$source" "$dest" + return 0 + fi + + user_content=$(cat "$dest") + + # Step 1: Did pgxntool change this file? + if [[ "$old_content" == "$new_content" ]]; then + debug 30 "$dest: pgxntool unchanged, skipping" + return 0 + fi + + # Step 2: Did user modify their copy? + if [[ "$user_content" == "$old_content" ]]; then + echo " $dest: updated (you hadn't modified it)" + cp "pgxntool/$source" "$dest" + return 0 + fi + + # Step 3: Both changed - need 3-way merge + echo " $dest: attempting 3-way merge..." + + # Create temp files for git merge-file + local tmp_old tmp_new + tmp_old=$(mktemp) + tmp_new=$(mktemp) + trap "rm -f '$tmp_old' '$tmp_new'" RETURN + + echo "$old_content" > "$tmp_old" + echo "$new_content" > "$tmp_new" + + # git merge-file modifies the first file in place + # Returns 0 on clean merge, >0 if conflicts (but still writes result) + if git merge-file -L "yours" -L "old pgxntool" -L "new pgxntool" \ + "$dest" "$tmp_old" "$tmp_new"; then + echo " $dest: merged cleanly (please review)" + else + echo " $dest: CONFLICTS - resolve manually" + fi +} + +# Process a symlink +# Usage: process_symlink +process_symlink() { + local dest=$1 + local target=$2 + + if [[ -L "$dest" ]]; then + local current_target + current_target=$(readlink "$dest") + if [[ "$current_target" == "$target" ]]; then + debug 30 "$dest: symlink unchanged" + else + echo " $dest: symlink points to '$current_target', expected '$target'" + echo " (not auto-fixing - please check manually)" + fi + elif [[ -e "$dest" ]]; then + echo " $dest: exists but is not a symlink (expected symlink to $target)" + else + echo " $dest: creating symlink to $target" + ln -s "$target" "$dest" + fi +} + +# ============================================================================= +# Main +# ============================================================================= + +[[ $# -eq 1 ]] || usage + +old_commit=$1 + +# Verify we're in a git repo with pgxntool subtree +[[ -d "pgxntool" ]] || die 1 "pgxntool directory not found. Run from project root." +[[ -d ".git" ]] || die 1 "Not in a git repository." + +# Verify the old commit is valid +if ! git cat-file -e "${old_commit}^{commit}" 2>/dev/null; then + die 1 "Invalid commit: $old_commit" +fi + +echo "Checking setup files for updates..." +echo + +# Process regular files +for entry in "${SETUP_FILES[@]}"; do + source="${entry%%:*}" + dest="${entry##*:}" + process_file "$source" "$dest" "$old_commit" +done + +# Process symlinks +for entry in "${SETUP_SYMLINKS[@]}"; do + dest="${entry%%:*}" + target="${entry##*:}" + process_symlink "$dest" "$target" +done + +echo +echo "Done. Review changes with 'git diff' and commit when ready." diff --git a/sql/test_factory--1.0.0.sql b/sql/test_factory--1.0.0.sql new file mode 100644 index 0000000..636bcb5 --- /dev/null +++ b/sql/test_factory--1.0.0.sql @@ -0,0 +1,264 @@ +/* DO NOT EDIT - AUTO-GENERATED FILE */ +CREATE TEMP TABLE original_role ON COMMIT DROP AS SELECT current_user AS original_role; + +GRANT SELECT ON pg_temp.original_role TO public; +DO $body$ +BEGIN + CREATE ROLE test_factory__owner; +EXCEPTION + WHEN duplicate_object THEN + NULL; +END +$body$; + +CREATE SCHEMA tf AUTHORIZATION test_factory__owner; +COMMENT ON SCHEMA tf IS $$Test factory. Tools for maintaining test data.$$; +GRANT USAGE ON SCHEMA tf TO public; + +CREATE SCHEMA _tf AUTHORIZATION test_factory__owner; +-- Sucks that we have to do this. Need community to separate visibility and usage. +GRANT USAGE ON SCHEMA _tf TO public; + +CREATE SCHEMA _test_factory_test_data AUTHORIZATION test_factory__owner; + +-- Need to be SU +CREATE OR REPLACE FUNCTION _tf.schema__getsert( +) RETURNS name SECURITY DEFINER SET search_path = pg_catalog LANGUAGE plpgsql AS $body$ +BEGIN + /* + IF NOT EXISTS( SELECT 1 FROM pg_namespace WHERE nspname = '_test_data' ) THEN + CREATE SCHEMA _test_data AUTHORIZATION test_factory__owner; + END IF; + */ + + RETURN '_test_factory_test_data'; +END +$body$; + +SET LOCAL ROLE test_factory__owner; + +CREATE TYPE tf.test_set AS ( + set_name text + , insert_sql text +); + +CREATE TABLE _tf._test_factory( + factory_id SERIAL NOT NULL PRIMARY KEY + , table_oid regclass NOT NULL -- Can't do a FK to a catalog + , set_name text NOT NULL + , insert_sql text NOT NULL + , UNIQUE( table_oid, set_name ) +); +SELECT pg_catalog.pg_extension_config_dump('_tf._test_factory', ''); +SELECT pg_catalog.pg_extension_config_dump('_tf._test_factory_factory_id_seq', ''); + + +CREATE OR REPLACE FUNCTION _tf.data_table_name( + table_name text -- Sanitized by tf.test_factory__get() + , set_name _tf._test_factory.set_name%TYPE +) RETURNS name LANGUAGE plpgsql AS $body$ +DECLARE + v_factory_id_text text; + v_table_name name; + + v_name name; +BEGIN + SELECT + -- Get a fixed-width representation of ID. btrim shouldn't be necessary but it is + '_' || btrim( to_char( + factory_id + -- Get a string of 0's long enough to hold a max-sized int + , repeat( '0', length( (2^31-1)::int::text ) ) + ) ) + , c.relname + INTO v_factory_id_text, v_table_name + FROM tf.test_factory__get( table_name, set_name ) f + JOIN pg_class c ON c.oid = f.table_oid + JOIN pg_namespace n ON n.oid = c.relnamespace + ; + + v_name := v_table_name || v_factory_id_text; + + -- Was the name truncated? + IF v_name <> (v_table_name || v_factory_id_text) THEN + v_name := substring( v_table_name, length(v_name) - length(v_factory_id_text ) ) + || v_factory_id_text + ; + END IF; + + RETURN v_name; +END +$body$; + + +CREATE OR REPLACE FUNCTION _tf.test_factory__get( + table_name text -- Sanitized by tf.test_factory__get() + , set_name _tf._test_factory.set_name%TYPE + , table_oid oid -- Must be passed in because of forced search_path +) RETURNS _tf._test_factory SECURITY DEFINER SET search_path = pg_catalog LANGUAGE plpgsql AS $body$ +DECLARE + v_test_factory _tf._test_factory; +BEGIN + SELECT * INTO STRICT v_test_factory + FROM _tf._test_factory tf + WHERE tf.table_oid = test_factory__get.table_oid + AND tf.set_name = test_factory__get.set_name + ; + + RETURN v_test_factory; +EXCEPTION + WHEN no_data_found THEN + RAISE 'No factory found for table "%", set name "%"', table_name, set_name; +END +$body$; +CREATE OR REPLACE FUNCTION tf.test_factory__get( + table_name text + , set_name _tf._test_factory.set_name%TYPE +) RETURNS _tf._test_factory LANGUAGE sql AS $body$ +SELECT * FROM _tf.test_factory__get(table_name, set_name, table_name::regclass) +$body$; + + +CREATE OR REPLACE FUNCTION _tf.test_factory__set( + table_oid regclass + , set_name text + , insert_sql text +) RETURNS void SECURITY DEFINER SET search_path = pg_catalog LANGUAGE plpgsql AS $body$ +BEGIN + UPDATE _tf._test_factory + SET insert_sql = test_factory__set.insert_sql + WHERE _test_factory.table_oid = test_factory__set.table_oid + AND _test_factory.set_name = test_factory__set.set_name + ; + /* + * There shouldn't be concurrency conflicts here. If there are I think it's + * better to error than UPSERT. + */ + IF NOT FOUND THEN + INSERT INTO _tf._test_factory( table_oid, set_name, insert_sql ) + VALUES( table_oid, set_name, insert_sql ) + ; + END IF; +END +$body$; + + +CREATE OR REPLACE FUNCTION tf.register( + table_name text + , test_sets tf.test_set[] +) RETURNS void LANGUAGE plpgsql AS $body$ +DECLARE + c_table_oid CONSTANT regclass := table_name; + v_set tf.test_set; +BEGIN + FOREACH v_set IN ARRAY test_sets LOOP + PERFORM _tf.test_factory__set( + c_table_oid + , v_set.set_name + , v_set.insert_sql + ); + END LOOP; +END +$body$; + + +CREATE OR REPLACE FUNCTION _tf.table_create( + table_name text +) RETURNS void SECURITY DEFINER SET search_path = pg_catalog LANGUAGE plpgsql AS $body$ +DECLARE + c_td_schema CONSTANT name := _tf.schema__getsert(); + sql text; +BEGIN + sql := format( + $sql$ +CREATE TABLE %I.%I AS SELECT * FROM pg_temp.%2$I; + $sql$ + , c_td_schema + , table_name + ); + RAISE DEBUG 'sql = %', sql; + EXECUTE sql; +END +$body$; + +CREATE OR REPLACE FUNCTION tf.get( + table_type anyelement + , set_name text +) RETURNS SETOF anyelement LANGUAGE plpgsql AS $body$ +DECLARE + c_table_name CONSTANT text := pg_typeof(table_type); + c_data_table_name CONSTANT name := _tf.data_table_name( c_table_name, set_name ); +BEGIN + -- SEE BELOW AS WELL + RETURN QUERY SELECT * FROM _tf.get(table_type, set_name, c_data_table_name); +EXCEPTION + WHEN undefined_table THEN + DECLARE + create_sql text; + BEGIN + -- TODO: Create temp table with caller security then create permanent table as test_factory__owner + SELECT format( + $$ +CREATE TEMP TABLE %I ON COMMIT DROP AS +WITH i AS ( + %s + ) + SELECT * + FROM i +; +GRANT SELECT ON pg_temp.%1$I TO test_factory__owner; +$$ + , c_data_table_name + , factory.insert_sql + ) + INTO create_sql + FROM tf.test_factory__get( c_table_name, set_name ) factory + ; + RAISE DEBUG 'sql = %', create_sql; + EXECUTE create_sql; + PERFORM _tf.table_create( c_data_table_name ); + + -- SEE ABOVE AS WELL + RETURN QUERY SELECT * FROM _tf.get(table_type, set_name, c_data_table_name); + + -- Can't do this in the secdef function because it doesn't own it. + EXECUTE format( 'DROP TABLE pg_temp.%I', c_data_table_name ); + END; +END +$body$; + +CREATE OR REPLACE FUNCTION _tf.get( + table_type anyelement -- Sanitized by tf.test_factory__get() + , set_name text + , data_table_name name +) RETURNS SETOF anyelement SECURITY DEFINER SET search_path = pg_catalog LANGUAGE plpgsql AS $body$ +DECLARE + c_table_name CONSTANT text := pg_typeof(table_type); + c_td_schema CONSTANT name := _tf.schema__getsert(); + + sql text; +BEGIN + sql := format( + 'SELECT * FROM %I.%I AS t' + , c_td_schema + , data_table_name + ); + RAISE DEBUG 'sql = %', sql; + + RETURN QUERY EXECUTE sql; +END +$body$; + +--select (tf.get('moo','moo')::moo).*; +DO $body$ +DECLARE + c_sql CONSTANT text := 'SET ROLE ' || (SELECT original_role FROM pg_temp.original_role); +BEGIN + --RAISE WARNING 'c_sql = %', c_sql; + EXECUTE c_sql; +END +$body$; + +DROP TABLE pg_temp.original_role; + +-- vi: expandtab ts=2 sw=2 diff --git a/sql/test_factory_pgtap--1.0.0.sql b/sql/test_factory_pgtap--1.0.0.sql new file mode 100644 index 0000000..67e2a94 --- /dev/null +++ b/sql/test_factory_pgtap--1.0.0.sql @@ -0,0 +1,41 @@ +/* DO NOT EDIT - AUTO-GENERATED FILE */ +CREATE TEMP TABLE original_role ON COMMIT DROP AS SELECT current_user AS original_role; +GRANT SELECT ON pg_temp.original_role TO public; + +SET LOCAL ROLE test_factory__owner; + +CREATE OR REPLACE FUNCTION tf.tap( + table_name text + , set_name text DEFAULT 'base' +) RETURNS SETOF text LANGUAGE plpgsql AS $body$ +DECLARE + c_table CONSTANT regclass := table_name; +BEGIN + RETURN NEXT isnt_empty( + format( + $$SELECT tf.get( NULL::%s, %L )$$ -- We assume regclass::text gives us valid output + , c_table + , set_name + ) + , format( + 'Get test data set "%s" for table %s' + , set_name + , c_table + ) + ); +END +$body$; + +-- Set role back to original value +DO $body$ +DECLARE + c_sql CONSTANT text := 'SET ROLE ' || (SELECT original_role FROM pg_temp.original_role); +BEGIN + --RAISE WARNING 'c_sql = %', c_sql; + EXECUTE c_sql; +END +$body$; + +DROP TABLE pg_temp.original_role; + +-- vi: expandtab ts=2 sw=2 diff --git a/test_factory.control b/test_factory.control index a18e438..fabea06 100644 --- a/test_factory.control +++ b/test_factory.control @@ -1,3 +1,3 @@ comment = 'A framework for managing test data' -default_version = '0.5.0' +default_version = '1.0.0' relocatable = false diff --git a/test_factory_pgtap.control b/test_factory_pgtap.control index 8e4a75f..9696b14 100644 --- a/test_factory_pgtap.control +++ b/test_factory_pgtap.control @@ -1,4 +1,4 @@ comment = 'A framework for managing test data' -default_version = '0.1.0' +default_version = '1.0.0' relocatable = false requires = 'pgtap, test_factory'