pgtap-0.90.0/000755 000765 000024 00000000000 11666503077 013160 5ustar00davidstaff000000 000000 pgtap-0.90.0/._Changes000644 000765 000024 00000000252 11666501762 014666 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/Changes000644 000765 000024 00000066260 11666501762 014464 0ustar00davidstaff000000 000000 Revision history for pgTAP ========================== 0.90.0 2011-12-03T20:18:16Z --------------------------- * Removed the "Supported Versions" section of the documentation. Suffice it to say that pgTAP supports PostgreSQL 8.0 or higher. * Added a build target to create a portable copy of pgTAP that can be included in any distribution and should just work for tesing on PostgreSQL 8.3+. The new files are `pgtap-core.sql`, which contains the core functionality, and `pgtap-schema.sql`, which depends on pgtap-core and adds in the schema testing assertion functions. * Added abstract to the `provides` section of `META.json`. * Removed use of `relistemp` column in an internal function, as it has been removed in PostgreSQL 9.1. As a bonus, it now works on PostgreSQL 8.3 and older without needing to be patched. Thanks to Tom Lane for the alternate syntax. * Added PostreSQL 9.1 `CREATE EXTENSION` support. * Removed `TAPSCHEMA` option to `make`. Use `PGOPTIONS=--search_path=tap` with `psql`, instead. * Added `db_owner_is()`. Based on a patch by Gerd Koenig. * Dropped support for PostgreSQL 8.0, as the new directory structure introduced in 0.25.0 is incompatible with the 8.0 version og `pg_regress`, making testing all but impossible. 8.0 has been EOLed for some time, so it's time for pgTAP to finally drop its support, too. 0.25.0 2011-02-02T03:21:55Z --------------------------- * Minor documentation tweaks. * The sequence created to keep track of test numbers is now a temporary sequence. This will prevent it from persisting beyond the current connection, which could lead to erorrs in future connections. Thanks to Richard Huxton for the report. * Fixed `is_superuser()` and `isnt_superuser()` so that they properly detect superuser roles as well as users. * Fixed examples of single-quoted string values stored in `psql` variables in `README.pgtap`. * Fixed a bug in `plan()` where a sequence wasn't getting created as a temporary sequence. This wasn't a problem if all testing was done inside a transaction, but if not, you could only run tests once without an error. * Fixed bug where `has_column()`, `col_type_is()`, `domain_type_is()`, `cast_exists()`, `cast_context_is()`, and `has_operator()`, were forcing the type argument to lowercase, which wasn't correct when the type is actually mixed case or uppercase (that is, named in double quotes when it was created). * The expected type passed to `index_is_type()` is no longer compared case-insensitively, since it might be possible in the future to create a type with mixed case by using double quotes when naming it. * Documented that double-quotes must be used for types created with double-quoted names in the strings passed to `casts_are()`. This should be the only part of the API that does require this sort of quoting. * Added `diag(anyelement)` (for 8.3 and higher) and `diag(VARIADIC anyarray)` (for 8.4 and higher) to make it easier to emit diagnostics for whatever data you have at hand. * The `_cleanup()` function now properly drops the temporary sequences as well as the temporary tables. These are usually automatically dropped when the tests finish and the client disconnects, but it's best to try to keep things tidy ourselves, too. Spotted by Peter Eisentraut. * Fixed a bug in `has_pk()` so that it properly checks that a table is visible in the search path when a schema is not specified, and doesn't check that when the schema *is* specified. Patch from CΓ©dric Villemain. * Fixed a bug in `col_is_unique()` and `col_has_check()` where they considered *all* columns in a table that were unique or involved in a check constraint were assocated with only one constraint. Since one can have multiple unique or check constraints on a table, each using different columns, this was sub-optimal. Thanks to CΓ©dric Villemain for the spot! * Removed `pg_prove` and `pg_tapgen` from the distribution. They must now be installed separately from CPAN. If it's not installed, the intaller will issue a warning. * Added `META.json` and distributed on [PGXN](http://pgxn.org/). * Rearranged the source directory layout to more closely match the [preferred PGXN layout](http://manager.pgxn.org/howto#new-order). 0.24 2010-05-24T23:33:22Z -------------------------- * Got `sql/artap.sql` tests passing again when building with `$TAPSCHEMA` set. * Changed to saner source URL in `contrib/pgtap.spec`. * Fixed a bug in `has_member()` where it failed to confirm that users were actually members of a group. * Fixed a bug where `display_type()` would include the schema name in its output for types not found in the current path, despite its assertion that it wouldn't. * Changed the diagnostic output for row type mismatches from `set_eq()`, `set_ne()`, `bag_eq()`, and `bag_ne()` to include the schema name for types not found in the search path. * Fixed bug in the diagnostic output of `set_eq()`, `set_ne()`, `bag_eq()`, and `bag_ne()` where a column's type would not be displayed if the column was not in the search path. Thanks to Rod Taylor for the spot! * Made the implementation of `row_eq()` always return a value, even if the query it executes returns no rows. * Fixed bug in the default description for `col_type_is()` where the column name was listed as the type! * Updated the `Makefile` and the test suite to support PostgreSQL 9. * Removed the primary keys from the temporary tables used internally by pgTAP and thus eliminated the logging of NOTICEs to the PostgreSQL log when pgTAP creates those tables. * Eliminated the need to set `USE_PGXS=1` when building outsde the contrib directory of the PostgreSQL distribution. If `pg_config` isn't in the `$PATH` environment variable, one can simply set `PG_CONFIG` to point to it. If building inside the contrib directory, set `NO_PGXS=1`. * Fixed typo in the statement to drop the `tap_funky` view in `uninstall_pgtap.sql`. Thanks to Erik Rijkers. * Removed deprecated `can_ok()` functions. Use `has_function()`, instead. 0.23 2009-12-18T23:03:39Z ------------------------- * Fixed broken Perl detection in `Makefile`. * Copied OS detection from Perl's `Configure` script to new script, `getos.sh`. OS detection should now be much more accurate. * Fixed `pg_prove` to exit with non-zero status if tests failed, as it works better in automated testing environments and consistent with `prove` (fix by Darrell Fuhriman). * Updated documentation of supported environment variables in `bin/pg_prove`. * Fixed a bug in the function tests where the return value of a function was not always consistently formatted. For example, `function_returns()` would find "bool" instead of "boolean". * Added `isa_ok()`. * Added support for building against 8.5 [Dan Colish]. * Fixed failing test on alpha releases [Jonathan Leto] * Added `is_empty()` to test that a query returns an empty set (no results). * Added `collect_tap()`, which makes it easier to run multiple tests in a single `SELECT` statement in combination with `skip()`. * Added `throws_like()`, `throws_ilike()`, `throws_matching()`, and `throws_imatching()` to test that an SQL statement throws an error message matching a `LIKE` pattern or a regular expression. * Added `roles_are()`, `types_are()`, `domains_are()`, `enums_are()`, `triggers_are()`, `casts_are()`, `operators_are()`, and `columns_are()`. * Fixed the diagnostic output from `isnt()` and `col_isnt_pk()` when they fail. They now more closely matches what Test::More's `isnt()` outputs and makes much more sense. * Added `domain_type_is()` and `domain_type_isnt()`. Based on an implementation by Bob Lunney. * Added variants of `col_is_type()` to allow a schema name to be specified for the type. * Added `display_type()` and replaced all internal use of `format_type()` with it. This is so that schemas are always displayed properly. * Added `row_eq()`. It's a 90% solution that requires that `record` values be cast to existing composite values. But it should work well even at that. * Changed the default descriptions output by `has_operator()`, `has_leftop()`, and `has_rightop()` to format the operator names more like the display of `regoperator` types. * Fixed issue with using SET SESSION AUTHORIZATION among tests [Kevin Field] * Added `display_oper()` so that schemas are always displayed properly when comparing operators. 0.22 2009-07-31T00:26:16Z ------------------------- * Fixed failing test on 8.4rc2. * Added result set testing functions. These allow testers to write queries in pure SQL and check that their results are as expected. The new functions are: + `results_eq()` + `results_ne()` + `set_eq()` + `bag_eq()` + `set_ne()` + `bag_ne()` + `set_has()` + `bag_has()` + `set_hasnt()` + `bag_hasnt()` * Changed some internal queries to use explicit `JOIN`s. * Fixed capitalization of `TAP::Harness` in the `Makefile`. Thanks to Quinn Weaver. * Fixed a syntax error that caused `uninstall_pgtap.sql` to fail on older PostgreSQL versions (fix by Quinn Weaver). * Modified the summary documentation for the `--schema` and `--match` options to `pg_prove` to better reflect that they are for finding xUnit tests, not for finding pgTAP functions. 0.21 2009-05-29T00:04:31Z ------------------------- * Fixed a bug in the processing of the `--schema` and `--match` options that only shows up in Getopt::Long 2.38 or higher. * A few doc and test typos fixed thanks to Gabrielle Roth. * Fixed failing test on Solaris 10 on Intel thanks to Gabrielle Roth. * Fixed a failing test for the version number string on 8.4 beta. * Added `performs_ok()`. * Added `has_language()`, `hasnt_language()`, and `language_is_trusted()`. * Added `has_opclass()` and `hasnt_opclass()`. * Added `has_rule()`, `hasnt_rule()`, `rule_is_instead()`, and `rule_is_on()`. * Added `tablespaces_are()`, `schemas_are()`, `tables_are()`, `views_are()`, `sequences_are()`, `functions_are()`, `indexes_are()`, `users_are()`, `groups_are()`, `opclasses_are()`, `languages_are()`, and `rules_are()`. * Added a `has_trigger(table, trigger, description)`. Note that this means that if you were previously using `has_trigger(schema, table, trigger)`, you will need to cast the third argument to `NAME` to get it working again. * Changed `can_ok()` to `has_function()`, so that it's named like all of the other functions that check for the presence of database objects. The old `can_ok()` function is still available as an alias, but it emits a warning and will be removed in a future version of pgTAP. * Added `hasnt_trigger()`, `hasnt_index()`, and `hasnt_function()`. * Added `function_lang_is()`, `function_returns()`, `is_definer()`, `is_aggregate()`, `is_strict()`, and `volatility_is()`. 0.20 2009-03-29T19:05:40Z ------------------------- * Changed the names of the functions tested in `sql/do_tap.sql` and `sql/runtests.sql` so that they are less likely to be ordered differently given varying collation orders provided in different locales and by different vendors. Reported by Ingmar Brouns. * Added the `--formatter` and `--archive` options to `pg_prove`. * Fixed the typos in `pg_prove` where the output of `--help` listed `--test-match` and `--test-schema` instead of `--match` and `--schema`. * Added `has_cast()`, `hasnt_cast()`, and `cast_context_is()`. * Fixed a borked function signature in `has_trigger()`. * Added `has_operator()`, `has_leftop()`, and `has_rightop()`. * Fixed a bug where the order of columns found for multicolumn indexes by `has_index()` could be wrong. Reported by Jeff Wartes. Thanks to Andrew Gierth for help fixing the query. 0.19 2009-02-21T02:09:26Z ------------------------- * Added an alternate version of `col_default_is()` to better handle the common case when a default is specified as a string, such as a text or expression default. This means that you have to do a lot less casting of default values specified in the arguments to `col_default_is()`. It also restores the signature that 0.17 recommended be dropped. * Added `has_role()` and `isnt_role()`. * Added `has_user()`, `isnt_user()`, `is_superuser()`, and `isnt_superuser()`. * Added `has_group()`, `isnt_group()`, and `is_member_of()`. * Fixed syntax in the `Makefile` to make it compatible with older versions of `make`. Reported by Aaron Kangas. * Improved the documentation of `runtests()` to make it clearer that all tests it runs are run in transactions that are rolled back after each test. Suggested by Aaron Kangas. * Added the `--runtests`, `--schema`, and `--match` options to `pg_prove` so that it can be used to run xUnit-style test functions without an SQL script. * Fixed a bug in `can()` where it could sometimes report that functions were available in a schema when in fact they were not. * In the schema testing functions, removed the use of `quote_ident()` to compare all identifiers, such as table names, schema names, column names, etc, added in 0.17. This is because `quote_ident(a) = quote_ident(b)` can't give a different result than `a = b`, and besides, made things slower and prevented the use of indexes. Thanks to Andrew Gierth for the spot. * The output from `pg_prove` now includes a list of failing tests when it is not run with `--verbose`. When using TAP::Harness 3.17 and later, it also shows comments and diagnostics in the non-verbose output. Verbose output still outputs everything. 0.18 2009-02-06T20:06:00Z -------------------------- * Fixed `pg_version_num()`. It was broken in 0.16; sorry about that! * Fixed a bug in `col_type_is()` where it would die if it was looking for a type in a table that had dropped columns. Thanks to depesz and RhodiumToad on #postgresql for the help nailing that one down! * Fixed a test failure in `sql/coltap.sql` on PostgreSQL 8.3. * Fixed a bug in the `Makefile` where it did not properly point to `pg_config` when building from the `compat` directory in the PostgreSQL source tree. * Fixed a bug in the `Makefile` where the `test_setup.sql` file, which is required for tests, was not always getting created. 0.17 2009-02-06T17:51:52Z -------------------------- * Fixed `col_default_is()` so that it works properly in cases where the default value is `NULL`. * Fixed `col_default_is()` to gracefully handle different data types, columns without defaults, and nonexistent columns. * Fixed the three-argument form of `col_default_is()` to accept any data type for the default, not just text. *NOTE:* You must `DROP FUNCTION col_default_is ( NAME, NAME, TEXT );` if you have previous versions of this function installed, so as to eliminate the incompatible version. * Added `col_has_default()` and `col_hasnt_default()`. * Changed default descriptions for column testing functions to refer to the columns as the more SQL-standard `schema.table.column` instead of `schema.table(column)`. * Modified all diagnostic messages and test descriptions that reference database objects to use `quote_ident()` to quote the names of those objects, rather than emitting them with or without double-quotes in an ad-hoc way as had hitherto been the case. * Modified `col_not_null()`, `col_is_null()` and `col_type_is()` to emit diagnostics if they fail because the column in question does not exist. * Added `has_tablespace()` and `hasnt_tablespace()`. * Added `has_sequence()` and `hasnt_sequence()`. * Changed `has_index()` so that expressions are compared case- sensitively. * In the schema testing functions, now using `quote_ident()` to compare all identifiers, such as table names, schema names, column names, etc. It had been a mix of straight-forward string comparison, and case-insensitive matching. This means that tests should use only lowercase strings to specify object names, unless mixed case objects were created with double quote characters. * Added version of `todo()` with the `why` and `how_many` arguments reversed, so that I don't have to remember a specific order. 0.16 2009-02-03T17:37:03Z -------------------------- * Switched from a crazy trinary logic in `is()` and `isnt()` to the use of `IS NOT DISTINCT FROM` and `IS DISTINCT FROM`. Swiped from PGUnit. * Fixed documentation for the short version of `--help` in `pg_prove`. It's `-H`, not `-h`. * Fixed a bug in the makefile that prevented OS detection from working properly on many platforms (including Linux, and probably many others). This allows `os_name()` to actually work on those platforms. * The definition of the `pg_typeof()` function is removed when installing on PostgreSQL 8.4 and no C code is compiled, since the only C code is for this function. This is because `pg_typeof()` is included with PostgreSQL 8.4. * Added `has_schema()` and `hasnt_schema()`. * Added `has_type()`, `hasnt_type()`, `has_domain()`, `hasnt_domain()`, `has_enum()`, and `hasnt_enum()`. * Added `enum_has_labels()`. * Updated the `Makefile` to fix the shebang line in `pg_prove` if Perl is found, and to emit a warning if the `$PERL` variable is not set. - Updated the `Makefile` so that if `$PERL` is set and TAP::Harness is not installed, it warns the user to install it in order to use `pg_prove`. - Updated the `Makefile` to set the location of the `psql` binary to the bin directory specified for PostgreSQL when it was built. * Fixed `pg_version_num()` to work on PostgreSQL 8.4devel. * Fixed test failures on PostgreSQL 8.4devel. 0.15 2009-01-20T18:41:24Z -------------------------- * Changed `pg_typeof()` from immutable to stable, in compliance with its configuration in the forthcoming PostgreSQL 8.4. * Added `do_tap()`, which finds test functions and runs them, allowing tap tests to be embedded in functions and then executed all at once. * Added `runtests()`, which introduces xUnit-style test running, for those who prefer to put their tests in a slew of test functions and then run one function to run all of the test functions (plus startup, setup, teardown, and shutdown tests). * Added `findfuncs()`, which is used by `do_tap()` to find the functions to execute. * The `col_type_is()` function now requires that the type be visible in the search path when it is called without a schema argument. * The `plan()` function no longer resets the `client_min_messages` setting to its default value, but leaves it set to whatever it was set to before the function was called. * Fixed a typo in the documentation of the short version of the `--version` option to `pg_prove`, which is `-V`, not `-v`. * Added `pgtap_version()`. * Added the "html" make target to generate the HTML documentation for the Web site, including a table of contents and documentation for `pg_prove`. 0.14 2008-10-27T22:43:36Z -------------------------- * Added `SET search_path` statements to `uninstall_pgtap.sql.in` so that it will work properly when TAP is installed in its own schema. Thanks to Ben for the catch! * Added commands to drop `pg_version()` and `pg_version_num()` to`uninstall_pgtap.sql.in`. * Added `has_index()`, `index_is_unique()`, `index_is_primary()`, `is_clustered()`, and `index_is_type()`. * Added `os_name()`. This is somewhat experimental. If you have `uname`, it's probably correct, but assistance in improving OS detection in the `Makefile` would be greatly appreciated. Notably, it does not detect Windows. * Made `ok()` smarter when the test result is passed as `NULL`. It was dying, but now it simply fails and attaches a diagnostic message reporting that the test result was `NULL`. Reported by Jason Gordon. * Fixed an issue in `check_test()` where an extra character was removed from the beginning of the diagnostic output before testing it. * Fixed a bug comparing `name[]`s on PostgreSQL 8.2, previously hacked around. * Added `has_trigger()` and `trigger_is()`. * Switched to pure SQL implementations of the `pg_version()` and `pg_version_num()` functions, to simplify including pgTAP in module distributions. * Added a note to `README.pgtap` about the need to avoid `pg_typeof()` and `cmp_ok()` in tests run as part of a distribution. 0.13 2008-10-13T19:09:46Z -------------------------- * Added `pg_version()` and `pg_version_num()`. * Documented `pg_typeof()`. 0.12 2008-10-11T04:02:42Z -------------------------- * Updated `plan()` to disable warnings while it creates its tables. This means that `plan()` no longer send NOTICE messages when they run, although tests still might, depending on the setting of `client_min_messages`. * Added `hasnt_table()`, `hasnt_view()`, and `hasnt_column()`. * Added `hasnt_pk()`, `hasnt_fk()`, `col_isnt_pk()`, and `col_isnt_fk()`. * Added missing `DROP` statements to `uninstall_pgtap.sql.in`. 0.11 2008-09-24T20:41:42Z -------------------------- * Simplified the tests so that they now load `test_setup.sql` instead of setting a bunch of stuff themselves. Now only `test_setup.sql` needs to be created from `test_setup.sql.in`, and the other `.sql` files depend on it, meaning that one no longer has to specify `TAPSCHEMA` for any `make` target other than the default. * Eliminated all uses of `E''` in the tests, so that we don't have to process them for testing on 8.0. * Fixed the spelling of `ON_ROLLBACK` in the test setup. Can't believe I had it with one L in all of the test files before! Thanks to Curtis "Ovid" Poe for the spot. * Added a couple of variants of `todo()` and `skip()`, since I can never remember whether the numeric argument comes first or second. Thanks to PostgreSQL's functional polymorphism, I don't have to. Also, there are variants where the numeric value, if not passed, defaults to 1. * Updated the link to the pgTAP home page in `pgtap.sql.in`. * TODO tests can now nest. * Added `todo_start()`, `todo_end()`, and `in_todo()`. * Added variants of `throws_ok()` that test error messages as well as error codes. * Converted some more tests to use `check_test()`. * Added `can()` and `can_ok()`. * Fixed a bug in `check_test()` where the leading white space for diagnostic messages could be off by 1 or more characters. * Fixed the `installcheck` target so that it properly installs PL/pgSQL into the target database before the tests run. 0.10 2008-09-18T22:59:31Z -------------------------- * Changed `pg_prove` to set `QUIET=1` when it runs, so as to prevent the output of extraneous stuff. * Added some `GRANT` statements to `plan()` in order to make it easier to run tests using roles other than the one that called `plan()`. Patch from Rod Taylor. * Replaced a call to `lastval()` with a call to `currval()` in order to improve compatibility with PostgreSQL 8.0. Reported by David Westbrook. * Added support for TODO and SKIP tests. * Removed the few uses of named parameters and added alias names instead. This improves compatibility for versions of PostgreSQL prior to 8.0. Reported by David Westbrook. * Fixed the plural of "test" in the output from `finish()`. It was plural when there was one test and singular otherwise. So I reversed that. * Moved assignment to declared variables from the `DECLARE` block to the body of the functions. Improves compatibility with versions of PostgreSQL prior to 8.0. Reported by David Westbrook. * Eliminated passing the result of a function call to `RAISE` in order to better support older versions of PostgreSQL. Reported by David Westbrook. * Switched from using `FOUND` to `GET DIAGNOSTICS ROW_COUNT` because the former does not seem to be set for `EXECUTE` SQL in older versions of PostgreSQL. Reported by David Westbrook. * Added tests specifically targeting PostgreSQL 7.3. From David Westbrook. * Ported all the way back to PostgreSQL 8.0, thanks to some Makefile hackery and a patch file. All tests pass on 8.0, 8.1, 8.2, and 8.3. The only exception is `throws_ok()` and `lives_ok()`, which are not supported on 8.0. Versions of PostgreSQL lower than 8.0 are not yet supported, even though we have made some changes to simplify getting things to work in earlier versions. * Changed "got/expected" to "have/want", following Schwern's plans for Test::Builder 2. Also changed "caught/expected" to "caught/wanted" for nice parity when outputting diagnostics for exception testing. * Added the `has_table()`, `has_view()`, `has_column()`, `has_pk()`, `has_fk()`, `fk_ok()`, `has_unique()` and `has_check()` test functions. * Added the `col_not_null()` and `col_is_null()` test functions. * Added the `col_type_is()`, `col_default_is()`, `col_is_pk()`, `col_is_fk()`, `col_is_unique()`, and `col_has_check()` test functions. * Fixed `is()` and `isnt()` to better handle `NULL`s. * Added `cmp_ok()`. * Added the `--set ON_ERROR_STOP=1` option to the call to `psql` in `pg_prove`. * Renamed `drop_pgtap.sql.in` to `uninstall_pgtap.sql.in`, which is more in line with typical PostgreSQL contrib modules. * Removed verbose output of the `psql` command from `pg_prove`. Thanks to Andy Armstrong for the spot. * Divided the tests up into many separate test script files, so that things are a bit better organized and easier to maintain. * Added the `check_test()` function and started converting internal tests to use it instead of the hacked stuff they were doing before. * As in Test::Builder 0.81_01, changed the message for extra tests run to show the number of tests run rather than the number extra to avoid the user having to do mental math. * The regression test files are now processed by `make installcheck` and `make test` so that the schema can be properly set, if pgTAP is built with a schema. 0.02 2008-06-17T16:26:41Z -------------------------- * Converted the documentation to Markdown. * Added pg_prove, a Perl script that use TAP::Harness to run tests and report the results, just like the Perl program `prove`. * Fixed `no_plan()` so that it no longer emits a plan, which apparently was wrong. Now `finish()` outputs it when there's no plan. * Fixed the test script so that it now emits a proper plan. * Removed all of the configuration settings from `pgtap.sql`, as they're now handled by `pg_prove`. I've mentioned them in the README for reference. * Added `lives_ok()`. * Moved the creation of temporary tables into `plan()`, so that everything is properly self-contained. * Improved the handling of transactions. Test scripts are now assumed to be single transactions with a ROLLBACK at the end. This makes it so that test scripts don't have to include `drop_pgtap.sql`. * Updated `pg_prove` to rollback on an error, rather than just stop. This allows all test functions to be properly rolled back, too, in a test script that includes them but then encounters an unhandled exception. * Updated `pg_prove` to emit an appropriate error message if no test scripts are specified. * Added a Makefile. It uses the typical PostgreSQL installation procedures to install pgTAP. The SQL files have now been turned into `.in` templates that are processed by `make`. * Added support for schema qualification of test functions. Just set the `$TAPSCHEMA` environment variable when running `make`. * Added support for standard PostgreSQL-type regression testing by just copying the test script, setting some variables inside it, and providing an `expected/` directory. The test now lives in the `sql/` directory. * Changed all instances of `RETURN QUERY SELECT` to `RETURN NEXT`, which should allow pgtap to run on versions of PostgreSQL earlier than 8.3. Thanks to Neil Conway for the suggestion. 0.01 2008-06-07T05:24:27Z -------------------------- * Initial public release. Announcement at http://justatheory.com/computers/databases/postgresql/introducing_pgtap.html pgtap-0.90.0/compat/000755 000765 000024 00000000000 11666503077 014443 5ustar00davidstaff000000 000000 pgtap-0.90.0/contrib/000755 000765 000024 00000000000 11666503077 014620 5ustar00davidstaff000000 000000 pgtap-0.90.0/doc/000755 000765 000024 00000000000 11666503077 013725 5ustar00davidstaff000000 000000 pgtap-0.90.0/._getos.sh000644 000765 000024 00000000252 11666501762 015050 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/getos.sh000644 000765 000024 00000020470 11666501762 014637 0ustar00davidstaff000000 000000 #!/bin/sh uname=`which uname` sed=`which sed` tr=`which tr` myuname='' newmyuname='' trnl='' case "$test" in test) echo "Hopefully test is built into your sh." ;; *) if `sh -c "PATH= test true" >/dev/null 2>&1`; then # echo "Using the test built into your sh." test=test _test=test fi ;; esac : Find the appropriate value for a newline for tr if test -n "$DJGPP"; then trnl='\012' fi if test X"$trnl" = X; then case "`echo foo|tr '\n' x 2>/dev/null`" in foox) trnl='\n' ;; esac fi if test X"$trnl" = X; then case "`echo foo|tr '\012' x 2>/dev/null`" in foox) trnl='\012' ;; esac fi if test X"$trnl" = X; then case "`echo foo|tr '\r\n' xy 2>/dev/null`" in fooxy) trnl='\n\r' ;; esac fi if test X"$trnl" = X; then cat <&2 $me: Fatal Error: cannot figure out how to translate newlines with 'tr'. EOM exit 1 fi myuname=`$uname -a 2>/dev/null` $test -z "$myuname" && myuname=`hostname 2>/dev/null` # tr '[A-Z]' '[a-z]' would not work in EBCDIC # because the A-Z/a-z are not consecutive. myuname=`echo $myuname | $sed -e 's/^[^=]*=//' -e "s,['/],,g" | \ $tr '[A-Z]' '[a-z]' | $tr $trnl ' '` newmyuname="$myuname" : Half the following guesses are probably wrong... If you have better : tests or hints, please send them to perlbug@perl.org : The metaconfig authors would also appreciate a copy... $test -f /irix && osname=irix $test -f /xenix && osname=sco_xenix $test -f /dynix && osname=dynix $test -f /dnix && osname=dnix $test -f /lynx.os && osname=lynxos $test -f /unicos && osname=unicos && osvers=`$uname -r` $test -f /unicosmk && osname=unicosmk && osvers=`$uname -r` $test -f /unicosmk.ar && osname=unicosmk && osvers=`$uname -r` $test -f /bin/mips && /bin/mips && osname=mips $test -d /NextApps && set X `hostinfo | grep 'NeXT Mach.*:' | \ $sed -e 's/://' -e 's/\./_/'` && osname=next && osvers=$4 $test -d /usr/apollo/bin && osname=apollo $test -f /etc/saf/_sactab && osname=svr4 $test -d /usr/include/minix && osname=minix $test -f /system/gnu_library/bin/ar.pm && osname=vos if $test -d /MachTen -o -d /MachTen_Folder; then osname=machten if $test -x /sbin/version; then osvers=`/sbin/version | $awk '{print $2}' | $sed -e 's/[A-Za-z]$//'` elif $test -x /usr/etc/version; then osvers=`/usr/etc/version | $awk '{print $2}' | $sed -e 's/[A-Za-z]$//'` else osvers="$2.$3" fi fi $test -f /sys/posix.dll && $test -f /usr/bin/what && set X `/usr/bin/what /sys/posix.dll` && $test "$3" = UWIN && osname=uwin && osvers="$5" if $test -f $uname; then set X $myuname shift case "$5" in fps*) osname=fps ;; mips*) case "$4" in umips) osname=umips ;; *) osname=mips ;; esac;; [23]100) osname=mips ;; next*) osname=next ;; i386*) tmp=`/bin/uname -X 2>/dev/null|awk '/3\.2v[45]/{ print $(NF) }'` if $test "$tmp" != "" -a "$3" = "3.2" -a -f '/etc/systemid'; then osname='sco' osvers=$tmp elif $test -f /etc/kconfig; then osname=isc if test "$lns" = "$ln -s"; then osvers=4 elif $contains _SYSV3 /usr/include/stdio.h > /dev/null 2>&1 ; then osvers=3 elif $contains _POSIX_SOURCE /usr/include/stdio.h > /dev/null 2>&1 ; then osvers=2 fi fi tmp='' ;; pc*) if test -n "$DJGPP"; then osname=dos osvers=djgpp fi ;; esac case "$1" in aix) osname=aix tmp=`( (oslevel) 2>/dev/null || echo "not found") 2>&1` case "$tmp" in # oslevel can fail with: # oslevel: Unable to acquire lock. *not\ found) osvers="$4"."$3" ;; '<3240'|'<>3240') osvers=3.2.0 ;; '=3240'|'>3240'|'<3250'|'<>3250') osvers=3.2.4 ;; '=3250'|'>3250') osvers=3.2.5 ;; *) osvers=$tmp;; esac ;; bsd386) osname=bsd386 osvers=`$uname -r` ;; cygwin*) osname=cygwin osvers="$3" ;; *dc.osx) osname=dcosx osvers="$3" ;; dnix) osname=dnix osvers="$3" ;; domainos) osname=apollo osvers="$3" ;; dgux) osname=dgux osvers="$3" ;; dragonfly) osname=dragonfly osvers="$3" ;; dynixptx*) osname=dynixptx osvers=`echo "$4"|sed 's/^v//'` ;; freebsd) osname=freebsd osvers="$3" ;; genix) osname=genix ;; gnu) osname=gnu osvers="$3" ;; hp*) osname=hpux osvers=`echo "$3" | $sed 's,.*\.\([0-9]*\.[0-9]*\),\1,'` ;; irix*) osname=irix case "$3" in 4*) osvers=4 ;; 5*) osvers=5 ;; *) osvers="$3" ;; esac ;; linux) osname=linux case "$3" in *) osvers="$3" ;; esac ;; MiNT) osname=mint ;; netbsd*) osname=netbsd osvers="$3" ;; news-os) osvers="$3" case "$3" in 4*) osname=newsos4 ;; *) osname=newsos ;; esac ;; next*) osname=next ;; nonstop-ux) osname=nonstopux ;; openbsd) osname=openbsd osvers="$3" ;; os2) osname=os2 osvers="$4" ;; POSIX-BC | posix-bc ) osname=posix-bc osvers="$3" ;; powerux | power_ux | powermax_os | powermaxos | \ powerunix | power_unix) osname=powerux osvers="$3" ;; qnx) osname=qnx osvers="$4" ;; solaris) osname=solaris case "$3" in 5*) osvers=`echo $3 | $sed 's/^5/2/g'` ;; *) osvers="$3" ;; esac ;; sunos) osname=sunos case "$3" in 5*) osname=solaris osvers=`echo $3 | $sed 's/^5/2/g'` ;; *) osvers="$3" ;; esac ;; titanos) osname=titanos case "$3" in 1*) osvers=1 ;; 2*) osvers=2 ;; 3*) osvers=3 ;; 4*) osvers=4 ;; *) osvers="$3" ;; esac ;; ultrix) osname=ultrix osvers="$3" ;; osf1|mls+) case "$5" in alpha) osname=dec_osf osvers=`sizer -v | awk -FUNIX '{print $2}' | awk '{print $1}' | tr '[A-Z]' '[a-z]' | sed 's/^[xvt]//'` case "$osvers" in [1-9].[0-9]*) ;; *) osvers=`echo "$3" | sed 's/^[xvt]//'` ;; esac ;; hp*) osname=hp_osf1 ;; mips) osname=mips_osf1 ;; esac ;; # UnixWare 7.1.2 is known as Open UNIX 8 openunix|unixware) osname=svr5 osvers="$4" ;; uts) osname=uts osvers="$3" ;; vos) osvers="$3" ;; $2) case "$osname" in *isc*) ;; *freebsd*) ;; svr*) : svr4.x or possibly later case "svr$3" in ${osname}*) osname=svr$3 osvers=$4 ;; esac case "$osname" in svr4.0) : Check for ESIX if test -f /stand/boot ; then eval `grep '^INITPROG=[a-z/0-9]*$' /stand/boot` if test -n "$INITPROG" -a -f "$INITPROG"; then isesix=`strings -a $INITPROG|grep 'ESIX SYSTEM V/386 Release 4.0'` if test -n "$isesix"; then osname=esix4 fi fi fi ;; esac ;; *) if test -f /etc/systemid; then osname=sco set `echo $3 | $sed 's/\./ /g'` $4 if $test -f $src/hints/sco_$1_$2_$3.sh; then osvers=$1.$2.$3 elif $test -f $src/hints/sco_$1_$2.sh; then osvers=$1.$2 elif $test -f $src/hints/sco_$1.sh; then osvers=$1 fi else case "$osname" in '') : Still unknown. Probably a generic Sys V. osname="sysv" osvers="$3" ;; esac fi ;; esac ;; *) case "$osname" in '') : Still unknown. Probably a generic BSD. osname="$1" osvers="$3" ;; esac ;; esac else if test -f /vmunix -a -f $src/hints/news_os.sh; then (what /vmunix | UU/tr '[A-Z]' '[a-z]') > UU/kernel.what 2>&1 if $contains news-os UU/kernel.what >/dev/null 2>&1; then osname=news_os fi $rm -f UU/kernel.what elif test -d c:/. -o -n "$is_os2" ; then set X $myuname osname=os2 osvers="$5" fi fi case "$targetarch" in '') ;; *) hostarch=$osname osname=`echo $targetarch|sed 's,^[^-]*-,,'` osvers='' ;; esac : Now look for a hint file osname_osvers, unless one has been : specified already. case "$hintfile" in ''|' ') file=`echo "${osname}_${osvers}" | $sed -e 's%\.%_%g' -e 's%_$%%'` : Also try without trailing minor version numbers. xfile=`echo $file | $sed -e 's%_[^_]*$%%'` xxfile=`echo $xfile | $sed -e 's%_[^_]*$%%'` xxxfile=`echo $xxfile | $sed -e 's%_[^_]*$%%'` xxxxfile=`echo $xxxfile | $sed -e 's%_[^_]*$%%'` case "$file" in '') dflt=none ;; *) case "$osvers" in '') dflt=$file ;; *) if $test -f $src/hints/$file.sh ; then dflt=$file elif $test -f $src/hints/$xfile.sh ; then dflt=$xfile elif $test -f $src/hints/$xxfile.sh ; then dflt=$xxfile elif $test -f $src/hints/$xxxfile.sh ; then dflt=$xxxfile elif $test -f $src/hints/$xxxxfile.sh ; then dflt=$xxxxfile elif $test -f "$src/hints/${osname}.sh" ; then dflt="${osname}" else dflt=none fi ;; esac ;; esac if $test -f Policy.sh ; then case "$dflt" in *Policy*) ;; none) dflt="Policy" ;; *) dflt="Policy $dflt" ;; esac fi ;; *) dflt=`echo $hintfile | $sed 's/\.sh$//'` ;; esac echo $osname pgtap-0.90.0/._Makefile000644 000765 000024 00000000252 11666501762 015033 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/Makefile000644 000765 000024 00000013301 11666501762 014615 0ustar00davidstaff000000 000000 MAINEXT = pgtap EXTENSION = $(MAINEXT) pgtap-core pgtap-schema EXTVERSION = $(shell grep default_version $(MAINEXT).control | \ sed -e "s/default_version[[:space:]]*=[[:space:]]*'\([^']*\)'/\1/") NUMVERSION = $(shell echo $(EXTVERSION) | sed -e 's/\([[:digit:]]*[.][[:digit:]]*\).*/\1/') DATA = $(filter-out $(wildcard sql/*--*.sql),$(wildcard sql/*.sql)) TESTS = $(wildcard test/sql/*.sql) EXTRA_CLEAN = sql/pgtap.sql sql/uninstall_pgtap.sql sql/pgtap-core.sql sql/pgtap-schema.sql doc/*.html DOCS = doc/pgtap.mmd REGRESS = $(patsubst test/sql/%.sql,%,$(TESTS)) REGRESS_OPTS = --inputdir=test --load-language=plpgsql PG_CONFIG = pg_config ifdef NO_PGXS top_builddir = ../.. PG_CONFIG := $(top_builddir)/src/bin/pg_config/pg_config else # Run pg_config to get the PGXS Makefiles PG_CONFIG = pg_config PGXS := $(shell $(PG_CONFIG) --pgxs) endif # We need to do various things with the PostgreSQLl version. VERSION = $(shell $(PG_CONFIG) --version | awk '{print $$2}') # We support 8.1 and later. ifeq ($(shell echo $(VERSION) | grep -qE " 7[.]|8[.]0" && echo yes || echo no),yes) $(error pgTAP requires PostgreSQL 8.0 or later. This is $(VERSION)) endif # Compile the C code only if we're on 8.3 or older. ifeq ($(shell echo $(VERSION) | grep -qE "8[.][123]" && echo yes || echo no),yes) MODULES = src/pgtap endif # We need Perl. ifndef PERL PERL := $(shell which perl) endif # Load PGXS now that we've set all the variables it might need. ifdef NO_PGXS include $(top_builddir)/src/Makefile.global include $(top_srcdir)/contrib/contrib-global.mk else include $(PGXS) endif # Is TAP::Parser::SourceHandler::pgTAP installed? ifdef PERL HAVE_HARNESS := $(shell $(PERL) -le 'eval { require TAP::Parser::SourceHandler::pgTAP }; print 1 unless $$@' ) endif ifndef HAVE_HARNESS $(warning To use pg_prove, TAP::Parser::SourceHandler::pgTAP Perl module) $(warning must be installed from CPAN. To do so, simply run:) $(warning cpan TAP::Parser::SourceHandler::pgTAP) endif # Enum tests not supported by 8.2 and earlier. ifeq ($(shell echo $(VERSION) | grep -qE "8[.][12]" && echo yes || echo no),yes) TESTS := $(filter-out test/sql/enumtap.sql,$(TESTS)) REGRESS := $(filter-out enumtap,$(REGRESS)) endif # Values tests not supported by 8.1 and earlier. ifeq ($(shell echo $(VERSION) | grep -qE "8[.][1]" && echo yes || echo no),yes) TESTS := $(filter-out test/sql/enumtap.sql sql/valueset.sql,$(TESTS)) REGRESS := $(filter-out enumtap valueset,$(REGRESS)) endif # Determine the OS. Borrowed from Perl's Configure. OSNAME := $(shell ./getos.sh) # Make sure we build these. all: sql/pgtap.sql sql/uninstall_pgtap.sql sql/pgtap-core.sql sql/pgtap-schema.sql # Add extension build targets on 9.1 and up. ifeq ($(shell echo $(VERSION) | grep -qE "8[.]|9[.]0" && echo no || echo yes),yes) all: sql/$(MAINEXT)--$(EXTVERSION).sql sql/$(MAINEXT)-core--$(EXTVERSION).sql sql/$(MAINEXT)-schema--$(EXTVERSION).sql sql/$(MAINEXT)--$(EXTVERSION).sql: sql/$(MAINEXT).sql cp $< $@ sql/$(MAINEXT)-core--$(EXTVERSION).sql: sql/$(MAINEXT)-core.sql cp $< $@ sql/$(MAINEXT)-schema--$(EXTVERSION).sql: sql/$(MAINEXT)-schema.sql cp $< $@ DATA = $(wildcard sql/*--*.sql) sql/$(MAINEXT)--$(EXTVERSION).sql sql/$(MAINEXT)-core--$(EXTVERSION).sql sql/$(MAINEXT)-schema--$(EXTVERSION).sql EXTRA_CLEAN += sql/$(MAINEXT)--$(EXTVERSION).sql sql/$(MAINEXT)-core--$(EXTVERSION).sql sql/$(MAINEXT)-schema--$(EXTVERSION).sql endif sql/pgtap.sql: sql/pgtap.sql.in test/setup.sql cp $< $@ ifeq ($(shell echo $(VERSION) | grep -qE "8[.][123]" && echo yes || echo no),yes) patch -p0 < compat/install-8.3.patch endif ifeq ($(shell echo $(VERSION) | grep -qE "8[.][12]" && echo yes || echo no),yes) patch -p0 < compat/install-8.2.patch endif ifeq ($(shell echo $(VERSION) | grep -qE "8[.][1]" && echo yes || echo no),yes) patch -p0 < compat/install-8.1.patch endif sed -e 's,MODULE_PATHNAME,$$libdir/pgtap,g' -e 's,__OS__,$(OSNAME),g' -e 's,__VERSION__,$(NUMVERSION),g' sql/pgtap.sql > sql/pgtap.tmp mv sql/pgtap.tmp sql/pgtap.sql sql/uninstall_pgtap.sql: sql/uninstall_pgtap.sql.in test/setup.sql cp sql/uninstall_pgtap.sql.in sql/uninstall_pgtap.sql ifeq ($(shell echo $(VERSION) | grep -qE "8[.][123]" && echo yes || echo no),yes) patch -p0 < compat/uninstall-8.3.patch endif ifeq ($(shell echo $(VERSION) | grep -qE "8[.][12]" && echo yes || echo no),yes) patch -p0 < compat/uninstall-8.2.patch endif sql/pgtap-core.sql: sql/pgtap.sql.in cp $< $@ sed -e 's,sql/pgtap,sql/pgtap-core,g' compat/install-8.3.patch | patch -p0 sed -e 's,MODULE_PATHNAME,$$libdir/pgtap,g' -e 's,__OS__,$(OSNAME),g' -e 's,__VERSION__,$(NUMVERSION),g' sql/pgtap-core.sql > sql/pgtap-core.tmp $(PERL) compat/gencore 0 sql/pgtap-core.tmp > sql/pgtap-core.sql rm sql/pgtap-core.tmp sql/pgtap-schema.sql: sql/pgtap.sql.in cp $< $@ sed -e 's,sql/pgtap,sql/pgtap-schema,g' compat/install-8.3.patch | patch -p0 sed -e 's,MODULE_PATHNAME,$$libdir/pgtap,g' -e 's,__OS__,$(OSNAME),g' -e 's,__VERSION__,$(NUMVERSION),g' sql/pgtap-schema.sql > sql/pgtap-schema.tmp $(PERL) compat/gencore 1 sql/pgtap-schema.tmp > sql/pgtap-schema.sql rm sql/pgtap-schema.tmp # Make sure that we build the regression tests. installcheck: test/setup.sql # In addition to installcheck, one can also run the tests through pg_prove. test: test/setup.sql pg_prove --pset tuples_only=1 $(TESTS) html: MultiMarkdown.pl doc/pgtap.mmd > doc/pgtap.html ./tocgen doc/pgtap.html 2> doc/toc.html perl -MPod::Simple::XHTML -E "my \$$p = Pod::Simple::XHTML->new; \$$p->html_header_tags(''); \$$p->strip_verbatim_indent(sub { (my \$$i = \$$_[0]->[0]) =~ s/\\S.*//; \$$i }); \$$p->parse_from_file('`perldoc -l pg_prove`')" > doc/pg_prove.html pgtap-0.90.0/._META.json000644 000765 000024 00000000252 11666501762 015014 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/META.json000644 000765 000024 00000003234 11666501762 014602 0ustar00davidstaff000000 000000 { "name": "pgTAP", "abstract": "Unit testing for PostgreSQL", "description": "pgTAP is a suite of database functions that make it easy to write TAP-emitting unit tests in psql scripts or xUnit-style test functions.", "version": "0.90.0", "maintainer": [ "David E. Wheeler ", "pgTAP List " ], "license": { "PostgreSQL": "http://www.postgresql.org/about/licence" }, "prereqs": { "runtime": { "requires": { "plpgsql": 0, "PostgreSQL": "8.1.0" }, "recommends": { "PostgreSQL": "8.4.0" } } }, "provides": { "pgtap": { "abstract": "Unit testing for PostgreSQL", "file": "sql/pgtap.sql", "version": "0.90.0" }, "pgtap-core": { "abstract": "Unit testing for PostgreSQL", "file": "sql/pgtap-core.sql", "version": "0.90.0" }, "pgtap-schema": { "abstract": "Schema unit testing for PostgreSQL", "file": "sql/pgtap-schema.sql", "version": "0.90.0" } }, "resources": { "homepage": "http://pgtap.org/", "bugtracker": { "web": "https://github.com/theory/pgtap/issues" }, "repository": { "url": "https://github.com/theory/pgtap.git", "web": "https://github.com/theory/pgtap", "type": "git" } }, "generated_by": "David E. Wheeler", "meta-spec": { "version": "1.0.0", "url": "http://pgxn.org/meta/spec.txt" }, "tags": [ "testing", "unit testing", "tap", "tddd", "test driven database development" ] } pgtap-0.90.0/._pgtap-core.control000644 000765 000024 00000000252 11666501762 017036 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/pgtap-core.control000644 000765 000024 00000000241 11666501762 016617 0ustar00davidstaff000000 000000 # pgTAP Core extension comment = 'Unit testing for PostgreSQL' default_version = '0.90.0' module_pathname = '$libdir/pgtap' relocatable = true superuser = false pgtap-0.90.0/._pgtap-schema.control000644 000765 000024 00000000252 11666501762 017346 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/pgtap-schema.control000644 000765 000024 00000000312 11666501762 017126 0ustar00davidstaff000000 000000 # pgTAP Schema testing extension comment = 'Schema unit testing for PostgreSQL' default_version = '0.90.0' module_pathname = '$libdir/pgtap' requires = 'pgtap-core' relocatable = true superuser = false pgtap-0.90.0/._pgtap.control000644 000765 000024 00000000252 11666501762 016110 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/pgtap.control000644 000765 000024 00000000234 11666501762 015673 0ustar00davidstaff000000 000000 # pgTAP extension comment = 'Unit testing for PostgreSQL' default_version = '0.90.0' module_pathname = '$libdir/pgtap' relocatable = true superuser = false pgtap-0.90.0/._README.md000644 000765 000024 00000000252 11666501762 014652 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/README.md000644 000765 000024 00000007201 11666501762 014436 0ustar00davidstaff000000 000000 pgTAP 0.90.0 =========== [pgTAP](http://pgtap.org) is a unit testing framework for PostgreSQL written in PL/pgSQL and PL/SQL. It includes a comprehensive collection of [TAP](http://testanything.org)-emitting assertion functions, as well as the ability to integrate with other TAP-emitting test frameworks. It can also be used in the xUnit testing style. For detailed documentation, see the documentation in `doc/pgtap.mmd` or [online](http://pgtap.org/documentation.html "Complete pgTAP Documentation"). To build it, just do this: make make installcheck make install If you encounter an error such as: "Makefile", line 8: Need an operator You need to use GNU make, which may well be installed on your system as `gmake`: gmake gmake install gmake installcheck If you encounter an error such as: make: pg_config: Command not found Or: Makefile:52: *** pgTAP requires PostgreSQL 8.1 or later. This is . Stop. 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 && make installcheck And finally, if all that fails (and if you're on PostgreSQL 8.1, it likely will), copy the entire distribution directory to the `contrib/` subdirectory of the PostgreSQL source tree and try it there without `pg_config`: env NO_PGXS=1 make && make install && make installcheck If you encounter an error such as: ERROR: must be owner of database regression You need to run the test suite using a super user, such as the default "postgres" super user: make installcheck PGUSER=postgres Once pgTAP is installed, you can add it to a database. If you're running PostgreSQL 9.1.0 or greater, it's a simple as connecting to a database as a super user and running: CREATE EXTENSION pgtap; If you've upgraded your cluster to PostgreSQL 9.1 and already had pgTAP installed, you can upgrade it to a properly packaged extension with: CREATE EXTENSION pgtap FROM unpackaged; For versions of PostgreSQL less than 9.1.0, you'll need to run the installation script: psql -d mydb -f /path/to/pgsql/share/contrib/pgtap.sql If you want to install pgTAP and all of its supporting objects into a specific schema, use the `PGOPTIONS` environment variable to specify the schema, like so: PGOPTIONS=--search_path=tap psql -d mydb -f pgTAP.sql Dependencies ------------ pgTAP requires PostgreSQL 8.1 or higher, with 8.4 or higher recommended for full use of its API. It also requires PL/pgSQL. Copyright and License --------------------- Copyright (c) 2008-2011 David E. Wheeler. Some rights reserved. 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 DAVID E. WHEELER 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 DAVID E. WHEELER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DAVID E. WHEELER 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 DAVID E. WHEELER HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. pgtap-0.90.0/sql/000755 000765 000024 00000000000 11666503077 013757 5ustar00davidstaff000000 000000 pgtap-0.90.0/src/000755 000765 000024 00000000000 11666503077 013747 5ustar00davidstaff000000 000000 pgtap-0.90.0/test/000755 000765 000024 00000000000 11666503077 014137 5ustar00davidstaff000000 000000 pgtap-0.90.0/._tocgen000644 000765 000024 00000000252 11666501762 014575 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/tocgen000644 000765 000024 00000001565 11666501762 014370 0ustar00davidstaff000000 000000 #!/usr/bin/env perl -n -pi our $prevn; BEGIN { $prevn = 0; print STDERR "

Contents

\n
    \n"; } if (m{ ( # 4. header ([^(]+)?.+? # 5. label ) }x) { my ($hn, $id, $val, $label) = ($1, $2, $3, $4); if ($prevn) { if ($hn != $prevn) { print STDERR $hn > $prevn ? $hn - $prevn > 1 ? "
      • " : "
          \n" : $prevn - $hn > 1 ? "
    • \n" : "
    \n"; $prevn = $hn; } else { print STDERR "\n" } } else { $prevn = $hn; } print STDERR qq{
  • $val}; $_ = qq{$val\n}; } END { print STDERR "
  • \n
\n" } pgtap-0.90.0/test/expected/000755 000765 000024 00000000000 11666503077 015740 5ustar00davidstaff000000 000000 pgtap-0.90.0/test/._setup.sql000644 000765 000024 00000000252 11666501762 016233 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/setup.sql000644 000765 000024 00000000420 11666501762 016013 0ustar00davidstaff000000 000000 \set QUIET 1 -- -- Tests for pgTAP. -- -- -- Format the output for nice TAP. \pset format unaligned \pset tuples_only true \pset pager -- Revert all changes on failure. \set ON_ERROR_ROLLBACK 1 \set ON_ERROR_STOP true -- Load the TAP functions. BEGIN; \i sql/pgtap.sql pgtap-0.90.0/test/sql/000755 000765 000024 00000000000 11666503077 014736 5ustar00davidstaff000000 000000 pgtap-0.90.0/test/sql/._aretap.sql000644 000765 000024 00000000252 11666501762 017146 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/aretap.sql000644 000765 000024 00000112174 11666501762 016740 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(399); --SELECT * FROM no_plan(); -- This will be rolled back. :-) SET client_min_messages = warning; CREATE TABLE public.fou( id INT NOT NULL PRIMARY KEY, name TEXT DEFAULT '', numb NUMERIC(10, 2), "myInt" NUMERIC(8) ); CREATE TABLE public.foo( id INT NOT NULL PRIMARY KEY ); CREATE RULE ins_me AS ON INSERT TO public.fou DO NOTHING; CREATE RULE upd_me AS ON UPDATE TO public.fou DO NOTHING; CREATE INDEX idx_fou_id ON public.fou(id); CREATE INDEX idx_fou_name ON public.fou(name); CREATE VIEW public.voo AS SELECT * FROM foo; CREATE VIEW public.vou AS SELECT * FROM fou; CREATE SEQUENCE public.someseq; CREATE SEQUENCE public.sumeseq; CREATE SCHEMA someschema; CREATE FUNCTION someschema.yip() returns boolean as 'SELECT TRUE' language SQL; CREATE FUNCTION someschema.yap() returns boolean as 'SELECT TRUE' language SQL; CREATE DOMAIN public.goofy AS text CHECK ( TRUE ); CREATE DOMAIN public."myDomain" AS text CHECK ( TRUE ); CREATE OR REPLACE FUNCTION public.goofy_cmp(goofy,goofy) RETURNS INTEGER AS $$ SELECT CASE WHEN $1 = $2 THEN 0 WHEN $1 > $2 THEN 1 ELSE -1 END; $$ LANGUAGE SQL IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION public.goofy_eq (goofy, goofy) RETURNS boolean AS $$ SELECT $1 = $2; $$ LANGUAGE SQL IMMUTABLE STRICT; CREATE SCHEMA disney; CREATE OPERATOR disney.= ( PROCEDURE = goofy_eq, LEFTARG = goofy, RIGHTARG = goofy); CREATE OPERATOR = ( PROCEDURE = goofy_eq, LEFTARG = goofy, RIGHTARG = goofy); CREATE OPERATOR CLASS public.goofy_ops DEFAULT FOR TYPE goofy USING BTREE AS OPERATOR 1 disney.=, FUNCTION 1 goofy_cmp(goofy,goofy) ; CREATE TYPE someschema.sometype AS ( id INT, name TEXT ); CREATE TYPE someschema."myType" AS ( id INT, foo INT ); RESET client_min_messages; /****************************************************************************/ -- Test tablespaces_are(). CREATE FUNCTION ___myts(ex text) RETURNS NAME[] AS $$ SELECT ARRAY( SELECT spcname FROM pg_catalog.pg_tablespace WHERE spcname <> $1 ); $$ LANGUAGE SQL; SELECT * FROM check_test( tablespaces_are( ___myts(''), 'whatever' ), true, 'tablespaces_are(tablespaces, desc)', 'whatever', '' ); SELECT * FROM check_test( tablespaces_are( ___myts('') ), true, 'tablespaces_are(tablespaces)', 'There should be the correct tablespaces', '' ); SELECT * FROM check_test( tablespaces_are( array_append(___myts(''), '__booya__'), 'whatever' ), false, 'tablespaces_are(tablespaces, desc) missing', 'whatever', ' Missing tablespaces: __booya__' ); SELECT * FROM check_test( tablespaces_are( ___myts('pg_default'), 'whatever' ), false, 'tablespaces_are(tablespaces, desc) extra', 'whatever', ' Extra tablespaces: pg_default' ); SELECT * FROM check_test( tablespaces_are( array_append(___myts('pg_default'), '__booya__'), 'whatever' ), false, 'tablespaces_are(tablespaces, desc) extras and missing', 'whatever', ' Extra tablespaces: pg_default Missing tablespaces: __booya__' ); /****************************************************************************/ -- Test schemas_are(). CREATE FUNCTION ___mysch(ex text) RETURNS NAME[] AS $$ SELECT ARRAY( SELECT nspname FROM pg_catalog.pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname <> 'information_schema' AND nspname <> $1 ); $$ LANGUAGE SQL; SELECT * FROM check_test( schemas_are( ___mysch(''), 'whatever' ), true, 'schemas_are(schemas, desc)', 'whatever', '' ); SELECT * FROM check_test( schemas_are( ___mysch('') ), true, 'schemas_are(schemas)', 'There should be the correct schemas', '' ); SELECT * FROM check_test( schemas_are( array_append(___mysch(''), '__howdy__'), 'whatever' ), false, 'schemas_are(schemas, desc) missing', 'whatever', ' Missing schemas: __howdy__' ); SELECT * FROM check_test( schemas_are( ___mysch('someschema'), 'whatever' ), false, 'schemas_are(schemas, desc) extras', 'whatever', ' Extra schemas: someschema' ); SELECT * FROM check_test( schemas_are( array_append(___mysch('someschema'), '__howdy__'), 'whatever' ), false, 'schemas_are(schemas, desc) missing and extras', 'whatever', ' Extra schemas: someschema Missing schemas: __howdy__' ); /****************************************************************************/ -- Test tables_are(). SELECT * FROM check_test( tables_are( 'public', ARRAY['fou', 'foo'], 'whatever' ), true, 'tables_are(schema, tables, desc)', 'whatever', '' ); SELECT * FROM check_test( tables_are( 'public', ARRAY['fou', 'foo'] ), true, 'tables_are(schema, tables)', 'Schema public should have the correct tables', '' ); SELECT * FROM check_test( tables_are( ARRAY['fou', 'foo'] ), true, 'tables_are(tables)', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct tables', '' ); SELECT * FROM check_test( tables_are( ARRAY['fou', 'foo'], 'whatever' ), true, 'tables_are(tables, desc)', 'whatever', '' ); SELECT * FROM check_test( tables_are( 'public', ARRAY['fou', 'foo', 'bar'] ), false, 'tables_are(schema, tables) missing', 'Schema public should have the correct tables', ' Missing tables: bar' ); SELECT * FROM check_test( tables_are( ARRAY['fou', 'foo', 'bar'] ), false, 'tables_are(tables) missing', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct tables', ' Missing tables: bar' ); SELECT * FROM check_test( tables_are( 'public', ARRAY['fou'] ), false, 'tables_are(schema, tables) extra', 'Schema public should have the correct tables', ' Extra tables: foo' ); SELECT * FROM check_test( tables_are( ARRAY['fou'] ), false, 'tables_are(tables) extra', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct tables', ' Extra tables: foo' ); SELECT * FROM check_test( tables_are( 'public', ARRAY['bar', 'baz'] ), false, 'tables_are(schema, tables) extra and missing', 'Schema public should have the correct tables', ' Extra tables: fo[ou] fo[ou] Missing tables: ba[rz] ba[rz]', true ); SELECT * FROM check_test( tables_are( ARRAY['bar', 'baz'] ), false, 'tables_are(tables) extra and missing', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct tables', ' Extra tables:' || ' fo[ou] fo[ou] Missing tables:' || ' ba[rz] ba[rz]', true ); /****************************************************************************/ -- Test views_are(). SELECT * FROM check_test( views_are( 'public', ARRAY['vou', 'voo'], 'whatever' ), true, 'views_are(schema, views, desc)', 'whatever', '' ); SELECT * FROM check_test( views_are( 'public', ARRAY['vou', 'voo'] ), true, 'views_are(schema, views)', 'Schema public should have the correct views', '' ); SELECT * FROM check_test( views_are( ARRAY['vou', 'voo'] ), true, 'views_are(views)', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct views', '' ); SELECT * FROM check_test( views_are( ARRAY['vou', 'voo'], 'whatever' ), true, 'views_are(views, desc)', 'whatever', '' ); SELECT * FROM check_test( views_are( 'public', ARRAY['vou', 'voo', 'bar'] ), false, 'views_are(schema, views) missing', 'Schema public should have the correct views', ' Missing views: bar' ); SELECT * FROM check_test( views_are( ARRAY['vou', 'voo', 'bar'] ), false, 'views_are(views) missing', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct views', ' Missing views: bar' ); SELECT * FROM check_test( views_are( 'public', ARRAY['vou'] ), false, 'views_are(schema, views) extra', 'Schema public should have the correct views', ' Extra views: voo' ); SELECT * FROM check_test( views_are( ARRAY['vou'] ), false, 'views_are(views) extra', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct views', ' Extra views: voo' ); SELECT * FROM check_test( views_are( 'public', ARRAY['bar', 'baz'] ), false, 'views_are(schema, views) extra and missing', 'Schema public should have the correct views', ' Extra views: vo[ou] vo[ou] Missing views: ba[rz] ba[rz]', true ); SELECT * FROM check_test( views_are( ARRAY['bar', 'baz'] ), false, 'views_are(views) extra and missing', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct views', ' Extra views:' || ' vo[ou] vo[ou] Missing views:' || ' ba[rz] ba[rz]', true ); /****************************************************************************/ -- Test sequences_are(). SELECT * FROM check_test( sequences_are( 'public', ARRAY['sumeseq', 'someseq'], 'whatever' ), true, 'sequences_are(schema, sequences, desc)', 'whatever', '' ); SELECT * FROM check_test( sequences_are( 'public', ARRAY['sumeseq', 'someseq'] ), true, 'sequences_are(schema, sequences)', 'Schema public should have the correct sequences', '' ); SELECT * FROM check_test( sequences_are( ARRAY['sumeseq', 'someseq'] ), true, 'sequences_are(sequences)', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct sequences', '' ); SELECT * FROM check_test( sequences_are( ARRAY['sumeseq', 'someseq'], 'whatever' ), true, 'sequences_are(sequences, desc)', 'whatever', '' ); SELECT * FROM check_test( sequences_are( 'public', ARRAY['sumeseq', 'someseq', 'bar'] ), false, 'sequences_are(schema, sequences) missing', 'Schema public should have the correct sequences', ' Missing sequences: bar' ); SELECT * FROM check_test( sequences_are( ARRAY['sumeseq', 'someseq', 'bar'] ), false, 'sequences_are(sequences) missing', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct sequences', ' Missing sequences: bar' ); SELECT * FROM check_test( sequences_are( 'public', ARRAY['sumeseq'] ), false, 'sequences_are(schema, sequences) extra', 'Schema public should have the correct sequences', ' Extra sequences: someseq' ); SELECT * FROM check_test( sequences_are( ARRAY['sumeseq'] ), false, 'sequences_are(sequences) extra', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct sequences', ' Extra sequences: someseq' ); SELECT * FROM check_test( sequences_are( 'public', ARRAY['bar', 'baz'] ), false, 'sequences_are(schema, sequences) extra and missing', 'Schema public should have the correct sequences', ' Extra sequences: s[ou]meseq s[ou]meseq Missing sequences: ba[rz] ba[rz]', true ); SELECT * FROM check_test( sequences_are( ARRAY['bar', 'baz'] ), false, 'sequences_are(sequences) extra and missing', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct sequences', ' Extra sequences:' || ' s[ou]meseq s[ou]meseq Missing sequences:' || ' ba[rz] ba[rz]', true ); /****************************************************************************/ -- Test functions_are(). SELECT * FROM check_test( functions_are( 'someschema', ARRAY['yip', 'yap'], 'whatever' ), true, 'functions_are(schema, functions, desc)', 'whatever', '' ); SELECT * FROM check_test( functions_are( 'someschema', ARRAY['yip', 'yap'] ), true, 'functions_are(schema, functions)', 'Schema someschema should have the correct functions' '' ); SELECT * FROM check_test( functions_are( 'someschema', ARRAY['yip', 'yap', 'yop'], 'whatever' ), false, 'functions_are(schema, functions, desc) + missing', 'whatever', ' Missing functions: yop' ); SELECT * FROM check_test( functions_are( 'someschema', ARRAY['yip'], 'whatever' ), false, 'functions_are(schema, functions, desc) + extra', 'whatever', ' Extra functions: yap' ); SELECT * FROM check_test( functions_are( 'someschema', ARRAY['yap', 'yop'], 'whatever' ), false, 'functions_are(schema, functions, desc) + extra & missing', 'whatever', ' Extra functions: yip Missing functions: yop' ); CREATE FUNCTION ___myfunk(ex text) RETURNS NAME[] AS $$ SELECT ARRAY( SELECT p.proname FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_proc p ON n.oid = p.pronamespace WHERE pg_catalog.pg_function_is_visible(p.oid) AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND p.proname <> $1 ); $$ LANGUAGE SQL; SELECT * FROM check_test( functions_are( ___myfunk(''), 'whatever' ), true, 'functions_are(functions, desc)', 'whatever', '' ); SELECT * FROM check_test( functions_are( ___myfunk('') ), true, 'functions_are(functions)', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct functions', '' ); SELECT * FROM check_test( functions_are( array_append(___myfunk(''), '__booyah__'), 'whatever' ), false, 'functions_are(functions, desc) + missing', 'whatever', ' Missing functions: __booyah__' ); SELECT * FROM check_test( functions_are( ___myfunk('check_test'), 'whatever' ), false, 'functions_are(functions, desc) + extra', 'whatever', ' Extra functions: check_test' ); SELECT * FROM check_test( functions_are( array_append(___myfunk('check_test'), '__booyah__'), 'whatever' ), false, 'functions_are(functions, desc) + extra & missing', 'whatever', ' Extra functions: check_test Missing functions: __booyah__' ); /****************************************************************************/ -- Test indexes_are(). SELECT * FROM check_test( indexes_are( 'public', 'fou', ARRAY['idx_fou_id', 'idx_fou_name', 'fou_pkey'], 'whatever' ), true, 'indexes_are(schema, table, indexes, desc)', 'whatever', '' ); SELECT * FROM check_test( indexes_are( 'public', 'fou', ARRAY['idx_fou_id', 'idx_fou_name', 'fou_pkey'] ), true, 'indexes_are(schema, table, indexes)', 'Table public.fou should have the correct indexes', '' ); SELECT * FROM check_test( indexes_are( 'public', 'fou', ARRAY['idx_fou_id', 'idx_fou_name'] ), false, 'indexes_are(schema, table, indexes) + extra', 'Table public.fou should have the correct indexes', ' Extra indexes: fou_pkey' ); SELECT * FROM check_test( indexes_are( 'public', 'fou', ARRAY['idx_fou_id', 'idx_fou_name', 'fou_pkey', 'howdy'] ), false, 'indexes_are(schema, table, indexes) + missing', 'Table public.fou should have the correct indexes', ' Missing indexes: howdy' ); SELECT * FROM check_test( indexes_are( 'public', 'fou', ARRAY['idx_fou_id', 'idx_fou_name', 'howdy'] ), false, 'indexes_are(schema, table, indexes) + extra & missing', 'Table public.fou should have the correct indexes', ' Extra indexes: fou_pkey Missing indexes: howdy' ); SELECT * FROM check_test( indexes_are( 'fou', ARRAY['idx_fou_id', 'idx_fou_name', 'fou_pkey'], 'whatever' ), true, 'indexes_are(table, indexes, desc)', 'whatever', '' ); SELECT * FROM check_test( indexes_are( 'fou', ARRAY['idx_fou_id', 'idx_fou_name', 'fou_pkey'] ), true, 'indexes_are(table, indexes)', 'Table fou should have the correct indexes', '' ); SELECT * FROM check_test( indexes_are( 'fou', ARRAY['idx_fou_id', 'idx_fou_name'] ), false, 'indexes_are(table, indexes) + extra', 'Table fou should have the correct indexes', ' Extra indexes: fou_pkey' ); SELECT * FROM check_test( indexes_are( 'fou', ARRAY['idx_fou_id', 'idx_fou_name', 'fou_pkey', 'howdy'] ), false, 'indexes_are(table, indexes) + missing', 'Table fou should have the correct indexes', ' Missing indexes: howdy' ); SELECT * FROM check_test( indexes_are( 'fou', ARRAY['idx_fou_id', 'idx_fou_name', 'howdy'] ), false, 'indexes_are(table, indexes) + extra & missing', 'Table fou should have the correct indexes', ' Extra indexes: fou_pkey Missing indexes: howdy' ); /****************************************************************************/ -- Test users_are(). CREATE FUNCTION ___myusers(ex text) RETURNS NAME[] AS $$ SELECT COALESCE(ARRAY( SELECT usename FROM pg_catalog.pg_user WHERE usename <> $1 ), '{}'::name[]);; $$ LANGUAGE SQL; SELECT * FROM check_test( users_are( ___myusers(''), 'whatever' ), true, 'users_are(users, desc)', 'whatever', '' ); SELECT * FROM check_test( users_are( ___myusers('') ), true, 'users_are(users)', 'There should be the correct users', '' ); SELECT * FROM check_test( users_are( array_append(___myusers(''), '__howdy__'), 'whatever' ), false, 'users_are(users, desc) missing', 'whatever', ' Missing users: __howdy__' ); SELECT * FROM check_test( users_are( ___myusers(current_user), 'whatever' ), false, 'users_are(users, desc) extras', 'whatever', ' Extra users: ' || current_user ); SELECT * FROM check_test( users_are( array_append(___myusers(current_user), '__howdy__'), 'whatever' ), false, 'users_are(users, desc) missing and extras', 'whatever', ' Extra users: ' || current_user || ' Missing users: __howdy__' ); /****************************************************************************/ -- Test groups_are(). CREATE GROUP meanies; CREATE FUNCTION ___mygroups(ex text) RETURNS NAME[] AS $$ SELECT COALESCE(ARRAY( SELECT groname FROM pg_catalog.pg_group WHERE groname <> $1 ), '{}'::name[]);; $$ LANGUAGE SQL; SELECT * FROM check_test( groups_are( ___mygroups(''), 'whatever' ), true, 'groups_are(groups, desc)', 'whatever', '' ); SELECT * FROM check_test( groups_are( ___mygroups('') ), true, 'groups_are(groups)', 'There should be the correct groups', '' ); SELECT * FROM check_test( groups_are( array_append(___mygroups(''), '__howdy__'), 'whatever' ), false, 'groups_are(groups, desc) missing', 'whatever', ' Missing groups: __howdy__' ); SELECT * FROM check_test( groups_are( ___mygroups('meanies'), 'whatever' ), false, 'groups_are(groups, desc) extras', 'whatever', ' Extra groups: meanies' ); SELECT * FROM check_test( groups_are( array_append(___mygroups('meanies'), '__howdy__'), 'whatever' ), false, 'groups_are(groups, desc) missing and extras', 'whatever', ' Extra groups: meanies Missing groups: __howdy__' ); /****************************************************************************/ -- Test languages_are(). CREATE FUNCTION ___mylangs(ex text) RETURNS NAME[] AS $$ SELECT COALESCE(ARRAY( SELECT lanname FROM pg_catalog.pg_language WHERE lanispl AND lanname <> $1 ), '{}'::name[]);; $$ LANGUAGE SQL; SELECT * FROM check_test( languages_are( ___mylangs(''), 'whatever' ), true, 'languages_are(languages, desc)', 'whatever', '' ); SELECT * FROM check_test( languages_are( ___mylangs('') ), true, 'languages_are(languages)', 'There should be the correct procedural languages', '' ); SELECT * FROM check_test( languages_are( array_append(___mylangs(''), 'plomgwtf'), 'whatever' ), false, 'languages_are(languages, desc) missing', 'whatever', ' Missing languages: plomgwtf' ); SELECT * FROM check_test( languages_are( ___mylangs('plpgsql'), 'whatever' ), false, 'languages_are(languages, desc) extras', 'whatever', ' Extra languages: plpgsql' ); SELECT * FROM check_test( languages_are( array_append(___mylangs('plpgsql'), 'plomgwtf'), 'whatever' ), false, 'languages_are(languages, desc) missing and extras', 'whatever', ' Extra languages: plpgsql Missing languages: plomgwtf' ); /****************************************************************************/ -- Test opclasses_are(). SELECT * FROM check_test( opclasses_are( 'public', ARRAY['goofy_ops'], 'whatever' ), true, 'opclasses_are(schema, opclasses, desc)', 'whatever', '' ); SELECT * FROM check_test( opclasses_are( 'public', ARRAY['goofy_ops'] ), true, 'opclasses_are(schema, opclasses)', 'Schema public should have the correct operator classes' '' ); SELECT * FROM check_test( opclasses_are( 'public', ARRAY['goofy_ops', 'yops'], 'whatever' ), false, 'opclasses_are(schema, opclasses, desc) + missing', 'whatever', ' Missing operator classes: yops' ); SELECT * FROM check_test( opclasses_are( 'public', '{}'::name[], 'whatever' ), false, 'opclasses_are(schema, opclasses, desc) + extra', 'whatever', ' Extra operator classes: goofy_ops' ); SELECT * FROM check_test( opclasses_are( 'public', ARRAY['yops'], 'whatever' ), false, 'opclasses_are(schema, opclasses, desc) + extra & missing', 'whatever', ' Extra operator classes: goofy_ops Missing operator classes: yops' ); CREATE FUNCTION ___myopc(ex text) RETURNS NAME[] AS $$ SELECT COALESCE(ARRAY( SELECT oc.opcname FROM pg_catalog.pg_opclass oc JOIN pg_catalog.pg_namespace n ON oc.opcnamespace = n.oid WHERE n.nspname <> 'pg_catalog' AND oc.opcname <> $1 AND pg_catalog.pg_opclass_is_visible(oc.oid) ), '{}'::name[]);; $$ LANGUAGE SQL; SELECT * FROM check_test( opclasses_are( ___myopc('') ), true, 'opclasses_are(opclasses)', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct operator classes', '' ); SELECT * FROM check_test( opclasses_are( array_append(___myopc(''), 'sillyops'), 'whatever' ), false, 'opclasses_are(opclasses, desc) + missing', 'whatever', ' Missing operator classes: sillyops' ); SELECT * FROM check_test( opclasses_are( ___myopc('goofy_ops'), 'whatever' ), false, 'opclasses_are(opclasses, desc) + extra', 'whatever', ' Extra operator classes: goofy_ops' ); SELECT * FROM check_test( opclasses_are( array_append(___myopc('goofy_ops'), 'sillyops'), 'whatever' ), false, 'opclasses_are(opclasses, desc) + extra & missing', 'whatever', ' Extra operator classes: goofy_ops Missing operator classes: sillyops' ); /****************************************************************************/ -- Test rules_are(). SELECT * FROM check_test( rules_are( 'public', 'fou', ARRAY['ins_me', 'upd_me'], 'whatever' ), true, 'rules_are(schema, table, rules, desc)', 'whatever', '' ); SELECT * FROM check_test( rules_are( 'public', 'fou', ARRAY['ins_me', 'upd_me'] ), true, 'rules_are(schema, table, rules)', 'Relation public.fou should have the correct rules', '' ); SELECT * FROM check_test( rules_are( 'public', 'fou', ARRAY['ins_me'] ), false, 'rules_are(schema, table, rules) + extra', 'Relation public.fou should have the correct rules', ' Extra rules: upd_me' ); SELECT * FROM check_test( rules_are( 'public', 'fou', ARRAY['ins_me', 'upd_me', 'del_me'] ), false, 'rules_are(schema, table, rules) + missing', 'Relation public.fou should have the correct rules', ' Missing rules: del_me' ); SELECT * FROM check_test( rules_are( 'public', 'fou', ARRAY['ins_me', 'del_me'] ), false, 'rules_are(schema, table, rules) + extra & missing', 'Relation public.fou should have the correct rules', ' Extra rules: upd_me Missing rules: del_me' ); SELECT * FROM check_test( rules_are( 'fou', ARRAY['ins_me', 'upd_me'], 'whatever' ), true, 'rules_are(table, rules, desc)', 'whatever', '' ); SELECT * FROM check_test( rules_are( 'fou', ARRAY['ins_me', 'upd_me'] ), true, 'rules_are(table, rules)', 'Relation fou should have the correct rules', '' ); SELECT * FROM check_test( rules_are( 'fou', ARRAY['ins_me'] ), false, 'rules_are(table, rules) + extra', 'Relation fou should have the correct rules', ' Extra rules: upd_me' ); SELECT * FROM check_test( rules_are( 'fou', ARRAY['ins_me', 'upd_me', 'del_me'] ), false, 'rules_are(table, rules) + missing', 'Relation fou should have the correct rules', ' Missing rules: del_me' ); SELECT * FROM check_test( rules_are( 'fou', ARRAY['ins_me', 'del_me'] ), false, 'rules_are(table, rules) + extra & missing', 'Relation fou should have the correct rules', ' Extra rules: upd_me Missing rules: del_me' ); /****************************************************************************/ -- Test types_are(). SELECT * FROM check_test( types_are( 'someschema', ARRAY['sometype', 'myType'], 'whatever' ), true, 'types_are(schema, types, desc)', 'whatever', '' ); SELECT * FROM check_test( types_are( 'someschema', ARRAY['sometype', 'myType'] ), true, 'types_are(schema, types)', 'Schema someschema should have the correct types' '' ); SELECT * FROM check_test( types_are( 'someschema', ARRAY['sometype', 'myType', 'typo'], 'whatever' ), false, 'types_are(schema, types, desc) + missing', 'whatever', ' Missing types: typo' ); SELECT * FROM check_test( types_are( 'someschema', ARRAY['myType'], 'whatever' ), false, 'types_are(schema, types, desc) + extra', 'whatever', ' Extra types: sometype' ); SELECT * FROM check_test( types_are( 'someschema', ARRAY['typo', 'myType'], 'whatever' ), false, 'types_are(schema, types, desc) + extra & missing', 'whatever', ' Extra types: sometype Missing types: typo' ); CREATE FUNCTION ___mytype(ex text) RETURNS NAME[] AS $$ SELECT COALESCE(ARRAY( SELECT t.typname FROM pg_catalog.pg_type t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE ( t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) ) AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem) AND n.nspname NOT IN('pg_catalog', 'information_schema') AND t.typname <> $1 AND pg_catalog.pg_type_is_visible(t.oid) ), '{}'::name[]);; $$ LANGUAGE SQL; SELECT * FROM check_test( types_are( ___mytype('') ), true, 'types_are(types)', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct types', '' ); SELECT * FROM check_test( types_are( array_append(___mytype(''), 'silltypo'), 'whatever' ), false, 'types_are(types, desc) + missing', 'whatever', ' Missing types: silltypo' ); SELECT * FROM check_test( types_are( ___mytype('goofy'), 'whatever' ), false, 'types_are(types, desc) + extra', 'whatever', ' Extra types: goofy' ); SELECT * FROM check_test( types_are( array_append(___mytype('goofy'), 'silltypo'), 'whatever' ), false, 'types_are(types, desc) + extra & missing', 'whatever', ' Extra types: goofy Missing types: silltypo' ); /****************************************************************************/ -- Test domains_are(). SELECT * FROM check_test( domains_are( 'public', ARRAY['goofy', 'myDomain'], 'whatever' ), true, 'domains_are(schema, domains, desc)', 'whatever', '' ); SELECT * FROM check_test( domains_are( 'public', ARRAY['goofy', 'myDomain'] ), true, 'domains_are(schema, domains)', 'Schema public should have the correct domains', '' ); SELECT * FROM check_test( domains_are( 'public', ARRAY['freddy', 'myDomain'], 'whatever' ), false, 'domains_are(schema, domains, desc) fail', 'whatever', ' Extra types: goofy Missing types: freddy' ); SELECT * FROM check_test( domains_are( 'public', ARRAY['freddy', 'myDomain'] ), false, 'domains_are(schema, domains) fail', 'Schema public should have the correct domains', ' Extra types: goofy Missing types: freddy' ); CREATE FUNCTION ___mydo(ex text) RETURNS NAME[] AS $$ SELECT COALESCE(ARRAY( SELECT t.typname FROM pg_catalog.pg_type t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE ( t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) ) AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem) AND n.nspname NOT IN('pg_catalog', 'information_schema') AND t.typname <> $1 AND pg_catalog.pg_type_is_visible(t.oid) AND t.typtype = 'd' ), '{}'::name[]); $$ LANGUAGE SQL; SELECT * FROM check_test( domains_are( ___mydo(''), 'whatever' ), true, 'domains_are(domains, desc)', 'whatever', '' ); SELECT * FROM check_test( domains_are( ___mydo('') ), true, 'domains_are(domains)', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct domains', '' ); SELECT * FROM check_test( domains_are( array_append(___mydo('goofy'), 'fredy'), 'whatever' ), false, 'domains_are(domains, desc) fail', 'whatever', ' Extra types: goofy Missing types: fredy' ); SELECT * FROM check_test( domains_are( array_append(___mydo('goofy'), 'fredy') ), false, 'domains_are(domains) fail', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct domains', ' Extra types: goofy Missing types: fredy' ); /****************************************************************************/ -- Test casts_are(). CREATE OR REPLACE FUNCTION ___mycasts(ex text) RETURNS TEXT[] AS $$ SELECT ARRAY( SELECT display_type(castsource, NULL) || ' AS ' || display_type(casttarget, NULL) FROM pg_catalog.pg_cast WHERE castsource::regtype::text <> $1 ); $$ LANGUAGE SQL; SELECT * FROM check_test( casts_are( ___mycasts(''), 'whatever' ), true, 'casts_are(casts, desc)', 'whatever', '' ); SELECT * FROM check_test( casts_are( ___mycasts('') ), true, 'casts_are(casts)', 'There should be the correct casts', '' ); SELECT * FROM check_test( casts_are( array_append(___mycasts(''), '__booya__ AS integer'), 'whatever' ), false, 'casts_are(casts, desc) missing', 'whatever', ' Missing casts: __booya__ AS integer' ); SELECT * FROM check_test( casts_are( ___mycasts('lseg'), 'whatever' ), false, 'casts_are(casts, desc) extra', 'whatever', ' Extra casts: lseg AS point' ); SELECT * FROM check_test( casts_are( array_append(___mycasts('lseg'), '__booya__ AS integer'), 'whatever' ), false, 'casts_are(casts, desc) extras and missing', 'whatever', ' Extra casts: lseg AS point Missing casts: __booya__ AS integer' ); /****************************************************************************/ -- Test operators_are(). --SET search_path = disney,public,pg_catalog; SELECT * FROM check_test( operators_are( 'disney', ARRAY['=(goofy,goofy) RETURNS boolean'], 'whatever' ), true, 'operators_are(schema, operators, desc)', 'whatever', '' ); SELECT * FROM check_test( operators_are( 'disney', ARRAY['=(goofy,goofy) RETURNS boolean'] ), true, 'operators_are(schema, operators)', 'Schema disney should have the correct operators', '' ); SELECT * FROM check_test( operators_are( 'disney', ARRAY['+(freddy,freddy) RETURNS barnie'], 'whatever' ), false, 'operators_are(schema, operators, desc) fail', 'whatever', ' Extra operators: =(goofy,goofy) RETURNS boolean Missing operators: +(freddy,freddy) RETURNS barnie' ); SELECT * FROM check_test( operators_are( 'disney', ARRAY['+(freddy,freddy) RETURNS barnie'] ), false, 'operators_are(schema, operators) fail', 'Schema disney should have the correct operators', ' Extra operators: =(goofy,goofy) RETURNS boolean Missing operators: +(freddy,freddy) RETURNS barnie' ); CREATE OR REPLACE FUNCTION ___myops(ex text) RETURNS TEXT[] AS $$ SELECT ARRAY( SELECT textin(regoperatorout(o.oid::regoperator)) || ' RETURNS ' || o.oprresult::regtype::text FROM pg_catalog.pg_operator o JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid WHERE pg_catalog.pg_operator_is_visible(o.oid) AND o.oprleft::regtype::text <> $1 AND n.nspname NOT IN ('pg_catalog', 'information_schema') ); $$ LANGUAGE SQL; SELECT * FROM check_test( operators_are( array_append( ___myops(''), '=(goofy,goofy) RETURNS boolean' ), 'whatever' ), true, 'operators_are(operators, desc)', 'whatever', '' ); SELECT * FROM check_test( operators_are( array_append( ___myops(''), '=(goofy,goofy) RETURNS boolean' ) ), true, 'operators_are(operators)', 'There should be the correct operators', '' ); SELECT * FROM check_test( operators_are( array_append( ___myops('goofy'), '+(freddy,freddy) RETURNS barnie' ), 'whatever' ), false, 'operators_are(operators, desc) fail', 'whatever', ' Extra operators: =(goofy,goofy) RETURNS boolean Missing operators: +(freddy,freddy) RETURNS barnie' ); SELECT * FROM check_test( operators_are( array_append( ___myops('goofy'), '+(freddy,freddy) RETURNS barnie' ) ), false, 'operators_are(operators) fail', 'There should be the correct operators', ' Extra operators: =(goofy,goofy) RETURNS boolean Missing operators: +(freddy,freddy) RETURNS barnie' ); /****************************************************************************/ -- Test columns_are(). SELECT * FROM check_test( columns_are( 'public', 'fou', ARRAY['id', 'name', 'numb', 'myInt'], 'whatever' ), true, 'columns_are(schema, table, columns, desc)', 'whatever', '' ); SELECT * FROM check_test( columns_are( 'public', 'fou', ARRAY['id', 'name', 'numb', 'myInt'] ), true, 'columns_are(schema, table, columns)', 'Table public.fou should have the correct columns', '' ); SELECT * FROM check_test( columns_are( 'public', 'fou', ARRAY['id', 'name', 'numb'] ), false, 'columns_are(schema, table, columns) + extra', 'Table public.fou should have the correct columns', ' Extra columns: "myInt"' ); SELECT * FROM check_test( columns_are( 'public', 'fou', ARRAY['id', 'name', 'numb', 'myInt', 'howdy'] ), false, 'columns_are(schema, table, columns) + missing', 'Table public.fou should have the correct columns', ' Missing columns: howdy' ); SELECT * FROM check_test( columns_are( 'public', 'fou', ARRAY['id', 'name', 'numb', 'howdy'] ), false, 'columns_are(schema, table, columns) + extra & missing', 'Table public.fou should have the correct columns', ' Extra columns: "myInt" Missing columns: howdy' ); SELECT * FROM check_test( columns_are( 'fou', ARRAY['id', 'name', 'numb', 'myInt'], 'whatever' ), true, 'columns_are(table, columns, desc)', 'whatever', '' ); SELECT * FROM check_test( columns_are( 'fou', ARRAY['id', 'name', 'numb', 'myInt'] ), true, 'columns_are(table, columns)', 'Table fou should have the correct columns', '' ); SELECT * FROM check_test( columns_are( 'fou', ARRAY['id', 'name', 'numb'] ), false, 'columns_are(table, columns) + extra', 'Table fou should have the correct columns', ' Extra columns: "myInt"' ); SELECT * FROM check_test( columns_are( 'fou', ARRAY['id', 'name', 'numb', 'myInt', 'howdy'] ), false, 'columns_are(table, columns) + missing', 'Table fou should have the correct columns', ' Missing columns: howdy' ); SELECT * FROM check_test( columns_are( 'fou', ARRAY['id', 'name', 'numb', 'howdy'] ), false, 'columns_are(table, columns) + extra & missing', 'Table fou should have the correct columns', ' Extra columns: "myInt" Missing columns: howdy' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._check.sql000644 000765 000024 00000000252 11666501762 016747 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/check.sql000644 000765 000024 00000010747 11666501762 016544 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(48); -- This will be rolled back. :-) SET client_min_messages = warning; CREATE TABLE public.sometab( id INT NOT NULL PRIMARY KEY, name TEXT DEFAULT '' CHECK ( name IN ('foo', 'bar', 'baz') ), numb NUMERIC(10, 2), myint NUMERIC(8), CHECK (numb > 1.0 AND myint < 10) ); RESET client_min_messages; /****************************************************************************/ -- Test has_check(). SELECT * FROM check_test( has_check( 'public', 'sometab', 'public.sometab should have a check constraint' ), true, 'has_check( schema, table, desc )', 'public.sometab should have a check constraint', '' ); SELECT * FROM check_test( has_check( 'sometab', 'sometab should have a check constraint' ), true, 'has_check( table, desc )', 'sometab should have a check constraint', '' ); SELECT * FROM check_test( has_check( 'sometab' ), true, 'has_check( table )', 'Table sometab should have a check constraint', '' ); SELECT * FROM check_test( has_check( 'pg_catalog', 'pg_class', 'pg_catalog.pg_class should have a check constraint' ), false, 'has_check( schema, table, descr ) fail', 'pg_catalog.pg_class should have a check constraint', '' ); SELECT * FROM check_test( has_check( 'pg_class', 'pg_class should have a check constraint' ), false, 'has_check( table, desc ) fail', 'pg_class should have a check constraint', '' ); /****************************************************************************/ -- Test col_has_check(). SELECT * FROM check_test( col_has_check( 'public', 'sometab', 'name', 'public.sometab.name should have a check' ), true, 'col_has_check( sch, tab, col, desc )', 'public.sometab.name should have a check', '' ); SELECT * FROM check_test( col_has_check( 'public', 'sometab', ARRAY['numb', 'myint'], 'public.sometab.numb+myint should have a check' ), true, 'col_has_check( sch, tab, cols, desc )', 'public.sometab.numb+myint should have a check', '' ); SELECT * FROM check_test( col_has_check( 'sometab', 'name', 'sometab.name should have a check' ), true, 'col_has_check( tab, col, desc )', 'sometab.name should have a check', '' ); SELECT * FROM check_test( col_has_check( 'sometab', ARRAY['numb', 'myint'], 'sometab.numb+myint should have a check' ), true, 'col_has_check( tab, cols, desc )', 'sometab.numb+myint should have a check', '' ); SELECT * FROM check_test( col_has_check( 'sometab', 'name' ), true, 'col_has_check( table, column )', 'Column sometab(name) should have a check constraint', '' ); SELECT * FROM check_test( col_has_check( 'sometab', ARRAY['numb', 'myint'] ), true, 'col_has_check( table, columns )', 'Columns sometab(numb, myint) should have a check constraint', '' ); SELECT * FROM check_test( col_has_check( 'public', 'sometab', 'id', 'public.sometab.id should have a check' ), false, 'col_has_check( sch, tab, col, desc ) fail', 'public.sometab.id should have a check', ' have: {name} {numb,myint} want: {id}' ); SELECT * FROM check_test( col_has_check( 'sometab', 'id', 'sometab.id should have a check' ), false, 'col_has_check( tab, col, desc ) fail', 'sometab.id should have a check', ' have: {name} {numb,myint} want: {id}' ); /****************************************************************************/ -- Test col_has_check() with an array of columns. SET LOCAL client_min_messages = warning; CREATE TABLE public.argh ( id INT NOT NULL, name TEXT NOT NULL, CHECK ( id IN (1, 2) AND name IN ('foo', 'bar')) ); RESET client_min_messages; SELECT * FROM check_test( col_has_check( 'public', 'argh', ARRAY['id', 'name'], 'id + name should have a check' ), true, 'col_has_check( sch, tab, col[], desc )', 'id + name should have a check', '' ); SELECT * FROM check_test( col_has_check( 'argh', ARRAY['id', 'name'], 'id + name should have a check' ), true, 'col_has_check( tab, col[], desc )', 'id + name should have a check', '' ); SELECT * FROM check_test( col_has_check( 'argh', ARRAY['id', 'name'] ), true, 'col_has_check( tab, col[] )', 'Columns argh(id, name) should have a check constraint', '' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._cmpok.sql000644 000765 000024 00000000252 11666501762 017003 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/cmpok.sql000644 000765 000024 00000005742 11666501762 016577 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(38); /****************************************************************************/ -- Set up some functions that are used only by this test, and aren't available -- in PostgreSQL 8.2 or older CREATE OR REPLACE FUNCTION quote_literal(polygon) RETURNS TEXT AS 'SELECT '''''''' || textin(poly_out($1)) || ''''''''' LANGUAGE SQL IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION quote_literal(integer[]) RETURNS TEXT AS 'SELECT '''''''' || textin(array_out($1)) || ''''''''' LANGUAGE SQL IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION quote_literal(inet[]) RETURNS TEXT AS 'SELECT '''''''' || textin(array_out($1)) || ''''''''' LANGUAGE SQL IMMUTABLE STRICT; /****************************************************************************/ -- Test cmp_ok(). SELECT * FROM check_test( cmp_ok( 1, '=', 1, '1 should = 1' ), true, 'cmp_ok( int, =, int )', '1 should = 1', '' ); SELECT * FROM check_test( cmp_ok( 1, '<>', 2, '1 should <> 2' ), true, 'cmp_ok( int, <>, int )', '1 should <> 2', '' ); SELECT * FROM check_test( cmp_ok( '((0,0),(1,1))'::polygon, '~=', '((1,1),(0,0))'::polygon ), true, 'cmp_ok( polygon, ~=, polygon )' '', '' ); SELECT * FROM check_test( cmp_ok( ARRAY[1, 2], '=', ARRAY[1, 2]), true, 'cmp_ok( int[], =, int[] )', '', '' ); SELECT * FROM check_test( cmp_ok( ARRAY['192.168.1.2'::inet], '=', ARRAY['192.168.1.2'::inet] ), true, 'cmp_ok( inet[], =, inet[] )', '', '' ); SELECT * FROM check_test( cmp_ok( 1, '=', 2, '1 should = 2' ), false, 'cmp_ok() fail', '1 should = 2', ' ''1'' = ''2''' ); SELECT * FROM check_test( cmp_ok( 1, '=', NULL, '1 should = NULL' ), false, 'cmp_ok() NULL fail', '1 should = NULL', ' ''1'' = NULL' ); /****************************************************************************/ -- Test isa_ok(). SELECT * FROM check_test( isa_ok( ''::text, 'text', 'an empty string' ), true, 'isa_ok("", text, desc)', 'an empty string isa text', '' ); SELECT * FROM check_test( isa_ok( ''::text, 'text', 'an empty string' ), true, 'isa_ok("", text, desc)', 'an empty string isa text', '' ); SELECT * FROM check_test( isa_ok( false, 'bool' ), true, 'isa_ok(false, boolean)', 'the value isa boolean', '' ); SELECT * FROM check_test( isa_ok( NULL::boolean, 'bool' ), true, 'isa_ok(NULL, boolean)', 'the value isa boolean', '' ); SELECT * FROM check_test( isa_ok( ARRAY[false], 'bool[]' ), true, 'isa_ok(ARRAY, boolean[])', 'the value isa boolean[]', '' ); SELECT * FROM check_test( isa_ok( true, 'int[]' ), false, 'isa_ok(bool, int[])', 'the value isa integer[]', ' the value isn''t a "integer[]" it''s a "boolean"' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._coltap.sql000644 000765 000024 00000000252 11666501762 017154 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/coltap.sql000644 000765 000024 00000044542 11666501762 016751 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(204); --SELECT * from no_plan(); CREATE TYPE public."myType" AS ( id INT, foo INT ); -- This will be rolled back. :-) SET client_min_messages = warning; CREATE TABLE public.sometab( id INT NOT NULL PRIMARY KEY, name TEXT DEFAULT '', numb NUMERIC(10, 2) DEFAULT NULL, "myNum" NUMERIC(8) DEFAULT 24, myat TIMESTAMP DEFAULT NOW(), plain INTEGER, camel "myType" ); CREATE OR REPLACE FUNCTION fakeout( eok boolean, name text ) RETURNS SETOF TEXT AS $$ DECLARE descr text := coalesce( name || ' ', 'Test ' ) || 'should '; BEGIN RETURN NEXT pass(descr || CASE eok WHEN true then 'pass' ELSE 'fail' END); RETURN NEXT pass(descr || 'have the proper description'); RETURN NEXT pass(descr || 'have the proper diagnostics'); RETURN; END; $$ LANGUAGE PLPGSQL; RESET client_min_messages; /****************************************************************************/ -- Test col_not_null(). SELECT * FROM check_test( col_not_null( 'pg_catalog', 'pg_type', 'typname', 'typname not null' ), true, 'col_not_null( sch, tab, col, desc )', 'typname not null', '' ); SELECT * FROM check_test( col_not_null( 'sometab', 'id', 'blah blah blah' ), true, 'col_not_null( tab, col, desc )', 'blah blah blah', '' ); SELECT * FROM check_test( col_not_null( 'sometab', 'id' ), true, 'col_not_null( table, column )', 'Column sometab.id should be NOT NULL', '' ); -- Make sure failure is correct. SELECT * FROM check_test( col_not_null( 'sometab', 'name' ), false, 'col_not_null( table, column ) fail', 'Column sometab.name should be NOT NULL', '' ); -- Make sure nonexisting column is correct SELECT * FROM check_test( col_not_null( 'pg_catalog', 'pg_type', 'foo', 'desc' ), false, 'col_not_null( sch, tab, noncol, desc )', 'desc', ' Column pg_catalog.pg_type.foo does not exist' ); SELECT * FROM check_test( col_not_null( 'sometab', 'foo' ), false, 'col_not_null( table, noncolumn ) fail', 'Column sometab.foo should be NOT NULL', ' Column sometab.foo does not exist' ); /****************************************************************************/ -- Test col_is_null(). SELECT * FROM check_test( col_is_null( 'public', 'sometab', 'name', 'name is null' ), true, 'col_is_null( sch, tab, col, desc )', 'name is null', '' ); SELECT * FROM check_test( col_is_null( 'sometab', 'name', 'my desc' ), true, 'col_is_null( tab, col, desc )', 'my desc', '' ); SELECT * FROM check_test( col_is_null( 'sometab', 'name' ), true, 'col_is_null( tab, col )', 'Column sometab.name should allow NULL', '' ); -- Make sure failure is correct. SELECT * FROM check_test( col_is_null( 'sometab', 'id' ), false, 'col_is_null( tab, col ) fail', 'Column sometab.id should allow NULL', '' ); -- Make sure nonexisting column is correct SELECT * FROM check_test( col_is_null( 'pg_catalog', 'pg_type', 'foo', 'desc' ), false, 'col_is_null( sch, tab, noncol, desc )', 'desc', ' Column pg_catalog.pg_type.foo does not exist' ); SELECT * FROM check_test( col_is_null( 'sometab', 'foo' ), false, 'col_is_null( table, noncolumn ) fail', 'Column sometab.foo should allow NULL', ' Column sometab.foo does not exist' ); /****************************************************************************/ -- Test col_type_is(). SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'name', 'pg_catalog', 'text', 'name is text' ), true, 'col_type_is( sch, tab, col, sch, type, desc )', 'name is text', '' ); SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'name', 'pg_catalog'::name, 'text' ), true, 'col_type_is( sch, tab, col, sch, type, desc )', 'Column public.sometab.name should be type pg_catalog.text', '' ); -- Try case-sensitive column name. SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'myNum', 'pg_catalog', 'numeric(8,0)', 'myNum is numeric' ), true, 'col_type_is( sch, tab, myNum, sch, type, desc )', 'myNum is numeric', '' ); SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'myNum', 'pg_catalog'::name, 'numeric(8,0)' ), true, 'col_type_is( sch, tab, myNum, sch, type, desc )', 'Column public.sometab."myNum" should be type pg_catalog.numeric(8,0)', '' ); -- Try case-sensitive type name. SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'camel', 'public', 'myType', 'camel is myType' ), true, 'col_type_is( sch, tab, camel, sch, type, desc )', 'camel is myType', '' ); SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'camel', 'public'::name, 'myType' ), true, 'col_type_is( sch, tab, camel, sch, type, desc )', 'Column public.sometab.camel should be type public.myType', '' ); SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'camel', 'myType', 'whatever' ), true, 'col_type_is( sch, tab, camel, type, desc )', 'whatever', '' ); -- Try failures. SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'name', 'pg_catalog', 'integer', 'whatever' ), false, 'col_type_is( sch, tab, col, sch, type, desc ) fail', 'whatever', ' have: pg_catalog.text want: pg_catalog.integer' ); SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'name', 'pg_catalog', 'blech', 'whatever' ), false, 'col_type_is( sch, tab, col, sch, non-type, desc )', 'whatever', ' have: pg_catalog.text want: pg_catalog.blech' ); SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'name', 'fooey', 'text', 'whatever' ), false, 'col_type_is( sch, tab, col, non-sch, type, desc )', 'whatever', ' have: pg_catalog.text want: fooey.text' ); SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'nonesuch', 'pg_catalog', 'text', 'whatever' ), false, 'col_type_is( sch, tab, non-col, sch, type, desc )', 'whatever', ' Column public.sometab.nonesuch does not exist' ); SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'name', 'text', 'name is text' ), true, 'col_type_is( sch, tab, col, type, desc )', 'name is text', '' ); SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'name'::name, 'text' ), true, 'col_type_is( sch, tab, col, type )', 'Column public.sometab.name should be type text', '' ); SELECT * FROM check_test( col_type_is( 'sometab', 'name', 'text', 'yadda yadda yadda' ), true, 'col_type_is( tab, col, type, desc )', 'yadda yadda yadda', '' ); SELECT * FROM check_test( col_type_is( 'sometab', 'name', 'text' ), true, 'col_type_is( tab, col, type )', 'Column sometab.name should be type text', '' ); -- Make sure failure is correct. SELECT * FROM check_test( col_type_is( 'sometab', 'name', 'int4' ), false, 'col_type_is( tab, col, type ) fail', 'Column sometab.name should be type int4', ' have: text want: int4' ); -- Make sure missing column is in diagnostics. SELECT * FROM check_test( col_type_is( 'sometab', 'blah', 'int4' ), false, 'col_type_is( tab, noncol, type ) fail', 'Column sometab.blah should be type int4', ' Column sometab.blah does not exist' ); SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'blah', 'text', 'blah is text' ), false, 'col_type_is( sch, tab, noncol, type, desc ) fail', 'blah is text', ' Column public.sometab.blah does not exist' ); /****************************************************************************/ -- Try col_type_is() with precision. SELECT * FROM check_test( col_type_is( 'public', 'sometab', 'numb', 'numeric(10,2)', 'lol' ), true, 'col_type_is with precision', 'lol', '' ); -- Check its diagnostics. SELECT * FROM check_test( col_type_is( 'sometab', 'myNum', 'numeric(7)', 'should be numeric(7)' ), false, 'col_type_is precision fail', 'should be numeric(7)', ' have: numeric(8,0) want: numeric(7)' ); /****************************************************************************/ -- Test col_has_default(). SELECT * FROM check_test( col_has_default( 'public', 'sometab', 'name', 'desc' ), true, 'col_has_default( sch, tab, col, desc )', 'desc', '' ); SELECT * FROM check_test( col_has_default( 'sometab', 'name', 'desc' ), true, 'col_has_default( tab, col, desc )', 'desc', '' ); SELECT * FROM check_test( col_has_default( 'sometab', 'name' ), true, 'col_has_default( tab, col )', 'Column sometab.name should have a default', '' ); -- Check with a column with no default. SELECT * FROM check_test( col_has_default( 'public', 'sometab', 'plain', 'desc' ), false, 'col_has_default( sch, tab, col, desc )', 'desc', '' ); SELECT * FROM check_test( col_has_default( 'sometab', 'plain', 'desc' ), false, 'col_has_default( tab, col, desc )', 'desc', '' ); SELECT * FROM check_test( col_has_default( 'sometab', 'plain' ), false, 'col_has_default( tab, col )', 'Column sometab.plain should have a default', '' ); -- Check with a nonexistent column. SELECT * FROM check_test( col_has_default( 'public', 'sometab', '__asdfasdfs__', 'desc' ), false, 'col_has_default( sch, tab, col, desc )', 'desc', ' Column public.sometab.__asdfasdfs__ does not exist' ); SELECT * FROM check_test( col_has_default( 'sometab', '__asdfasdfs__', 'desc' ), false, 'col_has_default( tab, col, desc )', 'desc', ' Column sometab.__asdfasdfs__ does not exist' ); SELECT * FROM check_test( col_has_default( 'sometab', '__asdfasdfs__' ), false, 'col_has_default( tab, col )', 'Column sometab.__asdfasdfs__ should have a default', ' Column sometab.__asdfasdfs__ does not exist' ); /****************************************************************************/ -- Test col_hasnt_default(). SELECT * FROM check_test( col_hasnt_default( 'public', 'sometab', 'name', 'desc' ), false, 'col_hasnt_default( sch, tab, col, desc )', 'desc', '' ); SELECT * FROM check_test( col_hasnt_default( 'sometab', 'name', 'desc' ), false, 'col_hasnt_default( tab, col, desc )', 'desc', '' ); SELECT * FROM check_test( col_hasnt_default( 'sometab', 'name' ), false, 'col_hasnt_default( tab, col )', 'Column sometab.name should not have a default', '' ); -- Check with a column with no default. SELECT * FROM check_test( col_hasnt_default( 'public', 'sometab', 'plain', 'desc' ), true, 'col_hasnt_default( sch, tab, col, desc )', 'desc', '' ); SELECT * FROM check_test( col_hasnt_default( 'sometab', 'plain', 'desc' ), true, 'col_hasnt_default( tab, col, desc )', 'desc', '' ); SELECT * FROM check_test( col_hasnt_default( 'sometab', 'plain' ), true, 'col_hasnt_default( tab, col )', 'Column sometab.plain should not have a default', '' ); -- Check with a nonexistent column. SELECT * FROM check_test( col_hasnt_default( 'public', 'sometab', '__asdfasdfs__', 'desc' ), false, 'col_hasnt_default( sch, tab, col, desc )', 'desc', ' Column public.sometab.__asdfasdfs__ does not exist' ); SELECT * FROM check_test( col_hasnt_default( 'sometab', '__asdfasdfs__', 'desc' ), false, 'col_hasnt_default( tab, col, desc )', 'desc', ' Column sometab.__asdfasdfs__ does not exist' ); SELECT * FROM check_test( col_hasnt_default( 'sometab', '__asdfasdfs__' ), false, 'col_hasnt_default( tab, col )', 'Column sometab.__asdfasdfs__ should not have a default', ' Column sometab.__asdfasdfs__ does not exist' ); /****************************************************************************/ -- Test col_default_is(). SELECT * FROM check_test( col_default_is( 'public', 'sometab', 'name', ''::text, 'name should default to empty string' ), true, 'col_default_is( sch, tab, col, def, desc )', 'name should default to empty string', '' ); SELECT * FROM check_test( col_default_is( 'public', 'sometab', 'name', 'foo'::text, 'name should default to ''foo''' ), false, 'col_default_is() fail', 'name should default to ''foo''', ' have: want: foo' ); SELECT * FROM check_test( col_default_is( 'sometab', 'name', ''::text, 'name should default to empty string' ), true, 'col_default_is( tab, col, def, desc )', 'name should default to empty string', '' ); SELECT * FROM check_test( col_default_is( 'sometab', 'name', ''::text ), true, 'col_default_is( tab, col, def )', 'Column sometab.name should default to ''''', '' ); -- Make sure it works with a NULL default. CREATE OR REPLACE FUNCTION versiontests () RETURNS SETOF TEXT AS $$ DECLARE tap record; BEGIN IF pg_version_num() < 80300 THEN -- Before 8.3, have to cast to text. FOR tap IN SELECT * FROM check_test( col_default_is( 'sometab', 'myNum', 24::text ), true, 'col_default_is( tab, col, int )', 'Column sometab."myNum" should default to ''24''', '' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; -- Before 8.3, DEFAULT NULL was ignored. FOR tap IN SELECT * FROM fakeout( true, 'col_default_is( tab, col, NULL, desc )' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM fakeout( true, 'col_default_is( tab, col, NULL )' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; -- Make sure that it fails when there is no default. -- Before 8.3, must cast values to text FOR tap IN SELECT * FROM check_test( col_default_is( 'sometab', 'plain', 1::text, 'desc' ), false, 'col_default_is( tab, col, bogus, desc )', 'desc', ' Column sometab.plain has no default' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( col_default_is( 'sometab', 'plain', 1::text ), false, 'col_default_is( tab, col, bogus )', 'Column sometab.plain should default to ''1''', ' Column sometab.plain has no default' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; ELSE -- In 8.3 and later, can just use the raw value. FOR tap IN SELECT * FROM check_test( col_default_is( 'sometab', 'myNum', 24 ), true, 'col_default_is( tab, col, int )', 'Column sometab."myNum" should default to ''24''', '' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; -- In 8.3 and later, we can handle DEFAULT NULL correctly. FOR tap IN SELECT * FROM check_test( col_default_is( 'sometab', 'numb', NULL::numeric, 'desc' ), true, 'col_default_is( tab, col, NULL, desc )', 'desc', '' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( col_default_is( 'sometab', 'numb', NULL::numeric ), true, 'col_default_is( tab, col, NULL )', 'Column sometab.numb should default to NULL', '' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; -- Make sure that it fails when there is no default. -- In 8.3 and later, can just use raw values. FOR tap IN SELECT * FROM check_test( col_default_is( 'sometab', 'plain', 1, 'desc' ), false, 'col_default_is( tab, col, bogus, desc )', 'desc', ' Column sometab.plain has no default' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( col_default_is( 'sometab', 'plain', 1 ), false, 'col_default_is( tab, col, bogus )', 'Column sometab.plain should default to ''1''', ' Column sometab.plain has no default' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; END IF; RETURN; END; $$ LANGUAGE plpgsql; SELECT * FROM versiontests(); -- Make sure that it works when the default is an expression. SELECT * FROM check_test( col_default_is( 'sometab', 'myat', 'now()' ), true, 'col_default_is( tab, col, expression )', 'Column sometab.myat should default to ''now()''', '' ); SELECT * FROM check_test( col_default_is( 'sometab', 'myat', 'now()'::text ), true, 'col_default_is( tab, col, expression::text )', 'Column sometab.myat should default to ''now()''', '' ); SELECT * FROM check_test( col_default_is( 'sometab', 'myat', 'now()', 'desc' ), true, 'col_default_is( tab, col, expression, desc )', 'desc', '' ); SELECT * FROM check_test( col_default_is( 'sometab', 'myat', 'now()', 'desc'::text ), true, 'col_default_is( tab, col, expression, desc )', 'desc', '' ); SELECT * FROM check_test( col_default_is( 'public', 'sometab', 'myat', 'now()', 'desc' ), true, 'col_default_is( schema, tab, col, expression, desc )', 'desc', '' ); SELECT * FROM check_test( col_default_is( 'public', 'sometab', 'myat', 'now()', 'desc'::text ), true, 'col_default_is( schema, tab, col, expression, desc )', 'desc', '' ); -- Check with a nonexistent column. SELECT * FROM check_test( col_default_is( 'public', 'sometab', '__asdfasdfs__', NULL::text, 'desc' ), false, 'col_default_is( sch, tab, col, def, desc )', 'desc', ' Column public.sometab.__asdfasdfs__ does not exist' ); SELECT * FROM check_test( col_default_is( 'sometab', '__asdfasdfs__', NULL::text, 'desc' ), false, 'col_default_is( tab, col, def, desc )', 'desc', ' Column sometab.__asdfasdfs__ does not exist' ); SELECT * FROM check_test( col_default_is( 'sometab', '__asdfasdfs__', NULL::text ), false, 'col_default_is( tab, col, def )', 'Column sometab.__asdfasdfs__ should default to NULL', ' Column sometab.__asdfasdfs__ does not exist' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._do_tap.sql000644 000765 000024 00000000252 11666501762 017140 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/do_tap.sql000644 000765 000024 00000002420 11666501762 016722 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SET client_min_messages = notice; SELECT plan(26); --SELECT * FROM no_plan(); CREATE OR REPLACE FUNCTION public.testthis() RETURNS SETOF TEXT AS $$ SELECT pass('simple pass') AS foo UNION SELECT pass('another simple pass') ORDER BY foo ASC; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION public.testplpgsql() RETURNS SETOF TEXT AS $$ BEGIN RETURN NEXT pass( 'plpgsql simple' ); RETURN NEXT pass( 'plpgsql simple 2' ); RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION public."test ident"() RETURNS SETOF TEXT AS $$ BEGIN RETURN NEXT pass( 'ident' ); RETURN NEXT pass( 'ident 2' ); RETURN; END; $$ LANGUAGE plpgsql; SELECT is( findfuncs('public', '^test'), ARRAY[ 'public."test ident"', 'public.testplpgsql', 'public.testthis' ], 'findfuncs(public, ^test) should work' ); SELECT is( findfuncs('^test'), ARRAY[ 'public."test ident"', 'public.testplpgsql', 'public.testthis' ], 'findfuncs(^test) should work' ); SELECT * FROM do_tap('public', '^test'); SELECT * FROM do_tap('public'::name); SELECT * FROM do_tap('^test'); SELECT * FROM do_tap(); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._enumtap.sql000644 000765 000024 00000000252 11666501762 017343 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/enumtap.sql000644 000765 000024 00000016637 11666501762 017144 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(96); --SELECT * FROM no_plan(); -- This will be rolled back. :-) SET client_min_messages = warning; CREATE TYPE public.bug_status AS ENUM ('new', 'open', 'closed'); RESET client_min_messages; /****************************************************************************/ -- Make sure has_type for enums. SELECT * FROM check_test( has_type( 'bug_status' ), true, 'has_type(enum)', 'Type bug_status should exist', '' ); /****************************************************************************/ -- Test has_enum(). SELECT * FROM check_test( has_enum( 'bug_status' ), true, 'has_enum(enum)', 'Enum bug_status should exist', '' ); SELECT * FROM check_test( has_enum( 'bug_status', 'mydesc' ), true, 'has_enum(enum, desc)', 'mydesc', '' ); SELECT * FROM check_test( has_enum( 'public'::name, 'bug_status'::name ), true, 'has_enum(scheam, enum)', 'Enum public.bug_status should exist', '' ); SELECT * FROM check_test( has_enum( 'public', 'bug_status', 'mydesc' ), true, 'has_enum(schema, enum, desc)', 'mydesc', '' ); -- Try failures. SELECT * FROM check_test( has_enum( '__foobarbaz__' ), false, 'has_enum(enum)', 'Enum __foobarbaz__ should exist', '' ); SELECT * FROM check_test( has_enum( '__foobarbaz__', 'mydesc' ), false, 'has_enum(enum, desc)', 'mydesc', '' ); SELECT * FROM check_test( has_enum( 'public'::name, '__foobarbaz__'::name ), false, 'has_enum(scheam, enum)', 'Enum public.__foobarbaz__ should exist', '' ); SELECT * FROM check_test( has_enum( 'public', '__foobarbaz__', 'mydesc' ), false, 'has_enum(schema, enum, desc)', 'mydesc', '' ); /****************************************************************************/ -- Test hasnt_enum(). SELECT * FROM check_test( hasnt_enum( '__foobarbaz__' ), true, 'hasnt_enum(enum)', 'Enum __foobarbaz__ should not exist', '' ); SELECT * FROM check_test( hasnt_enum( '__foobarbaz__', 'mydesc' ), true, 'hasnt_enum(enum, desc)', 'mydesc', '' ); SELECT * FROM check_test( hasnt_enum( 'public'::name, '__foobarbaz__'::name ), true, 'hasnt_enum(scheam, enum)', 'Enum public.__foobarbaz__ should not exist', '' ); SELECT * FROM check_test( hasnt_enum( 'public', '__foobarbaz__', 'mydesc' ), true, 'hasnt_enum(schema, enum, desc)', 'mydesc', '' ); -- Try failures. SELECT * FROM check_test( hasnt_enum( 'bug_status' ), false, 'hasnt_enum(enum)', 'Enum bug_status should not exist', '' ); SELECT * FROM check_test( hasnt_enum( 'bug_status', 'mydesc' ), false, 'hasnt_enum(enum, desc)', 'mydesc', '' ); SELECT * FROM check_test( hasnt_enum( 'public'::name, 'bug_status'::name ), false, 'hasnt_enum(scheam, enum)', 'Enum public.bug_status should not exist', '' ); SELECT * FROM check_test( hasnt_enum( 'public', 'bug_status', 'mydesc' ), false, 'hasnt_enum(schema, enum, desc)', 'mydesc', '' ); /****************************************************************************/ -- Test enum_has_labels(). SELECT * FROM check_test( enum_has_labels( 'public', 'bug_status', ARRAY['new', 'open', 'closed'], 'mydesc' ), true, 'enum_has_labels(schema, enum, labels, desc)', 'mydesc', '' ); SELECT * FROM check_test( enum_has_labels( 'public', 'bug_status', ARRAY['new', 'open', 'closed'] ), true, 'enum_has_labels(schema, enum, labels)', 'Enum public.bug_status should have labels (new, open, closed)', '' ); SELECT * FROM check_test( enum_has_labels( 'bug_status', ARRAY['new', 'open', 'closed'], 'mydesc' ), true, 'enum_has_labels(enum, labels, desc)', 'mydesc', '' ); SELECT * FROM check_test( enum_has_labels( 'bug_status', ARRAY['new', 'open', 'closed'] ), true, 'enum_has_labels(enum, labels)', 'Enum bug_status should have labels (new, open, closed)', '' ); -- Try failures. SELECT * FROM check_test( enum_has_labels( 'public', 'bug_status', ARRAY['new', 'closed', 'open'], 'mydesc' ), false, 'enum_has_labels(schema, enum, labels, desc) fail', 'mydesc', ' have: {new,open,closed} want: {new,closed,open}' ); SELECT * FROM check_test( enum_has_labels( 'public', 'bug_status', ARRAY['new', 'open', 'Closed'], 'mydesc' ), false, 'enum_has_labels(schema, enum, labels, desc) fail', 'mydesc', ' have: {new,open,closed} want: {new,open,Closed}' ); SELECT * FROM check_test( enum_has_labels( 'bug_status', ARRAY['new', 'closed', 'open'], 'mydesc' ), false, 'enum_has_labels(enum, labels, desc) fail', 'mydesc', ' have: {new,open,closed} want: {new,closed,open}' ); /****************************************************************************/ -- Test enums_are(). SELECT * FROM check_test( enums_are( 'public', ARRAY['bug_status'], 'whatever' ), true, 'enums_are(schema, enums, desc)', 'whatever', '' ); SELECT * FROM check_test( enums_are( 'public', ARRAY['bug_status'] ), true, 'enums_are(schema, enums)', 'Schema public should have the correct enums', '' ); SELECT * FROM check_test( enums_are( 'public', ARRAY['freddy'], 'whatever' ), false, 'enums_are(schema, enums, desc) fail', 'whatever', ' Extra types: bug_status Missing types: freddy' ); SELECT * FROM check_test( enums_are( 'public', ARRAY['freddy'] ), false, 'enums_are(schema, enums) fail', 'Schema public should have the correct enums', ' Extra types: bug_status Missing types: freddy' ); CREATE FUNCTION ___myenum(ex text) RETURNS NAME[] AS $$ SELECT COALESCE(ARRAY( SELECT t.typname FROM pg_catalog.pg_type t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE ( t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) ) AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid) AND n.nspname NOT IN('pg_catalog', 'information_schema') AND t.typname <> $1 AND pg_catalog.pg_type_is_visible(t.oid) AND t.typtype = 'e' ), '{}'::name[]); $$ LANGUAGE SQL; SELECT * FROM check_test( enums_are( ___myenum(''), 'whatever' ), true, 'enums_are(enums, desc)', 'whatever', '' ); SELECT * FROM check_test( enums_are( ___myenum('') ), true, 'enums_are(enums)', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct enums', '' ); SELECT * FROM check_test( enums_are( array_append(___myenum('bug_status'), 'fredy'), 'whatever' ), false, 'enums_are(enums, desc) fail', 'whatever', ' Extra types: bug_status Missing types: fredy' ); SELECT * FROM check_test( enums_are( array_append(___myenum('bug_status'), 'fredy') ), false, 'enums_are(enums) fail', 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct enums', ' Extra types: bug_status Missing types: fredy' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._fktap.sql000644 000765 000024 00000000252 11666501762 016777 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/fktap.sql000644 000765 000024 00000031057 11666501762 016571 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(128); --SELECT * from no_plan(); -- These will be rolled back. :-) SET client_min_messages = warning; CREATE TABLE public.pk ( id INT NOT NULL PRIMARY KEY, name TEXT DEFAULT '' ); CREATE TABLE public.fk ( id INT NOT NULL PRIMARY KEY, pk_id INT NOT NULL REFERENCES pk(id) ); CREATE TABLE public.pk2 ( num int NOT NULL, dot int NOT NULL, PRIMARY KEY (num, dot) ); CREATE TABLE public.fk2 ( pk2_num int NOT NULL, pk2_dot int NOT NULL, FOREIGN KEY(pk2_num, pk2_dot) REFERENCES pk2( num, dot) ); CREATE TABLE public.fk3( id INT NOT NULL PRIMARY KEY, pk_id INT NOT NULL REFERENCES pk(id), pk2_num int NOT NULL, pk2_dot int NOT NULL, foo_id INT NOT NULL, FOREIGN KEY(pk2_num, pk2_dot) REFERENCES pk2( num, dot) ); RESET client_min_messages; /****************************************************************************/ -- Test has_fk(). SELECT * FROM check_test( has_fk( 'public', 'fk', 'public.fk should have an fk' ), true, 'has_fk( schema, table, description )', 'public.fk should have an fk' ); SELECT * FROM check_test( has_fk( 'fk', 'fk should have an fk' ), 'true', 'has_fk( table, description )', 'fk should have an fk' ); SELECT * FROM check_test( has_fk( 'fk' ), true, 'has_fk( table )', 'Table fk should have a foreign key constraint' ); SELECT * FROM check_test( has_fk( 'pg_catalog', 'pg_class', 'pg_catalog.pg_class should have an fk' ), false, 'has_fk( schema, table, description ) fail', 'pg_catalog.pg_class should have an fk' ); SELECT * FROM check_test( has_fk( 'pg_class', 'pg_class should have an fk' ), false, 'has_fk( table, description ) fail', 'pg_class should have an fk' ); /****************************************************************************/ -- Test hasnt_fk(). SELECT * FROM check_test( hasnt_fk( 'public', 'fk', 'public.fk should not have an fk' ), false, 'hasnt_fk( schema, table, description )', 'public.fk should not have an fk' ); SELECT * FROM check_test( hasnt_fk( 'fk', 'fk should not have an fk' ), 'false', 'hasnt_fk( table, description )', 'fk should not have an fk' ); SELECT * FROM check_test( hasnt_fk( 'fk' ), false, 'hasnt_fk( table )', 'Table fk should not have a foreign key constraint' ); SELECT * FROM check_test( hasnt_fk( 'pg_catalog', 'pg_class', 'pg_catalog.pg_class should not have an fk' ), true, 'hasnt_fk( schema, table, description ) pass', 'pg_catalog.pg_class should not have an fk' ); SELECT * FROM check_test( hasnt_fk( 'pg_class', 'pg_class should not have an fk' ), true, 'hasnt_fk( table, description ) pass', 'pg_class should not have an fk' ); /****************************************************************************/ -- Test col_is_fk(). SELECT * FROM check_test( col_is_fk( 'public', 'fk', 'pk_id', 'public.fk.pk_id should be an fk' ), true, 'col_is_fk( schema, table, column, description )', 'public.fk.pk_id should be an fk' ); SELECT * FROM check_test( col_is_fk( 'fk', 'pk_id', 'fk.pk_id should be an fk' ), true, 'col_is_fk( table, column, description )', 'fk.pk_id should be an fk' ); SELECT * FROM check_test( col_is_fk( 'fk', 'pk_id' ), true, 'col_is_fk( table, column )', 'Column fk(pk_id) should be a foreign key' ); SELECT * FROM check_test( col_is_fk( 'public', 'fk', 'name', 'public.fk.name should be an fk' ), false, 'col_is_fk( schema, table, column, description )', 'public.fk.name should be an fk', ' Table public.fk has foreign key constraints on these columns: pk_id' ); SELECT * FROM check_test( col_is_fk( 'fk3', 'name', 'fk3.name should be an fk' ), false, 'col_is_fk( table, column, description )', 'fk3.name should be an fk', ' Table fk3 has foreign key constraints on these columns: pk2_num, pk2_dot pk_id' ); -- Check table with multiple FKs. SELECT * FROM check_test( col_is_fk( 'fk3', 'pk_id' ), true, 'multi-fk col_is_fk test', 'Column fk3(pk_id) should be a foreign key' ); -- Check failure for table with no FKs. SELECT * FROM check_test( col_is_fk( 'public', 'pk', 'name', 'pk.name should be an fk' ), false, 'col_is_fk with no FKs', 'pk.name should be an fk', ' Table public.pk has no foreign key columns' ); SELECT * FROM check_test( col_is_fk( 'pk', 'name' ), false, 'col_is_fk with no FKs', 'Column pk(name) should be a foreign key', ' Table pk has no foreign key columns' ); /****************************************************************************/ -- Test col_is_fk() with an array of columns. SELECT * FROM check_test( col_is_fk( 'public', 'fk2', ARRAY['pk2_num', 'pk2_dot'], 'id + pk2_dot should be an fk' ), true, 'col_is_fk( schema, table, column[], description )', 'id + pk2_dot should be an fk' ); SELECT * FROM check_test( col_is_fk( 'fk2', ARRAY['pk2_num', 'pk2_dot'], 'id + pk2_dot should be an fk' ), true, 'col_is_fk( table, column[], description )', 'id + pk2_dot should be an fk' ); SELECT * FROM check_test( col_is_fk( 'fk2', ARRAY['pk2_num', 'pk2_dot'] ), true, 'col_is_fk( table, column[] )', 'Columns fk2(pk2_num, pk2_dot) should be a foreign key' ); /****************************************************************************/ -- Test col_isnt_fk(). SELECT * FROM check_test( col_isnt_fk( 'public', 'fk', 'pk_id', 'public.fk.pk_id should not be an fk' ), false, 'col_isnt_fk( schema, table, column, description )', 'public.fk.pk_id should not be an fk', '' ); SELECT * FROM check_test( col_isnt_fk( 'fk', 'pk_id', 'fk.pk_id should not be an fk' ), false, 'col_isnt_fk( table, column, description )', 'fk.pk_id should not be an fk', '' ); SELECT * FROM check_test( col_isnt_fk( 'fk', 'pk_id' ), false, 'col_isnt_fk( table, column )', 'Column fk(pk_id) should not be a foreign key', '' ); SELECT * FROM check_test( col_isnt_fk( 'public', 'fk', 'name', 'public.fk.name should not be an fk' ), true, 'col_isnt_fk( schema, table, column, description )', 'public.fk.name should not be an fk', '' ); SELECT * FROM check_test( col_isnt_fk( 'fk3', 'name', 'fk3.name should not be an fk' ), true, 'col_isnt_fk( table, column, description )', 'fk3.name should not be an fk', '' ); -- Check table with multiple FKs. SELECT * FROM check_test( col_isnt_fk( 'fk3', 'pk_id' ), false, 'multi-fk col_isnt_fk test', 'Column fk3(pk_id) should not be a foreign key', '' ); -- Check failure for table with no FKs. SELECT * FROM check_test( col_isnt_fk( 'public', 'pk', 'name', 'pk.name should not be an fk' ), true, 'col_isnt_fk with no FKs', 'pk.name should not be an fk', '' ); SELECT * FROM check_test( col_isnt_fk( 'pk', 'name' ), true, 'col_isnt_fk with no FKs', 'Column pk(name) should not be a foreign key', '' ); /****************************************************************************/ -- Test col_isnt_fk() with an array of columns. SELECT * FROM check_test( col_isnt_fk( 'public', 'fk2', ARRAY['pk2_num', 'pk2_dot'], 'id + pk2_dot should not be an fk' ), false, 'col_isnt_fk( schema, table, column[], description )', 'id + pk2_dot should not be an fk' ); SELECT * FROM check_test( col_isnt_fk( 'fk2', ARRAY['pk2_num', 'pk2_dot'], 'id + pk2_dot should not be an fk' ), false, 'col_isnt_fk( table, column[], description )', 'id + pk2_dot should not be an fk' ); SELECT * FROM check_test( col_isnt_fk( 'fk2', ARRAY['pk2_num', 'pk2_dot'] ), false, 'col_isnt_fk( table, column[] )', 'Columns fk2(pk2_num, pk2_dot) should not be a foreign key' ); /****************************************************************************/ -- Test fk_ok(). SELECT * FROM check_test( fk_ok( 'public', 'fk', ARRAY['pk_id'], 'public', 'pk', ARRAY['id'], 'WHATEVER' ), true, 'full fk_ok array', 'WHATEVER' ); SELECT * FROM check_test( fk_ok( 'public', 'fk2', ARRAY['pk2_num', 'pk2_dot'], 'public', 'pk2', ARRAY['num', 'dot'] ), true, 'multiple fk fk_ok desc', 'public.fk2(pk2_num, pk2_dot) should reference public.pk2(num, dot)' ); SELECT * FROM check_test( fk_ok( 'public', 'fk', ARRAY['pk_id'], 'public', 'pk', ARRAY['id'] ), true, 'fk_ok array desc', 'public.fk(pk_id) should reference public.pk(id)' ); SELECT * FROM check_test( fk_ok( 'fk', ARRAY['pk_id'], 'pk', ARRAY['id'] ), true, 'fk_ok array noschema desc', 'fk(pk_id) should reference pk(id)' ); SELECT * FROM check_test( fk_ok( 'fk2', ARRAY['pk2_num', 'pk2_dot'], 'pk2', ARRAY['num', 'dot'] ), true, 'multiple fk fk_ok noschema desc', 'fk2(pk2_num, pk2_dot) should reference pk2(num, dot)' ); SELECT * FROM check_test( fk_ok( 'fk', ARRAY['pk_id'], 'pk', ARRAY['id'], 'WHATEVER' ), true, 'fk_ok array noschema', 'WHATEVER' ); SELECT * FROM check_test( fk_ok( 'public', 'fk', 'pk_id', 'public', 'pk', 'id', 'WHATEVER' ), true, 'basic fk_ok', 'WHATEVER' ); SELECT * FROM check_test( fk_ok( 'public', 'fk', 'pk_id', 'public', 'pk', 'id' ), true, 'basic fk_ok desc', 'public.fk(pk_id) should reference public.pk(id)' ); SELECT * FROM check_test( fk_ok( 'fk', 'pk_id', 'pk', 'id', 'WHATEVER' ), true, 'basic fk_ok noschema', 'WHATEVER' ); SELECT * FROM check_test( fk_ok( 'fk', 'pk_id', 'pk', 'id' ), true, 'basic fk_ok noschema desc', 'fk(pk_id) should reference pk(id)', '' ); -- Make sure check_test() works properly with no name argument. SELECT * FROM check_test( fk_ok( 'fk', 'pk_id', 'pk', 'id' ), true ); SELECT * FROM check_test( fk_ok( 'public', 'fk', ARRAY['pk_id'], 'public', 'pk', ARRAY['fid'], 'WHATEVER' ), false, 'fk_ok fail', 'WHATEVER', ' have: public.fk(pk_id) REFERENCES public.pk(id) want: public.fk(pk_id) REFERENCES public.pk(fid)' ); SELECT * FROM check_test( fk_ok( 'public', 'fk', ARRAY['pk_id'], 'public', 'pk', ARRAY['fid'] ), false, 'fk_ok fail desc', 'public.fk(pk_id) should reference public.pk(fid)', ' have: public.fk(pk_id) REFERENCES public.pk(id) want: public.fk(pk_id) REFERENCES public.pk(fid)' ); SELECT * FROM check_test( fk_ok( 'fk', ARRAY['pk_id'], 'pk', ARRAY['fid'], 'WHATEVER' ), false, 'fk_ok fail no schema', 'WHATEVER', ' have: fk(pk_id) REFERENCES pk(id) want: fk(pk_id) REFERENCES pk(fid)' ); SELECT * FROM check_test( fk_ok( 'fk', ARRAY['pk_id'], 'pk', ARRAY['fid'] ), false, 'fk_ok fail no schema desc', 'fk(pk_id) should reference pk(fid)', ' have: fk(pk_id) REFERENCES pk(id) want: fk(pk_id) REFERENCES pk(fid)' ); SELECT * FROM check_test( fk_ok( 'fk', ARRAY['pk_id'], 'ok', ARRAY['fid'], 'WHATEVER' ), false, 'fk_ok bad PK test', 'WHATEVER', ' have: fk(pk_id) REFERENCES pk(id) want: fk(pk_id) REFERENCES ok(fid)' ); -- Try a table with multiple FKs. SELECT * FROM check_test( fk_ok( 'public', 'fk3', 'pk_id', 'public', 'pk', 'id' ), true, 'double fk schema test', 'public.fk3(pk_id) should reference public.pk(id)', '' ); SELECT * FROM check_test( fk_ok( 'fk3', 'pk_id', 'pk', 'id' ), true, 'double fk test', 'fk3(pk_id) should reference pk(id)', '' ); -- Try the second FK on that table, which happens to be a multicolumn FK. SELECT * FROM check_test( fk_ok( 'public', 'fk3', ARRAY['pk2_num', 'pk2_dot'], 'public', 'pk2', ARRAY['num', 'dot'] ), true, 'double fk and col schema test', 'public.fk3(pk2_num, pk2_dot) should reference public.pk2(num, dot)', '' ); -- Try FK columns that reference nothing. SELECT * FROM check_test( fk_ok( 'public', 'fk3', 'id', 'public', 'foo', 'id' ), false, 'missing fk test', 'public.fk3(id) should reference public.foo(id)', ' have: public.fk3(id) REFERENCES NOTHING want: public.fk3(id) REFERENCES public.foo(id)' ); -- Try non-existent FK colums. SELECT * FROM check_test( fk_ok( 'fk3', ARRAY['pk2_blah', 'pk2_dot'], 'pk2', ARRAY['num', 'dot'] ), false, 'bad FK column test', 'fk3(pk2_blah, pk2_dot) should reference pk2(num, dot)', ' have: fk3(pk2_blah, pk2_dot) REFERENCES NOTHING want: fk3(pk2_blah, pk2_dot) REFERENCES pk2(num, dot)' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._functap.sql000644 000765 000024 00000000252 11666501762 017332 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/functap.sql000644 000765 000024 00000074653 11666501762 017135 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(466); --SELECT * FROM no_plan(); CREATE SCHEMA someschema; CREATE FUNCTION someschema.huh () RETURNS BOOL AS 'SELECT TRUE' LANGUAGE SQL; CREATE FUNCTION someschema.bah (int, text) RETURNS BOOL AS 'BEGIN RETURN TRUE; END;' LANGUAGE plpgsql; CREATE FUNCTION public.yay () RETURNS BOOL AS 'SELECT TRUE' LANGUAGE SQL STRICT SECURITY DEFINER VOLATILE; CREATE FUNCTION public.oww (int, text) RETURNS BOOL AS 'BEGIN RETURN TRUE; END;' LANGUAGE plpgsql IMMUTABLE; CREATE FUNCTION public.pet () RETURNS SETOF BOOL AS 'BEGIN RETURN NEXT TRUE; RETURN; END;' LANGUAGE plpgsql STABLE; CREATE AGGREGATE public.tap_accum ( sfunc = array_append, basetype = anyelement, stype = anyarray, initcond = '{}' ); /****************************************************************************/ -- Test has_function(). SELECT * FROM check_test( has_function( 'now' ), true, 'simple function', 'Function now() should exist', '' ); SELECT * FROM check_test( has_function( 'pg_catalog', 'now'::name ), true, 'simple schema.function', 'Function pg_catalog.now() should exist', '' ); SELECT * FROM check_test( has_function( 'now', 'whatever' ), true, 'simple function desc', 'whatever', '' ); SELECT * FROM check_test( has_function( 'now', '{}'::name[] ), true, 'simple with 0 args', 'Function now() should exist', '' ); SELECT * FROM check_test( has_function( 'now', '{}'::name[], 'whatever' ), true, 'simple with 0 args desc', 'whatever', '' ); SELECT * FROM check_test( has_function( 'pg_catalog', 'now', '{}'::name[] ), true, 'simple schema.func with 0 args', 'Function pg_catalog.now() should exist', '' ); SELECT * FROM check_test( has_function( 'pg_catalog', 'now', 'whatever' ), true, 'simple schema.func with desc', 'whatever', '' ); SELECT * FROM check_test( has_function( 'pg_catalog', 'now', '{}'::name[], 'whatever' ), true, 'simple scchma.func with 0 args, desc', 'whatever', '' ); SELECT * FROM check_test( has_function( 'lower', '{text}'::name[] ), true, 'simple function with 1 arg', 'Function lower(text) should exist', '' ); SELECT * FROM check_test( has_function( 'decode', '{text,text}'::name[] ), true, 'simple function with 2 args', 'Function decode(text, text) should exist', '' ); SELECT * FROM check_test( has_function( 'array_cat', ARRAY['anyarray','anyarray'] ), true, 'simple array function', 'Function array_cat(anyarray, anyarray) should exist', '' ); -- Check a custom function with an array argument. CREATE FUNCTION __cat__ (text[]) RETURNS BOOLEAN AS 'SELECT TRUE' LANGUAGE SQL; SELECT * FROM check_test( has_function( '__cat__', '{text[]}'::name[] ), true, 'custom array function', 'Function __cat__(text[]) should exist', '' ); -- Check a custom function with a numeric argument. CREATE FUNCTION __cat__ (numeric(10,2)) RETURNS BOOLEAN AS 'SELECT TRUE' LANGUAGE SQL; SELECT * FROM check_test( has_function( '__cat__', '{numeric}'::name[] ), true, 'custom numeric function', 'Function __cat__(numeric) should exist', '' ); -- Check failure output. SELECT * FROM check_test( has_function( '__cat__', '{varchar[]}'::name[] ), false, 'failure output', 'Function __cat__(varchar[]) should exist', '' -- No diagnostics. ); /****************************************************************************/ -- Test hasnt_function(). SELECT * FROM check_test( hasnt_function( 'now' ), false, 'simple function', 'Function now() should not exist', '' ); SELECT * FROM check_test( hasnt_function( 'pg_catalog', 'now'::name ), false, 'simple schema.function', 'Function pg_catalog.now() should not exist', '' ); SELECT * FROM check_test( hasnt_function( 'now', 'whatever' ), false, 'simple function desc', 'whatever', '' ); SELECT * FROM check_test( hasnt_function( 'now', '{}'::name[] ), false, 'simple with 0 args', 'Function now() should not exist', '' ); SELECT * FROM check_test( hasnt_function( 'now', '{}'::name[], 'whatever' ), false, 'simple with 0 args desc', 'whatever', '' ); SELECT * FROM check_test( hasnt_function( 'pg_catalog', 'now', '{}'::name[] ), false, 'simple schema.func with 0 args', 'Function pg_catalog.now() should not exist', '' ); SELECT * FROM check_test( hasnt_function( 'pg_catalog', 'now', 'whatever' ), false, 'simple schema.func with desc', 'whatever', '' ); SELECT * FROM check_test( hasnt_function( 'pg_catalog', 'now', '{}'::name[], 'whatever' ), false, 'simple scchma.func with 0 args, desc', 'whatever', '' ); SELECT * FROM check_test( hasnt_function( 'lower', '{text}'::name[] ), false, 'simple function with 1 arg', 'Function lower(text) should not exist', '' ); SELECT * FROM check_test( hasnt_function( 'decode', '{text,text}'::name[] ), false, 'simple function with 2 args', 'Function decode(text, text) should not exist', '' ); SELECT * FROM check_test( hasnt_function( 'array_cat', ARRAY['anyarray','anyarray'] ), false, 'simple array function', 'Function array_cat(anyarray, anyarray) should not exist', '' ); SELECT * FROM check_test( hasnt_function( '__cat__', '{text[]}'::name[] ), false, 'custom array function', 'Function __cat__(text[]) should not exist', '' ); SELECT * FROM check_test( hasnt_function( '__cat__', '{numeric}'::name[] ), false, 'custom numeric function', 'Function __cat__(numeric) should not exist', '' ); /****************************************************************************/ -- Try can() function names. SELECT * FROM check_test( can( 'pg_catalog', ARRAY['lower', 'upper'], 'whatever' ), true, 'can(schema) with desc', 'whatever', '' ); SELECT * FROM check_test( can( 'pg_catalog', ARRAY['lower', 'upper'] ), true, 'can(schema)', 'Schema pg_catalog can', '' ); SELECT * FROM check_test( can( 'pg_catalog', ARRAY['lower', 'foo', 'bar'], 'whatever' ), false, 'fail can(schema) with desc', 'whatever', ' pg_catalog.foo() missing pg_catalog.bar() missing' ); SELECT * FROM check_test( can( 'someschema', ARRAY['huh', 'lower', 'upper'], 'whatever' ), false, 'fail can(someschema) with desc', 'whatever', ' someschema.lower() missing someschema.upper() missing' ); SELECT * FROM check_test( can( ARRAY['__cat__', 'lower', 'upper'], 'whatever' ), true, 'can() with desc', 'whatever', '' ); SELECT * FROM check_test( can( ARRAY['lower', 'upper'] ), true, 'can(schema)', 'Schema ' || array_to_string(current_schemas(true), ' or ') || ' can', '' ); SELECT * FROM check_test( can( ARRAY['__cat__', 'foo', 'bar'], 'whatever' ), false, 'fail can() with desc', 'whatever', ' foo() missing bar() missing' ); /****************************************************************************/ -- Test function_lang_is(). SELECT * FROM check_test( function_lang_is( 'someschema', 'huh', '{}'::name[], 'sql', 'whatever' ), true, 'function_lang_is(schema, func, 0 args, sql, desc)', 'whatever', '' ); SELECT * FROM check_test( function_lang_is( 'someschema', 'huh', '{}'::name[], 'sql' ), true, 'function_lang_is(schema, func, 0 args, sql)', 'Function someschema.huh() should be written in sql', '' ); SELECT * FROM check_test( function_lang_is( 'someschema', 'bah', '{"integer", "text"}'::name[], 'plpgsql', 'whatever' ), true, 'function_lang_is(schema, func, args, plpgsql, desc)', 'whatever', '' ); SELECT * FROM check_test( function_lang_is( 'someschema', 'bah', '{"integer", "text"}'::name[], 'plpgsql' ), true, 'function_lang_is(schema, func, args, plpgsql)', 'Function someschema.bah(integer, text) should be written in plpgsql', '' ); SELECT * FROM check_test( function_lang_is( 'someschema', 'huh', '{}'::name[], 'perl', 'whatever' ), false, 'function_lang_is(schema, func, 0 args, perl, desc)', 'whatever', ' have: sql want: perl' ); SELECT * FROM check_test( function_lang_is( 'someschema', 'why', '{}'::name[], 'sql', 'whatever' ), false, 'function_lang_is(schema, non-func, 0 args, sql, desc)', 'whatever', ' Function someschema.why() does not exist' ); SELECT * FROM check_test( function_lang_is( 'someschema', 'why', '{"integer", "text"}'::name[], 'plpgsql' ), false, 'function_lang_is(schema, func, args, plpgsql)', 'Function someschema.why(integer, text) should be written in plpgsql', ' Function someschema.why(integer, text) does not exist' ); SELECT * FROM check_test( function_lang_is( 'someschema', 'huh', 'sql', 'whatever' ), true, 'function_lang_is(schema, func, sql, desc)', 'whatever', '' ); SELECT * FROM check_test( function_lang_is( 'someschema', 'huh', 'sql'::name ), true, 'function_lang_is(schema, func, sql)', 'Function someschema.huh() should be written in sql', '' ); SELECT * FROM check_test( function_lang_is( 'someschema', 'huh', 'perl', 'whatever' ), false, 'function_lang_is(schema, func, perl, desc)', 'whatever', ' have: sql want: perl' ); SELECT * FROM check_test( function_lang_is( 'someschema', 'why', 'sql', 'whatever' ), false, 'function_lang_is(schema, non-func, sql, desc)', 'whatever', ' Function someschema.why() does not exist' ); SELECT * FROM check_test( function_lang_is( 'yay', '{}'::name[], 'sql', 'whatever' ), true, 'function_lang_is(func, 0 args, sql, desc)', 'whatever', '' ); SELECT * FROM check_test( function_lang_is( 'yay', '{}'::name[], 'sql' ), true, 'function_lang_is(func, 0 args, sql)', 'Function yay() should be written in sql', '' ); SELECT * FROM check_test( function_lang_is( 'oww', '{"integer", "text"}'::name[], 'plpgsql', 'whatever' ), true, 'function_lang_is(func, args, plpgsql, desc)', 'whatever', '' ); SELECT * FROM check_test( function_lang_is( 'oww', '{"integer", "text"}'::name[], 'plpgsql' ), true, 'function_lang_is(func, args, plpgsql)', 'Function oww(integer, text) should be written in plpgsql', '' ); SELECT * FROM check_test( function_lang_is( 'yay', '{}'::name[], 'perl', 'whatever' ), false, 'function_lang_is(func, 0 args, perl, desc)', 'whatever', ' have: sql want: perl' ); SELECT * FROM check_test( function_lang_is( 'why', '{}'::name[], 'sql', 'whatever' ), false, 'function_lang_is(non-func, 0 args, sql, desc)', 'whatever', ' Function why() does not exist' ); SELECT * FROM check_test( function_lang_is( 'why', '{"integer", "text"}'::name[], 'plpgsql' ), false, 'function_lang_is(func, args, plpgsql)', 'Function why(integer, text) should be written in plpgsql', ' Function why(integer, text) does not exist' ); SELECT * FROM check_test( function_lang_is( 'yay', 'sql', 'whatever' ), true, 'function_lang_is(func, sql, desc)', 'whatever', '' ); SELECT * FROM check_test( function_lang_is( 'yay', 'sql' ), true, 'function_lang_is(func, sql)', 'Function yay() should be written in sql', '' ); SELECT * FROM check_test( function_lang_is( 'yay', 'perl', 'whatever' ), false, 'function_lang_is(func, perl, desc)', 'whatever', ' have: sql want: perl' ); SELECT * FROM check_test( function_lang_is( 'why', 'sql', 'whatever' ), false, 'function_lang_is(non-func, sql, desc)', 'whatever', ' Function why() does not exist' ); /****************************************************************************/ -- Test function_returns(). SELECT * FROM check_test( function_returns( 'someschema', 'huh', '{}'::name[], 'boolean', 'whatever' ), true, 'function_returns(schema, func, 0 args, bool, desc)', 'whatever', '' ); SELECT * FROM check_test( function_returns( 'someschema', 'huh', '{}'::name[], 'boolean' ), true, 'function_returns(schema, func, 0 args, bool)', 'Function someschema.huh() should return boolean', '' ); SELECT * FROM check_test( function_returns( 'someschema', 'bah', ARRAY['integer', 'text'], 'boolean', 'whatever' ), true, 'function_returns(schema, func, args, bool, false)', 'whatever', '' ); SELECT * FROM check_test( function_returns( 'someschema', 'bah', ARRAY['integer', 'text'], 'boolean' ), true, 'function_returns(schema, func, args, bool)', 'Function someschema.bah(integer, text) should return boolean', '' ); SELECT * FROM check_test( function_returns( 'public', 'pet', '{}'::name[], 'setof boolean', 'whatever' ), true, 'function_returns(schema, func, 0 args, setof bool, desc)', 'whatever', '' ); SELECT * FROM check_test( function_returns( 'public', 'pet', '{}'::name[], 'setof boolean' ), true, 'function_returns(schema, func, 0 args, setof bool)', 'Function public.pet() should return setof boolean', '' ); SELECT * FROM check_test( function_returns( 'someschema', 'huh', 'boolean', 'whatever' ), true, 'function_returns(schema, func, bool, desc)', 'whatever', '' ); SELECT * FROM check_test( function_returns( 'someschema', 'huh'::name, 'boolean' ), true, 'function_returns(schema, func, bool)', 'Function someschema.huh() should return boolean', '' ); SELECT * FROM check_test( function_returns( 'someschema', 'bah', 'boolean', 'whatever' ), true, 'function_returns(schema, other func, bool, false)', 'whatever', '' ); SELECT * FROM check_test( function_returns( 'someschema', 'bah'::name, 'boolean' ), true, 'function_returns(schema, other func, bool)', 'Function someschema.bah() should return boolean', '' ); SELECT * FROM check_test( function_returns( 'public', 'pet', 'setof boolean', 'whatever' ), true, 'function_returns(schema, func, setof bool, desc)', 'whatever', '' ); SELECT * FROM check_test( function_returns( 'public', 'pet'::name, 'setof boolean' ), true, 'function_returns(schema, func, setof bool)', 'Function public.pet() should return setof boolean', '' ); SELECT * FROM check_test( function_returns( 'yay', '{}'::name[], 'boolean', 'whatever' ), true, 'function_returns(func, 0 args, bool, desc)', 'whatever', '' ); SELECT * FROM check_test( function_returns( 'yay', '{}'::name[], 'boolean' ), true, 'function_returns(func, 0 args, bool)', 'Function yay() should return boolean', '' ); SELECT * FROM check_test( function_returns( 'oww', ARRAY['integer', 'text'], 'boolean', 'whatever' ), true, 'function_returns(func, args, bool, false)', 'whatever', '' ); SELECT * FROM check_test( function_returns( 'oww', ARRAY['integer', 'text'], 'boolean' ), true, 'function_returns(func, args, bool)', 'Function oww(integer, text) should return boolean', '' ); SELECT * FROM check_test( function_returns( 'pet', '{}'::name[], 'setof boolean', 'whatever' ), true, 'function_returns(func, 0 args, setof bool, desc)', 'whatever', '' ); SELECT * FROM check_test( function_returns( 'pet', '{}'::name[], 'setof boolean' ), true, 'function_returns(func, 0 args, setof bool)', 'Function pet() should return setof boolean', '' ); SELECT * FROM check_test( function_returns( 'yay', 'boolean', 'whatever' ), true, 'function_returns(func, bool, desc)', 'whatever', '' ); SELECT * FROM check_test( function_returns( 'yay', 'boolean' ), true, 'function_returns(func, bool)', 'Function yay() should return boolean', '' ); SELECT * FROM check_test( function_returns( 'oww', 'boolean', 'whatever' ), true, 'function_returns(other func, bool, false)', 'whatever', '' ); SELECT * FROM check_test( function_returns( 'oww', 'boolean' ), true, 'function_returns(other func, bool)', 'Function oww() should return boolean', '' ); SELECT * FROM check_test( function_returns( 'pet', 'setof boolean', 'whatever' ), true, 'function_returns(func, setof bool, desc)', 'whatever', '' ); SELECT * FROM check_test( function_returns( 'pet', 'setof boolean' ), true, 'function_returns(func, setof bool)', 'Function pet() should return setof boolean', '' ); /****************************************************************************/ -- Test is_definer(). SELECT * FROM check_test( is_definer( 'public', 'yay', '{}'::name[], 'whatever' ), true, 'is_definer(schema, func, 0 args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_definer( 'public', 'yay', '{}'::name[] ), true, 'is_definer(schema, func, 0 args)', 'Function public.yay() should be security definer', '' ); SELECT * FROM check_test( is_definer( 'public', 'oww', ARRAY['integer', 'text'], 'whatever' ), false, 'is_definer(schema, func, args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_definer( 'public', 'oww', ARRAY['integer', 'text'] ), false, 'is_definer(schema, func, args)', 'Function public.oww(integer, text) should be security definer', '' ); SELECT * FROM check_test( is_definer( 'public', 'yay', 'whatever' ), true, 'is_definer(schema, func, desc)', 'whatever', '' ); SELECT * FROM check_test( is_definer( 'public', 'yay'::name ), true, 'is_definer(schema, func)', 'Function public.yay() should be security definer', '' ); SELECT * FROM check_test( is_definer( 'public', 'yay', '{}'::name[], 'whatever' ), true, 'is_definer(schema, func, 0 args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_definer( 'public', 'yay', '{}'::name[] ), true, 'is_definer(schema, func, 0 args)', 'Function public.yay() should be security definer', '' ); SELECT * FROM check_test( is_definer( 'public', 'oww', ARRAY['integer', 'text'], 'whatever' ), false, 'is_definer(schema, func, args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_definer( 'public', 'oww', ARRAY['integer', 'text'] ), false, 'is_definer(schema, func, args)', 'Function public.oww(integer, text) should be security definer', '' ); SELECT * FROM check_test( is_definer( 'public', 'yay', 'whatever' ), true, 'is_definer(schema, func, desc)', 'whatever', '' ); SELECT * FROM check_test( is_definer( 'public', 'yay'::name ), true, 'is_definer(schema, func)', 'Function public.yay() should be security definer', '' ); SELECT * FROM check_test( is_definer( 'yay', '{}'::name[], 'whatever' ), true, 'is_definer(func, 0 args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_definer( 'yay', '{}'::name[] ), true, 'is_definer(func, 0 args)', 'Function yay() should be security definer', '' ); SELECT * FROM check_test( is_definer( 'oww', ARRAY['integer', 'text'], 'whatever' ), false, 'is_definer(func, args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_definer( 'oww', ARRAY['integer', 'text'] ), false, 'is_definer(func, args)', 'Function oww(integer, text) should be security definer', '' ); SELECT * FROM check_test( is_definer( 'yay', 'whatever' ), true, 'is_definer(func, desc)', 'whatever', '' ); SELECT * FROM check_test( is_definer( 'yay'::name ), true, 'is_definer(func)', 'Function yay() should be security definer', '' ); /****************************************************************************/ -- Test is_aggregate(). SELECT * FROM check_test( is_aggregate( 'public', 'tap_accum', ARRAY['anyelement'], 'whatever' ), true, 'is_aggregate(schema, func, arg, desc)', 'whatever', '' ); SELECT * FROM check_test( is_aggregate( 'public', 'tap_accum', ARRAY['anyelement'] ), true, 'is_aggregate(schema, func, arg)', 'Function public.tap_accum(anyelement) should be an aggregate function', '' ); SELECT * FROM check_test( is_aggregate( 'public', 'oww', ARRAY['integer', 'text'], 'whatever' ), false, 'is_aggregate(schema, func, args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_aggregate( 'public', 'oww', ARRAY['integer', 'text'] ), false, 'is_aggregate(schema, func, args)', 'Function public.oww(integer, text) should be an aggregate function', '' ); SELECT * FROM check_test( is_aggregate( 'public', 'tap_accum', 'whatever' ), true, 'is_aggregate(schema, func, desc)', 'whatever', '' ); SELECT * FROM check_test( is_aggregate( 'public', 'tap_accum'::name ), true, 'is_aggregate(schema, func)', 'Function public.tap_accum() should be an aggregate function', '' ); SELECT * FROM check_test( is_aggregate( 'public', 'tap_accum', ARRAY['anyelement'], 'whatever' ), true, 'is_aggregate(schema, func, arg, desc)', 'whatever', '' ); SELECT * FROM check_test( is_aggregate( 'public', 'tap_accum', ARRAY['anyelement'] ), true, 'is_aggregate(schema, func, arg)', 'Function public.tap_accum(anyelement) should be an aggregate function', '' ); SELECT * FROM check_test( is_aggregate( 'public', 'oww', ARRAY['integer', 'text'], 'whatever' ), false, 'is_aggregate(schema, func, args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_aggregate( 'public', 'oww', ARRAY['integer', 'text'] ), false, 'is_aggregate(schema, func, args)', 'Function public.oww(integer, text) should be an aggregate function', '' ); SELECT * FROM check_test( is_aggregate( 'public', 'tap_accum', 'whatever' ), true, 'is_aggregate(schema, func, desc)', 'whatever', '' ); SELECT * FROM check_test( is_aggregate( 'public', 'tap_accum'::name ), true, 'is_aggregate(schema, func)', 'Function public.tap_accum() should be an aggregate function', '' ); SELECT * FROM check_test( is_aggregate( 'tap_accum', ARRAY['anyelement'], 'whatever' ), true, 'is_aggregate(func, arg, desc)', 'whatever', '' ); SELECT * FROM check_test( is_aggregate( 'tap_accum', ARRAY['anyelement'] ), true, 'is_aggregate(func, arg)', 'Function tap_accum(anyelement) should be an aggregate function', '' ); SELECT * FROM check_test( is_aggregate( 'oww', ARRAY['integer', 'text'], 'whatever' ), false, 'is_aggregate(func, args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_aggregate( 'oww', ARRAY['integer', 'text'] ), false, 'is_aggregate(func, args)', 'Function oww(integer, text) should be an aggregate function', '' ); SELECT * FROM check_test( is_aggregate( 'tap_accum', 'whatever' ), true, 'is_aggregate(func, desc)', 'whatever', '' ); SELECT * FROM check_test( is_aggregate( 'tap_accum'::name ), true, 'is_aggregate(func)', 'Function tap_accum() should be an aggregate function', '' ); /****************************************************************************/ -- Test is_strict(). SELECT * FROM check_test( is_strict( 'public', 'yay', '{}'::name[], 'whatever' ), true, 'is_strict(schema, func, 0 args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_strict( 'public', 'yay', '{}'::name[] ), true, 'is_strict(schema, func, 0 args)', 'Function public.yay() should be strict', '' ); SELECT * FROM check_test( is_strict( 'public', 'oww', ARRAY['integer', 'text'], 'whatever' ), false, 'is_strict(schema, func, args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_strict( 'public', 'oww', ARRAY['integer', 'text'] ), false, 'is_strict(schema, func, args)', 'Function public.oww(integer, text) should be strict', '' ); SELECT * FROM check_test( is_strict( 'public', 'yay', 'whatever' ), true, 'is_strict(schema, func, desc)', 'whatever', '' ); SELECT * FROM check_test( is_strict( 'public', 'yay'::name ), true, 'is_strict(schema, func)', 'Function public.yay() should be strict', '' ); SELECT * FROM check_test( is_strict( 'public', 'yay', '{}'::name[], 'whatever' ), true, 'is_strict(schema, func, 0 args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_strict( 'public', 'yay', '{}'::name[] ), true, 'is_strict(schema, func, 0 args)', 'Function public.yay() should be strict', '' ); SELECT * FROM check_test( is_strict( 'public', 'oww', ARRAY['integer', 'text'], 'whatever' ), false, 'is_strict(schema, func, args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_strict( 'public', 'oww', ARRAY['integer', 'text'] ), false, 'is_strict(schema, func, args)', 'Function public.oww(integer, text) should be strict', '' ); SELECT * FROM check_test( is_strict( 'public', 'yay', 'whatever' ), true, 'is_strict(schema, func, desc)', 'whatever', '' ); SELECT * FROM check_test( is_strict( 'public', 'yay'::name ), true, 'is_strict(schema, func)', 'Function public.yay() should be strict', '' ); SELECT * FROM check_test( is_strict( 'yay', '{}'::name[], 'whatever' ), true, 'is_strict(func, 0 args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_strict( 'yay', '{}'::name[] ), true, 'is_strict(func, 0 args)', 'Function yay() should be strict', '' ); SELECT * FROM check_test( is_strict( 'oww', ARRAY['integer', 'text'], 'whatever' ), false, 'is_strict(func, args, desc)', 'whatever', '' ); SELECT * FROM check_test( is_strict( 'oww', ARRAY['integer', 'text'] ), false, 'is_strict(func, args)', 'Function oww(integer, text) should be strict', '' ); SELECT * FROM check_test( is_strict( 'yay', 'whatever' ), true, 'is_strict(func, desc)', 'whatever', '' ); SELECT * FROM check_test( is_strict( 'yay'::name ), true, 'is_strict(func)', 'Function yay() should be strict', '' ); /****************************************************************************/ -- Test volatility_is(). SELECT * FROM check_test( volatility_is( 'public', 'yay', '{}'::name[], 'volatile', 'whatever' ), true, 'function_volatility(schema, func, 0 args, volatile, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'public', 'yay', '{}'::name[], 'VOLATILE', 'whatever' ), true, 'function_volatility(schema, func, 0 args, VOLATILE, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'public', 'yay', '{}'::name[], 'v', 'whatever' ), true, 'function_volatility(schema, func, 0 args, v, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'public', 'oww', ARRAY['integer', 'text'], 'immutable', 'whatever' ), true, 'function_volatility(schema, func, args, immutable, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'public', 'pet', '{}'::name[], 'stable', 'whatever' ), true, 'function_volatility(schema, func, 0 args, stable, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'public', 'yay', '{}'::name[], 'volatile' ), true, 'function_volatility(schema, func, 0 args, volatile)', 'Function public.yay() should be VOLATILE', '' ); SELECT * FROM check_test( volatility_is( 'public', 'oww', ARRAY['integer', 'text'], 'immutable' ), true, 'function_volatility(schema, func, args, immutable)', 'Function public.oww(integer, text) should be IMMUTABLE' '' ); SELECT * FROM check_test( volatility_is( 'public', 'yay', 'volatile', 'whatever' ), true, 'function_volatility(schema, func, volatile, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'public', 'yay'::name, 'volatile' ), true, 'function_volatility(schema, func, volatile)', 'Function public.yay() should be VOLATILE', '' ); SELECT * FROM check_test( volatility_is( 'public', 'oww', 'immutable', 'whatever' ), true, 'function_volatility(schema, func, immutable, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'public', 'pet', 'stable', 'whatever' ), true, 'function_volatility(schema, func, stable, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'yay', '{}'::name[], 'volatile', 'whatever' ), true, 'function_volatility(func, 0 args, volatile, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'yay', '{}'::name[], 'VOLATILE', 'whatever' ), true, 'function_volatility(func, 0 args, VOLATILE, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'yay', '{}'::name[], 'v', 'whatever' ), true, 'function_volatility(func, 0 args, v, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'oww', ARRAY['integer', 'text'], 'immutable', 'whatever' ), true, 'function_volatility(func, args, immutable, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'pet', '{}'::name[], 'stable', 'whatever' ), true, 'function_volatility(func, 0 args, stable, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'yay', '{}'::name[], 'volatile' ), true, 'function_volatility(func, 0 args, volatile)', 'Function yay() should be VOLATILE', '' ); SELECT * FROM check_test( volatility_is( 'oww', ARRAY['integer', 'text'], 'immutable' ), true, 'function_volatility(func, args, immutable)', 'Function oww(integer, text) should be IMMUTABLE' '' ); SELECT * FROM check_test( volatility_is( 'yay', 'volatile', 'whatever' ), true, 'function_volatility(func, volatile, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'yay'::name, 'volatile' ), true, 'function_volatility(func, volatile)', 'Function yay() should be VOLATILE', '' ); SELECT * FROM check_test( volatility_is( 'oww', 'immutable', 'whatever' ), true, 'function_volatility(func, immutable, desc)', 'whatever', '' ); SELECT * FROM check_test( volatility_is( 'pet', 'stable', 'whatever' ), true, 'function_volatility(func, stable, desc)', 'whatever', '' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._hastap.sql000644 000765 000024 00000000252 11666501762 017152 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/hastap.sql000644 000765 000024 00000123000 11666501762 016732 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(678); --SELECT * FROM no_plan(); -- This will be rolled back. :-) SET client_min_messages = warning; CREATE TABLE public.sometab( id INT NOT NULL PRIMARY KEY, name TEXT DEFAULT '', numb NUMERIC(10, 2), "myInt" NUMERIC(8) ); CREATE TYPE public.sometype AS ( id INT, name TEXT ); CREATE TYPE public."myType" AS ( id INT, foo INT ); CREATE DOMAIN public.us_postal_code AS TEXT CHECK( VALUE ~ '^[[:digit:]]{5}$' OR VALUE ~ '^[[:digit:]]{5}-[[:digit:]]{4}$' ); CREATE DOMAIN public."myDomain" AS TEXT CHECK(TRUE); CREATE SEQUENCE public.someseq; CREATE SCHEMA someschema; RESET client_min_messages; /****************************************************************************/ -- Test has_tablespace(). Can't really test with the location argument, though. SELECT * FROM check_test( has_tablespace( '__SDFSDFD__' ), false, 'has_tablespace(non-existent tablespace)', 'Tablespace "__SDFSDFD__" should exist', '' ); SELECT * FROM check_test( has_tablespace( '__SDFSDFD__', 'lol' ), false, 'has_tablespace(non-existent tablespace, tab)', 'lol', '' ); SELECT * FROM check_test( has_tablespace( 'pg_default' ), true, 'has_tablespace(tablespace)', 'Tablespace pg_default should exist', '' ); SELECT * FROM check_test( has_tablespace( 'pg_default', 'lol' ), true, 'has_tablespace(tablespace, desc)', 'lol', '' ); /****************************************************************************/ -- Test hasnt_tablespace(). SELECT * FROM check_test( hasnt_tablespace( '__SDFSDFD__' ), true, 'hasnt_tablespace(non-existent tablespace)', 'Tablespace "__SDFSDFD__" should not exist', '' ); SELECT * FROM check_test( hasnt_tablespace( '__SDFSDFD__', 'lol' ), true, 'hasnt_tablespace(non-existent tablespace, tab)', 'lol', '' ); SELECT * FROM check_test( hasnt_tablespace( 'pg_default' ), false, 'hasnt_tablespace(pg_default)', 'Tablespace pg_default should not exist', '' ); SELECT * FROM check_test( hasnt_tablespace( 'pg_default', 'lol' ), false, 'hasnt_tablespace(tablespace, desc)', 'lol', '' ); /****************************************************************************/ -- Test has_schema(). SELECT * FROM check_test( has_schema( '__SDFSDFD__' ), false, 'has_schema(non-existent schema)', 'Schema "__SDFSDFD__" should exist', '' ); SELECT * FROM check_test( has_schema( '__SDFSDFD__', 'lol' ), false, 'has_schema(non-existent schema, tab)', 'lol', '' ); SELECT * FROM check_test( has_schema( 'someschema' ), true, 'has_schema(schema)', 'Schema someschema should exist', '' ); SELECT * FROM check_test( has_schema( 'someschema', 'lol' ), true, 'has_schema(schema, desc)', 'lol', '' ); /****************************************************************************/ -- Test hasnt_schema(). SELECT * FROM check_test( hasnt_schema( '__SDFSDFD__' ), true, 'hasnt_schema(non-existent schema)', 'Schema "__SDFSDFD__" should not exist', '' ); SELECT * FROM check_test( hasnt_schema( '__SDFSDFD__', 'lol' ), true, 'hasnt_schema(non-existent schema, tab)', 'lol', '' ); SELECT * FROM check_test( hasnt_schema( 'someschema' ), false, 'hasnt_schema(schema)', 'Schema someschema should not exist', '' ); SELECT * FROM check_test( hasnt_schema( 'someschema', 'lol' ), false, 'hasnt_schema(schema, desc)', 'lol', '' ); /****************************************************************************/ -- Test has_table(). SELECT * FROM check_test( has_table( '__SDFSDFD__' ), false, 'has_table(non-existent table)', 'Table "__SDFSDFD__" should exist', '' ); SELECT * FROM check_test( has_table( '__SDFSDFD__', 'lol' ), false, 'has_table(non-existent schema, tab)', 'lol', '' ); SELECT * FROM check_test( has_table( 'foo', '__SDFSDFD__', 'desc' ), false, 'has_table(sch, non-existent table, desc)', 'desc', '' ); SELECT * FROM check_test( has_table( 'pg_type', 'lol' ), true, 'has_table(tab, desc)', 'lol', '' ); SELECT * FROM check_test( has_table( 'pg_catalog', 'pg_type', 'desc' ), true, 'has_table(sch, tab, desc)', 'desc', '' ); -- It should ignore views and types. SELECT * FROM check_test( has_table( 'pg_catalog', 'pg_tables', 'desc' ), false, 'has_table(sch, view, desc)', 'desc', '' ); SELECT * FROM check_test( has_table( 'sometype', 'desc' ), false, 'has_table(type, desc)', 'desc', '' ); /****************************************************************************/ -- Test hasnt_table(). SELECT * FROM check_test( hasnt_table( '__SDFSDFD__' ), true, 'hasnt_table(non-existent table)', 'Table "__SDFSDFD__" should not exist', '' ); SELECT * FROM check_test( hasnt_table( '__SDFSDFD__', 'lol' ), true, 'hasnt_table(non-existent schema, tab)', 'lol', '' ); SELECT * FROM check_test( hasnt_table( 'foo', '__SDFSDFD__', 'desc' ), true, 'hasnt_table(sch, non-existent tab, desc)', 'desc', '' ); SELECT * FROM check_test( hasnt_table( 'pg_type', 'lol' ), false, 'hasnt_table(tab, desc)', 'lol', '' ); SELECT * FROM check_test( hasnt_table( 'pg_catalog', 'pg_type', 'desc' ), false, 'hasnt_table(sch, tab, desc)', 'desc', '' ); /****************************************************************************/ -- Test has_view(). SELECT * FROM check_test( has_view( '__SDFSDFD__' ), false, 'has_view(non-existent view)', 'View "__SDFSDFD__" should exist', '' ); SELECT * FROM check_test( has_view( '__SDFSDFD__', 'howdy' ), false, 'has_view(non-existent view, desc)', 'howdy', '' ); SELECT * FROM check_test( has_view( 'foo', '__SDFSDFD__', 'desc' ), false, 'has_view(sch, non-existtent view, desc)', 'desc', '' ); SELECT * FROM check_test( has_view( 'pg_tables', 'yowza' ), true, 'has_view(view, desc)', 'yowza', '' ); SELECT * FROM check_test( has_view( 'information_schema', 'tables', 'desc' ), true, 'has_view(sch, view, desc)', 'desc', '' ); /****************************************************************************/ -- Test hasnt_view(). SELECT * FROM check_test( hasnt_view( '__SDFSDFD__' ), true, 'hasnt_view(non-existent view)', 'View "__SDFSDFD__" should not exist', '' ); SELECT * FROM check_test( hasnt_view( '__SDFSDFD__', 'howdy' ), true, 'hasnt_view(non-existent view, desc)', 'howdy', '' ); SELECT * FROM check_test( hasnt_view( 'foo', '__SDFSDFD__', 'desc' ), true, 'hasnt_view(sch, non-existtent view, desc)', 'desc', '' ); SELECT * FROM check_test( hasnt_view( 'pg_tables', 'yowza' ), false, 'hasnt_view(view, desc)', 'yowza', '' ); SELECT * FROM check_test( hasnt_view( 'information_schema', 'tables', 'desc' ), false, 'hasnt_view(sch, view, desc)', 'desc', '' ); /****************************************************************************/ -- Test has_sequence(). SELECT * FROM check_test( has_sequence( '__SDFSDFD__' ), false, 'has_sequence(non-existent sequence)', 'Sequence "__SDFSDFD__" should exist', '' ); SELECT * FROM check_test( has_sequence( '__SDFSDFD__', 'howdy' ), false, 'has_sequence(non-existent sequence, desc)', 'howdy', '' ); SELECT * FROM check_test( has_sequence( 'foo', '__SDFSDFD__', 'desc' ), false, 'has_sequence(sch, non-existtent sequence, desc)', 'desc', '' ); SELECT * FROM check_test( has_sequence( 'someseq', 'yowza' ), true, 'has_sequence(sequence, desc)', 'yowza', '' ); SELECT * FROM check_test( has_sequence( 'public', 'someseq', 'desc' ), true, 'has_sequence(sch, sequence, desc)', 'desc', '' ); /****************************************************************************/ -- Test hasnt_sequence(). SELECT * FROM check_test( hasnt_sequence( '__SDFSDFD__' ), true, 'hasnt_sequence(non-existent sequence)', 'Sequence "__SDFSDFD__" should not exist', '' ); SELECT * FROM check_test( hasnt_sequence( '__SDFSDFD__', 'howdy' ), true, 'hasnt_sequence(non-existent sequence, desc)', 'howdy', '' ); SELECT * FROM check_test( hasnt_sequence( 'foo', '__SDFSDFD__', 'desc' ), true, 'hasnt_sequence(sch, non-existtent sequence, desc)', 'desc', '' ); SELECT * FROM check_test( hasnt_sequence( 'someseq', 'yowza' ), false, 'hasnt_sequence(sequence, desc)', 'yowza', '' ); SELECT * FROM check_test( hasnt_sequence( 'public', 'someseq', 'desc' ), false, 'hasnt_sequence(sch, sequence, desc)', 'desc', '' ); /****************************************************************************/ -- Test has_type(). SELECT * FROM check_test( has_type( 'sometype' ), true, 'has_type(type)', 'Type sometype should exist', '' ); SELECT * FROM check_test( has_type( 'sometype', 'mydesc' ), true, 'has_type(type, desc)', 'mydesc', '' ); SELECT * FROM check_test( has_type( 'public'::name, 'sometype'::name ), true, 'has_type(scheam, type)', 'Type public.sometype should exist', '' ); SELECT * FROM check_test( has_type( 'public', 'sometype', 'mydesc' ), true, 'has_type(schema, type, desc)', 'mydesc', '' ); -- Try case-sensitive. SELECT * FROM check_test( has_type( 'myType' ), true, 'has_type(myType)', 'Type "myType" should exist', '' ); SELECT * FROM check_test( has_type( 'myType', 'mydesc' ), true, 'has_type(myType, desc)', 'mydesc', '' ); SELECT * FROM check_test( has_type( 'public'::name, 'myType'::name ), true, 'has_type(scheam, myType)', 'Type public."myType" should exist', '' ); SELECT * FROM check_test( has_type( 'public', 'myType', 'mydesc' ), true, 'has_type(schema, myType, desc)', 'mydesc', '' ); -- Try failures. SELECT * FROM check_test( has_type( '__foobarbaz__' ), false, 'has_type(type)', 'Type __foobarbaz__ should exist', '' ); SELECT * FROM check_test( has_type( '__foobarbaz__', 'mydesc' ), false, 'has_type(type, desc)', 'mydesc', '' ); SELECT * FROM check_test( has_type( 'public'::name, '__foobarbaz__'::name ), false, 'has_type(scheam, type)', 'Type public.__foobarbaz__ should exist', '' ); SELECT * FROM check_test( has_type( 'public', '__foobarbaz__', 'mydesc' ), false, 'has_type(schema, type, desc)', 'mydesc', '' ); -- Make sure it works for domains. SELECT * FROM check_test( has_type( 'us_postal_code' ), true, 'has_type(domain)', 'Type us_postal_code should exist', '' ); SELECT * FROM check_test( has_type( 'myDomain' ), true, 'has_type(myDomain)', 'Type "myDomain" should exist', '' ); /****************************************************************************/ -- Test hasnt_type(). SELECT * FROM check_test( hasnt_type( '__foobarbaz__' ), true, 'hasnt_type(type)', 'Type __foobarbaz__ should not exist', '' ); SELECT * FROM check_test( hasnt_type( '__foobarbaz__', 'mydesc' ), true, 'hasnt_type(type, desc)', 'mydesc', '' ); SELECT * FROM check_test( hasnt_type( 'public'::name, '__foobarbaz__'::name ), true, 'hasnt_type(scheam, type)', 'Type public.__foobarbaz__ should not exist', '' ); SELECT * FROM check_test( hasnt_type( 'public', '__foobarbaz__', 'mydesc' ), true, 'hasnt_type(schema, type, desc)', 'mydesc', '' ); -- Try failures. SELECT * FROM check_test( hasnt_type( 'sometype' ), false, 'hasnt_type(type)', 'Type sometype should not exist', '' ); SELECT * FROM check_test( hasnt_type( 'sometype', 'mydesc' ), false, 'hasnt_type(type, desc)', 'mydesc', '' ); SELECT * FROM check_test( hasnt_type( 'public'::name, 'sometype'::name ), false, 'hasnt_type(scheam, type)', 'Type public.sometype should not exist', '' ); SELECT * FROM check_test( hasnt_type( 'public', 'sometype', 'mydesc' ), false, 'hasnt_type(schema, type, desc)', 'mydesc', '' ); /****************************************************************************/ -- Test has_domain(). SELECT * FROM check_test( has_domain( 'us_postal_code' ), true, 'has_domain(domain)', 'Domain us_postal_code should exist', '' ); SELECT * FROM check_test( has_domain( 'us_postal_code', 'mydesc' ), true, 'has_domain(domain, desc)', 'mydesc', '' ); SELECT * FROM check_test( has_domain( 'public'::name, 'us_postal_code'::name ), true, 'has_domain(scheam, domain)', 'Domain public.us_postal_code should exist', '' ); SELECT * FROM check_test( has_domain( 'public', 'us_postal_code', 'mydesc' ), true, 'has_domain(schema, domain, desc)', 'mydesc', '' ); -- Try case-sensitive. SELECT * FROM check_test( has_domain( 'myDomain' ), true, 'has_domain(myDomain)', 'Domain "myDomain" should exist', '' ); SELECT * FROM check_test( has_domain( 'myDomain', 'mydesc' ), true, 'has_domain(myDomain, desc)', 'mydesc', '' ); SELECT * FROM check_test( has_domain( 'public'::name, 'myDomain'::name ), true, 'has_domain(scheam, myDomain)', 'Domain public."myDomain" should exist', '' ); SELECT * FROM check_test( has_domain( 'public', 'myDomain', 'mydesc' ), true, 'has_domain(schema, myDomain, desc)', 'mydesc', '' ); -- Try failures. SELECT * FROM check_test( has_domain( '__foobarbaz__' ), false, 'has_domain(domain)', 'Domain __foobarbaz__ should exist', '' ); SELECT * FROM check_test( has_domain( '__foobarbaz__', 'mydesc' ), false, 'has_domain(domain, desc)', 'mydesc', '' ); SELECT * FROM check_test( has_domain( 'public'::name, '__foobarbaz__'::name ), false, 'has_domain(scheam, domain)', 'Domain public.__foobarbaz__ should exist', '' ); SELECT * FROM check_test( has_domain( 'public', '__foobarbaz__', 'mydesc' ), false, 'has_domain(schema, domain, desc)', 'mydesc', '' ); /****************************************************************************/ -- Test hasnt_domain(). SELECT * FROM check_test( hasnt_domain( '__foobarbaz__' ), true, 'hasnt_domain(domain)', 'Domain __foobarbaz__ should not exist', '' ); SELECT * FROM check_test( hasnt_domain( '__foobarbaz__', 'mydesc' ), true, 'hasnt_domain(domain, desc)', 'mydesc', '' ); SELECT * FROM check_test( hasnt_domain( 'public'::name, '__foobarbaz__'::name ), true, 'hasnt_domain(scheam, domain)', 'Domain public.__foobarbaz__ should not exist', '' ); SELECT * FROM check_test( hasnt_domain( 'public', '__foobarbaz__', 'mydesc' ), true, 'hasnt_domain(schema, domain, desc)', 'mydesc', '' ); -- Try failures. SELECT * FROM check_test( hasnt_domain( 'us_postal_code' ), false, 'hasnt_domain(domain)', 'Domain us_postal_code should not exist', '' ); SELECT * FROM check_test( hasnt_domain( 'us_postal_code', 'mydesc' ), false, 'hasnt_domain(domain, desc)', 'mydesc', '' ); SELECT * FROM check_test( hasnt_domain( 'public'::name, 'us_postal_code'::name ), false, 'hasnt_domain(scheam, domain)', 'Domain public.us_postal_code should not exist', '' ); SELECT * FROM check_test( hasnt_domain( 'public', 'us_postal_code', 'mydesc' ), false, 'hasnt_domain(schema, domain, desc)', 'mydesc', '' ); /****************************************************************************/ -- Test has_column(). SELECT * FROM check_test( has_column( '__SDFSDFD__', 'foo' ), false, 'has_column(non-existent tab, col)', 'Column "__SDFSDFD__".foo should exist', '' ); SELECT * FROM check_test( has_column( '__SDFSDFD__', 'bar', 'whatever' ), false, 'has_column(non-existent tab, col, desc)', 'whatever', '' ); SELECT * FROM check_test( has_column( 'foo', '__SDFSDFD__', 'bar', 'desc' ), false, 'has_column(non-existent sch, tab, col, desc)', 'desc', '' ); SELECT * FROM check_test( has_column( 'sometab', 'id' ), true, 'has_column(table, column)', 'Column sometab.id should exist', '' ); SELECT * FROM check_test( has_column( 'information_schema', 'tables', 'table_name', 'desc' ), true, 'has_column(sch, tab, col, desc)', 'desc', '' ); SELECT * FROM check_test( has_column( 'sometab', 'myInt' ), true, 'has_column(table, camleCase column)', 'Column sometab."myInt" should exist', '' ); -- Make sure it works with views. SELECT * FROM check_test( has_column( 'pg_tables', 'schemaname' ), true, 'has_column(view, column)', 'Column pg_tables.schemaname should exist', '' ); -- Make sure it works with composite types. SELECT * FROM check_test( has_column( 'sometype', 'name' ), true, 'has_column(type, column)', 'Column sometype.name should exist', '' ); /****************************************************************************/ -- Test hasnt_column(). SELECT * FROM check_test( hasnt_column( '__SDFSDFD__', 'foo' ), true, 'hasnt_column(non-existent tab, col)', 'Column "__SDFSDFD__".foo should not exist', '' ); SELECT * FROM check_test( hasnt_column( '__SDFSDFD__', 'bar', 'whatever' ), true, 'hasnt_column(non-existent tab, col, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_column( 'foo', '__SDFSDFD__', 'bar', 'desc' ), true, 'hasnt_column(non-existent sch, tab, col, desc)', 'desc', '' ); SELECT * FROM check_test( hasnt_column( 'sometab', 'id' ), false, 'hasnt_column(table, column)', 'Column sometab.id should not exist', '' ); SELECT * FROM check_test( hasnt_column( 'information_schema', 'tables', 'table_name', 'desc' ), false, 'hasnt_column(sch, tab, col, desc)', 'desc', '' ); -- Make sure it works with views. SELECT * FROM check_test( hasnt_column( 'pg_tables', 'whatever' ), true, 'hasnt_column(view, column)', 'Column pg_tables.whatever should not exist', '' ); -- Make sure it works with composite types. SELECT * FROM check_test( hasnt_column( 'sometype', 'foobar' ), true, 'hasnt_column(type, column)', 'Column sometype.foobar should not exist', '' ); /****************************************************************************/ -- Test has_cast(). SELECT * FROM check_test( has_cast( 'integer', 'bigint', 'pg_catalog', 'int8', 'desc' ), true, 'has_cast( src, targ, schema, func, desc)', 'desc', '' ); SELECT * FROM check_test( has_cast( 'integer', 'bigint', 'pg_catalog', 'int8'::name), true, 'has_cast( src, targ, schema, func )', 'Cast ("integer" AS "bigint") WITH FUNCTION pg_catalog.int8() should exist', '' ); SELECT * FROM check_test( has_cast( 'integer', 'bigint', 'int8', 'desc' ), true, 'has_cast( src, targ, func, desc )', 'desc', '' ); SELECT * FROM check_test( has_cast( 'integer', 'bigint', 'int8'::name), true, 'has_cast( src, targ, func)', 'Cast ("integer" AS "bigint") WITH FUNCTION int8() should exist', '' ); SELECT * FROM check_test( has_cast( 'integer', 'bigint', 'desc' ), true, 'has_cast( src, targ, desc )', 'desc', '' ); SELECT * FROM check_test( has_cast( 'integer', 'bigint' ), true, 'has_cast( src, targ )', 'Cast ("integer" AS "bigint") should exist', '' ); SELECT * FROM check_test( has_cast( 'integer', 'bigint', 'pg_catalog', 'foo', 'desc' ), false, 'has_cast( src, targ, schema, func, desc) fail', 'desc', '' ); SELECT * FROM check_test( has_cast( 'integer', 'bigint', 'foo', 'desc' ), false, 'has_cast( src, targ, func, desc ) fail', 'desc', '' ); SELECT * FROM check_test( has_cast( 'integer', 'clue', 'desc' ), false, 'has_cast( src, targ, desc ) fail', 'desc', '' ); /****************************************************************************/ -- Test hasnt_cast(). SELECT * FROM check_test( hasnt_cast( 'integer', 'bigint', 'pg_catalog', 'int8', 'desc' ), false, 'hasnt_cast( src, targ, schema, func, desc)', 'desc', '' ); SELECT * FROM check_test( hasnt_cast( 'integer', 'bigint', 'pg_catalog', 'int8'::name), false, 'hasnt_cast( src, targ, schema, func )', 'Cast ("integer" AS "bigint") WITH FUNCTION pg_catalog.int8() should not exist', '' ); SELECT * FROM check_test( hasnt_cast( 'integer', 'bigint', 'int8', 'desc' ), false, 'hasnt_cast( src, targ, func, desc )', 'desc', '' ); SELECT * FROM check_test( hasnt_cast( 'integer', 'bigint', 'int8'::name), false, 'hasnt_cast( src, targ, func)', 'Cast ("integer" AS "bigint") WITH FUNCTION int8() should not exist', '' ); SELECT * FROM check_test( hasnt_cast( 'integer', 'bigint', 'desc' ), false, 'hasnt_cast( src, targ, desc )', 'desc', '' ); SELECT * FROM check_test( hasnt_cast( 'integer', 'bigint' ), false, 'hasnt_cast( src, targ )', 'Cast ("integer" AS "bigint") should not exist', '' ); SELECT * FROM check_test( hasnt_cast( 'integer', 'bigint', 'pg_catalog', 'foo', 'desc' ), true, 'hasnt_cast( src, targ, schema, func, desc) fail', 'desc', '' ); SELECT * FROM check_test( hasnt_cast( 'integer', 'bigint', 'foo', 'desc' ), true, 'hasnt_cast( src, targ, func, desc ) fail', 'desc', '' ); SELECT * FROM check_test( hasnt_cast( 'integer', 'clue', 'desc' ), true, 'hasnt_cast( src, targ, desc ) fail', 'desc', '' ); /****************************************************************************/ -- Test cast_has_context(). SELECT * FROM check_test( cast_context_is( 'integer', 'bigint', 'implicit', 'desc' ), true, 'cast_context_is( src, targ, context, desc )', 'desc', '' ); SELECT * FROM check_test( cast_context_is( 'integer', 'bigint', 'implicit' ), true, 'cast_context_is( src, targ, context )', 'Cast ("integer" AS "bigint") context should be implicit', '' ); SELECT * FROM check_test( cast_context_is( 'integer', 'bigint', 'i', 'desc' ), true, 'cast_context_is( src, targ, i, desc )', 'desc', '' ); SELECT * FROM check_test( cast_context_is( 'integer', 'bigint', 'IMPL', 'desc' ), true, 'cast_context_is( src, targ, IMPL, desc )', 'desc', '' ); SELECT * FROM check_test( cast_context_is( 'bigint', 'smallint', 'assignment', 'desc' ), true, 'cast_context_is( src, targ, assignment, desc )', 'desc', '' ); SELECT * FROM check_test( cast_context_is( 'bigint', 'smallint', 'a', 'desc' ), true, 'cast_context_is( src, targ, a, desc )', 'desc', '' ); SELECT * FROM check_test( cast_context_is( 'bigint', 'smallint', 'ASS', 'desc' ), true, 'cast_context_is( src, targ, ASS, desc )', 'desc', '' ); SELECT * FROM check_test( cast_context_is( 'bit', 'integer', 'explicit', 'desc' ), true, 'cast_context_is( src, targ, explicit, desc )', 'desc', '' ); SELECT * FROM check_test( cast_context_is( 'bit', 'integer', 'e', 'desc' ), true, 'cast_context_is( src, targ, e, desc )', 'desc', '' ); SELECT * FROM check_test( cast_context_is( 'bit', 'integer', 'EX', 'desc' ), true, 'cast_context_is( src, targ, EX, desc )', 'desc', '' ); SELECT * FROM check_test( cast_context_is( 'integer', 'bigint', 'ex', 'desc' ), false, 'cast_context_is( src, targ, context, desc ) fail', 'desc', ' have: implicit want: explicit' ); SELECT * FROM check_test( cast_context_is( 'integer', 'bigint', 'ex' ), false, 'cast_context_is( src, targ, context ) fail', 'Cast ("integer" AS "bigint") context should be explicit', ' have: implicit want: explicit' ); SELECT * FROM check_test( cast_context_is( 'integer', 'bogus', 'ex', 'desc' ), false, 'cast_context_is( src, targ, context, desc ) noexist', 'desc', ' Cast ("integer" AS bogus) does not exist' ); /****************************************************************************/ -- Test has_operator(). SELECT * FROM check_test( has_operator( 'integer', 'pg_catalog', '<=', 'integer', 'boolean', 'desc' ), true, 'has_operator( left, schema, name, right, result, desc )', 'desc', '' ); SELECT * FROM check_test( has_operator( 'integer', 'pg_catalog', '<=', 'integer', 'boolean'::name ), true, 'has_operator( left, schema, name, right, result )', 'Operator pg_catalog.<=(integer,integer) RETURNS boolean should exist', '' ); SELECT * FROM check_test( has_operator( 'integer', '<=', 'integer', 'boolean', 'desc' ), true, 'has_operator( left, name, right, result, desc )', 'desc', '' ); SELECT * FROM check_test( has_operator( 'integer', '<=', 'integer', 'boolean'::name ), true, 'has_operator( left, name, right, result )', 'Operator <=(integer,integer) RETURNS boolean should exist', '' ); SELECT * FROM check_test( has_operator( 'integer', '<=', 'integer', 'desc' ), true, 'has_operator( left, name, right, desc )', 'desc', '' ); SELECT * FROM check_test( has_operator( 'integer', '<=', 'integer'::name ), true, 'has_operator( left, name, right )', 'Operator <=(integer,integer) should exist', '' ); SELECT * FROM check_test( has_operator( 'integer', 'pg_catalog', '<=', 'text', 'boolean', 'desc' ), false, 'has_operator( left, schema, name, right, result, desc ) fail', 'desc', '' ); SELECT * FROM check_test( has_operator( 'integer', 'pg_catalog', '<=', 'text', 'boolean'::name ), false, 'has_operator( left, schema, name, right, result ) fail', 'Operator pg_catalog.<=(integer,text) RETURNS boolean should exist', '' ); SELECT * FROM check_test( has_operator( 'integer', '<=', 'text', 'boolean', 'desc' ), false, 'has_operator( left, name, right, result, desc ) fail', 'desc', '' ); SELECT * FROM check_test( has_operator( 'integer', '<=', 'text', 'boolean'::name ), false, 'has_operator( left, name, right, result ) fail', 'Operator <=(integer,text) RETURNS boolean should exist', '' ); SELECT * FROM check_test( has_operator( 'integer', '<=', 'text', 'desc' ), false, 'has_operator( left, name, right, desc ) fail', 'desc', '' ); SELECT * FROM check_test( has_operator( 'integer', '<=', 'text'::name ), false, 'has_operator( left, name, right ) fail', 'Operator <=(integer,text) should exist', '' ); /****************************************************************************/ -- Test has_leftop(). SELECT * FROM check_test( has_leftop( 'pg_catalog', '!!', 'bigint', 'numeric', 'desc' ), true, 'has_leftop( schema, name, right, result, desc )', 'desc', '' ); SELECT * FROM check_test( has_leftop( 'pg_catalog', '!!', 'bigint', 'numeric'::name ), true, 'has_leftop( schema, name, right, result )', 'Left operator pg_catalog.!!(NONE,bigint) RETURNS numeric should exist', '' ); SELECT * FROM check_test( has_leftop( '!!', 'bigint', 'numeric', 'desc' ), true, 'has_leftop( name, right, result, desc )', 'desc', '' ); SELECT * FROM check_test( has_leftop( '!!', 'bigint', 'numeric'::name ), true, 'has_leftop( name, right, result )', 'Left operator !!(NONE,bigint) RETURNS numeric should exist', '' ); SELECT * FROM check_test( has_leftop( '!!', 'bigint', 'desc' ), true, 'has_leftop( name, right, desc )', 'desc', '' ); SELECT * FROM check_test( has_leftop( '!!', 'bigint' ), true, 'has_leftop( name, right )', 'Left operator !!(NONE,bigint) should exist', '' ); SELECT * FROM check_test( has_leftop( 'pg_catalog', '!!', 'text', 'numeric', 'desc' ), false, 'has_leftop( schema, name, right, result, desc ) fail', 'desc', '' ); SELECT * FROM check_test( has_leftop( 'pg_catalog', '!!', 'text', 'numeric'::name ), false, 'has_leftop( schema, name, right, result ) fail', 'Left operator pg_catalog.!!(NONE,text) RETURNS numeric should exist', '' ); SELECT * FROM check_test( has_leftop( '!!', 'text', 'numeric', 'desc' ), false, 'has_leftop( name, right, result, desc ) fail', 'desc', '' ); SELECT * FROM check_test( has_leftop( '!!', 'text', 'numeric'::name ), false, 'has_leftop( name, right, result ) fail', 'Left operator !!(NONE,text) RETURNS numeric should exist', '' ); SELECT * FROM check_test( has_leftop( '!!', 'text', 'desc' ), false, 'has_leftop( name, right, desc ) fail', 'desc', '' ); SELECT * FROM check_test( has_leftop( '!!', 'text' ), false, 'has_leftop( name, right ) fail', 'Left operator !!(NONE,text) should exist', '' ); /****************************************************************************/ -- Test has_rightop(). SELECT * FROM check_test( has_rightop( 'bigint', 'pg_catalog', '!', 'numeric', 'desc' ), true, 'has_rightop( left, schema, name, result, desc )', 'desc', '' ); SELECT * FROM check_test( has_rightop( 'bigint', 'pg_catalog', '!', 'numeric'::name ), true, 'has_rightop( left, schema, name, result )', 'Right operator pg_catalog.!(bigint,NONE) RETURNS numeric should exist', '' ); SELECT * FROM check_test( has_rightop( 'bigint', '!', 'numeric', 'desc' ), true, 'has_rightop( left, name, result, desc )', 'desc', '' ); SELECT * FROM check_test( has_rightop( 'bigint', '!', 'numeric'::name ), true, 'has_rightop( left, name, result )', 'Right operator !(bigint,NONE) RETURNS numeric should exist', '' ); SELECT * FROM check_test( has_rightop( 'bigint', '!', 'desc' ), true, 'has_rightop( left, name, desc )', 'desc', '' ); SELECT * FROM check_test( has_rightop( 'bigint', '!' ), true, 'has_rightop( left, name )', 'Right operator !(bigint,NONE) should exist', '' ); SELECT * FROM check_test( has_rightop( 'text', 'pg_catalog', '!', 'numeric', 'desc' ), false, 'has_rightop( left, schema, name, result, desc ) fail', 'desc', '' ); SELECT * FROM check_test( has_rightop( 'text', 'pg_catalog', '!', 'numeric'::name ), false, 'has_rightop( left, schema, name, result ) fail', 'Right operator pg_catalog.!(text,NONE) RETURNS numeric should exist', '' ); SELECT * FROM check_test( has_rightop( 'text', '!', 'numeric', 'desc' ), false, 'has_rightop( left, name, result, desc ) fail', 'desc', '' ); SELECT * FROM check_test( has_rightop( 'text', '!', 'numeric'::name ), false, 'has_rightop( left, name, result ) fail', 'Right operator !(text,NONE) RETURNS numeric should exist', '' ); SELECT * FROM check_test( has_rightop( 'text', '!', 'desc' ), false, 'has_rightop( left, name, desc ) fail', 'desc', '' ); SELECT * FROM check_test( has_rightop( 'text', '!' ), false, 'has_rightop( left, name ) fail', 'Right operator !(text,NONE) should exist', '' ); /****************************************************************************/ -- Test has_language() and hasnt_language(). SELECT * FROM check_test( has_language('plpgsql'), true, 'has_language(language)', 'Procedural language ' || quote_ident('plpgsql') || ' should exist', '' ); SELECT * FROM check_test( has_language('plpgsql', 'whatever'), true, 'has_language(language, desc)', 'whatever', '' ); SELECT * FROM check_test( has_language('aoijaoisjfaoidfjaisjdfosjf'), false, 'has_language(nonexistent language)', 'Procedural language aoijaoisjfaoidfjaisjdfosjf should exist', '' ); SELECT * FROM check_test( has_language('aoijaoisjfaoidfjaisjdfosjf', 'desc'), false, 'has_language(nonexistent language, desc)', 'desc', '' ); SELECT * FROM check_test( hasnt_language('plpgsql'), false, 'hasnt_language(language)', 'Procedural language ' || quote_ident('plpgsql') || ' should not exist', '' ); SELECT * FROM check_test( hasnt_language('plpgsql', 'whatever'), false, 'hasnt_language(language, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_language('plomgwtf'), true, 'hasnt_language(nonexistent language)', 'Procedural language plomgwtf should not exist', '' ); SELECT * FROM check_test( hasnt_language('plomgwtf', 'desc'), true, 'hasnt_language(nonexistent language, desc)', 'desc', '' ); /****************************************************************************/ -- Test language_is_trusted(). SELECT * FROM check_test( language_is_trusted('sql', 'whatever'), true, 'language_is_trusted(language, desc)', 'whatever', '' ); SELECT * FROM check_test( language_is_trusted('sql'), true, 'language_is_trusted(language)', 'Procedural language sql should be trusted', '' ); SELECT * FROM check_test( language_is_trusted('c', 'whatever'), false, 'language_is_trusted(language, desc) fail', 'whatever', '' ); SELECT * FROM check_test( language_is_trusted('plomgwtf', 'whatever'), false, 'language_is_trusted(language, desc) non-existent', 'whatever', ' Procedural language plomgwtf does not exist' ); /****************************************************************************/ -- Test has_opclass() and hasnt_opclass(). SELECT * FROM check_test( has_opclass( 'pg_catalog', 'int4_ops', 'whatever' ), true, 'has_opclass( schema, name, desc )', 'whatever', '' ); SELECT * FROM check_test( has_opclass( 'pg_catalog', 'int4_ops'::name ), true, 'has_opclass( schema, name )', 'Operator class pg_catalog.int4_ops should exist', '' ); SELECT * FROM check_test( has_opclass( 'int4_ops', 'whatever' ), true, 'has_opclass( name, desc )', 'whatever', '' ); SELECT * FROM check_test( has_opclass( 'int4_ops' ), true, 'has_opclass( name )', 'Operator class int4_ops should exist', '' ); SELECT * FROM check_test( has_opclass( 'pg_catalog', 'int4_opss', 'whatever' ), false, 'has_opclass( schema, name, desc ) fail', 'whatever', '' ); SELECT * FROM check_test( has_opclass( 'int4_opss', 'whatever' ), false, 'has_opclass( name, desc ) fail', 'whatever', '' ); SELECT * FROM check_test( hasnt_opclass( 'pg_catalog', 'int4_ops', 'whatever' ), false, 'hasnt_opclass( schema, name, desc )', 'whatever', '' ); SELECT * FROM check_test( hasnt_opclass( 'pg_catalog', 'int4_ops'::name ), false, 'hasnt_opclass( schema, name )', 'Operator class pg_catalog.int4_ops should exist', '' ); SELECT * FROM check_test( hasnt_opclass( 'int4_ops', 'whatever' ), false, 'hasnt_opclass( name, desc )', 'whatever', '' ); SELECT * FROM check_test( hasnt_opclass( 'int4_ops' ), false, 'hasnt_opclass( name )', 'Operator class int4_ops should exist', '' ); SELECT * FROM check_test( hasnt_opclass( 'pg_catalog', 'int4_opss', 'whatever' ), true, 'hasnt_opclass( schema, name, desc ) fail', 'whatever', '' ); SELECT * FROM check_test( hasnt_opclass( 'int4_opss', 'whatever' ), true, 'hasnt_opclass( name, desc ) fail', 'whatever', '' ); /****************************************************************************/ -- Test domain_type_is() and domain_type_isnt(). SELECT * FROM check_test( domain_type_is( 'public', 'us_postal_code', 'public', 'text', 'whatever'), true, 'domain_type_is(schema, domain, schema, type, desc)', 'whatever', '' ); SELECT * FROM check_test( domain_type_is( 'public', 'us_postal_code', 'public'::name, 'text'), true, 'domain_type_is(schema, domain, schema, type)', 'Domain public.us_postal_code should extend type public.text', '' ); SELECT * FROM check_test( domain_type_is( 'public', 'us_postal_code', 'public', 'integer', 'whatever'), false, 'domain_type_is(schema, domain, schema, type, desc) fail', 'whatever', ' have: public.text want: public.integer' ); SELECT * FROM check_test( domain_type_is( 'public', 'zip_code', 'public', 'integer', 'whatever'), false, 'domain_type_is(schema, nondomain, schema, type, desc)', 'whatever', ' Domain public.zip_code does not exist' ); SELECT * FROM check_test( domain_type_is( 'public', 'integer', 'public', 'integer', 'whatever'), false, 'domain_type_is(schema, type, schema, type, desc) fail', 'whatever', ' Domain public.integer does not exist' ); SELECT * FROM check_test( domain_type_is( 'public', 'us_postal_code', 'text', 'whatever'), true, 'domain_type_is(schema, domain, type, desc)', 'whatever', '' ); SELECT * FROM check_test( domain_type_is( 'public'::name, 'us_postal_code', 'text'), true, 'domain_type_is(schema, domain, type)', 'Domain public.us_postal_code should extend type text', '' ); SELECT * FROM check_test( domain_type_is( 'public', 'us_postal_code', 'integer', 'whatever'), false, 'domain_type_is(schema, domain, type, desc) fail', 'whatever', ' have: text want: integer' ); SELECT * FROM check_test( domain_type_is( 'public', 'zip_code', 'integer', 'whatever'), false, 'domain_type_is(schema, nondomain, type, desc)', 'whatever', ' Domain public.zip_code does not exist' ); SELECT * FROM check_test( domain_type_is( 'public', 'integer', 'integer', 'whatever'), false, 'domain_type_is(schema, type, type, desc) fail', 'whatever', ' Domain public.integer does not exist' ); SELECT * FROM check_test( domain_type_is( 'us_postal_code', 'text', 'whatever'), true, 'domain_type_is(domain, type, desc)', 'whatever', '' ); SELECT * FROM check_test( domain_type_is( 'us_postal_code', 'text'), true, 'domain_type_is(domain, type)', 'Domain us_postal_code should extend type text', '' ); SELECT * FROM check_test( domain_type_is( 'us_postal_code', 'integer', 'whatever'), false, 'domain_type_is(domain, type, desc) fail', 'whatever', ' have: text want: integer' ); SELECT * FROM check_test( domain_type_is( 'zip_code', 'integer', 'whatever'), false, 'domain_type_is(nondomain, type, desc)', 'whatever', ' Domain zip_code does not exist' ); SELECT * FROM check_test( domain_type_is( 'integer', 'integer', 'whatever'), false, 'domain_type_is(type, type, desc) fail', 'whatever', ' Domain integer does not exist' ); SELECT * FROM check_test( domain_type_isnt( 'public', 'us_postal_code', 'public', 'integer', 'whatever'), true, 'domain_type_isnt(schema, domain, schema, type, desc)', 'whatever', '' ); SELECT * FROM check_test( domain_type_isnt( 'public', 'us_postal_code', 'public'::name, 'integer'), true, 'domain_type_isnt(schema, domain, schema, type)', 'Domain public.us_postal_code should not extend type public.integer', '' ); SELECT * FROM check_test( domain_type_isnt( 'public', 'us_postal_code', 'public', 'text', 'whatever'), false, 'domain_type_isnt(schema, domain, schema, type, desc) fail', 'whatever', ' have: public.text want: anything else' ); SELECT * FROM check_test( domain_type_isnt( 'public', 'zip_code', 'public', 'text', 'whatever'), false, 'domain_type_isnt(schema, nondomain, schema, type, desc)', 'whatever', ' Domain public.zip_code does not exist' ); SELECT * FROM check_test( domain_type_isnt( 'public', 'integer', 'public', 'text', 'whatever'), false, 'domain_type_isnt(schema, type, schema, type, desc)', 'whatever', ' Domain public.integer does not exist' ); SELECT * FROM check_test( domain_type_isnt( 'public', 'us_postal_code', 'integer', 'whatever'), true, 'domain_type_isnt(schema, domain, type, desc)', 'whatever', '' ); SELECT * FROM check_test( domain_type_isnt( 'public'::name, 'us_postal_code', 'integer'), true, 'domain_type_isnt(schema, domain, type)', 'Domain public.us_postal_code should not extend type integer', '' ); SELECT * FROM check_test( domain_type_isnt( 'public', 'us_postal_code', 'text', 'whatever'), false, 'domain_type_isnt(schema, domain, type, desc) fail', 'whatever', ' have: text want: anything else' ); SELECT * FROM check_test( domain_type_isnt( 'public', 'zip_code', 'text', 'whatever'), false, 'domain_type_isnt(schema, nondomain, type, desc)', 'whatever', ' Domain public.zip_code does not exist' ); SELECT * FROM check_test( domain_type_isnt( 'public', 'integer', 'text', 'whatever'), false, 'domain_type_isnt(schema, type, type, desc)', 'whatever', ' Domain public.integer does not exist' ); SELECT * FROM check_test( domain_type_isnt( 'us_postal_code', 'integer', 'whatever'), true, 'domain_type_isnt(domain, type, desc)', 'whatever', '' ); SELECT * FROM check_test( domain_type_isnt( 'us_postal_code', 'integer'), true, 'domain_type_isnt(domain, type)', 'Domain us_postal_code should not extend type integer', '' ); SELECT * FROM check_test( domain_type_isnt( 'us_postal_code', 'text', 'whatever'), false, 'domain_type_isnt(domain, type, desc) fail', 'whatever', ' have: text want: anything else' ); SELECT * FROM check_test( domain_type_isnt( 'zip_code', 'text', 'whatever'), false, 'domain_type_isnt(nondomain, type, desc)', 'whatever', ' Domain zip_code does not exist' ); SELECT * FROM check_test( domain_type_isnt( 'integer', 'text', 'whatever'), false, 'domain_type_isnt(type, type, desc)', 'whatever', ' Domain integer does not exist' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._index.sql000644 000765 000024 00000000252 11666501762 017001 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/index.sql000644 000765 000024 00000035242 11666501762 016573 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(225); --SELECT * FROM no_plan(); -- This will be rolled back. :-) SET client_min_messages = warning; CREATE TABLE public.sometab( id INT NOT NULL PRIMARY KEY, name TEXT DEFAULT '', numb NUMERIC(10, 2), myint NUMERIC(8) ); CREATE INDEX idx_hey ON public.sometab(numb); CREATE INDEX idx_foo ON public.sometab using hash(name); CREATE INDEX idx_bar ON public.sometab(numb, name); CREATE UNIQUE INDEX idx_baz ON public.sometab(LOWER(name)); RESET client_min_messages; /****************************************************************************/ -- Test has_index(). SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_hey', 'numb', 'whatever' ), true, 'has_index() single column', 'whatever', '' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_hey', 'numb'::name ), true, 'has_index() single column no desc', 'Index idx_hey should exist', '' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_foo', 'name', 'whatever' ), true, 'has_index() hash index', 'whatever', '' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_foo', 'name'::name ), true, 'has_index() hash index no desc', 'Index idx_foo should exist', '' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_bar', ARRAY['numb', 'name'], 'whatever' ), true, 'has_index() multi-column', 'whatever', '' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_bar', ARRAY['numb', 'name'] ), true, 'has_index() multi-column no desc', 'Index idx_bar should exist', '' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_baz', 'lower(name)', 'whatever' ), true, 'has_index() functional', 'whatever', '' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_baz', 'whatever' ), true, 'has_index() no cols', 'whatever', '' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_foo', 'whatever' ), true, 'has_index() hash index', 'whatever', '' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_baz'::name ), true, 'has_index() no cols no desc', 'Index idx_baz should exist', '' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_foo'::name ), true, 'has_index() no cols hash index no desc', 'Index idx_foo should exist', '' ); SELECT * FROM check_test( has_index( 'sometab', 'idx_foo', 'name', 'whatever' ), true, 'has_index() no schema single column', 'whatever', '' ); SELECT * FROM check_test( has_index( 'sometab', 'idx_foo', 'name'::name ), true, 'has_index() no schema single column no desc', 'Index idx_foo should exist', '' ); SELECT * FROM check_test( has_index( 'sometab', 'idx_bar', ARRAY['numb', 'name'], 'whatever' ), true, 'has_index() no schema multi-column', 'whatever', '' ); SELECT * FROM check_test( has_index( 'sometab', 'idx_bar', ARRAY['numb', 'name'] ), true, 'has_index() no schema multi-column no desc', 'Index idx_bar should exist', '' ); SELECT * FROM check_test( has_index( 'sometab', 'idx_baz', 'lower(name)', 'whatever' ), true, 'has_index() no schema functional', 'whatever', '' ); SELECT * FROM check_test( has_index( 'sometab', 'idx_baz', 'lower(name)' ), true, 'has_index() no schema functional no desc', 'Index idx_baz should exist', '' ); SELECT * FROM check_test( has_index( 'sometab', 'idx_baz', 'whatever' ), true, 'has_index() no schema or cols', 'whatever', '' ); SELECT * FROM check_test( has_index( 'sometab', 'idx_foo', 'whatever' ), true, 'has_index() hash index no schema or cols', 'whatever', '' ); SELECT * FROM check_test( has_index( 'sometab', 'idx_baz' ), true, 'has_index() no schema or cols or desc', 'Index idx_baz should exist', '' ); SELECT * FROM check_test( has_index( 'sometab', 'idx_foo' ), true, 'has_index() hash index no schema or cols or desc', 'Index idx_foo should exist', '' ); -- Check failure diagnostics. SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_heya', 'numb', 'whatever' ), false, 'has_index() non-existent', 'whatever', 'Index idx_heya ON public.sometab not found' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'blah', ARRAY['numb', 'name'], 'whatever' ), false, 'has_index() missing', 'whatever', 'Index blah ON public.sometab not found' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_bar', ARRAY['name', 'id'], 'whatever' ), false, 'has_index() invalid', 'whatever', ' have: idx_bar ON public.sometab(numb, name) want: idx_bar ON public.sometab(name, id)' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_bar', ARRAY['name'], 'whatever' ), false, 'has_index() missing column', 'whatever', ' have: idx_bar ON public.sometab(numb, name) want: idx_bar ON public.sometab(name)' ); SELECT * FROM check_test( has_index( 'sometab', 'blah', ARRAY['numb', 'name'], 'whatever' ), false, 'has_index() missing no schema', 'whatever', 'Index blah ON sometab not found' ); SELECT * FROM check_test( has_index( 'sometab', 'idx_bar', ARRAY['name', 'id'], 'whatever' ), false, 'has_index() invalid no schema', 'whatever', ' have: idx_bar ON sometab(numb, name) want: idx_bar ON sometab(name, id)' ); SELECT * FROM check_test( has_index( 'public', 'sometab', 'idx_baz', 'lower(wank)', 'whatever' ), false, 'has_index() functional fail', 'whatever', ' have: idx_baz ON public.sometab(lower(name)) want: idx_baz ON public.sometab(lower(wank))' ); SELECT * FROM check_test( has_index( 'sometab', 'idx_baz', 'lower(wank)', 'whatever' ), false, 'has_index() functional fail no schema', 'whatever', ' have: idx_baz ON sometab(lower(name)) want: idx_baz ON sometab(lower(wank))' ); /****************************************************************************/ -- Test hasnt_index(). SELECT * FROM check_test( hasnt_index( 'public', 'sometab', 'idx_foo', 'whatever' ), false, 'hasnt_index(schema, table, index, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_index( 'public', 'sometab', 'idx_foo'::name ), false, 'hasnt_index(schema, table, index)', 'Index idx_foo should not exist', '' ); SELECT * FROM check_test( hasnt_index( 'public', 'sometab', 'idx_blah', 'whatever' ), true, 'hasnt_index(schema, table, non-index, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_index( 'public', 'sometab', 'idx_blah'::name ), true, 'hasnt_index(schema, table, non-index)', 'Index idx_blah should not exist', '' ); SELECT * FROM check_test( hasnt_index( 'sometab', 'idx_foo', 'whatever' ), false, 'hasnt_index(table, index, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_index( 'sometab', 'idx_foo'::name ), false, 'hasnt_index(table, index)', 'Index idx_foo should not exist', '' ); SELECT * FROM check_test( hasnt_index( 'sometab', 'idx_blah', 'whatever' ), true, 'hasnt_index(table, non-index, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_index( 'sometab', 'idx_blah'::name ), true, 'hasnt_index(table, non-index)', 'Index idx_blah should not exist', '' ); /****************************************************************************/ -- Test index_is_unique(). SELECT * FROM check_test( index_is_unique( 'public', 'sometab', 'idx_baz', 'whatever' ), true, 'index_is_unique()', 'whatever', '' ); SELECT * FROM check_test( index_is_unique( 'public', 'sometab', 'idx_baz' ), true, 'index_is_unique() no desc', 'Index idx_baz should be unique', '' ); SELECT * FROM check_test( index_is_unique( 'sometab', 'idx_baz' ), true, 'index_is_unique() no schema', 'Index idx_baz should be unique', '' ); SELECT * FROM check_test( index_is_unique( 'idx_baz' ), true, 'index_is_unique() index only', 'Index idx_baz should be unique', '' ); SELECT * FROM check_test( index_is_unique( 'public', 'sometab', 'sometab_pkey', 'whatever' ), true, 'index_is_unique() on pk', 'whatever', '' ); SELECT * FROM check_test( index_is_unique( 'public', 'sometab', 'sometab_pkey' ), true, 'index_is_unique() on pk no desc', 'Index sometab_pkey should be unique', '' ); SELECT * FROM check_test( index_is_unique( 'sometab', 'sometab_pkey' ), true, 'index_is_unique() on pk no schema', 'Index sometab_pkey should be unique', '' ); SELECT * FROM check_test( index_is_unique( 'sometab_pkey' ), true, 'index_is_unique() on pk index only', 'Index sometab_pkey should be unique', '' ); SELECT * FROM check_test( index_is_unique( 'public', 'sometab', 'idx_bar', 'whatever' ), false, 'index_is_unique() fail', 'whatever', '' ); SELECT * FROM check_test( index_is_unique( 'public', 'sometab', 'idx_bar' ), false, 'index_is_unique() fail no desc', 'Index idx_bar should be unique', '' ); SELECT * FROM check_test( index_is_unique( 'sometab', 'idx_bar' ), false, 'index_is_unique() fail no schema', 'Index idx_bar should be unique', '' ); SELECT * FROM check_test( index_is_unique( 'idx_bar' ), false, 'index_is_unique() fail index only', 'Index idx_bar should be unique', '' ); SELECT * FROM check_test( index_is_unique( 'blahblah' ), false, 'index_is_unique() no such index', 'Index blahblah should be unique', '' ); /****************************************************************************/ -- Test index_is_primary(). SELECT * FROM check_test( index_is_primary( 'public', 'sometab', 'sometab_pkey', 'whatever' ), true, 'index_is_primary()', 'whatever', '' ); SELECT * FROM check_test( index_is_primary( 'public', 'sometab', 'sometab_pkey' ), true, 'index_is_primary() no desc', 'Index sometab_pkey should be on a primary key', '' ); SELECT * FROM check_test( index_is_primary( 'sometab', 'sometab_pkey' ), true, 'index_is_primary() no schema', 'Index sometab_pkey should be on a primary key', '' ); SELECT * FROM check_test( index_is_primary( 'sometab_pkey' ), true, 'index_is_primary() index only', 'Index sometab_pkey should be on a primary key', '' ); SELECT * FROM check_test( index_is_primary( 'public', 'sometab', 'idx_baz', 'whatever' ), false, 'index_is_primary() fail', 'whatever', '' ); SELECT * FROM check_test( index_is_primary( 'public', 'sometab', 'idx_baz' ), false, 'index_is_primary() fail no desc', 'Index idx_baz should be on a primary key', '' ); SELECT * FROM check_test( index_is_primary( 'sometab', 'idx_baz' ), false, 'index_is_primary() fail no schema', 'Index idx_baz should be on a primary key', '' ); SELECT * FROM check_test( index_is_primary( 'idx_baz' ), false, 'index_is_primary() fail index only', 'Index idx_baz should be on a primary key', '' ); SELECT * FROM check_test( index_is_primary( 'blahblah' ), false, 'index_is_primary() no such index', 'Index blahblah should be on a primary key', '' ); /****************************************************************************/ -- Test is_clustered(). SELECT * FROM check_test( is_clustered( 'public', 'sometab', 'idx_bar', 'whatever' ), false, 'is_clustered() fail', 'whatever', '' ); SELECT * FROM check_test( is_clustered( 'public', 'sometab', 'idx_bar' ), false, 'is_clustered() fail no desc', 'Table public.sometab should be clustered on index idx_bar', '' ); SELECT * FROM check_test( is_clustered( 'sometab', 'idx_bar' ), false, 'is_clustered() fail no schema', 'Table sometab should be clustered on index idx_bar', '' ); SELECT * FROM check_test( is_clustered( 'idx_bar' ), false, 'is_clustered() fail index only', 'Table should be clustered on index idx_bar', '' ); CLUSTER idx_bar ON public.sometab; SELECT * FROM check_test( is_clustered( 'public', 'sometab', 'idx_bar', 'whatever' ), true, 'is_clustered()', 'whatever', '' ); SELECT * FROM check_test( is_clustered( 'public', 'sometab', 'idx_bar' ), true, 'is_clustered() no desc', 'Table public.sometab should be clustered on index idx_bar', '' ); SELECT * FROM check_test( is_clustered( 'sometab', 'idx_bar' ), true, 'is_clustered() no schema', 'Table sometab should be clustered on index idx_bar', '' ); SELECT * FROM check_test( is_clustered( 'idx_bar' ), true, 'is_clustered() index only', 'Table should be clustered on index idx_bar', '' ); /****************************************************************************/ -- Test index_is_type(). SELECT * FROM check_test( index_is_type( 'public', 'sometab', 'idx_bar', 'btree', 'whatever' ), true, 'index_is_type()', 'whatever', '' ); SELECT * FROM check_test( index_is_type( 'public', 'sometab', 'idx_bar', 'btree' ), true, 'index_is_type() no desc', 'Index idx_bar should be a btree index', '' ); SELECT * FROM check_test( index_is_type( 'public', 'sometab', 'idx_bar', 'hash' ), false, 'index_is_type() fail', 'Index idx_bar should be a hash index', ' have: btree want: hash' ); SELECT * FROM check_test( index_is_type( 'sometab', 'idx_bar', 'btree' ), true, 'index_is_type() no schema', 'Index idx_bar should be a btree index', '' ); SELECT * FROM check_test( index_is_type( 'sometab', 'idx_bar', 'hash' ), false, 'index_is_type() no schema fail', 'Index idx_bar should be a hash index', ' have: btree want: hash' ); SELECT * FROM check_test( index_is_type( 'idx_bar', 'btree' ), true, 'index_is_type() no table', 'Index idx_bar should be a btree index', '' ); SELECT * FROM check_test( index_is_type( 'idx_bar', 'hash' ), false, 'index_is_type() no table fail', 'Index idx_bar should be a hash index', ' have: btree want: hash' ); SELECT * FROM check_test( index_is_type( 'idx_foo', 'hash' ), true, 'index_is_type() hash', 'Index idx_foo should be a hash index', '' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._istap.sql000644 000765 000024 00000000252 11666501762 017012 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/istap.sql000644 000765 000024 00000012156 11666501762 016603 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(47); --SELECT * from no_plan(); /****************************************************************************/ -- Test is(). SELECT * FROM check_test( is(1, 1), true, 'is(1, 1)', '', '' ); SELECT * FROM check_test( is('x'::text, 'x'::text), true, 'is(''x'', ''x'')', '', '' ); SELECT * FROM check_test( is(1.1, 1.10), true, 'is(1.1, 1.10)', '', '' ); SELECT * FROM check_test( is(true, true), true, 'is(true, true)', '', '' ); SELECT * FROM check_test( is(false, false), true, 'is(false, false)', '', '' ); SELECT * FROM check_test( is(1, 1, 'foo'), true, 'is(1, 1, desc)', 'foo', '' ); SELECT * FROM check_test( is( 1, 2 ), false, 'is(1, 2)', '', ' have: 1 want: 2'); /****************************************************************************/ -- Test isnt(). SELECT * FROM check_test( isnt(1, 2), true, 'isnt(1, 2)', '', '' ); SELECT * FROM check_test( isnt( 1, 1 ), false, 'isnt(1, 1)', '', ' have: 1 want: anything else' ); /****************************************************************************/ -- Try using variables. \set foo '\'' waffle '\'' \set bar '\'' waffle '\'' SELECT is( :foo::text, :bar::text, 'is() should work with psql variables' ); /****************************************************************************/ -- Try using NULLs. SELECT * FROM check_test( is( NULL::text, NULL::text, 'NULLs' ), true, 'is(NULL, NULL)', 'NULLs', '' ); SELECT * FROM check_test( is( NULL::text, 'foo' ), false, 'is(NULL, foo)', '', ' have: NULL want: foo' ); SELECT * FROM check_test( is( 'foo', NULL::text ), false, 'is(foo, NULL)', '', ' have: foo want: NULL' ); SET client_min_messages = warning; CREATE TABLE mumble ( id int, name text ); RESET client_min_messages; INSERT INTO mumble VALUES (1, 'hey'); CREATE FUNCTION test_records() RETURNS SETOF TEXT AS $$ DECLARE tap record; BEGIN IF pg_version_num() < 80100 THEN -- Can't do shit with records on 8.0 RETURN NEXT pass('with records!'); RETURN NEXT pass( 'is(mumble, row) fail should fail'); RETURN NEXT pass( 'is(mumble, row) fail should have the proper description'); RETURN NEXT pass( 'is(mumble, row) fail should have the proper diagnostics'); RETURN NEXT pass( 'is(mumble, row) fail with NULL should fail'); RETURN NEXT pass( 'is(mumble, row) fail with NULL should have the proper description'); RETURN NEXT pass( 'is(mumble, row) fail with NULL should have the proper diagnostics'); RETURN NEXT pass( 'is(mumble, NULL) should fail'); RETURN NEXT pass( 'is(mumble, NULL) should have the proper description'); RETURN NEXT pass( 'is(mumble, NULL) should have the proper diagnostics'); ELSIF pg_version_num() >= 80400 THEN RETURN NEXT is( mumble.*, ROW(1, 'hey')::mumble, 'with records!' ) FROM mumble; -- Before 8.3, have to cast to text. FOR tap IN SELECT check_test( is( mumble.*, ROW(1, 'HEY')::mumble ), false, 'is(mumble, row) fail', '', ' have: (1,hey) want: (1,HEY)' ) AS b FROM mumble LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT check_test( is( mumble.*, ROW(1, NULL)::mumble ), false, 'is(mumble, row) fail with NULL', '', ' have: (1,hey) want: (1,)' ) AS b FROM mumble LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT check_test( is( mumble.*, NULL::mumble ), false, 'is(mumble, NULL)', '', ' have: (1,hey) want: NULL' ) AS b FROM mumble LOOP RETURN NEXT tap.b; END LOOP; ELSE RETURN NEXT is( textin(record_out(mumble.*)), textin(record_out(ROW(1, 'hey'))), 'with records!' ) FROM mumble; FOR tap IN SELECT check_test( is( textin(record_out(mumble.*)), textin(record_out(ROW(1, 'HEY')))), false, 'is(mumble, row) fail', '', ' have: (1,hey) want: (1,HEY)' ) AS b FROM mumble LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT check_test( is( textin(record_out(mumble.*)), textin(record_out(ROW(1, NULL))) ), false, 'is(mumble, row) fail with NULL', '', ' have: (1,hey) want: (1,)' ) AS b FROM mumble LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT check_test( is( textin(record_out(mumble.*)), NULL::text ), false, 'is(mumble, NULL)', '', ' have: (1,hey) want: NULL' ) AS b FROM mumble LOOP RETURN NEXT tap.b; END LOOP; END IF; RETURN; END; $$ LANGUAGE PLPGSQL; SELECT * FROM test_records(); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._matching.sql000644 000765 000024 00000000252 11666501762 017464 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/matching.sql000644 000765 000024 00000004071 11666501762 017252 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(24); /****************************************************************************/ -- Test matches(). SELECT matches( 'foo'::text, 'o', 'matches() should work' ); SELECT matches( 'foo'::text, '^fo', 'matches() should work with a regex' ); SELECT imatches( 'FOO'::text, '^fo', 'imatches() should work with a regex' ); -- Check matches() diagnostics. SELECT * FROM check_test( matches( 'foo'::text, '^a' ), false, 'matches() fail', '', ' ''foo'' doesn''t match: ''^a''' ); -- Check doesnt_match. SELECT doesnt_match( 'foo'::text, 'a', 'doesnt_match() should work' ); SELECT doesnt_match( 'foo'::text, '^o', 'doesnt_match() should work with a regex' ); SELECT doesnt_imatch( 'foo'::text, '^o', 'doesnt_imatch() should work with a regex' ); -- Check doesnt_match diagnostics. SELECT * FROM check_test( doesnt_match( 'foo'::text, 'o' ), false, 'doesnt_match() fail', '', ' ''foo'' matches: ''o''' ); /****************************************************************************/ -- Test alike(). SELECT alike( 'foo'::text, 'foo', 'alike() should work' ); SELECT alike( 'foo'::text, 'fo%', 'alike() should work with a regex' ); SELECT ialike( 'FOO'::text, 'fo%', 'ialike() should work with a regex' ); -- Check alike() diagnostics. SELECT * FROM check_test( alike( 'foo'::text, 'a%'::text ), false, 'alike() fail', '', ' ''foo'' doesn''t match: ''a%''' ); -- Test unalike(). SELECT unalike( 'foo'::text, 'f', 'unalike() should work' ); SELECT unalike( 'foo'::text, 'f%i', 'unalike() should work with a regex' ); SELECT unialike( 'FOO'::text, 'f%i', 'iunalike() should work with a regex' ); -- Check unalike() diagnostics. SELECT * FROM check_test( unalike( 'foo'::text, 'f%'::text ), false, 'unalike() fail', '', ' ''foo'' matches: ''f%''' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._moretap.sql000644 000765 000024 00000000252 11666501762 017341 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/moretap.sql000644 000765 000024 00000010325 11666501762 017126 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql \set numb_tests 46 SELECT plan(:numb_tests); -- Replace the internal record of the plan for a few tests. UPDATE __tcache__ SET value = 3 WHERE label = 'plan'; /****************************************************************************/ -- Test pass(). SELECT pass( 'My pass() passed, w00t!' ); -- Test fail(). \set fail_numb 2 \echo ok :fail_numb - Testing fail() SELECT is( fail('oops'), 'not ok 2 - oops # Failed test 2: "oops"', 'We should get the proper output from fail()'); -- Check the finish() output. SELECT is( (SELECT * FROM finish() LIMIT 1), '# Looks like you failed 1 test of 3', 'The output of finish() should reflect the test failure' ); /****************************************************************************/ -- Check num_failed SELECT is( num_failed(), 1, 'We should have one failure' ); UPDATE __tresults__ SET ok = true, aok = true WHERE numb = :fail_numb; SELECT is( num_failed(), 0, 'We should now have no failures' ); /****************************************************************************/ -- Check diag. SELECT is( diag('foo'), '# foo', 'diag() should work properly' ); SELECT is( diag( 'foo bar'), '# foo # bar', 'multiline diag() should work properly' ); SELECT is( diag( 'foo # bar'), '# foo # # bar', 'multiline diag() should work properly with existing comments' ); -- Try anyelement form. SELECT is(diag(6), '# 6', 'diag(int)'); SELECT is(diag(11.2), '# 11.2', 'diag(numeric)'); SELECT is(diag(NOW()), '# ' || NOW(), 'diag(timestamptz)'); -- Try variadic anyarray CREATE FUNCTION test_variadic() RETURNS SETOF TEXT AS $$ BEGIN IF pg_version_num() >= 80400 THEN RETURN NEXT is(diag('foo'::text, 'bar', 'baz'), '# foobarbaz', 'variadic text'); RETURN NEXT is(diag(1::int, 3, 4), '# 134', 'variadic int'); RETURN NEXT is(diag('foo', 'bar', 'baz'), '# foobarbaz', 'variadic unknown'); ELSE RETURN NEXT pass('variadic text'); RETURN NEXT pass('variadic int'); RETURN NEXT pass('variadic unknown'); RETURN; END IF; END; $$ LANGUAGE plpgsql; SELECT * FROM test_variadic(); /****************************************************************************/ -- Check no_plan. DELETE FROM __tcache__ WHERE label = 'plan'; SELECT * FROM no_plan(); SELECT is( value, 0, 'no_plan() should have stored a plan of 0' ) FROM __tcache__ WHERE label = 'plan'; -- Set the plan to a high number. DELETE FROM __tcache__ WHERE label = 'plan'; SELECT is( plan(4000), '1..4000', 'Set the plan to 4000' ); SELECT is( (SELECT * FROM finish() LIMIT 1), '# Looks like you planned 4000 tests but ran 17', 'The output of finish() should reflect a high test plan' ); -- Set the plan to a low number. DELETE FROM __tcache__ WHERE label = 'plan'; SELECT is( plan(4), '1..4', 'Set the plan to 4' ); SELECT is( (SELECT * FROM finish() LIMIT 1), '# Looks like you planned 4 tests but ran 19', 'The output of finish() should reflect a low test plan' ); -- Reset the original plan. DELETE FROM __tcache__ WHERE label = 'plan'; SELECT is( plan(:numb_tests), '1..' || :numb_tests, 'Reset the plan' ); SELECT is( value, :numb_tests, 'plan() should have stored the test count' ) FROM __tcache__ WHERE label = 'plan'; /****************************************************************************/ -- Test ok() SELECT * FROM check_test( ok(true), true, 'ok(true)', '', ''); SELECT * FROM check_test( ok(true, ''), true, 'ok(true, '''')', '', '' ); SELECT * FROM check_test( ok(true, 'foo'), true, 'ok(true, ''foo'')', 'foo', '' ); SELECT * FROM check_test( ok(false), false, 'ok(false)', '', '' ); SELECT * FROM check_test( ok(false, ''), false, 'ok(false, '''')', '', '' ); SELECT * FROM check_test( ok(false, 'foo'), false, 'ok(false, ''foo'')', 'foo', '' ); SELECT * FROM check_test( ok(NULL, 'null'), false, 'ok(NULL, ''null'')', 'null', ' (test result was NULL)' ); /****************************************************************************/ -- test multiline description. SELECT * FROM check_test( ok( true, 'foo bar' ), true, 'multiline desc', 'foo bar', '' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._ownership.sql000644 000765 000024 00000000252 11666501762 017710 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/ownership.sql000644 000765 000024 00000002170 11666501762 017474 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(12); --SELECT * FROM no_plan(); /****************************************************************************/ SELECT * From check_test( db_owner_is(current_database(), current_user, 'mumble'), true, 'db_owner_is(db, user, desc)', 'mumble', '' ); SELECT * From check_test( db_owner_is(current_database(), current_user), true, 'db_owner_is(db, user)', 'Database ' || quote_ident(current_database()) || ' should be owned by ' || current_user, '' ); SELECT * From check_test( db_owner_is('__not__' || current_database(), current_user, 'mumble'), false, 'db_owner_is(non-db, user)', 'mumble', ' Database __not__' || current_database() || ' does not exist' ); SELECT * From check_test( db_owner_is(current_database(), '__not__' || current_user, 'mumble'), false, 'db_owner_is(db, non-user)', 'mumble', ' have: ' || current_user || ' want: __not__' || current_user ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._perform.sql000644 000765 000024 00000000252 11666501762 017344 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/perform.sql000644 000765 000024 00000003377 11666501762 017142 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(24); --SELECT * FROM no_plan(); /****************************************************************************/ -- Test performs_ok(). SELECT * FROM check_test( performs_ok( 'SELECT TRUE', 500, 'whatever' ), true, 'simple select', 'whatever', '' ); SELECT * FROM check_test( performs_ok( 'SELECT TRUE', 500 ), true, 'simple select no desc', 'Should run in less than 500 ms', '' ); SELECT * FROM check_test( performs_ok( 'SELECT TRUE', 99.99 ), true, 'simple select numeric', 'Should run in less than 99.99 ms', '' ); PREPARE mytest AS SELECT TRUE; SELECT * FROM check_test( performs_ok( 'mytest', 100 ), true, 'simple prepare', 'Should run in less than 100 ms', '' ); SELECT * FROM check_test( performs_ok( 'EXECUTE mytest', 100 ), true, 'simple execute', 'Should run in less than 100 ms', '' ); SELECT * FROM check_test( performs_ok( 'SELECT TRUE', 0, 'whatever' ), false, 'simple select fail', 'whatever', ' runtime: [[:digit:]]+([.][[:digit:]]+)? ms exceeds: 0 ms', true ); SELECT * FROM check_test( performs_ok( 'SELECT TRUE', 0 ), false, 'simple select no desc fail', 'Should run in less than 0 ms', ' runtime: [[:digit:]]+([.][[:digit:]]+)? ms exceeds: 0 ms', true ); SELECT * FROM check_test( performs_ok( 'SELECT TRUE', 0.00 ), false, 'simple select no desc numeric fail', 'Should run in less than 0.00 ms', ' runtime: [[:digit:]]+([.][[:digit:]]+)? ms exceeds: 0.00 ms', true ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._pg73.sql000644 000765 000024 00000000252 11666501762 016452 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/pg73.sql000644 000765 000024 00000003353 11666501762 016242 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql select plan(39); select ok(true); select ok(true, 'true'); select ok(NOT false); select ok(NOT false, 'NOT false'); select ok(3 = 3); select ok(3 = 3, 'three'); select ok(1 != 2); select ok(1 <> 2); select isnt(1,2); select isnt(1,2,'1=2'); select is( now(), now(), 'now()=now()'); select is( '1 hour'::interval, '1 hour'::interval, '''1 hour''::interval, ''1 hour''::interval'); select is( now()::date, now()::date); select is( now()::date, now()::date, 'now=now date' ); select isnt( now()::date, now()::date + 1, 'now!=now+1' ); select is( now()::timestamp, now()::timestamp, 'now()=now() timestamp'); select is( now()::date, now()::date, 'now()=now() date'); select is( TRUE, TRUE, 'TRUE=TRUE' ); select isnt( TRUE, FALSE, 'TRUE!=FALSE' ); select is('a'::char, 'a'::char, 'a=a char'); select isnt('a'::char, 'b'::char, 'a!=b char'); select is('a'::text, 'a'::text, 'a=a text'); select isnt('a'::text, 'b'::text, 'a!=b text'); select is(3::int, 3::int, '3=3 int'); select isnt(3::int, 4::int, '3!=4 int'); select is(3::integer, 3::integer, '3=3 integer'); select isnt(3::integer, 4::integer, '3!=4 integer'); select is(3::int2, 3::int2, '3=3 int2'); select isnt(3::int2, 4::int2, '3!=4 int2'); select is(3::int4, 3::int4, '3=3 int4'); select isnt(3::int4, 4::int4, '3!=4 int4'); select is(3::int8, 3::int8, '3=3 int8'); select isnt(3::int8, 4::int8, '3!=4 int8'); select is(3.2::float, 3.2::float, '3.2=3.2 float'); select isnt(3.2::float, 4.5::float, '3.2!=4.5 float'); select is(3.2::float4, 3.2::float4, '3.2=3.2 float4'); select isnt(3.2::float4, 4.5::float4, '3.2!=4.5 float4'); select is(3.2::float8, 3.2::float8, '3.2=3.2 float8'); select isnt(3.2::float8, 4.5::float8, '3.2!=4.5 float8'); select * from finish(); ROLLBACK; pgtap-0.90.0/test/sql/._pktap.sql000644 000765 000024 00000000252 11666501762 017011 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/pktap.sql000644 000765 000024 00000016121 11666501762 016576 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(84); --SELECT * FROM no_plan(); -- This will be rolled back. :-) SET client_min_messages = warning; CREATE TABLE public.sometab( id INT NOT NULL PRIMARY KEY, name TEXT DEFAULT '', numb NUMERIC(10, 2), myint NUMERIC(8) ); CREATE SCHEMA hide; CREATE TABLE hide.hidesometab( id INT NOT NULL PRIMARY KEY, name TEXT DEFAULT '', numb NUMERIC(10, 2), myint NUMERIC(8) ); RESET client_min_messages; /****************************************************************************/ -- Test has_pk(). SELECT * FROM check_test( has_pk( 'public', 'sometab', 'public.sometab should have a pk' ), true, 'has_pk( schema, table, description )', 'public.sometab should have a pk', '' ); SELECT * FROM check_test( has_pk( 'hide', 'hidesometab', 'hide.sometab should have a pk' ), true, 'has_pk( hideschema, hidetable, description )', 'hide.sometab should have a pk', '' ); SELECT * FROM check_test( has_pk( 'sometab', 'sometab should have a pk' ), true, 'has_pk( table, description )', 'sometab should have a pk', '' ); SELECT * FROM check_test( has_pk( 'hidesometab', 'hidesometab should have a pk' ), false, 'has_pk( hidetable, description ) fail', 'hidesometab should have a pk', '' ); SELECT * FROM check_test( has_pk( 'sometab' ), true, 'has_pk( table )', 'Table sometab should have a primary key', '' ); SELECT * FROM check_test( has_pk( 'pg_catalog', 'pg_class', 'pg_catalog.pg_class should have a pk' ), false, 'has_pk( schema, table, description ) fail', 'pg_catalog.pg_class should have a pk', '' ); SELECT * FROM check_test( has_pk( 'pg_class', 'pg_class should have a pk' ), false, 'has_pk( table, description ) fail', 'pg_class should have a pk', '' ); /****************************************************************************/ -- Test hasnt_pk(). SELECT * FROM check_test( hasnt_pk( 'public', 'sometab', 'public.sometab should not have a pk' ), false, 'hasnt_pk( schema, table, description )', 'public.sometab should not have a pk', '' ); SELECT * FROM check_test( hasnt_pk( 'sometab', 'sometab should not have a pk' ), false, 'hasnt_pk( table, description )', 'sometab should not have a pk', '' ); SELECT * FROM check_test( hasnt_pk( 'sometab' ), false, 'hasnt_pk( table )', 'Table sometab should not have a primary key', '' ); SELECT * FROM check_test( hasnt_pk( 'pg_catalog', 'pg_class', 'pg_catalog.pg_class should not have a pk' ), true, 'hasnt_pk( schema, table, description ) pass', 'pg_catalog.pg_class should not have a pk', '' ); SELECT * FROM check_test( hasnt_pk( 'pg_class', 'pg_class should not have a pk' ), true, 'hasnt_pk( table, description ) pass', 'pg_class should not have a pk', '' ); /****************************************************************************/ -- Test col_is_pk(). SELECT * FROM check_test( col_is_pk( 'public', 'sometab', 'id', 'public.sometab.id should be a pk' ), true, 'col_is_pk( schema, table, column, description )', 'public.sometab.id should be a pk', '' ); SELECT * FROM check_test( col_is_pk( 'sometab', 'id', 'sometab.id should be a pk' ), true, 'col_is_pk( table, column, description )', 'sometab.id should be a pk', '' ); SELECT * FROM check_test( col_is_pk( 'sometab', 'id' ), true, 'col_is_pk( table, column )', 'Column sometab(id) should be a primary key', '' ); SELECT * FROM check_test( col_is_pk( 'public', 'sometab', 'name', 'public.sometab.name should be a pk' ), false, 'col_is_pk( schema, table, column, description ) fail', 'public.sometab.name should be a pk', ' have: {id} want: {name}' ); SELECT * FROM check_test( col_is_pk( 'sometab', 'name', 'sometab.name should be a pk' ), false, 'col_is_pk( table, column, description ) fail', 'sometab.name should be a pk', ' have: {id} want: {name}' ); /****************************************************************************/ -- Test col_is_pk() with an array of columns. SET client_min_messages = warning; CREATE TABLE public.argh ( id INT NOT NULL, name TEXT NOT NULL, PRIMARY KEY (id, name) ); RESET client_min_messages; SELECT * FROM check_test( col_is_pk( 'public', 'argh', ARRAY['id', 'name'], 'id + name should be a pk' ), true, 'col_is_pk( schema, table, column[], description )', 'id + name should be a pk', '' ); SELECT * FROM check_test( col_is_pk( 'argh', ARRAY['id', 'name'], 'id + name should be a pk' ), true, 'col_is_pk( table, column[], description )', 'id + name should be a pk', '' ); SELECT * FROM check_test( col_is_pk( 'argh', ARRAY['id', 'name'] ), true, 'col_is_pk( table, column[] )', 'Columns argh(id, name) should be a primary key', '' ); /****************************************************************************/ -- Test col_isnt_pk(). SELECT * FROM check_test( col_isnt_pk( 'public', 'sometab', 'id', 'public.sometab.id should not be a pk' ), false, 'col_isnt_pk( schema, table, column, description )', 'public.sometab.id should not be a pk', ' have: {id} want: anything else' ); SELECT * FROM check_test( col_isnt_pk( 'sometab', 'id', 'sometab.id should not be a pk' ), false, 'col_isnt_pk( table, column, description )', 'sometab.id should not be a pk', ' have: {id} want: anything else' ); SELECT * FROM check_test( col_isnt_pk( 'sometab', 'id' ), false, 'col_isnt_pk( table, column )', 'Column sometab(id) should not be a primary key', ' have: {id} want: anything else' ); SELECT * FROM check_test( col_isnt_pk( 'public', 'sometab', 'name', 'public.sometab.name should not be a pk' ), true, 'col_isnt_pk( schema, table, column, description ) pass', 'public.sometab.name should not be a pk', '' ); SELECT * FROM check_test( col_isnt_pk( 'sometab', 'name', 'sometab.name should not be a pk' ), true, 'col_isnt_pk( table, column, description ) pass', 'sometab.name should not be a pk', '' ); /****************************************************************************/ -- Test col_isnt_pk() with an array of columns. SELECT * FROM check_test( col_isnt_pk( 'public', 'argh', ARRAY['id', 'foo'], 'id + foo should not be a pk' ), true, 'col_isnt_pk( schema, table, column[], description )', 'id + foo should not be a pk', '' ); SELECT * FROM check_test( col_isnt_pk( 'argh', ARRAY['id', 'foo'], 'id + foo should not be a pk' ), true, 'col_isnt_pk( table, column[], description )', 'id + foo should not be a pk', '' ); SELECT * FROM check_test( col_isnt_pk( 'argh', ARRAY['id', 'foo'] ), true, 'col_isnt_pk( table, column[] )', 'Columns argh(id, foo) should not be a primary key', '' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._resultset.sql000644 000765 000024 00000000252 11666501762 017724 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/resultset.sql000644 000765 000024 00000201750 11666501762 017515 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(515); --SELECT * FROM no_plan(); -- This will be rolled back. :-) SET client_min_messages = warning; CREATE TABLE names ( id SERIAL NOT NULL PRIMARY KEY, name TEXT DEFAULT '' ); CREATE TABLE someat ( id SERIAL PRIMARY KEY, ts timestamp DEFAULT NOW(), active BOOLEAN DEFAULT TRUE ); RESET client_min_messages; -- Top 100 boy an 100 girl names in 2005. http://www.ssa.gov/OACT/babynames/ INSERT INTO names (name) VALUES ('Jacob'); INSERT INTO names (name) VALUES ('Emily'); INSERT INTO names (name) VALUES ('Michael'); INSERT INTO names (name) VALUES ('Emma'); INSERT INTO names (name) VALUES ('Joshua'); INSERT INTO names (name) VALUES ('Madison'); INSERT INTO names (name) VALUES ('Matthew'); INSERT INTO names (name) VALUES ('Abigail'); INSERT INTO names (name) VALUES ('Ethan'); INSERT INTO names (name) VALUES ('Olivia'); INSERT INTO names (name) VALUES ('Andrew'); INSERT INTO names (name) VALUES ('Isabella'); INSERT INTO names (name) VALUES ('Daniel'); INSERT INTO names (name) VALUES ('Hannah'); INSERT INTO names (name) VALUES ('Anthony'); INSERT INTO names (name) VALUES ('Samantha'); INSERT INTO names (name) VALUES ('Christopher'); INSERT INTO names (name) VALUES ('Ava'); INSERT INTO names (name) VALUES ('Joseph'); INSERT INTO names (name) VALUES ('Ashley'); INSERT INTO names (name) VALUES ('William'); INSERT INTO names (name) VALUES ('Elizabeth'); INSERT INTO names (name) VALUES ('Alexander'); INSERT INTO names (name) VALUES ('Sophia'); INSERT INTO names (name) VALUES ('David'); INSERT INTO names (name) VALUES ('Alexis'); INSERT INTO names (name) VALUES ('Ryan'); INSERT INTO names (name) VALUES ('Grace'); INSERT INTO names (name) VALUES ('Nicholas'); INSERT INTO names (name) VALUES ('Sarah'); INSERT INTO names (name) VALUES ('Tyler'); INSERT INTO names (name) VALUES ('Alyssa'); INSERT INTO names (name) VALUES ('James'); INSERT INTO names (name) VALUES ('Mia'); INSERT INTO names (name) VALUES ('John'); INSERT INTO names (name) VALUES ('Natalie'); INSERT INTO names (name) VALUES ('Jonathan'); INSERT INTO names (name) VALUES ('Chloe'); INSERT INTO names (name) VALUES ('Nathan'); INSERT INTO names (name) VALUES ('Brianna'); INSERT INTO names (name) VALUES ('Samuel'); INSERT INTO names (name) VALUES ('Lauren'); INSERT INTO names (name) VALUES ('Christian'); INSERT INTO names (name) VALUES ('Anna'); INSERT INTO names (name) VALUES ('Noah'); INSERT INTO names (name) VALUES ('Ella'); INSERT INTO names (name) VALUES ('Dylan'); INSERT INTO names (name) VALUES ('Taylor'); INSERT INTO names (name) VALUES ('Benjamin'); INSERT INTO names (name) VALUES ('Kayla'); INSERT INTO names (name) VALUES ('Logan'); INSERT INTO names (name) VALUES ('Hailey'); INSERT INTO names (name) VALUES ('Brandon'); INSERT INTO names (name) VALUES ('Jessica'); INSERT INTO names (name) VALUES ('Gabriel'); INSERT INTO names (name) VALUES ('Victoria'); INSERT INTO names (name) VALUES ('Zachary'); INSERT INTO names (name) VALUES ('Jasmine'); INSERT INTO names (name) VALUES ('Jose'); INSERT INTO names (name) VALUES ('Sydney'); INSERT INTO names (name) VALUES ('Elijah'); INSERT INTO names (name) VALUES ('Julia'); INSERT INTO names (name) VALUES ('Angel'); INSERT INTO names (name) VALUES ('Destiny'); INSERT INTO names (name) VALUES ('Kevin'); INSERT INTO names (name) VALUES ('Morgan'); INSERT INTO names (name) VALUES ('Jack'); INSERT INTO names (name) VALUES ('Kaitlyn'); INSERT INTO names (name) VALUES ('Caleb'); INSERT INTO names (name) VALUES ('Savannah'); INSERT INTO names (name) VALUES ('Justin'); INSERT INTO names (name) VALUES ('Katherine'); INSERT INTO names (name) VALUES ('Robert'); INSERT INTO names (name) VALUES ('Alexandra'); INSERT INTO names (name) VALUES ('Austin'); INSERT INTO names (name) VALUES ('Rachel'); INSERT INTO names (name) VALUES ('Evan'); INSERT INTO names (name) VALUES ('Lily'); INSERT INTO names (name) VALUES ('Thomas'); INSERT INTO names (name) VALUES ('Kaylee'); INSERT INTO names (name) VALUES ('Luke'); INSERT INTO names (name) VALUES ('Megan'); INSERT INTO names (name) VALUES ('Mason'); INSERT INTO names (name) VALUES ('Jennifer'); INSERT INTO names (name) VALUES ('Aidan'); INSERT INTO names (name) VALUES ('Angelina'); INSERT INTO names (name) VALUES ('Jackson'); INSERT INTO names (name) VALUES ('Makayla'); INSERT INTO names (name) VALUES ('Isaiah'); INSERT INTO names (name) VALUES ('Allison'); INSERT INTO names (name) VALUES ('Jordan'); INSERT INTO names (name) VALUES ('Maria'); INSERT INTO names (name) VALUES ('Gavin'); INSERT INTO names (name) VALUES ('Brooke'); INSERT INTO names (name) VALUES ('Connor'); INSERT INTO names (name) VALUES ('Trinity'); INSERT INTO names (name) VALUES ('Isaac'); INSERT INTO names (name) VALUES ('Faith'); INSERT INTO names (name) VALUES ('Aiden'); INSERT INTO names (name) VALUES ('Lillian'); INSERT INTO names (name) VALUES ('Jason'); INSERT INTO names (name) VALUES ('Mackenzie'); INSERT INTO names (name) VALUES ('Cameron'); INSERT INTO names (name) VALUES ('Sofia'); INSERT INTO names (name) VALUES ('Hunter'); INSERT INTO names (name) VALUES ('Riley'); INSERT INTO names (name) VALUES ('Jayden'); INSERT INTO names (name) VALUES ('Haley'); INSERT INTO names (name) VALUES ('Juan'); INSERT INTO names (name) VALUES ('Gabrielle'); INSERT INTO names (name) VALUES ('Charles'); INSERT INTO names (name) VALUES ('Nicole'); INSERT INTO names (name) VALUES ('Aaron'); INSERT INTO names (name) VALUES ('Kylie'); INSERT INTO names (name) VALUES ('Lucas'); INSERT INTO names (name) VALUES ('Zoe'); INSERT INTO names (name) VALUES ('Luis'); INSERT INTO names (name) VALUES ('Katelyn'); INSERT INTO names (name) VALUES ('Owen'); INSERT INTO names (name) VALUES ('Paige'); INSERT INTO names (name) VALUES ('Landon'); INSERT INTO names (name) VALUES ('Gabriella'); INSERT INTO names (name) VALUES ('Diego'); INSERT INTO names (name) VALUES ('Jenna'); INSERT INTO names (name) VALUES ('Brian'); INSERT INTO names (name) VALUES ('Kimberly'); INSERT INTO names (name) VALUES ('Adam'); INSERT INTO names (name) VALUES ('Stephanie'); INSERT INTO names (name) VALUES ('Adrian'); INSERT INTO names (name) VALUES ('Andrea'); INSERT INTO names (name) VALUES ('Eric'); INSERT INTO names (name) VALUES ('Alexa'); INSERT INTO names (name) VALUES ('Kyle'); INSERT INTO names (name) VALUES ('Avery'); INSERT INTO names (name) VALUES ('Ian'); INSERT INTO names (name) VALUES ('Leah'); INSERT INTO names (name) VALUES ('Nathaniel'); INSERT INTO names (name) VALUES ('Nevaeh'); INSERT INTO names (name) VALUES ('Carlos'); INSERT INTO names (name) VALUES ('Madeline'); INSERT INTO names (name) VALUES ('Alex'); INSERT INTO names (name) VALUES ('Evelyn'); INSERT INTO names (name) VALUES ('Bryan'); INSERT INTO names (name) VALUES ('Mary'); INSERT INTO names (name) VALUES ('Jesus'); INSERT INTO names (name) VALUES ('Maya'); INSERT INTO names (name) VALUES ('Julian'); INSERT INTO names (name) VALUES ('Michelle'); INSERT INTO names (name) VALUES ('Sean'); INSERT INTO names (name) VALUES ('Sara'); INSERT INTO names (name) VALUES ('Hayden'); INSERT INTO names (name) VALUES ('Jada'); INSERT INTO names (name) VALUES ('Carter'); INSERT INTO names (name) VALUES ('Audrey'); INSERT INTO names (name) VALUES ('Jeremiah'); INSERT INTO names (name) VALUES ('Brooklyn'); INSERT INTO names (name) VALUES ('Cole'); INSERT INTO names (name) VALUES ('Vanessa'); INSERT INTO names (name) VALUES ('Brayden'); INSERT INTO names (name) VALUES ('Amanda'); INSERT INTO names (name) VALUES ('Wyatt'); INSERT INTO names (name) VALUES ('Rebecca'); INSERT INTO names (name) VALUES ('Chase'); INSERT INTO names (name) VALUES ('Caroline'); INSERT INTO names (name) VALUES ('Steven'); INSERT INTO names (name) VALUES ('Ariana'); INSERT INTO names (name) VALUES ('Timothy'); INSERT INTO names (name) VALUES ('Amelia'); INSERT INTO names (name) VALUES ('Dominic'); INSERT INTO names (name) VALUES ('Mariah'); INSERT INTO names (name) VALUES ('Sebastian'); INSERT INTO names (name) VALUES ('Jordan'); INSERT INTO names (name) VALUES ('Xavier'); INSERT INTO names (name) VALUES ('Jocelyn'); INSERT INTO names (name) VALUES ('Jaden'); INSERT INTO names (name) VALUES ('Arianna'); INSERT INTO names (name) VALUES ('Jesse'); INSERT INTO names (name) VALUES ('Isabel'); INSERT INTO names (name) VALUES ('Seth'); INSERT INTO names (name) VALUES ('Marissa'); INSERT INTO names (name) VALUES ('Devin'); INSERT INTO names (name) VALUES ('Autumn'); INSERT INTO names (name) VALUES ('Antonio'); INSERT INTO names (name) VALUES ('Melanie'); INSERT INTO names (name) VALUES ('Miguel'); INSERT INTO names (name) VALUES ('Aaliyah'); INSERT INTO names (name) VALUES ('Richard'); INSERT INTO names (name) VALUES ('Gracie'); INSERT INTO names (name) VALUES ('Colin'); INSERT INTO names (name) VALUES ('Claire'); INSERT INTO names (name) VALUES ('Cody'); INSERT INTO names (name) VALUES ('Isabelle'); INSERT INTO names (name) VALUES ('Alejandro'); INSERT INTO names (name) VALUES ('Molly'); INSERT INTO names (name) VALUES ('Caden'); INSERT INTO names (name) VALUES ('Mya'); INSERT INTO names (name) VALUES ('Blake'); INSERT INTO names (name) VALUES ('Diana'); INSERT INTO names (name) VALUES ('Kaden'); INSERT INTO names (name) VALUES ('Katie'); CREATE TABLE annames AS SELECT id, name FROM names WHERE name like 'An%'; -- We'll use these prepared statements. PREPARE anames AS SELECT id, name FROM names WHERE name like 'An%'; CREATE TABLE toexpect (id int, name text); INSERT INTO toexpect (id, name) VALUES(11, 'Andrew'); INSERT INTO toexpect (id, name) VALUES(44, 'Anna'); INSERT INTO toexpect (id, name) VALUES(15, 'Anthony'); INSERT INTO toexpect (id, name) VALUES(183, 'Antonio'); INSERT INTO toexpect (id, name) VALUES(86, 'Angelina'); INSERT INTO toexpect (id, name) VALUES(130, 'Andrea'); INSERT INTO toexpect (id, name) VALUES(63, 'Angel'); PREPARE expect AS SELECT id, name FROM toexpect; /****************************************************************************/ -- First, test _temptable. SELECT is( _temptable('SELECT * FROM names', '__foonames__'), '__foonames__', 'Should create temp table with simple query' ); SELECT has_table('__foonames__' ); SELECT is( _temptable( 'anames', '__somenames__' ), '__somenames__', 'Should create a temp table for a prepared statement' ); SELECT has_table('__somenames__' ); PREPARE "something cool" AS SELECT 1 AS a, 2 AS b; SELECT is( _temptable( '"something cool"', '__spacenames__' ), '__spacenames__', 'Should create a temp table for a prepared statement with space' ); SELECT has_table('__somenames__' ); SELECT has_table('__spacenames__' ); /****************************************************************************/ -- Now test set_eq(). SELECT * FROM check_test( set_eq( 'anames', 'expect', 'whatever' ), true, 'set_eq(prepared, prepared, desc)', 'whatever', '' ); SELECT * FROM check_test( set_eq( 'anames', 'expect' ), true, 'set_eq(prepared, prepared)', '', '' ); -- Pass a full SQL statement for the prepared statements. SELECT * FROM check_test( set_eq( 'EXECUTE anames', 'EXECUTE expect' ), true, 'set_eq(execute, execute, desc)', '', '' ); -- Compare actual SELECT statements. SELECT * FROM check_test( set_eq( 'SELECT id, name FROM names WHERE name like ''An%''', 'SELECT id, name FROM annames' ), true, 'set_eq(select, select)', '', '' ); -- Make sure that dupes are disregarded. SELECT * FROM check_test( set_eq( 'SELECT 1 AS a, ''Anna''::text AS b', 'SELECT 1 AS a, ''Anna''::text AS b UNION ALL SELECT 1, ''Anna''' ), true, 'set_eq(values, dupe values)', '', '' ); -- Try some failures. SELECT * FROM check_test( set_eq( 'anames', 'SELECT id, name FROM annames WHERE name <> ''Anna''' ), false, 'set_eq(prepared, select) fail extra', '', ' Extra records: (44,Anna)' ); SELECT * FROM check_test( set_eq( 'anames', 'SELECT id, name FROM annames WHERE name NOT IN (''Anna'', ''Angelina'')' ), false, 'set_eq(prepared, select) fail extras', '', ' Extra records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); SELECT * FROM check_test( set_eq( 'SELECT id, name FROM annames WHERE name <> ''Anna''', 'expect' ), false, 'set_eq(select, prepared) fail missing', '', ' Missing records: (44,Anna)' ); SELECT * FROM check_test( set_eq( 'SELECT id, name FROM annames WHERE name NOT IN (''Anna'', ''Angelina'')', 'expect' ), false, 'set_eq(select, prepared) fail missings', '', ' Missing records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); SELECT * FROM check_test( set_eq( 'SELECT id, name FROM names WHERE name ~ ''^(An|Jacob)'' AND name <> ''Anna''', 'SELECT id, name FROM annames' ), false, 'set_eq(select, select) fail extra & missing', '', ' Extra records: (1,Jacob) Missing records: (44,Anna)' ); SELECT * FROM check_test( set_eq( 'SELECT id, name FROM names WHERE name ~ ''^(An|Jacob|Jacks)'' AND name NOT IN (''Anna'', ''Angelina'')', 'SELECT id, name FROM annames' ), false, 'set_eq(select, select) fail extras & missings', '', ' Extra records: [(](1,Jacob|87,Jackson)[)] [(](1,Jacob|87,Jackson)[)] Missing records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); -- Handle failure due to column mismatch. SELECT * FROM check_test( set_eq( 'SELECT 1 AS a, ''foo''::text AS b UNION ALL SELECT 2, ''bar''', 'SELECT ''foo''::text AS a, 1 AS b UNION ALL SELECT ''bar'', 2' ), false, 'set_eq(values, values) fail mismatch', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( set_eq( 'SELECT 1 AS a UNION ALL SELECT 2 AS b', 'SELECT ''foo''::text AS a, 1 AS b UNION ALL SELECT ''bar'', 2' ), false, 'set_eq(values, values) fail column count', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); -- Handle failure with column mismatch with a column type in a schema not in -- the search path. This is a regression. CREATE SCHEMA __myfoo; CREATE DOMAIN __myfoo.text AS TEXT CHECK(TRUE); CREATE TABLE __yowza( foo text, bar __myfoo.text, baz integer ); INSERT INTO __yowza VALUES ('abc', 'xyz', 1); INSERT INTO __yowza VALUES ('def', 'utf', 2); SELECT * FROM check_test( set_eq( 'SELECT foo, bar from __yowza', 'SELECT foo, bar, baz from __yowza' ), false, 'set_eq(sql, sql) fail type schema visibility', '', ' Columns differ between queries: have: (text,__myfoo.text) want: (text,__myfoo.text,integer)' ); /****************************************************************************/ -- Now test bag_eq(). SELECT * FROM check_test( bag_eq( 'anames', 'expect', 'whatever' ), true, 'bag_eq(prepared, prepared, desc)', 'whatever', '' ); SELECT * FROM check_test( bag_eq( 'anames', 'expect' ), true, 'bag_eq(prepared, prepared)', '', '' ); -- Pass a full SQL statement for the prepared statements. SELECT * FROM check_test( bag_eq( 'EXECUTE anames', 'EXECUTE expect' ), true, 'bag_eq(execute, execute)', '', '' ); -- Compare actual SELECT statements. SELECT * FROM check_test( bag_eq( 'SELECT id, name FROM names WHERE name like ''An%''', 'SELECT id, name FROM annames' ), true, 'bag_eq(select, select)', '', '' ); -- Compare with dupes. SELECT * FROM check_test( bag_eq( 'SELECT 1 AS a, ''Anna''::text AS b UNION ALL SELECT 86, ''Angelina'' UNION ALL SELECT 1, ''Anna''', 'SELECT 1 AS a, ''Anna''::text AS b UNION ALL SELECT 1, ''Anna'' UNION ALL SELECT 86, ''Angelina''' ), true, 'bag_eq(dupe values, dupe values)', '', '' ); -- And now some failures. SELECT * FROM check_test( bag_eq( 'anames', 'SELECT id, name FROM annames WHERE name <> ''Anna''' ), false, 'bag_eq(prepared, select) fail extra', '', ' Extra records: (44,Anna)' ); SELECT * FROM check_test( bag_eq( 'anames', 'SELECT id, name FROM annames WHERE name NOT IN (''Anna'', ''Angelina'')' ), false, 'bag_eq(prepared, select) fail extras', '', ' Extra records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); SELECT * FROM check_test( bag_eq( 'SELECT id, name FROM annames WHERE name <> ''Anna''', 'expect' ), false, 'bag_eq(select, prepared) fail missing', '', ' Missing records: (44,Anna)' ); SELECT * FROM check_test( bag_eq( 'SELECT id, name FROM annames WHERE name NOT IN (''Anna'', ''Angelina'')', 'expect' ), false, 'bag_eq(select, prepared) fail missings', '', ' Missing records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); SELECT * FROM check_test( bag_eq( 'SELECT id, name FROM names WHERE name ~ ''^(An|Jacob)'' AND name <> ''Anna''', 'SELECT id, name FROM annames' ), false, 'bag_eq(select, select) fail extra & missing', '', ' Extra records: (1,Jacob) Missing records: (44,Anna)' ); SELECT * FROM check_test( bag_eq( 'SELECT id, name FROM names WHERE name ~ ''^(An|Jacob|Jacks)'' AND name NOT IN (''Anna'', ''Angelina'')', 'SELECT id, name FROM annames' ), false, 'bag_eq(select, select) fail extras & missings', '', ' Extra records: [(](1,Jacob|87,Jackson)[)] [(](1,Jacob|87,Jackson)[)] Missing records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); -- Handle failure due to column mismatch. SELECT * FROM check_test( bag_eq( 'SELECT 1 AS a, ''foo''::text AS b UNION ALL SELECT 2, ''bar''', 'SELECT ''foo''::text AS a, 1 AS b UNION ALL SELECT ''bar'', 2' ), false, 'bag_eq(values, values) fail mismatch', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( bag_eq( 'SELECT 1 AS a UNION ALL SELECT 2 AS b', 'SELECT ''foo''::text AS a, 1 AS b UNION ALL SELECT ''bar'', 2' ), false, 'bag_eq(values, values) fail column count', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); -- Handle failure due to missing dupe. SELECT * FROM check_test( bag_eq( 'SELECT 1 AS a, ''Anna''::text AS b UNION ALL SELECT 86, ''Angelina'' UNION ALL SELECT 1, ''Anna''', 'SELECT 1 AS a, ''Anna''::TEXT AS b UNION ALL SELECT 86, ''Angelina''' ), false, 'bag_eq(values, values) fail missing dupe', '', ' Extra records: (1,Anna)' ); /****************************************************************************/ -- Now test set_eq(). SELECT * FROM check_test( set_ne( 'anames', 'SELECT id, name FROM annames WHERE name <> ''Anna''', 'whatever' ), true, 'set_ne(prepared, select, desc)', 'whatever', '' ); SELECT * FROM check_test( set_ne( 'anames', 'SELECT id, name FROM annames WHERE name <> ''Anna''' ), true, 'set_ne(prepared, select)', '', '' ); SELECT * FROM check_test( set_ne( 'anames', 'expect' ), false, 'set_ne(prepared, prepared) fail', '', '' ); -- Handle fail with column mismatch. SELECT * FROM check_test( set_ne( 'SELECT 1 AS a, ''foo''::text AS b UNION ALL SELECT 2, ''bar''', 'SELECT ''foo''::text AS a, 1 AS b UNION ALL SELECT ''bar'', 2' ), false, 'set_ne fail with column mismatch', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( set_ne( 'SELECT 1 UNION ALL SELECT 2', 'SELECT ''foo''::text AS a, 1 UNION ALL SELECT ''bar'', 2' ), false, 'set_ne fail with different col counts', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); -- Handle fail with a dupe. SELECT * FROM check_test( set_ne( 'SELECT 1 AS a, ''Anna''::text UNION ALL SELECT 86, ''Angelina'' UNION ALL SELECT 1, ''Anna''', 'SELECT 1 AS a, ''Anna''::text UNION ALL SELECT 86, ''Angelina''' ), false, 'set_ne fail with dupe', '', '' ); /****************************************************************************/ -- Now test bag_ne(). SELECT * FROM check_test( bag_ne( 'anames', 'SELECT id, name FROM annames WHERE name <> ''Anna''', 'whatever' ), true, 'bag_ne(prepared, select, desc)', 'whatever', '' ); SELECT * FROM check_test( bag_ne( 'anames', 'SELECT id, name FROM annames WHERE name <> ''Anna''' ), true, 'bag_ne(prepared, select)', '', '' ); SELECT * FROM check_test( bag_ne( 'anames', 'expect' ), false, 'bag_ne(prepared, prepared) fail', '', '' ); SELECT * FROM check_test( bag_ne( 'SELECT 1 AS a, ''foo''::text UNION ALL SELECT 2, ''bar''', 'SELECT ''foo'' AS a, 1 UNION ALL SELECT ''bar'', 2' ), false, 'bag_ne fail with column mismatch', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle pass with a dupe. SELECT * FROM check_test( bag_ne( 'SELECT 1 AS a, ''Anna''::text UNION ALL SELECT 86, ''Angelina'' UNION ALL SELECT 1, ''Anna''', 'SELECT 1 AS a, ''Anna''::text UNION ALL SELECT 86, ''Angelina''' ), true, 'set_ne pass with dupe', '', '' ); -- Handle fail with column mismatch. SELECT * FROM check_test( bag_ne( 'SELECT 1 AS a, ''foo''::text UNION ALL SELECT 2, ''bar''', 'SELECT ''foo'' AS a, 1 UNION ALL SELECT ''bar'', 2' ), false, 'bag_ne fail with column mismatch', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( bag_ne( 'SELECT 1 UNION SELECT 2', 'SELECT ''foo''::text AS a, 1 UNION SELECT ''bar'', 2' ), false, 'bag_ne fail with different col counts', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); /****************************************************************************/ -- Now test results_eq(). PREPARE anames_ord AS SELECT id, name FROM names WHERE name like 'An%' ORDER BY id; PREPARE expect_ord AS SELECT id, name FROM toexpect ORDER BY id; SELECT * FROM check_test( results_eq( 'anames_ord', 'expect_ord', 'whatever' ), true, 'results_eq(prepared, prepared, desc)', 'whatever', '' ); SELECT * FROM check_test( results_eq( 'anames_ord', 'expect_ord' ), true, 'results_eq(prepared, prepared)', '', '' ); -- Pass a full SQL statement for the prepared statements. SELECT * FROM check_test( results_eq( 'EXECUTE anames_ord', 'EXECUTE expect_ord' ), true, 'results_eq(execute, execute)', '', '' ); -- Compare actual SELECT statements. SELECT * FROM check_test( results_eq( 'SELECT id, name FROM names WHERE name like ''An%'' ORDER BY id', 'SELECT id, name FROM annames ORDER BY id' ), true, 'results_eq(select, select)', '', '' ); -- Compare with dupes. SET client_min_messages = warning; CREATE table dupes (pk SERIAL PRIMARY KEY, id int, name text); RESET client_min_messages; INSERT INTO dupes (id, name) VALUES(1, 'Anna'); INSERT INTO dupes (id, name) VALUES(86, 'Angelina'); INSERT INTO dupes (id, name) VALUES(1, 'Anna'); SELECT * FROM check_test( results_eq( 'SELECT id, name FROM dupes ORDER BY pk', 'SELECT id, name FROM dupes ORDER BY pk' ), true, 'results_eq(dupe values, dupe values)', '', '' ); UPDATE dupes SET name = NULL WHERE pk = 1; -- Compare with nulls. SELECT * FROM check_test( results_eq( 'SELECT id, name FROM dupes ORDER BY pk', 'SELECT id, name FROM dupes ORDER BY pk' ), true, 'results_eq(values with null, values with null)', '', '' ); UPDATE dupes SET id = NULL, name = NULL; -- Compare only NULLs SELECT * FROM check_test( results_eq( 'SELECT id, name FROM dupes LIMIT 2', 'SELECT id, name FROM dupes LIMIT 2' ), true, 'results_eq(nulls, nulls)', '', '' ); -- Compare differnt rows of NULLs SELECT * FROM check_test( results_eq( 'SELECT id, name FROM dupes LIMIT 2', 'SELECT id, name FROM dupes LIMIT 1' ), false, 'results_eq(nulls, nulls) fail', '', ' Results differ beginning at row 2: have: (,) want: NULL' ); -- And now some failures. SELECT * FROM check_test( results_eq( 'anames_ord', 'SELECT id, name FROM annames WHERE name <> ''Anna''' ), false, 'results_eq(prepared, select) fail', '', ' Results differ beginning at row 3: have: (44,Anna) want: (63,Angel)' ); -- Now when the last row is missing. SELECT * FROM check_test( results_eq( 'SELECT id, name FROM annames WHERE name <> ''Antonio''', 'anames_ord' ), false, 'results_eq(select, prepared) fail missing last row', '', ' Results differ beginning at row 7: have: NULL want: (183,Antonio)' ); -- Invert that. SELECT * FROM check_test( results_eq( 'anames_ord', 'SELECT id, name FROM annames WHERE name <> ''Antonio''' ), false, 'results_eq(prepared, select) fail missing first row', '', ' Results differ beginning at row 7: have: (183,Antonio) want: NULL' ); -- Compare with missing dupe. SET client_min_messages = warning; CREATE table dubs (pk SERIAL PRIMARY KEY, id int, name text); RESET client_min_messages; INSERT INTO dubs (id, name) VALUES(1, 'Anna'); INSERT INTO dubs (id, name) VALUES(86, 'Angelina'); INSERT INTO dubs (id, name) VALUES(1, 'Anna'); SELECT * FROM check_test( results_eq( 'SELECT id, name from dubs ORDER BY pk', 'SELECT id, name from dubs ORDER BY pk LIMIT 2' ), false, 'results_eq(values dupe, values)', '', ' Results differ beginning at row 3: have: (1,Anna) want: NULL' ); UPDATE dubs SET name = NULL WHERE pk = 1; -- Handle failure with null. SELECT * FROM check_test( results_eq( 'SELECT id, name from dubs ORDER BY pk LIMIT 2', 'SELECT id, name from dubs ORDER BY pk DESC LIMIT 2' ), false, 'results_eq(values null, values)', '', ' Results differ beginning at row 1: have: (1,) want: (1,Anna)' ); UPDATE dubs SET name = 'foo' WHERE pk = 1; UPDATE dubs SET name = 'bar' WHERE pk = 2; -- Handle failure due to column mismatch. SELECT * FROM check_test( results_eq( 'SELECT pk, name from dubs ORDER BY pk LIMIT 2', 'SELECT name, pk from dubs ORDER BY pk LIMIT 2' ), false, 'results_eq(values, values) mismatch', '', CASE WHEN pg_version_num() < 80400 THEN ' Results differ beginning at row 1:' ELSE ' Columns differ between queries:' END || ' have: (1,foo) want: (foo,1)' ); -- Handle failure due to more subtle column mismatch, valid only on 8.4. CREATE OR REPLACE FUNCTION subtlefail() RETURNS SETOF TEXT AS $$ DECLARE tap record; BEGIN IF pg_version_num() < 80400 THEN -- 8.3 and earlier cast records to text, so subtlety is out. RETURN NEXT pass('results_eq(values, values) subtle mismatch should fail'); RETURN NEXT pass('results_eq(values, values) subtle mismatch should have the proper description'); RETURN NEXT pass('results_eq(values, values) subtle mismatch should have the proper diagnostics'); ELSE -- 8.4 does true record comparisions, yay! FOR tap IN SELECT * FROM check_test( results_eq( 'VALUES (1, ''foo''::varchar), (2, ''bar''::varchar)', 'VALUES (1, ''foo''), (2, ''bar'')' ), false, 'results_eq(values, values) subtle mismatch', '', ' Columns differ between queries: have: (1,foo) want: (1,foo)' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; END IF; RETURN; END; $$ LANGUAGE plpgsql; SELECT * FROM subtlefail(); -- Handle failure due to column count mismatch. SELECT * FROM check_test( results_eq( 'SELECT pk from dubs ORDER BY pk LIMIT 2', 'SELECT name, pk from dubs ORDER BY pk LIMIT 2' ), false, 'results_eq(values, values) fail column count', '', CASE WHEN pg_version_num() < 80400 THEN ' Results differ beginning at row 1:' ELSE ' Columns differ between queries:' END || ' have: (1) want: (foo,1)' ); -- Compare with cursors. DECLARE cwant CURSOR FOR SELECT id, name FROM names WHERE name like 'An%' ORDER BY id; DECLARE chave CURSOR FOR SELECT id, name from annames ORDER BY id; SELECT * FROM check_test( results_eq( 'cwant'::refcursor, 'chave'::refcursor ), true, 'results_eq(cursor, cursor)', '', '' ); -- Mix cursors and prepared statements PREPARE annames_ord AS SELECT id, name FROM annames ORDER BY id; MOVE BACKWARD ALL IN cwant; SELECT * FROM check_test( results_eq( 'cwant'::refcursor, 'annames_ord' ), true, 'results_eq(cursor, prepared)', '', '' ); MOVE BACKWARD ALL IN chave; SELECT * FROM check_test( results_eq( 'annames_ord', 'chave'::refcursor ), true, 'results_eq(prepared, cursor)', '', '' ); -- Mix cursor and SQL. MOVE BACKWARD ALL IN cwant; SELECT * FROM check_test( results_eq( 'cwant'::refcursor, 'SELECT id, name FROM annames ORDER BY id' ), true, 'results_eq(cursor, sql)', '', '' ); MOVE BACKWARD ALL IN chave; SELECT * FROM check_test( results_eq( 'SELECT id, name FROM annames ORDER BY id', 'chave'::refcursor ), true, 'results_eq(sql, cursor)', '', '' ); /****************************************************************************/ -- Now test set_has(). SELECT * FROM check_test( set_has( 'anames', 'expect', 'whatever' ), true, 'set_has( prepared, prepared, description )', 'whatever', '' ); PREPARE subset AS SELECT id, name FROM toexpect WHERE id IN (11, 44, 63); SELECT * FROM check_test( set_has( 'anames', 'subset' ), true, 'set_has( prepared, subprepared )', '', '' ); SELECT * FROM check_test( set_has( 'EXECUTE anames', 'EXECUTE subset' ), true, 'set_has( execute, execute )', '', '' ); -- Compare actual SELECT statements. SELECT * FROM check_test( set_has( 'SELECT id, name FROM names WHERE name like ''An%''', 'SELECT id, name FROM annames' ), true, 'set_has( select, select )', '', '' ); -- Try an empty set in the second arg. SELECT * FROM check_test( set_has( 'anames', 'SELECT id, name FROM annames WHERE false' ), true, 'set_has( prepared, empty )', '', '' ); -- Make sure that dupes are ignored. SELECT * FROM check_test( set_has( 'anames', 'SELECT 44 AS a, ''Anna''::text UNION ALL SELECT 44, ''Anna''' ), true, 'set_has( prepared, dupes )', '', '' ); SELECT * FROM check_test( set_has( 'SELECT 44 AS a, ''Anna''::text UNION ALL SELECT 44, ''Anna''', 'SELECT 44 AS a, ''Anna''::text' ), true, 'set_has( dupes, values )', '', '' ); -- Check failures. SELECT * FROM check_test( set_has( 'SELECT id, name FROM annames WHERE name <> ''Anna''', 'expect' ), false, 'set_has( missing1, expect )', '', ' Missing records: (44,Anna)' ); SELECT * FROM check_test( set_has( 'SELECT id, name FROM annames WHERE name NOT IN (''Anna'', ''Angelina'')', 'expect' ), false, 'set_has(missing2, expect )', '', ' Missing records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); -- Handle failure due to column mismatch. SELECT * FROM check_test( set_has( 'SELECT 1 AS a, ''foo''::text UNION ALL SELECT 2, ''bar''', 'SELECT ''foo''::text AS a, 1 UNION ALL SELECT ''bar'', 2' ), false, 'set_has((int,text), (text,int))', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( set_has( 'SELECT 1 UNION SELECT 2', 'SELECT ''foo''::text AS a, 1 UNION SELECT ''bar'', 2' ), false, 'set_has((int), (text,int))', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); /****************************************************************************/ -- Now test bag_has(). SELECT * FROM check_test( bag_has( 'anames', 'expect', 'whatever' ), true, 'bag_has( prepared, prepared, description )', 'whatever', '' ); SELECT * FROM check_test( bag_has( 'anames', 'subset' ), true, 'bag_has( prepared, subprepared )', '', '' ); SELECT * FROM check_test( bag_has( 'EXECUTE anames', 'EXECUTE subset' ), true, 'bag_has( execute, execute )', '', '' ); -- Compare actual SELECT statements. SELECT * FROM check_test( bag_has( 'SELECT id, name FROM names WHERE name like ''An%''', 'SELECT id, name FROM annames' ), true, 'bag_has( select, select )', '', '' ); -- Try an empty set in the second arg. SELECT * FROM check_test( bag_has( 'anames', 'SELECT id, name FROM annames WHERE false' ), true, 'bag_has( prepared, empty )', '', '' ); -- Make sure that dupes are not ignored. SELECT * FROM check_test( bag_has( 'anames', 'SELECT 44 AS a, ''Anna''::text UNION ALL SELECT 44, ''Anna''' ), false, 'bag_has( prepared, dupes )', '', ' Missing records: (44,Anna)' ); SELECT * FROM check_test( bag_has( 'SELECT 44 AS a, ''Anna''::text UNION ALL SELECT 44, ''Anna''', 'SELECT 44 AS a, ''Anna''::text' ), true, 'bag_has( dupes, values )', '', '' ); SELECT * FROM check_test( bag_has( 'SELECT id, name FROM annames WHERE name <> ''Anna''', 'expect' ), false, 'bag_has( missing1, expect )', '', ' Missing records: (44,Anna)' ); SELECT * FROM check_test( bag_has( 'SELECT id, name FROM annames WHERE name NOT IN (''Anna'', ''Angelina'')', 'expect' ), false, 'bag_has(missing2, expect )', '', ' Missing records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); -- Handle failure due to column mismatch. SELECT * FROM check_test( bag_has( 'SELECT 1 AS a, ''foo''::text UNION SELECT 2, ''bar''', 'SELECT ''foo''::text AS a, 1 UNION SELECT ''bar'', 2' ), false, 'bag_has((int,text), (text,int))', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( bag_has( 'SELECT 1 UNION SELECT 2', 'SELECT ''foo''::text AS a, 1 UNION SELECT ''bar'', 2' ), false, 'bag_has((int), (text,int))', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); /****************************************************************************/ -- Now test set_hasnt(). CREATE TABLE folk (id int, name text); INSERT INTO folk (id, name) VALUES ( 44, 'Larry' ); INSERT INTO folk (id, name) VALUES (52, 'Tom'); INSERT INTO folk (id, name) VALUES (23, 'Damian' ); PREPARE others AS SELECT id, name FROM folk; SELECT * FROM check_test( set_hasnt( 'anames', 'others', 'whatever' ), true, 'set_hasnt( prepared, prepared, description )', 'whatever', '' ); SELECT * FROM check_test( set_hasnt( 'anames', 'others' ), true, 'set_hasnt( prepared, prepared, description )', '', '' ); SELECT * FROM check_test( set_hasnt( 'EXECUTE anames', 'EXECUTE others' ), true, 'set_hasnt( execute, execute )', '', '' ); -- Compare actual SELECT statements. SELECT * FROM check_test( set_hasnt( 'SELECT id, name FROM names WHERE name like ''An%''', 'SELECT id, name FROM names WHERE name like ''B%''' ), true, 'set_hasnt( select, select )', '', '' ); -- Try an empty set in the second arg. SELECT * FROM check_test( set_hasnt( 'anames', 'SELECT id, name FROM annames WHERE false' ), true, 'set_hasnt( prepared, empty )', '', '' ); -- Make sure that dupes are ignored. SELECT * FROM check_test( set_hasnt( 'anames', 'SELECT 44 AS a, ''Bob''::text UNION ALL SELECT 44, ''Bob''' ), true, 'set_hasnt( prepared, dupes )', '', '' ); SELECT * FROM check_test( set_hasnt( 'anames', 'SELECT 44 AS a, ''Anna''::text' ), false, 'set_hasnt( prepared, value )', '', ' Extra records: (44,Anna)' ); SELECT * FROM check_test( set_hasnt( 'anames', 'SELECT 44 AS a, ''Anna''::text UNION SELECT 86, ''Angelina''' ), false, 'set_hasnt( prepared, values )', '', ' Extra records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); -- Handle failure due to column mismatch. SELECT * FROM check_test( set_hasnt( 'SELECT 1 AS a, ''foo''::text UNION SELECT 2, ''bar''', 'SELECT ''foo''::text AS a, 1 UNION SELECT ''bar'', 2' ), false, 'set_hasnt((int,text), (text,int))', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( set_hasnt( 'SELECT 1 UNION SELECT 2', 'SELECT ''foo''::text AS a, 1 UNION SELECT ''bar'', 2' ), false, 'set_hasnt((int), (text,int))', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); /****************************************************************************/ -- Now test bag_hasnt(). SELECT * FROM check_test( bag_hasnt( 'anames', 'others', 'whatever' ), true, 'bag_hasnt( prepared, prepared, description )', 'whatever', '' ); SELECT * FROM check_test( bag_hasnt( 'anames', 'others' ), true, 'bag_hasnt( prepared, prepared, description )', '', '' ); SELECT * FROM check_test( bag_hasnt( 'EXECUTE anames', 'EXECUTE others' ), true, 'bag_hasnt( execute, execute )', '', '' ); -- Compare actual SELECT statements. SELECT * FROM check_test( bag_hasnt( 'SELECT id, name FROM names WHERE name like ''An%''', 'SELECT id, name FROM names WHERE name like ''B%''' ), true, 'bag_hasnt( select, select )', '', '' ); -- Try an empty bag in the second arg. SELECT * FROM check_test( bag_hasnt( 'anames', 'SELECT id, name FROM annames WHERE false' ), true, 'bag_hasnt( prepared, empty )', '', '' ); SELECT * FROM check_test( bag_hasnt( 'anames', 'SELECT 44 AS a, ''Anna''::text' ), false, 'bag_hasnt( prepared, value )', '', ' Extra records: (44,Anna)' ); SELECT * FROM check_test( bag_hasnt( 'anames', 'SELECT 44 AS a, ''Anna''::text UNION SELECT 86, ''Angelina''' ), false, 'bag_hasnt( prepared, values )', '', ' Extra records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); -- Handle failure due to column mismatch. SELECT * FROM check_test( bag_hasnt( 'SELECT 1 AS a, ''foo''::text UNION SELECT 2, ''bar''', 'SELECT ''foo''::text AS a, 1 UNION SELECT ''bar'', 2' ), false, 'bag_hasnt((int,text), (text,int))', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( bag_hasnt( 'SELECT 1 UNION SELECT 2', 'SELECT ''foo''::text AS a, 1 UNION SELECT ''bar'', 2' ), false, 'bag_hasnt((int), (text,int))', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); -- Make sure that dupes are not ignored. SELECT * FROM check_test( bag_hasnt( 'SELECT 44 AS a, ''Anna''::text UNION ALL SELECT 44, ''Anna''', 'SELECT 44 AS a, ''Anna''::text UNION ALL SELECT 44, ''Anna''' ), false, 'bag_hasnt( dupes, dupes )', '', ' Extra records: (44,Anna) (44,Anna)' ); -- But a dupe that appears only once should be in the list only once. SELECT * FROM check_test( bag_hasnt( 'SELECT 44 AS a, ''Anna''::text', 'SELECT 44 AS a, ''Anna''::text UNION ALL SELECT 44, ''Anna''' ), false, 'bag_hasnt( value, dupes )', '', ' Extra records: (44,Anna)' ); /****************************************************************************/ -- Test set_eq() with an array argument. SELECT * FROM check_test( set_eq( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ], 'whatever' ), true, 'set_eq(sql, array, desc)', 'whatever', '' ); SELECT * FROM check_test( set_eq( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), true, 'set_eq(sql, array)', '', '' ); SELECT * FROM check_test( set_eq( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel', 'Andrew', 'Anna' ] ), true, 'set_eq(sql, dupe array)', '', '' ); -- Fail with an extra record. SELECT * FROM check_test( set_eq( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'set_eq(sql, array) extra record', '', ' Extra records: (Anthony)' ); -- Fail with a missing record. SELECT * FROM check_test( set_eq( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Anthony', 'Alan', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'set_eq(sql, array) missing record', '', ' Missing records: (Alan)' ); -- Fail with incompatible columns. SELECT * FROM check_test( set_eq( 'SELECT name FROM names WHERE name like ''An%''', ARRAY[1, 2, 3] ), false, 'set_eq(sql, array) incompatible types', '', ' Columns differ between queries: have: (text) want: (integer)' ); -- Fail with invalid column counts. SELECT * FROM check_test( set_eq( 'anames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'set_eq(sql, array) incompatible types', '', ' Columns differ between queries: have: (integer,text) want: (text)' ); /****************************************************************************/ -- Test bag_eq() with an array argument. SELECT * FROM check_test( bag_eq( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ], 'whatever' ), true, 'bag_eq(sql, array, desc)', 'whatever', '' ); SELECT * FROM check_test( bag_eq( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), true, 'bag_eq(sql, array)', '', '' ); SELECT * FROM check_test( bag_eq( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel', 'Anna' ] ), false, 'bag_eq(sql, dupe array) fail', '', ' Missing records: (Anna)' ); -- Fail with an extra record. SELECT * FROM check_test( bag_eq( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'bag_eq(sql, array) extra record', '', ' Extra records: (Anthony)' ); -- Fail with a missing record. SELECT * FROM check_test( bag_eq( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Anthony', 'Alan', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'bag_eq(sql, array) missing record', '', ' Missing records: (Alan)' ); -- Fail with incompatible columns. SELECT * FROM check_test( bag_eq( 'SELECT name FROM names WHERE name like ''An%''', ARRAY[1, 2, 3] ), false, 'bag_eq(sql, array) incompatible types', '', ' Columns differ between queries: have: (text) want: (integer)' ); -- Fail with invalid column counts. SELECT * FROM check_test( bag_eq( 'anames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'bag_eq(sql, array) incompatible types', '', ' Columns differ between queries: have: (integer,text) want: (text)' ); /****************************************************************************/ -- Test set_ne() with an array argument. SELECT * FROM check_test( set_ne( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna' ], 'whatever' ), true, 'set_ne(sql, array, desc)', 'whatever', '' ); SELECT * FROM check_test( set_ne( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna' ] ), true, 'set_ne(sql, array)', '', '' ); SELECT * FROM check_test( set_ne( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'set_ne(sql, array) fail', '', '' ); -- Fail with dupes. SELECT * FROM check_test( set_ne( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel', 'Anna' ] ), false, 'set_ne(sql, dupes array) fail', '', '' ); -- Fail with incompatible columns. SELECT * FROM check_test( set_ne( 'SELECT name FROM names WHERE name like ''An%''', ARRAY[1, 2, 3] ), false, 'set_ne(sql, array) incompatible types', '', ' Columns differ between queries: have: (text) want: (integer)' ); -- Fail with invalid column counts. SELECT * FROM check_test( set_ne( 'anames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'set_ne(sql, array) incompatible types', '', ' Columns differ between queries: have: (integer,text) want: (text)' ); /****************************************************************************/ -- Test bag_ne() with an array argument. SELECT * FROM check_test( bag_ne( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna' ], 'whatever' ), true, 'bag_ne(sql, array, desc)', 'whatever', '' ); SELECT * FROM check_test( bag_ne( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna' ] ), true, 'bag_ne(sql, array)', '', '' ); SELECT * FROM check_test( bag_ne( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'bag_ne(sql, array) fail', '', '' ); -- Pass with dupes. SELECT * FROM check_test( bag_ne( 'SELECT name FROM names WHERE name like ''An%''', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel', 'Anna' ] ), true, 'bag_ne(sql, dupes array)', '', '' ); -- Fail with incompatible columns. SELECT * FROM check_test( bag_ne( 'SELECT name FROM names WHERE name like ''An%''', ARRAY[1, 2, 3] ), false, 'bag_ne(sql, array) incompatible types', '', ' Columns differ between queries: have: (text) want: (integer)' ); -- Fail with invalid column counts. SELECT * FROM check_test( bag_ne( 'anames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'bag_ne(sql, array) incompatible types', '', ' Columns differ between queries: have: (integer,text) want: (text)' ); /****************************************************************************/ -- Now test results_eq() with an array argument. PREPARE anames_only AS SELECT name FROM names WHERE name like 'An%' ORDER BY name; SELECT * FROM check_test( results_eq( 'anames_only', ARRAY['Andrea', 'Andrew', 'Angel', 'Angelina', 'Anna', 'Anthony', 'Antonio' ], 'whatever' ), true, 'results_eq(prepared, array, desc)', 'whatever', '' ); SELECT * FROM check_test( results_eq( 'anames_only', ARRAY['Andrea', 'Andrew', 'Angel', 'Angelina', 'Anna', 'Anthony', 'Antonio' ] ), true, 'results_eq(prepared, array)', '', '' ); SELECT * FROM check_test( results_eq( 'SELECT name FROM names WHERE name like ''An%'' ORDER BY name', ARRAY['Andrea', 'Andrew', 'Angel', 'Angelina', 'Anna', 'Anthony', 'Antonio' ], 'whatever' ), true, 'results_eq(sql, array, desc)', 'whatever', '' ); SELECT * FROM check_test( results_eq( 'SELECT name FROM names WHERE name like ''An%'' ORDER BY name', ARRAY['Andrea', 'Andrew', 'Angel', 'Angelina', 'Anna', 'Anthony', 'Antonio' ] ), true, 'results_eq(sql, array, desc)', '', '' ); SELECT * FROM check_test( results_eq( 'anames_only', ARRAY['Andrea', 'Andrew', 'Angel', 'Angelina', 'Anna', 'Anthony' ] ), false, 'results_eq(prepared, array) extra record', '', ' Results differ beginning at row 7: have: (Antonio) want: NULL' ); SELECT * FROM check_test( results_eq( 'SELECT name FROM names WHERE name like ''An%'' AND name <> ''Anna'' ORDER BY name', ARRAY['Andrea', 'Andrew', 'Angel', 'Angelina', 'Anna', 'Anthony', 'Antonio' ] ), false, 'results_eq(select, array) missing record', '', ' Results differ beginning at row 5: have: (Anthony) want: (Anna)' ); /****************************************************************************/ -- Now test results_eq(). PREPARE nenames_ord AS SELECT id, name FROM names WHERE name like 'An%' ORDER BY id; SET client_min_messages = warning; CREATE TEMPORARY TABLE nord (pk SERIAL PRIMARY KEY, id int, name text); RESET client_min_messages; INSERT INTO nord (id, name ) VALUES(15, 'Anthony'); INSERT INTO nord (id, name ) VALUES(44, 'Anna'); INSERT INTO nord (id, name ) VALUES(11, 'Andrew'); INSERT INTO nord (id, name ) VALUES(63, 'Angel'); INSERT INTO nord (id, name ) VALUES(86, 'Angelina'); INSERT INTO nord (id, name ) VALUES(130, 'Andrea'); INSERT INTO nord (id, name ) VALUES(183, 'Antonio'); PREPARE nexpect_ord AS SELECT id, name FROM nord ORDER BY pk; SELECT * FROM check_test( results_ne( 'nenames_ord', 'nexpect_ord', 'whatever' ), true, 'results_ne(prepared, prepared, desc)', 'whatever', '' ); SELECT * FROM check_test( results_ne( 'nenames_ord', 'nexpect_ord' ), true, 'results_ne(prepared, prepared)', '', '' ); -- Pass a full SQL statement for the prepared statements. SELECT * FROM check_test( results_ne( 'EXECUTE nenames_ord', 'EXECUTE nexpect_ord' ), true, 'results_ne(execute, execute)', '', '' ); -- Compare actual SELECT statements. SELECT * FROM check_test( results_ne( 'SELECT id, name FROM names WHERE name like ''An%'' ORDER BY id', 'SELECT id, name FROM annames WHERE name <> ''Anna'' ORDER BY id' ), true, 'results_ne(select, select)', '', '' ); UPDATE dubs SET name = 'Anna' WHERE pk = 1; UPDATE dubs SET name = 'Angelina', id = 86 WHERE pk = 2; SET client_min_messages = warning; CREATE table buds (pk SERIAL PRIMARY KEY, id int, name text); RESET client_min_messages; INSERT INTO buds (id, name) VALUES(2, 'Anna'); INSERT INTO buds (id, name) VALUES(86, 'Angelina'); INSERT INTO buds (id, name) VALUES(2, 'Anna'); -- Compare with dupes. SELECT * FROM check_test( results_ne( 'SELECT id, name FROM dubs ORDER BY pk', 'SELECT id, name FROM buds ORDER BY pk' ), true, 'results_ne(dupe values, dupe values)', '', '' ); UPDATE dubs SET id = 4, name = NULL WHERE pk = 1; UPDATE dubs SET name = NULL WHERE pk = 3; UPDATE buds SET id = 4, name = NULL WHERE pk = 1; -- Compare with nulls. SELECT * FROM check_test( results_ne( 'SELECT id, name FROM dubs ORDER BY pk', 'SELECT id, name FROM buds ORDER BY pk' ), true, 'results_ne(values with null, values with null)', '', '' ); -- Compare only NULLs SELECT * FROM check_test( results_ne( 'SELECT id, name FROM dupes LIMIT 3', 'SELECT id, name FROM dupes LIMIT 2' ), true, 'results_ne(nulls, nulls)', '', '' ); -- And now a failure. SELECT * FROM check_test( results_ne( 'nenames_ord', 'SELECT id, name FROM annames' ), false, 'results_ne(prepared, select) fail', '', '' ); -- Now when the last row is missing. SELECT * FROM check_test( results_ne( 'SELECT id, name FROM annames WHERE name <> ''Antonio''', 'nenames_ord' ), true, 'results_ne(select, prepared) missing last row', '', '' ); -- Invert that. SELECT * FROM check_test( results_ne( 'nenames_ord', 'SELECT id, name FROM annames WHERE name <> ''Antonio''' ), true, 'results_ne(prepared, select) missing first row', '', '' ); UPDATE dubs SET id = 1, name = 'Anna' WHERE pk IN (1, 3); -- Compare with missing dupe. SELECT * FROM check_test( results_ne( 'SELECT id, name FROM dubs ORDER BY pk', 'SELECT id, name FROM dubs ORDER BY pk LIMIT 2' ), true, 'results_ne(values dupe, values)', '', '' ); UPDATE dubs SET name = NULL where PK = 2; -- Handle pass with null. SELECT * FROM check_test( results_ne( 'SELECT id, name FROM dubs ORDER BY pk LIMIT 2', 'SELECT id, name FROM buds ORDER BY pk LIMIT 2' ), true, 'results_ne(values null, values)', '', '' ); -- Handle failure due to more subtle column mismatch, valid only on 8.4. CREATE OR REPLACE FUNCTION subtlefail() RETURNS SETOF TEXT AS $$ DECLARE tap record; BEGIN IF pg_version_num() < 80400 THEN -- 8.3 and earlier cast records to text, so subtlety is out. RETURN NEXT pass('results_ne(values, values) mismatch should fail'); RETURN NEXT pass('results_ne(values, values) mismatch should have the proper description'); RETURN NEXT pass('results_ne(values, values) mismatch should have the proper diagnostics'); RETURN NEXT pass('results_ne(values, values) subtle mismatch should fail'); RETURN NEXT pass('results_ne(values, values) subtle mismatch should have the proper description'); RETURN NEXT pass('results_ne(values, values) subtle mismatch should have the proper diagnostics'); RETURN NEXT pass('results_ne(values, values) fail column count should fail'); RETURN NEXT pass('results_ne(values, values) fail column count should have the proper description'); RETURN NEXT pass('results_ne(values, values) fail column count should have the proper diagnostics'); ELSE -- 8.4 does true record comparisions, yay! -- Handle failure due to column mismatch. FOR tap IN SELECT * FROM check_test( results_ne( 'VALUES (1, ''foo''), (2, ''bar'')', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'results_ne(values, values) mismatch', '', ' Columns differ between queries: have: (1,foo) want: (foo,1)' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; -- Handle failure due to subtle column mismatch. FOR tap IN SELECT * FROM check_test( results_ne( 'VALUES (1, ''foo''::varchar), (2, ''bar''::varchar)', 'VALUES (1, ''foo''), (2, ''bar'')' ), false, 'results_ne(values, values) subtle mismatch', '', ' Columns differ between queries: have: (1,foo) want: (1,foo)' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; -- Handle failure due to column count mismatch. FOR tap IN SELECT * FROM check_test( results_ne( 'VALUES (1), (2)', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'results_ne(values, values) fail column count', '', ' Columns differ between queries: have: (1) want: (foo,1)' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; END IF; RETURN; END; $$ LANGUAGE plpgsql; SELECT * FROM subtlefail(); -- Compare with cursors. CLOSE cwant; CLOSE chave; DECLARE cwant CURSOR FOR SELECT id, name FROM names WHERE name like 'An%' ORDER BY id; DECLARE chave CURSOR FOR SELECT id, name from annames ORDER BY id; SELECT * FROM check_test( results_ne( 'cwant'::refcursor, 'chave'::refcursor ), false, 'results_ne(cursor, cursor)', '', '' ); -- Mix cursors and prepared statements DEALLOCATE annames_ord; PREPARE annames_ord AS SELECT id, name FROM annames ORDER BY id; MOVE BACKWARD ALL IN cwant; SELECT * FROM check_test( results_ne( 'cwant'::refcursor, 'annames_ord' ), false, 'results_ne(cursor, prepared)', '', '' ); MOVE BACKWARD ALL IN chave; SELECT * FROM check_test( results_ne( 'annames_ord', 'chave'::refcursor ), false, 'results_ne(prepared, cursor)', '', '' ); -- Mix cursor and SQL. SELECT * FROM check_test( results_ne( 'cwant'::refcursor, 'SELECT id, name FROM annames ORDER BY id' ), true, 'results_ne(cursor, sql)', '', '' ); MOVE BACKWARD ALL IN chave; SELECT * FROM check_test( results_ne( 'SELECT id, name FROM annames ORDER BY id', 'chave'::refcursor ), false, 'results_ne(sql, cursor)', '', '' ); /****************************************************************************/ -- Now test is_empty(). SELECT * FROM check_test( is_empty( 'SELECT 1 WHERE FALSE', 'whatever' ), true, 'is_empty(sql, desc)', 'whatever', '' ); SELECT * FROM check_test( is_empty( 'SELECT 1 WHERE FALSE' ), true, 'is_empty(sql)', '', '' ); PREPARE emptyset AS SELECT * FROM names WHERE FALSE; SELECT * FROM check_test( is_empty( 'emptyset', 'whatever' ), true, 'is_empty(prepared, desc)', 'whatever', '' ); SELECT * FROM check_test( is_empty( 'emptyset' ), true, 'is_empty(prepared)', '', '' ); CREATE FUNCTION test_empty_fail() RETURNS SETOF TEXT AS $$ DECLARE tap record; BEGIN IF pg_version_num() < 80100 THEN -- Can't do shit with records on 8.0 RETURN NEXT pass('is_empty(prepared, desc) fail should fail'); RETURN NEXT pass('is_empty(prepared, desc) fail should have the proper description'); RETURN NEXT pass('is_empty(prepared, desc) fail should have the proper diagnostics'); RETURN NEXT pass('is_empty(prepared) fail should fail'); RETURN NEXT pass('is_empty(prepared) fail should have the proper description'); RETURN NEXT pass('is_empty(prepared) fail should have the proper diagnostics'); ELSE PREPARE notempty AS SELECT id, name FROM names WHERE name IN ('Jacob', 'Emily') ORDER BY ID; FOR tap IN SELECT * FROM check_test( is_empty( 'notempty', 'whatever' ), false, 'is_empty(prepared, desc) fail', 'whatever', ' Unexpected records: (1,Jacob) (2,Emily)' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( is_empty( 'notempty' ), false, 'is_empty(prepared) fail', '', ' Unexpected records: (1,Jacob) (2,Emily)' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; END IF; RETURN; END; $$ LANGUAGE PLPGSQL; SELECT * FROM test_empty_fail(); /****************************************************************************/ -- Test row_eq(). PREPARE arow AS SELECT id, name FROM names WHERE name = 'Jacob'; CREATE TYPE sometype AS ( id INT, name TEXT ); CREATE FUNCTION test_row_eq() RETURNS SETOF TEXT AS $$ DECLARE tap record; BEGIN IF pg_version_num() < 80100 THEN -- Can't do shit with records on 8.0 RETURN NEXT pass('row_eq(prepared, record, desc) should pass'); RETURN NEXT pass('row_eq(prepared, record, desc) should have the proper description'); RETURN NEXT pass('row_eq(prepared, record, desc) should have the proper diagnostics'); RETURN NEXT pass('row_eq(sql, record, desc) should pass'); RETURN NEXT pass('row_eq(sql, record, desc) should have the proper description'); RETURN NEXT pass('row_eq(sql, record, desc) should have the proper diagnostics'); RETURN NEXT pass('row_eq(prepared, record, desc) should pass'); RETURN NEXT pass('row_eq(prepared, record, desc) should have the proper description'); RETURN NEXT pass('row_eq(prepared, record, desc) should have the proper diagnostics'); RETURN NEXT pass('row_eq(prepared, record, desc) should fail'); RETURN NEXT pass('row_eq(prepared, record, desc) should have the proper description'); RETURN NEXT pass('row_eq(prepared, record, desc) should have the proper diagnostics'); RETURN NEXT pass('row_eq(prepared, sometype, desc) should pass'); RETURN NEXT pass('row_eq(prepared, sometype, desc) should have the proper description'); RETURN NEXT pass('row_eq(prepared, sometype, desc) should have the proper diagnostics'); RETURN NEXT pass('row_eq(sqlrow, sometype, desc) should pass'); RETURN NEXT pass('row_eq(sqlrow, sometype, desc) should have the proper description'); RETURN NEXT pass('row_eq(sqlrow, sometype, desc) should have the proper diagnostics'); RETURN NEXT pass('threw 0A000'); ELSE FOR tap IN SELECT * FROM check_test( row_eq('arow', ROW(1, 'Jacob')::names, 'whatever'), true, 'row_eq(prepared, record, desc)', 'whatever', '' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( row_eq('SELECT id, name FROM names WHERE id = 1', ROW(1, 'Jacob')::names, 'whatever'), true, 'row_eq(sql, record, desc)', 'whatever', '' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( row_eq('arow', ROW(1, 'Jacob')::names), true, 'row_eq(prepared, record, desc)', '', '' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( row_eq('arow', ROW(1, 'Larry')::names), false, 'row_eq(prepared, record, desc)', '', ' have: (1,Jacob) want: (1,Larry)' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( row_eq('arow', ROW(1, 'Jacob')::sometype), true, 'row_eq(prepared, sometype, desc)', '', '' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; FOR tap IN SELECT * FROM check_test( row_eq('SELECT 1, ''Jacob''::text', ROW(1, 'Jacob')::sometype), true, 'row_eq(sqlrow, sometype, desc)', '', '' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; INSERT INTO someat (ts) values ('2009-12-04T07:22:52'); RETURN NEXT throws_ok( 'SELECT row_eq( ''SELECT id, ts FROM someat'', ROW(1, ''2009-12-04T07:22:52'') )', '0A000' -- 'PL/pgSQL functions cannot accept type record' ); -- FOR tap IN SELECT * FROM check_test( -- row_eq( 'SELECT id, ts FROM someat', ROW(1, '2009-12-04T07:22:52') ), -- true, -- 'row_eq(sql, rec)', -- '', -- '' -- ) AS a(b) LOOP -- RETURN NEXT tap.b; -- END LOOP; END IF; RETURN; END; $$ LANGUAGE plpgsql; SELECT * FROM test_row_eq(); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._roletap.sql000644 000765 000024 00000000252 11666501762 017340 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/roletap.sql000644 000765 000024 00000005477 11666501762 017141 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(39); --SELECT * FROM no_plan(); /****************************************************************************/ -- Test has_role() and hasnt_role(). SELECT * FROM check_test( has_role(current_role), true, 'has_role(current role)', 'Role ' || quote_ident(current_role) || ' should exist', '' ); SELECT * FROM check_test( has_role(current_role, 'whatever'), true, 'has_role(current role, desc)', 'whatever', '' ); SELECT * FROM check_test( has_role('aoijaoisjfaoidfjaisjdfosjf'), false, 'has_role(nonexistent role)', 'Role aoijaoisjfaoidfjaisjdfosjf should exist', '' ); SELECT * FROM check_test( has_role('aoijaoisjfaoidfjaisjdfosjf', 'desc'), false, 'has_role(nonexistent role, desc)', 'desc', '' ); SELECT * FROM check_test( hasnt_role(current_role), false, 'hasnt_role(current role)', 'Role ' || quote_ident(current_role) || ' should not exist', '' ); SELECT * FROM check_test( hasnt_role(current_role, 'whatever'), false, 'hasnt_role(current role, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_role('aoijaoisjfaoidfjaisjdfosjf'), true, 'hasnt_role(nonexistent role)', 'Role aoijaoisjfaoidfjaisjdfosjf should not exist', '' ); SELECT * FROM check_test( hasnt_role('aoijaoisjfaoidfjaisjdfosjf', 'desc'), true, 'hasnt_role(nonexistent role, desc)', 'desc', '' ); /****************************************************************************/ -- Test roles_are(). CREATE FUNCTION ___myroles(ex text) RETURNS NAME[] AS $$ SELECT COALESCE(ARRAY( SELECT rolname FROM pg_catalog.pg_roles WHERE rolname <> $1 ), '{}'::name[]);; $$ LANGUAGE SQL; SELECT * FROM check_test( roles_are( ___myroles(''), 'whatever' ), true, 'roles_are(roles, desc)', 'whatever', '' ); SELECT * FROM check_test( roles_are( ___myroles('') ), true, 'roles_are(roles)', 'There should be the correct roles', '' ); SELECT * FROM check_test( roles_are( array_append(___myroles(''), '__howdy__'), 'whatever' ), false, 'roles_are(roles, desc) missing', 'whatever', ' Missing roles: __howdy__' ); SELECT * FROM check_test( roles_are( ___myroles(current_role), 'whatever' ), false, 'roles_are(roles, desc) extras', 'whatever', ' Extra roles: ' || current_role ); SELECT * FROM check_test( roles_are( array_append(___myroles(current_role), '__howdy__'), 'whatever' ), false, 'roles_are(roles, desc) missing and extras', 'whatever', ' Extra roles: ' || current_role || ' Missing roles: __howdy__' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._ruletap.sql000644 000765 000024 00000000252 11666501762 017346 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/ruletap.sql000644 000765 000024 00000022305 11666501762 017134 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(132); --SELECT * FROM no_plan(); -- This will be rolled back. :-) SET client_min_messages = warning; CREATE TABLE public.sometab( id INT NOT NULL PRIMARY KEY, name TEXT DEFAULT '', numb NUMERIC(10, 2), myint NUMERIC(8) ); CREATE RULE ins_me AS ON INSERT TO public.sometab DO NOTHING; CREATE RULE upd_me AS ON UPDATE TO public.sometab DO ALSO SELECT now(); CREATE TABLE public.toview ( id INT ); CREATE RULE "_RETURN" AS ON SELECT TO public.toview DO INSTEAD SELECT 42 AS id; CREATE TABLE public.widgets (id int); CREATE RULE del_me AS ON DELETE TO public.widgets DO NOTHING; CREATE RULE ins_me AS ON INSERT TO public.widgets DO NOTHING; RESET client_min_messages; /****************************************************************************/ -- Test has_rule() and hasnt_rule(). SELECT * FROM check_test( has_rule( 'public', 'sometab', 'ins_me', 'whatever' ), true, 'has_rule(schema, table, rule, desc)', 'whatever', '' ); SELECT * FROM check_test( has_rule( 'public', 'sometab', 'ins_me'::name ), true, 'has_rule(schema, table, rule)', 'Relation public.sometab should have rule ins_me', '' ); SELECT * FROM check_test( has_rule( 'public', 'sometab', 'del_me', 'whatever' ), false, 'has_rule(schema, table, rule, desc) fail', 'whatever', '' ); SELECT * FROM check_test( has_rule( 'sometab', 'ins_me', 'whatever' ), true, 'has_rule(table, rule, desc)', 'whatever', '' ); SELECT * FROM check_test( has_rule( 'sometab', 'ins_me'::name ), true, 'has_rule(table, rule)', 'Relation sometab should have rule ins_me', '' ); SELECT * FROM check_test( has_rule( 'sometab', 'del_me', 'whatever' ), false, 'has_rule(table, rule, desc) fail', 'whatever', '' ); SELECT * FROM check_test( hasnt_rule( 'public', 'sometab', 'ins_me', 'whatever' ), false, 'hasnt_rule(schema, table, rule, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_rule( 'public', 'sometab', 'ins_me'::name ), false, 'hasnt_rule(schema, table, rule)', 'Relation public.sometab should not have rule ins_me', '' ); SELECT * FROM check_test( hasnt_rule( 'public', 'sometab', 'del_me', 'whatever' ), true, 'hasnt_rule(schema, table, rule, desc) fail', 'whatever', '' ); SELECT * FROM check_test( hasnt_rule( 'sometab', 'ins_me', 'whatever' ), false, 'hasnt_rule(table, rule, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_rule( 'sometab', 'ins_me'::name ), false, 'hasnt_rule(table, rule)', 'Relation sometab should not have rule ins_me', '' ); SELECT * FROM check_test( hasnt_rule( 'sometab', 'del_me', 'whatever' ), true, 'hasnt_rule(table, rule, desc) fail', 'whatever', '' ); /****************************************************************************/ -- Test rule_is_instead(). SELECT * FROM check_test( rule_is_instead( 'public', 'toview', '_RETURN', 'whatever' ), true, 'rule_is_instead(schema, table, rule, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_instead( 'public', 'toview', '_RETURN'::name ), true, 'rule_is_instead(schema, table, rule)', 'Rule "_RETURN" on relation public.toview should be an INSTEAD rule', '' ); SELECT * FROM check_test( rule_is_instead( 'public', 'sometab', 'ins_me', 'whatever' ), false, 'rule_is_instead(schema, table, nothing rule, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_instead( 'public', 'sometab', 'upd_me', 'whatever' ), false, 'rule_is_instead(schema, table, also rule, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_instead( 'toview', '_RETURN', 'whatever' ), true, 'rule_is_instead(table, rule, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_instead( 'toview', '_RETURN'::name ), true, 'rule_is_instead(table, rule)', 'Rule "_RETURN" on relation toview should be an INSTEAD rule', '' ); SELECT * FROM check_test( rule_is_instead( 'sometab', 'ins_me', 'whatever' ), false, 'rule_is_instead(table, nothing rule, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_instead( 'sometab', 'upd_me', 'whatever' ), false, 'rule_is_instead(table, also rule, desc)', 'whatever', '' ); -- Check failure diagnostics for non-existent rules. SELECT * FROM check_test( rule_is_instead( 'public', 'sometab', 'blah', 'whatever' ), false, 'rule_is_instead(schema, table, non-existent rule, desc)', 'whatever', ' Rule blah does not exist' ); SELECT * FROM check_test( rule_is_instead( 'sometab', 'blah', 'whatever' ), false, 'rule_is_instead(table, non-existent rule, desc)', 'whatever', ' Rule blah does not exist' ); /****************************************************************************/ -- Test rule_is_on(). SELECT * FROM check_test( rule_is_on( 'public', 'sometab', 'ins_me', 'insert', 'whatever' ), true, 'rule_is_on(schema, table, rule, insert, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'public', 'sometab', 'upd_me', 'update', 'whatever' ), true, 'rule_is_on(schema, table, rule, update, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'public', 'toview', '_RETURN', 'SELECT', 'whatever' ), true, 'rule_is_on(schema, table, rule, SELECT, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'public', 'widgets', 'del_me', 'delete', 'whatever' ), true, 'rule_is_on(schema, table, rule, delete, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'public', 'widgets', 'ins_me', 'insert', 'whatever' ), true, 'rule_is_on(schema, table, dupe rule, insert, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'public', 'sometab', 'ins_me', 'INSERT', 'whatever' ), true, 'rule_is_on(schema, table, rule, INSERT, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'public', 'sometab', 'ins_me', 'i', 'whatever' ), true, 'rule_is_on(schema, table, rule, i, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'public', 'sometab', 'ins_me', 'indigo', 'whatever' ), true, 'rule_is_on(schema, table, rule, indigo, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'public', 'sometab', 'ins_me'::name, 'i' ), true, 'rule_is_on(schema, table, rule, i, desc)', 'Rule ins_me should be on INSERT to public.sometab', '' ); SELECT * FROM check_test( rule_is_on( 'public', 'sometab', 'ins_me'::name, 'u' ), false, 'rule_is_on(schema, table, rule, u, desc) fail', 'Rule ins_me should be on UPDATE to public.sometab', ' have: INSERT want: UPDATE' ); SELECT * FROM check_test( rule_is_on( 'public', 'sometab', 'foo_me'::name, 'u' ), false, 'rule_is_on(schema, table, invalid rule, u, desc)', 'Rule foo_me should be on UPDATE to public.sometab', ' Rule foo_me does not exist on public.sometab' ); SELECT * FROM check_test( rule_is_on( 'sometab', 'ins_me', 'insert', 'whatever' ), true, 'rule_is_on(table, rule, insert, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'sometab', 'upd_me', 'update', 'whatever' ), true, 'rule_is_on(table, rule, update, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'toview', '_RETURN', 'SELECT', 'whatever' ), true, 'rule_is_on(table, rule, SELECT, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'widgets', 'del_me', 'delete', 'whatever' ), true, 'rule_is_on(table, rule, delete, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'widgets', 'ins_me', 'insert', 'whatever' ), true, 'rule_is_on(table, dupe rule, insert, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'sometab', 'ins_me', 'INSERT', 'whatever' ), true, 'rule_is_on(table, rule, INSERT, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'sometab', 'ins_me', 'i', 'whatever' ), true, 'rule_is_on(table, rule, i, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'sometab', 'ins_me', 'indigo', 'whatever' ), true, 'rule_is_on(table, rule, indigo, desc)', 'whatever', '' ); SELECT * FROM check_test( rule_is_on( 'sometab', 'ins_me'::name, 'i' ), true, 'rule_is_on(table, rule, i, desc)', 'Rule ins_me should be on INSERT to sometab', '' ); SELECT * FROM check_test( rule_is_on( 'sometab', 'ins_me'::name, 'u' ), false, 'rule_is_on(table, rule, u, desc) fail', 'Rule ins_me should be on UPDATE to sometab', ' have: INSERT want: UPDATE' ); SELECT * FROM check_test( rule_is_on( 'sometab', 'foo_me'::name, 'u' ), false, 'rule_is_on(table, invalid rule, u, desc)', 'Rule foo_me should be on UPDATE to sometab', ' Rule foo_me does not exist on sometab' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._runtests.sql000644 000765 000024 00000000252 11666501762 017561 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/runtests.sql000644 000765 000024 00000004364 11666501762 017354 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SET client_min_messages = warning; CREATE SCHEMA whatever; CREATE TABLE whatever.foo ( id serial primary key ); -- Make sure we get test function names. SET client_min_messages = notice; CREATE OR REPLACE FUNCTION whatever.startup() RETURNS SETOF TEXT AS $$ SELECT pass('starting up'); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION whatever.startupmore() RETURNS SETOF TEXT AS $$ SELECT pass('starting up some more'); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION whatever.setup() RETURNS SETOF TEXT AS $$ SELECT pass('setup') UNION SELECT is( MAX(id), NULL, 'Should be nothing in the test table') FROM whatever.foo; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION whatever.setupmore() RETURNS SETOF TEXT AS $$ SELECT pass('setup more'); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION whatever.teardown() RETURNS SETOF TEXT AS $$ SELECT pass('teardown'); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION whatever.teardownmore() RETURNS SETOF TEXT AS $$ SELECT pass('teardown more'); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION whatever.shutdown() RETURNS SETOF TEXT AS $$ SELECT pass('shutting down'); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION whatever.shutdownmore() RETURNS SETOF TEXT AS $$ SELECT pass('shutting down more'); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION whatever.testthis() RETURNS SETOF TEXT AS $$ SELECT pass('simple pass') AS foo UNION SELECT pass('another simple pass') ORDER BY foo ASC; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION whatever.testplpgsql() RETURNS SETOF TEXT AS $$ BEGIN RETURN NEXT pass( 'plpgsql simple' ); RETURN NEXT pass( 'plpgsql simple 2' ); INSERT INTO whatever.foo VALUES(1); RETURN NEXT is( MAX(id), 1, 'Should be a 1 in the test table') FROM whatever.foo; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION whatever.testz() RETURNS SETOF TEXT AS $$ SELECT is( MAX(id), NULL, 'Late test should find nothing in the test table') FROM whatever.foo; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION whatever."test ident"() RETURNS SETOF TEXT AS $$ BEGIN RETURN NEXT pass( 'ident' ); RETURN NEXT pass( 'ident 2' ); END; $$ LANGUAGE plpgsql; -- Run the actual tests. Yes, it's a one-liner! SELECT * FROM runtests('whatever'::name); ROLLBACK; pgtap-0.90.0/test/sql/._throwtap.sql000644 000765 000024 00000000252 11666501762 017542 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/throwtap.sql000644 000765 000024 00000016052 11666501762 017332 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(84); --SELECT * FROM no_plan(); /****************************************************************************/ -- test throws_ok(). SELECT * FROM check_test( throws_ok( 'SELECT * FROM todo_end()', 'P0001', 'todo_end() called without todo_start()', 'whatever' ), true, 'four-argument form', 'whatever', '' ); SELECT * FROM check_test( throws_ok( 'SELECT * FROM todo_end()', 'P0001', 'todo_end() called without todo_start()'), true, 'three-argument errcode', 'threw P0001: todo_end() called without todo_start()', '' ); SELECT * FROM check_test( throws_ok( 'SELECT 1 / 0', '22012' ), true, 'two-argument errcode', 'threw 22012' '' ); SELECT * FROM check_test( throws_ok( 'SELECT * FROM todo_end()', 'todo_end() called without todo_start()', 'whatever'), true, 'three argument errmsg', 'whatever', '' ); SELECT * FROM check_test( throws_ok( 'SELECT * FROM todo_end()', 'todo_end() called without todo_start()'), true, 'two-argument errmsg', 'threw todo_end() called without todo_start()', '' ); SELECT * FROM check_test( throws_ok( 'SELECT 1 / 0' ), true, 'single-argument form', 'threw an exception', '' ); -- Try using a prepared statement. PREPARE mytest AS SELECT * FROM todo_end(); SELECT * FROM check_test( throws_ok( 'mytest', 'P0001'), true, 'prepared statement & errcode', 'threw P0001' '' ); SELECT * FROM check_test( throws_ok( 'EXECUTE mytest', 'P0001'), true, 'execute & errcode', 'threw P0001' '' ); -- Check its diagnostics for an invalid error code. SELECT * FROM check_test( throws_ok( 'SELECT * FROM todo_end()', 97212 ), false, 'invalid errcode', 'threw 97212', ' caught: P0001: todo_end() called without todo_start() wanted: 97212' ); SELECT throws_ok( 'SELECT 1 / 0', NULL, NULL, 'throws_ok(1/0, NULL) should work' ); -- Check its diagnostics no error. SELECT * FROM check_test( throws_ok( 'SELECT 1', NULL ), false, 'throws_ok diagnostics', 'threw an exception', ' caught: no exception wanted: an exception' ); /****************************************************************************/ -- test lives_ok(). SELECT lives_ok( 'SELECT 1', 'lives_ok() should work' ); PREPARE livetest AS SELECT 1; SELECT * FROM check_test( lives_ok( 'livetest'), true, 'lives_ok(prepared)' '', '' ); SELECT * FROM check_test( lives_ok( 'EXECUTE livetest'), true, 'lives_ok(execute)' '', '' ); -- Check its diagnostics when there is an exception. SELECT * FROM check_test( lives_ok( 'SELECT * FROM todo_end()' ), false, 'lives_ok failure diagnostics', '', ' died: P0001: todo_end() called without todo_start()' ); /****************************************************************************/ -- test throws_like(). SELECT * FROM check_test( throws_like( 'SELECT * FROM todo_end()', '%end() called without todo%', 'whatever' ), true, 'throws_like(sql, pattern, desc)', 'whatever', '' ); SELECT * FROM check_test( throws_like( 'SELECT * FROM todo_end()', '%end() called without todo%' ), true, 'throws_like(sql, pattern)', 'Should throw exception like ''%end() called without todo%''', '' ); SELECT * FROM check_test( throws_like( 'SELECT * FROM todo_end()', '%huh%', 'whatever' ), false, 'throws_like(sql, pattern, desc) fail', 'whatever', ' error message: ''todo_end() called without todo_start()'' doesn''t match: ''%huh%''' ); SELECT * FROM check_test( throws_like( 'SELECT 1', '%huh%', 'whatever' ), false, 'throws_like(valid sql, pattern, desc)', 'whatever', ' no exception thrown' ); /****************************************************************************/ -- test throws_ilike(). SELECT * FROM check_test( throws_ilike( 'SELECT * FROM todo_end()', '%END() called without todo%', 'whatever' ), true, 'throws_ilike(sql, pattern, desc)', 'whatever', '' ); SELECT * FROM check_test( throws_ilike( 'SELECT * FROM todo_end()', '%END() called without todo%' ), true, 'throws_ilike(sql, pattern)', 'Should throw exception like ''%END() called without todo%''', '' ); SELECT * FROM check_test( throws_ilike( 'SELECT * FROM todo_end()', '%HUH%', 'whatever' ), false, 'throws_ilike(sql, pattern, desc) fail', 'whatever', ' error message: ''todo_end() called without todo_start()'' doesn''t match: ''%HUH%''' ); SELECT * FROM check_test( throws_ilike( 'SELECT 1', '%HUH%', 'whatever' ), false, 'throws_ilike(valid sql, pattern, desc)', 'whatever', ' no exception thrown' ); /****************************************************************************/ -- test throws_matching(). SELECT * FROM check_test( throws_matching( 'SELECT * FROM todo_end()', '.*end[(][)] called without todo.+', 'whatever' ), true, 'throws_matching(sql, regex, desc)', 'whatever', '' ); SELECT * FROM check_test( throws_matching( 'SELECT * FROM todo_end()', '.*end[(][)] called without todo.+' ), true, 'throws_matching(sql, regex, desc)', 'Should throw exception matching ''.*end[(][)] called without todo.+''', '' ); SELECT * FROM check_test( throws_matching( 'SELECT * FROM todo_end()', 'huh.+', 'whatever' ), false, 'throws_matching(sql, regex, desc)', 'whatever', ' error message: ''todo_end() called without todo_start()'' doesn''t match: ''huh.+''' ); SELECT * FROM check_test( throws_matching( 'SELECT 1', 'huh.+', 'whatever' ), false, 'throws_matching(valid sql, regex, desc)', 'whatever', ' no exception thrown' ); /****************************************************************************/ -- test throws_imatching(). SELECT * FROM check_test( throws_imatching( 'SELECT * FROM todo_end()', '.*end[(][)] CALLED without todo.+', 'whatever' ), true, 'throws_imatching(sql, regex, desc)', 'whatever', '' ); SELECT * FROM check_test( throws_imatching( 'SELECT * FROM todo_end()', '.*end[(][)] CALLED without todo.+' ), true, 'throws_imatching(sql, regex, desc)', 'Should throw exception matching ''.*end[(][)] CALLED without todo.+''', '' ); SELECT * FROM check_test( throws_imatching( 'SELECT * FROM todo_end()', 'HUH.+', 'whatever' ), false, 'throws_imatching(sql, regex, desc)', 'whatever', ' error message: ''todo_end() called without todo_start()'' doesn''t match: ''HUH.+''' ); SELECT * FROM check_test( throws_imatching( 'SELECT 1', 'HUH.+', 'whatever' ), false, 'throws_imatching(valid sql, regex, desc)', 'whatever', ' no exception thrown' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._todotap.sql000644 000765 000024 00000000252 11666501762 017344 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/todotap.sql000644 000765 000024 00000013143 11666501762 017132 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(36); --SELECT * FROM no_plan(); /****************************************************************************/ -- Test todo tests. \echo ok 1 - todo fail \echo ok 2 - todo pass SELECT * FROM todo('just because', 2 ); SELECT is( fail('This is a todo test' ) || ' ' || pass('This is a todo test that unexpectedly passes' ), 'not ok 1 - This is a todo test # TODO just because # Failed (TODO) test 1: "This is a todo test" ok 2 - This is a todo test that unexpectedly passes # TODO just because', 'TODO tests should display properly' ); -- Try just a reason. \echo ok 4 - todo fail SELECT * FROM todo( 'for whatever reason' ); SELECT is( fail('Another todo test'), 'not ok 4 - Another todo test # TODO for whatever reason # Failed (TODO) test 4: "Another todo test"', 'Single default todo test should display properly' ); UPDATE __tresults__ SET ok = true, aok = true WHERE numb IN( 2, 4 ); -- Try just a number. \echo ok 6 - todo fail \echo ok 7 - todo pass SELECT * FROM todo( 2 ); SELECT is( fail('This is a todo test' ) || ' ' || pass('This is a todo test that unexpectedly passes' ), 'not ok 6 - This is a todo test # TODO # Failed (TODO) test 6: "This is a todo test" ok 7 - This is a todo test that unexpectedly passes # TODO ', 'TODO tests should display properly' ); /****************************************************************************/ -- Test skipping tests. SELECT * FROM check_test( skip('Just because'), true, 'simple skip', 'SKIP: Just because', '' ); SELECT * FROM check_test( skip('Just because', 1), true, 'skip with num', 'SKIP: Just because', '' ); \echo ok 15 - Skip multiple \echo ok 16 - Skip multiple \echo ok 17 - Skip multiple SELECT is( skip( 'Whatever', 3 ), 'ok 15 - SKIP: Whatever ok 16 - SKIP: Whatever ok 17 - SKIP: Whatever', 'We should get the proper output for multiple skips' ); -- Test inversion. SELECT * FROM check_test( skip(1, 'Just because'), true, 'inverted skip', 'SKIP: Just because', '' ); -- Test num only. SELECT * FROM check_test( skip(1), true, 'num only', 'SKIP: ', '' ); /****************************************************************************/ -- Try nesting todo tests. \echo ok 25 - todo fail \echo ok 26 - todo fail \echo ok 27 - todo fail SELECT * FROM todo('just because', 2 ); -- We have to use ok() instead of is() to get around lack of cast to text in 8.0. SELECT ok( ARRAY( SELECT fail('This is a todo test 1') AS stuff UNION SELECT todo::text FROM todo('inside') UNION SELECT fail('This is a todo test 2') UNION SELECT fail('This is a todo test 3') ORDER BY stuff ) = ARRAY[ 'not ok 25 - This is a todo test 1 # TODO just because # Failed (TODO) test 25: "This is a todo test 1"', 'not ok 26 - This is a todo test 2 # TODO inside # Failed (TODO) test 26: "This is a todo test 2"', 'not ok 27 - This is a todo test 3 # TODO just because # Failed (TODO) test 27: "This is a todo test 3"' ], 'Nested todos should work properly' ); UPDATE __tresults__ SET ok = true, aok = true WHERE numb IN( 25, 26, 27 ); /****************************************************************************/ -- Test todo_start() and todo_end(). \echo ok 29 - todo fail \echo ok 30 - todo fail \echo ok 31 - todo fail SELECT * FROM todo_start('some todos'); -- We have to use ok() instead of is() to get around lack of cast to text in 8.0. SELECT ok( ARRAY( SELECT fail('This is a todo test 1') AS stuff UNION SELECT in_todo()::text UNION SELECT todo::text FROM todo('inside') UNION SELECT fail('This is a todo test 2') UNION SELECT fail('This is a todo test 3') UNION SELECT todo_end::text FROM todo_end() UNION SELECT in_todo()::text ORDER BY stuff ) = ARRAY[ 'false', 'not ok 29 - This is a todo test 1 # TODO some todos # Failed (TODO) test 29: "This is a todo test 1"', 'not ok 30 - This is a todo test 2 # TODO inside # Failed (TODO) test 30: "This is a todo test 2"', 'not ok 31 - This is a todo test 3 # TODO some todos # Failed (TODO) test 31: "This is a todo test 3"', 'true' ], 'todo_start() and todo_end() should work properly with in_todo()' ); UPDATE __tresults__ SET ok = true, aok = true WHERE numb IN( 29, 30, 31 ); /****************************************************************************/ -- Make sure we can reverse the arguments. \echo ok 33 - todo fail \echo ok 34 - todo pass SELECT * FROM todo(2, 'just because' ); SELECT is( fail('This is a todo test' ) || ' ' || fail('Another todo test'), 'not ok 33 - This is a todo test # TODO just because # Failed (TODO) test 33: "This is a todo test" not ok 34 - Another todo test # TODO just because # Failed (TODO) test 34: "Another todo test"', 'Should be able to revers the arguments to todo()' ); UPDATE __tresults__ SET ok = true, aok = true WHERE numb IN( 32, 33 ); -- Test the exception when throws_ok() is available. SELECT CASE WHEN pg_version_num() < 80100 THEN pass('Should get an exception when todo_end() is called without todo_start()') ELSE throws_ok( 'SELECT todo_end()', 'P0001', 'todo_end() called without todo_start()', 'Should get an exception when todo_end() is called without todo_start()' ) END; /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._trigger.sql000644 000765 000024 00000000252 11666501762 017335 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/trigger.sql000644 000765 000024 00000015577 11666501762 017140 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(84); --SELECT * FROM no_plan(); -- This will be rolled back. :-) SET client_min_messages = warning; CREATE TABLE public.users( nick text NOT NULL PRIMARY KEY, pass text NOT NULL ); CREATE FUNCTION public.hash_pass() RETURNS TRIGGER AS ' BEGIN NEW.pass := MD5( NEW.pass ); RETURN NEW; END; ' LANGUAGE plpgsql; CREATE TRIGGER set_users_pass BEFORE INSERT ON public.users FOR EACH ROW EXECUTE PROCEDURE hash_pass(); CREATE TRIGGER upd_users_pass BEFORE UPDATE ON public.users FOR EACH ROW EXECUTE PROCEDURE hash_pass(); RESET client_min_messages; /****************************************************************************/ -- Test has_trigger() and hasnt_trigger(). SELECT * FROM check_test( has_trigger( 'public', 'users', 'set_users_pass', 'whatever' ), true, 'has_trigger(schema, table, trigger, desc)', 'whatever', '' ); SELECT * FROM check_test( has_trigger( 'public', 'users', 'set_users_pass'::name ), true, 'has_trigger(schema, table, trigger)', 'Table public.users should have trigger set_users_pass', '' ); SELECT * FROM check_test( has_trigger( 'users', 'set_users_pass', 'whatever' ), true, 'has_trigger(table, trigger, desc)', 'whatever', '' ); SELECT * FROM check_test( has_trigger( 'users', 'set_users_pass' ), true, 'has_trigger(table, trigger)', 'Table users should have trigger set_users_pass', '' ); SELECT * FROM check_test( has_trigger( 'public', 'users', 'nosuch', 'whatever' ), false, 'has_trigger(schema, table, nonexistent, desc)', 'whatever', '' ); SELECT * FROM check_test( has_trigger( 'users', 'nosuch' ), false, 'has_trigger(table, nonexistent) no schema fail', 'Table users should have trigger nosuch', '' ); SELECT * FROM check_test( hasnt_trigger( 'public', 'users', 'set_users_pass', 'whatever' ), false, 'hasnt_trigger(schema, table, trigger, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_trigger( 'public', 'users', 'set_users_pass'::name ), false, 'hasnt_trigger(schema, table, trigger)', 'Table public.users should not have trigger set_users_pass', '' ); SELECT * FROM check_test( hasnt_trigger( 'users', 'set_users_pass', 'whatever' ), false, 'hasnt_trigger(table, trigger, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_trigger( 'users', 'set_users_pass' ), false, 'hasnt_trigger(table, trigger)', 'Table users should not have trigger set_users_pass', '' ); SELECT * FROM check_test( hasnt_trigger( 'public', 'users', 'nosuch', 'whatever' ), true, 'hasnt_trigger(schema, table, nonexistent, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_trigger( 'users', 'nosuch' ), true, 'hasnt_trigger(table, nonexistent) no schema fail', 'Table users should not have trigger nosuch', '' ); /****************************************************************************/ -- test trigger_is() SELECT * FROM check_test( trigger_is( 'public', 'users', 'set_users_pass', 'public', 'hash_pass', 'whatever' ), true, 'trigger_is()', 'whatever', '' ); SELECT * FROM check_test( trigger_is( 'public', 'users', 'set_users_pass', 'public', 'hash_pass' ), true, 'trigger_is() no desc', 'Trigger set_users_pass should call public.hash_pass()', '' ); SELECT * FROM check_test( trigger_is( 'users', 'set_users_pass', 'hash_pass', 'whatever' ), true, 'trigger_is() no schema', 'whatever', '' ); SELECT * FROM check_test( trigger_is( 'users', 'set_users_pass', 'hash_pass' ), true, 'trigger_is() no schema or desc', 'Trigger set_users_pass should call hash_pass()', '' ); SELECT * FROM check_test( trigger_is( 'public', 'users', 'set_users_pass', 'public', 'oops', 'whatever' ), false, 'trigger_is() fail', 'whatever', ' have: public.hash_pass want: public.oops' ); SELECT * FROM check_test( trigger_is( 'users', 'set_users_pass', 'oops' ), false, 'trigger_is() no schema fail', 'Trigger set_users_pass should call oops()', ' have: hash_pass want: oops' ); /****************************************************************************/ -- Test triggers_are(). SELECT * FROM check_test( triggers_are( 'public', 'users', ARRAY['set_users_pass', 'upd_users_pass'], 'whatever' ), true, 'triggers_are(schema, table, triggers, desc)', 'whatever', '' ); SELECT * FROM check_test( triggers_are( 'public', 'users', ARRAY['set_users_pass', 'upd_users_pass'] ), true, 'triggers_are(schema, table, triggers)', 'Table public.users should have the correct triggers', '' ); SELECT * FROM check_test( triggers_are( 'public', 'users', ARRAY['set_users_pass'] ), false, 'triggers_are(schema, table, triggers) + extra', 'Table public.users should have the correct triggers', ' Extra triggers: upd_users_pass' ); SELECT * FROM check_test( triggers_are( 'public', 'users', ARRAY['set_users_pass', 'upd_users_pass', 'howdy'] ), false, 'triggers_are(schema, table, triggers) + missing', 'Table public.users should have the correct triggers', ' Missing triggers: howdy' ); SELECT * FROM check_test( triggers_are( 'public', 'users', ARRAY['set_users_pass', 'howdy'] ), false, 'triggers_are(schema, table, triggers) + extra & missing', 'Table public.users should have the correct triggers', ' Extra triggers: upd_users_pass Missing triggers: howdy' ); SELECT * FROM check_test( triggers_are( 'users', ARRAY['set_users_pass', 'upd_users_pass'], 'whatever' ), true, 'triggers_are(table, triggers, desc)', 'whatever', '' ); SELECT * FROM check_test( triggers_are( 'users', ARRAY['set_users_pass', 'upd_users_pass'] ), true, 'triggers_are(table, triggers)', 'Table users should have the correct triggers', '' ); SELECT * FROM check_test( triggers_are( 'users', ARRAY['set_users_pass'] ), false, 'triggers_are(table, triggers) + extra', 'Table users should have the correct triggers', ' Extra triggers: upd_users_pass' ); SELECT * FROM check_test( triggers_are( 'users', ARRAY['set_users_pass', 'upd_users_pass', 'howdy'] ), false, 'triggers_are(table, triggers) + missing', 'Table users should have the correct triggers', ' Missing triggers: howdy' ); SELECT * FROM check_test( triggers_are( 'users', ARRAY['set_users_pass', 'howdy'] ), false, 'triggers_are(table, triggers) + extra & missing', 'Table users should have the correct triggers', ' Extra triggers: upd_users_pass Missing triggers: howdy' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._unique.sql000644 000765 000024 00000000252 11666501762 017200 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/unique.sql000644 000765 000024 00000011004 11666501762 016760 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(48); -- This will be rolled back. :-) SET client_min_messages = warning; CREATE TABLE public.sometab( id INT NOT NULL PRIMARY KEY, name TEXT DEFAULT '' UNIQUE, numb NUMERIC(10, 2), myint NUMERIC(8), UNIQUE (numb, myint) ); RESET client_min_messages; /****************************************************************************/ -- Test has_unique(). SELECT * FROM check_test( has_unique( 'public', 'sometab', 'public.sometab should have a unique constraint' ), true, 'has_unique( schema, table, description )', 'public.sometab should have a unique constraint', '' ); SELECT * FROM check_test( has_unique( 'sometab', 'sometab should have a unique constraint' ), true, 'has_unique( table, description )', 'sometab should have a unique constraint', '' ); SELECT * FROM check_test( has_unique( 'sometab' ), true, 'has_unique( table )', 'Table sometab should have a unique constraint', '' ); SELECT * FROM check_test( has_unique( 'pg_catalog', 'pg_class', 'pg_catalog.pg_class should have a unique constraint' ), false, 'has_unique( schema, table, description ) fail', 'pg_catalog.pg_class should have a unique constraint', '' ); SELECT * FROM check_test( has_unique( 'pg_class', 'pg_class should have a unique constraint' ), false, 'has_unique( table, description ) fail', 'pg_class should have a unique constraint', '' ); /****************************************************************************/ -- Test col_is_unique(). SELECT * FROM check_test( col_is_unique( 'public', 'sometab', 'name', 'public.sometab.name should be unique' ), true, 'col_is_unique( schema, table, column, description )', 'public.sometab.name should be unique', '' ); SELECT * FROM check_test( col_is_unique( 'public', 'sometab', ARRAY['numb', 'myint'], 'public.sometab.numb+myint should be unique' ), true, 'col_is_unique( schema, table, columns, description )', 'public.sometab.numb+myint should be unique', '' ); SELECT * FROM check_test( col_is_unique( 'sometab', 'name', 'sometab.name should be unique' ), true, 'col_is_unique( table, column, description )', 'sometab.name should be unique', '' ); SELECT * FROM check_test( col_is_unique( 'sometab', ARRAY['numb', 'myint'], 'sometab.numb+myint should be unique' ), true, 'col_is_unique( table, columns, description )', 'sometab.numb+myint should be unique', '' ); SELECT * FROM check_test( col_is_unique( 'sometab', 'name' ), true, 'col_is_unique( table, column )', 'Column sometab(name) should have a unique constraint', '' ); SELECT * FROM check_test( col_is_unique( 'sometab', ARRAY['numb', 'myint'] ), true, 'col_is_unique( table, columns )', 'Columns sometab(numb, myint) should have a unique constraint', '' ); SELECT * FROM check_test( col_is_unique( 'public', 'sometab', 'id', 'public.sometab.id should be unique' ), false, 'col_is_unique( schema, table, column, description ) fail', 'public.sometab.id should be unique', ' have: {name} {numb,myint} want: {id}' ); SELECT * FROM check_test( col_is_unique( 'sometab', 'id', 'sometab.id should be unique' ), false, 'col_is_unique( table, column, description ) fail', 'sometab.id should be unique', ' have: {name} {numb,myint} want: {id}' ); /****************************************************************************/ -- Test col_is_unique() with an array of columns. SET client_min_messages = warning; CREATE TABLE public.argh ( id INT NOT NULL, name TEXT NOT NULL, UNIQUE (id, name) ); RESET client_min_messages; SELECT * FROM check_test( col_is_unique( 'public', 'argh', ARRAY['id', 'name'], 'id + name should be unique' ), true, 'col_is_unique( schema, table, column[], description )', 'id + name should be unique', '' ); SELECT * FROM check_test( col_is_unique( 'argh', ARRAY['id', 'name'], 'id + name should be unique' ), true, 'col_is_unique( table, column[], description )', 'id + name should be unique', '' ); SELECT * FROM check_test( col_is_unique( 'argh', ARRAY['id', 'name'] ), true, 'col_is_unique( table, column[] )', 'Columns argh(id, name) should have a unique constraint', '' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._usergroup.sql000644 000765 000024 00000000252 11666501762 017725 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/usergroup.sql000644 000765 000024 00000012474 11666501762 017521 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(78); --SELECT * FROM no_plan(); /****************************************************************************/ -- Test has_user() and hasnt_user(). SELECT * FROM check_test( has_user(current_user), true, 'has_user(current user)', 'User ' || quote_ident(current_user) || ' should exist', '' ); SELECT * FROM check_test( has_user(current_user, 'whatever'), true, 'has_user(current user, desc)', 'whatever', '' ); SELECT * FROM check_test( has_user('aoijaoisjfaoidfjaisjdfosjf'), false, 'has_user(nonexistent user)', 'User aoijaoisjfaoidfjaisjdfosjf should exist', '' ); SELECT * FROM check_test( has_user('aoijaoisjfaoidfjaisjdfosjf', 'desc'), false, 'has_user(nonexistent user, desc)', 'desc', '' ); SELECT * FROM check_test( hasnt_user(current_user), false, 'hasnt_user(current user)', 'User ' || quote_ident(current_user) || ' should not exist', '' ); SELECT * FROM check_test( hasnt_user(current_user, 'whatever'), false, 'hasnt_user(current user, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_user('aoijaoisjfaoidfjaisjdfosjf'), true, 'hasnt_user(nonexistent user)', 'User aoijaoisjfaoidfjaisjdfosjf should not exist', '' ); SELECT * FROM check_test( hasnt_user('aoijaoisjfaoidfjaisjdfosjf', 'desc'), true, 'hasnt_user(nonexistent user, desc)', 'desc', '' ); /****************************************************************************/ -- Test is_superuser() and isnt_superuser(). SELECT * FROM check_test( is_superuser('aoijaoisjfaoidfjaisjdfosjf', 'desc'), false, 'is_superuser(nonexistent user, desc)', 'desc', ' User aoijaoisjfaoidfjaisjdfosjf does not exist' ); SELECT * FROM check_test( is_superuser('aoijaoisjfaoidfjaisjdfosjf'), false, 'is_superuser(nonexistent user)', 'User aoijaoisjfaoidfjaisjdfosjf should be a super user', ' User aoijaoisjfaoidfjaisjdfosjf does not exist' ); SELECT * FROM check_test( isnt_superuser('aoijaoisjfaoidfjaisjdfosjf', 'desc'), false, 'isnt_superuser(nonexistent user, desc)', 'desc', ' User aoijaoisjfaoidfjaisjdfosjf does not exist' ); SELECT * FROM check_test( isnt_superuser('aoijaoisjfaoidfjaisjdfosjf'), false, 'isnt_superuser(nonexistent user)', 'User aoijaoisjfaoidfjaisjdfosjf should not be a super user', ' User aoijaoisjfaoidfjaisjdfosjf does not exist' ); SELECT * FROM check_test( is_superuser(current_user), true, 'is_superuser( current user )', 'User ' || quote_ident(current_user) || ' should be a super user', '' ); SELECT * FROM check_test( is_superuser(current_user, 'whatever'), true, 'is_superuser( current user, desc )', 'whatever', '' ); /****************************************************************************/ -- Test has_group() and hasnt_group(). CREATE GROUP meanies; SELECT * FROM check_test( has_group('meanies'), true, 'has_group(group)', 'Group ' || quote_ident('meanies') || ' should exist', '' ); SELECT * FROM check_test( has_group('meanies', 'whatever'), true, 'has_group(group, desc)', 'whatever', '' ); SELECT * FROM check_test( has_group('aoijaoisjfaoidfjaisjdfosjf'), false, 'has_group(nonexistent group)', 'Group aoijaoisjfaoidfjaisjdfosjf should exist', '' ); SELECT * FROM check_test( has_group('aoijaoisjfaoidfjaisjdfosjf', 'desc'), false, 'has_group(nonexistent group, desc)', 'desc', '' ); SELECT * FROM check_test( hasnt_group('meanies'), false, 'hasnt_group(group)', 'Group ' || quote_ident('meanies') || ' should not exist', '' ); SELECT * FROM check_test( hasnt_group('meanies', 'whatever'), false, 'hasnt_group(group, desc)', 'whatever', '' ); SELECT * FROM check_test( hasnt_group('aoijaoisjfaoidfjaisjdfosjf'), true, 'hasnt_group(nonexistent group)', 'Group aoijaoisjfaoidfjaisjdfosjf should not exist', '' ); SELECT * FROM check_test( hasnt_group('aoijaoisjfaoidfjaisjdfosjf', 'desc'), true, 'hasnt_group(nonexistent group, desc)', 'desc', '' ); /****************************************************************************/ -- Test is_member_of(). CREATE OR REPLACE FUNCTION addmember() RETURNS SETOF TEXT AS $$ BEGIN EXECUTE 'ALTER GROUP meanies ADD USER ' || current_user; RETURN; END; $$ LANGUAGE PLPGSQL; SELECT * FROM addmember(); SELECT * FROM check_test( is_member_of('meanies', ARRAY[current_user], 'whatever' ), true, 'is_member_of(meanies, [current_user], desc)', 'whatever', '' ); SELECT * FROM check_test( is_member_of('meanies', ARRAY[current_user] ), true, 'is_member_of(meanies, [current_user])', 'Should have members of group meanies', '' ); SELECT * FROM check_test( is_member_of('meanies', current_user, 'whatever' ), true, 'is_member_of(meanies, current_user, desc)', 'whatever', '' ); SELECT * FROM check_test( is_member_of('meanies', current_user ), true, 'is_member_of(meanies, current_user)', 'Should have members of group meanies', '' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._util.sql000644 000765 000024 00000000252 11666501762 016647 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/util.sql000644 000765 000024 00000012014 11666501762 016431 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(35); --SELECT * FROM no_plan(); SELECT is( pg_typeof(42), 'integer', 'pg_type(int) should work' ); SELECT is( pg_typeof(42.1), 'numeric', 'pg_type(numeric) should work' ); SELECT is( pg_typeof(''::text), 'text', 'pg_type(text) should work' ); SELECT is( pg_typeof( pg_version() ), 'text', 'pg_version() should return text' ); SELECT is( pg_version(), current_setting( 'server_version'), 'pg_version() should return same as "server_version" setting' ); SELECT matches( pg_version(), '^[89][.][[:digit:]]{1,2}([.][[:digit:]]{1,2}|devel|(alpha|beta|rc)[[:digit:]]+)$', 'pg_version() should work' ); SELECT CASE WHEN pg_version_num() < 81000 THEN pass( 'pg_version() should return same as "server_version" setting' ) ELSE is( pg_version_num(), current_setting( 'server_version_num')::integer, 'pg_version() should return same as "server_version" setting' ) END; SELECT is( pg_typeof( pg_version_num() ), 'integer', 'pg_version_num() should return integer' ); SELECT matches( pg_version_num()::text, '^[89][[:digit:]]{4}$', 'pg_version_num() should be correct' ); SELECT matches( os_name(), '^[[:alnum:]]+$', 'os_name() should output something like an OS name' ); SELECT is( findfuncs('pg_catalog', '^abs$'), ARRAY['pg_catalog.abs'], 'findfincs() should return distinct values' ); SELECT matches( pgtap_version()::text, '^0[.][[:digit:]]{2}$', 'pgtap_version() should work' ); /****************************************************************************/ -- Test collect_tap(). SELECT is( collect_tap(ARRAY['foo', 'bar', 'baz']), 'foo bar baz', 'collect_tap(text[]) should simply collect tap' ); CREATE FUNCTION test_variadic() RETURNS TEXT AS $$ BEGIN IF pg_version_num() >= 80400 THEN RETURN collect_tap('foo', 'bar', 'baz'); ELSE RETURN collect_tap(ARRAY['foo', 'bar', 'baz']); END IF; END; $$ LANGUAGE plpgsql; SELECT is( test_variadic(), 'foo bar baz', 'variadic collect_tap() should simply collect tap' ); /****************************************************************************/ -- Test display_type(). SELECT is( display_type('int4'::regtype, NULL), 'integer', 'display_type(int4)'); SELECT is( display_type('numeric'::regtype, NULL), 'numeric', 'display_type(numeric)'); SELECT is( display_type('numeric'::regtype, 196612), 'numeric(3,0)', 'display_type(numeric, typmod)'); SELECT is( display_type('"char"'::regtype, NULL), '"char"', 'display_type("char")'); SELECT is( display_type('char'::regtype, NULL), 'character', 'display_type(char)'); SELECT is( display_type('timestamp'::regtype, NULL), 'timestamp without time zone', 'display_type(timestamp)'); SELECT is( display_type('timestamptz'::regtype, NULL), 'timestamp with time zone', 'display_type(timestamptz)'); SELECT is( display_type('foo', 'int4'::regtype, NULL), 'foo.integer', 'display_type(foo, int4)'); SELECT is( display_type('HEY', 'numeric'::regtype, NULL), '"HEY".numeric', 'display_type(HEY, numeric)'); SELECT is( display_type('t z', 'int4'::regtype, NULL), '"t z".integer', 'display_type(t z, int4)'); SELECT is( display_type('text'::regtype, NULL), 'text', 'display type_type(text)'); -- Look at a type not in the current schema. CREATE SCHEMA __foo; CREATE DOMAIN __foo.goofy AS text CHECK ( TRUE ); SELECT is( display_type( oid, NULL ), 'goofy', 'display_type(__foo.goofy)' ) FROM pg_type WHERE typname = 'goofy'; -- Look at types with funny names. CREATE DOMAIN __foo."this.that" AS text CHECK (TRUE); SELECT is( display_type( oid, NULL ), '"this.that"', 'display_type(__foo."this.that")' ) FROM pg_type WHERE typname = 'this.that'; CREATE DOMAIN __foo."this"".that" AS text CHECK (TRUE); SELECT is( display_type( oid, NULL ), '"this"".that"', 'display_type(__foo."this"".that")' ) FROM pg_type WHERE typname = 'this".that'; -- Look at types with precision. CREATE DOMAIN __foo."hey"".yoman" AS numeric CHECK (TRUE); SELECT is( display_type( oid, 13 ), '"hey"".yoman"(13)', 'display_type(__foo."hey"".yoman", 13)' ) FROM pg_type WHERE typname = 'hey".yoman'; CREATE DOMAIN "try.this""" AS numeric CHECK (TRUE); SELECT is( display_type( oid, 42 ), '"try.this"""(42)', 'display_type("try.this""", 42)' ) FROM pg_type WHERE typname = 'try.this"'; -- Take care about quoting with/without precision SELECT is(_quote_ident_like('test','public.test'), 'test', 'No quoting is required'); SELECT is(_quote_ident_like('test type','public."test type"'), '"test type"', 'Just quote'); SELECT is(_quote_ident_like('varchar(12)', 'varchar(12)'), 'varchar(12)', 'No quoting is required (with precision)'); SELECT is(_quote_ident_like('test type(123)','myschema."test type"(234)'), '"test type"(123)', 'Quote as type with precision'); SELECT is(_quote_ident_like('test table (123)','public."test table (123)"'), '"test table (123)"', 'Quote as ident without precision'); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/sql/._valueset.sql000644 000765 000024 00000000252 11666501762 017522 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/sql/valueset.sql000644 000765 000024 00000125531 11666501762 017315 0ustar00davidstaff000000 000000 \unset ECHO \i test/setup.sql SELECT plan(349); --SELECT * FROM no_plan(); -- This will be rolled back. :-) SET client_min_messages = warning; CREATE TABLE names ( id SERIAL NOT NULL PRIMARY KEY, name TEXT DEFAULT '' ); RESET client_min_messages; -- Top 100 boy an 100 girl names in 2005. http://www.ssa.gov/OACT/babynames/ INSERT INTO names (name) VALUES ('Jacob'); INSERT INTO names (name) VALUES ('Emily'); INSERT INTO names (name) VALUES ('Michael'); INSERT INTO names (name) VALUES ('Emma'); INSERT INTO names (name) VALUES ('Joshua'); INSERT INTO names (name) VALUES ('Madison'); INSERT INTO names (name) VALUES ('Matthew'); INSERT INTO names (name) VALUES ('Abigail'); INSERT INTO names (name) VALUES ('Ethan'); INSERT INTO names (name) VALUES ('Olivia'); INSERT INTO names (name) VALUES ('Andrew'); INSERT INTO names (name) VALUES ('Isabella'); INSERT INTO names (name) VALUES ('Daniel'); INSERT INTO names (name) VALUES ('Hannah'); INSERT INTO names (name) VALUES ('Anthony'); INSERT INTO names (name) VALUES ('Samantha'); INSERT INTO names (name) VALUES ('Christopher'); INSERT INTO names (name) VALUES ('Ava'); INSERT INTO names (name) VALUES ('Joseph'); INSERT INTO names (name) VALUES ('Ashley'); INSERT INTO names (name) VALUES ('William'); INSERT INTO names (name) VALUES ('Elizabeth'); INSERT INTO names (name) VALUES ('Alexander'); INSERT INTO names (name) VALUES ('Sophia'); INSERT INTO names (name) VALUES ('David'); INSERT INTO names (name) VALUES ('Alexis'); INSERT INTO names (name) VALUES ('Ryan'); INSERT INTO names (name) VALUES ('Grace'); INSERT INTO names (name) VALUES ('Nicholas'); INSERT INTO names (name) VALUES ('Sarah'); INSERT INTO names (name) VALUES ('Tyler'); INSERT INTO names (name) VALUES ('Alyssa'); INSERT INTO names (name) VALUES ('James'); INSERT INTO names (name) VALUES ('Mia'); INSERT INTO names (name) VALUES ('John'); INSERT INTO names (name) VALUES ('Natalie'); INSERT INTO names (name) VALUES ('Jonathan'); INSERT INTO names (name) VALUES ('Chloe'); INSERT INTO names (name) VALUES ('Nathan'); INSERT INTO names (name) VALUES ('Brianna'); INSERT INTO names (name) VALUES ('Samuel'); INSERT INTO names (name) VALUES ('Lauren'); INSERT INTO names (name) VALUES ('Christian'); INSERT INTO names (name) VALUES ('Anna'); INSERT INTO names (name) VALUES ('Noah'); INSERT INTO names (name) VALUES ('Ella'); INSERT INTO names (name) VALUES ('Dylan'); INSERT INTO names (name) VALUES ('Taylor'); INSERT INTO names (name) VALUES ('Benjamin'); INSERT INTO names (name) VALUES ('Kayla'); INSERT INTO names (name) VALUES ('Logan'); INSERT INTO names (name) VALUES ('Hailey'); INSERT INTO names (name) VALUES ('Brandon'); INSERT INTO names (name) VALUES ('Jessica'); INSERT INTO names (name) VALUES ('Gabriel'); INSERT INTO names (name) VALUES ('Victoria'); INSERT INTO names (name) VALUES ('Zachary'); INSERT INTO names (name) VALUES ('Jasmine'); INSERT INTO names (name) VALUES ('Jose'); INSERT INTO names (name) VALUES ('Sydney'); INSERT INTO names (name) VALUES ('Elijah'); INSERT INTO names (name) VALUES ('Julia'); INSERT INTO names (name) VALUES ('Angel'); INSERT INTO names (name) VALUES ('Destiny'); INSERT INTO names (name) VALUES ('Kevin'); INSERT INTO names (name) VALUES ('Morgan'); INSERT INTO names (name) VALUES ('Jack'); INSERT INTO names (name) VALUES ('Kaitlyn'); INSERT INTO names (name) VALUES ('Caleb'); INSERT INTO names (name) VALUES ('Savannah'); INSERT INTO names (name) VALUES ('Justin'); INSERT INTO names (name) VALUES ('Katherine'); INSERT INTO names (name) VALUES ('Robert'); INSERT INTO names (name) VALUES ('Alexandra'); INSERT INTO names (name) VALUES ('Austin'); INSERT INTO names (name) VALUES ('Rachel'); INSERT INTO names (name) VALUES ('Evan'); INSERT INTO names (name) VALUES ('Lily'); INSERT INTO names (name) VALUES ('Thomas'); INSERT INTO names (name) VALUES ('Kaylee'); INSERT INTO names (name) VALUES ('Luke'); INSERT INTO names (name) VALUES ('Megan'); INSERT INTO names (name) VALUES ('Mason'); INSERT INTO names (name) VALUES ('Jennifer'); INSERT INTO names (name) VALUES ('Aidan'); INSERT INTO names (name) VALUES ('Angelina'); INSERT INTO names (name) VALUES ('Jackson'); INSERT INTO names (name) VALUES ('Makayla'); INSERT INTO names (name) VALUES ('Isaiah'); INSERT INTO names (name) VALUES ('Allison'); INSERT INTO names (name) VALUES ('Jordan'); INSERT INTO names (name) VALUES ('Maria'); INSERT INTO names (name) VALUES ('Gavin'); INSERT INTO names (name) VALUES ('Brooke'); INSERT INTO names (name) VALUES ('Connor'); INSERT INTO names (name) VALUES ('Trinity'); INSERT INTO names (name) VALUES ('Isaac'); INSERT INTO names (name) VALUES ('Faith'); INSERT INTO names (name) VALUES ('Aiden'); INSERT INTO names (name) VALUES ('Lillian'); INSERT INTO names (name) VALUES ('Jason'); INSERT INTO names (name) VALUES ('Mackenzie'); INSERT INTO names (name) VALUES ('Cameron'); INSERT INTO names (name) VALUES ('Sofia'); INSERT INTO names (name) VALUES ('Hunter'); INSERT INTO names (name) VALUES ('Riley'); INSERT INTO names (name) VALUES ('Jayden'); INSERT INTO names (name) VALUES ('Haley'); INSERT INTO names (name) VALUES ('Juan'); INSERT INTO names (name) VALUES ('Gabrielle'); INSERT INTO names (name) VALUES ('Charles'); INSERT INTO names (name) VALUES ('Nicole'); INSERT INTO names (name) VALUES ('Aaron'); INSERT INTO names (name) VALUES ('Kylie'); INSERT INTO names (name) VALUES ('Lucas'); INSERT INTO names (name) VALUES ('Zoe'); INSERT INTO names (name) VALUES ('Luis'); INSERT INTO names (name) VALUES ('Katelyn'); INSERT INTO names (name) VALUES ('Owen'); INSERT INTO names (name) VALUES ('Paige'); INSERT INTO names (name) VALUES ('Landon'); INSERT INTO names (name) VALUES ('Gabriella'); INSERT INTO names (name) VALUES ('Diego'); INSERT INTO names (name) VALUES ('Jenna'); INSERT INTO names (name) VALUES ('Brian'); INSERT INTO names (name) VALUES ('Kimberly'); INSERT INTO names (name) VALUES ('Adam'); INSERT INTO names (name) VALUES ('Stephanie'); INSERT INTO names (name) VALUES ('Adrian'); INSERT INTO names (name) VALUES ('Andrea'); INSERT INTO names (name) VALUES ('Eric'); INSERT INTO names (name) VALUES ('Alexa'); INSERT INTO names (name) VALUES ('Kyle'); INSERT INTO names (name) VALUES ('Avery'); INSERT INTO names (name) VALUES ('Ian'); INSERT INTO names (name) VALUES ('Leah'); INSERT INTO names (name) VALUES ('Nathaniel'); INSERT INTO names (name) VALUES ('Nevaeh'); INSERT INTO names (name) VALUES ('Carlos'); INSERT INTO names (name) VALUES ('Madeline'); INSERT INTO names (name) VALUES ('Alex'); INSERT INTO names (name) VALUES ('Evelyn'); INSERT INTO names (name) VALUES ('Bryan'); INSERT INTO names (name) VALUES ('Mary'); INSERT INTO names (name) VALUES ('Jesus'); INSERT INTO names (name) VALUES ('Maya'); INSERT INTO names (name) VALUES ('Julian'); INSERT INTO names (name) VALUES ('Michelle'); INSERT INTO names (name) VALUES ('Sean'); INSERT INTO names (name) VALUES ('Sara'); INSERT INTO names (name) VALUES ('Hayden'); INSERT INTO names (name) VALUES ('Jada'); INSERT INTO names (name) VALUES ('Carter'); INSERT INTO names (name) VALUES ('Audrey'); INSERT INTO names (name) VALUES ('Jeremiah'); INSERT INTO names (name) VALUES ('Brooklyn'); INSERT INTO names (name) VALUES ('Cole'); INSERT INTO names (name) VALUES ('Vanessa'); INSERT INTO names (name) VALUES ('Brayden'); INSERT INTO names (name) VALUES ('Amanda'); INSERT INTO names (name) VALUES ('Wyatt'); INSERT INTO names (name) VALUES ('Rebecca'); INSERT INTO names (name) VALUES ('Chase'); INSERT INTO names (name) VALUES ('Caroline'); INSERT INTO names (name) VALUES ('Steven'); INSERT INTO names (name) VALUES ('Ariana'); INSERT INTO names (name) VALUES ('Timothy'); INSERT INTO names (name) VALUES ('Amelia'); INSERT INTO names (name) VALUES ('Dominic'); INSERT INTO names (name) VALUES ('Mariah'); INSERT INTO names (name) VALUES ('Sebastian'); INSERT INTO names (name) VALUES ('Jordan'); INSERT INTO names (name) VALUES ('Xavier'); INSERT INTO names (name) VALUES ('Jocelyn'); INSERT INTO names (name) VALUES ('Jaden'); INSERT INTO names (name) VALUES ('Arianna'); INSERT INTO names (name) VALUES ('Jesse'); INSERT INTO names (name) VALUES ('Isabel'); INSERT INTO names (name) VALUES ('Seth'); INSERT INTO names (name) VALUES ('Marissa'); INSERT INTO names (name) VALUES ('Devin'); INSERT INTO names (name) VALUES ('Autumn'); INSERT INTO names (name) VALUES ('Antonio'); INSERT INTO names (name) VALUES ('Melanie'); INSERT INTO names (name) VALUES ('Miguel'); INSERT INTO names (name) VALUES ('Aaliyah'); INSERT INTO names (name) VALUES ('Richard'); INSERT INTO names (name) VALUES ('Gracie'); INSERT INTO names (name) VALUES ('Colin'); INSERT INTO names (name) VALUES ('Claire'); INSERT INTO names (name) VALUES ('Cody'); INSERT INTO names (name) VALUES ('Isabelle'); INSERT INTO names (name) VALUES ('Alejandro'); INSERT INTO names (name) VALUES ('Molly'); INSERT INTO names (name) VALUES ('Caden'); INSERT INTO names (name) VALUES ('Mya'); INSERT INTO names (name) VALUES ('Blake'); INSERT INTO names (name) VALUES ('Diana'); INSERT INTO names (name) VALUES ('Kaden'); INSERT INTO names (name) VALUES ('Katie'); CREATE TABLE annames AS SELECT id, name FROM names WHERE name like 'An%'; -- We'll use these prepared statements. PREPARE anames AS SELECT id, name FROM names WHERE name like 'An%'; PREPARE expect AS VALUES (11, 'Andrew'), ( 44, 'Anna'), (15, 'Anthony'), (183, 'Antonio'), (86, 'Angelina'), (130, 'Andrea'), (63, 'Angel'); /****************************************************************************/ -- First, test _temptable. PREPARE "something cool" AS VALUES (1, 2), (3, 4); SELECT is( _temptable( '"something cool"', '__spacenames__' ), '__spacenames__', 'Should create a temp table for a prepared statement with space and values' ); SELECT has_table('__spacenames__' ); SELECT is( _temptable('VALUES (1, 2), (3, 5)', '__somevals__'), '__somevals__', 'Should create a temp table for a values statement' ); SELECT has_table('__somevals__'); /****************************************************************************/ -- Now test set_eq(). SELECT * FROM check_test( set_eq( 'anames', 'expect', 'whatever' ), true, 'set_eq(prepared, prepared, desc)', 'whatever', '' ); SELECT * FROM check_test( set_eq( 'anames', 'expect' ), true, 'set_eq(prepared, prepared)', '', '' ); -- Pass a full SQL statement for the prepared statements. SELECT * FROM check_test( set_eq( 'EXECUTE anames', 'EXECUTE expect' ), true, 'set_eq(execute, execute, desc)', '', '' ); -- Make sure that dupes are disregarded. SELECT * FROM check_test( set_eq( 'VALUES (1, ''Anna'')', 'VALUES (1, ''Anna''), (1, ''Anna'')' ), true, 'set_eq(values, dupe values)', '', '' ); -- Try some failures. SELECT * FROM check_test( set_eq( 'SELECT id, name FROM annames WHERE name <> ''Anna''', 'expect' ), false, 'set_eq(select, prepared) fail missing', '', ' Missing records: (44,Anna)' ); SELECT * FROM check_test( set_eq( 'SELECT id, name FROM annames WHERE name NOT IN (''Anna'', ''Angelina'')', 'expect' ), false, 'set_eq(select, prepared) fail missings', '', E' Missing records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); -- Handle failure due to column mismatch. SELECT * FROM check_test( set_eq( 'VALUES (1, ''foo''), (2, ''bar'')', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'set_eq(values, values) fail mismatch', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( set_eq( 'VALUES (1), (2)', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'set_eq(values, values) fail column count', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); /****************************************************************************/ -- Now test bag_eq(). SELECT * FROM check_test( bag_eq( 'anames', 'expect', 'whatever' ), true, 'bag_eq(prepared, prepared, desc)', 'whatever', '' ); SELECT * FROM check_test( bag_eq( 'anames', 'expect' ), true, 'bag_eq(prepared, prepared)', '', '' ); -- Pass a full SQL statement for the prepared statements. SELECT * FROM check_test( bag_eq( 'EXECUTE anames', 'EXECUTE expect' ), true, 'bag_eq(execute, execute)', '', '' ); -- Compare with dupes. SELECT * FROM check_test( bag_eq( 'VALUES (1, ''Anna''), (86, ''Angelina''), (1, ''Anna'')', 'VALUES (1, ''Anna''), (1, ''Anna''), (86, ''Angelina'')' ), true, 'bag_eq(dupe values, dupe values)', '', '' ); -- And now some failures. SELECT * FROM check_test( bag_eq( 'SELECT id, name FROM annames WHERE name <> ''Anna''', 'expect' ), false, 'bag_eq(select, prepared) fail missing', '', ' Missing records: (44,Anna)' ); SELECT * FROM check_test( bag_eq( 'SELECT id, name FROM annames WHERE name NOT IN (''Anna'', ''Angelina'')', 'expect' ), false, 'bag_eq(select, prepared) fail missings', '', E' Missing records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); -- Handle failure due to column mismatch. SELECT * FROM check_test( bag_eq( 'VALUES (1, ''foo''), (2, ''bar'')', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'bag_eq(values, values) fail mismatch', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( bag_eq( 'VALUES (1), (2)', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'bag_eq(values, values) fail column count', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); -- Handle failure due to missing dupe. SELECT * FROM check_test( bag_eq( 'VALUES (1, ''Anna''), (86, ''Angelina''), (1, ''Anna'')', 'VALUES (1, ''Anna''), (86, ''Angelina'')' ), false, 'bag_eq(values, values) fail missing dupe', '', ' Extra records: (1,Anna)' ); /****************************************************************************/ -- Now test set_eq(). SELECT * FROM check_test( set_ne( 'anames', 'expect' ), false, 'set_ne(prepared, prepared) fail', '', '' ); -- Handle fail with column mismatch. SELECT * FROM check_test( set_ne( 'VALUES (1, ''foo''), (2, ''bar'')', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'set_ne fail with column mismatch', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( set_ne( 'VALUES (1), (2)', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'set_ne fail with different col counts', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); -- Handle fail with a dupe. SELECT * FROM check_test( set_ne( 'VALUES (1, ''Anna''), (86, ''Angelina''), (1, ''Anna'')', 'VALUES (1, ''Anna''), (86, ''Angelina'')' ), false, 'set_ne fail with dupe', '', '' ); /****************************************************************************/ -- Now test bag_ne(). SELECT * FROM check_test( bag_ne( 'anames', 'expect' ), false, 'bag_ne(prepared, prepared) fail', '', '' ); SELECT * FROM check_test( bag_ne( 'VALUES (1, ''foo''), (2, ''bar'')', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'bag_ne fail with column mismatch', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle pass with a dupe. SELECT * FROM check_test( bag_ne( 'VALUES (1, ''Anna''), (86, ''Angelina''), (1, ''Anna'')', 'VALUES (1, ''Anna''), (86, ''Angelina'')' ), true, 'set_ne pass with dupe', '', '' ); -- Handle fail with column mismatch. SELECT * FROM check_test( bag_ne( 'VALUES (1, ''foo''), (2, ''bar'')', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'bag_ne fail with column mismatch', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( bag_ne( 'VALUES (1), (2)', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'bag_ne fail with different col counts', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); /****************************************************************************/ -- Now test results_eq(). PREPARE anames_ord AS SELECT id, name FROM names WHERE name like 'An%' ORDER BY id; PREPARE expect_ord AS VALUES (11, 'Andrew'), (15, 'Anthony'), ( 44, 'Anna'), (63, 'Angel'), (86, 'Angelina'), (130, 'Andrea'), (183, 'Antonio'); SELECT * FROM check_test( results_eq( 'anames_ord', 'expect_ord', 'whatever' ), true, 'results_eq(prepared, prepared, desc)', 'whatever', '' ); SELECT * FROM check_test( results_eq( 'anames_ord', 'expect_ord' ), true, 'results_eq(prepared, prepared)', '', '' ); -- Pass a full SQL statement for the prepared statements. SELECT * FROM check_test( results_eq( 'EXECUTE anames_ord', 'EXECUTE expect_ord' ), true, 'results_eq(execute, execute)', '', '' ); -- Compare with dupes. SELECT * FROM check_test( results_eq( 'VALUES (1, ''Anna''), (86, ''Angelina''), (1, ''Anna'')', 'VALUES (1, ''Anna''), (86, ''Angelina''), (1, ''Anna'')' ), true, 'results_eq(dupe values, dupe values)', '', '' ); -- Compare with nulls. SELECT * FROM check_test( results_eq( 'VALUES (4, NULL), (86, ''Angelina''), (1, ''Anna'')', 'VALUES (4, NULL), (86, ''Angelina''), (1, ''Anna'')' ), true, 'results_eq(values with null, values with null)', '', '' ); -- Compare only NULLs SELECT * FROM check_test( results_eq( 'VALUES (NULL, NULL), (NULL, NULL)', 'VALUES (NULL, NULL), (NULL, NULL)' ), true, 'results_eq(nulls, nulls)', '', '' ); -- Compare only NULLs SELECT * FROM check_test( results_eq( 'VALUES (NULL, NULL), (NULL, NULL)', 'VALUES (NULL, NULL)' ), false, 'results_eq(nulls, nulls) fail', '', ' Results differ beginning at row 2: have: (,) want: NULL' ); -- Now when the last row is missing. SELECT * FROM check_test( results_eq( 'SELECT id, name FROM annames WHERE name <> ''Antonio''', 'anames_ord' ), false, 'results_eq(select, prepared) fail missing last row', '', ' Results differ beginning at row 7: have: NULL want: (183,Antonio)' ); -- Invert that. SELECT * FROM check_test( results_eq( 'anames_ord', 'SELECT id, name FROM annames WHERE name <> ''Antonio''' ), false, 'results_eq(prepared, select) fail missing first row', '', ' Results differ beginning at row 7: have: (183,Antonio) want: NULL' ); -- Compare with missing dupe. SELECT * FROM check_test( results_eq( 'VALUES (1, ''Anna''), (86, ''Angelina''), (1, ''Anna'')', 'VALUES (1, ''Anna''), (86, ''Angelina'')' ), false, 'results_eq(values dupe, values)', '', ' Results differ beginning at row 3: have: (1,Anna) want: NULL' ); -- Handle failure with null. SELECT * FROM check_test( results_eq( 'VALUES (1, NULL), (86, ''Angelina'')', 'VALUES (1, ''Anna''), (86, ''Angelina'')' ), false, 'results_eq(values null, values)', '', ' Results differ beginning at row 1: have: (1,) want: (1,Anna)' ); -- Handle failure due to column mismatch. SELECT * FROM check_test( results_eq( 'VALUES (1, ''foo''), (2, ''bar'')', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'results_eq(values, values) mismatch', '', CASE WHEN pg_version_num() < 80400 THEN ' Results differ beginning at row 1:' ELSE ' Columns differ between queries:' END || ' have: (1,foo) want: (foo,1)' ); -- Handle failure due to more subtle column mismatch, valid only on 8.4. CREATE OR REPLACE FUNCTION subtlefail() RETURNS SETOF TEXT AS $$ DECLARE tap record; BEGIN IF pg_version_num() < 80400 THEN -- 8.3 and earlier cast records to text, so subtlety is out. RETURN NEXT pass('results_eq(values, values) subtle mismatch should fail'); RETURN NEXT pass('results_eq(values, values) subtle mismatch should have the proper description'); RETURN NEXT pass('results_eq(values, values) subtle mismatch should have the proper diagnostics'); ELSE -- 8.4 does true record comparisions, yay! FOR tap IN SELECT * FROM check_test( results_eq( 'VALUES (1, ''foo''::varchar), (2, ''bar''::varchar)', 'VALUES (1, ''foo''), (2, ''bar'')' ), false, 'results_eq(values, values) subtle mismatch', '', ' Columns differ between queries: have: (1,foo) want: (1,foo)' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; END IF; RETURN; END; $$ LANGUAGE plpgsql; SELECT * FROM subtlefail(); -- Handle failure due to column count mismatch. SELECT * FROM check_test( results_eq( 'VALUES (1), (2)', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'results_eq(values, values) fail column count', '', CASE WHEN pg_version_num() < 80400 THEN ' Results differ beginning at row 1:' ELSE ' Columns differ between queries:' END || ' have: (1) want: (foo,1)' ); -- Compare with cursors. DECLARE cwant CURSOR FOR SELECT id, name FROM names WHERE name like 'An%' ORDER BY id; DECLARE chave CURSOR FOR SELECT id, name from annames ORDER BY id; -- Mix cursors and prepared statements PREPARE annames_ord AS VALUES (11, 'Andrew'), (15, 'Anthony'), ( 44, 'Anna'), (63, 'Angel'), (86, 'Angelina'), (130, 'Andrea'), (183, 'Antonio'); MOVE BACKWARD ALL IN cwant; SELECT * FROM check_test( results_eq( 'cwant'::refcursor, 'annames_ord' ), true, 'results_eq(cursor, prepared)', '', '' ); SELECT * FROM check_test( results_eq( 'annames_ord', 'chave'::refcursor ), true, 'results_eq(prepared, cursor)', '', '' ); /****************************************************************************/ -- Now test set_has(). SELECT * FROM check_test( set_has( 'anames', 'expect', 'whatever' ), true, 'set_has( prepared, prepared, description )', 'whatever', '' ); PREPARE subset AS VALUES (11, 'Andrew'), ( 44, 'Anna'), (63, 'Angel'); SELECT * FROM check_test( set_has( 'anames', 'subset' ), true, 'set_has( prepared, subprepared )', '', '' ); SELECT * FROM check_test( set_has( 'EXECUTE anames', 'EXECUTE subset' ), true, 'set_has( execute, execute )', '', '' ); -- Make sure that dupes are ignored. SELECT * FROM check_test( set_has( 'anames', 'VALUES (44, ''Anna''), (44, ''Anna'')' ), true, 'set_has( prepared, dupes )', '', '' ); SELECT * FROM check_test( set_has( 'VALUES (44, ''Anna''), (44, ''Anna'')', 'VALUES(44, ''Anna'')' ), true, 'set_has( dupes, values )', '', '' ); -- Check failures. SELECT * FROM check_test( set_has( 'SELECT id, name FROM annames WHERE name <> ''Anna''', 'expect' ), false, 'set_has( missing1, expect )', '', ' Missing records: (44,Anna)' ); SELECT * FROM check_test( set_has( 'SELECT id, name FROM annames WHERE name NOT IN (''Anna'', ''Angelina'')', 'expect' ), false, 'set_has(missing2, expect )', '', E' Missing records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); -- Handle failure due to column mismatch. SELECT * FROM check_test( set_has( 'VALUES (1, ''foo''), (2, ''bar'')', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'set_has((int,text), (text,int))', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( set_has( 'VALUES (1), (2)', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'set_has((int), (text,int))', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); /****************************************************************************/ -- Now test bag_has(). SELECT * FROM check_test( bag_has( 'anames', 'expect', 'whatever' ), true, 'bag_has( prepared, prepared, description )', 'whatever', '' ); SELECT * FROM check_test( bag_has( 'anames', 'subset' ), true, 'bag_has( prepared, subprepared )', '', '' ); SELECT * FROM check_test( bag_has( 'EXECUTE anames', 'EXECUTE subset' ), true, 'bag_has( execute, execute )', '', '' ); -- Make sure that dupes are not ignored. SELECT * FROM check_test( bag_has( 'anames', 'VALUES (44, ''Anna''), (44, ''Anna'')' ), false, 'bag_has( prepared, dupes )', '', ' Missing records: (44,Anna)' ); SELECT * FROM check_test( bag_has( 'VALUES (44, ''Anna''), (44, ''Anna'')', 'VALUES(44, ''Anna'')' ), true, 'bag_has( dupes, values )', '', '' ); SELECT * FROM check_test( bag_has( 'SELECT id, name FROM annames WHERE name <> ''Anna''', 'expect' ), false, 'bag_has( missing1, expect )', '', ' Missing records: (44,Anna)' ); SELECT * FROM check_test( bag_has( 'SELECT id, name FROM annames WHERE name NOT IN (''Anna'', ''Angelina'')', 'expect' ), false, 'bag_has(missing2, expect )', '', E' Missing records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); -- Handle failure due to column mismatch. SELECT * FROM check_test( bag_has( 'VALUES (1, ''foo''), (2, ''bar'')', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'bag_has((int,text), (text,int))', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( bag_has( 'VALUES (1), (2)', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'bag_has((int), (text,int))', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); /****************************************************************************/ -- Now test set_hasnt(). PREPARE others AS VALUES ( 44, 'Larry' ), (52, 'Tom'), (23, 'Damian' ); SELECT * FROM check_test( set_hasnt( 'anames', 'others', 'whatever' ), true, 'set_hasnt( prepared, prepared, description )', 'whatever', '' ); SELECT * FROM check_test( set_hasnt( 'anames', 'others' ), true, 'set_hasnt( prepared, prepared, description )', '', '' ); SELECT * FROM check_test( set_hasnt( 'EXECUTE anames', 'EXECUTE others' ), true, 'set_hasnt( execute, execute )', '', '' ); -- Make sure that dupes are ignored. SELECT * FROM check_test( set_hasnt( 'anames', 'VALUES (44, ''Bob''), (44, ''Bob'')' ), true, 'set_hasnt( prepared, dupes )', '', '' ); SELECT * FROM check_test( set_hasnt( 'anames', 'VALUES (44,''Anna'')' ), false, 'set_hasnt( prepared, value )', '', ' Extra records: (44,Anna)' ); SELECT * FROM check_test( set_hasnt( 'anames', 'VALUES (44, ''Anna''), (86, ''Angelina'')' ), false, 'set_hasnt( prepared, values )', '', E' Extra records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); -- Handle failure due to column mismatch. SELECT * FROM check_test( set_hasnt( 'VALUES (1, ''foo''), (2, ''bar'')', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'set_hasnt((int,text), (text,int))', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( set_hasnt( 'VALUES (1), (2)', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'set_hasnt((int), (text,int))', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); /****************************************************************************/ -- Now test bag_hasnt(). SELECT * FROM check_test( bag_hasnt( 'anames', 'others', 'whatever' ), true, 'bag_hasnt( prepared, prepared, description )', 'whatever', '' ); SELECT * FROM check_test( bag_hasnt( 'anames', 'others' ), true, 'bag_hasnt( prepared, prepared, description )', '', '' ); SELECT * FROM check_test( bag_hasnt( 'EXECUTE anames', 'EXECUTE others' ), true, 'bag_hasnt( execute, execute )', '', '' ); SELECT * FROM check_test( bag_hasnt( 'anames', 'VALUES (44,''Anna'')' ), false, 'bag_hasnt( prepared, value )', '', ' Extra records: (44,Anna)' ); SELECT * FROM check_test( bag_hasnt( 'anames', 'VALUES (44, ''Anna''), (86, ''Angelina'')' ), false, 'bag_hasnt( prepared, values )', '', E' Extra records: [(](44,Anna|86,Angelina)[)] [(](44,Anna|86,Angelina)[)]', true ); -- Handle failure due to column mismatch. SELECT * FROM check_test( bag_hasnt( 'VALUES (1, ''foo''), (2, ''bar'')', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'bag_hasnt((int,text), (text,int))', '', ' Columns differ between queries: have: (integer,text) want: (text,integer)' ); -- Handle failure due to column count mismatch. SELECT * FROM check_test( bag_hasnt( 'VALUES (1), (2)', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'bag_hasnt((int), (text,int))', '', ' Columns differ between queries: have: (integer) want: (text,integer)' ); -- Make sure that dupes are not ignored. SELECT * FROM check_test( bag_hasnt( 'VALUES (44, ''Anna''), (44, ''Anna'')', 'VALUES (44, ''Anna''), (44, ''Anna'')' ), false, 'bag_hasnt( dupes, dupes )', '', ' Extra records: (44,Anna) (44,Anna)' ); -- But a dupe that appears only once should be in the list only once. SELECT * FROM check_test( bag_hasnt( 'VALUES (44, ''Anna'')', 'VALUES (44, ''Anna''), (44, ''Anna'')' ), false, 'bag_hasnt( value, dupes )', '', ' Extra records: (44,Anna)' ); /****************************************************************************/ -- Test set_eq() with an array argument. PREPARE justnames AS VALUES ('Andrew'), ('Antonio'), ('Angelina'), ('Anna'), ('Anthony'), ('Andrea'), ('Angel'); SELECT * FROM check_test( set_eq( 'justnames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ], 'whatever' ), true, 'set_eq(prepared, array, desc)', 'whatever', '' ); SELECT * FROM check_test( set_eq( 'justnames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), true, 'set_eq(prepared, array)', '', '' ); SELECT * FROM check_test( set_eq( 'justnames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel', 'Andrew', 'Anna' ] ), true, 'set_eq(prepared, dupe array)', '', '' ); -- Fail with an extra record. SELECT * FROM check_test( set_eq( 'justnames', ARRAY['Andrew', 'Anna', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'set_eq(prepared, array) extra record', '', ' Extra records: (Anthony)' ); -- Fail with a missing record. SELECT * FROM check_test( set_eq( 'justnames', ARRAY['Andrew', 'Anna', 'Anthony', 'Alan', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'set_eq(prepared, array) missing record', '', ' Missing records: (Alan)' ); -- Fail with incompatible columns. SELECT * FROM check_test( set_eq( 'justnames', ARRAY[1, 2, 3] ), false, 'set_eq(sql, array) incompatible types', '', ' Columns differ between queries: have: (text) want: (integer)' ); /****************************************************************************/ -- Test bag_eq() with an array argument. SELECT * FROM check_test( bag_eq( 'justnames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ], 'whatever' ), true, 'bag_eq(prepared, array, desc)', 'whatever', '' ); SELECT * FROM check_test( bag_eq( 'justnames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), true, 'bag_eq(prepared, array)', '', '' ); SELECT * FROM check_test( bag_eq( 'justnames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel', 'Anna' ] ), false, 'bag_eq(prepared, dupe array) fail', '', ' Missing records: (Anna)' ); -- Fail with an extra record. SELECT * FROM check_test( bag_eq( 'justnames', ARRAY['Andrew', 'Anna', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'bag_eq(prepared, array) extra record', '', ' Extra records: (Anthony)' ); -- Fail with a missing record. SELECT * FROM check_test( bag_eq( 'justnames', ARRAY['Andrew', 'Anna', 'Anthony', 'Alan', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'bag_eq(prepared, array) missing record', '', ' Missing records: (Alan)' ); -- Fail with incompatible columns. SELECT * FROM check_test( bag_eq( 'justnames', ARRAY[1, 2, 3] ), false, 'bag_eq(prepared, array) incompatible types', '', ' Columns differ between queries: have: (text) want: (integer)' ); /****************************************************************************/ -- Test set_ne() with an array argument. SELECT * FROM check_test( set_ne( 'justnames', ARRAY['Andrew', 'Anna' ], 'whatever' ), true, 'set_ne(prepared, array, desc)', 'whatever', '' ); SELECT * FROM check_test( set_ne( 'justnames', ARRAY['Andrew', 'Anna' ] ), true, 'set_ne(prepared, array)', '', '' ); SELECT * FROM check_test( set_ne( 'justnames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'set_ne(prepared, array) fail', '', '' ); -- Fail with dupes. SELECT * FROM check_test( set_ne( 'justnames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel', 'Anna' ] ), false, 'set_ne(prepared, dupes array) fail', '', '' ); -- Fail with incompatible columns. SELECT * FROM check_test( set_ne( 'justnames', ARRAY[1, 2, 3] ), false, 'set_ne(sql, array) incompatible types', '', ' Columns differ between queries: have: (text) want: (integer)' ); /****************************************************************************/ -- Test bag_ne() with an array argument. SELECT * FROM check_test( bag_ne( 'justnames', ARRAY['Andrew', 'Anna' ], 'whatever' ), true, 'bag_ne(prepared, array, desc)', 'whatever', '' ); SELECT * FROM check_test( bag_ne( 'justnames', ARRAY['Andrew', 'Anna' ] ), true, 'bag_ne(prepared, array)', '', '' ); SELECT * FROM check_test( bag_ne( 'justnames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel' ] ), false, 'bag_ne(prepared, array) fail', '', '' ); -- Pass with dupes. SELECT * FROM check_test( bag_ne( 'justnames', ARRAY['Andrew', 'Anna', 'Anthony', 'Antonio', 'Angelina', 'Andrea', 'Angel', 'Anna' ] ), true, 'bag_ne(prepared, dupes array)', '', '' ); -- Fail with incompatible columns. SELECT * FROM check_test( bag_ne( 'justnames', ARRAY[1, 2, 3] ), false, 'bag_ne(prepared, array) incompatible types', '', ' Columns differ between queries: have: (text) want: (integer)' ); /****************************************************************************/ -- Now test results_eq() with an array argument. PREPARE ordnames AS VALUES ('Andrea'), ('Andrew'), ('Angel'), ('Angelina'), ('Anna'), ('Anthony'), ('Antonio'); SELECT * FROM check_test( results_eq( 'ordnames', ARRAY['Andrea', 'Andrew', 'Angel', 'Angelina', 'Anna', 'Anthony', 'Antonio' ], 'whatever' ), true, 'results_eq(prepared, array, desc)', 'whatever', '' ); SELECT * FROM check_test( results_eq( 'ordnames', ARRAY['Andrea', 'Andrew', 'Angel', 'Angelina', 'Anna', 'Anthony', 'Antonio' ] ), true, 'results_eq(prepared, array)', '', '' ); SELECT * FROM check_test( results_eq( 'ordnames', ARRAY['Andrea', 'Andrew', 'Angel', 'Angelina', 'Anna', 'Anthony' ] ), false, 'results_eq(prepared, array) extra record', '', ' Results differ beginning at row 7: have: (Antonio) want: NULL' ); /****************************************************************************/ -- Now test results_eq(). PREPARE nenames_ord AS SELECT id, name FROM names WHERE name like 'An%' ORDER BY id; PREPARE nexpect_ord AS VALUES (15, 'Anthony'), ( 44, 'Anna'), (11, 'Andrew'), (63, 'Angel'), (86, 'Angelina'), (130, 'Andrea'), (183, 'Antonio'); SELECT * FROM check_test( results_ne( 'nenames_ord', 'nexpect_ord', 'whatever' ), true, 'results_ne(prepared, prepared, desc)', 'whatever', '' ); SELECT * FROM check_test( results_ne( 'nenames_ord', 'nexpect_ord' ), true, 'results_ne(prepared, prepared)', '', '' ); -- Pass a full SQL statement for the prepared statements. SELECT * FROM check_test( results_ne( 'EXECUTE nenames_ord', 'EXECUTE nexpect_ord' ), true, 'results_ne(execute, execute)', '', '' ); -- Compare with dupes. SELECT * FROM check_test( results_ne( 'VALUES (1, ''Anna''), (86, ''Angelina''), (1, ''Anna'')', 'VALUES (2, ''Anna''), (86, ''Angelina''), (2, ''Anna'')' ), true, 'results_ne(dupe values, dupe values)', '', '' ); -- Compare with nulls. SELECT * FROM check_test( results_ne( 'VALUES (4, NULL), (86, ''Angelina''), (1, NULL)', 'VALUES (4, NULL), (86, ''Angelina''), (1, ''Anna'')' ), true, 'results_ne(values with null, values with null)', '', '' ); -- Compare only NULLs SELECT * FROM check_test( results_ne( 'VALUES (NULL, NULL), (NULL, NULL), (NULL, NULL)', 'VALUES (NULL, NULL), (NULL, NULL)' ), true, 'results_ne(nulls, nulls)', '', '' ); -- Compare with missing dupe. SELECT * FROM check_test( results_ne( 'VALUES (1, ''Anna''), (86, ''Angelina''), (1, ''Anna'')', 'VALUES (1, ''Anna''), (86, ''Angelina'')' ), true, 'results_ne(values dupe, values)', '', '' ); -- Handle pass with null. SELECT * FROM check_test( results_ne( 'VALUES (1, NULL), (86, ''Angelina'')', 'VALUES (1, ''Anna''), (86, ''Angelina'')' ), true, 'results_ne(values null, values)', '', '' ); -- Handle failure due to more subtle column mismatch, valid only on 8.4. CREATE OR REPLACE FUNCTION subtlefail() RETURNS SETOF TEXT AS $$ DECLARE tap record; BEGIN IF pg_version_num() < 80400 THEN -- 8.3 and earlier cast records to text, so subtlety is out. RETURN NEXT pass('results_ne(values, values) mismatch should fail'); RETURN NEXT pass('results_ne(values, values) mismatch should have the proper description'); RETURN NEXT pass('results_ne(values, values) mismatch should have the proper diagnostics'); RETURN NEXT pass('results_ne(values, values) subtle mismatch should fail'); RETURN NEXT pass('results_ne(values, values) subtle mismatch should have the proper description'); RETURN NEXT pass('results_ne(values, values) subtle mismatch should have the proper diagnostics'); RETURN NEXT pass('results_ne(values, values) fail column count should fail'); RETURN NEXT pass('results_ne(values, values) fail column count should have the proper description'); RETURN NEXT pass('results_ne(values, values) fail column count should have the proper diagnostics'); ELSE -- 8.4 does true record comparisions, yay! -- Handle failure due to column mismatch. FOR tap IN SELECT * FROM check_test( results_ne( 'VALUES (1, ''foo''), (2, ''bar'')', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'results_ne(values, values) mismatch', '', ' Columns differ between queries: have: (1,foo) want: (foo,1)' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; -- Handle failure due to subtle column mismatch. FOR tap IN SELECT * FROM check_test( results_ne( 'VALUES (1, ''foo''::varchar), (2, ''bar''::varchar)', 'VALUES (1, ''foo''), (2, ''bar'')' ), false, 'results_ne(values, values) subtle mismatch', '', ' Columns differ between queries: have: (1,foo) want: (1,foo)' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; -- Handle failure due to column count mismatch. FOR tap IN SELECT * FROM check_test( results_ne( 'VALUES (1), (2)', 'VALUES (''foo'', 1), (''bar'', 2)' ), false, 'results_ne(values, values) fail column count', '', ' Columns differ between queries: have: (1) want: (foo,1)' ) AS a(b) LOOP RETURN NEXT tap.b; END LOOP; END IF; RETURN; END; $$ LANGUAGE plpgsql; SELECT * FROM subtlefail(); -- Compare with cursors. CLOSE cwant; CLOSE chave; DECLARE cwant CURSOR FOR SELECT id, name FROM names WHERE name like 'An%' ORDER BY id; DECLARE chave CURSOR FOR SELECT id, name from annames ORDER BY id; -- Mix cursors and prepared statements MOVE BACKWARD ALL IN cwant; SELECT * FROM check_test( results_ne( 'cwant'::refcursor, 'annames_ord' ), false, 'results_ne(cursor, prepared)', '', '' ); MOVE BACKWARD ALL IN chave; SELECT * FROM check_test( results_ne( 'annames_ord', 'chave'::refcursor ), false, 'results_ne(prepared, cursor)', '', '' ); /****************************************************************************/ -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; pgtap-0.90.0/test/expected/._aretap.out000644 000765 000024 00000000252 11666501762 020160 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/aretap.out000644 000765 000024 00000067512 11666501762 017757 0ustar00davidstaff000000 000000 \unset ECHO 1..399 ok 1 - tablespaces_are(tablespaces, desc) should pass ok 2 - tablespaces_are(tablespaces, desc) should have the proper description ok 3 - tablespaces_are(tablespaces, desc) should have the proper diagnostics ok 4 - tablespaces_are(tablespaces) should pass ok 5 - tablespaces_are(tablespaces) should have the proper description ok 6 - tablespaces_are(tablespaces) should have the proper diagnostics ok 7 - tablespaces_are(tablespaces, desc) missing should fail ok 8 - tablespaces_are(tablespaces, desc) missing should have the proper description ok 9 - tablespaces_are(tablespaces, desc) missing should have the proper diagnostics ok 10 - tablespaces_are(tablespaces, desc) extra should fail ok 11 - tablespaces_are(tablespaces, desc) extra should have the proper description ok 12 - tablespaces_are(tablespaces, desc) extra should have the proper diagnostics ok 13 - tablespaces_are(tablespaces, desc) extras and missing should fail ok 14 - tablespaces_are(tablespaces, desc) extras and missing should have the proper description ok 15 - tablespaces_are(tablespaces, desc) extras and missing should have the proper diagnostics ok 16 - schemas_are(schemas, desc) should pass ok 17 - schemas_are(schemas, desc) should have the proper description ok 18 - schemas_are(schemas, desc) should have the proper diagnostics ok 19 - schemas_are(schemas) should pass ok 20 - schemas_are(schemas) should have the proper description ok 21 - schemas_are(schemas) should have the proper diagnostics ok 22 - schemas_are(schemas, desc) missing should fail ok 23 - schemas_are(schemas, desc) missing should have the proper description ok 24 - schemas_are(schemas, desc) missing should have the proper diagnostics ok 25 - schemas_are(schemas, desc) extras should fail ok 26 - schemas_are(schemas, desc) extras should have the proper description ok 27 - schemas_are(schemas, desc) extras should have the proper diagnostics ok 28 - schemas_are(schemas, desc) missing and extras should fail ok 29 - schemas_are(schemas, desc) missing and extras should have the proper description ok 30 - schemas_are(schemas, desc) missing and extras should have the proper diagnostics ok 31 - tables_are(schema, tables, desc) should pass ok 32 - tables_are(schema, tables, desc) should have the proper description ok 33 - tables_are(schema, tables, desc) should have the proper diagnostics ok 34 - tables_are(schema, tables) should pass ok 35 - tables_are(schema, tables) should have the proper description ok 36 - tables_are(schema, tables) should have the proper diagnostics ok 37 - tables_are(tables) should pass ok 38 - tables_are(tables) should have the proper description ok 39 - tables_are(tables) should have the proper diagnostics ok 40 - tables_are(tables, desc) should pass ok 41 - tables_are(tables, desc) should have the proper description ok 42 - tables_are(tables, desc) should have the proper diagnostics ok 43 - tables_are(schema, tables) missing should fail ok 44 - tables_are(schema, tables) missing should have the proper description ok 45 - tables_are(schema, tables) missing should have the proper diagnostics ok 46 - tables_are(tables) missing should fail ok 47 - tables_are(tables) missing should have the proper description ok 48 - tables_are(tables) missing should have the proper diagnostics ok 49 - tables_are(schema, tables) extra should fail ok 50 - tables_are(schema, tables) extra should have the proper description ok 51 - tables_are(schema, tables) extra should have the proper diagnostics ok 52 - tables_are(tables) extra should fail ok 53 - tables_are(tables) extra should have the proper description ok 54 - tables_are(tables) extra should have the proper diagnostics ok 55 - tables_are(schema, tables) extra and missing should fail ok 56 - tables_are(schema, tables) extra and missing should have the proper description ok 57 - tables_are(schema, tables) extra and missing should have the proper diagnostics ok 58 - tables_are(tables) extra and missing should fail ok 59 - tables_are(tables) extra and missing should have the proper description ok 60 - tables_are(tables) extra and missing should have the proper diagnostics ok 61 - views_are(schema, views, desc) should pass ok 62 - views_are(schema, views, desc) should have the proper description ok 63 - views_are(schema, views, desc) should have the proper diagnostics ok 64 - views_are(schema, views) should pass ok 65 - views_are(schema, views) should have the proper description ok 66 - views_are(schema, views) should have the proper diagnostics ok 67 - views_are(views) should pass ok 68 - views_are(views) should have the proper description ok 69 - views_are(views) should have the proper diagnostics ok 70 - views_are(views, desc) should pass ok 71 - views_are(views, desc) should have the proper description ok 72 - views_are(views, desc) should have the proper diagnostics ok 73 - views_are(schema, views) missing should fail ok 74 - views_are(schema, views) missing should have the proper description ok 75 - views_are(schema, views) missing should have the proper diagnostics ok 76 - views_are(views) missing should fail ok 77 - views_are(views) missing should have the proper description ok 78 - views_are(views) missing should have the proper diagnostics ok 79 - views_are(schema, views) extra should fail ok 80 - views_are(schema, views) extra should have the proper description ok 81 - views_are(schema, views) extra should have the proper diagnostics ok 82 - views_are(views) extra should fail ok 83 - views_are(views) extra should have the proper description ok 84 - views_are(views) extra should have the proper diagnostics ok 85 - views_are(schema, views) extra and missing should fail ok 86 - views_are(schema, views) extra and missing should have the proper description ok 87 - views_are(schema, views) extra and missing should have the proper diagnostics ok 88 - views_are(views) extra and missing should fail ok 89 - views_are(views) extra and missing should have the proper description ok 90 - views_are(views) extra and missing should have the proper diagnostics ok 91 - sequences_are(schema, sequences, desc) should pass ok 92 - sequences_are(schema, sequences, desc) should have the proper description ok 93 - sequences_are(schema, sequences, desc) should have the proper diagnostics ok 94 - sequences_are(schema, sequences) should pass ok 95 - sequences_are(schema, sequences) should have the proper description ok 96 - sequences_are(schema, sequences) should have the proper diagnostics ok 97 - sequences_are(sequences) should pass ok 98 - sequences_are(sequences) should have the proper description ok 99 - sequences_are(sequences) should have the proper diagnostics ok 100 - sequences_are(sequences, desc) should pass ok 101 - sequences_are(sequences, desc) should have the proper description ok 102 - sequences_are(sequences, desc) should have the proper diagnostics ok 103 - sequences_are(schema, sequences) missing should fail ok 104 - sequences_are(schema, sequences) missing should have the proper description ok 105 - sequences_are(schema, sequences) missing should have the proper diagnostics ok 106 - sequences_are(sequences) missing should fail ok 107 - sequences_are(sequences) missing should have the proper description ok 108 - sequences_are(sequences) missing should have the proper diagnostics ok 109 - sequences_are(schema, sequences) extra should fail ok 110 - sequences_are(schema, sequences) extra should have the proper description ok 111 - sequences_are(schema, sequences) extra should have the proper diagnostics ok 112 - sequences_are(sequences) extra should fail ok 113 - sequences_are(sequences) extra should have the proper description ok 114 - sequences_are(sequences) extra should have the proper diagnostics ok 115 - sequences_are(schema, sequences) extra and missing should fail ok 116 - sequences_are(schema, sequences) extra and missing should have the proper description ok 117 - sequences_are(schema, sequences) extra and missing should have the proper diagnostics ok 118 - sequences_are(sequences) extra and missing should fail ok 119 - sequences_are(sequences) extra and missing should have the proper description ok 120 - sequences_are(sequences) extra and missing should have the proper diagnostics ok 121 - functions_are(schema, functions, desc) should pass ok 122 - functions_are(schema, functions, desc) should have the proper description ok 123 - functions_are(schema, functions, desc) should have the proper diagnostics ok 124 - functions_are(schema, functions) should pass ok 125 - functions_are(schema, functions) should have the proper description ok 126 - functions_are(schema, functions, desc) + missing should fail ok 127 - functions_are(schema, functions, desc) + missing should have the proper description ok 128 - functions_are(schema, functions, desc) + missing should have the proper diagnostics ok 129 - functions_are(schema, functions, desc) + extra should fail ok 130 - functions_are(schema, functions, desc) + extra should have the proper description ok 131 - functions_are(schema, functions, desc) + extra should have the proper diagnostics ok 132 - functions_are(schema, functions, desc) + extra & missing should fail ok 133 - functions_are(schema, functions, desc) + extra & missing should have the proper description ok 134 - functions_are(schema, functions, desc) + extra & missing should have the proper diagnostics ok 135 - functions_are(functions, desc) should pass ok 136 - functions_are(functions, desc) should have the proper description ok 137 - functions_are(functions, desc) should have the proper diagnostics ok 138 - functions_are(functions) should pass ok 139 - functions_are(functions) should have the proper description ok 140 - functions_are(functions) should have the proper diagnostics ok 141 - functions_are(functions, desc) + missing should fail ok 142 - functions_are(functions, desc) + missing should have the proper description ok 143 - functions_are(functions, desc) + missing should have the proper diagnostics ok 144 - functions_are(functions, desc) + extra should fail ok 145 - functions_are(functions, desc) + extra should have the proper description ok 146 - functions_are(functions, desc) + extra should have the proper diagnostics ok 147 - functions_are(functions, desc) + extra & missing should fail ok 148 - functions_are(functions, desc) + extra & missing should have the proper description ok 149 - functions_are(functions, desc) + extra & missing should have the proper diagnostics ok 150 - indexes_are(schema, table, indexes, desc) should pass ok 151 - indexes_are(schema, table, indexes, desc) should have the proper description ok 152 - indexes_are(schema, table, indexes, desc) should have the proper diagnostics ok 153 - indexes_are(schema, table, indexes) should pass ok 154 - indexes_are(schema, table, indexes) should have the proper description ok 155 - indexes_are(schema, table, indexes) should have the proper diagnostics ok 156 - indexes_are(schema, table, indexes) + extra should fail ok 157 - indexes_are(schema, table, indexes) + extra should have the proper description ok 158 - indexes_are(schema, table, indexes) + extra should have the proper diagnostics ok 159 - indexes_are(schema, table, indexes) + missing should fail ok 160 - indexes_are(schema, table, indexes) + missing should have the proper description ok 161 - indexes_are(schema, table, indexes) + missing should have the proper diagnostics ok 162 - indexes_are(schema, table, indexes) + extra & missing should fail ok 163 - indexes_are(schema, table, indexes) + extra & missing should have the proper description ok 164 - indexes_are(schema, table, indexes) + extra & missing should have the proper diagnostics ok 165 - indexes_are(table, indexes, desc) should pass ok 166 - indexes_are(table, indexes, desc) should have the proper description ok 167 - indexes_are(table, indexes, desc) should have the proper diagnostics ok 168 - indexes_are(table, indexes) should pass ok 169 - indexes_are(table, indexes) should have the proper description ok 170 - indexes_are(table, indexes) should have the proper diagnostics ok 171 - indexes_are(table, indexes) + extra should fail ok 172 - indexes_are(table, indexes) + extra should have the proper description ok 173 - indexes_are(table, indexes) + extra should have the proper diagnostics ok 174 - indexes_are(table, indexes) + missing should fail ok 175 - indexes_are(table, indexes) + missing should have the proper description ok 176 - indexes_are(table, indexes) + missing should have the proper diagnostics ok 177 - indexes_are(table, indexes) + extra & missing should fail ok 178 - indexes_are(table, indexes) + extra & missing should have the proper description ok 179 - indexes_are(table, indexes) + extra & missing should have the proper diagnostics ok 180 - users_are(users, desc) should pass ok 181 - users_are(users, desc) should have the proper description ok 182 - users_are(users, desc) should have the proper diagnostics ok 183 - users_are(users) should pass ok 184 - users_are(users) should have the proper description ok 185 - users_are(users) should have the proper diagnostics ok 186 - users_are(users, desc) missing should fail ok 187 - users_are(users, desc) missing should have the proper description ok 188 - users_are(users, desc) missing should have the proper diagnostics ok 189 - users_are(users, desc) extras should fail ok 190 - users_are(users, desc) extras should have the proper description ok 191 - users_are(users, desc) extras should have the proper diagnostics ok 192 - users_are(users, desc) missing and extras should fail ok 193 - users_are(users, desc) missing and extras should have the proper description ok 194 - users_are(users, desc) missing and extras should have the proper diagnostics ok 195 - groups_are(groups, desc) should pass ok 196 - groups_are(groups, desc) should have the proper description ok 197 - groups_are(groups, desc) should have the proper diagnostics ok 198 - groups_are(groups) should pass ok 199 - groups_are(groups) should have the proper description ok 200 - groups_are(groups) should have the proper diagnostics ok 201 - groups_are(groups, desc) missing should fail ok 202 - groups_are(groups, desc) missing should have the proper description ok 203 - groups_are(groups, desc) missing should have the proper diagnostics ok 204 - groups_are(groups, desc) extras should fail ok 205 - groups_are(groups, desc) extras should have the proper description ok 206 - groups_are(groups, desc) extras should have the proper diagnostics ok 207 - groups_are(groups, desc) missing and extras should fail ok 208 - groups_are(groups, desc) missing and extras should have the proper description ok 209 - groups_are(groups, desc) missing and extras should have the proper diagnostics ok 210 - languages_are(languages, desc) should pass ok 211 - languages_are(languages, desc) should have the proper description ok 212 - languages_are(languages, desc) should have the proper diagnostics ok 213 - languages_are(languages) should pass ok 214 - languages_are(languages) should have the proper description ok 215 - languages_are(languages) should have the proper diagnostics ok 216 - languages_are(languages, desc) missing should fail ok 217 - languages_are(languages, desc) missing should have the proper description ok 218 - languages_are(languages, desc) missing should have the proper diagnostics ok 219 - languages_are(languages, desc) extras should fail ok 220 - languages_are(languages, desc) extras should have the proper description ok 221 - languages_are(languages, desc) extras should have the proper diagnostics ok 222 - languages_are(languages, desc) missing and extras should fail ok 223 - languages_are(languages, desc) missing and extras should have the proper description ok 224 - languages_are(languages, desc) missing and extras should have the proper diagnostics ok 225 - opclasses_are(schema, opclasses, desc) should pass ok 226 - opclasses_are(schema, opclasses, desc) should have the proper description ok 227 - opclasses_are(schema, opclasses, desc) should have the proper diagnostics ok 228 - opclasses_are(schema, opclasses) should pass ok 229 - opclasses_are(schema, opclasses) should have the proper description ok 230 - opclasses_are(schema, opclasses, desc) + missing should fail ok 231 - opclasses_are(schema, opclasses, desc) + missing should have the proper description ok 232 - opclasses_are(schema, opclasses, desc) + missing should have the proper diagnostics ok 233 - opclasses_are(schema, opclasses, desc) + extra should fail ok 234 - opclasses_are(schema, opclasses, desc) + extra should have the proper description ok 235 - opclasses_are(schema, opclasses, desc) + extra should have the proper diagnostics ok 236 - opclasses_are(schema, opclasses, desc) + extra & missing should fail ok 237 - opclasses_are(schema, opclasses, desc) + extra & missing should have the proper description ok 238 - opclasses_are(schema, opclasses, desc) + extra & missing should have the proper diagnostics ok 239 - opclasses_are(opclasses) should pass ok 240 - opclasses_are(opclasses) should have the proper description ok 241 - opclasses_are(opclasses) should have the proper diagnostics ok 242 - opclasses_are(opclasses, desc) + missing should fail ok 243 - opclasses_are(opclasses, desc) + missing should have the proper description ok 244 - opclasses_are(opclasses, desc) + missing should have the proper diagnostics ok 245 - opclasses_are(opclasses, desc) + extra should fail ok 246 - opclasses_are(opclasses, desc) + extra should have the proper description ok 247 - opclasses_are(opclasses, desc) + extra should have the proper diagnostics ok 248 - opclasses_are(opclasses, desc) + extra & missing should fail ok 249 - opclasses_are(opclasses, desc) + extra & missing should have the proper description ok 250 - opclasses_are(opclasses, desc) + extra & missing should have the proper diagnostics ok 251 - rules_are(schema, table, rules, desc) should pass ok 252 - rules_are(schema, table, rules, desc) should have the proper description ok 253 - rules_are(schema, table, rules, desc) should have the proper diagnostics ok 254 - rules_are(schema, table, rules) should pass ok 255 - rules_are(schema, table, rules) should have the proper description ok 256 - rules_are(schema, table, rules) should have the proper diagnostics ok 257 - rules_are(schema, table, rules) + extra should fail ok 258 - rules_are(schema, table, rules) + extra should have the proper description ok 259 - rules_are(schema, table, rules) + extra should have the proper diagnostics ok 260 - rules_are(schema, table, rules) + missing should fail ok 261 - rules_are(schema, table, rules) + missing should have the proper description ok 262 - rules_are(schema, table, rules) + missing should have the proper diagnostics ok 263 - rules_are(schema, table, rules) + extra & missing should fail ok 264 - rules_are(schema, table, rules) + extra & missing should have the proper description ok 265 - rules_are(schema, table, rules) + extra & missing should have the proper diagnostics ok 266 - rules_are(table, rules, desc) should pass ok 267 - rules_are(table, rules, desc) should have the proper description ok 268 - rules_are(table, rules, desc) should have the proper diagnostics ok 269 - rules_are(table, rules) should pass ok 270 - rules_are(table, rules) should have the proper description ok 271 - rules_are(table, rules) should have the proper diagnostics ok 272 - rules_are(table, rules) + extra should fail ok 273 - rules_are(table, rules) + extra should have the proper description ok 274 - rules_are(table, rules) + extra should have the proper diagnostics ok 275 - rules_are(table, rules) + missing should fail ok 276 - rules_are(table, rules) + missing should have the proper description ok 277 - rules_are(table, rules) + missing should have the proper diagnostics ok 278 - rules_are(table, rules) + extra & missing should fail ok 279 - rules_are(table, rules) + extra & missing should have the proper description ok 280 - rules_are(table, rules) + extra & missing should have the proper diagnostics ok 281 - types_are(schema, types, desc) should pass ok 282 - types_are(schema, types, desc) should have the proper description ok 283 - types_are(schema, types, desc) should have the proper diagnostics ok 284 - types_are(schema, types) should pass ok 285 - types_are(schema, types) should have the proper description ok 286 - types_are(schema, types, desc) + missing should fail ok 287 - types_are(schema, types, desc) + missing should have the proper description ok 288 - types_are(schema, types, desc) + missing should have the proper diagnostics ok 289 - types_are(schema, types, desc) + extra should fail ok 290 - types_are(schema, types, desc) + extra should have the proper description ok 291 - types_are(schema, types, desc) + extra should have the proper diagnostics ok 292 - types_are(schema, types, desc) + extra & missing should fail ok 293 - types_are(schema, types, desc) + extra & missing should have the proper description ok 294 - types_are(schema, types, desc) + extra & missing should have the proper diagnostics ok 295 - types_are(types) should pass ok 296 - types_are(types) should have the proper description ok 297 - types_are(types) should have the proper diagnostics ok 298 - types_are(types, desc) + missing should fail ok 299 - types_are(types, desc) + missing should have the proper description ok 300 - types_are(types, desc) + missing should have the proper diagnostics ok 301 - types_are(types, desc) + extra should fail ok 302 - types_are(types, desc) + extra should have the proper description ok 303 - types_are(types, desc) + extra should have the proper diagnostics ok 304 - types_are(types, desc) + extra & missing should fail ok 305 - types_are(types, desc) + extra & missing should have the proper description ok 306 - types_are(types, desc) + extra & missing should have the proper diagnostics ok 307 - domains_are(schema, domains, desc) should pass ok 308 - domains_are(schema, domains, desc) should have the proper description ok 309 - domains_are(schema, domains, desc) should have the proper diagnostics ok 310 - domains_are(schema, domains) should pass ok 311 - domains_are(schema, domains) should have the proper description ok 312 - domains_are(schema, domains) should have the proper diagnostics ok 313 - domains_are(schema, domains, desc) fail should fail ok 314 - domains_are(schema, domains, desc) fail should have the proper description ok 315 - domains_are(schema, domains, desc) fail should have the proper diagnostics ok 316 - domains_are(schema, domains) fail should fail ok 317 - domains_are(schema, domains) fail should have the proper description ok 318 - domains_are(schema, domains) fail should have the proper diagnostics ok 319 - domains_are(domains, desc) should pass ok 320 - domains_are(domains, desc) should have the proper description ok 321 - domains_are(domains, desc) should have the proper diagnostics ok 322 - domains_are(domains) should pass ok 323 - domains_are(domains) should have the proper description ok 324 - domains_are(domains) should have the proper diagnostics ok 325 - domains_are(domains, desc) fail should fail ok 326 - domains_are(domains, desc) fail should have the proper description ok 327 - domains_are(domains, desc) fail should have the proper diagnostics ok 328 - domains_are(domains) fail should fail ok 329 - domains_are(domains) fail should have the proper description ok 330 - domains_are(domains) fail should have the proper diagnostics ok 331 - casts_are(casts, desc) should pass ok 332 - casts_are(casts, desc) should have the proper description ok 333 - casts_are(casts, desc) should have the proper diagnostics ok 334 - casts_are(casts) should pass ok 335 - casts_are(casts) should have the proper description ok 336 - casts_are(casts) should have the proper diagnostics ok 337 - casts_are(casts, desc) missing should fail ok 338 - casts_are(casts, desc) missing should have the proper description ok 339 - casts_are(casts, desc) missing should have the proper diagnostics ok 340 - casts_are(casts, desc) extra should fail ok 341 - casts_are(casts, desc) extra should have the proper description ok 342 - casts_are(casts, desc) extra should have the proper diagnostics ok 343 - casts_are(casts, desc) extras and missing should fail ok 344 - casts_are(casts, desc) extras and missing should have the proper description ok 345 - casts_are(casts, desc) extras and missing should have the proper diagnostics ok 346 - operators_are(schema, operators, desc) should pass ok 347 - operators_are(schema, operators, desc) should have the proper description ok 348 - operators_are(schema, operators, desc) should have the proper diagnostics ok 349 - operators_are(schema, operators) should pass ok 350 - operators_are(schema, operators) should have the proper description ok 351 - operators_are(schema, operators) should have the proper diagnostics ok 352 - operators_are(schema, operators, desc) fail should fail ok 353 - operators_are(schema, operators, desc) fail should have the proper description ok 354 - operators_are(schema, operators, desc) fail should have the proper diagnostics ok 355 - operators_are(schema, operators) fail should fail ok 356 - operators_are(schema, operators) fail should have the proper description ok 357 - operators_are(schema, operators) fail should have the proper diagnostics ok 358 - operators_are(operators, desc) should pass ok 359 - operators_are(operators, desc) should have the proper description ok 360 - operators_are(operators, desc) should have the proper diagnostics ok 361 - operators_are(operators) should pass ok 362 - operators_are(operators) should have the proper description ok 363 - operators_are(operators) should have the proper diagnostics ok 364 - operators_are(operators, desc) fail should fail ok 365 - operators_are(operators, desc) fail should have the proper description ok 366 - operators_are(operators, desc) fail should have the proper diagnostics ok 367 - operators_are(operators) fail should fail ok 368 - operators_are(operators) fail should have the proper description ok 369 - operators_are(operators) fail should have the proper diagnostics ok 370 - columns_are(schema, table, columns, desc) should pass ok 371 - columns_are(schema, table, columns, desc) should have the proper description ok 372 - columns_are(schema, table, columns, desc) should have the proper diagnostics ok 373 - columns_are(schema, table, columns) should pass ok 374 - columns_are(schema, table, columns) should have the proper description ok 375 - columns_are(schema, table, columns) should have the proper diagnostics ok 376 - columns_are(schema, table, columns) + extra should fail ok 377 - columns_are(schema, table, columns) + extra should have the proper description ok 378 - columns_are(schema, table, columns) + extra should have the proper diagnostics ok 379 - columns_are(schema, table, columns) + missing should fail ok 380 - columns_are(schema, table, columns) + missing should have the proper description ok 381 - columns_are(schema, table, columns) + missing should have the proper diagnostics ok 382 - columns_are(schema, table, columns) + extra & missing should fail ok 383 - columns_are(schema, table, columns) + extra & missing should have the proper description ok 384 - columns_are(schema, table, columns) + extra & missing should have the proper diagnostics ok 385 - columns_are(table, columns, desc) should pass ok 386 - columns_are(table, columns, desc) should have the proper description ok 387 - columns_are(table, columns, desc) should have the proper diagnostics ok 388 - columns_are(table, columns) should pass ok 389 - columns_are(table, columns) should have the proper description ok 390 - columns_are(table, columns) should have the proper diagnostics ok 391 - columns_are(table, columns) + extra should fail ok 392 - columns_are(table, columns) + extra should have the proper description ok 393 - columns_are(table, columns) + extra should have the proper diagnostics ok 394 - columns_are(table, columns) + missing should fail ok 395 - columns_are(table, columns) + missing should have the proper description ok 396 - columns_are(table, columns) + missing should have the proper diagnostics ok 397 - columns_are(table, columns) + extra & missing should fail ok 398 - columns_are(table, columns) + extra & missing should have the proper description ok 399 - columns_are(table, columns) + extra & missing should have the proper diagnostics pgtap-0.90.0/test/expected/._check.out000644 000765 000024 00000000252 11666501762 017761 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/check.out000644 000765 000024 00000006334 11666501762 017553 0ustar00davidstaff000000 000000 \unset ECHO 1..48 ok 1 - has_check( schema, table, desc ) should pass ok 2 - has_check( schema, table, desc ) should have the proper description ok 3 - has_check( schema, table, desc ) should have the proper diagnostics ok 4 - has_check( table, desc ) should pass ok 5 - has_check( table, desc ) should have the proper description ok 6 - has_check( table, desc ) should have the proper diagnostics ok 7 - has_check( table ) should pass ok 8 - has_check( table ) should have the proper description ok 9 - has_check( table ) should have the proper diagnostics ok 10 - has_check( schema, table, descr ) fail should fail ok 11 - has_check( schema, table, descr ) fail should have the proper description ok 12 - has_check( schema, table, descr ) fail should have the proper diagnostics ok 13 - has_check( table, desc ) fail should fail ok 14 - has_check( table, desc ) fail should have the proper description ok 15 - has_check( table, desc ) fail should have the proper diagnostics ok 16 - col_has_check( sch, tab, col, desc ) should pass ok 17 - col_has_check( sch, tab, col, desc ) should have the proper description ok 18 - col_has_check( sch, tab, col, desc ) should have the proper diagnostics ok 19 - col_has_check( sch, tab, cols, desc ) should pass ok 20 - col_has_check( sch, tab, cols, desc ) should have the proper description ok 21 - col_has_check( sch, tab, cols, desc ) should have the proper diagnostics ok 22 - col_has_check( tab, col, desc ) should pass ok 23 - col_has_check( tab, col, desc ) should have the proper description ok 24 - col_has_check( tab, col, desc ) should have the proper diagnostics ok 25 - col_has_check( tab, cols, desc ) should pass ok 26 - col_has_check( tab, cols, desc ) should have the proper description ok 27 - col_has_check( tab, cols, desc ) should have the proper diagnostics ok 28 - col_has_check( table, column ) should pass ok 29 - col_has_check( table, column ) should have the proper description ok 30 - col_has_check( table, column ) should have the proper diagnostics ok 31 - col_has_check( table, columns ) should pass ok 32 - col_has_check( table, columns ) should have the proper description ok 33 - col_has_check( table, columns ) should have the proper diagnostics ok 34 - col_has_check( sch, tab, col, desc ) fail should fail ok 35 - col_has_check( sch, tab, col, desc ) fail should have the proper description ok 36 - col_has_check( sch, tab, col, desc ) fail should have the proper diagnostics ok 37 - col_has_check( tab, col, desc ) fail should fail ok 38 - col_has_check( tab, col, desc ) fail should have the proper description ok 39 - col_has_check( tab, col, desc ) fail should have the proper diagnostics ok 40 - col_has_check( sch, tab, col[], desc ) should pass ok 41 - col_has_check( sch, tab, col[], desc ) should have the proper description ok 42 - col_has_check( sch, tab, col[], desc ) should have the proper diagnostics ok 43 - col_has_check( tab, col[], desc ) should pass ok 44 - col_has_check( tab, col[], desc ) should have the proper description ok 45 - col_has_check( tab, col[], desc ) should have the proper diagnostics ok 46 - col_has_check( tab, col[] ) should pass ok 47 - col_has_check( tab, col[] ) should have the proper description ok 48 - col_has_check( tab, col[] ) should have the proper diagnostics pgtap-0.90.0/test/expected/._cmpok.out000644 000765 000024 00000000252 11666501762 020015 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/cmpok.out000644 000765 000024 00000004242 11666501762 017603 0ustar00davidstaff000000 000000 \unset ECHO 1..38 ok 1 - cmp_ok( int, =, int ) should pass ok 2 - cmp_ok( int, =, int ) should have the proper description ok 3 - cmp_ok( int, =, int ) should have the proper diagnostics ok 4 - cmp_ok( int, <>, int ) should pass ok 5 - cmp_ok( int, <>, int ) should have the proper description ok 6 - cmp_ok( int, <>, int ) should have the proper diagnostics ok 7 - cmp_ok( polygon, ~=, polygon ) should pass ok 8 - cmp_ok( polygon, ~=, polygon ) should have the proper description ok 9 - cmp_ok( int[], =, int[] ) should pass ok 10 - cmp_ok( int[], =, int[] ) should have the proper description ok 11 - cmp_ok( int[], =, int[] ) should have the proper diagnostics ok 12 - cmp_ok( inet[], =, inet[] ) should pass ok 13 - cmp_ok( inet[], =, inet[] ) should have the proper description ok 14 - cmp_ok( inet[], =, inet[] ) should have the proper diagnostics ok 15 - cmp_ok() fail should fail ok 16 - cmp_ok() fail should have the proper description ok 17 - cmp_ok() fail should have the proper diagnostics ok 18 - cmp_ok() NULL fail should fail ok 19 - cmp_ok() NULL fail should have the proper description ok 20 - cmp_ok() NULL fail should have the proper diagnostics ok 21 - isa_ok("", text, desc) should pass ok 22 - isa_ok("", text, desc) should have the proper description ok 23 - isa_ok("", text, desc) should have the proper diagnostics ok 24 - isa_ok("", text, desc) should pass ok 25 - isa_ok("", text, desc) should have the proper description ok 26 - isa_ok("", text, desc) should have the proper diagnostics ok 27 - isa_ok(false, boolean) should pass ok 28 - isa_ok(false, boolean) should have the proper description ok 29 - isa_ok(false, boolean) should have the proper diagnostics ok 30 - isa_ok(NULL, boolean) should pass ok 31 - isa_ok(NULL, boolean) should have the proper description ok 32 - isa_ok(NULL, boolean) should have the proper diagnostics ok 33 - isa_ok(ARRAY, boolean[]) should pass ok 34 - isa_ok(ARRAY, boolean[]) should have the proper description ok 35 - isa_ok(ARRAY, boolean[]) should have the proper diagnostics ok 36 - isa_ok(bool, int[]) should fail ok 37 - isa_ok(bool, int[]) should have the proper description ok 38 - isa_ok(bool, int[]) should have the proper diagnostics pgtap-0.90.0/test/expected/._coltap.out000644 000765 000024 00000000252 11666501762 020166 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/coltap.out000644 000765 000024 00000035321 11666501762 017756 0ustar00davidstaff000000 000000 \unset ECHO 1..204 ok 1 - col_not_null( sch, tab, col, desc ) should pass ok 2 - col_not_null( sch, tab, col, desc ) should have the proper description ok 3 - col_not_null( sch, tab, col, desc ) should have the proper diagnostics ok 4 - col_not_null( tab, col, desc ) should pass ok 5 - col_not_null( tab, col, desc ) should have the proper description ok 6 - col_not_null( tab, col, desc ) should have the proper diagnostics ok 7 - col_not_null( table, column ) should pass ok 8 - col_not_null( table, column ) should have the proper description ok 9 - col_not_null( table, column ) should have the proper diagnostics ok 10 - col_not_null( table, column ) fail should fail ok 11 - col_not_null( table, column ) fail should have the proper description ok 12 - col_not_null( table, column ) fail should have the proper diagnostics ok 13 - col_not_null( sch, tab, noncol, desc ) should fail ok 14 - col_not_null( sch, tab, noncol, desc ) should have the proper description ok 15 - col_not_null( sch, tab, noncol, desc ) should have the proper diagnostics ok 16 - col_not_null( table, noncolumn ) fail should fail ok 17 - col_not_null( table, noncolumn ) fail should have the proper description ok 18 - col_not_null( table, noncolumn ) fail should have the proper diagnostics ok 19 - col_is_null( sch, tab, col, desc ) should pass ok 20 - col_is_null( sch, tab, col, desc ) should have the proper description ok 21 - col_is_null( sch, tab, col, desc ) should have the proper diagnostics ok 22 - col_is_null( tab, col, desc ) should pass ok 23 - col_is_null( tab, col, desc ) should have the proper description ok 24 - col_is_null( tab, col, desc ) should have the proper diagnostics ok 25 - col_is_null( tab, col ) should pass ok 26 - col_is_null( tab, col ) should have the proper description ok 27 - col_is_null( tab, col ) should have the proper diagnostics ok 28 - col_is_null( tab, col ) fail should fail ok 29 - col_is_null( tab, col ) fail should have the proper description ok 30 - col_is_null( tab, col ) fail should have the proper diagnostics ok 31 - col_is_null( sch, tab, noncol, desc ) should fail ok 32 - col_is_null( sch, tab, noncol, desc ) should have the proper description ok 33 - col_is_null( sch, tab, noncol, desc ) should have the proper diagnostics ok 34 - col_is_null( table, noncolumn ) fail should fail ok 35 - col_is_null( table, noncolumn ) fail should have the proper description ok 36 - col_is_null( table, noncolumn ) fail should have the proper diagnostics ok 37 - col_type_is( sch, tab, col, sch, type, desc ) should pass ok 38 - col_type_is( sch, tab, col, sch, type, desc ) should have the proper description ok 39 - col_type_is( sch, tab, col, sch, type, desc ) should have the proper diagnostics ok 40 - col_type_is( sch, tab, col, sch, type, desc ) should pass ok 41 - col_type_is( sch, tab, col, sch, type, desc ) should have the proper description ok 42 - col_type_is( sch, tab, col, sch, type, desc ) should have the proper diagnostics ok 43 - col_type_is( sch, tab, myNum, sch, type, desc ) should pass ok 44 - col_type_is( sch, tab, myNum, sch, type, desc ) should have the proper description ok 45 - col_type_is( sch, tab, myNum, sch, type, desc ) should have the proper diagnostics ok 46 - col_type_is( sch, tab, myNum, sch, type, desc ) should pass ok 47 - col_type_is( sch, tab, myNum, sch, type, desc ) should have the proper description ok 48 - col_type_is( sch, tab, myNum, sch, type, desc ) should have the proper diagnostics ok 49 - col_type_is( sch, tab, camel, sch, type, desc ) should pass ok 50 - col_type_is( sch, tab, camel, sch, type, desc ) should have the proper description ok 51 - col_type_is( sch, tab, camel, sch, type, desc ) should have the proper diagnostics ok 52 - col_type_is( sch, tab, camel, sch, type, desc ) should pass ok 53 - col_type_is( sch, tab, camel, sch, type, desc ) should have the proper description ok 54 - col_type_is( sch, tab, camel, sch, type, desc ) should have the proper diagnostics ok 55 - col_type_is( sch, tab, camel, type, desc ) should pass ok 56 - col_type_is( sch, tab, camel, type, desc ) should have the proper description ok 57 - col_type_is( sch, tab, camel, type, desc ) should have the proper diagnostics ok 58 - col_type_is( sch, tab, col, sch, type, desc ) fail should fail ok 59 - col_type_is( sch, tab, col, sch, type, desc ) fail should have the proper description ok 60 - col_type_is( sch, tab, col, sch, type, desc ) fail should have the proper diagnostics ok 61 - col_type_is( sch, tab, col, sch, non-type, desc ) should fail ok 62 - col_type_is( sch, tab, col, sch, non-type, desc ) should have the proper description ok 63 - col_type_is( sch, tab, col, sch, non-type, desc ) should have the proper diagnostics ok 64 - col_type_is( sch, tab, col, non-sch, type, desc ) should fail ok 65 - col_type_is( sch, tab, col, non-sch, type, desc ) should have the proper description ok 66 - col_type_is( sch, tab, col, non-sch, type, desc ) should have the proper diagnostics ok 67 - col_type_is( sch, tab, non-col, sch, type, desc ) should fail ok 68 - col_type_is( sch, tab, non-col, sch, type, desc ) should have the proper description ok 69 - col_type_is( sch, tab, non-col, sch, type, desc ) should have the proper diagnostics ok 70 - col_type_is( sch, tab, col, type, desc ) should pass ok 71 - col_type_is( sch, tab, col, type, desc ) should have the proper description ok 72 - col_type_is( sch, tab, col, type, desc ) should have the proper diagnostics ok 73 - col_type_is( sch, tab, col, type ) should pass ok 74 - col_type_is( sch, tab, col, type ) should have the proper description ok 75 - col_type_is( sch, tab, col, type ) should have the proper diagnostics ok 76 - col_type_is( tab, col, type, desc ) should pass ok 77 - col_type_is( tab, col, type, desc ) should have the proper description ok 78 - col_type_is( tab, col, type, desc ) should have the proper diagnostics ok 79 - col_type_is( tab, col, type ) should pass ok 80 - col_type_is( tab, col, type ) should have the proper description ok 81 - col_type_is( tab, col, type ) should have the proper diagnostics ok 82 - col_type_is( tab, col, type ) fail should fail ok 83 - col_type_is( tab, col, type ) fail should have the proper description ok 84 - col_type_is( tab, col, type ) fail should have the proper diagnostics ok 85 - col_type_is( tab, noncol, type ) fail should fail ok 86 - col_type_is( tab, noncol, type ) fail should have the proper description ok 87 - col_type_is( tab, noncol, type ) fail should have the proper diagnostics ok 88 - col_type_is( sch, tab, noncol, type, desc ) fail should fail ok 89 - col_type_is( sch, tab, noncol, type, desc ) fail should have the proper description ok 90 - col_type_is( sch, tab, noncol, type, desc ) fail should have the proper diagnostics ok 91 - col_type_is with precision should pass ok 92 - col_type_is with precision should have the proper description ok 93 - col_type_is with precision should have the proper diagnostics ok 94 - col_type_is precision fail should fail ok 95 - col_type_is precision fail should have the proper description ok 96 - col_type_is precision fail should have the proper diagnostics ok 97 - col_has_default( sch, tab, col, desc ) should pass ok 98 - col_has_default( sch, tab, col, desc ) should have the proper description ok 99 - col_has_default( sch, tab, col, desc ) should have the proper diagnostics ok 100 - col_has_default( tab, col, desc ) should pass ok 101 - col_has_default( tab, col, desc ) should have the proper description ok 102 - col_has_default( tab, col, desc ) should have the proper diagnostics ok 103 - col_has_default( tab, col ) should pass ok 104 - col_has_default( tab, col ) should have the proper description ok 105 - col_has_default( tab, col ) should have the proper diagnostics ok 106 - col_has_default( sch, tab, col, desc ) should fail ok 107 - col_has_default( sch, tab, col, desc ) should have the proper description ok 108 - col_has_default( sch, tab, col, desc ) should have the proper diagnostics ok 109 - col_has_default( tab, col, desc ) should fail ok 110 - col_has_default( tab, col, desc ) should have the proper description ok 111 - col_has_default( tab, col, desc ) should have the proper diagnostics ok 112 - col_has_default( tab, col ) should fail ok 113 - col_has_default( tab, col ) should have the proper description ok 114 - col_has_default( tab, col ) should have the proper diagnostics ok 115 - col_has_default( sch, tab, col, desc ) should fail ok 116 - col_has_default( sch, tab, col, desc ) should have the proper description ok 117 - col_has_default( sch, tab, col, desc ) should have the proper diagnostics ok 118 - col_has_default( tab, col, desc ) should fail ok 119 - col_has_default( tab, col, desc ) should have the proper description ok 120 - col_has_default( tab, col, desc ) should have the proper diagnostics ok 121 - col_has_default( tab, col ) should fail ok 122 - col_has_default( tab, col ) should have the proper description ok 123 - col_has_default( tab, col ) should have the proper diagnostics ok 124 - col_hasnt_default( sch, tab, col, desc ) should fail ok 125 - col_hasnt_default( sch, tab, col, desc ) should have the proper description ok 126 - col_hasnt_default( sch, tab, col, desc ) should have the proper diagnostics ok 127 - col_hasnt_default( tab, col, desc ) should fail ok 128 - col_hasnt_default( tab, col, desc ) should have the proper description ok 129 - col_hasnt_default( tab, col, desc ) should have the proper diagnostics ok 130 - col_hasnt_default( tab, col ) should fail ok 131 - col_hasnt_default( tab, col ) should have the proper description ok 132 - col_hasnt_default( tab, col ) should have the proper diagnostics ok 133 - col_hasnt_default( sch, tab, col, desc ) should pass ok 134 - col_hasnt_default( sch, tab, col, desc ) should have the proper description ok 135 - col_hasnt_default( sch, tab, col, desc ) should have the proper diagnostics ok 136 - col_hasnt_default( tab, col, desc ) should pass ok 137 - col_hasnt_default( tab, col, desc ) should have the proper description ok 138 - col_hasnt_default( tab, col, desc ) should have the proper diagnostics ok 139 - col_hasnt_default( tab, col ) should pass ok 140 - col_hasnt_default( tab, col ) should have the proper description ok 141 - col_hasnt_default( tab, col ) should have the proper diagnostics ok 142 - col_hasnt_default( sch, tab, col, desc ) should fail ok 143 - col_hasnt_default( sch, tab, col, desc ) should have the proper description ok 144 - col_hasnt_default( sch, tab, col, desc ) should have the proper diagnostics ok 145 - col_hasnt_default( tab, col, desc ) should fail ok 146 - col_hasnt_default( tab, col, desc ) should have the proper description ok 147 - col_hasnt_default( tab, col, desc ) should have the proper diagnostics ok 148 - col_hasnt_default( tab, col ) should fail ok 149 - col_hasnt_default( tab, col ) should have the proper description ok 150 - col_hasnt_default( tab, col ) should have the proper diagnostics ok 151 - col_default_is( sch, tab, col, def, desc ) should pass ok 152 - col_default_is( sch, tab, col, def, desc ) should have the proper description ok 153 - col_default_is( sch, tab, col, def, desc ) should have the proper diagnostics ok 154 - col_default_is() fail should fail ok 155 - col_default_is() fail should have the proper description ok 156 - col_default_is() fail should have the proper diagnostics ok 157 - col_default_is( tab, col, def, desc ) should pass ok 158 - col_default_is( tab, col, def, desc ) should have the proper description ok 159 - col_default_is( tab, col, def, desc ) should have the proper diagnostics ok 160 - col_default_is( tab, col, def ) should pass ok 161 - col_default_is( tab, col, def ) should have the proper description ok 162 - col_default_is( tab, col, def ) should have the proper diagnostics ok 163 - col_default_is( tab, col, int ) should pass ok 164 - col_default_is( tab, col, int ) should have the proper description ok 165 - col_default_is( tab, col, int ) should have the proper diagnostics ok 166 - col_default_is( tab, col, NULL, desc ) should pass ok 167 - col_default_is( tab, col, NULL, desc ) should have the proper description ok 168 - col_default_is( tab, col, NULL, desc ) should have the proper diagnostics ok 169 - col_default_is( tab, col, NULL ) should pass ok 170 - col_default_is( tab, col, NULL ) should have the proper description ok 171 - col_default_is( tab, col, NULL ) should have the proper diagnostics ok 172 - col_default_is( tab, col, bogus, desc ) should fail ok 173 - col_default_is( tab, col, bogus, desc ) should have the proper description ok 174 - col_default_is( tab, col, bogus, desc ) should have the proper diagnostics ok 175 - col_default_is( tab, col, bogus ) should fail ok 176 - col_default_is( tab, col, bogus ) should have the proper description ok 177 - col_default_is( tab, col, bogus ) should have the proper diagnostics ok 178 - col_default_is( tab, col, expression ) should pass ok 179 - col_default_is( tab, col, expression ) should have the proper description ok 180 - col_default_is( tab, col, expression ) should have the proper diagnostics ok 181 - col_default_is( tab, col, expression::text ) should pass ok 182 - col_default_is( tab, col, expression::text ) should have the proper description ok 183 - col_default_is( tab, col, expression::text ) should have the proper diagnostics ok 184 - col_default_is( tab, col, expression, desc ) should pass ok 185 - col_default_is( tab, col, expression, desc ) should have the proper description ok 186 - col_default_is( tab, col, expression, desc ) should have the proper diagnostics ok 187 - col_default_is( tab, col, expression, desc ) should pass ok 188 - col_default_is( tab, col, expression, desc ) should have the proper description ok 189 - col_default_is( tab, col, expression, desc ) should have the proper diagnostics ok 190 - col_default_is( schema, tab, col, expression, desc ) should pass ok 191 - col_default_is( schema, tab, col, expression, desc ) should have the proper description ok 192 - col_default_is( schema, tab, col, expression, desc ) should have the proper diagnostics ok 193 - col_default_is( schema, tab, col, expression, desc ) should pass ok 194 - col_default_is( schema, tab, col, expression, desc ) should have the proper description ok 195 - col_default_is( schema, tab, col, expression, desc ) should have the proper diagnostics ok 196 - col_default_is( sch, tab, col, def, desc ) should fail ok 197 - col_default_is( sch, tab, col, def, desc ) should have the proper description ok 198 - col_default_is( sch, tab, col, def, desc ) should have the proper diagnostics ok 199 - col_default_is( tab, col, def, desc ) should fail ok 200 - col_default_is( tab, col, def, desc ) should have the proper description ok 201 - col_default_is( tab, col, def, desc ) should have the proper diagnostics ok 202 - col_default_is( tab, col, def ) should fail ok 203 - col_default_is( tab, col, def ) should have the proper description ok 204 - col_default_is( tab, col, def ) should have the proper diagnostics pgtap-0.90.0/test/expected/._do_tap.out000644 000765 000024 00000000252 11666501762 020152 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/do_tap.out000644 000765 000024 00000001537 11666501762 017744 0ustar00davidstaff000000 000000 \unset ECHO 1..26 ok 1 - findfuncs(public, ^test) should work ok 2 - findfuncs(^test) should work # public."test ident"() ok 3 - ident ok 4 - ident 2 # public.testplpgsql() ok 5 - plpgsql simple ok 6 - plpgsql simple 2 # public.testthis() ok 7 - simple pass ok 8 - another simple pass # public."test ident"() ok 9 - ident ok 10 - ident 2 # public.testplpgsql() ok 11 - plpgsql simple ok 12 - plpgsql simple 2 # public.testthis() ok 13 - simple pass ok 14 - another simple pass # public."test ident"() ok 15 - ident ok 16 - ident 2 # public.testplpgsql() ok 17 - plpgsql simple ok 18 - plpgsql simple 2 # public.testthis() ok 19 - simple pass ok 20 - another simple pass # public."test ident"() ok 21 - ident ok 22 - ident 2 # public.testplpgsql() ok 23 - plpgsql simple ok 24 - plpgsql simple 2 # public.testthis() ok 25 - simple pass ok 26 - another simple pass pgtap-0.90.0/test/expected/._enumtap.out000644 000765 000024 00000000252 11666501762 020355 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/enumtap.out000644 000765 000024 00000013637 11666501762 020153 0ustar00davidstaff000000 000000 \unset ECHO 1..96 ok 1 - has_type(enum) should pass ok 2 - has_type(enum) should have the proper description ok 3 - has_type(enum) should have the proper diagnostics ok 4 - has_enum(enum) should pass ok 5 - has_enum(enum) should have the proper description ok 6 - has_enum(enum) should have the proper diagnostics ok 7 - has_enum(enum, desc) should pass ok 8 - has_enum(enum, desc) should have the proper description ok 9 - has_enum(enum, desc) should have the proper diagnostics ok 10 - has_enum(scheam, enum) should pass ok 11 - has_enum(scheam, enum) should have the proper description ok 12 - has_enum(scheam, enum) should have the proper diagnostics ok 13 - has_enum(schema, enum, desc) should pass ok 14 - has_enum(schema, enum, desc) should have the proper description ok 15 - has_enum(schema, enum, desc) should have the proper diagnostics ok 16 - has_enum(enum) should fail ok 17 - has_enum(enum) should have the proper description ok 18 - has_enum(enum) should have the proper diagnostics ok 19 - has_enum(enum, desc) should fail ok 20 - has_enum(enum, desc) should have the proper description ok 21 - has_enum(enum, desc) should have the proper diagnostics ok 22 - has_enum(scheam, enum) should fail ok 23 - has_enum(scheam, enum) should have the proper description ok 24 - has_enum(scheam, enum) should have the proper diagnostics ok 25 - has_enum(schema, enum, desc) should fail ok 26 - has_enum(schema, enum, desc) should have the proper description ok 27 - has_enum(schema, enum, desc) should have the proper diagnostics ok 28 - hasnt_enum(enum) should pass ok 29 - hasnt_enum(enum) should have the proper description ok 30 - hasnt_enum(enum) should have the proper diagnostics ok 31 - hasnt_enum(enum, desc) should pass ok 32 - hasnt_enum(enum, desc) should have the proper description ok 33 - hasnt_enum(enum, desc) should have the proper diagnostics ok 34 - hasnt_enum(scheam, enum) should pass ok 35 - hasnt_enum(scheam, enum) should have the proper description ok 36 - hasnt_enum(scheam, enum) should have the proper diagnostics ok 37 - hasnt_enum(schema, enum, desc) should pass ok 38 - hasnt_enum(schema, enum, desc) should have the proper description ok 39 - hasnt_enum(schema, enum, desc) should have the proper diagnostics ok 40 - hasnt_enum(enum) should fail ok 41 - hasnt_enum(enum) should have the proper description ok 42 - hasnt_enum(enum) should have the proper diagnostics ok 43 - hasnt_enum(enum, desc) should fail ok 44 - hasnt_enum(enum, desc) should have the proper description ok 45 - hasnt_enum(enum, desc) should have the proper diagnostics ok 46 - hasnt_enum(scheam, enum) should fail ok 47 - hasnt_enum(scheam, enum) should have the proper description ok 48 - hasnt_enum(scheam, enum) should have the proper diagnostics ok 49 - hasnt_enum(schema, enum, desc) should fail ok 50 - hasnt_enum(schema, enum, desc) should have the proper description ok 51 - hasnt_enum(schema, enum, desc) should have the proper diagnostics ok 52 - enum_has_labels(schema, enum, labels, desc) should pass ok 53 - enum_has_labels(schema, enum, labels, desc) should have the proper description ok 54 - enum_has_labels(schema, enum, labels, desc) should have the proper diagnostics ok 55 - enum_has_labels(schema, enum, labels) should pass ok 56 - enum_has_labels(schema, enum, labels) should have the proper description ok 57 - enum_has_labels(schema, enum, labels) should have the proper diagnostics ok 58 - enum_has_labels(enum, labels, desc) should pass ok 59 - enum_has_labels(enum, labels, desc) should have the proper description ok 60 - enum_has_labels(enum, labels, desc) should have the proper diagnostics ok 61 - enum_has_labels(enum, labels) should pass ok 62 - enum_has_labels(enum, labels) should have the proper description ok 63 - enum_has_labels(enum, labels) should have the proper diagnostics ok 64 - enum_has_labels(schema, enum, labels, desc) fail should fail ok 65 - enum_has_labels(schema, enum, labels, desc) fail should have the proper description ok 66 - enum_has_labels(schema, enum, labels, desc) fail should have the proper diagnostics ok 67 - enum_has_labels(schema, enum, labels, desc) fail should fail ok 68 - enum_has_labels(schema, enum, labels, desc) fail should have the proper description ok 69 - enum_has_labels(schema, enum, labels, desc) fail should have the proper diagnostics ok 70 - enum_has_labels(enum, labels, desc) fail should fail ok 71 - enum_has_labels(enum, labels, desc) fail should have the proper description ok 72 - enum_has_labels(enum, labels, desc) fail should have the proper diagnostics ok 73 - enums_are(schema, enums, desc) should pass ok 74 - enums_are(schema, enums, desc) should have the proper description ok 75 - enums_are(schema, enums, desc) should have the proper diagnostics ok 76 - enums_are(schema, enums) should pass ok 77 - enums_are(schema, enums) should have the proper description ok 78 - enums_are(schema, enums) should have the proper diagnostics ok 79 - enums_are(schema, enums, desc) fail should fail ok 80 - enums_are(schema, enums, desc) fail should have the proper description ok 81 - enums_are(schema, enums, desc) fail should have the proper diagnostics ok 82 - enums_are(schema, enums) fail should fail ok 83 - enums_are(schema, enums) fail should have the proper description ok 84 - enums_are(schema, enums) fail should have the proper diagnostics ok 85 - enums_are(enums, desc) should pass ok 86 - enums_are(enums, desc) should have the proper description ok 87 - enums_are(enums, desc) should have the proper diagnostics ok 88 - enums_are(enums) should pass ok 89 - enums_are(enums) should have the proper description ok 90 - enums_are(enums) should have the proper diagnostics ok 91 - enums_are(enums, desc) fail should fail ok 92 - enums_are(enums, desc) fail should have the proper description ok 93 - enums_are(enums, desc) fail should have the proper diagnostics ok 94 - enums_are(enums) fail should fail ok 95 - enums_are(enums) fail should have the proper description ok 96 - enums_are(enums) fail should have the proper diagnostics pgtap-0.90.0/test/expected/._fktap.out000644 000765 000024 00000000252 11666501762 020011 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/fktap.out000644 000765 000024 00000017554 11666501762 017611 0ustar00davidstaff000000 000000 \unset ECHO 1..128 ok 1 - has_fk( schema, table, description ) should pass ok 2 - has_fk( schema, table, description ) should have the proper description ok 3 - has_fk( table, description ) should pass ok 4 - has_fk( table, description ) should have the proper description ok 5 - has_fk( table ) should pass ok 6 - has_fk( table ) should have the proper description ok 7 - has_fk( schema, table, description ) fail should fail ok 8 - has_fk( schema, table, description ) fail should have the proper description ok 9 - has_fk( table, description ) fail should fail ok 10 - has_fk( table, description ) fail should have the proper description ok 11 - hasnt_fk( schema, table, description ) should fail ok 12 - hasnt_fk( schema, table, description ) should have the proper description ok 13 - hasnt_fk( table, description ) should fail ok 14 - hasnt_fk( table, description ) should have the proper description ok 15 - hasnt_fk( table ) should fail ok 16 - hasnt_fk( table ) should have the proper description ok 17 - hasnt_fk( schema, table, description ) pass should pass ok 18 - hasnt_fk( schema, table, description ) pass should have the proper description ok 19 - hasnt_fk( table, description ) pass should pass ok 20 - hasnt_fk( table, description ) pass should have the proper description ok 21 - col_is_fk( schema, table, column, description ) should pass ok 22 - col_is_fk( schema, table, column, description ) should have the proper description ok 23 - col_is_fk( table, column, description ) should pass ok 24 - col_is_fk( table, column, description ) should have the proper description ok 25 - col_is_fk( table, column ) should pass ok 26 - col_is_fk( table, column ) should have the proper description ok 27 - col_is_fk( schema, table, column, description ) should fail ok 28 - col_is_fk( schema, table, column, description ) should have the proper description ok 29 - col_is_fk( schema, table, column, description ) should have the proper diagnostics ok 30 - col_is_fk( table, column, description ) should fail ok 31 - col_is_fk( table, column, description ) should have the proper description ok 32 - col_is_fk( table, column, description ) should have the proper diagnostics ok 33 - multi-fk col_is_fk test should pass ok 34 - multi-fk col_is_fk test should have the proper description ok 35 - col_is_fk with no FKs should fail ok 36 - col_is_fk with no FKs should have the proper description ok 37 - col_is_fk with no FKs should have the proper diagnostics ok 38 - col_is_fk with no FKs should fail ok 39 - col_is_fk with no FKs should have the proper description ok 40 - col_is_fk with no FKs should have the proper diagnostics ok 41 - col_is_fk( schema, table, column[], description ) should pass ok 42 - col_is_fk( schema, table, column[], description ) should have the proper description ok 43 - col_is_fk( table, column[], description ) should pass ok 44 - col_is_fk( table, column[], description ) should have the proper description ok 45 - col_is_fk( table, column[] ) should pass ok 46 - col_is_fk( table, column[] ) should have the proper description ok 47 - col_isnt_fk( schema, table, column, description ) should fail ok 48 - col_isnt_fk( schema, table, column, description ) should have the proper description ok 49 - col_isnt_fk( schema, table, column, description ) should have the proper diagnostics ok 50 - col_isnt_fk( table, column, description ) should fail ok 51 - col_isnt_fk( table, column, description ) should have the proper description ok 52 - col_isnt_fk( table, column, description ) should have the proper diagnostics ok 53 - col_isnt_fk( table, column ) should fail ok 54 - col_isnt_fk( table, column ) should have the proper description ok 55 - col_isnt_fk( table, column ) should have the proper diagnostics ok 56 - col_isnt_fk( schema, table, column, description ) should pass ok 57 - col_isnt_fk( schema, table, column, description ) should have the proper description ok 58 - col_isnt_fk( schema, table, column, description ) should have the proper diagnostics ok 59 - col_isnt_fk( table, column, description ) should pass ok 60 - col_isnt_fk( table, column, description ) should have the proper description ok 61 - col_isnt_fk( table, column, description ) should have the proper diagnostics ok 62 - multi-fk col_isnt_fk test should fail ok 63 - multi-fk col_isnt_fk test should have the proper description ok 64 - multi-fk col_isnt_fk test should have the proper diagnostics ok 65 - col_isnt_fk with no FKs should pass ok 66 - col_isnt_fk with no FKs should have the proper description ok 67 - col_isnt_fk with no FKs should have the proper diagnostics ok 68 - col_isnt_fk with no FKs should pass ok 69 - col_isnt_fk with no FKs should have the proper description ok 70 - col_isnt_fk with no FKs should have the proper diagnostics ok 71 - col_isnt_fk( schema, table, column[], description ) should fail ok 72 - col_isnt_fk( schema, table, column[], description ) should have the proper description ok 73 - col_isnt_fk( table, column[], description ) should fail ok 74 - col_isnt_fk( table, column[], description ) should have the proper description ok 75 - col_isnt_fk( table, column[] ) should fail ok 76 - col_isnt_fk( table, column[] ) should have the proper description ok 77 - full fk_ok array should pass ok 78 - full fk_ok array should have the proper description ok 79 - multiple fk fk_ok desc should pass ok 80 - multiple fk fk_ok desc should have the proper description ok 81 - fk_ok array desc should pass ok 82 - fk_ok array desc should have the proper description ok 83 - fk_ok array noschema desc should pass ok 84 - fk_ok array noschema desc should have the proper description ok 85 - multiple fk fk_ok noschema desc should pass ok 86 - multiple fk fk_ok noschema desc should have the proper description ok 87 - fk_ok array noschema should pass ok 88 - fk_ok array noschema should have the proper description ok 89 - basic fk_ok should pass ok 90 - basic fk_ok should have the proper description ok 91 - basic fk_ok desc should pass ok 92 - basic fk_ok desc should have the proper description ok 93 - basic fk_ok noschema should pass ok 94 - basic fk_ok noschema should have the proper description ok 95 - basic fk_ok noschema desc should pass ok 96 - basic fk_ok noschema desc should have the proper description ok 97 - basic fk_ok noschema desc should have the proper diagnostics ok 98 - Test should pass ok 99 - fk_ok fail should fail ok 100 - fk_ok fail should have the proper description ok 101 - fk_ok fail should have the proper diagnostics ok 102 - fk_ok fail desc should fail ok 103 - fk_ok fail desc should have the proper description ok 104 - fk_ok fail desc should have the proper diagnostics ok 105 - fk_ok fail no schema should fail ok 106 - fk_ok fail no schema should have the proper description ok 107 - fk_ok fail no schema should have the proper diagnostics ok 108 - fk_ok fail no schema desc should fail ok 109 - fk_ok fail no schema desc should have the proper description ok 110 - fk_ok fail no schema desc should have the proper diagnostics ok 111 - fk_ok bad PK test should fail ok 112 - fk_ok bad PK test should have the proper description ok 113 - fk_ok bad PK test should have the proper diagnostics ok 114 - double fk schema test should pass ok 115 - double fk schema test should have the proper description ok 116 - double fk schema test should have the proper diagnostics ok 117 - double fk test should pass ok 118 - double fk test should have the proper description ok 119 - double fk test should have the proper diagnostics ok 120 - double fk and col schema test should pass ok 121 - double fk and col schema test should have the proper description ok 122 - double fk and col schema test should have the proper diagnostics ok 123 - missing fk test should fail ok 124 - missing fk test should have the proper description ok 125 - missing fk test should have the proper diagnostics ok 126 - bad FK column test should fail ok 127 - bad FK column test should have the proper description ok 128 - bad FK column test should have the proper diagnostics pgtap-0.90.0/test/expected/._functap.out000644 000765 000024 00000000252 11666501762 020344 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/functap.out000644 000765 000024 00000100457 11666501762 020137 0ustar00davidstaff000000 000000 \unset ECHO 1..466 ok 1 - simple function should pass ok 2 - simple function should have the proper description ok 3 - simple function should have the proper diagnostics ok 4 - simple schema.function should pass ok 5 - simple schema.function should have the proper description ok 6 - simple schema.function should have the proper diagnostics ok 7 - simple function desc should pass ok 8 - simple function desc should have the proper description ok 9 - simple function desc should have the proper diagnostics ok 10 - simple with 0 args should pass ok 11 - simple with 0 args should have the proper description ok 12 - simple with 0 args should have the proper diagnostics ok 13 - simple with 0 args desc should pass ok 14 - simple with 0 args desc should have the proper description ok 15 - simple with 0 args desc should have the proper diagnostics ok 16 - simple schema.func with 0 args should pass ok 17 - simple schema.func with 0 args should have the proper description ok 18 - simple schema.func with 0 args should have the proper diagnostics ok 19 - simple schema.func with desc should pass ok 20 - simple schema.func with desc should have the proper description ok 21 - simple schema.func with desc should have the proper diagnostics ok 22 - simple scchma.func with 0 args, desc should pass ok 23 - simple scchma.func with 0 args, desc should have the proper description ok 24 - simple scchma.func with 0 args, desc should have the proper diagnostics ok 25 - simple function with 1 arg should pass ok 26 - simple function with 1 arg should have the proper description ok 27 - simple function with 1 arg should have the proper diagnostics ok 28 - simple function with 2 args should pass ok 29 - simple function with 2 args should have the proper description ok 30 - simple function with 2 args should have the proper diagnostics ok 31 - simple array function should pass ok 32 - simple array function should have the proper description ok 33 - simple array function should have the proper diagnostics ok 34 - custom array function should pass ok 35 - custom array function should have the proper description ok 36 - custom array function should have the proper diagnostics ok 37 - custom numeric function should pass ok 38 - custom numeric function should have the proper description ok 39 - custom numeric function should have the proper diagnostics ok 40 - failure output should fail ok 41 - failure output should have the proper description ok 42 - failure output should have the proper diagnostics ok 43 - simple function should fail ok 44 - simple function should have the proper description ok 45 - simple function should have the proper diagnostics ok 46 - simple schema.function should fail ok 47 - simple schema.function should have the proper description ok 48 - simple schema.function should have the proper diagnostics ok 49 - simple function desc should fail ok 50 - simple function desc should have the proper description ok 51 - simple function desc should have the proper diagnostics ok 52 - simple with 0 args should fail ok 53 - simple with 0 args should have the proper description ok 54 - simple with 0 args should have the proper diagnostics ok 55 - simple with 0 args desc should fail ok 56 - simple with 0 args desc should have the proper description ok 57 - simple with 0 args desc should have the proper diagnostics ok 58 - simple schema.func with 0 args should fail ok 59 - simple schema.func with 0 args should have the proper description ok 60 - simple schema.func with 0 args should have the proper diagnostics ok 61 - simple schema.func with desc should fail ok 62 - simple schema.func with desc should have the proper description ok 63 - simple schema.func with desc should have the proper diagnostics ok 64 - simple scchma.func with 0 args, desc should fail ok 65 - simple scchma.func with 0 args, desc should have the proper description ok 66 - simple scchma.func with 0 args, desc should have the proper diagnostics ok 67 - simple function with 1 arg should fail ok 68 - simple function with 1 arg should have the proper description ok 69 - simple function with 1 arg should have the proper diagnostics ok 70 - simple function with 2 args should fail ok 71 - simple function with 2 args should have the proper description ok 72 - simple function with 2 args should have the proper diagnostics ok 73 - simple array function should fail ok 74 - simple array function should have the proper description ok 75 - simple array function should have the proper diagnostics ok 76 - custom array function should fail ok 77 - custom array function should have the proper description ok 78 - custom array function should have the proper diagnostics ok 79 - custom numeric function should fail ok 80 - custom numeric function should have the proper description ok 81 - custom numeric function should have the proper diagnostics ok 82 - can(schema) with desc should pass ok 83 - can(schema) with desc should have the proper description ok 84 - can(schema) with desc should have the proper diagnostics ok 85 - can(schema) should pass ok 86 - can(schema) should have the proper description ok 87 - can(schema) should have the proper diagnostics ok 88 - fail can(schema) with desc should fail ok 89 - fail can(schema) with desc should have the proper description ok 90 - fail can(schema) with desc should have the proper diagnostics ok 91 - fail can(someschema) with desc should fail ok 92 - fail can(someschema) with desc should have the proper description ok 93 - fail can(someschema) with desc should have the proper diagnostics ok 94 - can() with desc should pass ok 95 - can() with desc should have the proper description ok 96 - can() with desc should have the proper diagnostics ok 97 - can(schema) should pass ok 98 - can(schema) should have the proper description ok 99 - can(schema) should have the proper diagnostics ok 100 - fail can() with desc should fail ok 101 - fail can() with desc should have the proper description ok 102 - fail can() with desc should have the proper diagnostics ok 103 - function_lang_is(schema, func, 0 args, sql, desc) should pass ok 104 - function_lang_is(schema, func, 0 args, sql, desc) should have the proper description ok 105 - function_lang_is(schema, func, 0 args, sql, desc) should have the proper diagnostics ok 106 - function_lang_is(schema, func, 0 args, sql) should pass ok 107 - function_lang_is(schema, func, 0 args, sql) should have the proper description ok 108 - function_lang_is(schema, func, 0 args, sql) should have the proper diagnostics ok 109 - function_lang_is(schema, func, args, plpgsql, desc) should pass ok 110 - function_lang_is(schema, func, args, plpgsql, desc) should have the proper description ok 111 - function_lang_is(schema, func, args, plpgsql, desc) should have the proper diagnostics ok 112 - function_lang_is(schema, func, args, plpgsql) should pass ok 113 - function_lang_is(schema, func, args, plpgsql) should have the proper description ok 114 - function_lang_is(schema, func, args, plpgsql) should have the proper diagnostics ok 115 - function_lang_is(schema, func, 0 args, perl, desc) should fail ok 116 - function_lang_is(schema, func, 0 args, perl, desc) should have the proper description ok 117 - function_lang_is(schema, func, 0 args, perl, desc) should have the proper diagnostics ok 118 - function_lang_is(schema, non-func, 0 args, sql, desc) should fail ok 119 - function_lang_is(schema, non-func, 0 args, sql, desc) should have the proper description ok 120 - function_lang_is(schema, non-func, 0 args, sql, desc) should have the proper diagnostics ok 121 - function_lang_is(schema, func, args, plpgsql) should fail ok 122 - function_lang_is(schema, func, args, plpgsql) should have the proper description ok 123 - function_lang_is(schema, func, args, plpgsql) should have the proper diagnostics ok 124 - function_lang_is(schema, func, sql, desc) should pass ok 125 - function_lang_is(schema, func, sql, desc) should have the proper description ok 126 - function_lang_is(schema, func, sql, desc) should have the proper diagnostics ok 127 - function_lang_is(schema, func, sql) should pass ok 128 - function_lang_is(schema, func, sql) should have the proper description ok 129 - function_lang_is(schema, func, sql) should have the proper diagnostics ok 130 - function_lang_is(schema, func, perl, desc) should fail ok 131 - function_lang_is(schema, func, perl, desc) should have the proper description ok 132 - function_lang_is(schema, func, perl, desc) should have the proper diagnostics ok 133 - function_lang_is(schema, non-func, sql, desc) should fail ok 134 - function_lang_is(schema, non-func, sql, desc) should have the proper description ok 135 - function_lang_is(schema, non-func, sql, desc) should have the proper diagnostics ok 136 - function_lang_is(func, 0 args, sql, desc) should pass ok 137 - function_lang_is(func, 0 args, sql, desc) should have the proper description ok 138 - function_lang_is(func, 0 args, sql, desc) should have the proper diagnostics ok 139 - function_lang_is(func, 0 args, sql) should pass ok 140 - function_lang_is(func, 0 args, sql) should have the proper description ok 141 - function_lang_is(func, 0 args, sql) should have the proper diagnostics ok 142 - function_lang_is(func, args, plpgsql, desc) should pass ok 143 - function_lang_is(func, args, plpgsql, desc) should have the proper description ok 144 - function_lang_is(func, args, plpgsql, desc) should have the proper diagnostics ok 145 - function_lang_is(func, args, plpgsql) should pass ok 146 - function_lang_is(func, args, plpgsql) should have the proper description ok 147 - function_lang_is(func, args, plpgsql) should have the proper diagnostics ok 148 - function_lang_is(func, 0 args, perl, desc) should fail ok 149 - function_lang_is(func, 0 args, perl, desc) should have the proper description ok 150 - function_lang_is(func, 0 args, perl, desc) should have the proper diagnostics ok 151 - function_lang_is(non-func, 0 args, sql, desc) should fail ok 152 - function_lang_is(non-func, 0 args, sql, desc) should have the proper description ok 153 - function_lang_is(non-func, 0 args, sql, desc) should have the proper diagnostics ok 154 - function_lang_is(func, args, plpgsql) should fail ok 155 - function_lang_is(func, args, plpgsql) should have the proper description ok 156 - function_lang_is(func, args, plpgsql) should have the proper diagnostics ok 157 - function_lang_is(func, sql, desc) should pass ok 158 - function_lang_is(func, sql, desc) should have the proper description ok 159 - function_lang_is(func, sql, desc) should have the proper diagnostics ok 160 - function_lang_is(func, sql) should pass ok 161 - function_lang_is(func, sql) should have the proper description ok 162 - function_lang_is(func, sql) should have the proper diagnostics ok 163 - function_lang_is(func, perl, desc) should fail ok 164 - function_lang_is(func, perl, desc) should have the proper description ok 165 - function_lang_is(func, perl, desc) should have the proper diagnostics ok 166 - function_lang_is(non-func, sql, desc) should fail ok 167 - function_lang_is(non-func, sql, desc) should have the proper description ok 168 - function_lang_is(non-func, sql, desc) should have the proper diagnostics ok 169 - function_returns(schema, func, 0 args, bool, desc) should pass ok 170 - function_returns(schema, func, 0 args, bool, desc) should have the proper description ok 171 - function_returns(schema, func, 0 args, bool, desc) should have the proper diagnostics ok 172 - function_returns(schema, func, 0 args, bool) should pass ok 173 - function_returns(schema, func, 0 args, bool) should have the proper description ok 174 - function_returns(schema, func, 0 args, bool) should have the proper diagnostics ok 175 - function_returns(schema, func, args, bool, false) should pass ok 176 - function_returns(schema, func, args, bool, false) should have the proper description ok 177 - function_returns(schema, func, args, bool, false) should have the proper diagnostics ok 178 - function_returns(schema, func, args, bool) should pass ok 179 - function_returns(schema, func, args, bool) should have the proper description ok 180 - function_returns(schema, func, args, bool) should have the proper diagnostics ok 181 - function_returns(schema, func, 0 args, setof bool, desc) should pass ok 182 - function_returns(schema, func, 0 args, setof bool, desc) should have the proper description ok 183 - function_returns(schema, func, 0 args, setof bool, desc) should have the proper diagnostics ok 184 - function_returns(schema, func, 0 args, setof bool) should pass ok 185 - function_returns(schema, func, 0 args, setof bool) should have the proper description ok 186 - function_returns(schema, func, 0 args, setof bool) should have the proper diagnostics ok 187 - function_returns(schema, func, bool, desc) should pass ok 188 - function_returns(schema, func, bool, desc) should have the proper description ok 189 - function_returns(schema, func, bool, desc) should have the proper diagnostics ok 190 - function_returns(schema, func, bool) should pass ok 191 - function_returns(schema, func, bool) should have the proper description ok 192 - function_returns(schema, func, bool) should have the proper diagnostics ok 193 - function_returns(schema, other func, bool, false) should pass ok 194 - function_returns(schema, other func, bool, false) should have the proper description ok 195 - function_returns(schema, other func, bool, false) should have the proper diagnostics ok 196 - function_returns(schema, other func, bool) should pass ok 197 - function_returns(schema, other func, bool) should have the proper description ok 198 - function_returns(schema, other func, bool) should have the proper diagnostics ok 199 - function_returns(schema, func, setof bool, desc) should pass ok 200 - function_returns(schema, func, setof bool, desc) should have the proper description ok 201 - function_returns(schema, func, setof bool, desc) should have the proper diagnostics ok 202 - function_returns(schema, func, setof bool) should pass ok 203 - function_returns(schema, func, setof bool) should have the proper description ok 204 - function_returns(schema, func, setof bool) should have the proper diagnostics ok 205 - function_returns(func, 0 args, bool, desc) should pass ok 206 - function_returns(func, 0 args, bool, desc) should have the proper description ok 207 - function_returns(func, 0 args, bool, desc) should have the proper diagnostics ok 208 - function_returns(func, 0 args, bool) should pass ok 209 - function_returns(func, 0 args, bool) should have the proper description ok 210 - function_returns(func, 0 args, bool) should have the proper diagnostics ok 211 - function_returns(func, args, bool, false) should pass ok 212 - function_returns(func, args, bool, false) should have the proper description ok 213 - function_returns(func, args, bool, false) should have the proper diagnostics ok 214 - function_returns(func, args, bool) should pass ok 215 - function_returns(func, args, bool) should have the proper description ok 216 - function_returns(func, args, bool) should have the proper diagnostics ok 217 - function_returns(func, 0 args, setof bool, desc) should pass ok 218 - function_returns(func, 0 args, setof bool, desc) should have the proper description ok 219 - function_returns(func, 0 args, setof bool, desc) should have the proper diagnostics ok 220 - function_returns(func, 0 args, setof bool) should pass ok 221 - function_returns(func, 0 args, setof bool) should have the proper description ok 222 - function_returns(func, 0 args, setof bool) should have the proper diagnostics ok 223 - function_returns(func, bool, desc) should pass ok 224 - function_returns(func, bool, desc) should have the proper description ok 225 - function_returns(func, bool, desc) should have the proper diagnostics ok 226 - function_returns(func, bool) should pass ok 227 - function_returns(func, bool) should have the proper description ok 228 - function_returns(func, bool) should have the proper diagnostics ok 229 - function_returns(other func, bool, false) should pass ok 230 - function_returns(other func, bool, false) should have the proper description ok 231 - function_returns(other func, bool, false) should have the proper diagnostics ok 232 - function_returns(other func, bool) should pass ok 233 - function_returns(other func, bool) should have the proper description ok 234 - function_returns(other func, bool) should have the proper diagnostics ok 235 - function_returns(func, setof bool, desc) should pass ok 236 - function_returns(func, setof bool, desc) should have the proper description ok 237 - function_returns(func, setof bool, desc) should have the proper diagnostics ok 238 - function_returns(func, setof bool) should pass ok 239 - function_returns(func, setof bool) should have the proper description ok 240 - function_returns(func, setof bool) should have the proper diagnostics ok 241 - is_definer(schema, func, 0 args, desc) should pass ok 242 - is_definer(schema, func, 0 args, desc) should have the proper description ok 243 - is_definer(schema, func, 0 args, desc) should have the proper diagnostics ok 244 - is_definer(schema, func, 0 args) should pass ok 245 - is_definer(schema, func, 0 args) should have the proper description ok 246 - is_definer(schema, func, 0 args) should have the proper diagnostics ok 247 - is_definer(schema, func, args, desc) should fail ok 248 - is_definer(schema, func, args, desc) should have the proper description ok 249 - is_definer(schema, func, args, desc) should have the proper diagnostics ok 250 - is_definer(schema, func, args) should fail ok 251 - is_definer(schema, func, args) should have the proper description ok 252 - is_definer(schema, func, args) should have the proper diagnostics ok 253 - is_definer(schema, func, desc) should pass ok 254 - is_definer(schema, func, desc) should have the proper description ok 255 - is_definer(schema, func, desc) should have the proper diagnostics ok 256 - is_definer(schema, func) should pass ok 257 - is_definer(schema, func) should have the proper description ok 258 - is_definer(schema, func) should have the proper diagnostics ok 259 - is_definer(schema, func, 0 args, desc) should pass ok 260 - is_definer(schema, func, 0 args, desc) should have the proper description ok 261 - is_definer(schema, func, 0 args, desc) should have the proper diagnostics ok 262 - is_definer(schema, func, 0 args) should pass ok 263 - is_definer(schema, func, 0 args) should have the proper description ok 264 - is_definer(schema, func, 0 args) should have the proper diagnostics ok 265 - is_definer(schema, func, args, desc) should fail ok 266 - is_definer(schema, func, args, desc) should have the proper description ok 267 - is_definer(schema, func, args, desc) should have the proper diagnostics ok 268 - is_definer(schema, func, args) should fail ok 269 - is_definer(schema, func, args) should have the proper description ok 270 - is_definer(schema, func, args) should have the proper diagnostics ok 271 - is_definer(schema, func, desc) should pass ok 272 - is_definer(schema, func, desc) should have the proper description ok 273 - is_definer(schema, func, desc) should have the proper diagnostics ok 274 - is_definer(schema, func) should pass ok 275 - is_definer(schema, func) should have the proper description ok 276 - is_definer(schema, func) should have the proper diagnostics ok 277 - is_definer(func, 0 args, desc) should pass ok 278 - is_definer(func, 0 args, desc) should have the proper description ok 279 - is_definer(func, 0 args, desc) should have the proper diagnostics ok 280 - is_definer(func, 0 args) should pass ok 281 - is_definer(func, 0 args) should have the proper description ok 282 - is_definer(func, 0 args) should have the proper diagnostics ok 283 - is_definer(func, args, desc) should fail ok 284 - is_definer(func, args, desc) should have the proper description ok 285 - is_definer(func, args, desc) should have the proper diagnostics ok 286 - is_definer(func, args) should fail ok 287 - is_definer(func, args) should have the proper description ok 288 - is_definer(func, args) should have the proper diagnostics ok 289 - is_definer(func, desc) should pass ok 290 - is_definer(func, desc) should have the proper description ok 291 - is_definer(func, desc) should have the proper diagnostics ok 292 - is_definer(func) should pass ok 293 - is_definer(func) should have the proper description ok 294 - is_definer(func) should have the proper diagnostics ok 295 - is_aggregate(schema, func, arg, desc) should pass ok 296 - is_aggregate(schema, func, arg, desc) should have the proper description ok 297 - is_aggregate(schema, func, arg, desc) should have the proper diagnostics ok 298 - is_aggregate(schema, func, arg) should pass ok 299 - is_aggregate(schema, func, arg) should have the proper description ok 300 - is_aggregate(schema, func, arg) should have the proper diagnostics ok 301 - is_aggregate(schema, func, args, desc) should fail ok 302 - is_aggregate(schema, func, args, desc) should have the proper description ok 303 - is_aggregate(schema, func, args, desc) should have the proper diagnostics ok 304 - is_aggregate(schema, func, args) should fail ok 305 - is_aggregate(schema, func, args) should have the proper description ok 306 - is_aggregate(schema, func, args) should have the proper diagnostics ok 307 - is_aggregate(schema, func, desc) should pass ok 308 - is_aggregate(schema, func, desc) should have the proper description ok 309 - is_aggregate(schema, func, desc) should have the proper diagnostics ok 310 - is_aggregate(schema, func) should pass ok 311 - is_aggregate(schema, func) should have the proper description ok 312 - is_aggregate(schema, func) should have the proper diagnostics ok 313 - is_aggregate(schema, func, arg, desc) should pass ok 314 - is_aggregate(schema, func, arg, desc) should have the proper description ok 315 - is_aggregate(schema, func, arg, desc) should have the proper diagnostics ok 316 - is_aggregate(schema, func, arg) should pass ok 317 - is_aggregate(schema, func, arg) should have the proper description ok 318 - is_aggregate(schema, func, arg) should have the proper diagnostics ok 319 - is_aggregate(schema, func, args, desc) should fail ok 320 - is_aggregate(schema, func, args, desc) should have the proper description ok 321 - is_aggregate(schema, func, args, desc) should have the proper diagnostics ok 322 - is_aggregate(schema, func, args) should fail ok 323 - is_aggregate(schema, func, args) should have the proper description ok 324 - is_aggregate(schema, func, args) should have the proper diagnostics ok 325 - is_aggregate(schema, func, desc) should pass ok 326 - is_aggregate(schema, func, desc) should have the proper description ok 327 - is_aggregate(schema, func, desc) should have the proper diagnostics ok 328 - is_aggregate(schema, func) should pass ok 329 - is_aggregate(schema, func) should have the proper description ok 330 - is_aggregate(schema, func) should have the proper diagnostics ok 331 - is_aggregate(func, arg, desc) should pass ok 332 - is_aggregate(func, arg, desc) should have the proper description ok 333 - is_aggregate(func, arg, desc) should have the proper diagnostics ok 334 - is_aggregate(func, arg) should pass ok 335 - is_aggregate(func, arg) should have the proper description ok 336 - is_aggregate(func, arg) should have the proper diagnostics ok 337 - is_aggregate(func, args, desc) should fail ok 338 - is_aggregate(func, args, desc) should have the proper description ok 339 - is_aggregate(func, args, desc) should have the proper diagnostics ok 340 - is_aggregate(func, args) should fail ok 341 - is_aggregate(func, args) should have the proper description ok 342 - is_aggregate(func, args) should have the proper diagnostics ok 343 - is_aggregate(func, desc) should pass ok 344 - is_aggregate(func, desc) should have the proper description ok 345 - is_aggregate(func, desc) should have the proper diagnostics ok 346 - is_aggregate(func) should pass ok 347 - is_aggregate(func) should have the proper description ok 348 - is_aggregate(func) should have the proper diagnostics ok 349 - is_strict(schema, func, 0 args, desc) should pass ok 350 - is_strict(schema, func, 0 args, desc) should have the proper description ok 351 - is_strict(schema, func, 0 args, desc) should have the proper diagnostics ok 352 - is_strict(schema, func, 0 args) should pass ok 353 - is_strict(schema, func, 0 args) should have the proper description ok 354 - is_strict(schema, func, 0 args) should have the proper diagnostics ok 355 - is_strict(schema, func, args, desc) should fail ok 356 - is_strict(schema, func, args, desc) should have the proper description ok 357 - is_strict(schema, func, args, desc) should have the proper diagnostics ok 358 - is_strict(schema, func, args) should fail ok 359 - is_strict(schema, func, args) should have the proper description ok 360 - is_strict(schema, func, args) should have the proper diagnostics ok 361 - is_strict(schema, func, desc) should pass ok 362 - is_strict(schema, func, desc) should have the proper description ok 363 - is_strict(schema, func, desc) should have the proper diagnostics ok 364 - is_strict(schema, func) should pass ok 365 - is_strict(schema, func) should have the proper description ok 366 - is_strict(schema, func) should have the proper diagnostics ok 367 - is_strict(schema, func, 0 args, desc) should pass ok 368 - is_strict(schema, func, 0 args, desc) should have the proper description ok 369 - is_strict(schema, func, 0 args, desc) should have the proper diagnostics ok 370 - is_strict(schema, func, 0 args) should pass ok 371 - is_strict(schema, func, 0 args) should have the proper description ok 372 - is_strict(schema, func, 0 args) should have the proper diagnostics ok 373 - is_strict(schema, func, args, desc) should fail ok 374 - is_strict(schema, func, args, desc) should have the proper description ok 375 - is_strict(schema, func, args, desc) should have the proper diagnostics ok 376 - is_strict(schema, func, args) should fail ok 377 - is_strict(schema, func, args) should have the proper description ok 378 - is_strict(schema, func, args) should have the proper diagnostics ok 379 - is_strict(schema, func, desc) should pass ok 380 - is_strict(schema, func, desc) should have the proper description ok 381 - is_strict(schema, func, desc) should have the proper diagnostics ok 382 - is_strict(schema, func) should pass ok 383 - is_strict(schema, func) should have the proper description ok 384 - is_strict(schema, func) should have the proper diagnostics ok 385 - is_strict(func, 0 args, desc) should pass ok 386 - is_strict(func, 0 args, desc) should have the proper description ok 387 - is_strict(func, 0 args, desc) should have the proper diagnostics ok 388 - is_strict(func, 0 args) should pass ok 389 - is_strict(func, 0 args) should have the proper description ok 390 - is_strict(func, 0 args) should have the proper diagnostics ok 391 - is_strict(func, args, desc) should fail ok 392 - is_strict(func, args, desc) should have the proper description ok 393 - is_strict(func, args, desc) should have the proper diagnostics ok 394 - is_strict(func, args) should fail ok 395 - is_strict(func, args) should have the proper description ok 396 - is_strict(func, args) should have the proper diagnostics ok 397 - is_strict(func, desc) should pass ok 398 - is_strict(func, desc) should have the proper description ok 399 - is_strict(func, desc) should have the proper diagnostics ok 400 - is_strict(func) should pass ok 401 - is_strict(func) should have the proper description ok 402 - is_strict(func) should have the proper diagnostics ok 403 - function_volatility(schema, func, 0 args, volatile, desc) should pass ok 404 - function_volatility(schema, func, 0 args, volatile, desc) should have the proper description ok 405 - function_volatility(schema, func, 0 args, volatile, desc) should have the proper diagnostics ok 406 - function_volatility(schema, func, 0 args, VOLATILE, desc) should pass ok 407 - function_volatility(schema, func, 0 args, VOLATILE, desc) should have the proper description ok 408 - function_volatility(schema, func, 0 args, VOLATILE, desc) should have the proper diagnostics ok 409 - function_volatility(schema, func, 0 args, v, desc) should pass ok 410 - function_volatility(schema, func, 0 args, v, desc) should have the proper description ok 411 - function_volatility(schema, func, 0 args, v, desc) should have the proper diagnostics ok 412 - function_volatility(schema, func, args, immutable, desc) should pass ok 413 - function_volatility(schema, func, args, immutable, desc) should have the proper description ok 414 - function_volatility(schema, func, args, immutable, desc) should have the proper diagnostics ok 415 - function_volatility(schema, func, 0 args, stable, desc) should pass ok 416 - function_volatility(schema, func, 0 args, stable, desc) should have the proper description ok 417 - function_volatility(schema, func, 0 args, stable, desc) should have the proper diagnostics ok 418 - function_volatility(schema, func, 0 args, volatile) should pass ok 419 - function_volatility(schema, func, 0 args, volatile) should have the proper description ok 420 - function_volatility(schema, func, 0 args, volatile) should have the proper diagnostics ok 421 - function_volatility(schema, func, args, immutable) should pass ok 422 - function_volatility(schema, func, args, immutable) should have the proper description ok 423 - function_volatility(schema, func, volatile, desc) should pass ok 424 - function_volatility(schema, func, volatile, desc) should have the proper description ok 425 - function_volatility(schema, func, volatile, desc) should have the proper diagnostics ok 426 - function_volatility(schema, func, volatile) should pass ok 427 - function_volatility(schema, func, volatile) should have the proper description ok 428 - function_volatility(schema, func, volatile) should have the proper diagnostics ok 429 - function_volatility(schema, func, immutable, desc) should pass ok 430 - function_volatility(schema, func, immutable, desc) should have the proper description ok 431 - function_volatility(schema, func, immutable, desc) should have the proper diagnostics ok 432 - function_volatility(schema, func, stable, desc) should pass ok 433 - function_volatility(schema, func, stable, desc) should have the proper description ok 434 - function_volatility(schema, func, stable, desc) should have the proper diagnostics ok 435 - function_volatility(func, 0 args, volatile, desc) should pass ok 436 - function_volatility(func, 0 args, volatile, desc) should have the proper description ok 437 - function_volatility(func, 0 args, volatile, desc) should have the proper diagnostics ok 438 - function_volatility(func, 0 args, VOLATILE, desc) should pass ok 439 - function_volatility(func, 0 args, VOLATILE, desc) should have the proper description ok 440 - function_volatility(func, 0 args, VOLATILE, desc) should have the proper diagnostics ok 441 - function_volatility(func, 0 args, v, desc) should pass ok 442 - function_volatility(func, 0 args, v, desc) should have the proper description ok 443 - function_volatility(func, 0 args, v, desc) should have the proper diagnostics ok 444 - function_volatility(func, args, immutable, desc) should pass ok 445 - function_volatility(func, args, immutable, desc) should have the proper description ok 446 - function_volatility(func, args, immutable, desc) should have the proper diagnostics ok 447 - function_volatility(func, 0 args, stable, desc) should pass ok 448 - function_volatility(func, 0 args, stable, desc) should have the proper description ok 449 - function_volatility(func, 0 args, stable, desc) should have the proper diagnostics ok 450 - function_volatility(func, 0 args, volatile) should pass ok 451 - function_volatility(func, 0 args, volatile) should have the proper description ok 452 - function_volatility(func, 0 args, volatile) should have the proper diagnostics ok 453 - function_volatility(func, args, immutable) should pass ok 454 - function_volatility(func, args, immutable) should have the proper description ok 455 - function_volatility(func, volatile, desc) should pass ok 456 - function_volatility(func, volatile, desc) should have the proper description ok 457 - function_volatility(func, volatile, desc) should have the proper diagnostics ok 458 - function_volatility(func, volatile) should pass ok 459 - function_volatility(func, volatile) should have the proper description ok 460 - function_volatility(func, volatile) should have the proper diagnostics ok 461 - function_volatility(func, immutable, desc) should pass ok 462 - function_volatility(func, immutable, desc) should have the proper description ok 463 - function_volatility(func, immutable, desc) should have the proper diagnostics ok 464 - function_volatility(func, stable, desc) should pass ok 465 - function_volatility(func, stable, desc) should have the proper description ok 466 - function_volatility(func, stable, desc) should have the proper diagnostics pgtap-0.90.0/test/expected/._hastap.out000644 000765 000024 00000000252 11666501762 020164 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/hastap.out000644 000765 000024 00000136465 11666501762 017767 0ustar00davidstaff000000 000000 \unset ECHO 1..678 ok 1 - has_tablespace(non-existent tablespace) should fail ok 2 - has_tablespace(non-existent tablespace) should have the proper description ok 3 - has_tablespace(non-existent tablespace) should have the proper diagnostics ok 4 - has_tablespace(non-existent tablespace, tab) should fail ok 5 - has_tablespace(non-existent tablespace, tab) should have the proper description ok 6 - has_tablespace(non-existent tablespace, tab) should have the proper diagnostics ok 7 - has_tablespace(tablespace) should pass ok 8 - has_tablespace(tablespace) should have the proper description ok 9 - has_tablespace(tablespace) should have the proper diagnostics ok 10 - has_tablespace(tablespace, desc) should pass ok 11 - has_tablespace(tablespace, desc) should have the proper description ok 12 - has_tablespace(tablespace, desc) should have the proper diagnostics ok 13 - hasnt_tablespace(non-existent tablespace) should pass ok 14 - hasnt_tablespace(non-existent tablespace) should have the proper description ok 15 - hasnt_tablespace(non-existent tablespace) should have the proper diagnostics ok 16 - hasnt_tablespace(non-existent tablespace, tab) should pass ok 17 - hasnt_tablespace(non-existent tablespace, tab) should have the proper description ok 18 - hasnt_tablespace(non-existent tablespace, tab) should have the proper diagnostics ok 19 - hasnt_tablespace(pg_default) should fail ok 20 - hasnt_tablespace(pg_default) should have the proper description ok 21 - hasnt_tablespace(pg_default) should have the proper diagnostics ok 22 - hasnt_tablespace(tablespace, desc) should fail ok 23 - hasnt_tablespace(tablespace, desc) should have the proper description ok 24 - hasnt_tablespace(tablespace, desc) should have the proper diagnostics ok 25 - has_schema(non-existent schema) should fail ok 26 - has_schema(non-existent schema) should have the proper description ok 27 - has_schema(non-existent schema) should have the proper diagnostics ok 28 - has_schema(non-existent schema, tab) should fail ok 29 - has_schema(non-existent schema, tab) should have the proper description ok 30 - has_schema(non-existent schema, tab) should have the proper diagnostics ok 31 - has_schema(schema) should pass ok 32 - has_schema(schema) should have the proper description ok 33 - has_schema(schema) should have the proper diagnostics ok 34 - has_schema(schema, desc) should pass ok 35 - has_schema(schema, desc) should have the proper description ok 36 - has_schema(schema, desc) should have the proper diagnostics ok 37 - hasnt_schema(non-existent schema) should pass ok 38 - hasnt_schema(non-existent schema) should have the proper description ok 39 - hasnt_schema(non-existent schema) should have the proper diagnostics ok 40 - hasnt_schema(non-existent schema, tab) should pass ok 41 - hasnt_schema(non-existent schema, tab) should have the proper description ok 42 - hasnt_schema(non-existent schema, tab) should have the proper diagnostics ok 43 - hasnt_schema(schema) should fail ok 44 - hasnt_schema(schema) should have the proper description ok 45 - hasnt_schema(schema) should have the proper diagnostics ok 46 - hasnt_schema(schema, desc) should fail ok 47 - hasnt_schema(schema, desc) should have the proper description ok 48 - hasnt_schema(schema, desc) should have the proper diagnostics ok 49 - has_table(non-existent table) should fail ok 50 - has_table(non-existent table) should have the proper description ok 51 - has_table(non-existent table) should have the proper diagnostics ok 52 - has_table(non-existent schema, tab) should fail ok 53 - has_table(non-existent schema, tab) should have the proper description ok 54 - has_table(non-existent schema, tab) should have the proper diagnostics ok 55 - has_table(sch, non-existent table, desc) should fail ok 56 - has_table(sch, non-existent table, desc) should have the proper description ok 57 - has_table(sch, non-existent table, desc) should have the proper diagnostics ok 58 - has_table(tab, desc) should pass ok 59 - has_table(tab, desc) should have the proper description ok 60 - has_table(tab, desc) should have the proper diagnostics ok 61 - has_table(sch, tab, desc) should pass ok 62 - has_table(sch, tab, desc) should have the proper description ok 63 - has_table(sch, tab, desc) should have the proper diagnostics ok 64 - has_table(sch, view, desc) should fail ok 65 - has_table(sch, view, desc) should have the proper description ok 66 - has_table(sch, view, desc) should have the proper diagnostics ok 67 - has_table(type, desc) should fail ok 68 - has_table(type, desc) should have the proper description ok 69 - has_table(type, desc) should have the proper diagnostics ok 70 - hasnt_table(non-existent table) should pass ok 71 - hasnt_table(non-existent table) should have the proper description ok 72 - hasnt_table(non-existent table) should have the proper diagnostics ok 73 - hasnt_table(non-existent schema, tab) should pass ok 74 - hasnt_table(non-existent schema, tab) should have the proper description ok 75 - hasnt_table(non-existent schema, tab) should have the proper diagnostics ok 76 - hasnt_table(sch, non-existent tab, desc) should pass ok 77 - hasnt_table(sch, non-existent tab, desc) should have the proper description ok 78 - hasnt_table(sch, non-existent tab, desc) should have the proper diagnostics ok 79 - hasnt_table(tab, desc) should fail ok 80 - hasnt_table(tab, desc) should have the proper description ok 81 - hasnt_table(tab, desc) should have the proper diagnostics ok 82 - hasnt_table(sch, tab, desc) should fail ok 83 - hasnt_table(sch, tab, desc) should have the proper description ok 84 - hasnt_table(sch, tab, desc) should have the proper diagnostics ok 85 - has_view(non-existent view) should fail ok 86 - has_view(non-existent view) should have the proper description ok 87 - has_view(non-existent view) should have the proper diagnostics ok 88 - has_view(non-existent view, desc) should fail ok 89 - has_view(non-existent view, desc) should have the proper description ok 90 - has_view(non-existent view, desc) should have the proper diagnostics ok 91 - has_view(sch, non-existtent view, desc) should fail ok 92 - has_view(sch, non-existtent view, desc) should have the proper description ok 93 - has_view(sch, non-existtent view, desc) should have the proper diagnostics ok 94 - has_view(view, desc) should pass ok 95 - has_view(view, desc) should have the proper description ok 96 - has_view(view, desc) should have the proper diagnostics ok 97 - has_view(sch, view, desc) should pass ok 98 - has_view(sch, view, desc) should have the proper description ok 99 - has_view(sch, view, desc) should have the proper diagnostics ok 100 - hasnt_view(non-existent view) should pass ok 101 - hasnt_view(non-existent view) should have the proper description ok 102 - hasnt_view(non-existent view) should have the proper diagnostics ok 103 - hasnt_view(non-existent view, desc) should pass ok 104 - hasnt_view(non-existent view, desc) should have the proper description ok 105 - hasnt_view(non-existent view, desc) should have the proper diagnostics ok 106 - hasnt_view(sch, non-existtent view, desc) should pass ok 107 - hasnt_view(sch, non-existtent view, desc) should have the proper description ok 108 - hasnt_view(sch, non-existtent view, desc) should have the proper diagnostics ok 109 - hasnt_view(view, desc) should fail ok 110 - hasnt_view(view, desc) should have the proper description ok 111 - hasnt_view(view, desc) should have the proper diagnostics ok 112 - hasnt_view(sch, view, desc) should fail ok 113 - hasnt_view(sch, view, desc) should have the proper description ok 114 - hasnt_view(sch, view, desc) should have the proper diagnostics ok 115 - has_sequence(non-existent sequence) should fail ok 116 - has_sequence(non-existent sequence) should have the proper description ok 117 - has_sequence(non-existent sequence) should have the proper diagnostics ok 118 - has_sequence(non-existent sequence, desc) should fail ok 119 - has_sequence(non-existent sequence, desc) should have the proper description ok 120 - has_sequence(non-existent sequence, desc) should have the proper diagnostics ok 121 - has_sequence(sch, non-existtent sequence, desc) should fail ok 122 - has_sequence(sch, non-existtent sequence, desc) should have the proper description ok 123 - has_sequence(sch, non-existtent sequence, desc) should have the proper diagnostics ok 124 - has_sequence(sequence, desc) should pass ok 125 - has_sequence(sequence, desc) should have the proper description ok 126 - has_sequence(sequence, desc) should have the proper diagnostics ok 127 - has_sequence(sch, sequence, desc) should pass ok 128 - has_sequence(sch, sequence, desc) should have the proper description ok 129 - has_sequence(sch, sequence, desc) should have the proper diagnostics ok 130 - hasnt_sequence(non-existent sequence) should pass ok 131 - hasnt_sequence(non-existent sequence) should have the proper description ok 132 - hasnt_sequence(non-existent sequence) should have the proper diagnostics ok 133 - hasnt_sequence(non-existent sequence, desc) should pass ok 134 - hasnt_sequence(non-existent sequence, desc) should have the proper description ok 135 - hasnt_sequence(non-existent sequence, desc) should have the proper diagnostics ok 136 - hasnt_sequence(sch, non-existtent sequence, desc) should pass ok 137 - hasnt_sequence(sch, non-existtent sequence, desc) should have the proper description ok 138 - hasnt_sequence(sch, non-existtent sequence, desc) should have the proper diagnostics ok 139 - hasnt_sequence(sequence, desc) should fail ok 140 - hasnt_sequence(sequence, desc) should have the proper description ok 141 - hasnt_sequence(sequence, desc) should have the proper diagnostics ok 142 - hasnt_sequence(sch, sequence, desc) should fail ok 143 - hasnt_sequence(sch, sequence, desc) should have the proper description ok 144 - hasnt_sequence(sch, sequence, desc) should have the proper diagnostics ok 145 - has_type(type) should pass ok 146 - has_type(type) should have the proper description ok 147 - has_type(type) should have the proper diagnostics ok 148 - has_type(type, desc) should pass ok 149 - has_type(type, desc) should have the proper description ok 150 - has_type(type, desc) should have the proper diagnostics ok 151 - has_type(scheam, type) should pass ok 152 - has_type(scheam, type) should have the proper description ok 153 - has_type(scheam, type) should have the proper diagnostics ok 154 - has_type(schema, type, desc) should pass ok 155 - has_type(schema, type, desc) should have the proper description ok 156 - has_type(schema, type, desc) should have the proper diagnostics ok 157 - has_type(myType) should pass ok 158 - has_type(myType) should have the proper description ok 159 - has_type(myType) should have the proper diagnostics ok 160 - has_type(myType, desc) should pass ok 161 - has_type(myType, desc) should have the proper description ok 162 - has_type(myType, desc) should have the proper diagnostics ok 163 - has_type(scheam, myType) should pass ok 164 - has_type(scheam, myType) should have the proper description ok 165 - has_type(scheam, myType) should have the proper diagnostics ok 166 - has_type(schema, myType, desc) should pass ok 167 - has_type(schema, myType, desc) should have the proper description ok 168 - has_type(schema, myType, desc) should have the proper diagnostics ok 169 - has_type(type) should fail ok 170 - has_type(type) should have the proper description ok 171 - has_type(type) should have the proper diagnostics ok 172 - has_type(type, desc) should fail ok 173 - has_type(type, desc) should have the proper description ok 174 - has_type(type, desc) should have the proper diagnostics ok 175 - has_type(scheam, type) should fail ok 176 - has_type(scheam, type) should have the proper description ok 177 - has_type(scheam, type) should have the proper diagnostics ok 178 - has_type(schema, type, desc) should fail ok 179 - has_type(schema, type, desc) should have the proper description ok 180 - has_type(schema, type, desc) should have the proper diagnostics ok 181 - has_type(domain) should pass ok 182 - has_type(domain) should have the proper description ok 183 - has_type(domain) should have the proper diagnostics ok 184 - has_type(myDomain) should pass ok 185 - has_type(myDomain) should have the proper description ok 186 - has_type(myDomain) should have the proper diagnostics ok 187 - hasnt_type(type) should pass ok 188 - hasnt_type(type) should have the proper description ok 189 - hasnt_type(type) should have the proper diagnostics ok 190 - hasnt_type(type, desc) should pass ok 191 - hasnt_type(type, desc) should have the proper description ok 192 - hasnt_type(type, desc) should have the proper diagnostics ok 193 - hasnt_type(scheam, type) should pass ok 194 - hasnt_type(scheam, type) should have the proper description ok 195 - hasnt_type(scheam, type) should have the proper diagnostics ok 196 - hasnt_type(schema, type, desc) should pass ok 197 - hasnt_type(schema, type, desc) should have the proper description ok 198 - hasnt_type(schema, type, desc) should have the proper diagnostics ok 199 - hasnt_type(type) should fail ok 200 - hasnt_type(type) should have the proper description ok 201 - hasnt_type(type) should have the proper diagnostics ok 202 - hasnt_type(type, desc) should fail ok 203 - hasnt_type(type, desc) should have the proper description ok 204 - hasnt_type(type, desc) should have the proper diagnostics ok 205 - hasnt_type(scheam, type) should fail ok 206 - hasnt_type(scheam, type) should have the proper description ok 207 - hasnt_type(scheam, type) should have the proper diagnostics ok 208 - hasnt_type(schema, type, desc) should fail ok 209 - hasnt_type(schema, type, desc) should have the proper description ok 210 - hasnt_type(schema, type, desc) should have the proper diagnostics ok 211 - has_domain(domain) should pass ok 212 - has_domain(domain) should have the proper description ok 213 - has_domain(domain) should have the proper diagnostics ok 214 - has_domain(domain, desc) should pass ok 215 - has_domain(domain, desc) should have the proper description ok 216 - has_domain(domain, desc) should have the proper diagnostics ok 217 - has_domain(scheam, domain) should pass ok 218 - has_domain(scheam, domain) should have the proper description ok 219 - has_domain(scheam, domain) should have the proper diagnostics ok 220 - has_domain(schema, domain, desc) should pass ok 221 - has_domain(schema, domain, desc) should have the proper description ok 222 - has_domain(schema, domain, desc) should have the proper diagnostics ok 223 - has_domain(myDomain) should pass ok 224 - has_domain(myDomain) should have the proper description ok 225 - has_domain(myDomain) should have the proper diagnostics ok 226 - has_domain(myDomain, desc) should pass ok 227 - has_domain(myDomain, desc) should have the proper description ok 228 - has_domain(myDomain, desc) should have the proper diagnostics ok 229 - has_domain(scheam, myDomain) should pass ok 230 - has_domain(scheam, myDomain) should have the proper description ok 231 - has_domain(scheam, myDomain) should have the proper diagnostics ok 232 - has_domain(schema, myDomain, desc) should pass ok 233 - has_domain(schema, myDomain, desc) should have the proper description ok 234 - has_domain(schema, myDomain, desc) should have the proper diagnostics ok 235 - has_domain(domain) should fail ok 236 - has_domain(domain) should have the proper description ok 237 - has_domain(domain) should have the proper diagnostics ok 238 - has_domain(domain, desc) should fail ok 239 - has_domain(domain, desc) should have the proper description ok 240 - has_domain(domain, desc) should have the proper diagnostics ok 241 - has_domain(scheam, domain) should fail ok 242 - has_domain(scheam, domain) should have the proper description ok 243 - has_domain(scheam, domain) should have the proper diagnostics ok 244 - has_domain(schema, domain, desc) should fail ok 245 - has_domain(schema, domain, desc) should have the proper description ok 246 - has_domain(schema, domain, desc) should have the proper diagnostics ok 247 - hasnt_domain(domain) should pass ok 248 - hasnt_domain(domain) should have the proper description ok 249 - hasnt_domain(domain) should have the proper diagnostics ok 250 - hasnt_domain(domain, desc) should pass ok 251 - hasnt_domain(domain, desc) should have the proper description ok 252 - hasnt_domain(domain, desc) should have the proper diagnostics ok 253 - hasnt_domain(scheam, domain) should pass ok 254 - hasnt_domain(scheam, domain) should have the proper description ok 255 - hasnt_domain(scheam, domain) should have the proper diagnostics ok 256 - hasnt_domain(schema, domain, desc) should pass ok 257 - hasnt_domain(schema, domain, desc) should have the proper description ok 258 - hasnt_domain(schema, domain, desc) should have the proper diagnostics ok 259 - hasnt_domain(domain) should fail ok 260 - hasnt_domain(domain) should have the proper description ok 261 - hasnt_domain(domain) should have the proper diagnostics ok 262 - hasnt_domain(domain, desc) should fail ok 263 - hasnt_domain(domain, desc) should have the proper description ok 264 - hasnt_domain(domain, desc) should have the proper diagnostics ok 265 - hasnt_domain(scheam, domain) should fail ok 266 - hasnt_domain(scheam, domain) should have the proper description ok 267 - hasnt_domain(scheam, domain) should have the proper diagnostics ok 268 - hasnt_domain(schema, domain, desc) should fail ok 269 - hasnt_domain(schema, domain, desc) should have the proper description ok 270 - hasnt_domain(schema, domain, desc) should have the proper diagnostics ok 271 - has_column(non-existent tab, col) should fail ok 272 - has_column(non-existent tab, col) should have the proper description ok 273 - has_column(non-existent tab, col) should have the proper diagnostics ok 274 - has_column(non-existent tab, col, desc) should fail ok 275 - has_column(non-existent tab, col, desc) should have the proper description ok 276 - has_column(non-existent tab, col, desc) should have the proper diagnostics ok 277 - has_column(non-existent sch, tab, col, desc) should fail ok 278 - has_column(non-existent sch, tab, col, desc) should have the proper description ok 279 - has_column(non-existent sch, tab, col, desc) should have the proper diagnostics ok 280 - has_column(table, column) should pass ok 281 - has_column(table, column) should have the proper description ok 282 - has_column(table, column) should have the proper diagnostics ok 283 - has_column(sch, tab, col, desc) should pass ok 284 - has_column(sch, tab, col, desc) should have the proper description ok 285 - has_column(sch, tab, col, desc) should have the proper diagnostics ok 286 - has_column(table, camleCase column) should pass ok 287 - has_column(table, camleCase column) should have the proper description ok 288 - has_column(table, camleCase column) should have the proper diagnostics ok 289 - has_column(view, column) should pass ok 290 - has_column(view, column) should have the proper description ok 291 - has_column(view, column) should have the proper diagnostics ok 292 - has_column(type, column) should pass ok 293 - has_column(type, column) should have the proper description ok 294 - has_column(type, column) should have the proper diagnostics ok 295 - hasnt_column(non-existent tab, col) should pass ok 296 - hasnt_column(non-existent tab, col) should have the proper description ok 297 - hasnt_column(non-existent tab, col) should have the proper diagnostics ok 298 - hasnt_column(non-existent tab, col, desc) should pass ok 299 - hasnt_column(non-existent tab, col, desc) should have the proper description ok 300 - hasnt_column(non-existent tab, col, desc) should have the proper diagnostics ok 301 - hasnt_column(non-existent sch, tab, col, desc) should pass ok 302 - hasnt_column(non-existent sch, tab, col, desc) should have the proper description ok 303 - hasnt_column(non-existent sch, tab, col, desc) should have the proper diagnostics ok 304 - hasnt_column(table, column) should fail ok 305 - hasnt_column(table, column) should have the proper description ok 306 - hasnt_column(table, column) should have the proper diagnostics ok 307 - hasnt_column(sch, tab, col, desc) should fail ok 308 - hasnt_column(sch, tab, col, desc) should have the proper description ok 309 - hasnt_column(sch, tab, col, desc) should have the proper diagnostics ok 310 - hasnt_column(view, column) should pass ok 311 - hasnt_column(view, column) should have the proper description ok 312 - hasnt_column(view, column) should have the proper diagnostics ok 313 - hasnt_column(type, column) should pass ok 314 - hasnt_column(type, column) should have the proper description ok 315 - hasnt_column(type, column) should have the proper diagnostics ok 316 - has_cast( src, targ, schema, func, desc) should pass ok 317 - has_cast( src, targ, schema, func, desc) should have the proper description ok 318 - has_cast( src, targ, schema, func, desc) should have the proper diagnostics ok 319 - has_cast( src, targ, schema, func ) should pass ok 320 - has_cast( src, targ, schema, func ) should have the proper description ok 321 - has_cast( src, targ, schema, func ) should have the proper diagnostics ok 322 - has_cast( src, targ, func, desc ) should pass ok 323 - has_cast( src, targ, func, desc ) should have the proper description ok 324 - has_cast( src, targ, func, desc ) should have the proper diagnostics ok 325 - has_cast( src, targ, func) should pass ok 326 - has_cast( src, targ, func) should have the proper description ok 327 - has_cast( src, targ, func) should have the proper diagnostics ok 328 - has_cast( src, targ, desc ) should pass ok 329 - has_cast( src, targ, desc ) should have the proper description ok 330 - has_cast( src, targ, desc ) should have the proper diagnostics ok 331 - has_cast( src, targ ) should pass ok 332 - has_cast( src, targ ) should have the proper description ok 333 - has_cast( src, targ ) should have the proper diagnostics ok 334 - has_cast( src, targ, schema, func, desc) fail should fail ok 335 - has_cast( src, targ, schema, func, desc) fail should have the proper description ok 336 - has_cast( src, targ, schema, func, desc) fail should have the proper diagnostics ok 337 - has_cast( src, targ, func, desc ) fail should fail ok 338 - has_cast( src, targ, func, desc ) fail should have the proper description ok 339 - has_cast( src, targ, func, desc ) fail should have the proper diagnostics ok 340 - has_cast( src, targ, desc ) fail should fail ok 341 - has_cast( src, targ, desc ) fail should have the proper description ok 342 - has_cast( src, targ, desc ) fail should have the proper diagnostics ok 343 - hasnt_cast( src, targ, schema, func, desc) should fail ok 344 - hasnt_cast( src, targ, schema, func, desc) should have the proper description ok 345 - hasnt_cast( src, targ, schema, func, desc) should have the proper diagnostics ok 346 - hasnt_cast( src, targ, schema, func ) should fail ok 347 - hasnt_cast( src, targ, schema, func ) should have the proper description ok 348 - hasnt_cast( src, targ, schema, func ) should have the proper diagnostics ok 349 - hasnt_cast( src, targ, func, desc ) should fail ok 350 - hasnt_cast( src, targ, func, desc ) should have the proper description ok 351 - hasnt_cast( src, targ, func, desc ) should have the proper diagnostics ok 352 - hasnt_cast( src, targ, func) should fail ok 353 - hasnt_cast( src, targ, func) should have the proper description ok 354 - hasnt_cast( src, targ, func) should have the proper diagnostics ok 355 - hasnt_cast( src, targ, desc ) should fail ok 356 - hasnt_cast( src, targ, desc ) should have the proper description ok 357 - hasnt_cast( src, targ, desc ) should have the proper diagnostics ok 358 - hasnt_cast( src, targ ) should fail ok 359 - hasnt_cast( src, targ ) should have the proper description ok 360 - hasnt_cast( src, targ ) should have the proper diagnostics ok 361 - hasnt_cast( src, targ, schema, func, desc) fail should pass ok 362 - hasnt_cast( src, targ, schema, func, desc) fail should have the proper description ok 363 - hasnt_cast( src, targ, schema, func, desc) fail should have the proper diagnostics ok 364 - hasnt_cast( src, targ, func, desc ) fail should pass ok 365 - hasnt_cast( src, targ, func, desc ) fail should have the proper description ok 366 - hasnt_cast( src, targ, func, desc ) fail should have the proper diagnostics ok 367 - hasnt_cast( src, targ, desc ) fail should pass ok 368 - hasnt_cast( src, targ, desc ) fail should have the proper description ok 369 - hasnt_cast( src, targ, desc ) fail should have the proper diagnostics ok 370 - cast_context_is( src, targ, context, desc ) should pass ok 371 - cast_context_is( src, targ, context, desc ) should have the proper description ok 372 - cast_context_is( src, targ, context, desc ) should have the proper diagnostics ok 373 - cast_context_is( src, targ, context ) should pass ok 374 - cast_context_is( src, targ, context ) should have the proper description ok 375 - cast_context_is( src, targ, context ) should have the proper diagnostics ok 376 - cast_context_is( src, targ, i, desc ) should pass ok 377 - cast_context_is( src, targ, i, desc ) should have the proper description ok 378 - cast_context_is( src, targ, i, desc ) should have the proper diagnostics ok 379 - cast_context_is( src, targ, IMPL, desc ) should pass ok 380 - cast_context_is( src, targ, IMPL, desc ) should have the proper description ok 381 - cast_context_is( src, targ, IMPL, desc ) should have the proper diagnostics ok 382 - cast_context_is( src, targ, assignment, desc ) should pass ok 383 - cast_context_is( src, targ, assignment, desc ) should have the proper description ok 384 - cast_context_is( src, targ, assignment, desc ) should have the proper diagnostics ok 385 - cast_context_is( src, targ, a, desc ) should pass ok 386 - cast_context_is( src, targ, a, desc ) should have the proper description ok 387 - cast_context_is( src, targ, a, desc ) should have the proper diagnostics ok 388 - cast_context_is( src, targ, ASS, desc ) should pass ok 389 - cast_context_is( src, targ, ASS, desc ) should have the proper description ok 390 - cast_context_is( src, targ, ASS, desc ) should have the proper diagnostics ok 391 - cast_context_is( src, targ, explicit, desc ) should pass ok 392 - cast_context_is( src, targ, explicit, desc ) should have the proper description ok 393 - cast_context_is( src, targ, explicit, desc ) should have the proper diagnostics ok 394 - cast_context_is( src, targ, e, desc ) should pass ok 395 - cast_context_is( src, targ, e, desc ) should have the proper description ok 396 - cast_context_is( src, targ, e, desc ) should have the proper diagnostics ok 397 - cast_context_is( src, targ, EX, desc ) should pass ok 398 - cast_context_is( src, targ, EX, desc ) should have the proper description ok 399 - cast_context_is( src, targ, EX, desc ) should have the proper diagnostics ok 400 - cast_context_is( src, targ, context, desc ) fail should fail ok 401 - cast_context_is( src, targ, context, desc ) fail should have the proper description ok 402 - cast_context_is( src, targ, context, desc ) fail should have the proper diagnostics ok 403 - cast_context_is( src, targ, context ) fail should fail ok 404 - cast_context_is( src, targ, context ) fail should have the proper description ok 405 - cast_context_is( src, targ, context ) fail should have the proper diagnostics ok 406 - cast_context_is( src, targ, context, desc ) noexist should fail ok 407 - cast_context_is( src, targ, context, desc ) noexist should have the proper description ok 408 - cast_context_is( src, targ, context, desc ) noexist should have the proper diagnostics ok 409 - has_operator( left, schema, name, right, result, desc ) should pass ok 410 - has_operator( left, schema, name, right, result, desc ) should have the proper description ok 411 - has_operator( left, schema, name, right, result, desc ) should have the proper diagnostics ok 412 - has_operator( left, schema, name, right, result ) should pass ok 413 - has_operator( left, schema, name, right, result ) should have the proper description ok 414 - has_operator( left, schema, name, right, result ) should have the proper diagnostics ok 415 - has_operator( left, name, right, result, desc ) should pass ok 416 - has_operator( left, name, right, result, desc ) should have the proper description ok 417 - has_operator( left, name, right, result, desc ) should have the proper diagnostics ok 418 - has_operator( left, name, right, result ) should pass ok 419 - has_operator( left, name, right, result ) should have the proper description ok 420 - has_operator( left, name, right, result ) should have the proper diagnostics ok 421 - has_operator( left, name, right, desc ) should pass ok 422 - has_operator( left, name, right, desc ) should have the proper description ok 423 - has_operator( left, name, right, desc ) should have the proper diagnostics ok 424 - has_operator( left, name, right ) should pass ok 425 - has_operator( left, name, right ) should have the proper description ok 426 - has_operator( left, name, right ) should have the proper diagnostics ok 427 - has_operator( left, schema, name, right, result, desc ) fail should fail ok 428 - has_operator( left, schema, name, right, result, desc ) fail should have the proper description ok 429 - has_operator( left, schema, name, right, result, desc ) fail should have the proper diagnostics ok 430 - has_operator( left, schema, name, right, result ) fail should fail ok 431 - has_operator( left, schema, name, right, result ) fail should have the proper description ok 432 - has_operator( left, schema, name, right, result ) fail should have the proper diagnostics ok 433 - has_operator( left, name, right, result, desc ) fail should fail ok 434 - has_operator( left, name, right, result, desc ) fail should have the proper description ok 435 - has_operator( left, name, right, result, desc ) fail should have the proper diagnostics ok 436 - has_operator( left, name, right, result ) fail should fail ok 437 - has_operator( left, name, right, result ) fail should have the proper description ok 438 - has_operator( left, name, right, result ) fail should have the proper diagnostics ok 439 - has_operator( left, name, right, desc ) fail should fail ok 440 - has_operator( left, name, right, desc ) fail should have the proper description ok 441 - has_operator( left, name, right, desc ) fail should have the proper diagnostics ok 442 - has_operator( left, name, right ) fail should fail ok 443 - has_operator( left, name, right ) fail should have the proper description ok 444 - has_operator( left, name, right ) fail should have the proper diagnostics ok 445 - has_leftop( schema, name, right, result, desc ) should pass ok 446 - has_leftop( schema, name, right, result, desc ) should have the proper description ok 447 - has_leftop( schema, name, right, result, desc ) should have the proper diagnostics ok 448 - has_leftop( schema, name, right, result ) should pass ok 449 - has_leftop( schema, name, right, result ) should have the proper description ok 450 - has_leftop( schema, name, right, result ) should have the proper diagnostics ok 451 - has_leftop( name, right, result, desc ) should pass ok 452 - has_leftop( name, right, result, desc ) should have the proper description ok 453 - has_leftop( name, right, result, desc ) should have the proper diagnostics ok 454 - has_leftop( name, right, result ) should pass ok 455 - has_leftop( name, right, result ) should have the proper description ok 456 - has_leftop( name, right, result ) should have the proper diagnostics ok 457 - has_leftop( name, right, desc ) should pass ok 458 - has_leftop( name, right, desc ) should have the proper description ok 459 - has_leftop( name, right, desc ) should have the proper diagnostics ok 460 - has_leftop( name, right ) should pass ok 461 - has_leftop( name, right ) should have the proper description ok 462 - has_leftop( name, right ) should have the proper diagnostics ok 463 - has_leftop( schema, name, right, result, desc ) fail should fail ok 464 - has_leftop( schema, name, right, result, desc ) fail should have the proper description ok 465 - has_leftop( schema, name, right, result, desc ) fail should have the proper diagnostics ok 466 - has_leftop( schema, name, right, result ) fail should fail ok 467 - has_leftop( schema, name, right, result ) fail should have the proper description ok 468 - has_leftop( schema, name, right, result ) fail should have the proper diagnostics ok 469 - has_leftop( name, right, result, desc ) fail should fail ok 470 - has_leftop( name, right, result, desc ) fail should have the proper description ok 471 - has_leftop( name, right, result, desc ) fail should have the proper diagnostics ok 472 - has_leftop( name, right, result ) fail should fail ok 473 - has_leftop( name, right, result ) fail should have the proper description ok 474 - has_leftop( name, right, result ) fail should have the proper diagnostics ok 475 - has_leftop( name, right, desc ) fail should fail ok 476 - has_leftop( name, right, desc ) fail should have the proper description ok 477 - has_leftop( name, right, desc ) fail should have the proper diagnostics ok 478 - has_leftop( name, right ) fail should fail ok 479 - has_leftop( name, right ) fail should have the proper description ok 480 - has_leftop( name, right ) fail should have the proper diagnostics ok 481 - has_rightop( left, schema, name, result, desc ) should pass ok 482 - has_rightop( left, schema, name, result, desc ) should have the proper description ok 483 - has_rightop( left, schema, name, result, desc ) should have the proper diagnostics ok 484 - has_rightop( left, schema, name, result ) should pass ok 485 - has_rightop( left, schema, name, result ) should have the proper description ok 486 - has_rightop( left, schema, name, result ) should have the proper diagnostics ok 487 - has_rightop( left, name, result, desc ) should pass ok 488 - has_rightop( left, name, result, desc ) should have the proper description ok 489 - has_rightop( left, name, result, desc ) should have the proper diagnostics ok 490 - has_rightop( left, name, result ) should pass ok 491 - has_rightop( left, name, result ) should have the proper description ok 492 - has_rightop( left, name, result ) should have the proper diagnostics ok 493 - has_rightop( left, name, desc ) should pass ok 494 - has_rightop( left, name, desc ) should have the proper description ok 495 - has_rightop( left, name, desc ) should have the proper diagnostics ok 496 - has_rightop( left, name ) should pass ok 497 - has_rightop( left, name ) should have the proper description ok 498 - has_rightop( left, name ) should have the proper diagnostics ok 499 - has_rightop( left, schema, name, result, desc ) fail should fail ok 500 - has_rightop( left, schema, name, result, desc ) fail should have the proper description ok 501 - has_rightop( left, schema, name, result, desc ) fail should have the proper diagnostics ok 502 - has_rightop( left, schema, name, result ) fail should fail ok 503 - has_rightop( left, schema, name, result ) fail should have the proper description ok 504 - has_rightop( left, schema, name, result ) fail should have the proper diagnostics ok 505 - has_rightop( left, name, result, desc ) fail should fail ok 506 - has_rightop( left, name, result, desc ) fail should have the proper description ok 507 - has_rightop( left, name, result, desc ) fail should have the proper diagnostics ok 508 - has_rightop( left, name, result ) fail should fail ok 509 - has_rightop( left, name, result ) fail should have the proper description ok 510 - has_rightop( left, name, result ) fail should have the proper diagnostics ok 511 - has_rightop( left, name, desc ) fail should fail ok 512 - has_rightop( left, name, desc ) fail should have the proper description ok 513 - has_rightop( left, name, desc ) fail should have the proper diagnostics ok 514 - has_rightop( left, name ) fail should fail ok 515 - has_rightop( left, name ) fail should have the proper description ok 516 - has_rightop( left, name ) fail should have the proper diagnostics ok 517 - has_language(language) should pass ok 518 - has_language(language) should have the proper description ok 519 - has_language(language) should have the proper diagnostics ok 520 - has_language(language, desc) should pass ok 521 - has_language(language, desc) should have the proper description ok 522 - has_language(language, desc) should have the proper diagnostics ok 523 - has_language(nonexistent language) should fail ok 524 - has_language(nonexistent language) should have the proper description ok 525 - has_language(nonexistent language) should have the proper diagnostics ok 526 - has_language(nonexistent language, desc) should fail ok 527 - has_language(nonexistent language, desc) should have the proper description ok 528 - has_language(nonexistent language, desc) should have the proper diagnostics ok 529 - hasnt_language(language) should fail ok 530 - hasnt_language(language) should have the proper description ok 531 - hasnt_language(language) should have the proper diagnostics ok 532 - hasnt_language(language, desc) should fail ok 533 - hasnt_language(language, desc) should have the proper description ok 534 - hasnt_language(language, desc) should have the proper diagnostics ok 535 - hasnt_language(nonexistent language) should pass ok 536 - hasnt_language(nonexistent language) should have the proper description ok 537 - hasnt_language(nonexistent language) should have the proper diagnostics ok 538 - hasnt_language(nonexistent language, desc) should pass ok 539 - hasnt_language(nonexistent language, desc) should have the proper description ok 540 - hasnt_language(nonexistent language, desc) should have the proper diagnostics ok 541 - language_is_trusted(language, desc) should pass ok 542 - language_is_trusted(language, desc) should have the proper description ok 543 - language_is_trusted(language, desc) should have the proper diagnostics ok 544 - language_is_trusted(language) should pass ok 545 - language_is_trusted(language) should have the proper description ok 546 - language_is_trusted(language) should have the proper diagnostics ok 547 - language_is_trusted(language, desc) fail should fail ok 548 - language_is_trusted(language, desc) fail should have the proper description ok 549 - language_is_trusted(language, desc) fail should have the proper diagnostics ok 550 - language_is_trusted(language, desc) non-existent should fail ok 551 - language_is_trusted(language, desc) non-existent should have the proper description ok 552 - language_is_trusted(language, desc) non-existent should have the proper diagnostics ok 553 - has_opclass( schema, name, desc ) should pass ok 554 - has_opclass( schema, name, desc ) should have the proper description ok 555 - has_opclass( schema, name, desc ) should have the proper diagnostics ok 556 - has_opclass( schema, name ) should pass ok 557 - has_opclass( schema, name ) should have the proper description ok 558 - has_opclass( schema, name ) should have the proper diagnostics ok 559 - has_opclass( name, desc ) should pass ok 560 - has_opclass( name, desc ) should have the proper description ok 561 - has_opclass( name, desc ) should have the proper diagnostics ok 562 - has_opclass( name ) should pass ok 563 - has_opclass( name ) should have the proper description ok 564 - has_opclass( name ) should have the proper diagnostics ok 565 - has_opclass( schema, name, desc ) fail should fail ok 566 - has_opclass( schema, name, desc ) fail should have the proper description ok 567 - has_opclass( schema, name, desc ) fail should have the proper diagnostics ok 568 - has_opclass( name, desc ) fail should fail ok 569 - has_opclass( name, desc ) fail should have the proper description ok 570 - has_opclass( name, desc ) fail should have the proper diagnostics ok 571 - hasnt_opclass( schema, name, desc ) should fail ok 572 - hasnt_opclass( schema, name, desc ) should have the proper description ok 573 - hasnt_opclass( schema, name, desc ) should have the proper diagnostics ok 574 - hasnt_opclass( schema, name ) should fail ok 575 - hasnt_opclass( schema, name ) should have the proper description ok 576 - hasnt_opclass( schema, name ) should have the proper diagnostics ok 577 - hasnt_opclass( name, desc ) should fail ok 578 - hasnt_opclass( name, desc ) should have the proper description ok 579 - hasnt_opclass( name, desc ) should have the proper diagnostics ok 580 - hasnt_opclass( name ) should fail ok 581 - hasnt_opclass( name ) should have the proper description ok 582 - hasnt_opclass( name ) should have the proper diagnostics ok 583 - hasnt_opclass( schema, name, desc ) fail should pass ok 584 - hasnt_opclass( schema, name, desc ) fail should have the proper description ok 585 - hasnt_opclass( schema, name, desc ) fail should have the proper diagnostics ok 586 - hasnt_opclass( name, desc ) fail should pass ok 587 - hasnt_opclass( name, desc ) fail should have the proper description ok 588 - hasnt_opclass( name, desc ) fail should have the proper diagnostics ok 589 - domain_type_is(schema, domain, schema, type, desc) should pass ok 590 - domain_type_is(schema, domain, schema, type, desc) should have the proper description ok 591 - domain_type_is(schema, domain, schema, type, desc) should have the proper diagnostics ok 592 - domain_type_is(schema, domain, schema, type) should pass ok 593 - domain_type_is(schema, domain, schema, type) should have the proper description ok 594 - domain_type_is(schema, domain, schema, type) should have the proper diagnostics ok 595 - domain_type_is(schema, domain, schema, type, desc) fail should fail ok 596 - domain_type_is(schema, domain, schema, type, desc) fail should have the proper description ok 597 - domain_type_is(schema, domain, schema, type, desc) fail should have the proper diagnostics ok 598 - domain_type_is(schema, nondomain, schema, type, desc) should fail ok 599 - domain_type_is(schema, nondomain, schema, type, desc) should have the proper description ok 600 - domain_type_is(schema, nondomain, schema, type, desc) should have the proper diagnostics ok 601 - domain_type_is(schema, type, schema, type, desc) fail should fail ok 602 - domain_type_is(schema, type, schema, type, desc) fail should have the proper description ok 603 - domain_type_is(schema, type, schema, type, desc) fail should have the proper diagnostics ok 604 - domain_type_is(schema, domain, type, desc) should pass ok 605 - domain_type_is(schema, domain, type, desc) should have the proper description ok 606 - domain_type_is(schema, domain, type, desc) should have the proper diagnostics ok 607 - domain_type_is(schema, domain, type) should pass ok 608 - domain_type_is(schema, domain, type) should have the proper description ok 609 - domain_type_is(schema, domain, type) should have the proper diagnostics ok 610 - domain_type_is(schema, domain, type, desc) fail should fail ok 611 - domain_type_is(schema, domain, type, desc) fail should have the proper description ok 612 - domain_type_is(schema, domain, type, desc) fail should have the proper diagnostics ok 613 - domain_type_is(schema, nondomain, type, desc) should fail ok 614 - domain_type_is(schema, nondomain, type, desc) should have the proper description ok 615 - domain_type_is(schema, nondomain, type, desc) should have the proper diagnostics ok 616 - domain_type_is(schema, type, type, desc) fail should fail ok 617 - domain_type_is(schema, type, type, desc) fail should have the proper description ok 618 - domain_type_is(schema, type, type, desc) fail should have the proper diagnostics ok 619 - domain_type_is(domain, type, desc) should pass ok 620 - domain_type_is(domain, type, desc) should have the proper description ok 621 - domain_type_is(domain, type, desc) should have the proper diagnostics ok 622 - domain_type_is(domain, type) should pass ok 623 - domain_type_is(domain, type) should have the proper description ok 624 - domain_type_is(domain, type) should have the proper diagnostics ok 625 - domain_type_is(domain, type, desc) fail should fail ok 626 - domain_type_is(domain, type, desc) fail should have the proper description ok 627 - domain_type_is(domain, type, desc) fail should have the proper diagnostics ok 628 - domain_type_is(nondomain, type, desc) should fail ok 629 - domain_type_is(nondomain, type, desc) should have the proper description ok 630 - domain_type_is(nondomain, type, desc) should have the proper diagnostics ok 631 - domain_type_is(type, type, desc) fail should fail ok 632 - domain_type_is(type, type, desc) fail should have the proper description ok 633 - domain_type_is(type, type, desc) fail should have the proper diagnostics ok 634 - domain_type_isnt(schema, domain, schema, type, desc) should pass ok 635 - domain_type_isnt(schema, domain, schema, type, desc) should have the proper description ok 636 - domain_type_isnt(schema, domain, schema, type, desc) should have the proper diagnostics ok 637 - domain_type_isnt(schema, domain, schema, type) should pass ok 638 - domain_type_isnt(schema, domain, schema, type) should have the proper description ok 639 - domain_type_isnt(schema, domain, schema, type) should have the proper diagnostics ok 640 - domain_type_isnt(schema, domain, schema, type, desc) fail should fail ok 641 - domain_type_isnt(schema, domain, schema, type, desc) fail should have the proper description ok 642 - domain_type_isnt(schema, domain, schema, type, desc) fail should have the proper diagnostics ok 643 - domain_type_isnt(schema, nondomain, schema, type, desc) should fail ok 644 - domain_type_isnt(schema, nondomain, schema, type, desc) should have the proper description ok 645 - domain_type_isnt(schema, nondomain, schema, type, desc) should have the proper diagnostics ok 646 - domain_type_isnt(schema, type, schema, type, desc) should fail ok 647 - domain_type_isnt(schema, type, schema, type, desc) should have the proper description ok 648 - domain_type_isnt(schema, type, schema, type, desc) should have the proper diagnostics ok 649 - domain_type_isnt(schema, domain, type, desc) should pass ok 650 - domain_type_isnt(schema, domain, type, desc) should have the proper description ok 651 - domain_type_isnt(schema, domain, type, desc) should have the proper diagnostics ok 652 - domain_type_isnt(schema, domain, type) should pass ok 653 - domain_type_isnt(schema, domain, type) should have the proper description ok 654 - domain_type_isnt(schema, domain, type) should have the proper diagnostics ok 655 - domain_type_isnt(schema, domain, type, desc) fail should fail ok 656 - domain_type_isnt(schema, domain, type, desc) fail should have the proper description ok 657 - domain_type_isnt(schema, domain, type, desc) fail should have the proper diagnostics ok 658 - domain_type_isnt(schema, nondomain, type, desc) should fail ok 659 - domain_type_isnt(schema, nondomain, type, desc) should have the proper description ok 660 - domain_type_isnt(schema, nondomain, type, desc) should have the proper diagnostics ok 661 - domain_type_isnt(schema, type, type, desc) should fail ok 662 - domain_type_isnt(schema, type, type, desc) should have the proper description ok 663 - domain_type_isnt(schema, type, type, desc) should have the proper diagnostics ok 664 - domain_type_isnt(domain, type, desc) should pass ok 665 - domain_type_isnt(domain, type, desc) should have the proper description ok 666 - domain_type_isnt(domain, type, desc) should have the proper diagnostics ok 667 - domain_type_isnt(domain, type) should pass ok 668 - domain_type_isnt(domain, type) should have the proper description ok 669 - domain_type_isnt(domain, type) should have the proper diagnostics ok 670 - domain_type_isnt(domain, type, desc) fail should fail ok 671 - domain_type_isnt(domain, type, desc) fail should have the proper description ok 672 - domain_type_isnt(domain, type, desc) fail should have the proper diagnostics ok 673 - domain_type_isnt(nondomain, type, desc) should fail ok 674 - domain_type_isnt(nondomain, type, desc) should have the proper description ok 675 - domain_type_isnt(nondomain, type, desc) should have the proper diagnostics ok 676 - domain_type_isnt(type, type, desc) should fail ok 677 - domain_type_isnt(type, type, desc) should have the proper description ok 678 - domain_type_isnt(type, type, desc) should have the proper diagnostics pgtap-0.90.0/test/expected/._index.out000644 000765 000024 00000000252 11666501762 020013 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/index.out000644 000765 000024 00000034657 11666501762 017616 0ustar00davidstaff000000 000000 \unset ECHO 1..225 ok 1 - has_index() single column should pass ok 2 - has_index() single column should have the proper description ok 3 - has_index() single column should have the proper diagnostics ok 4 - has_index() single column no desc should pass ok 5 - has_index() single column no desc should have the proper description ok 6 - has_index() single column no desc should have the proper diagnostics ok 7 - has_index() hash index should pass ok 8 - has_index() hash index should have the proper description ok 9 - has_index() hash index should have the proper diagnostics ok 10 - has_index() hash index no desc should pass ok 11 - has_index() hash index no desc should have the proper description ok 12 - has_index() hash index no desc should have the proper diagnostics ok 13 - has_index() multi-column should pass ok 14 - has_index() multi-column should have the proper description ok 15 - has_index() multi-column should have the proper diagnostics ok 16 - has_index() multi-column no desc should pass ok 17 - has_index() multi-column no desc should have the proper description ok 18 - has_index() multi-column no desc should have the proper diagnostics ok 19 - has_index() functional should pass ok 20 - has_index() functional should have the proper description ok 21 - has_index() functional should have the proper diagnostics ok 22 - has_index() no cols should pass ok 23 - has_index() no cols should have the proper description ok 24 - has_index() no cols should have the proper diagnostics ok 25 - has_index() hash index should pass ok 26 - has_index() hash index should have the proper description ok 27 - has_index() hash index should have the proper diagnostics ok 28 - has_index() no cols no desc should pass ok 29 - has_index() no cols no desc should have the proper description ok 30 - has_index() no cols no desc should have the proper diagnostics ok 31 - has_index() no cols hash index no desc should pass ok 32 - has_index() no cols hash index no desc should have the proper description ok 33 - has_index() no cols hash index no desc should have the proper diagnostics ok 34 - has_index() no schema single column should pass ok 35 - has_index() no schema single column should have the proper description ok 36 - has_index() no schema single column should have the proper diagnostics ok 37 - has_index() no schema single column no desc should pass ok 38 - has_index() no schema single column no desc should have the proper description ok 39 - has_index() no schema single column no desc should have the proper diagnostics ok 40 - has_index() no schema multi-column should pass ok 41 - has_index() no schema multi-column should have the proper description ok 42 - has_index() no schema multi-column should have the proper diagnostics ok 43 - has_index() no schema multi-column no desc should pass ok 44 - has_index() no schema multi-column no desc should have the proper description ok 45 - has_index() no schema multi-column no desc should have the proper diagnostics ok 46 - has_index() no schema functional should pass ok 47 - has_index() no schema functional should have the proper description ok 48 - has_index() no schema functional should have the proper diagnostics ok 49 - has_index() no schema functional no desc should pass ok 50 - has_index() no schema functional no desc should have the proper description ok 51 - has_index() no schema functional no desc should have the proper diagnostics ok 52 - has_index() no schema or cols should pass ok 53 - has_index() no schema or cols should have the proper description ok 54 - has_index() no schema or cols should have the proper diagnostics ok 55 - has_index() hash index no schema or cols should pass ok 56 - has_index() hash index no schema or cols should have the proper description ok 57 - has_index() hash index no schema or cols should have the proper diagnostics ok 58 - has_index() no schema or cols or desc should pass ok 59 - has_index() no schema or cols or desc should have the proper description ok 60 - has_index() no schema or cols or desc should have the proper diagnostics ok 61 - has_index() hash index no schema or cols or desc should pass ok 62 - has_index() hash index no schema or cols or desc should have the proper description ok 63 - has_index() hash index no schema or cols or desc should have the proper diagnostics ok 64 - has_index() non-existent should fail ok 65 - has_index() non-existent should have the proper description ok 66 - has_index() non-existent should have the proper diagnostics ok 67 - has_index() missing should fail ok 68 - has_index() missing should have the proper description ok 69 - has_index() missing should have the proper diagnostics ok 70 - has_index() invalid should fail ok 71 - has_index() invalid should have the proper description ok 72 - has_index() invalid should have the proper diagnostics ok 73 - has_index() missing column should fail ok 74 - has_index() missing column should have the proper description ok 75 - has_index() missing column should have the proper diagnostics ok 76 - has_index() missing no schema should fail ok 77 - has_index() missing no schema should have the proper description ok 78 - has_index() missing no schema should have the proper diagnostics ok 79 - has_index() invalid no schema should fail ok 80 - has_index() invalid no schema should have the proper description ok 81 - has_index() invalid no schema should have the proper diagnostics ok 82 - has_index() functional fail should fail ok 83 - has_index() functional fail should have the proper description ok 84 - has_index() functional fail should have the proper diagnostics ok 85 - has_index() functional fail no schema should fail ok 86 - has_index() functional fail no schema should have the proper description ok 87 - has_index() functional fail no schema should have the proper diagnostics ok 88 - hasnt_index(schema, table, index, desc) should fail ok 89 - hasnt_index(schema, table, index, desc) should have the proper description ok 90 - hasnt_index(schema, table, index, desc) should have the proper diagnostics ok 91 - hasnt_index(schema, table, index) should fail ok 92 - hasnt_index(schema, table, index) should have the proper description ok 93 - hasnt_index(schema, table, index) should have the proper diagnostics ok 94 - hasnt_index(schema, table, non-index, desc) should pass ok 95 - hasnt_index(schema, table, non-index, desc) should have the proper description ok 96 - hasnt_index(schema, table, non-index, desc) should have the proper diagnostics ok 97 - hasnt_index(schema, table, non-index) should pass ok 98 - hasnt_index(schema, table, non-index) should have the proper description ok 99 - hasnt_index(schema, table, non-index) should have the proper diagnostics ok 100 - hasnt_index(table, index, desc) should fail ok 101 - hasnt_index(table, index, desc) should have the proper description ok 102 - hasnt_index(table, index, desc) should have the proper diagnostics ok 103 - hasnt_index(table, index) should fail ok 104 - hasnt_index(table, index) should have the proper description ok 105 - hasnt_index(table, index) should have the proper diagnostics ok 106 - hasnt_index(table, non-index, desc) should pass ok 107 - hasnt_index(table, non-index, desc) should have the proper description ok 108 - hasnt_index(table, non-index, desc) should have the proper diagnostics ok 109 - hasnt_index(table, non-index) should pass ok 110 - hasnt_index(table, non-index) should have the proper description ok 111 - hasnt_index(table, non-index) should have the proper diagnostics ok 112 - index_is_unique() should pass ok 113 - index_is_unique() should have the proper description ok 114 - index_is_unique() should have the proper diagnostics ok 115 - index_is_unique() no desc should pass ok 116 - index_is_unique() no desc should have the proper description ok 117 - index_is_unique() no desc should have the proper diagnostics ok 118 - index_is_unique() no schema should pass ok 119 - index_is_unique() no schema should have the proper description ok 120 - index_is_unique() no schema should have the proper diagnostics ok 121 - index_is_unique() index only should pass ok 122 - index_is_unique() index only should have the proper description ok 123 - index_is_unique() index only should have the proper diagnostics ok 124 - index_is_unique() on pk should pass ok 125 - index_is_unique() on pk should have the proper description ok 126 - index_is_unique() on pk should have the proper diagnostics ok 127 - index_is_unique() on pk no desc should pass ok 128 - index_is_unique() on pk no desc should have the proper description ok 129 - index_is_unique() on pk no desc should have the proper diagnostics ok 130 - index_is_unique() on pk no schema should pass ok 131 - index_is_unique() on pk no schema should have the proper description ok 132 - index_is_unique() on pk no schema should have the proper diagnostics ok 133 - index_is_unique() on pk index only should pass ok 134 - index_is_unique() on pk index only should have the proper description ok 135 - index_is_unique() on pk index only should have the proper diagnostics ok 136 - index_is_unique() fail should fail ok 137 - index_is_unique() fail should have the proper description ok 138 - index_is_unique() fail should have the proper diagnostics ok 139 - index_is_unique() fail no desc should fail ok 140 - index_is_unique() fail no desc should have the proper description ok 141 - index_is_unique() fail no desc should have the proper diagnostics ok 142 - index_is_unique() fail no schema should fail ok 143 - index_is_unique() fail no schema should have the proper description ok 144 - index_is_unique() fail no schema should have the proper diagnostics ok 145 - index_is_unique() fail index only should fail ok 146 - index_is_unique() fail index only should have the proper description ok 147 - index_is_unique() fail index only should have the proper diagnostics ok 148 - index_is_unique() no such index should fail ok 149 - index_is_unique() no such index should have the proper description ok 150 - index_is_unique() no such index should have the proper diagnostics ok 151 - index_is_primary() should pass ok 152 - index_is_primary() should have the proper description ok 153 - index_is_primary() should have the proper diagnostics ok 154 - index_is_primary() no desc should pass ok 155 - index_is_primary() no desc should have the proper description ok 156 - index_is_primary() no desc should have the proper diagnostics ok 157 - index_is_primary() no schema should pass ok 158 - index_is_primary() no schema should have the proper description ok 159 - index_is_primary() no schema should have the proper diagnostics ok 160 - index_is_primary() index only should pass ok 161 - index_is_primary() index only should have the proper description ok 162 - index_is_primary() index only should have the proper diagnostics ok 163 - index_is_primary() fail should fail ok 164 - index_is_primary() fail should have the proper description ok 165 - index_is_primary() fail should have the proper diagnostics ok 166 - index_is_primary() fail no desc should fail ok 167 - index_is_primary() fail no desc should have the proper description ok 168 - index_is_primary() fail no desc should have the proper diagnostics ok 169 - index_is_primary() fail no schema should fail ok 170 - index_is_primary() fail no schema should have the proper description ok 171 - index_is_primary() fail no schema should have the proper diagnostics ok 172 - index_is_primary() fail index only should fail ok 173 - index_is_primary() fail index only should have the proper description ok 174 - index_is_primary() fail index only should have the proper diagnostics ok 175 - index_is_primary() no such index should fail ok 176 - index_is_primary() no such index should have the proper description ok 177 - index_is_primary() no such index should have the proper diagnostics ok 178 - is_clustered() fail should fail ok 179 - is_clustered() fail should have the proper description ok 180 - is_clustered() fail should have the proper diagnostics ok 181 - is_clustered() fail no desc should fail ok 182 - is_clustered() fail no desc should have the proper description ok 183 - is_clustered() fail no desc should have the proper diagnostics ok 184 - is_clustered() fail no schema should fail ok 185 - is_clustered() fail no schema should have the proper description ok 186 - is_clustered() fail no schema should have the proper diagnostics ok 187 - is_clustered() fail index only should fail ok 188 - is_clustered() fail index only should have the proper description ok 189 - is_clustered() fail index only should have the proper diagnostics ok 190 - is_clustered() should pass ok 191 - is_clustered() should have the proper description ok 192 - is_clustered() should have the proper diagnostics ok 193 - is_clustered() no desc should pass ok 194 - is_clustered() no desc should have the proper description ok 195 - is_clustered() no desc should have the proper diagnostics ok 196 - is_clustered() no schema should pass ok 197 - is_clustered() no schema should have the proper description ok 198 - is_clustered() no schema should have the proper diagnostics ok 199 - is_clustered() index only should pass ok 200 - is_clustered() index only should have the proper description ok 201 - is_clustered() index only should have the proper diagnostics ok 202 - index_is_type() should pass ok 203 - index_is_type() should have the proper description ok 204 - index_is_type() should have the proper diagnostics ok 205 - index_is_type() no desc should pass ok 206 - index_is_type() no desc should have the proper description ok 207 - index_is_type() no desc should have the proper diagnostics ok 208 - index_is_type() fail should fail ok 209 - index_is_type() fail should have the proper description ok 210 - index_is_type() fail should have the proper diagnostics ok 211 - index_is_type() no schema should pass ok 212 - index_is_type() no schema should have the proper description ok 213 - index_is_type() no schema should have the proper diagnostics ok 214 - index_is_type() no schema fail should fail ok 215 - index_is_type() no schema fail should have the proper description ok 216 - index_is_type() no schema fail should have the proper diagnostics ok 217 - index_is_type() no table should pass ok 218 - index_is_type() no table should have the proper description ok 219 - index_is_type() no table should have the proper diagnostics ok 220 - index_is_type() no table fail should fail ok 221 - index_is_type() no table fail should have the proper description ok 222 - index_is_type() no table fail should have the proper diagnostics ok 223 - index_is_type() hash should pass ok 224 - index_is_type() hash should have the proper description ok 225 - index_is_type() hash should have the proper diagnostics pgtap-0.90.0/test/expected/._istap.out000644 000765 000024 00000000252 11666501762 020024 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/istap.out000644 000765 000024 00000004450 11666501762 017613 0ustar00davidstaff000000 000000 \unset ECHO 1..47 ok 1 - is(1, 1) should pass ok 2 - is(1, 1) should have the proper description ok 3 - is(1, 1) should have the proper diagnostics ok 4 - is('x', 'x') should pass ok 5 - is('x', 'x') should have the proper description ok 6 - is('x', 'x') should have the proper diagnostics ok 7 - is(1.1, 1.10) should pass ok 8 - is(1.1, 1.10) should have the proper description ok 9 - is(1.1, 1.10) should have the proper diagnostics ok 10 - is(true, true) should pass ok 11 - is(true, true) should have the proper description ok 12 - is(true, true) should have the proper diagnostics ok 13 - is(false, false) should pass ok 14 - is(false, false) should have the proper description ok 15 - is(false, false) should have the proper diagnostics ok 16 - is(1, 1, desc) should pass ok 17 - is(1, 1, desc) should have the proper description ok 18 - is(1, 1, desc) should have the proper diagnostics ok 19 - is(1, 2) should fail ok 20 - is(1, 2) should have the proper description ok 21 - is(1, 2) should have the proper diagnostics ok 22 - isnt(1, 2) should pass ok 23 - isnt(1, 2) should have the proper description ok 24 - isnt(1, 2) should have the proper diagnostics ok 25 - isnt(1, 1) should fail ok 26 - isnt(1, 1) should have the proper description ok 27 - isnt(1, 1) should have the proper diagnostics ok 28 - is() should work with psql variables ok 29 - is(NULL, NULL) should pass ok 30 - is(NULL, NULL) should have the proper description ok 31 - is(NULL, NULL) should have the proper diagnostics ok 32 - is(NULL, foo) should fail ok 33 - is(NULL, foo) should have the proper description ok 34 - is(NULL, foo) should have the proper diagnostics ok 35 - is(foo, NULL) should fail ok 36 - is(foo, NULL) should have the proper description ok 37 - is(foo, NULL) should have the proper diagnostics ok 38 - with records! ok 39 - is(mumble, row) fail should fail ok 40 - is(mumble, row) fail should have the proper description ok 41 - is(mumble, row) fail should have the proper diagnostics ok 42 - is(mumble, row) fail with NULL should fail ok 43 - is(mumble, row) fail with NULL should have the proper description ok 44 - is(mumble, row) fail with NULL should have the proper diagnostics ok 45 - is(mumble, NULL) should fail ok 46 - is(mumble, NULL) should have the proper description ok 47 - is(mumble, NULL) should have the proper diagnostics pgtap-0.90.0/test/expected/._matching.out000644 000765 000024 00000000252 11666501762 020476 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/matching.out000644 000765 000024 00000002113 11666501762 020257 0ustar00davidstaff000000 000000 \unset ECHO 1..24 ok 1 - matches() should work ok 2 - matches() should work with a regex ok 3 - imatches() should work with a regex ok 4 - matches() fail should fail ok 5 - matches() fail should have the proper description ok 6 - matches() fail should have the proper diagnostics ok 7 - doesnt_match() should work ok 8 - doesnt_match() should work with a regex ok 9 - doesnt_imatch() should work with a regex ok 10 - doesnt_match() fail should fail ok 11 - doesnt_match() fail should have the proper description ok 12 - doesnt_match() fail should have the proper diagnostics ok 13 - alike() should work ok 14 - alike() should work with a regex ok 15 - ialike() should work with a regex ok 16 - alike() fail should fail ok 17 - alike() fail should have the proper description ok 18 - alike() fail should have the proper diagnostics ok 19 - unalike() should work ok 20 - unalike() should work with a regex ok 21 - iunalike() should work with a regex ok 22 - unalike() fail should fail ok 23 - unalike() fail should have the proper description ok 24 - unalike() fail should have the proper diagnostics pgtap-0.90.0/test/expected/._moretap.out000644 000765 000024 00000000252 11666501762 020353 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/moretap.out000644 000765 000024 00000003744 11666501762 020147 0ustar00davidstaff000000 000000 \unset ECHO 1..46 ok 1 - My pass() passed, w00t! ok 2 - Testing fail() ok 3 - We should get the proper output from fail() ok 4 - The output of finish() should reflect the test failure ok 5 - We should have one failure ok 6 - We should now have no failures ok 7 - diag() should work properly ok 8 - multiline diag() should work properly ok 9 - multiline diag() should work properly with existing comments ok 10 - diag(int) ok 11 - diag(numeric) ok 12 - diag(timestamptz) ok 13 - variadic text ok 14 - variadic int ok 15 - variadic unknown ok 16 - no_plan() should have stored a plan of 0 ok 17 - Set the plan to 4000 ok 18 - The output of finish() should reflect a high test plan ok 19 - Set the plan to 4 ok 20 - The output of finish() should reflect a low test plan ok 21 - Reset the plan ok 22 - plan() should have stored the test count ok 23 - ok(true) should pass ok 24 - ok(true) should have the proper description ok 25 - ok(true) should have the proper diagnostics ok 26 - ok(true, '') should pass ok 27 - ok(true, '') should have the proper description ok 28 - ok(true, '') should have the proper diagnostics ok 29 - ok(true, 'foo') should pass ok 30 - ok(true, 'foo') should have the proper description ok 31 - ok(true, 'foo') should have the proper diagnostics ok 32 - ok(false) should fail ok 33 - ok(false) should have the proper description ok 34 - ok(false) should have the proper diagnostics ok 35 - ok(false, '') should fail ok 36 - ok(false, '') should have the proper description ok 37 - ok(false, '') should have the proper diagnostics ok 38 - ok(false, 'foo') should fail ok 39 - ok(false, 'foo') should have the proper description ok 40 - ok(false, 'foo') should have the proper diagnostics ok 41 - ok(NULL, 'null') should fail ok 42 - ok(NULL, 'null') should have the proper description ok 43 - ok(NULL, 'null') should have the proper diagnostics ok 44 - multiline desc should pass ok 45 - multiline desc should have the proper description ok 46 - multiline desc should have the proper diagnostics pgtap-0.90.0/test/expected/._ownership.out000644 000765 000024 00000000252 11666501762 020722 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/ownership.out000644 000765 000024 00000001343 11666501762 020507 0ustar00davidstaff000000 000000 \unset ECHO 1..12 ok 1 - db_owner_is(db, user, desc) should pass ok 2 - db_owner_is(db, user, desc) should have the proper description ok 3 - db_owner_is(db, user, desc) should have the proper diagnostics ok 4 - db_owner_is(db, user) should pass ok 5 - db_owner_is(db, user) should have the proper description ok 6 - db_owner_is(db, user) should have the proper diagnostics ok 7 - db_owner_is(non-db, user) should fail ok 8 - db_owner_is(non-db, user) should have the proper description ok 9 - db_owner_is(non-db, user) should have the proper diagnostics ok 10 - db_owner_is(db, non-user) should fail ok 11 - db_owner_is(db, non-user) should have the proper description ok 12 - db_owner_is(db, non-user) should have the proper diagnostics pgtap-0.90.0/test/expected/._perform.out000644 000765 000024 00000000252 11666501762 020356 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/perform.out000644 000765 000024 00000002524 11666501762 020145 0ustar00davidstaff000000 000000 \unset ECHO 1..24 ok 1 - simple select should pass ok 2 - simple select should have the proper description ok 3 - simple select should have the proper diagnostics ok 4 - simple select no desc should pass ok 5 - simple select no desc should have the proper description ok 6 - simple select no desc should have the proper diagnostics ok 7 - simple select numeric should pass ok 8 - simple select numeric should have the proper description ok 9 - simple select numeric should have the proper diagnostics ok 10 - simple prepare should pass ok 11 - simple prepare should have the proper description ok 12 - simple prepare should have the proper diagnostics ok 13 - simple execute should pass ok 14 - simple execute should have the proper description ok 15 - simple execute should have the proper diagnostics ok 16 - simple select fail should fail ok 17 - simple select fail should have the proper description ok 18 - simple select fail should have the proper diagnostics ok 19 - simple select no desc fail should fail ok 20 - simple select no desc fail should have the proper description ok 21 - simple select no desc fail should have the proper diagnostics ok 22 - simple select no desc numeric fail should fail ok 23 - simple select no desc numeric fail should have the proper description ok 24 - simple select no desc numeric fail should have the proper diagnostics pgtap-0.90.0/test/expected/._pg73.out000644 000765 000024 00000000252 11666501762 017464 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/pg73.out000644 000765 000024 00000001270 11666501762 017250 0ustar00davidstaff000000 000000 \unset ECHO 1..39 ok 1 ok 2 - true ok 3 ok 4 - NOT false ok 5 ok 6 - three ok 7 ok 8 ok 9 ok 10 - 1=2 ok 11 - now()=now() ok 12 - '1 hour'::interval, '1 hour'::interval ok 13 ok 14 - now=now date ok 15 - now!=now+1 ok 16 - now()=now() timestamp ok 17 - now()=now() date ok 18 - TRUE=TRUE ok 19 - TRUE!=FALSE ok 20 - a=a char ok 21 - a!=b char ok 22 - a=a text ok 23 - a!=b text ok 24 - 3=3 int ok 25 - 3!=4 int ok 26 - 3=3 integer ok 27 - 3!=4 integer ok 28 - 3=3 int2 ok 29 - 3!=4 int2 ok 30 - 3=3 int4 ok 31 - 3!=4 int4 ok 32 - 3=3 int8 ok 33 - 3!=4 int8 ok 34 - 3.2=3.2 float ok 35 - 3.2!=4.5 float ok 36 - 3.2=3.2 float4 ok 37 - 3.2!=4.5 float4 ok 38 - 3.2=3.2 float8 ok 39 - 3.2!=4.5 float8 pgtap-0.90.0/test/expected/._pktap.out000644 000765 000024 00000000252 11666501762 020023 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/pktap.out000644 000765 000024 00000014160 11666501762 017611 0ustar00davidstaff000000 000000 \unset ECHO 1..84 ok 1 - has_pk( schema, table, description ) should pass ok 2 - has_pk( schema, table, description ) should have the proper description ok 3 - has_pk( schema, table, description ) should have the proper diagnostics ok 4 - has_pk( hideschema, hidetable, description ) should pass ok 5 - has_pk( hideschema, hidetable, description ) should have the proper description ok 6 - has_pk( hideschema, hidetable, description ) should have the proper diagnostics ok 7 - has_pk( table, description ) should pass ok 8 - has_pk( table, description ) should have the proper description ok 9 - has_pk( table, description ) should have the proper diagnostics ok 10 - has_pk( hidetable, description ) fail should fail ok 11 - has_pk( hidetable, description ) fail should have the proper description ok 12 - has_pk( hidetable, description ) fail should have the proper diagnostics ok 13 - has_pk( table ) should pass ok 14 - has_pk( table ) should have the proper description ok 15 - has_pk( table ) should have the proper diagnostics ok 16 - has_pk( schema, table, description ) fail should fail ok 17 - has_pk( schema, table, description ) fail should have the proper description ok 18 - has_pk( schema, table, description ) fail should have the proper diagnostics ok 19 - has_pk( table, description ) fail should fail ok 20 - has_pk( table, description ) fail should have the proper description ok 21 - has_pk( table, description ) fail should have the proper diagnostics ok 22 - hasnt_pk( schema, table, description ) should fail ok 23 - hasnt_pk( schema, table, description ) should have the proper description ok 24 - hasnt_pk( schema, table, description ) should have the proper diagnostics ok 25 - hasnt_pk( table, description ) should fail ok 26 - hasnt_pk( table, description ) should have the proper description ok 27 - hasnt_pk( table, description ) should have the proper diagnostics ok 28 - hasnt_pk( table ) should fail ok 29 - hasnt_pk( table ) should have the proper description ok 30 - hasnt_pk( table ) should have the proper diagnostics ok 31 - hasnt_pk( schema, table, description ) pass should pass ok 32 - hasnt_pk( schema, table, description ) pass should have the proper description ok 33 - hasnt_pk( schema, table, description ) pass should have the proper diagnostics ok 34 - hasnt_pk( table, description ) pass should pass ok 35 - hasnt_pk( table, description ) pass should have the proper description ok 36 - hasnt_pk( table, description ) pass should have the proper diagnostics ok 37 - col_is_pk( schema, table, column, description ) should pass ok 38 - col_is_pk( schema, table, column, description ) should have the proper description ok 39 - col_is_pk( schema, table, column, description ) should have the proper diagnostics ok 40 - col_is_pk( table, column, description ) should pass ok 41 - col_is_pk( table, column, description ) should have the proper description ok 42 - col_is_pk( table, column, description ) should have the proper diagnostics ok 43 - col_is_pk( table, column ) should pass ok 44 - col_is_pk( table, column ) should have the proper description ok 45 - col_is_pk( table, column ) should have the proper diagnostics ok 46 - col_is_pk( schema, table, column, description ) fail should fail ok 47 - col_is_pk( schema, table, column, description ) fail should have the proper description ok 48 - col_is_pk( schema, table, column, description ) fail should have the proper diagnostics ok 49 - col_is_pk( table, column, description ) fail should fail ok 50 - col_is_pk( table, column, description ) fail should have the proper description ok 51 - col_is_pk( table, column, description ) fail should have the proper diagnostics ok 52 - col_is_pk( schema, table, column[], description ) should pass ok 53 - col_is_pk( schema, table, column[], description ) should have the proper description ok 54 - col_is_pk( schema, table, column[], description ) should have the proper diagnostics ok 55 - col_is_pk( table, column[], description ) should pass ok 56 - col_is_pk( table, column[], description ) should have the proper description ok 57 - col_is_pk( table, column[], description ) should have the proper diagnostics ok 58 - col_is_pk( table, column[] ) should pass ok 59 - col_is_pk( table, column[] ) should have the proper description ok 60 - col_is_pk( table, column[] ) should have the proper diagnostics ok 61 - col_isnt_pk( schema, table, column, description ) should fail ok 62 - col_isnt_pk( schema, table, column, description ) should have the proper description ok 63 - col_isnt_pk( schema, table, column, description ) should have the proper diagnostics ok 64 - col_isnt_pk( table, column, description ) should fail ok 65 - col_isnt_pk( table, column, description ) should have the proper description ok 66 - col_isnt_pk( table, column, description ) should have the proper diagnostics ok 67 - col_isnt_pk( table, column ) should fail ok 68 - col_isnt_pk( table, column ) should have the proper description ok 69 - col_isnt_pk( table, column ) should have the proper diagnostics ok 70 - col_isnt_pk( schema, table, column, description ) pass should pass ok 71 - col_isnt_pk( schema, table, column, description ) pass should have the proper description ok 72 - col_isnt_pk( schema, table, column, description ) pass should have the proper diagnostics ok 73 - col_isnt_pk( table, column, description ) pass should pass ok 74 - col_isnt_pk( table, column, description ) pass should have the proper description ok 75 - col_isnt_pk( table, column, description ) pass should have the proper diagnostics ok 76 - col_isnt_pk( schema, table, column[], description ) should pass ok 77 - col_isnt_pk( schema, table, column[], description ) should have the proper description ok 78 - col_isnt_pk( schema, table, column[], description ) should have the proper diagnostics ok 79 - col_isnt_pk( table, column[], description ) should pass ok 80 - col_isnt_pk( table, column[], description ) should have the proper description ok 81 - col_isnt_pk( table, column[], description ) should have the proper diagnostics ok 82 - col_isnt_pk( table, column[] ) should pass ok 83 - col_isnt_pk( table, column[] ) should have the proper description ok 84 - col_isnt_pk( table, column[] ) should have the proper diagnostics pgtap-0.90.0/test/expected/._resultset.out000644 000765 000024 00000000252 11666501762 020736 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/resultset.out000644 000765 000024 00000104176 11666501762 020533 0ustar00davidstaff000000 000000 \unset ECHO 1..515 ok 1 - Should create temp table with simple query ok 2 - Table __foonames__ should exist ok 3 - Should create a temp table for a prepared statement ok 4 - Table __somenames__ should exist ok 5 - Should create a temp table for a prepared statement with space ok 6 - Table __somenames__ should exist ok 7 - Table __spacenames__ should exist ok 8 - set_eq(prepared, prepared, desc) should pass ok 9 - set_eq(prepared, prepared, desc) should have the proper description ok 10 - set_eq(prepared, prepared, desc) should have the proper diagnostics ok 11 - set_eq(prepared, prepared) should pass ok 12 - set_eq(prepared, prepared) should have the proper description ok 13 - set_eq(prepared, prepared) should have the proper diagnostics ok 14 - set_eq(execute, execute, desc) should pass ok 15 - set_eq(execute, execute, desc) should have the proper description ok 16 - set_eq(execute, execute, desc) should have the proper diagnostics ok 17 - set_eq(select, select) should pass ok 18 - set_eq(select, select) should have the proper description ok 19 - set_eq(select, select) should have the proper diagnostics ok 20 - set_eq(values, dupe values) should pass ok 21 - set_eq(values, dupe values) should have the proper description ok 22 - set_eq(values, dupe values) should have the proper diagnostics ok 23 - set_eq(prepared, select) fail extra should fail ok 24 - set_eq(prepared, select) fail extra should have the proper description ok 25 - set_eq(prepared, select) fail extra should have the proper diagnostics ok 26 - set_eq(prepared, select) fail extras should fail ok 27 - set_eq(prepared, select) fail extras should have the proper description ok 28 - set_eq(prepared, select) fail extras should have the proper diagnostics ok 29 - set_eq(select, prepared) fail missing should fail ok 30 - set_eq(select, prepared) fail missing should have the proper description ok 31 - set_eq(select, prepared) fail missing should have the proper diagnostics ok 32 - set_eq(select, prepared) fail missings should fail ok 33 - set_eq(select, prepared) fail missings should have the proper description ok 34 - set_eq(select, prepared) fail missings should have the proper diagnostics ok 35 - set_eq(select, select) fail extra & missing should fail ok 36 - set_eq(select, select) fail extra & missing should have the proper description ok 37 - set_eq(select, select) fail extra & missing should have the proper diagnostics ok 38 - set_eq(select, select) fail extras & missings should fail ok 39 - set_eq(select, select) fail extras & missings should have the proper description ok 40 - set_eq(select, select) fail extras & missings should have the proper diagnostics ok 41 - set_eq(values, values) fail mismatch should fail ok 42 - set_eq(values, values) fail mismatch should have the proper description ok 43 - set_eq(values, values) fail mismatch should have the proper diagnostics ok 44 - set_eq(values, values) fail column count should fail ok 45 - set_eq(values, values) fail column count should have the proper description ok 46 - set_eq(values, values) fail column count should have the proper diagnostics ok 47 - set_eq(sql, sql) fail type schema visibility should fail ok 48 - set_eq(sql, sql) fail type schema visibility should have the proper description ok 49 - set_eq(sql, sql) fail type schema visibility should have the proper diagnostics ok 50 - bag_eq(prepared, prepared, desc) should pass ok 51 - bag_eq(prepared, prepared, desc) should have the proper description ok 52 - bag_eq(prepared, prepared, desc) should have the proper diagnostics ok 53 - bag_eq(prepared, prepared) should pass ok 54 - bag_eq(prepared, prepared) should have the proper description ok 55 - bag_eq(prepared, prepared) should have the proper diagnostics ok 56 - bag_eq(execute, execute) should pass ok 57 - bag_eq(execute, execute) should have the proper description ok 58 - bag_eq(execute, execute) should have the proper diagnostics ok 59 - bag_eq(select, select) should pass ok 60 - bag_eq(select, select) should have the proper description ok 61 - bag_eq(select, select) should have the proper diagnostics ok 62 - bag_eq(dupe values, dupe values) should pass ok 63 - bag_eq(dupe values, dupe values) should have the proper description ok 64 - bag_eq(dupe values, dupe values) should have the proper diagnostics ok 65 - bag_eq(prepared, select) fail extra should fail ok 66 - bag_eq(prepared, select) fail extra should have the proper description ok 67 - bag_eq(prepared, select) fail extra should have the proper diagnostics ok 68 - bag_eq(prepared, select) fail extras should fail ok 69 - bag_eq(prepared, select) fail extras should have the proper description ok 70 - bag_eq(prepared, select) fail extras should have the proper diagnostics ok 71 - bag_eq(select, prepared) fail missing should fail ok 72 - bag_eq(select, prepared) fail missing should have the proper description ok 73 - bag_eq(select, prepared) fail missing should have the proper diagnostics ok 74 - bag_eq(select, prepared) fail missings should fail ok 75 - bag_eq(select, prepared) fail missings should have the proper description ok 76 - bag_eq(select, prepared) fail missings should have the proper diagnostics ok 77 - bag_eq(select, select) fail extra & missing should fail ok 78 - bag_eq(select, select) fail extra & missing should have the proper description ok 79 - bag_eq(select, select) fail extra & missing should have the proper diagnostics ok 80 - bag_eq(select, select) fail extras & missings should fail ok 81 - bag_eq(select, select) fail extras & missings should have the proper description ok 82 - bag_eq(select, select) fail extras & missings should have the proper diagnostics ok 83 - bag_eq(values, values) fail mismatch should fail ok 84 - bag_eq(values, values) fail mismatch should have the proper description ok 85 - bag_eq(values, values) fail mismatch should have the proper diagnostics ok 86 - bag_eq(values, values) fail column count should fail ok 87 - bag_eq(values, values) fail column count should have the proper description ok 88 - bag_eq(values, values) fail column count should have the proper diagnostics ok 89 - bag_eq(values, values) fail missing dupe should fail ok 90 - bag_eq(values, values) fail missing dupe should have the proper description ok 91 - bag_eq(values, values) fail missing dupe should have the proper diagnostics ok 92 - set_ne(prepared, select, desc) should pass ok 93 - set_ne(prepared, select, desc) should have the proper description ok 94 - set_ne(prepared, select, desc) should have the proper diagnostics ok 95 - set_ne(prepared, select) should pass ok 96 - set_ne(prepared, select) should have the proper description ok 97 - set_ne(prepared, select) should have the proper diagnostics ok 98 - set_ne(prepared, prepared) fail should fail ok 99 - set_ne(prepared, prepared) fail should have the proper description ok 100 - set_ne(prepared, prepared) fail should have the proper diagnostics ok 101 - set_ne fail with column mismatch should fail ok 102 - set_ne fail with column mismatch should have the proper description ok 103 - set_ne fail with column mismatch should have the proper diagnostics ok 104 - set_ne fail with different col counts should fail ok 105 - set_ne fail with different col counts should have the proper description ok 106 - set_ne fail with different col counts should have the proper diagnostics ok 107 - set_ne fail with dupe should fail ok 108 - set_ne fail with dupe should have the proper description ok 109 - set_ne fail with dupe should have the proper diagnostics ok 110 - bag_ne(prepared, select, desc) should pass ok 111 - bag_ne(prepared, select, desc) should have the proper description ok 112 - bag_ne(prepared, select, desc) should have the proper diagnostics ok 113 - bag_ne(prepared, select) should pass ok 114 - bag_ne(prepared, select) should have the proper description ok 115 - bag_ne(prepared, select) should have the proper diagnostics ok 116 - bag_ne(prepared, prepared) fail should fail ok 117 - bag_ne(prepared, prepared) fail should have the proper description ok 118 - bag_ne(prepared, prepared) fail should have the proper diagnostics ok 119 - bag_ne fail with column mismatch should fail ok 120 - bag_ne fail with column mismatch should have the proper description ok 121 - bag_ne fail with column mismatch should have the proper diagnostics ok 122 - set_ne pass with dupe should pass ok 123 - set_ne pass with dupe should have the proper description ok 124 - set_ne pass with dupe should have the proper diagnostics ok 125 - bag_ne fail with column mismatch should fail ok 126 - bag_ne fail with column mismatch should have the proper description ok 127 - bag_ne fail with column mismatch should have the proper diagnostics ok 128 - bag_ne fail with different col counts should fail ok 129 - bag_ne fail with different col counts should have the proper description ok 130 - bag_ne fail with different col counts should have the proper diagnostics ok 131 - results_eq(prepared, prepared, desc) should pass ok 132 - results_eq(prepared, prepared, desc) should have the proper description ok 133 - results_eq(prepared, prepared, desc) should have the proper diagnostics ok 134 - results_eq(prepared, prepared) should pass ok 135 - results_eq(prepared, prepared) should have the proper description ok 136 - results_eq(prepared, prepared) should have the proper diagnostics ok 137 - results_eq(execute, execute) should pass ok 138 - results_eq(execute, execute) should have the proper description ok 139 - results_eq(execute, execute) should have the proper diagnostics ok 140 - results_eq(select, select) should pass ok 141 - results_eq(select, select) should have the proper description ok 142 - results_eq(select, select) should have the proper diagnostics ok 143 - results_eq(dupe values, dupe values) should pass ok 144 - results_eq(dupe values, dupe values) should have the proper description ok 145 - results_eq(dupe values, dupe values) should have the proper diagnostics ok 146 - results_eq(values with null, values with null) should pass ok 147 - results_eq(values with null, values with null) should have the proper description ok 148 - results_eq(values with null, values with null) should have the proper diagnostics ok 149 - results_eq(nulls, nulls) should pass ok 150 - results_eq(nulls, nulls) should have the proper description ok 151 - results_eq(nulls, nulls) should have the proper diagnostics ok 152 - results_eq(nulls, nulls) fail should fail ok 153 - results_eq(nulls, nulls) fail should have the proper description ok 154 - results_eq(nulls, nulls) fail should have the proper diagnostics ok 155 - results_eq(prepared, select) fail should fail ok 156 - results_eq(prepared, select) fail should have the proper description ok 157 - results_eq(prepared, select) fail should have the proper diagnostics ok 158 - results_eq(select, prepared) fail missing last row should fail ok 159 - results_eq(select, prepared) fail missing last row should have the proper description ok 160 - results_eq(select, prepared) fail missing last row should have the proper diagnostics ok 161 - results_eq(prepared, select) fail missing first row should fail ok 162 - results_eq(prepared, select) fail missing first row should have the proper description ok 163 - results_eq(prepared, select) fail missing first row should have the proper diagnostics ok 164 - results_eq(values dupe, values) should fail ok 165 - results_eq(values dupe, values) should have the proper description ok 166 - results_eq(values dupe, values) should have the proper diagnostics ok 167 - results_eq(values null, values) should fail ok 168 - results_eq(values null, values) should have the proper description ok 169 - results_eq(values null, values) should have the proper diagnostics ok 170 - results_eq(values, values) mismatch should fail ok 171 - results_eq(values, values) mismatch should have the proper description ok 172 - results_eq(values, values) mismatch should have the proper diagnostics ok 173 - results_eq(values, values) subtle mismatch should fail ok 174 - results_eq(values, values) subtle mismatch should have the proper description ok 175 - results_eq(values, values) subtle mismatch should have the proper diagnostics ok 176 - results_eq(values, values) fail column count should fail ok 177 - results_eq(values, values) fail column count should have the proper description ok 178 - results_eq(values, values) fail column count should have the proper diagnostics ok 179 - results_eq(cursor, cursor) should pass ok 180 - results_eq(cursor, cursor) should have the proper description ok 181 - results_eq(cursor, cursor) should have the proper diagnostics ok 182 - results_eq(cursor, prepared) should pass ok 183 - results_eq(cursor, prepared) should have the proper description ok 184 - results_eq(cursor, prepared) should have the proper diagnostics ok 185 - results_eq(prepared, cursor) should pass ok 186 - results_eq(prepared, cursor) should have the proper description ok 187 - results_eq(prepared, cursor) should have the proper diagnostics ok 188 - results_eq(cursor, sql) should pass ok 189 - results_eq(cursor, sql) should have the proper description ok 190 - results_eq(cursor, sql) should have the proper diagnostics ok 191 - results_eq(sql, cursor) should pass ok 192 - results_eq(sql, cursor) should have the proper description ok 193 - results_eq(sql, cursor) should have the proper diagnostics ok 194 - set_has( prepared, prepared, description ) should pass ok 195 - set_has( prepared, prepared, description ) should have the proper description ok 196 - set_has( prepared, prepared, description ) should have the proper diagnostics ok 197 - set_has( prepared, subprepared ) should pass ok 198 - set_has( prepared, subprepared ) should have the proper description ok 199 - set_has( prepared, subprepared ) should have the proper diagnostics ok 200 - set_has( execute, execute ) should pass ok 201 - set_has( execute, execute ) should have the proper description ok 202 - set_has( execute, execute ) should have the proper diagnostics ok 203 - set_has( select, select ) should pass ok 204 - set_has( select, select ) should have the proper description ok 205 - set_has( select, select ) should have the proper diagnostics ok 206 - set_has( prepared, empty ) should pass ok 207 - set_has( prepared, empty ) should have the proper description ok 208 - set_has( prepared, empty ) should have the proper diagnostics ok 209 - set_has( prepared, dupes ) should pass ok 210 - set_has( prepared, dupes ) should have the proper description ok 211 - set_has( prepared, dupes ) should have the proper diagnostics ok 212 - set_has( dupes, values ) should pass ok 213 - set_has( dupes, values ) should have the proper description ok 214 - set_has( dupes, values ) should have the proper diagnostics ok 215 - set_has( missing1, expect ) should fail ok 216 - set_has( missing1, expect ) should have the proper description ok 217 - set_has( missing1, expect ) should have the proper diagnostics ok 218 - set_has(missing2, expect ) should fail ok 219 - set_has(missing2, expect ) should have the proper description ok 220 - set_has(missing2, expect ) should have the proper diagnostics ok 221 - set_has((int,text), (text,int)) should fail ok 222 - set_has((int,text), (text,int)) should have the proper description ok 223 - set_has((int,text), (text,int)) should have the proper diagnostics ok 224 - set_has((int), (text,int)) should fail ok 225 - set_has((int), (text,int)) should have the proper description ok 226 - set_has((int), (text,int)) should have the proper diagnostics ok 227 - bag_has( prepared, prepared, description ) should pass ok 228 - bag_has( prepared, prepared, description ) should have the proper description ok 229 - bag_has( prepared, prepared, description ) should have the proper diagnostics ok 230 - bag_has( prepared, subprepared ) should pass ok 231 - bag_has( prepared, subprepared ) should have the proper description ok 232 - bag_has( prepared, subprepared ) should have the proper diagnostics ok 233 - bag_has( execute, execute ) should pass ok 234 - bag_has( execute, execute ) should have the proper description ok 235 - bag_has( execute, execute ) should have the proper diagnostics ok 236 - bag_has( select, select ) should pass ok 237 - bag_has( select, select ) should have the proper description ok 238 - bag_has( select, select ) should have the proper diagnostics ok 239 - bag_has( prepared, empty ) should pass ok 240 - bag_has( prepared, empty ) should have the proper description ok 241 - bag_has( prepared, empty ) should have the proper diagnostics ok 242 - bag_has( prepared, dupes ) should fail ok 243 - bag_has( prepared, dupes ) should have the proper description ok 244 - bag_has( prepared, dupes ) should have the proper diagnostics ok 245 - bag_has( dupes, values ) should pass ok 246 - bag_has( dupes, values ) should have the proper description ok 247 - bag_has( dupes, values ) should have the proper diagnostics ok 248 - bag_has( missing1, expect ) should fail ok 249 - bag_has( missing1, expect ) should have the proper description ok 250 - bag_has( missing1, expect ) should have the proper diagnostics ok 251 - bag_has(missing2, expect ) should fail ok 252 - bag_has(missing2, expect ) should have the proper description ok 253 - bag_has(missing2, expect ) should have the proper diagnostics ok 254 - bag_has((int,text), (text,int)) should fail ok 255 - bag_has((int,text), (text,int)) should have the proper description ok 256 - bag_has((int,text), (text,int)) should have the proper diagnostics ok 257 - bag_has((int), (text,int)) should fail ok 258 - bag_has((int), (text,int)) should have the proper description ok 259 - bag_has((int), (text,int)) should have the proper diagnostics ok 260 - set_hasnt( prepared, prepared, description ) should pass ok 261 - set_hasnt( prepared, prepared, description ) should have the proper description ok 262 - set_hasnt( prepared, prepared, description ) should have the proper diagnostics ok 263 - set_hasnt( prepared, prepared, description ) should pass ok 264 - set_hasnt( prepared, prepared, description ) should have the proper description ok 265 - set_hasnt( prepared, prepared, description ) should have the proper diagnostics ok 266 - set_hasnt( execute, execute ) should pass ok 267 - set_hasnt( execute, execute ) should have the proper description ok 268 - set_hasnt( execute, execute ) should have the proper diagnostics ok 269 - set_hasnt( select, select ) should pass ok 270 - set_hasnt( select, select ) should have the proper description ok 271 - set_hasnt( select, select ) should have the proper diagnostics ok 272 - set_hasnt( prepared, empty ) should pass ok 273 - set_hasnt( prepared, empty ) should have the proper description ok 274 - set_hasnt( prepared, empty ) should have the proper diagnostics ok 275 - set_hasnt( prepared, dupes ) should pass ok 276 - set_hasnt( prepared, dupes ) should have the proper description ok 277 - set_hasnt( prepared, dupes ) should have the proper diagnostics ok 278 - set_hasnt( prepared, value ) should fail ok 279 - set_hasnt( prepared, value ) should have the proper description ok 280 - set_hasnt( prepared, value ) should have the proper diagnostics ok 281 - set_hasnt( prepared, values ) should fail ok 282 - set_hasnt( prepared, values ) should have the proper description ok 283 - set_hasnt( prepared, values ) should have the proper diagnostics ok 284 - set_hasnt((int,text), (text,int)) should fail ok 285 - set_hasnt((int,text), (text,int)) should have the proper description ok 286 - set_hasnt((int,text), (text,int)) should have the proper diagnostics ok 287 - set_hasnt((int), (text,int)) should fail ok 288 - set_hasnt((int), (text,int)) should have the proper description ok 289 - set_hasnt((int), (text,int)) should have the proper diagnostics ok 290 - bag_hasnt( prepared, prepared, description ) should pass ok 291 - bag_hasnt( prepared, prepared, description ) should have the proper description ok 292 - bag_hasnt( prepared, prepared, description ) should have the proper diagnostics ok 293 - bag_hasnt( prepared, prepared, description ) should pass ok 294 - bag_hasnt( prepared, prepared, description ) should have the proper description ok 295 - bag_hasnt( prepared, prepared, description ) should have the proper diagnostics ok 296 - bag_hasnt( execute, execute ) should pass ok 297 - bag_hasnt( execute, execute ) should have the proper description ok 298 - bag_hasnt( execute, execute ) should have the proper diagnostics ok 299 - bag_hasnt( select, select ) should pass ok 300 - bag_hasnt( select, select ) should have the proper description ok 301 - bag_hasnt( select, select ) should have the proper diagnostics ok 302 - bag_hasnt( prepared, empty ) should pass ok 303 - bag_hasnt( prepared, empty ) should have the proper description ok 304 - bag_hasnt( prepared, empty ) should have the proper diagnostics ok 305 - bag_hasnt( prepared, value ) should fail ok 306 - bag_hasnt( prepared, value ) should have the proper description ok 307 - bag_hasnt( prepared, value ) should have the proper diagnostics ok 308 - bag_hasnt( prepared, values ) should fail ok 309 - bag_hasnt( prepared, values ) should have the proper description ok 310 - bag_hasnt( prepared, values ) should have the proper diagnostics ok 311 - bag_hasnt((int,text), (text,int)) should fail ok 312 - bag_hasnt((int,text), (text,int)) should have the proper description ok 313 - bag_hasnt((int,text), (text,int)) should have the proper diagnostics ok 314 - bag_hasnt((int), (text,int)) should fail ok 315 - bag_hasnt((int), (text,int)) should have the proper description ok 316 - bag_hasnt((int), (text,int)) should have the proper diagnostics ok 317 - bag_hasnt( dupes, dupes ) should fail ok 318 - bag_hasnt( dupes, dupes ) should have the proper description ok 319 - bag_hasnt( dupes, dupes ) should have the proper diagnostics ok 320 - bag_hasnt( value, dupes ) should fail ok 321 - bag_hasnt( value, dupes ) should have the proper description ok 322 - bag_hasnt( value, dupes ) should have the proper diagnostics ok 323 - set_eq(sql, array, desc) should pass ok 324 - set_eq(sql, array, desc) should have the proper description ok 325 - set_eq(sql, array, desc) should have the proper diagnostics ok 326 - set_eq(sql, array) should pass ok 327 - set_eq(sql, array) should have the proper description ok 328 - set_eq(sql, array) should have the proper diagnostics ok 329 - set_eq(sql, dupe array) should pass ok 330 - set_eq(sql, dupe array) should have the proper description ok 331 - set_eq(sql, dupe array) should have the proper diagnostics ok 332 - set_eq(sql, array) extra record should fail ok 333 - set_eq(sql, array) extra record should have the proper description ok 334 - set_eq(sql, array) extra record should have the proper diagnostics ok 335 - set_eq(sql, array) missing record should fail ok 336 - set_eq(sql, array) missing record should have the proper description ok 337 - set_eq(sql, array) missing record should have the proper diagnostics ok 338 - set_eq(sql, array) incompatible types should fail ok 339 - set_eq(sql, array) incompatible types should have the proper description ok 340 - set_eq(sql, array) incompatible types should have the proper diagnostics ok 341 - set_eq(sql, array) incompatible types should fail ok 342 - set_eq(sql, array) incompatible types should have the proper description ok 343 - set_eq(sql, array) incompatible types should have the proper diagnostics ok 344 - bag_eq(sql, array, desc) should pass ok 345 - bag_eq(sql, array, desc) should have the proper description ok 346 - bag_eq(sql, array, desc) should have the proper diagnostics ok 347 - bag_eq(sql, array) should pass ok 348 - bag_eq(sql, array) should have the proper description ok 349 - bag_eq(sql, array) should have the proper diagnostics ok 350 - bag_eq(sql, dupe array) fail should fail ok 351 - bag_eq(sql, dupe array) fail should have the proper description ok 352 - bag_eq(sql, dupe array) fail should have the proper diagnostics ok 353 - bag_eq(sql, array) extra record should fail ok 354 - bag_eq(sql, array) extra record should have the proper description ok 355 - bag_eq(sql, array) extra record should have the proper diagnostics ok 356 - bag_eq(sql, array) missing record should fail ok 357 - bag_eq(sql, array) missing record should have the proper description ok 358 - bag_eq(sql, array) missing record should have the proper diagnostics ok 359 - bag_eq(sql, array) incompatible types should fail ok 360 - bag_eq(sql, array) incompatible types should have the proper description ok 361 - bag_eq(sql, array) incompatible types should have the proper diagnostics ok 362 - bag_eq(sql, array) incompatible types should fail ok 363 - bag_eq(sql, array) incompatible types should have the proper description ok 364 - bag_eq(sql, array) incompatible types should have the proper diagnostics ok 365 - set_ne(sql, array, desc) should pass ok 366 - set_ne(sql, array, desc) should have the proper description ok 367 - set_ne(sql, array, desc) should have the proper diagnostics ok 368 - set_ne(sql, array) should pass ok 369 - set_ne(sql, array) should have the proper description ok 370 - set_ne(sql, array) should have the proper diagnostics ok 371 - set_ne(sql, array) fail should fail ok 372 - set_ne(sql, array) fail should have the proper description ok 373 - set_ne(sql, array) fail should have the proper diagnostics ok 374 - set_ne(sql, dupes array) fail should fail ok 375 - set_ne(sql, dupes array) fail should have the proper description ok 376 - set_ne(sql, dupes array) fail should have the proper diagnostics ok 377 - set_ne(sql, array) incompatible types should fail ok 378 - set_ne(sql, array) incompatible types should have the proper description ok 379 - set_ne(sql, array) incompatible types should have the proper diagnostics ok 380 - set_ne(sql, array) incompatible types should fail ok 381 - set_ne(sql, array) incompatible types should have the proper description ok 382 - set_ne(sql, array) incompatible types should have the proper diagnostics ok 383 - bag_ne(sql, array, desc) should pass ok 384 - bag_ne(sql, array, desc) should have the proper description ok 385 - bag_ne(sql, array, desc) should have the proper diagnostics ok 386 - bag_ne(sql, array) should pass ok 387 - bag_ne(sql, array) should have the proper description ok 388 - bag_ne(sql, array) should have the proper diagnostics ok 389 - bag_ne(sql, array) fail should fail ok 390 - bag_ne(sql, array) fail should have the proper description ok 391 - bag_ne(sql, array) fail should have the proper diagnostics ok 392 - bag_ne(sql, dupes array) should pass ok 393 - bag_ne(sql, dupes array) should have the proper description ok 394 - bag_ne(sql, dupes array) should have the proper diagnostics ok 395 - bag_ne(sql, array) incompatible types should fail ok 396 - bag_ne(sql, array) incompatible types should have the proper description ok 397 - bag_ne(sql, array) incompatible types should have the proper diagnostics ok 398 - bag_ne(sql, array) incompatible types should fail ok 399 - bag_ne(sql, array) incompatible types should have the proper description ok 400 - bag_ne(sql, array) incompatible types should have the proper diagnostics ok 401 - results_eq(prepared, array, desc) should pass ok 402 - results_eq(prepared, array, desc) should have the proper description ok 403 - results_eq(prepared, array, desc) should have the proper diagnostics ok 404 - results_eq(prepared, array) should pass ok 405 - results_eq(prepared, array) should have the proper description ok 406 - results_eq(prepared, array) should have the proper diagnostics ok 407 - results_eq(sql, array, desc) should pass ok 408 - results_eq(sql, array, desc) should have the proper description ok 409 - results_eq(sql, array, desc) should have the proper diagnostics ok 410 - results_eq(sql, array, desc) should pass ok 411 - results_eq(sql, array, desc) should have the proper description ok 412 - results_eq(sql, array, desc) should have the proper diagnostics ok 413 - results_eq(prepared, array) extra record should fail ok 414 - results_eq(prepared, array) extra record should have the proper description ok 415 - results_eq(prepared, array) extra record should have the proper diagnostics ok 416 - results_eq(select, array) missing record should fail ok 417 - results_eq(select, array) missing record should have the proper description ok 418 - results_eq(select, array) missing record should have the proper diagnostics ok 419 - results_ne(prepared, prepared, desc) should pass ok 420 - results_ne(prepared, prepared, desc) should have the proper description ok 421 - results_ne(prepared, prepared, desc) should have the proper diagnostics ok 422 - results_ne(prepared, prepared) should pass ok 423 - results_ne(prepared, prepared) should have the proper description ok 424 - results_ne(prepared, prepared) should have the proper diagnostics ok 425 - results_ne(execute, execute) should pass ok 426 - results_ne(execute, execute) should have the proper description ok 427 - results_ne(execute, execute) should have the proper diagnostics ok 428 - results_ne(select, select) should pass ok 429 - results_ne(select, select) should have the proper description ok 430 - results_ne(select, select) should have the proper diagnostics ok 431 - results_ne(dupe values, dupe values) should pass ok 432 - results_ne(dupe values, dupe values) should have the proper description ok 433 - results_ne(dupe values, dupe values) should have the proper diagnostics ok 434 - results_ne(values with null, values with null) should pass ok 435 - results_ne(values with null, values with null) should have the proper description ok 436 - results_ne(values with null, values with null) should have the proper diagnostics ok 437 - results_ne(nulls, nulls) should pass ok 438 - results_ne(nulls, nulls) should have the proper description ok 439 - results_ne(nulls, nulls) should have the proper diagnostics ok 440 - results_ne(prepared, select) fail should fail ok 441 - results_ne(prepared, select) fail should have the proper description ok 442 - results_ne(prepared, select) fail should have the proper diagnostics ok 443 - results_ne(select, prepared) missing last row should pass ok 444 - results_ne(select, prepared) missing last row should have the proper description ok 445 - results_ne(select, prepared) missing last row should have the proper diagnostics ok 446 - results_ne(prepared, select) missing first row should pass ok 447 - results_ne(prepared, select) missing first row should have the proper description ok 448 - results_ne(prepared, select) missing first row should have the proper diagnostics ok 449 - results_ne(values dupe, values) should pass ok 450 - results_ne(values dupe, values) should have the proper description ok 451 - results_ne(values dupe, values) should have the proper diagnostics ok 452 - results_ne(values null, values) should pass ok 453 - results_ne(values null, values) should have the proper description ok 454 - results_ne(values null, values) should have the proper diagnostics ok 455 - results_ne(values, values) mismatch should fail ok 456 - results_ne(values, values) mismatch should have the proper description ok 457 - results_ne(values, values) mismatch should have the proper diagnostics ok 458 - results_ne(values, values) subtle mismatch should fail ok 459 - results_ne(values, values) subtle mismatch should have the proper description ok 460 - results_ne(values, values) subtle mismatch should have the proper diagnostics ok 461 - results_ne(values, values) fail column count should fail ok 462 - results_ne(values, values) fail column count should have the proper description ok 463 - results_ne(values, values) fail column count should have the proper diagnostics ok 464 - results_ne(cursor, cursor) should fail ok 465 - results_ne(cursor, cursor) should have the proper description ok 466 - results_ne(cursor, cursor) should have the proper diagnostics ok 467 - results_ne(cursor, prepared) should fail ok 468 - results_ne(cursor, prepared) should have the proper description ok 469 - results_ne(cursor, prepared) should have the proper diagnostics ok 470 - results_ne(prepared, cursor) should fail ok 471 - results_ne(prepared, cursor) should have the proper description ok 472 - results_ne(prepared, cursor) should have the proper diagnostics ok 473 - results_ne(cursor, sql) should pass ok 474 - results_ne(cursor, sql) should have the proper description ok 475 - results_ne(cursor, sql) should have the proper diagnostics ok 476 - results_ne(sql, cursor) should fail ok 477 - results_ne(sql, cursor) should have the proper description ok 478 - results_ne(sql, cursor) should have the proper diagnostics ok 479 - is_empty(sql, desc) should pass ok 480 - is_empty(sql, desc) should have the proper description ok 481 - is_empty(sql, desc) should have the proper diagnostics ok 482 - is_empty(sql) should pass ok 483 - is_empty(sql) should have the proper description ok 484 - is_empty(sql) should have the proper diagnostics ok 485 - is_empty(prepared, desc) should pass ok 486 - is_empty(prepared, desc) should have the proper description ok 487 - is_empty(prepared, desc) should have the proper diagnostics ok 488 - is_empty(prepared) should pass ok 489 - is_empty(prepared) should have the proper description ok 490 - is_empty(prepared) should have the proper diagnostics ok 491 - is_empty(prepared, desc) fail should fail ok 492 - is_empty(prepared, desc) fail should have the proper description ok 493 - is_empty(prepared, desc) fail should have the proper diagnostics ok 494 - is_empty(prepared) fail should fail ok 495 - is_empty(prepared) fail should have the proper description ok 496 - is_empty(prepared) fail should have the proper diagnostics ok 497 - row_eq(prepared, record, desc) should pass ok 498 - row_eq(prepared, record, desc) should have the proper description ok 499 - row_eq(prepared, record, desc) should have the proper diagnostics ok 500 - row_eq(sql, record, desc) should pass ok 501 - row_eq(sql, record, desc) should have the proper description ok 502 - row_eq(sql, record, desc) should have the proper diagnostics ok 503 - row_eq(prepared, record, desc) should pass ok 504 - row_eq(prepared, record, desc) should have the proper description ok 505 - row_eq(prepared, record, desc) should have the proper diagnostics ok 506 - row_eq(prepared, record, desc) should fail ok 507 - row_eq(prepared, record, desc) should have the proper description ok 508 - row_eq(prepared, record, desc) should have the proper diagnostics ok 509 - row_eq(prepared, sometype, desc) should pass ok 510 - row_eq(prepared, sometype, desc) should have the proper description ok 511 - row_eq(prepared, sometype, desc) should have the proper diagnostics ok 512 - row_eq(sqlrow, sometype, desc) should pass ok 513 - row_eq(sqlrow, sometype, desc) should have the proper description ok 514 - row_eq(sqlrow, sometype, desc) should have the proper diagnostics ok 515 - threw 0A000 pgtap-0.90.0/test/expected/._roletap.out000644 000765 000024 00000000252 11666501762 020352 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/roletap.out000644 000765 000024 00000004720 11666501762 020141 0ustar00davidstaff000000 000000 \unset ECHO 1..39 ok 1 - has_role(current role) should pass ok 2 - has_role(current role) should have the proper description ok 3 - has_role(current role) should have the proper diagnostics ok 4 - has_role(current role, desc) should pass ok 5 - has_role(current role, desc) should have the proper description ok 6 - has_role(current role, desc) should have the proper diagnostics ok 7 - has_role(nonexistent role) should fail ok 8 - has_role(nonexistent role) should have the proper description ok 9 - has_role(nonexistent role) should have the proper diagnostics ok 10 - has_role(nonexistent role, desc) should fail ok 11 - has_role(nonexistent role, desc) should have the proper description ok 12 - has_role(nonexistent role, desc) should have the proper diagnostics ok 13 - hasnt_role(current role) should fail ok 14 - hasnt_role(current role) should have the proper description ok 15 - hasnt_role(current role) should have the proper diagnostics ok 16 - hasnt_role(current role, desc) should fail ok 17 - hasnt_role(current role, desc) should have the proper description ok 18 - hasnt_role(current role, desc) should have the proper diagnostics ok 19 - hasnt_role(nonexistent role) should pass ok 20 - hasnt_role(nonexistent role) should have the proper description ok 21 - hasnt_role(nonexistent role) should have the proper diagnostics ok 22 - hasnt_role(nonexistent role, desc) should pass ok 23 - hasnt_role(nonexistent role, desc) should have the proper description ok 24 - hasnt_role(nonexistent role, desc) should have the proper diagnostics ok 25 - roles_are(roles, desc) should pass ok 26 - roles_are(roles, desc) should have the proper description ok 27 - roles_are(roles, desc) should have the proper diagnostics ok 28 - roles_are(roles) should pass ok 29 - roles_are(roles) should have the proper description ok 30 - roles_are(roles) should have the proper diagnostics ok 31 - roles_are(roles, desc) missing should fail ok 32 - roles_are(roles, desc) missing should have the proper description ok 33 - roles_are(roles, desc) missing should have the proper diagnostics ok 34 - roles_are(roles, desc) extras should fail ok 35 - roles_are(roles, desc) extras should have the proper description ok 36 - roles_are(roles, desc) extras should have the proper diagnostics ok 37 - roles_are(roles, desc) missing and extras should fail ok 38 - roles_are(roles, desc) missing and extras should have the proper description ok 39 - roles_are(roles, desc) missing and extras should have the proper diagnostics pgtap-0.90.0/test/expected/._ruletap.out000644 000765 000024 00000000252 11666501762 020360 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/ruletap.out000644 000765 000024 00000023315 11666501762 020150 0ustar00davidstaff000000 000000 \unset ECHO 1..132 ok 1 - has_rule(schema, table, rule, desc) should pass ok 2 - has_rule(schema, table, rule, desc) should have the proper description ok 3 - has_rule(schema, table, rule, desc) should have the proper diagnostics ok 4 - has_rule(schema, table, rule) should pass ok 5 - has_rule(schema, table, rule) should have the proper description ok 6 - has_rule(schema, table, rule) should have the proper diagnostics ok 7 - has_rule(schema, table, rule, desc) fail should fail ok 8 - has_rule(schema, table, rule, desc) fail should have the proper description ok 9 - has_rule(schema, table, rule, desc) fail should have the proper diagnostics ok 10 - has_rule(table, rule, desc) should pass ok 11 - has_rule(table, rule, desc) should have the proper description ok 12 - has_rule(table, rule, desc) should have the proper diagnostics ok 13 - has_rule(table, rule) should pass ok 14 - has_rule(table, rule) should have the proper description ok 15 - has_rule(table, rule) should have the proper diagnostics ok 16 - has_rule(table, rule, desc) fail should fail ok 17 - has_rule(table, rule, desc) fail should have the proper description ok 18 - has_rule(table, rule, desc) fail should have the proper diagnostics ok 19 - hasnt_rule(schema, table, rule, desc) should fail ok 20 - hasnt_rule(schema, table, rule, desc) should have the proper description ok 21 - hasnt_rule(schema, table, rule, desc) should have the proper diagnostics ok 22 - hasnt_rule(schema, table, rule) should fail ok 23 - hasnt_rule(schema, table, rule) should have the proper description ok 24 - hasnt_rule(schema, table, rule) should have the proper diagnostics ok 25 - hasnt_rule(schema, table, rule, desc) fail should pass ok 26 - hasnt_rule(schema, table, rule, desc) fail should have the proper description ok 27 - hasnt_rule(schema, table, rule, desc) fail should have the proper diagnostics ok 28 - hasnt_rule(table, rule, desc) should fail ok 29 - hasnt_rule(table, rule, desc) should have the proper description ok 30 - hasnt_rule(table, rule, desc) should have the proper diagnostics ok 31 - hasnt_rule(table, rule) should fail ok 32 - hasnt_rule(table, rule) should have the proper description ok 33 - hasnt_rule(table, rule) should have the proper diagnostics ok 34 - hasnt_rule(table, rule, desc) fail should pass ok 35 - hasnt_rule(table, rule, desc) fail should have the proper description ok 36 - hasnt_rule(table, rule, desc) fail should have the proper diagnostics ok 37 - rule_is_instead(schema, table, rule, desc) should pass ok 38 - rule_is_instead(schema, table, rule, desc) should have the proper description ok 39 - rule_is_instead(schema, table, rule, desc) should have the proper diagnostics ok 40 - rule_is_instead(schema, table, rule) should pass ok 41 - rule_is_instead(schema, table, rule) should have the proper description ok 42 - rule_is_instead(schema, table, rule) should have the proper diagnostics ok 43 - rule_is_instead(schema, table, nothing rule, desc) should fail ok 44 - rule_is_instead(schema, table, nothing rule, desc) should have the proper description ok 45 - rule_is_instead(schema, table, nothing rule, desc) should have the proper diagnostics ok 46 - rule_is_instead(schema, table, also rule, desc) should fail ok 47 - rule_is_instead(schema, table, also rule, desc) should have the proper description ok 48 - rule_is_instead(schema, table, also rule, desc) should have the proper diagnostics ok 49 - rule_is_instead(table, rule, desc) should pass ok 50 - rule_is_instead(table, rule, desc) should have the proper description ok 51 - rule_is_instead(table, rule, desc) should have the proper diagnostics ok 52 - rule_is_instead(table, rule) should pass ok 53 - rule_is_instead(table, rule) should have the proper description ok 54 - rule_is_instead(table, rule) should have the proper diagnostics ok 55 - rule_is_instead(table, nothing rule, desc) should fail ok 56 - rule_is_instead(table, nothing rule, desc) should have the proper description ok 57 - rule_is_instead(table, nothing rule, desc) should have the proper diagnostics ok 58 - rule_is_instead(table, also rule, desc) should fail ok 59 - rule_is_instead(table, also rule, desc) should have the proper description ok 60 - rule_is_instead(table, also rule, desc) should have the proper diagnostics ok 61 - rule_is_instead(schema, table, non-existent rule, desc) should fail ok 62 - rule_is_instead(schema, table, non-existent rule, desc) should have the proper description ok 63 - rule_is_instead(schema, table, non-existent rule, desc) should have the proper diagnostics ok 64 - rule_is_instead(table, non-existent rule, desc) should fail ok 65 - rule_is_instead(table, non-existent rule, desc) should have the proper description ok 66 - rule_is_instead(table, non-existent rule, desc) should have the proper diagnostics ok 67 - rule_is_on(schema, table, rule, insert, desc) should pass ok 68 - rule_is_on(schema, table, rule, insert, desc) should have the proper description ok 69 - rule_is_on(schema, table, rule, insert, desc) should have the proper diagnostics ok 70 - rule_is_on(schema, table, rule, update, desc) should pass ok 71 - rule_is_on(schema, table, rule, update, desc) should have the proper description ok 72 - rule_is_on(schema, table, rule, update, desc) should have the proper diagnostics ok 73 - rule_is_on(schema, table, rule, SELECT, desc) should pass ok 74 - rule_is_on(schema, table, rule, SELECT, desc) should have the proper description ok 75 - rule_is_on(schema, table, rule, SELECT, desc) should have the proper diagnostics ok 76 - rule_is_on(schema, table, rule, delete, desc) should pass ok 77 - rule_is_on(schema, table, rule, delete, desc) should have the proper description ok 78 - rule_is_on(schema, table, rule, delete, desc) should have the proper diagnostics ok 79 - rule_is_on(schema, table, dupe rule, insert, desc) should pass ok 80 - rule_is_on(schema, table, dupe rule, insert, desc) should have the proper description ok 81 - rule_is_on(schema, table, dupe rule, insert, desc) should have the proper diagnostics ok 82 - rule_is_on(schema, table, rule, INSERT, desc) should pass ok 83 - rule_is_on(schema, table, rule, INSERT, desc) should have the proper description ok 84 - rule_is_on(schema, table, rule, INSERT, desc) should have the proper diagnostics ok 85 - rule_is_on(schema, table, rule, i, desc) should pass ok 86 - rule_is_on(schema, table, rule, i, desc) should have the proper description ok 87 - rule_is_on(schema, table, rule, i, desc) should have the proper diagnostics ok 88 - rule_is_on(schema, table, rule, indigo, desc) should pass ok 89 - rule_is_on(schema, table, rule, indigo, desc) should have the proper description ok 90 - rule_is_on(schema, table, rule, indigo, desc) should have the proper diagnostics ok 91 - rule_is_on(schema, table, rule, i, desc) should pass ok 92 - rule_is_on(schema, table, rule, i, desc) should have the proper description ok 93 - rule_is_on(schema, table, rule, i, desc) should have the proper diagnostics ok 94 - rule_is_on(schema, table, rule, u, desc) fail should fail ok 95 - rule_is_on(schema, table, rule, u, desc) fail should have the proper description ok 96 - rule_is_on(schema, table, rule, u, desc) fail should have the proper diagnostics ok 97 - rule_is_on(schema, table, invalid rule, u, desc) should fail ok 98 - rule_is_on(schema, table, invalid rule, u, desc) should have the proper description ok 99 - rule_is_on(schema, table, invalid rule, u, desc) should have the proper diagnostics ok 100 - rule_is_on(table, rule, insert, desc) should pass ok 101 - rule_is_on(table, rule, insert, desc) should have the proper description ok 102 - rule_is_on(table, rule, insert, desc) should have the proper diagnostics ok 103 - rule_is_on(table, rule, update, desc) should pass ok 104 - rule_is_on(table, rule, update, desc) should have the proper description ok 105 - rule_is_on(table, rule, update, desc) should have the proper diagnostics ok 106 - rule_is_on(table, rule, SELECT, desc) should pass ok 107 - rule_is_on(table, rule, SELECT, desc) should have the proper description ok 108 - rule_is_on(table, rule, SELECT, desc) should have the proper diagnostics ok 109 - rule_is_on(table, rule, delete, desc) should pass ok 110 - rule_is_on(table, rule, delete, desc) should have the proper description ok 111 - rule_is_on(table, rule, delete, desc) should have the proper diagnostics ok 112 - rule_is_on(table, dupe rule, insert, desc) should pass ok 113 - rule_is_on(table, dupe rule, insert, desc) should have the proper description ok 114 - rule_is_on(table, dupe rule, insert, desc) should have the proper diagnostics ok 115 - rule_is_on(table, rule, INSERT, desc) should pass ok 116 - rule_is_on(table, rule, INSERT, desc) should have the proper description ok 117 - rule_is_on(table, rule, INSERT, desc) should have the proper diagnostics ok 118 - rule_is_on(table, rule, i, desc) should pass ok 119 - rule_is_on(table, rule, i, desc) should have the proper description ok 120 - rule_is_on(table, rule, i, desc) should have the proper diagnostics ok 121 - rule_is_on(table, rule, indigo, desc) should pass ok 122 - rule_is_on(table, rule, indigo, desc) should have the proper description ok 123 - rule_is_on(table, rule, indigo, desc) should have the proper diagnostics ok 124 - rule_is_on(table, rule, i, desc) should pass ok 125 - rule_is_on(table, rule, i, desc) should have the proper description ok 126 - rule_is_on(table, rule, i, desc) should have the proper diagnostics ok 127 - rule_is_on(table, rule, u, desc) fail should fail ok 128 - rule_is_on(table, rule, u, desc) fail should have the proper description ok 129 - rule_is_on(table, rule, u, desc) fail should have the proper diagnostics ok 130 - rule_is_on(table, invalid rule, u, desc) should fail ok 131 - rule_is_on(table, invalid rule, u, desc) should have the proper description ok 132 - rule_is_on(table, invalid rule, u, desc) should have the proper diagnostics pgtap-0.90.0/test/expected/._runtests.out000644 000765 000024 00000000252 11666501762 020573 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/runtests.out000644 000765 000024 00000001566 11666501762 020367 0ustar00davidstaff000000 000000 \unset ECHO ok 1 - starting up ok 2 - starting up some more # whatever."test ident"() ok 3 - setup ok 4 - Should be nothing in the test table ok 5 - setup more ok 6 - ident ok 7 - ident 2 ok 8 - teardown ok 9 - teardown more # whatever.testplpgsql() ok 10 - setup ok 11 - Should be nothing in the test table ok 12 - setup more ok 13 - plpgsql simple ok 14 - plpgsql simple 2 ok 15 - Should be a 1 in the test table ok 16 - teardown ok 17 - teardown more # whatever.testthis() ok 18 - setup ok 19 - Should be nothing in the test table ok 20 - setup more ok 21 - simple pass ok 22 - another simple pass ok 23 - teardown ok 24 - teardown more # whatever.testz() ok 25 - setup ok 26 - Should be nothing in the test table ok 27 - setup more ok 28 - Late test should find nothing in the test table ok 29 - teardown ok 30 - teardown more ok 31 - shutting down ok 32 - shutting down more 1..32 pgtap-0.90.0/test/expected/._throwtap.out000644 000765 000024 00000000252 11666501762 020554 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/throwtap.out000644 000765 000024 00000012334 11666501762 020343 0ustar00davidstaff000000 000000 \unset ECHO 1..84 ok 1 - four-argument form should pass ok 2 - four-argument form should have the proper description ok 3 - four-argument form should have the proper diagnostics ok 4 - three-argument errcode should pass ok 5 - three-argument errcode should have the proper description ok 6 - three-argument errcode should have the proper diagnostics ok 7 - two-argument errcode should pass ok 8 - two-argument errcode should have the proper description ok 9 - three argument errmsg should pass ok 10 - three argument errmsg should have the proper description ok 11 - three argument errmsg should have the proper diagnostics ok 12 - two-argument errmsg should pass ok 13 - two-argument errmsg should have the proper description ok 14 - two-argument errmsg should have the proper diagnostics ok 15 - single-argument form should pass ok 16 - single-argument form should have the proper description ok 17 - single-argument form should have the proper diagnostics ok 18 - prepared statement & errcode should pass ok 19 - prepared statement & errcode should have the proper description ok 20 - execute & errcode should pass ok 21 - execute & errcode should have the proper description ok 22 - invalid errcode should fail ok 23 - invalid errcode should have the proper description ok 24 - invalid errcode should have the proper diagnostics ok 25 - throws_ok(1/0, NULL) should work ok 26 - throws_ok diagnostics should fail ok 27 - throws_ok diagnostics should have the proper description ok 28 - throws_ok diagnostics should have the proper diagnostics ok 29 - lives_ok() should work ok 30 - lives_ok(prepared) should pass ok 31 - lives_ok(prepared) should have the proper description ok 32 - lives_ok(execute) should pass ok 33 - lives_ok(execute) should have the proper description ok 34 - lives_ok failure diagnostics should fail ok 35 - lives_ok failure diagnostics should have the proper description ok 36 - lives_ok failure diagnostics should have the proper diagnostics ok 37 - throws_like(sql, pattern, desc) should pass ok 38 - throws_like(sql, pattern, desc) should have the proper description ok 39 - throws_like(sql, pattern, desc) should have the proper diagnostics ok 40 - throws_like(sql, pattern) should pass ok 41 - throws_like(sql, pattern) should have the proper description ok 42 - throws_like(sql, pattern) should have the proper diagnostics ok 43 - throws_like(sql, pattern, desc) fail should fail ok 44 - throws_like(sql, pattern, desc) fail should have the proper description ok 45 - throws_like(sql, pattern, desc) fail should have the proper diagnostics ok 46 - throws_like(valid sql, pattern, desc) should fail ok 47 - throws_like(valid sql, pattern, desc) should have the proper description ok 48 - throws_like(valid sql, pattern, desc) should have the proper diagnostics ok 49 - throws_ilike(sql, pattern, desc) should pass ok 50 - throws_ilike(sql, pattern, desc) should have the proper description ok 51 - throws_ilike(sql, pattern, desc) should have the proper diagnostics ok 52 - throws_ilike(sql, pattern) should pass ok 53 - throws_ilike(sql, pattern) should have the proper description ok 54 - throws_ilike(sql, pattern) should have the proper diagnostics ok 55 - throws_ilike(sql, pattern, desc) fail should fail ok 56 - throws_ilike(sql, pattern, desc) fail should have the proper description ok 57 - throws_ilike(sql, pattern, desc) fail should have the proper diagnostics ok 58 - throws_ilike(valid sql, pattern, desc) should fail ok 59 - throws_ilike(valid sql, pattern, desc) should have the proper description ok 60 - throws_ilike(valid sql, pattern, desc) should have the proper diagnostics ok 61 - throws_matching(sql, regex, desc) should pass ok 62 - throws_matching(sql, regex, desc) should have the proper description ok 63 - throws_matching(sql, regex, desc) should have the proper diagnostics ok 64 - throws_matching(sql, regex, desc) should pass ok 65 - throws_matching(sql, regex, desc) should have the proper description ok 66 - throws_matching(sql, regex, desc) should have the proper diagnostics ok 67 - throws_matching(sql, regex, desc) should fail ok 68 - throws_matching(sql, regex, desc) should have the proper description ok 69 - throws_matching(sql, regex, desc) should have the proper diagnostics ok 70 - throws_matching(valid sql, regex, desc) should fail ok 71 - throws_matching(valid sql, regex, desc) should have the proper description ok 72 - throws_matching(valid sql, regex, desc) should have the proper diagnostics ok 73 - throws_imatching(sql, regex, desc) should pass ok 74 - throws_imatching(sql, regex, desc) should have the proper description ok 75 - throws_imatching(sql, regex, desc) should have the proper diagnostics ok 76 - throws_imatching(sql, regex, desc) should pass ok 77 - throws_imatching(sql, regex, desc) should have the proper description ok 78 - throws_imatching(sql, regex, desc) should have the proper diagnostics ok 79 - throws_imatching(sql, regex, desc) should fail ok 80 - throws_imatching(sql, regex, desc) should have the proper description ok 81 - throws_imatching(sql, regex, desc) should have the proper diagnostics ok 82 - throws_imatching(valid sql, regex, desc) should fail ok 83 - throws_imatching(valid sql, regex, desc) should have the proper description ok 84 - throws_imatching(valid sql, regex, desc) should have the proper diagnostics pgtap-0.90.0/test/expected/._todotap.out000644 000765 000024 00000000252 11666501762 020356 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/todotap.out000644 000765 000024 00000002464 11666501762 020150 0ustar00davidstaff000000 000000 \unset ECHO 1..36 ok 1 - todo fail ok 2 - todo pass ok 3 - TODO tests should display properly ok 4 - todo fail ok 5 - Single default todo test should display properly ok 6 - todo fail ok 7 - todo pass ok 8 - TODO tests should display properly ok 9 - simple skip should pass ok 10 - simple skip should have the proper description ok 11 - simple skip should have the proper diagnostics ok 12 - skip with num should pass ok 13 - skip with num should have the proper description ok 14 - skip with num should have the proper diagnostics ok 15 - Skip multiple ok 16 - Skip multiple ok 17 - Skip multiple ok 18 - We should get the proper output for multiple skips ok 19 - inverted skip should pass ok 20 - inverted skip should have the proper description ok 21 - inverted skip should have the proper diagnostics ok 22 - num only should pass ok 23 - num only should have the proper description ok 24 - num only should have the proper diagnostics ok 25 - todo fail ok 26 - todo fail ok 27 - todo fail ok 28 - Nested todos should work properly ok 29 - todo fail ok 30 - todo fail ok 31 - todo fail ok 32 - todo_start() and todo_end() should work properly with in_todo() ok 33 - todo fail ok 34 - todo pass ok 35 - Should be able to revers the arguments to todo() ok 36 - Should get an exception when todo_end() is called without todo_start() pgtap-0.90.0/test/expected/._trigger.out000644 000765 000024 00000000252 11666501762 020347 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/trigger.out000644 000765 000024 00000013705 11666501762 020141 0ustar00davidstaff000000 000000 \unset ECHO 1..84 ok 1 - has_trigger(schema, table, trigger, desc) should pass ok 2 - has_trigger(schema, table, trigger, desc) should have the proper description ok 3 - has_trigger(schema, table, trigger, desc) should have the proper diagnostics ok 4 - has_trigger(schema, table, trigger) should pass ok 5 - has_trigger(schema, table, trigger) should have the proper description ok 6 - has_trigger(schema, table, trigger) should have the proper diagnostics ok 7 - has_trigger(table, trigger, desc) should pass ok 8 - has_trigger(table, trigger, desc) should have the proper description ok 9 - has_trigger(table, trigger, desc) should have the proper diagnostics ok 10 - has_trigger(table, trigger) should pass ok 11 - has_trigger(table, trigger) should have the proper description ok 12 - has_trigger(table, trigger) should have the proper diagnostics ok 13 - has_trigger(schema, table, nonexistent, desc) should fail ok 14 - has_trigger(schema, table, nonexistent, desc) should have the proper description ok 15 - has_trigger(schema, table, nonexistent, desc) should have the proper diagnostics ok 16 - has_trigger(table, nonexistent) no schema fail should fail ok 17 - has_trigger(table, nonexistent) no schema fail should have the proper description ok 18 - has_trigger(table, nonexistent) no schema fail should have the proper diagnostics ok 19 - hasnt_trigger(schema, table, trigger, desc) should fail ok 20 - hasnt_trigger(schema, table, trigger, desc) should have the proper description ok 21 - hasnt_trigger(schema, table, trigger, desc) should have the proper diagnostics ok 22 - hasnt_trigger(schema, table, trigger) should fail ok 23 - hasnt_trigger(schema, table, trigger) should have the proper description ok 24 - hasnt_trigger(schema, table, trigger) should have the proper diagnostics ok 25 - hasnt_trigger(table, trigger, desc) should fail ok 26 - hasnt_trigger(table, trigger, desc) should have the proper description ok 27 - hasnt_trigger(table, trigger, desc) should have the proper diagnostics ok 28 - hasnt_trigger(table, trigger) should fail ok 29 - hasnt_trigger(table, trigger) should have the proper description ok 30 - hasnt_trigger(table, trigger) should have the proper diagnostics ok 31 - hasnt_trigger(schema, table, nonexistent, desc) should pass ok 32 - hasnt_trigger(schema, table, nonexistent, desc) should have the proper description ok 33 - hasnt_trigger(schema, table, nonexistent, desc) should have the proper diagnostics ok 34 - hasnt_trigger(table, nonexistent) no schema fail should pass ok 35 - hasnt_trigger(table, nonexistent) no schema fail should have the proper description ok 36 - hasnt_trigger(table, nonexistent) no schema fail should have the proper diagnostics ok 37 - trigger_is() should pass ok 38 - trigger_is() should have the proper description ok 39 - trigger_is() should have the proper diagnostics ok 40 - trigger_is() no desc should pass ok 41 - trigger_is() no desc should have the proper description ok 42 - trigger_is() no desc should have the proper diagnostics ok 43 - trigger_is() no schema should pass ok 44 - trigger_is() no schema should have the proper description ok 45 - trigger_is() no schema should have the proper diagnostics ok 46 - trigger_is() no schema or desc should pass ok 47 - trigger_is() no schema or desc should have the proper description ok 48 - trigger_is() no schema or desc should have the proper diagnostics ok 49 - trigger_is() fail should fail ok 50 - trigger_is() fail should have the proper description ok 51 - trigger_is() fail should have the proper diagnostics ok 52 - trigger_is() no schema fail should fail ok 53 - trigger_is() no schema fail should have the proper description ok 54 - trigger_is() no schema fail should have the proper diagnostics ok 55 - triggers_are(schema, table, triggers, desc) should pass ok 56 - triggers_are(schema, table, triggers, desc) should have the proper description ok 57 - triggers_are(schema, table, triggers, desc) should have the proper diagnostics ok 58 - triggers_are(schema, table, triggers) should pass ok 59 - triggers_are(schema, table, triggers) should have the proper description ok 60 - triggers_are(schema, table, triggers) should have the proper diagnostics ok 61 - triggers_are(schema, table, triggers) + extra should fail ok 62 - triggers_are(schema, table, triggers) + extra should have the proper description ok 63 - triggers_are(schema, table, triggers) + extra should have the proper diagnostics ok 64 - triggers_are(schema, table, triggers) + missing should fail ok 65 - triggers_are(schema, table, triggers) + missing should have the proper description ok 66 - triggers_are(schema, table, triggers) + missing should have the proper diagnostics ok 67 - triggers_are(schema, table, triggers) + extra & missing should fail ok 68 - triggers_are(schema, table, triggers) + extra & missing should have the proper description ok 69 - triggers_are(schema, table, triggers) + extra & missing should have the proper diagnostics ok 70 - triggers_are(table, triggers, desc) should pass ok 71 - triggers_are(table, triggers, desc) should have the proper description ok 72 - triggers_are(table, triggers, desc) should have the proper diagnostics ok 73 - triggers_are(table, triggers) should pass ok 74 - triggers_are(table, triggers) should have the proper description ok 75 - triggers_are(table, triggers) should have the proper diagnostics ok 76 - triggers_are(table, triggers) + extra should fail ok 77 - triggers_are(table, triggers) + extra should have the proper description ok 78 - triggers_are(table, triggers) + extra should have the proper diagnostics ok 79 - triggers_are(table, triggers) + missing should fail ok 80 - triggers_are(table, triggers) + missing should have the proper description ok 81 - triggers_are(table, triggers) + missing should have the proper diagnostics ok 82 - triggers_are(table, triggers) + extra & missing should fail ok 83 - triggers_are(table, triggers) + extra & missing should have the proper description ok 84 - triggers_are(table, triggers) + extra & missing should have the proper diagnostics pgtap-0.90.0/test/expected/._unique.out000644 000765 000024 00000000252 11666501762 020212 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/unique.out000644 000765 000024 00000007217 11666501762 020005 0ustar00davidstaff000000 000000 \unset ECHO 1..48 ok 1 - has_unique( schema, table, description ) should pass ok 2 - has_unique( schema, table, description ) should have the proper description ok 3 - has_unique( schema, table, description ) should have the proper diagnostics ok 4 - has_unique( table, description ) should pass ok 5 - has_unique( table, description ) should have the proper description ok 6 - has_unique( table, description ) should have the proper diagnostics ok 7 - has_unique( table ) should pass ok 8 - has_unique( table ) should have the proper description ok 9 - has_unique( table ) should have the proper diagnostics ok 10 - has_unique( schema, table, description ) fail should fail ok 11 - has_unique( schema, table, description ) fail should have the proper description ok 12 - has_unique( schema, table, description ) fail should have the proper diagnostics ok 13 - has_unique( table, description ) fail should fail ok 14 - has_unique( table, description ) fail should have the proper description ok 15 - has_unique( table, description ) fail should have the proper diagnostics ok 16 - col_is_unique( schema, table, column, description ) should pass ok 17 - col_is_unique( schema, table, column, description ) should have the proper description ok 18 - col_is_unique( schema, table, column, description ) should have the proper diagnostics ok 19 - col_is_unique( schema, table, columns, description ) should pass ok 20 - col_is_unique( schema, table, columns, description ) should have the proper description ok 21 - col_is_unique( schema, table, columns, description ) should have the proper diagnostics ok 22 - col_is_unique( table, column, description ) should pass ok 23 - col_is_unique( table, column, description ) should have the proper description ok 24 - col_is_unique( table, column, description ) should have the proper diagnostics ok 25 - col_is_unique( table, columns, description ) should pass ok 26 - col_is_unique( table, columns, description ) should have the proper description ok 27 - col_is_unique( table, columns, description ) should have the proper diagnostics ok 28 - col_is_unique( table, column ) should pass ok 29 - col_is_unique( table, column ) should have the proper description ok 30 - col_is_unique( table, column ) should have the proper diagnostics ok 31 - col_is_unique( table, columns ) should pass ok 32 - col_is_unique( table, columns ) should have the proper description ok 33 - col_is_unique( table, columns ) should have the proper diagnostics ok 34 - col_is_unique( schema, table, column, description ) fail should fail ok 35 - col_is_unique( schema, table, column, description ) fail should have the proper description ok 36 - col_is_unique( schema, table, column, description ) fail should have the proper diagnostics ok 37 - col_is_unique( table, column, description ) fail should fail ok 38 - col_is_unique( table, column, description ) fail should have the proper description ok 39 - col_is_unique( table, column, description ) fail should have the proper diagnostics ok 40 - col_is_unique( schema, table, column[], description ) should pass ok 41 - col_is_unique( schema, table, column[], description ) should have the proper description ok 42 - col_is_unique( schema, table, column[], description ) should have the proper diagnostics ok 43 - col_is_unique( table, column[], description ) should pass ok 44 - col_is_unique( table, column[], description ) should have the proper description ok 45 - col_is_unique( table, column[], description ) should have the proper diagnostics ok 46 - col_is_unique( table, column[] ) should pass ok 47 - col_is_unique( table, column[] ) should have the proper description ok 48 - col_is_unique( table, column[] ) should have the proper diagnostics pgtap-0.90.0/test/expected/._usergroup.out000644 000765 000024 00000000252 11666501762 020737 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/usergroup.out000644 000765 000024 00000012121 11666501762 020520 0ustar00davidstaff000000 000000 \unset ECHO 1..78 ok 1 - has_user(current user) should pass ok 2 - has_user(current user) should have the proper description ok 3 - has_user(current user) should have the proper diagnostics ok 4 - has_user(current user, desc) should pass ok 5 - has_user(current user, desc) should have the proper description ok 6 - has_user(current user, desc) should have the proper diagnostics ok 7 - has_user(nonexistent user) should fail ok 8 - has_user(nonexistent user) should have the proper description ok 9 - has_user(nonexistent user) should have the proper diagnostics ok 10 - has_user(nonexistent user, desc) should fail ok 11 - has_user(nonexistent user, desc) should have the proper description ok 12 - has_user(nonexistent user, desc) should have the proper diagnostics ok 13 - hasnt_user(current user) should fail ok 14 - hasnt_user(current user) should have the proper description ok 15 - hasnt_user(current user) should have the proper diagnostics ok 16 - hasnt_user(current user, desc) should fail ok 17 - hasnt_user(current user, desc) should have the proper description ok 18 - hasnt_user(current user, desc) should have the proper diagnostics ok 19 - hasnt_user(nonexistent user) should pass ok 20 - hasnt_user(nonexistent user) should have the proper description ok 21 - hasnt_user(nonexistent user) should have the proper diagnostics ok 22 - hasnt_user(nonexistent user, desc) should pass ok 23 - hasnt_user(nonexistent user, desc) should have the proper description ok 24 - hasnt_user(nonexistent user, desc) should have the proper diagnostics ok 25 - is_superuser(nonexistent user, desc) should fail ok 26 - is_superuser(nonexistent user, desc) should have the proper description ok 27 - is_superuser(nonexistent user, desc) should have the proper diagnostics ok 28 - is_superuser(nonexistent user) should fail ok 29 - is_superuser(nonexistent user) should have the proper description ok 30 - is_superuser(nonexistent user) should have the proper diagnostics ok 31 - isnt_superuser(nonexistent user, desc) should fail ok 32 - isnt_superuser(nonexistent user, desc) should have the proper description ok 33 - isnt_superuser(nonexistent user, desc) should have the proper diagnostics ok 34 - isnt_superuser(nonexistent user) should fail ok 35 - isnt_superuser(nonexistent user) should have the proper description ok 36 - isnt_superuser(nonexistent user) should have the proper diagnostics ok 37 - is_superuser( current user ) should pass ok 38 - is_superuser( current user ) should have the proper description ok 39 - is_superuser( current user ) should have the proper diagnostics ok 40 - is_superuser( current user, desc ) should pass ok 41 - is_superuser( current user, desc ) should have the proper description ok 42 - is_superuser( current user, desc ) should have the proper diagnostics ok 43 - has_group(group) should pass ok 44 - has_group(group) should have the proper description ok 45 - has_group(group) should have the proper diagnostics ok 46 - has_group(group, desc) should pass ok 47 - has_group(group, desc) should have the proper description ok 48 - has_group(group, desc) should have the proper diagnostics ok 49 - has_group(nonexistent group) should fail ok 50 - has_group(nonexistent group) should have the proper description ok 51 - has_group(nonexistent group) should have the proper diagnostics ok 52 - has_group(nonexistent group, desc) should fail ok 53 - has_group(nonexistent group, desc) should have the proper description ok 54 - has_group(nonexistent group, desc) should have the proper diagnostics ok 55 - hasnt_group(group) should fail ok 56 - hasnt_group(group) should have the proper description ok 57 - hasnt_group(group) should have the proper diagnostics ok 58 - hasnt_group(group, desc) should fail ok 59 - hasnt_group(group, desc) should have the proper description ok 60 - hasnt_group(group, desc) should have the proper diagnostics ok 61 - hasnt_group(nonexistent group) should pass ok 62 - hasnt_group(nonexistent group) should have the proper description ok 63 - hasnt_group(nonexistent group) should have the proper diagnostics ok 64 - hasnt_group(nonexistent group, desc) should pass ok 65 - hasnt_group(nonexistent group, desc) should have the proper description ok 66 - hasnt_group(nonexistent group, desc) should have the proper diagnostics ok 67 - is_member_of(meanies, [current_user], desc) should pass ok 68 - is_member_of(meanies, [current_user], desc) should have the proper description ok 69 - is_member_of(meanies, [current_user], desc) should have the proper diagnostics ok 70 - is_member_of(meanies, [current_user]) should pass ok 71 - is_member_of(meanies, [current_user]) should have the proper description ok 72 - is_member_of(meanies, [current_user]) should have the proper diagnostics ok 73 - is_member_of(meanies, current_user, desc) should pass ok 74 - is_member_of(meanies, current_user, desc) should have the proper description ok 75 - is_member_of(meanies, current_user, desc) should have the proper diagnostics ok 76 - is_member_of(meanies, current_user) should pass ok 77 - is_member_of(meanies, current_user) should have the proper description ok 78 - is_member_of(meanies, current_user) should have the proper diagnostics pgtap-0.90.0/test/expected/._util.out000644 000765 000024 00000000252 11666501762 017661 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/util.out000644 000765 000024 00000002560 11666501762 017450 0ustar00davidstaff000000 000000 \unset ECHO 1..35 ok 1 - pg_type(int) should work ok 2 - pg_type(numeric) should work ok 3 - pg_type(text) should work ok 4 - pg_version() should return text ok 5 - pg_version() should return same as "server_version" setting ok 6 - pg_version() should work ok 7 - pg_version() should return same as "server_version" setting ok 8 - pg_version_num() should return integer ok 9 - pg_version_num() should be correct ok 10 - os_name() should output something like an OS name ok 11 - findfincs() should return distinct values ok 12 - pgtap_version() should work ok 13 - collect_tap(text[]) should simply collect tap ok 14 - variadic collect_tap() should simply collect tap ok 15 - display_type(int4) ok 16 - display_type(numeric) ok 17 - display_type(numeric, typmod) ok 18 - display_type("char") ok 19 - display_type(char) ok 20 - display_type(timestamp) ok 21 - display_type(timestamptz) ok 22 - display_type(foo, int4) ok 23 - display_type(HEY, numeric) ok 24 - display_type(t z, int4) ok 25 - display type_type(text) ok 26 - display_type(__foo.goofy) ok 27 - display_type(__foo."this.that") ok 28 - display_type(__foo."this"".that") ok 29 - display_type(__foo."hey"".yoman", 13) ok 30 - display_type("try.this""", 42) ok 31 - No quoting is required ok 32 - Just quote ok 33 - No quoting is required (with precision) ok 34 - Quote as type with precision ok 35 - Quote as ident without precision pgtap-0.90.0/test/expected/._valueset.out000644 000765 000024 00000000252 11666501762 020534 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/test/expected/valueset.out000644 000765 000024 00000057150 11666501762 020330 0ustar00davidstaff000000 000000 \unset ECHO 1..349 ok 1 - Should create a temp table for a prepared statement with space and values ok 2 - Table __spacenames__ should exist ok 3 - Should create a temp table for a values statement ok 4 - Table __somevals__ should exist ok 5 - set_eq(prepared, prepared, desc) should pass ok 6 - set_eq(prepared, prepared, desc) should have the proper description ok 7 - set_eq(prepared, prepared, desc) should have the proper diagnostics ok 8 - set_eq(prepared, prepared) should pass ok 9 - set_eq(prepared, prepared) should have the proper description ok 10 - set_eq(prepared, prepared) should have the proper diagnostics ok 11 - set_eq(execute, execute, desc) should pass ok 12 - set_eq(execute, execute, desc) should have the proper description ok 13 - set_eq(execute, execute, desc) should have the proper diagnostics ok 14 - set_eq(values, dupe values) should pass ok 15 - set_eq(values, dupe values) should have the proper description ok 16 - set_eq(values, dupe values) should have the proper diagnostics ok 17 - set_eq(select, prepared) fail missing should fail ok 18 - set_eq(select, prepared) fail missing should have the proper description ok 19 - set_eq(select, prepared) fail missing should have the proper diagnostics ok 20 - set_eq(select, prepared) fail missings should fail ok 21 - set_eq(select, prepared) fail missings should have the proper description ok 22 - set_eq(select, prepared) fail missings should have the proper diagnostics ok 23 - set_eq(values, values) fail mismatch should fail ok 24 - set_eq(values, values) fail mismatch should have the proper description ok 25 - set_eq(values, values) fail mismatch should have the proper diagnostics ok 26 - set_eq(values, values) fail column count should fail ok 27 - set_eq(values, values) fail column count should have the proper description ok 28 - set_eq(values, values) fail column count should have the proper diagnostics ok 29 - bag_eq(prepared, prepared, desc) should pass ok 30 - bag_eq(prepared, prepared, desc) should have the proper description ok 31 - bag_eq(prepared, prepared, desc) should have the proper diagnostics ok 32 - bag_eq(prepared, prepared) should pass ok 33 - bag_eq(prepared, prepared) should have the proper description ok 34 - bag_eq(prepared, prepared) should have the proper diagnostics ok 35 - bag_eq(execute, execute) should pass ok 36 - bag_eq(execute, execute) should have the proper description ok 37 - bag_eq(execute, execute) should have the proper diagnostics ok 38 - bag_eq(dupe values, dupe values) should pass ok 39 - bag_eq(dupe values, dupe values) should have the proper description ok 40 - bag_eq(dupe values, dupe values) should have the proper diagnostics ok 41 - bag_eq(select, prepared) fail missing should fail ok 42 - bag_eq(select, prepared) fail missing should have the proper description ok 43 - bag_eq(select, prepared) fail missing should have the proper diagnostics ok 44 - bag_eq(select, prepared) fail missings should fail ok 45 - bag_eq(select, prepared) fail missings should have the proper description ok 46 - bag_eq(select, prepared) fail missings should have the proper diagnostics ok 47 - bag_eq(values, values) fail mismatch should fail ok 48 - bag_eq(values, values) fail mismatch should have the proper description ok 49 - bag_eq(values, values) fail mismatch should have the proper diagnostics ok 50 - bag_eq(values, values) fail column count should fail ok 51 - bag_eq(values, values) fail column count should have the proper description ok 52 - bag_eq(values, values) fail column count should have the proper diagnostics ok 53 - bag_eq(values, values) fail missing dupe should fail ok 54 - bag_eq(values, values) fail missing dupe should have the proper description ok 55 - bag_eq(values, values) fail missing dupe should have the proper diagnostics ok 56 - set_ne(prepared, prepared) fail should fail ok 57 - set_ne(prepared, prepared) fail should have the proper description ok 58 - set_ne(prepared, prepared) fail should have the proper diagnostics ok 59 - set_ne fail with column mismatch should fail ok 60 - set_ne fail with column mismatch should have the proper description ok 61 - set_ne fail with column mismatch should have the proper diagnostics ok 62 - set_ne fail with different col counts should fail ok 63 - set_ne fail with different col counts should have the proper description ok 64 - set_ne fail with different col counts should have the proper diagnostics ok 65 - set_ne fail with dupe should fail ok 66 - set_ne fail with dupe should have the proper description ok 67 - set_ne fail with dupe should have the proper diagnostics ok 68 - bag_ne(prepared, prepared) fail should fail ok 69 - bag_ne(prepared, prepared) fail should have the proper description ok 70 - bag_ne(prepared, prepared) fail should have the proper diagnostics ok 71 - bag_ne fail with column mismatch should fail ok 72 - bag_ne fail with column mismatch should have the proper description ok 73 - bag_ne fail with column mismatch should have the proper diagnostics ok 74 - set_ne pass with dupe should pass ok 75 - set_ne pass with dupe should have the proper description ok 76 - set_ne pass with dupe should have the proper diagnostics ok 77 - bag_ne fail with column mismatch should fail ok 78 - bag_ne fail with column mismatch should have the proper description ok 79 - bag_ne fail with column mismatch should have the proper diagnostics ok 80 - bag_ne fail with different col counts should fail ok 81 - bag_ne fail with different col counts should have the proper description ok 82 - bag_ne fail with different col counts should have the proper diagnostics ok 83 - results_eq(prepared, prepared, desc) should pass ok 84 - results_eq(prepared, prepared, desc) should have the proper description ok 85 - results_eq(prepared, prepared, desc) should have the proper diagnostics ok 86 - results_eq(prepared, prepared) should pass ok 87 - results_eq(prepared, prepared) should have the proper description ok 88 - results_eq(prepared, prepared) should have the proper diagnostics ok 89 - results_eq(execute, execute) should pass ok 90 - results_eq(execute, execute) should have the proper description ok 91 - results_eq(execute, execute) should have the proper diagnostics ok 92 - results_eq(dupe values, dupe values) should pass ok 93 - results_eq(dupe values, dupe values) should have the proper description ok 94 - results_eq(dupe values, dupe values) should have the proper diagnostics ok 95 - results_eq(values with null, values with null) should pass ok 96 - results_eq(values with null, values with null) should have the proper description ok 97 - results_eq(values with null, values with null) should have the proper diagnostics ok 98 - results_eq(nulls, nulls) should pass ok 99 - results_eq(nulls, nulls) should have the proper description ok 100 - results_eq(nulls, nulls) should have the proper diagnostics ok 101 - results_eq(nulls, nulls) fail should fail ok 102 - results_eq(nulls, nulls) fail should have the proper description ok 103 - results_eq(nulls, nulls) fail should have the proper diagnostics ok 104 - results_eq(select, prepared) fail missing last row should fail ok 105 - results_eq(select, prepared) fail missing last row should have the proper description ok 106 - results_eq(select, prepared) fail missing last row should have the proper diagnostics ok 107 - results_eq(prepared, select) fail missing first row should fail ok 108 - results_eq(prepared, select) fail missing first row should have the proper description ok 109 - results_eq(prepared, select) fail missing first row should have the proper diagnostics ok 110 - results_eq(values dupe, values) should fail ok 111 - results_eq(values dupe, values) should have the proper description ok 112 - results_eq(values dupe, values) should have the proper diagnostics ok 113 - results_eq(values null, values) should fail ok 114 - results_eq(values null, values) should have the proper description ok 115 - results_eq(values null, values) should have the proper diagnostics ok 116 - results_eq(values, values) mismatch should fail ok 117 - results_eq(values, values) mismatch should have the proper description ok 118 - results_eq(values, values) mismatch should have the proper diagnostics ok 119 - results_eq(values, values) subtle mismatch should fail ok 120 - results_eq(values, values) subtle mismatch should have the proper description ok 121 - results_eq(values, values) subtle mismatch should have the proper diagnostics ok 122 - results_eq(values, values) fail column count should fail ok 123 - results_eq(values, values) fail column count should have the proper description ok 124 - results_eq(values, values) fail column count should have the proper diagnostics ok 125 - results_eq(cursor, prepared) should pass ok 126 - results_eq(cursor, prepared) should have the proper description ok 127 - results_eq(cursor, prepared) should have the proper diagnostics ok 128 - results_eq(prepared, cursor) should pass ok 129 - results_eq(prepared, cursor) should have the proper description ok 130 - results_eq(prepared, cursor) should have the proper diagnostics ok 131 - set_has( prepared, prepared, description ) should pass ok 132 - set_has( prepared, prepared, description ) should have the proper description ok 133 - set_has( prepared, prepared, description ) should have the proper diagnostics ok 134 - set_has( prepared, subprepared ) should pass ok 135 - set_has( prepared, subprepared ) should have the proper description ok 136 - set_has( prepared, subprepared ) should have the proper diagnostics ok 137 - set_has( execute, execute ) should pass ok 138 - set_has( execute, execute ) should have the proper description ok 139 - set_has( execute, execute ) should have the proper diagnostics ok 140 - set_has( prepared, dupes ) should pass ok 141 - set_has( prepared, dupes ) should have the proper description ok 142 - set_has( prepared, dupes ) should have the proper diagnostics ok 143 - set_has( dupes, values ) should pass ok 144 - set_has( dupes, values ) should have the proper description ok 145 - set_has( dupes, values ) should have the proper diagnostics ok 146 - set_has( missing1, expect ) should fail ok 147 - set_has( missing1, expect ) should have the proper description ok 148 - set_has( missing1, expect ) should have the proper diagnostics ok 149 - set_has(missing2, expect ) should fail ok 150 - set_has(missing2, expect ) should have the proper description ok 151 - set_has(missing2, expect ) should have the proper diagnostics ok 152 - set_has((int,text), (text,int)) should fail ok 153 - set_has((int,text), (text,int)) should have the proper description ok 154 - set_has((int,text), (text,int)) should have the proper diagnostics ok 155 - set_has((int), (text,int)) should fail ok 156 - set_has((int), (text,int)) should have the proper description ok 157 - set_has((int), (text,int)) should have the proper diagnostics ok 158 - bag_has( prepared, prepared, description ) should pass ok 159 - bag_has( prepared, prepared, description ) should have the proper description ok 160 - bag_has( prepared, prepared, description ) should have the proper diagnostics ok 161 - bag_has( prepared, subprepared ) should pass ok 162 - bag_has( prepared, subprepared ) should have the proper description ok 163 - bag_has( prepared, subprepared ) should have the proper diagnostics ok 164 - bag_has( execute, execute ) should pass ok 165 - bag_has( execute, execute ) should have the proper description ok 166 - bag_has( execute, execute ) should have the proper diagnostics ok 167 - bag_has( prepared, dupes ) should fail ok 168 - bag_has( prepared, dupes ) should have the proper description ok 169 - bag_has( prepared, dupes ) should have the proper diagnostics ok 170 - bag_has( dupes, values ) should pass ok 171 - bag_has( dupes, values ) should have the proper description ok 172 - bag_has( dupes, values ) should have the proper diagnostics ok 173 - bag_has( missing1, expect ) should fail ok 174 - bag_has( missing1, expect ) should have the proper description ok 175 - bag_has( missing1, expect ) should have the proper diagnostics ok 176 - bag_has(missing2, expect ) should fail ok 177 - bag_has(missing2, expect ) should have the proper description ok 178 - bag_has(missing2, expect ) should have the proper diagnostics ok 179 - bag_has((int,text), (text,int)) should fail ok 180 - bag_has((int,text), (text,int)) should have the proper description ok 181 - bag_has((int,text), (text,int)) should have the proper diagnostics ok 182 - bag_has((int), (text,int)) should fail ok 183 - bag_has((int), (text,int)) should have the proper description ok 184 - bag_has((int), (text,int)) should have the proper diagnostics ok 185 - set_hasnt( prepared, prepared, description ) should pass ok 186 - set_hasnt( prepared, prepared, description ) should have the proper description ok 187 - set_hasnt( prepared, prepared, description ) should have the proper diagnostics ok 188 - set_hasnt( prepared, prepared, description ) should pass ok 189 - set_hasnt( prepared, prepared, description ) should have the proper description ok 190 - set_hasnt( prepared, prepared, description ) should have the proper diagnostics ok 191 - set_hasnt( execute, execute ) should pass ok 192 - set_hasnt( execute, execute ) should have the proper description ok 193 - set_hasnt( execute, execute ) should have the proper diagnostics ok 194 - set_hasnt( prepared, dupes ) should pass ok 195 - set_hasnt( prepared, dupes ) should have the proper description ok 196 - set_hasnt( prepared, dupes ) should have the proper diagnostics ok 197 - set_hasnt( prepared, value ) should fail ok 198 - set_hasnt( prepared, value ) should have the proper description ok 199 - set_hasnt( prepared, value ) should have the proper diagnostics ok 200 - set_hasnt( prepared, values ) should fail ok 201 - set_hasnt( prepared, values ) should have the proper description ok 202 - set_hasnt( prepared, values ) should have the proper diagnostics ok 203 - set_hasnt((int,text), (text,int)) should fail ok 204 - set_hasnt((int,text), (text,int)) should have the proper description ok 205 - set_hasnt((int,text), (text,int)) should have the proper diagnostics ok 206 - set_hasnt((int), (text,int)) should fail ok 207 - set_hasnt((int), (text,int)) should have the proper description ok 208 - set_hasnt((int), (text,int)) should have the proper diagnostics ok 209 - bag_hasnt( prepared, prepared, description ) should pass ok 210 - bag_hasnt( prepared, prepared, description ) should have the proper description ok 211 - bag_hasnt( prepared, prepared, description ) should have the proper diagnostics ok 212 - bag_hasnt( prepared, prepared, description ) should pass ok 213 - bag_hasnt( prepared, prepared, description ) should have the proper description ok 214 - bag_hasnt( prepared, prepared, description ) should have the proper diagnostics ok 215 - bag_hasnt( execute, execute ) should pass ok 216 - bag_hasnt( execute, execute ) should have the proper description ok 217 - bag_hasnt( execute, execute ) should have the proper diagnostics ok 218 - bag_hasnt( prepared, value ) should fail ok 219 - bag_hasnt( prepared, value ) should have the proper description ok 220 - bag_hasnt( prepared, value ) should have the proper diagnostics ok 221 - bag_hasnt( prepared, values ) should fail ok 222 - bag_hasnt( prepared, values ) should have the proper description ok 223 - bag_hasnt( prepared, values ) should have the proper diagnostics ok 224 - bag_hasnt((int,text), (text,int)) should fail ok 225 - bag_hasnt((int,text), (text,int)) should have the proper description ok 226 - bag_hasnt((int,text), (text,int)) should have the proper diagnostics ok 227 - bag_hasnt((int), (text,int)) should fail ok 228 - bag_hasnt((int), (text,int)) should have the proper description ok 229 - bag_hasnt((int), (text,int)) should have the proper diagnostics ok 230 - bag_hasnt( dupes, dupes ) should fail ok 231 - bag_hasnt( dupes, dupes ) should have the proper description ok 232 - bag_hasnt( dupes, dupes ) should have the proper diagnostics ok 233 - bag_hasnt( value, dupes ) should fail ok 234 - bag_hasnt( value, dupes ) should have the proper description ok 235 - bag_hasnt( value, dupes ) should have the proper diagnostics ok 236 - set_eq(prepared, array, desc) should pass ok 237 - set_eq(prepared, array, desc) should have the proper description ok 238 - set_eq(prepared, array, desc) should have the proper diagnostics ok 239 - set_eq(prepared, array) should pass ok 240 - set_eq(prepared, array) should have the proper description ok 241 - set_eq(prepared, array) should have the proper diagnostics ok 242 - set_eq(prepared, dupe array) should pass ok 243 - set_eq(prepared, dupe array) should have the proper description ok 244 - set_eq(prepared, dupe array) should have the proper diagnostics ok 245 - set_eq(prepared, array) extra record should fail ok 246 - set_eq(prepared, array) extra record should have the proper description ok 247 - set_eq(prepared, array) extra record should have the proper diagnostics ok 248 - set_eq(prepared, array) missing record should fail ok 249 - set_eq(prepared, array) missing record should have the proper description ok 250 - set_eq(prepared, array) missing record should have the proper diagnostics ok 251 - set_eq(sql, array) incompatible types should fail ok 252 - set_eq(sql, array) incompatible types should have the proper description ok 253 - set_eq(sql, array) incompatible types should have the proper diagnostics ok 254 - bag_eq(prepared, array, desc) should pass ok 255 - bag_eq(prepared, array, desc) should have the proper description ok 256 - bag_eq(prepared, array, desc) should have the proper diagnostics ok 257 - bag_eq(prepared, array) should pass ok 258 - bag_eq(prepared, array) should have the proper description ok 259 - bag_eq(prepared, array) should have the proper diagnostics ok 260 - bag_eq(prepared, dupe array) fail should fail ok 261 - bag_eq(prepared, dupe array) fail should have the proper description ok 262 - bag_eq(prepared, dupe array) fail should have the proper diagnostics ok 263 - bag_eq(prepared, array) extra record should fail ok 264 - bag_eq(prepared, array) extra record should have the proper description ok 265 - bag_eq(prepared, array) extra record should have the proper diagnostics ok 266 - bag_eq(prepared, array) missing record should fail ok 267 - bag_eq(prepared, array) missing record should have the proper description ok 268 - bag_eq(prepared, array) missing record should have the proper diagnostics ok 269 - bag_eq(prepared, array) incompatible types should fail ok 270 - bag_eq(prepared, array) incompatible types should have the proper description ok 271 - bag_eq(prepared, array) incompatible types should have the proper diagnostics ok 272 - set_ne(prepared, array, desc) should pass ok 273 - set_ne(prepared, array, desc) should have the proper description ok 274 - set_ne(prepared, array, desc) should have the proper diagnostics ok 275 - set_ne(prepared, array) should pass ok 276 - set_ne(prepared, array) should have the proper description ok 277 - set_ne(prepared, array) should have the proper diagnostics ok 278 - set_ne(prepared, array) fail should fail ok 279 - set_ne(prepared, array) fail should have the proper description ok 280 - set_ne(prepared, array) fail should have the proper diagnostics ok 281 - set_ne(prepared, dupes array) fail should fail ok 282 - set_ne(prepared, dupes array) fail should have the proper description ok 283 - set_ne(prepared, dupes array) fail should have the proper diagnostics ok 284 - set_ne(sql, array) incompatible types should fail ok 285 - set_ne(sql, array) incompatible types should have the proper description ok 286 - set_ne(sql, array) incompatible types should have the proper diagnostics ok 287 - bag_ne(prepared, array, desc) should pass ok 288 - bag_ne(prepared, array, desc) should have the proper description ok 289 - bag_ne(prepared, array, desc) should have the proper diagnostics ok 290 - bag_ne(prepared, array) should pass ok 291 - bag_ne(prepared, array) should have the proper description ok 292 - bag_ne(prepared, array) should have the proper diagnostics ok 293 - bag_ne(prepared, array) fail should fail ok 294 - bag_ne(prepared, array) fail should have the proper description ok 295 - bag_ne(prepared, array) fail should have the proper diagnostics ok 296 - bag_ne(prepared, dupes array) should pass ok 297 - bag_ne(prepared, dupes array) should have the proper description ok 298 - bag_ne(prepared, dupes array) should have the proper diagnostics ok 299 - bag_ne(prepared, array) incompatible types should fail ok 300 - bag_ne(prepared, array) incompatible types should have the proper description ok 301 - bag_ne(prepared, array) incompatible types should have the proper diagnostics ok 302 - results_eq(prepared, array, desc) should pass ok 303 - results_eq(prepared, array, desc) should have the proper description ok 304 - results_eq(prepared, array, desc) should have the proper diagnostics ok 305 - results_eq(prepared, array) should pass ok 306 - results_eq(prepared, array) should have the proper description ok 307 - results_eq(prepared, array) should have the proper diagnostics ok 308 - results_eq(prepared, array) extra record should fail ok 309 - results_eq(prepared, array) extra record should have the proper description ok 310 - results_eq(prepared, array) extra record should have the proper diagnostics ok 311 - results_ne(prepared, prepared, desc) should pass ok 312 - results_ne(prepared, prepared, desc) should have the proper description ok 313 - results_ne(prepared, prepared, desc) should have the proper diagnostics ok 314 - results_ne(prepared, prepared) should pass ok 315 - results_ne(prepared, prepared) should have the proper description ok 316 - results_ne(prepared, prepared) should have the proper diagnostics ok 317 - results_ne(execute, execute) should pass ok 318 - results_ne(execute, execute) should have the proper description ok 319 - results_ne(execute, execute) should have the proper diagnostics ok 320 - results_ne(dupe values, dupe values) should pass ok 321 - results_ne(dupe values, dupe values) should have the proper description ok 322 - results_ne(dupe values, dupe values) should have the proper diagnostics ok 323 - results_ne(values with null, values with null) should pass ok 324 - results_ne(values with null, values with null) should have the proper description ok 325 - results_ne(values with null, values with null) should have the proper diagnostics ok 326 - results_ne(nulls, nulls) should pass ok 327 - results_ne(nulls, nulls) should have the proper description ok 328 - results_ne(nulls, nulls) should have the proper diagnostics ok 329 - results_ne(values dupe, values) should pass ok 330 - results_ne(values dupe, values) should have the proper description ok 331 - results_ne(values dupe, values) should have the proper diagnostics ok 332 - results_ne(values null, values) should pass ok 333 - results_ne(values null, values) should have the proper description ok 334 - results_ne(values null, values) should have the proper diagnostics ok 335 - results_ne(values, values) mismatch should fail ok 336 - results_ne(values, values) mismatch should have the proper description ok 337 - results_ne(values, values) mismatch should have the proper diagnostics ok 338 - results_ne(values, values) subtle mismatch should fail ok 339 - results_ne(values, values) subtle mismatch should have the proper description ok 340 - results_ne(values, values) subtle mismatch should have the proper diagnostics ok 341 - results_ne(values, values) fail column count should fail ok 342 - results_ne(values, values) fail column count should have the proper description ok 343 - results_ne(values, values) fail column count should have the proper diagnostics ok 344 - results_ne(cursor, prepared) should fail ok 345 - results_ne(cursor, prepared) should have the proper description ok 346 - results_ne(cursor, prepared) should have the proper diagnostics ok 347 - results_ne(prepared, cursor) should fail ok 348 - results_ne(prepared, cursor) should have the proper description ok 349 - results_ne(prepared, cursor) should have the proper diagnostics pgtap-0.90.0/src/._pgtap.c000644 000765 000024 00000000252 11666501762 015441 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/src/pgtap.c000644 000765 000024 00000003202 11666501762 015222 0ustar00davidstaff000000 000000 /* * PostgreSQL utility functions for pgTAP. */ #include "postgres.h" #include "utils/builtins.h" #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif extern Datum pg_typeof (PG_FUNCTION_ARGS); /* Switched to pure SQL. extern Datum pg_version (PG_FUNCTION_ARGS); extern Datum pg_version_num (PG_FUNCTION_ARGS); */ /* * pg_typeof() * Returns the OID for the data type of its first argument. The SQL function * returns regtype, which magically makes it return text. */ PG_FUNCTION_INFO_V1(pg_typeof); Datum pg_typeof(PG_FUNCTION_ARGS) { PG_RETURN_OID( get_fn_expr_argtype(fcinfo->flinfo, 0) ); } /* * pg_version() * Returns the version number as output by version(), but without all the * other crap. Code borrowed from version.c. */ /* Switched to pure SQL. Kept here for posterity. PG_FUNCTION_INFO_V1(pg_version); Datum pg_version(PG_FUNCTION_ARGS) { int n = strlen(PG_VERSION); text *ret = (text *) palloc(n + VARHDRSZ); #ifdef SET_VARSIZE SET_VARSIZE(ret, n + VARHDRSZ); #else VARATT_SIZEP(ret) = n + VARHDRSZ; #endif memcpy(VARDATA(ret), PG_VERSION, n); PG_RETURN_TEXT_P(ret); } */ /* * pg_version_num() * Returns the version number as an integer. Support for pre-8.2 borrowed from * dumputils.c. */ /* Switched to pure SQL. Ketp here for posterity. PG_FUNCTION_INFO_V1(pg_version_num); Datum pg_version_num(PG_FUNCTION_ARGS) { #ifdef PG_VERSION_NUM PG_RETURN_INT32(PG_VERSION_NUM); #else int cnt; int vmaj, vmin, vrev; cnt = sscanf(PG_VERSION, "%d.%d.%d", &vmaj, &vmin, &vrev); if (cnt < 2) return -1; if (cnt == 2) vrev = 0; PG_RETURN_INT32( (100 * vmaj + vmin) * 100 + vrev ); #endif } */ pgtap-0.90.0/sql/._pgtap--unpackaged--0.26.0.sql000644 000765 000024 00000000252 11666501762 021001 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/sql/pgtap--unpackaged--0.26.0.sql000644 000765 000024 00000133635 11666501762 020600 0ustar00davidstaff000000 000000 ALTER EXTENSION pgtap ADD FUNCTION pg_version(); ALTER EXTENSION pgtap ADD FUNCTION pg_version_num(); ALTER EXTENSION pgtap ADD FUNCTION os_name(); ALTER EXTENSION pgtap ADD FUNCTION pgtap_version(); ALTER EXTENSION pgtap ADD FUNCTION plan( integer ); ALTER EXTENSION pgtap ADD FUNCTION no_plan(); ALTER EXTENSION pgtap ADD FUNCTION _get ( text ); ALTER EXTENSION pgtap ADD FUNCTION _get_latest ( text ); ALTER EXTENSION pgtap ADD FUNCTION _get_latest ( text, integer ); ALTER EXTENSION pgtap ADD FUNCTION _get_note ( text ); ALTER EXTENSION pgtap ADD FUNCTION _get_note ( integer ); ALTER EXTENSION pgtap ADD FUNCTION _set ( text, integer, text ); ALTER EXTENSION pgtap ADD FUNCTION _set ( text, integer ); ALTER EXTENSION pgtap ADD FUNCTION _set ( integer, integer ); ALTER EXTENSION pgtap ADD FUNCTION _add ( text, integer, text ); ALTER EXTENSION pgtap ADD FUNCTION _add ( text, integer ); ALTER EXTENSION pgtap ADD FUNCTION add_result ( bool, bool, text, text, text ); ALTER EXTENSION pgtap ADD FUNCTION num_failed (); ALTER EXTENSION pgtap ADD FUNCTION _finish ( INTEGER, INTEGER, INTEGER); ALTER EXTENSION pgtap ADD FUNCTION finish (); ALTER EXTENSION pgtap ADD FUNCTION diag ( msg text ); ALTER EXTENSION pgtap ADD FUNCTION diag ( msg anyelement ); ALTER EXTENSION pgtap ADD FUNCTION diag( VARIADIC text[] ); ALTER EXTENSION pgtap ADD FUNCTION diag( VARIADIC anyarray ); ALTER EXTENSION pgtap ADD FUNCTION ok ( boolean, text ); ALTER EXTENSION pgtap ADD FUNCTION ok ( boolean ); ALTER EXTENSION pgtap ADD FUNCTION is (anyelement, anyelement, text); ALTER EXTENSION pgtap ADD FUNCTION is (anyelement, anyelement); ALTER EXTENSION pgtap ADD FUNCTION isnt (anyelement, anyelement, text); ALTER EXTENSION pgtap ADD FUNCTION isnt (anyelement, anyelement); ALTER EXTENSION pgtap ADD FUNCTION _alike ( BOOLEAN, ANYELEMENT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION matches ( anyelement, text, text ); ALTER EXTENSION pgtap ADD FUNCTION matches ( anyelement, text ); ALTER EXTENSION pgtap ADD FUNCTION imatches ( anyelement, text, text ); ALTER EXTENSION pgtap ADD FUNCTION imatches ( anyelement, text ); ALTER EXTENSION pgtap ADD FUNCTION alike ( anyelement, text, text ); ALTER EXTENSION pgtap ADD FUNCTION alike ( anyelement, text ); ALTER EXTENSION pgtap ADD FUNCTION ialike ( anyelement, text, text ); ALTER EXTENSION pgtap ADD FUNCTION ialike ( anyelement, text ); ALTER EXTENSION pgtap ADD FUNCTION _unalike ( BOOLEAN, ANYELEMENT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION doesnt_match ( anyelement, text, text ); ALTER EXTENSION pgtap ADD FUNCTION doesnt_match ( anyelement, text ); ALTER EXTENSION pgtap ADD FUNCTION doesnt_imatch ( anyelement, text, text ); ALTER EXTENSION pgtap ADD FUNCTION doesnt_imatch ( anyelement, text ); ALTER EXTENSION pgtap ADD FUNCTION unalike ( anyelement, text, text ); ALTER EXTENSION pgtap ADD FUNCTION unalike ( anyelement, text ); ALTER EXTENSION pgtap ADD FUNCTION unialike ( anyelement, text, text ); ALTER EXTENSION pgtap ADD FUNCTION unialike ( anyelement, text ); ALTER EXTENSION pgtap ADD FUNCTION cmp_ok (anyelement, text, anyelement, text); ALTER EXTENSION pgtap ADD FUNCTION cmp_ok (anyelement, text, anyelement); ALTER EXTENSION pgtap ADD FUNCTION pass ( text ); ALTER EXTENSION pgtap ADD FUNCTION pass (); ALTER EXTENSION pgtap ADD FUNCTION fail ( text ); ALTER EXTENSION pgtap ADD FUNCTION fail (); ALTER EXTENSION pgtap ADD FUNCTION todo ( why text, how_many int ); ALTER EXTENSION pgtap ADD FUNCTION todo ( how_many int, why text ); ALTER EXTENSION pgtap ADD FUNCTION todo ( why text ); ALTER EXTENSION pgtap ADD FUNCTION todo ( how_many int ); ALTER EXTENSION pgtap ADD FUNCTION todo_start (text); ALTER EXTENSION pgtap ADD FUNCTION todo_start (); ALTER EXTENSION pgtap ADD FUNCTION in_todo (); ALTER EXTENSION pgtap ADD FUNCTION todo_end (); ALTER EXTENSION pgtap ADD FUNCTION _todo(); ALTER EXTENSION pgtap ADD FUNCTION skip ( why text, how_many int ); ALTER EXTENSION pgtap ADD FUNCTION skip ( text ); ALTER EXTENSION pgtap ADD FUNCTION skip( int, text ); ALTER EXTENSION pgtap ADD FUNCTION skip( int ); ALTER EXTENSION pgtap ADD FUNCTION _query( TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_ok ( TEXT, CHAR(5), TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_ok ( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_ok ( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_ok ( TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_ok ( TEXT, int4, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_ok ( TEXT, int4, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_ok ( TEXT, int4 ); ALTER EXTENSION pgtap ADD FUNCTION lives_ok ( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION lives_ok ( TEXT ); ALTER EXTENSION pgtap ADD FUNCTION performs_ok ( TEXT, NUMERIC, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION performs_ok ( TEXT, NUMERIC ); ALTER EXTENSION pgtap ADD FUNCTION _rexists ( CHAR, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _rexists ( CHAR, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_table ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_table ( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_table ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_table ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_table ( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_table ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_view ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_view ( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_view ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_view ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_view ( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_view ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_sequence ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_sequence ( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_sequence ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_sequence ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_sequence ( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_sequence ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _cexists ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _cexists ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_column ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_column ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_column ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_column ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_column ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_column ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _col_is_null ( NAME, NAME, NAME, TEXT, bool ); ALTER EXTENSION pgtap ADD FUNCTION _col_is_null ( NAME, NAME, TEXT, bool ); ALTER EXTENSION pgtap ADD FUNCTION col_not_null ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_not_null ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_not_null ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION col_is_null ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_null ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION col_is_null ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION display_type ( OID, INTEGER ); ALTER EXTENSION pgtap ADD FUNCTION display_type ( NAME, OID, INTEGER ); ALTER EXTENSION pgtap ADD FUNCTION _get_col_type ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _get_col_type ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _get_col_ns_type ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _quote_ident_like(TEXT, TEXT); ALTER EXTENSION pgtap ADD FUNCTION col_type_is ( NAME, NAME, NAME, NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_type_is ( NAME, NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_type_is ( NAME, NAME, NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_type_is ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_type_is ( NAME, NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_type_is ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _has_def ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _has_def ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION col_has_default ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_has_default ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_has_default ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION col_hasnt_default ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_hasnt_default ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_hasnt_default ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _def_is( TEXT, TEXT, anyelement, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _cdi ( NAME, NAME, NAME, anyelement, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _cdi ( NAME, NAME, anyelement, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _cdi ( NAME, NAME, anyelement ); ALTER EXTENSION pgtap ADD FUNCTION col_default_is ( NAME, NAME, NAME, anyelement, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_default_is ( NAME, NAME, NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_default_is ( NAME, NAME, anyelement, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_default_is ( NAME, NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_default_is ( NAME, NAME, anyelement ); ALTER EXTENSION pgtap ADD FUNCTION col_default_is ( NAME, NAME, text ); ALTER EXTENSION pgtap ADD FUNCTION _hasc ( NAME, NAME, CHAR ); ALTER EXTENSION pgtap ADD FUNCTION _hasc ( NAME, CHAR ); ALTER EXTENSION pgtap ADD FUNCTION has_pk ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_pk ( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_pk ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_pk ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_pk ( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_pk ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _ident_array_to_string( name[], text ); ALTER EXTENSION pgtap ADD FUNCTION _pg_sv_column_array( OID, SMALLINT[] ); ALTER EXTENSION pgtap ADD FUNCTION _pg_sv_table_accessible( OID, OID ); ALTER EXTENSION pgtap ADD VIEW pg_all_foreign_keys; ALTER EXTENSION pgtap ADD FUNCTION _keys ( NAME, NAME, CHAR ); ALTER EXTENSION pgtap ADD FUNCTION _keys ( NAME, CHAR ); ALTER EXTENSION pgtap ADD FUNCTION _ckeys ( NAME, NAME, CHAR ); ALTER EXTENSION pgtap ADD FUNCTION _ckeys ( NAME, CHAR ); ALTER EXTENSION pgtap ADD FUNCTION col_is_pk ( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_pk ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_pk ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION col_is_pk ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_pk ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_pk ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION col_isnt_pk ( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_isnt_pk ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_isnt_pk ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION col_isnt_pk ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_isnt_pk ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_isnt_pk ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_fk ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_fk ( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_fk ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_fk ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_fk ( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_fk ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _fkexists ( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _fkexists ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION col_is_fk ( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_fk ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_fk ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION col_is_fk ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_fk ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_fk ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION col_isnt_fk ( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_isnt_fk ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_isnt_fk ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION col_isnt_fk ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_isnt_fk ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_isnt_fk ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_unique ( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_unique ( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_unique ( TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _constraint ( NAME, NAME, CHAR, NAME[], TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _constraint ( NAME, CHAR, NAME[], TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_unique ( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_unique ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_unique ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION col_is_unique ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_unique ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_is_unique ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_check ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_check ( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_check ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION col_has_check ( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_has_check ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_has_check ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION col_has_check ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_has_check ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION col_has_check ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION fk_ok ( NAME, NAME, NAME[], NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION fk_ok ( NAME, NAME[], NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION fk_ok ( NAME, NAME, NAME[], NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION fk_ok ( NAME, NAME[], NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION fk_ok ( NAME, NAME, NAME, NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION fk_ok ( NAME, NAME, NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION fk_ok ( NAME, NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION fk_ok ( NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD VIEW tap_funky; ALTER EXTENSION pgtap ADD FUNCTION _got_func ( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _got_func ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _got_func ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _got_func ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_function ( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_function( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION has_function ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_function( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_function ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_function( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION has_function( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_function( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_function ( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_function( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_function ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_function( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_function ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_function( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_function( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_function( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _pg_sv_type_array( OID[] ); ALTER EXTENSION pgtap ADD FUNCTION can ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION can ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION can ( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION can ( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _ikeys( NAME, NAME, NAME); ALTER EXTENSION pgtap ADD FUNCTION _ikeys( NAME, NAME); ALTER EXTENSION pgtap ADD FUNCTION _have_index( NAME, NAME, NAME); ALTER EXTENSION pgtap ADD FUNCTION _have_index( NAME, NAME); ALTER EXTENSION pgtap ADD FUNCTION _iexpr( NAME, NAME, NAME); ALTER EXTENSION pgtap ADD FUNCTION _iexpr( NAME, NAME); ALTER EXTENSION pgtap ADD FUNCTION has_index ( NAME, NAME, NAME, NAME[], text ); ALTER EXTENSION pgtap ADD FUNCTION has_index ( NAME, NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION has_index ( NAME, NAME, NAME, NAME, text ); ALTER EXTENSION pgtap ADD FUNCTION has_index ( NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_index ( NAME, NAME, NAME[], text ); ALTER EXTENSION pgtap ADD FUNCTION has_index ( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _is_schema( NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_index ( NAME, NAME, NAME, text ); ALTER EXTENSION pgtap ADD FUNCTION has_index ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_index ( NAME, NAME, text ); ALTER EXTENSION pgtap ADD FUNCTION has_index ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_index ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_index ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_index ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_index ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION index_is_unique ( NAME, NAME, NAME, text ); ALTER EXTENSION pgtap ADD FUNCTION index_is_unique ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION index_is_unique ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION index_is_unique ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION index_is_primary ( NAME, NAME, NAME, text ); ALTER EXTENSION pgtap ADD FUNCTION index_is_primary ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION index_is_primary ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION index_is_primary ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION is_clustered ( NAME, NAME, NAME, text ); ALTER EXTENSION pgtap ADD FUNCTION is_clustered ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION is_clustered ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION is_clustered ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION index_is_type ( NAME, NAME, NAME, NAME, text ); ALTER EXTENSION pgtap ADD FUNCTION index_is_type ( NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION index_is_type ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION index_is_type ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _trig ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _trig ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_trigger ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_trigger ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_trigger ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_trigger ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_trigger ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_trigger ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_trigger ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_trigger ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION trigger_is ( NAME, NAME, NAME, NAME, NAME, text ); ALTER EXTENSION pgtap ADD FUNCTION trigger_is ( NAME, NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION trigger_is ( NAME, NAME, NAME, text ); ALTER EXTENSION pgtap ADD FUNCTION trigger_is ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_schema( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_schema( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_schema( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_schema( NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_tablespace( NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_tablespace( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_tablespace( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_tablespace( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_tablespace( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _has_type( NAME, NAME, CHAR[] ); ALTER EXTENSION pgtap ADD FUNCTION _has_type( NAME, CHAR[] ); ALTER EXTENSION pgtap ADD FUNCTION has_type( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_type( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_type( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_type( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_type( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_type( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_type( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_type( NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_domain( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_domain( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_domain( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_domain( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_domain( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_domain( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_domain( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_domain( NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_enum( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_enum( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_enum( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_enum( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_enum( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_enum( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_enum( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_enum( NAME ); ALTER EXTENSION pgtap ADD FUNCTION enum_has_labels( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION enum_has_labels( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION enum_has_labels( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION enum_has_labels( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _has_role( NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_role( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_role( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_role( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_role( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _has_user( NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_user( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_user( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_user( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_user( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _is_super( NAME ); ALTER EXTENSION pgtap ADD FUNCTION is_superuser( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_superuser( NAME ); ALTER EXTENSION pgtap ADD FUNCTION isnt_superuser( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION isnt_superuser( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _has_group( NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_group( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_group( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_group( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_group( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _grolist ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION is_member_of( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_member_of( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_member_of( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION is_member_of( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _cmp_types(oid, name); ALTER EXTENSION pgtap ADD FUNCTION _cast_exists ( NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _cast_exists ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _cast_exists ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_cast ( NAME, NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_cast ( NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_cast ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_cast ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_cast ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_cast ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_cast ( NAME, NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_cast ( NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_cast ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_cast ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_cast ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_cast ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _expand_context( char ); ALTER EXTENSION pgtap ADD FUNCTION _get_context( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION cast_context_is( NAME, NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION cast_context_is( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _op_exists ( NAME, NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _op_exists ( NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _op_exists ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_operator ( NAME, NAME, NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_operator ( NAME, NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_operator ( NAME, NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_operator ( NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_operator ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_operator ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_leftop ( NAME, NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_leftop ( NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_leftop ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_leftop ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_leftop ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_leftop ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_rightop ( NAME, NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_rightop ( NAME, NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_rightop ( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_rightop ( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_rightop ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_rightop ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _are ( text, name[], name[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION tablespaces_are ( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION tablespaces_are ( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION schemas_are ( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION schemas_are ( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _extras ( CHAR, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _extras ( CHAR, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _missing ( CHAR, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _missing ( CHAR, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION tables_are ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION tables_are ( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION tables_are ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION tables_are ( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION views_are ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION views_are ( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION views_are ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION views_are ( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION sequences_are ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION sequences_are ( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION sequences_are ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION sequences_are ( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION functions_are ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION functions_are ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION functions_are ( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION functions_are ( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION indexes_are( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION indexes_are( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION indexes_are( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION indexes_are( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION users_are( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION users_are( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION groups_are( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION groups_are( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION languages_are( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION languages_are( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _is_trusted( NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_language( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_language( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_language( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_language( NAME ); ALTER EXTENSION pgtap ADD FUNCTION language_is_trusted( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION language_is_trusted( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _opc_exists( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_opclass( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_opclass( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_opclass( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_opclass( NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_opclass( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_opclass( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_opclass( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_opclass( NAME ); ALTER EXTENSION pgtap ADD FUNCTION opclasses_are ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION opclasses_are ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION opclasses_are ( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION opclasses_are ( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION rules_are( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION rules_are( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION rules_are( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION rules_are( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _is_instead( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _is_instead( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_rule( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_rule( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION has_rule( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION has_rule( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_rule( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_rule( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_rule( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION hasnt_rule( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION rule_is_instead( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION rule_is_instead( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION rule_is_instead( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION rule_is_instead( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _expand_on( char ); ALTER EXTENSION pgtap ADD FUNCTION _contract_on( TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _rule_on( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _rule_on( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION rule_is_on( NAME, NAME, NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION rule_is_on( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION rule_is_on( NAME, NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION rule_is_on( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _nosuch( NAME, NAME, NAME[]); ALTER EXTENSION pgtap ADD FUNCTION _func_compare( NAME, NAME, NAME[], anyelement, anyelement, TEXT); ALTER EXTENSION pgtap ADD FUNCTION _func_compare( NAME, NAME, NAME[], boolean, TEXT); ALTER EXTENSION pgtap ADD FUNCTION _func_compare( NAME, NAME, anyelement, anyelement, TEXT); ALTER EXTENSION pgtap ADD FUNCTION _func_compare( NAME, NAME, boolean, TEXT); ALTER EXTENSION pgtap ADD FUNCTION _lang ( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _lang ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _lang ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _lang ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION function_lang_is( NAME, NAME, NAME[], NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION function_lang_is( NAME, NAME, NAME[], NAME ); ALTER EXTENSION pgtap ADD FUNCTION function_lang_is( NAME, NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION function_lang_is( NAME, NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION function_lang_is( NAME, NAME[], NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION function_lang_is( NAME, NAME[], NAME ); ALTER EXTENSION pgtap ADD FUNCTION function_lang_is( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION function_lang_is( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _returns ( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _returns ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _returns ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _returns ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION function_returns( NAME, NAME, NAME[], TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION function_returns( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION function_returns( NAME, NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION function_returns( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION function_returns( NAME, NAME[], TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION function_returns( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION function_returns( NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION function_returns( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _definer ( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _definer ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _definer ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _definer ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION is_definer ( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_definer( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION is_definer ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_definer( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION is_definer ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_definer( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION is_definer( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_definer( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _agg ( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _agg ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _agg ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _agg ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION is_aggregate ( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_aggregate( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION is_aggregate ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_aggregate( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION is_aggregate ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_aggregate( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION is_aggregate( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_aggregate( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _strict ( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _strict ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _strict ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _strict ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION is_strict ( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_strict( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION is_strict ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_strict( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION is_strict ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_strict( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION is_strict( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_strict( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _expand_vol( char ); ALTER EXTENSION pgtap ADD FUNCTION _refine_vol( text ); ALTER EXTENSION pgtap ADD FUNCTION _vol ( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _vol ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _vol ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _vol ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION volatility_is( NAME, NAME, NAME[], TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION volatility_is( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION volatility_is( NAME, NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION volatility_is( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION volatility_is( NAME, NAME[], TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION volatility_is( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION volatility_is( NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION volatility_is( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT, TEXT, BOOLEAN ); ALTER EXTENSION pgtap ADD FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION check_test( TEXT, BOOLEAN, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION check_test( TEXT, BOOLEAN ); ALTER EXTENSION pgtap ADD FUNCTION findfuncs( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION findfuncs( TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _runem( text[], boolean ); ALTER EXTENSION pgtap ADD FUNCTION _is_verbose(); ALTER EXTENSION pgtap ADD FUNCTION do_tap( name, text ); ALTER EXTENSION pgtap ADD FUNCTION do_tap( name ); ALTER EXTENSION pgtap ADD FUNCTION do_tap( text ); ALTER EXTENSION pgtap ADD FUNCTION do_tap( ); ALTER EXTENSION pgtap ADD FUNCTION _currtest(); ALTER EXTENSION pgtap ADD FUNCTION _cleanup(); ALTER EXTENSION pgtap ADD FUNCTION diag_test_name(TEXT); ALTER EXTENSION pgtap ADD FUNCTION _runner( text[], text[], text[], text[], text[] ); ALTER EXTENSION pgtap ADD FUNCTION runtests( NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION runtests( NAME ); ALTER EXTENSION pgtap ADD FUNCTION runtests( TEXT ); ALTER EXTENSION pgtap ADD FUNCTION runtests( ); ALTER EXTENSION pgtap ADD FUNCTION _temptable ( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _temptable ( anyarray, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _temptypes( TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _docomp( TEXT, TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _relcomp( TEXT, TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _relcomp( TEXT, anyarray, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION set_eq( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION set_eq( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION set_eq( TEXT, anyarray, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION set_eq( TEXT, anyarray ); ALTER EXTENSION pgtap ADD FUNCTION bag_eq( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION bag_eq( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION bag_eq( TEXT, anyarray, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION bag_eq( TEXT, anyarray ); ALTER EXTENSION pgtap ADD FUNCTION _do_ne( TEXT, TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _relne( TEXT, TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION _relne( TEXT, anyarray, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION set_ne( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION set_ne( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION set_ne( TEXT, anyarray, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION set_ne( TEXT, anyarray ); ALTER EXTENSION pgtap ADD FUNCTION bag_ne( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION bag_ne( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION bag_ne( TEXT, anyarray, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION bag_ne( TEXT, anyarray ); ALTER EXTENSION pgtap ADD FUNCTION _relcomp( TEXT, TEXT, TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION set_has( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION set_has( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION bag_has( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION bag_has( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION set_hasnt( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION set_hasnt( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION bag_hasnt( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION bag_hasnt( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_eq( refcursor, refcursor, text ); ALTER EXTENSION pgtap ADD FUNCTION results_eq( refcursor, refcursor ); ALTER EXTENSION pgtap ADD FUNCTION results_eq( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_eq( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_eq( TEXT, anyarray, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_eq( TEXT, anyarray ); ALTER EXTENSION pgtap ADD FUNCTION results_eq( TEXT, refcursor, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_eq( TEXT, refcursor ); ALTER EXTENSION pgtap ADD FUNCTION results_eq( refcursor, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_eq( refcursor, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_eq( refcursor, anyarray, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_eq( refcursor, anyarray ); ALTER EXTENSION pgtap ADD FUNCTION results_ne( refcursor, refcursor, text ); ALTER EXTENSION pgtap ADD FUNCTION results_ne( refcursor, refcursor ); ALTER EXTENSION pgtap ADD FUNCTION results_ne( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_ne( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_ne( TEXT, anyarray, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_ne( TEXT, anyarray ); ALTER EXTENSION pgtap ADD FUNCTION results_ne( TEXT, refcursor, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_ne( TEXT, refcursor ); ALTER EXTENSION pgtap ADD FUNCTION results_ne( refcursor, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_ne( refcursor, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_ne( refcursor, anyarray, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION results_ne( refcursor, anyarray ); ALTER EXTENSION pgtap ADD FUNCTION isa_ok( anyelement, regtype, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION isa_ok( anyelement, regtype ); ALTER EXTENSION pgtap ADD FUNCTION is_empty( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION is_empty( TEXT ); ALTER EXTENSION pgtap ADD FUNCTION collect_tap( VARIADIC text[] ); ALTER EXTENSION pgtap ADD FUNCTION collect_tap( VARCHAR[] ); ALTER EXTENSION pgtap ADD FUNCTION _tlike ( BOOLEAN, TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_like ( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_like ( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_ilike ( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_ilike ( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_matching ( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_matching ( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_imatching ( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION throws_imatching ( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION roles_are( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION roles_are( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _types_are ( NAME, NAME[], TEXT, CHAR[] ); ALTER EXTENSION pgtap ADD FUNCTION types_are ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION types_are ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _types_are ( NAME[], TEXT, CHAR[] ); ALTER EXTENSION pgtap ADD FUNCTION types_are ( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION types_are ( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION domains_are ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domains_are ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION domains_are ( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domains_are ( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION enums_are ( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION enums_are ( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION enums_are ( NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION enums_are ( NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _dexists ( NAME, NAME ); ALTER EXTENSION pgtap ADD FUNCTION _dexists ( NAME ); ALTER EXTENSION pgtap ADD FUNCTION _get_dtype( NAME, TEXT, BOOLEAN ); ALTER EXTENSION pgtap ADD FUNCTION _get_dtype( NAME ); ALTER EXTENSION pgtap ADD FUNCTION domain_type_is( NAME, TEXT, NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domain_type_is( NAME, TEXT, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domain_type_is( NAME, TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domain_type_is( NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domain_type_is( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domain_type_is( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domain_type_isnt( NAME, TEXT, NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domain_type_isnt( NAME, TEXT, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domain_type_isnt( NAME, TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domain_type_isnt( NAME, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domain_type_isnt( TEXT, TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION domain_type_isnt( TEXT, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION row_eq( TEXT, anyelement, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION row_eq( TEXT, anyelement ); ALTER EXTENSION pgtap ADD FUNCTION triggers_are( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION triggers_are( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION triggers_are( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION triggers_are( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _areni ( text, text[], text[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION casts_are ( TEXT[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION casts_are ( TEXT[] ); ALTER EXTENSION pgtap ADD FUNCTION display_oper ( NAME, OID ); ALTER EXTENSION pgtap ADD FUNCTION operators_are( NAME, TEXT[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION operators_are ( NAME, TEXT[] ); ALTER EXTENSION pgtap ADD FUNCTION operators_are( TEXT[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION operators_are ( TEXT[] ); ALTER EXTENSION pgtap ADD FUNCTION columns_are( NAME, NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION columns_are( NAME, NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION columns_are( NAME, NAME[], TEXT ); ALTER EXTENSION pgtap ADD FUNCTION columns_are( NAME, NAME[] ); ALTER EXTENSION pgtap ADD FUNCTION _get_db_owner( NAME ); ALTER EXTENSION pgtap ADD FUNCTION db_owner_is ( NAME, NAME, TEXT ); ALTER EXTENSION pgtap ADD FUNCTION db_owner_is ( NAME, NAME ); pgtap-0.90.0/sql/._pgtap.sql.in000644 000765 000024 00000000252 11666501762 016433 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/sql/pgtap.sql.in000644 000765 000024 00000705040 11666501762 016225 0ustar00davidstaff000000 000000 -- This file defines pgTAP, a collection of functions for TAP-based unit -- testing. It is distributed under the revised FreeBSD license. You can -- find the original here: -- -- http://github.com/theory/pgtap/raw/master/sql/pgtap.sql.in -- -- The home page for the pgTAP project is: -- -- http://pgtap.org/ CREATE OR REPLACE FUNCTION pg_version() RETURNS text AS 'SELECT current_setting(''server_version'')' LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION pg_version_num() RETURNS integer AS $$ SELECT s.a[1]::int * 10000 + COALESCE(substring(s.a[2] FROM '[[:digit:]]+')::int, 0) * 100 + COALESCE(substring(s.a[3] FROM '[[:digit:]]+')::int, 0) FROM ( SELECT string_to_array(current_setting('server_version'), '.') AS a ) AS s; $$ LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION os_name() RETURNS TEXT AS 'SELECT ''__OS__''::text;' LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION pgtap_version() RETURNS NUMERIC AS 'SELECT __VERSION__;' LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION plan( integer ) RETURNS TEXT AS $$ DECLARE rcount INTEGER; BEGIN BEGIN EXECUTE ' CREATE TEMP SEQUENCE __tcache___id_seq; CREATE TEMP TABLE __tcache__ ( id INTEGER NOT NULL DEFAULT nextval(''__tcache___id_seq''), label TEXT NOT NULL, value INTEGER NOT NULL, note TEXT NOT NULL DEFAULT '''' ); CREATE UNIQUE INDEX __tcache___key ON __tcache__(id); GRANT ALL ON TABLE __tcache__ TO PUBLIC; GRANT ALL ON TABLE __tcache___id_seq TO PUBLIC; CREATE TEMP SEQUENCE __tresults___numb_seq; CREATE TEMP TABLE __tresults__ ( numb INTEGER NOT NULL DEFAULT nextval(''__tresults___numb_seq''), ok BOOLEAN NOT NULL DEFAULT TRUE, aok BOOLEAN NOT NULL DEFAULT TRUE, descr TEXT NOT NULL DEFAULT '''', type TEXT NOT NULL DEFAULT '''', reason TEXT NOT NULL DEFAULT '''' ); CREATE UNIQUE INDEX __tresults___key ON __tresults__(numb); GRANT ALL ON TABLE __tresults__ TO PUBLIC; GRANT ALL ON TABLE __tresults___numb_seq TO PUBLIC; '; EXCEPTION WHEN duplicate_table THEN -- Raise an exception if there's already a plan. EXECUTE 'SELECT TRUE FROM __tcache__ WHERE label = ''plan'''; GET DIAGNOSTICS rcount = ROW_COUNT; IF rcount > 0 THEN RAISE EXCEPTION 'You tried to plan twice!'; END IF; END; -- Save the plan and return. PERFORM _set('plan', $1 ); RETURN '1..' || $1; END; $$ LANGUAGE plpgsql strict; CREATE OR REPLACE FUNCTION no_plan() RETURNS SETOF boolean AS $$ BEGIN PERFORM plan(0); RETURN; END; $$ LANGUAGE plpgsql strict; CREATE OR REPLACE FUNCTION _get ( text ) RETURNS integer AS $$ DECLARE ret integer; BEGIN EXECUTE 'SELECT value FROM __tcache__ WHERE label = ' || quote_literal($1) || ' LIMIT 1' INTO ret; RETURN ret; END; $$ LANGUAGE plpgsql strict; CREATE OR REPLACE FUNCTION _get_latest ( text ) RETURNS integer[] AS $$ DECLARE ret integer[]; BEGIN EXECUTE 'SELECT ARRAY[ id, value] FROM __tcache__ WHERE label = ' || quote_literal($1) || ' AND id = (SELECT MAX(id) FROM __tcache__ WHERE label = ' || quote_literal($1) || ') LIMIT 1' INTO ret; RETURN ret; END; $$ LANGUAGE plpgsql strict; CREATE OR REPLACE FUNCTION _get_latest ( text, integer ) RETURNS integer AS $$ DECLARE ret integer; BEGIN EXECUTE 'SELECT MAX(id) FROM __tcache__ WHERE label = ' || quote_literal($1) || ' AND value = ' || $2 INTO ret; RETURN ret; END; $$ LANGUAGE plpgsql strict; CREATE OR REPLACE FUNCTION _get_note ( text ) RETURNS text AS $$ DECLARE ret text; BEGIN EXECUTE 'SELECT note FROM __tcache__ WHERE label = ' || quote_literal($1) || ' LIMIT 1' INTO ret; RETURN ret; END; $$ LANGUAGE plpgsql strict; CREATE OR REPLACE FUNCTION _get_note ( integer ) RETURNS text AS $$ DECLARE ret text; BEGIN EXECUTE 'SELECT note FROM __tcache__ WHERE id = ' || $1 || ' LIMIT 1' INTO ret; RETURN ret; END; $$ LANGUAGE plpgsql strict; CREATE OR REPLACE FUNCTION _set ( text, integer, text ) RETURNS integer AS $$ DECLARE rcount integer; BEGIN EXECUTE 'UPDATE __tcache__ SET value = ' || $2 || CASE WHEN $3 IS NULL THEN '' ELSE ', note = ' || quote_literal($3) END || ' WHERE label = ' || quote_literal($1); GET DIAGNOSTICS rcount = ROW_COUNT; IF rcount = 0 THEN RETURN _add( $1, $2, $3 ); END IF; RETURN $2; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _set ( text, integer ) RETURNS integer AS $$ SELECT _set($1, $2, '') $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _set ( integer, integer ) RETURNS integer AS $$ BEGIN EXECUTE 'UPDATE __tcache__ SET value = ' || $2 || ' WHERE id = ' || $1; RETURN $2; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _add ( text, integer, text ) RETURNS integer AS $$ BEGIN EXECUTE 'INSERT INTO __tcache__ (label, value, note) values (' || quote_literal($1) || ', ' || $2 || ', ' || quote_literal(COALESCE($3, '')) || ')'; RETURN $2; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _add ( text, integer ) RETURNS integer AS $$ SELECT _add($1, $2, '') $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION add_result ( bool, bool, text, text, text ) RETURNS integer AS $$ BEGIN EXECUTE 'INSERT INTO __tresults__ ( ok, aok, descr, type, reason ) VALUES( ' || $1 || ', ' || $2 || ', ' || quote_literal(COALESCE($3, '')) || ', ' || quote_literal($4) || ', ' || quote_literal($5) || ' )'; RETURN currval('__tresults___numb_seq'); END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION num_failed () RETURNS INTEGER AS $$ DECLARE ret integer; BEGIN EXECUTE 'SELECT COUNT(*)::INTEGER FROM __tresults__ WHERE ok = FALSE' INTO ret; RETURN ret; END; $$ LANGUAGE plpgsql strict; CREATE OR REPLACE FUNCTION _finish ( INTEGER, INTEGER, INTEGER) RETURNS SETOF TEXT AS $$ DECLARE curr_test ALIAS FOR $1; exp_tests INTEGER := $2; num_faild ALIAS FOR $3; plural CHAR; BEGIN plural := CASE exp_tests WHEN 1 THEN '' ELSE 's' END; IF curr_test IS NULL THEN RAISE EXCEPTION '# No tests run!'; END IF; IF exp_tests = 0 OR exp_tests IS NULL THEN -- No plan. Output one now. exp_tests = curr_test; RETURN NEXT '1..' || exp_tests; END IF; IF curr_test <> exp_tests THEN RETURN NEXT diag( 'Looks like you planned ' || exp_tests || ' test' || plural || ' but ran ' || curr_test ); ELSIF num_faild > 0 THEN RETURN NEXT diag( 'Looks like you failed ' || num_faild || ' test' || CASE num_faild WHEN 1 THEN '' ELSE 's' END || ' of ' || exp_tests ); ELSE END IF; RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION finish () RETURNS SETOF TEXT AS $$ SELECT * FROM _finish( _get('curr_test'), _get('plan'), num_failed() ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION diag ( msg text ) RETURNS TEXT AS $$ SELECT '# ' || replace( replace( replace( $1, E'\r\n', E'\n# ' ), E'\n', E'\n# ' ), E'\r', E'\n# ' ); $$ LANGUAGE sql strict; CREATE OR REPLACE FUNCTION diag ( msg anyelement ) RETURNS TEXT AS $$ SELECT diag($1::text); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION diag( VARIADIC text[] ) RETURNS TEXT AS $$ SELECT diag(array_to_string($1, '')); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION diag( VARIADIC anyarray ) RETURNS TEXT AS $$ SELECT diag(array_to_string($1, '')); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION ok ( boolean, text ) RETURNS TEXT AS $$ DECLARE aok ALIAS FOR $1; descr text := $2; test_num INTEGER; todo_why TEXT; ok BOOL; BEGIN todo_why := _todo(); ok := CASE WHEN aok = TRUE THEN aok WHEN todo_why IS NULL THEN COALESCE(aok, false) ELSE TRUE END; IF _get('plan') IS NULL THEN RAISE EXCEPTION 'You tried to run a test without a plan! Gotta have a plan'; END IF; test_num := add_result( ok, COALESCE(aok, false), descr, CASE WHEN todo_why IS NULL THEN '' ELSE 'todo' END, COALESCE(todo_why, '') ); RETURN (CASE aok WHEN TRUE THEN '' ELSE 'not ' END) || 'ok ' || _set( 'curr_test', test_num ) || CASE descr WHEN '' THEN '' ELSE COALESCE( ' - ' || substr(diag( descr ), 3), '' ) END || COALESCE( ' ' || diag( 'TODO ' || todo_why ), '') || CASE aok WHEN TRUE THEN '' ELSE E'\n' || diag('Failed ' || CASE WHEN todo_why IS NULL THEN '' ELSE '(TODO) ' END || 'test ' || test_num || CASE descr WHEN '' THEN '' ELSE COALESCE(': "' || descr || '"', '') END ) || CASE WHEN aok IS NULL THEN E'\n' || diag(' (test result was NULL)') ELSE '' END END; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION ok ( boolean ) RETURNS TEXT AS $$ SELECT ok( $1, NULL ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION is (anyelement, anyelement, text) RETURNS TEXT AS $$ DECLARE result BOOLEAN; output TEXT; BEGIN -- Would prefer $1 IS NOT DISTINCT FROM, but that's not supported by 8.1. result := NOT $1 IS DISTINCT FROM $2; output := ok( result, $3 ); RETURN output || CASE result WHEN TRUE THEN '' ELSE E'\n' || diag( ' have: ' || CASE WHEN $1 IS NULL THEN 'NULL' ELSE $1::text END || E'\n want: ' || CASE WHEN $2 IS NULL THEN 'NULL' ELSE $2::text END ) END; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION is (anyelement, anyelement) RETURNS TEXT AS $$ SELECT is( $1, $2, NULL); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION isnt (anyelement, anyelement, text) RETURNS TEXT AS $$ DECLARE result BOOLEAN; output TEXT; BEGIN result := $1 IS DISTINCT FROM $2; output := ok( result, $3 ); RETURN output || CASE result WHEN TRUE THEN '' ELSE E'\n' || diag( ' have: ' || COALESCE( $1::text, 'NULL' ) || E'\n want: anything else' ) END; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION isnt (anyelement, anyelement) RETURNS TEXT AS $$ SELECT isnt( $1, $2, NULL); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _alike ( BOOLEAN, ANYELEMENT, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE result ALIAS FOR $1; got ALIAS FOR $2; rx ALIAS FOR $3; descr ALIAS FOR $4; output TEXT; BEGIN output := ok( result, descr ); RETURN output || CASE result WHEN TRUE THEN '' ELSE E'\n' || diag( ' ' || COALESCE( quote_literal(got), 'NULL' ) || E'\n doesn''t match: ' || COALESCE( quote_literal(rx), 'NULL' ) ) END; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION matches ( anyelement, text, text ) RETURNS TEXT AS $$ SELECT _alike( $1 ~ $2, $1, $2, $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION matches ( anyelement, text ) RETURNS TEXT AS $$ SELECT _alike( $1 ~ $2, $1, $2, NULL ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION imatches ( anyelement, text, text ) RETURNS TEXT AS $$ SELECT _alike( $1 ~* $2, $1, $2, $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION imatches ( anyelement, text ) RETURNS TEXT AS $$ SELECT _alike( $1 ~* $2, $1, $2, NULL ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION alike ( anyelement, text, text ) RETURNS TEXT AS $$ SELECT _alike( $1 ~~ $2, $1, $2, $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION alike ( anyelement, text ) RETURNS TEXT AS $$ SELECT _alike( $1 ~~ $2, $1, $2, NULL ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION ialike ( anyelement, text, text ) RETURNS TEXT AS $$ SELECT _alike( $1 ~~* $2, $1, $2, $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION ialike ( anyelement, text ) RETURNS TEXT AS $$ SELECT _alike( $1 ~~* $2, $1, $2, NULL ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _unalike ( BOOLEAN, ANYELEMENT, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE result ALIAS FOR $1; got ALIAS FOR $2; rx ALIAS FOR $3; descr ALIAS FOR $4; output TEXT; BEGIN output := ok( result, descr ); RETURN output || CASE result WHEN TRUE THEN '' ELSE E'\n' || diag( ' ' || COALESCE( quote_literal(got), 'NULL' ) || E'\n matches: ' || COALESCE( quote_literal(rx), 'NULL' ) ) END; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION doesnt_match ( anyelement, text, text ) RETURNS TEXT AS $$ SELECT _unalike( $1 !~ $2, $1, $2, $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION doesnt_match ( anyelement, text ) RETURNS TEXT AS $$ SELECT _unalike( $1 !~ $2, $1, $2, NULL ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION doesnt_imatch ( anyelement, text, text ) RETURNS TEXT AS $$ SELECT _unalike( $1 !~* $2, $1, $2, $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION doesnt_imatch ( anyelement, text ) RETURNS TEXT AS $$ SELECT _unalike( $1 !~* $2, $1, $2, NULL ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION unalike ( anyelement, text, text ) RETURNS TEXT AS $$ SELECT _unalike( $1 !~~ $2, $1, $2, $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION unalike ( anyelement, text ) RETURNS TEXT AS $$ SELECT _unalike( $1 !~~ $2, $1, $2, NULL ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION unialike ( anyelement, text, text ) RETURNS TEXT AS $$ SELECT _unalike( $1 !~~* $2, $1, $2, $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION unialike ( anyelement, text ) RETURNS TEXT AS $$ SELECT _unalike( $1 !~~* $2, $1, $2, NULL ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION cmp_ok (anyelement, text, anyelement, text) RETURNS TEXT AS $$ DECLARE have ALIAS FOR $1; op ALIAS FOR $2; want ALIAS FOR $3; descr ALIAS FOR $4; result BOOLEAN; output TEXT; BEGIN EXECUTE 'SELECT ' || COALESCE(quote_literal( have ), 'NULL') || '::' || pg_typeof(have) || ' ' || op || ' ' || COALESCE(quote_literal( want ), 'NULL') || '::' || pg_typeof(want) INTO result; output := ok( COALESCE(result, FALSE), descr ); RETURN output || CASE result WHEN TRUE THEN '' ELSE E'\n' || diag( ' ' || COALESCE( quote_literal(have), 'NULL' ) || E'\n ' || op || E'\n ' || COALESCE( quote_literal(want), 'NULL' ) ) END; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION cmp_ok (anyelement, text, anyelement) RETURNS TEXT AS $$ SELECT cmp_ok( $1, $2, $3, NULL ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION pass ( text ) RETURNS TEXT AS $$ SELECT ok( TRUE, $1 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION pass () RETURNS TEXT AS $$ SELECT ok( TRUE, NULL ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION fail ( text ) RETURNS TEXT AS $$ SELECT ok( FALSE, $1 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION fail () RETURNS TEXT AS $$ SELECT ok( FALSE, NULL ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION todo ( why text, how_many int ) RETURNS SETOF BOOLEAN AS $$ BEGIN PERFORM _add('todo', COALESCE(how_many, 1), COALESCE(why, '')); RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION todo ( how_many int, why text ) RETURNS SETOF BOOLEAN AS $$ BEGIN PERFORM _add('todo', COALESCE(how_many, 1), COALESCE(why, '')); RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION todo ( why text ) RETURNS SETOF BOOLEAN AS $$ BEGIN PERFORM _add('todo', 1, COALESCE(why, '')); RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION todo ( how_many int ) RETURNS SETOF BOOLEAN AS $$ BEGIN PERFORM _add('todo', COALESCE(how_many, 1), ''); RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION todo_start (text) RETURNS SETOF BOOLEAN AS $$ BEGIN PERFORM _add('todo', -1, COALESCE($1, '')); RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION todo_start () RETURNS SETOF BOOLEAN AS $$ BEGIN PERFORM _add('todo', -1, ''); RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION in_todo () RETURNS BOOLEAN AS $$ DECLARE todos integer; BEGIN todos := _get('todo'); RETURN CASE WHEN todos IS NULL THEN FALSE ELSE TRUE END; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION todo_end () RETURNS SETOF BOOLEAN AS $$ DECLARE id integer; BEGIN id := _get_latest( 'todo', -1 ); IF id IS NULL THEN RAISE EXCEPTION 'todo_end() called without todo_start()'; END IF; EXECUTE 'DELETE FROM __tcache__ WHERE id = ' || id; RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _todo() RETURNS TEXT AS $$ DECLARE todos INT[]; note text; BEGIN -- Get the latest id and value, because todo() might have been called -- again before the todos ran out for the first call to todo(). This -- allows them to nest. todos := _get_latest('todo'); IF todos IS NULL THEN -- No todos. RETURN NULL; END IF; IF todos[2] = 0 THEN -- Todos depleted. Clean up. EXECUTE 'DELETE FROM __tcache__ WHERE id = ' || todos[1]; RETURN NULL; END IF; -- Decrement the count of counted todos and return the reason. IF todos[2] <> -1 THEN PERFORM _set(todos[1], todos[2] - 1); END IF; note := _get_note(todos[1]); IF todos[2] = 1 THEN -- This was the last todo, so delete the record. EXECUTE 'DELETE FROM __tcache__ WHERE id = ' || todos[1]; END IF; RETURN note; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION skip ( why text, how_many int ) RETURNS TEXT AS $$ DECLARE output TEXT[]; BEGIN output := '{}'; FOR i IN 1..how_many LOOP output = array_append(output, ok( TRUE, 'SKIP: ' || COALESCE( why, '') ) ); END LOOP; RETURN array_to_string(output, E'\n'); END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION skip ( text ) RETURNS TEXT AS $$ SELECT ok( TRUE, 'SKIP: ' || $1 ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION skip( int, text ) RETURNS TEXT AS 'SELECT skip($2, $1)' LANGUAGE sql; CREATE OR REPLACE FUNCTION skip( int ) RETURNS TEXT AS 'SELECT skip(NULL, $1)' LANGUAGE sql; CREATE OR REPLACE FUNCTION _query( TEXT ) RETURNS TEXT AS $$ SELECT CASE WHEN $1 LIKE '"%' OR $1 !~ '[[:space:]]' THEN 'EXECUTE ' || $1 ELSE $1 END; $$ LANGUAGE SQL; -- throws_ok ( sql, errcode, errmsg, description ) CREATE OR REPLACE FUNCTION throws_ok ( TEXT, CHAR(5), TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE query TEXT := _query($1); errcode ALIAS FOR $2; errmsg ALIAS FOR $3; desctext ALIAS FOR $4; descr TEXT; BEGIN descr := COALESCE( desctext, 'threw ' || errcode || ': ' || errmsg, 'threw ' || errcode, 'threw ' || errmsg, 'threw an exception' ); EXECUTE query; RETURN ok( FALSE, descr ) || E'\n' || diag( ' caught: no exception' || E'\n wanted: ' || COALESCE( errcode, 'an exception' ) ); EXCEPTION WHEN OTHERS THEN IF (errcode IS NULL OR SQLSTATE = errcode) AND ( errmsg IS NULL OR SQLERRM = errmsg) THEN -- The expected errcode and/or message was thrown. RETURN ok( TRUE, descr ); ELSE -- This was not the expected errcode or errmsg. RETURN ok( FALSE, descr ) || E'\n' || diag( ' caught: ' || SQLSTATE || ': ' || SQLERRM || E'\n wanted: ' || COALESCE( errcode, 'an exception' ) || COALESCE( ': ' || errmsg, '') ); END IF; END; $$ LANGUAGE plpgsql; -- throws_ok ( sql, errcode, errmsg ) -- throws_ok ( sql, errmsg, description ) CREATE OR REPLACE FUNCTION throws_ok ( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ BEGIN IF octet_length($2) = 5 THEN RETURN throws_ok( $1, $2::char(5), $3, NULL ); ELSE RETURN throws_ok( $1, NULL, $2, $3 ); END IF; END; $$ LANGUAGE plpgsql; -- throws_ok ( query, errcode ) -- throws_ok ( query, errmsg ) CREATE OR REPLACE FUNCTION throws_ok ( TEXT, TEXT ) RETURNS TEXT AS $$ BEGIN IF octet_length($2) = 5 THEN RETURN throws_ok( $1, $2::char(5), NULL, NULL ); ELSE RETURN throws_ok( $1, NULL, $2, NULL ); END IF; END; $$ LANGUAGE plpgsql; -- throws_ok ( sql ) CREATE OR REPLACE FUNCTION throws_ok ( TEXT ) RETURNS TEXT AS $$ SELECT throws_ok( $1, NULL, NULL, NULL ); $$ LANGUAGE SQL; -- Magically cast integer error codes. -- throws_ok ( sql, errcode, errmsg, description ) CREATE OR REPLACE FUNCTION throws_ok ( TEXT, int4, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT throws_ok( $1, $2::char(5), $3, $4 ); $$ LANGUAGE SQL; -- throws_ok ( sql, errcode, errmsg ) CREATE OR REPLACE FUNCTION throws_ok ( TEXT, int4, TEXT ) RETURNS TEXT AS $$ SELECT throws_ok( $1, $2::char(5), $3, NULL ); $$ LANGUAGE SQL; -- throws_ok ( sql, errcode ) CREATE OR REPLACE FUNCTION throws_ok ( TEXT, int4 ) RETURNS TEXT AS $$ SELECT throws_ok( $1, $2::char(5), NULL, NULL ); $$ LANGUAGE SQL; -- lives_ok( sql, description ) CREATE OR REPLACE FUNCTION lives_ok ( TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE code TEXT := _query($1); descr ALIAS FOR $2; BEGIN EXECUTE code; RETURN ok( TRUE, descr ); EXCEPTION WHEN OTHERS THEN -- There should have been no exception. RETURN ok( FALSE, descr ) || E'\n' || diag( ' died: ' || SQLSTATE || ': ' || SQLERRM ); END; $$ LANGUAGE plpgsql; -- lives_ok( sql ) CREATE OR REPLACE FUNCTION lives_ok ( TEXT ) RETURNS TEXT AS $$ SELECT lives_ok( $1, NULL ); $$ LANGUAGE SQL; -- performs_ok ( sql, milliseconds, description ) CREATE OR REPLACE FUNCTION performs_ok ( TEXT, NUMERIC, TEXT ) RETURNS TEXT AS $$ DECLARE query TEXT := _query($1); max_time ALIAS FOR $2; descr ALIAS FOR $3; starts_at TEXT; act_time NUMERIC; BEGIN starts_at := timeofday(); EXECUTE query; act_time := extract( millisecond from timeofday()::timestamptz - starts_at::timestamptz); IF act_time < max_time THEN RETURN ok(TRUE, descr); END IF; RETURN ok( FALSE, descr ) || E'\n' || diag( ' runtime: ' || act_time || ' ms' || E'\n exceeds: ' || max_time || ' ms' ); END; $$ LANGUAGE plpgsql; -- performs_ok ( sql, milliseconds ) CREATE OR REPLACE FUNCTION performs_ok ( TEXT, NUMERIC ) RETURNS TEXT AS $$ SELECT performs_ok( $1, $2, 'Should run in less than ' || $2 || ' ms' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _rexists ( CHAR, NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace WHERE c.relkind = $1 AND n.nspname = $2 AND c.relname = $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _rexists ( CHAR, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_class c WHERE c.relkind = $1 AND pg_catalog.pg_table_is_visible(c.oid) AND c.relname = $2 ); $$ LANGUAGE SQL; -- has_table( schema, table, description ) CREATE OR REPLACE FUNCTION has_table ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _rexists( 'r', $1, $2 ), $3 ); $$ LANGUAGE SQL; -- has_table( table, description ) CREATE OR REPLACE FUNCTION has_table ( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _rexists( 'r', $1 ), $2 ); $$ LANGUAGE SQL; -- has_table( table ) CREATE OR REPLACE FUNCTION has_table ( NAME ) RETURNS TEXT AS $$ SELECT has_table( $1, 'Table ' || quote_ident($1) || ' should exist' ); $$ LANGUAGE SQL; -- hasnt_table( schema, table, description ) CREATE OR REPLACE FUNCTION hasnt_table ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _rexists( 'r', $1, $2 ), $3 ); $$ LANGUAGE SQL; -- hasnt_table( table, description ) CREATE OR REPLACE FUNCTION hasnt_table ( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _rexists( 'r', $1 ), $2 ); $$ LANGUAGE SQL; -- hasnt_table( table ) CREATE OR REPLACE FUNCTION hasnt_table ( NAME ) RETURNS TEXT AS $$ SELECT hasnt_table( $1, 'Table ' || quote_ident($1) || ' should not exist' ); $$ LANGUAGE SQL; -- has_view( schema, view, description ) CREATE OR REPLACE FUNCTION has_view ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _rexists( 'v', $1, $2 ), $3 ); $$ LANGUAGE SQL; -- has_view( view, description ) CREATE OR REPLACE FUNCTION has_view ( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _rexists( 'v', $1 ), $2 ); $$ LANGUAGE SQL; -- has_view( view ) CREATE OR REPLACE FUNCTION has_view ( NAME ) RETURNS TEXT AS $$ SELECT has_view( $1, 'View ' || quote_ident($1) || ' should exist' ); $$ LANGUAGE SQL; -- hasnt_view( schema, view, description ) CREATE OR REPLACE FUNCTION hasnt_view ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _rexists( 'v', $1, $2 ), $3 ); $$ LANGUAGE SQL; -- hasnt_view( view, description ) CREATE OR REPLACE FUNCTION hasnt_view ( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _rexists( 'v', $1 ), $2 ); $$ LANGUAGE SQL; -- hasnt_view( view ) CREATE OR REPLACE FUNCTION hasnt_view ( NAME ) RETURNS TEXT AS $$ SELECT hasnt_view( $1, 'View ' || quote_ident($1) || ' should not exist' ); $$ LANGUAGE SQL; -- has_sequence( schema, sequence, description ) CREATE OR REPLACE FUNCTION has_sequence ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _rexists( 'S', $1, $2 ), $3 ); $$ LANGUAGE SQL; -- has_sequence( sequence, description ) CREATE OR REPLACE FUNCTION has_sequence ( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _rexists( 'S', $1 ), $2 ); $$ LANGUAGE SQL; -- has_sequence( sequence ) CREATE OR REPLACE FUNCTION has_sequence ( NAME ) RETURNS TEXT AS $$ SELECT has_sequence( $1, 'Sequence ' || quote_ident($1) || ' should exist' ); $$ LANGUAGE SQL; -- hasnt_sequence( schema, sequence, description ) CREATE OR REPLACE FUNCTION hasnt_sequence ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _rexists( 'S', $1, $2 ), $3 ); $$ LANGUAGE SQL; -- hasnt_sequence( sequence, description ) CREATE OR REPLACE FUNCTION hasnt_sequence ( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _rexists( 'S', $1 ), $2 ); $$ LANGUAGE SQL; -- hasnt_sequence( sequence ) CREATE OR REPLACE FUNCTION hasnt_sequence ( NAME ) RETURNS TEXT AS $$ SELECT hasnt_sequence( $1, 'Sequence ' || quote_ident($1) || ' should not exist' ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _cexists ( NAME, NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid WHERE n.nspname = $1 AND c.relname = $2 AND a.attnum > 0 AND NOT a.attisdropped AND a.attname = $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _cexists ( NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_class c JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid WHERE c.relname = $1 AND pg_catalog.pg_table_is_visible(c.oid) AND a.attnum > 0 AND NOT a.attisdropped AND a.attname = $2 ); $$ LANGUAGE SQL; -- has_column( schema, table, column, description ) CREATE OR REPLACE FUNCTION has_column ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _cexists( $1, $2, $3 ), $4 ); $$ LANGUAGE SQL; -- has_column( table, column, description ) CREATE OR REPLACE FUNCTION has_column ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _cexists( $1, $2 ), $3 ); $$ LANGUAGE SQL; -- has_column( table, column ) CREATE OR REPLACE FUNCTION has_column ( NAME, NAME ) RETURNS TEXT AS $$ SELECT has_column( $1, $2, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' ); $$ LANGUAGE SQL; -- hasnt_column( schema, table, column, description ) CREATE OR REPLACE FUNCTION hasnt_column ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _cexists( $1, $2, $3 ), $4 ); $$ LANGUAGE SQL; -- hasnt_column( table, column, description ) CREATE OR REPLACE FUNCTION hasnt_column ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _cexists( $1, $2 ), $3 ); $$ LANGUAGE SQL; -- hasnt_column( table, column ) CREATE OR REPLACE FUNCTION hasnt_column ( NAME, NAME ) RETURNS TEXT AS $$ SELECT hasnt_column( $1, $2, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should not exist' ); $$ LANGUAGE SQL; -- _col_is_null( schema, table, column, desc, null ) CREATE OR REPLACE FUNCTION _col_is_null ( NAME, NAME, NAME, TEXT, bool ) RETURNS TEXT AS $$ BEGIN IF NOT _cexists( $1, $2, $3 ) THEN RETURN fail( $4 ) || E'\n' || diag (' Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' does not exist' ); END IF; RETURN ok( EXISTS( SELECT true FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid WHERE n.nspname = $1 AND c.relname = $2 AND a.attnum > 0 AND NOT a.attisdropped AND a.attname = $3 AND a.attnotnull = $5 ), $4 ); END; $$ LANGUAGE plpgsql; -- _col_is_null( table, column, desc, null ) CREATE OR REPLACE FUNCTION _col_is_null ( NAME, NAME, TEXT, bool ) RETURNS TEXT AS $$ BEGIN IF NOT _cexists( $1, $2 ) THEN RETURN fail( $3 ) || E'\n' || diag (' Column ' || quote_ident($1) || '.' || quote_ident($2) || ' does not exist' ); END IF; RETURN ok( EXISTS( SELECT true FROM pg_catalog.pg_class c JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid WHERE pg_catalog.pg_table_is_visible(c.oid) AND c.relname = $1 AND a.attnum > 0 AND NOT a.attisdropped AND a.attname = $2 AND a.attnotnull = $4 ), $3 ); END; $$ LANGUAGE plpgsql; -- col_not_null( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_not_null ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT _col_is_null( $1, $2, $3, $4, true ); $$ LANGUAGE SQL; -- col_not_null( table, column, description ) CREATE OR REPLACE FUNCTION col_not_null ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT _col_is_null( $1, $2, $3, true ); $$ LANGUAGE SQL; -- col_not_null( table, column ) CREATE OR REPLACE FUNCTION col_not_null ( NAME, NAME ) RETURNS TEXT AS $$ SELECT _col_is_null( $1, $2, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should be NOT NULL', true ); $$ LANGUAGE SQL; -- col_is_null( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_is_null ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT _col_is_null( $1, $2, $3, $4, false ); $$ LANGUAGE SQL; -- col_is_null( schema, table, column ) CREATE OR REPLACE FUNCTION col_is_null ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT _col_is_null( $1, $2, $3, false ); $$ LANGUAGE SQL; -- col_is_null( table, column ) CREATE OR REPLACE FUNCTION col_is_null ( NAME, NAME ) RETURNS TEXT AS $$ SELECT _col_is_null( $1, $2, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should allow NULL', false ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION display_type ( OID, INTEGER ) RETURNS TEXT AS $$ SELECT COALESCE(substring( pg_catalog.format_type($1, $2), '(("(?!")([^"]|"")+"|[^.]+)([(][^)]+[)])?)$' ), '') $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION display_type ( NAME, OID, INTEGER ) RETURNS TEXT AS $$ SELECT CASE WHEN $1 IS NULL THEN '' ELSE quote_ident($1) || '.' END || display_type($2, $3) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _get_col_type ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT display_type(a.atttypid, a.atttypmod) FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid WHERE n.nspname = $1 AND c.relname = $2 AND a.attname = $3 AND attnum > 0 AND NOT a.attisdropped $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _get_col_type ( NAME, NAME ) RETURNS TEXT AS $$ SELECT display_type(a.atttypid, a.atttypmod) FROM pg_catalog.pg_attribute a JOIN pg_catalog.pg_class c ON a.attrelid = c.oid WHERE pg_table_is_visible(c.oid) AND c.relname = $1 AND a.attname = $2 AND attnum > 0 AND NOT a.attisdropped AND pg_type_is_visible(a.atttypid) $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _get_col_ns_type ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT display_type(tn.nspname, a.atttypid, a.atttypmod) FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid JOIN pg_catalog.pg_type t ON a.atttypid = t.oid JOIN pg_catalog.pg_namespace tn ON t.typnamespace = tn.oid WHERE n.nspname = $1 AND c.relname = $2 AND a.attname = $3 AND attnum > 0 AND NOT a.attisdropped $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _quote_ident_like(TEXT, TEXT) RETURNS TEXT AS $$ DECLARE have TEXT; pcision TEXT; BEGIN -- Just return it if rhs isn't quoted. IF $2 !~ '"' THEN RETURN $1; END IF; -- If it's quoted ident without precision, return it quoted. IF $2 ~ '"$' THEN RETURN quote_ident($1); END IF; pcision := substring($1 FROM '[(][^")]+[)]$'); -- Just quote it if thre is no precision. if pcision IS NULL THEN RETURN quote_ident($1); END IF; -- Quote the non-precision part and concatenate with precision. RETURN quote_ident(substring($1 FOR char_length($1) - char_length(pcision))) || pcision; END; $$ LANGUAGE plpgsql; -- col_type_is( schema, table, column, schema, type, description ) CREATE OR REPLACE FUNCTION col_type_is ( NAME, NAME, NAME, NAME, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE have_type TEXT := _get_col_ns_type($1, $2, $3); want_type TEXT; BEGIN IF have_type IS NULL THEN RETURN fail( $6 ) || E'\n' || diag ( ' Column ' || COALESCE(quote_ident($1) || '.', '') || quote_ident($2) || '.' || quote_ident($3) || ' does not exist' ); END IF; want_type := quote_ident($4) || '.' || _quote_ident_like($5, have_type); IF have_type = want_type THEN -- We're good to go. RETURN ok( true, $6 ); END IF; -- Wrong data type. tell 'em what we really got. RETURN ok( false, $6 ) || E'\n' || diag( ' have: ' || have_type || E'\n want: ' || want_type ); END; $$ LANGUAGE plpgsql; -- col_type_is( schema, table, column, schema, type ) CREATE OR REPLACE FUNCTION col_type_is ( NAME, NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_type_is( $1, $2, $3, $4, $5, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' should be type ' || quote_ident($4) || '.' || $5); $$ LANGUAGE SQL; -- col_type_is( schema, table, column, type, description ) CREATE OR REPLACE FUNCTION col_type_is ( NAME, NAME, NAME, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE have_type TEXT; want_type TEXT; BEGIN -- Get the data type. IF $1 IS NULL THEN have_type := _get_col_type($2, $3); ELSE have_type := _get_col_type($1, $2, $3); END IF; IF have_type IS NULL THEN RETURN fail( $5 ) || E'\n' || diag ( ' Column ' || COALESCE(quote_ident($1) || '.', '') || quote_ident($2) || '.' || quote_ident($3) || ' does not exist' ); END IF; want_type := _quote_ident_like($4, have_type); IF have_type = want_type THEN -- We're good to go. RETURN ok( true, $5 ); END IF; -- Wrong data type. tell 'em what we really got. RETURN ok( false, $5 ) || E'\n' || diag( ' have: ' || have_type || E'\n want: ' || want_type ); END; $$ LANGUAGE plpgsql; -- col_type_is( schema, table, column, type ) CREATE OR REPLACE FUNCTION col_type_is ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_type_is( $1, $2, $3, $4, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' should be type ' || $4 ); $$ LANGUAGE SQL; -- col_type_is( table, column, type, description ) CREATE OR REPLACE FUNCTION col_type_is ( NAME, NAME, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT col_type_is( NULL, $1, $2, $3, $4 ); $$ LANGUAGE SQL; -- col_type_is( table, column, type ) CREATE OR REPLACE FUNCTION col_type_is ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_type_is( $1, $2, $3, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should be type ' || $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _has_def ( NAME, NAME, NAME ) RETURNS boolean AS $$ SELECT a.atthasdef FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid WHERE n.nspname = $1 AND c.relname = $2 AND a.attnum > 0 AND NOT a.attisdropped AND a.attname = $3 $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _has_def ( NAME, NAME ) RETURNS boolean AS $$ SELECT a.atthasdef FROM pg_catalog.pg_class c JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid WHERE c.relname = $1 AND a.attnum > 0 AND NOT a.attisdropped AND a.attname = $2 $$ LANGUAGE sql; -- col_has_default( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_has_default ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ BEGIN IF NOT _cexists( $1, $2, $3 ) THEN RETURN fail( $4 ) || E'\n' || diag (' Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' does not exist' ); END IF; RETURN ok( _has_def( $1, $2, $3 ), $4 ); END $$ LANGUAGE plpgsql; -- col_has_default( table, column, description ) CREATE OR REPLACE FUNCTION col_has_default ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ BEGIN IF NOT _cexists( $1, $2 ) THEN RETURN fail( $3 ) || E'\n' || diag (' Column ' || quote_ident($1) || '.' || quote_ident($2) || ' does not exist' ); END IF; RETURN ok( _has_def( $1, $2 ), $3 ); END; $$ LANGUAGE plpgsql; -- col_has_default( table, column ) CREATE OR REPLACE FUNCTION col_has_default ( NAME, NAME ) RETURNS TEXT AS $$ SELECT col_has_default( $1, $2, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should have a default' ); $$ LANGUAGE SQL; -- col_hasnt_default( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_hasnt_default ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ BEGIN IF NOT _cexists( $1, $2, $3 ) THEN RETURN fail( $4 ) || E'\n' || diag (' Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' does not exist' ); END IF; RETURN ok( NOT _has_def( $1, $2, $3 ), $4 ); END; $$ LANGUAGE plpgsql; -- col_hasnt_default( table, column, description ) CREATE OR REPLACE FUNCTION col_hasnt_default ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ BEGIN IF NOT _cexists( $1, $2 ) THEN RETURN fail( $3 ) || E'\n' || diag (' Column ' || quote_ident($1) || '.' || quote_ident($2) || ' does not exist' ); END IF; RETURN ok( NOT _has_def( $1, $2 ), $3 ); END; $$ LANGUAGE plpgsql; -- col_hasnt_default( table, column ) CREATE OR REPLACE FUNCTION col_hasnt_default ( NAME, NAME ) RETURNS TEXT AS $$ SELECT col_hasnt_default( $1, $2, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should not have a default' ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _def_is( TEXT, TEXT, anyelement, TEXT ) RETURNS TEXT AS $$ DECLARE thing text; BEGIN IF $1 ~ '^[^'']+[(]' THEN -- It's a functional default. RETURN is( $1, $3, $4 ); END IF; EXECUTE 'SELECT is(' || COALESCE($1, 'NULL' || '::' || $2) || '::' || $2 || ', ' || COALESCE(quote_literal($3), 'NULL') || '::' || $2 || ', ' || COALESCE(quote_literal($4), 'NULL') || ')' INTO thing; RETURN thing; END; $$ LANGUAGE plpgsql; -- _cdi( schema, table, column, default, description ) CREATE OR REPLACE FUNCTION _cdi ( NAME, NAME, NAME, anyelement, TEXT ) RETURNS TEXT AS $$ BEGIN IF NOT _cexists( $1, $2, $3 ) THEN RETURN fail( $5 ) || E'\n' || diag (' Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' does not exist' ); END IF; IF NOT _has_def( $1, $2, $3 ) THEN RETURN fail( $5 ) || E'\n' || diag (' Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' has no default' ); END IF; RETURN _def_is( pg_catalog.pg_get_expr(d.adbin, d.adrelid), display_type(a.atttypid, a.atttypmod), $4, $5 ) FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c, pg_catalog.pg_attribute a, pg_catalog.pg_attrdef d WHERE n.oid = c.relnamespace AND c.oid = a.attrelid AND a.atthasdef AND a.attrelid = d.adrelid AND a.attnum = d.adnum AND n.nspname = $1 AND c.relname = $2 AND a.attnum > 0 AND NOT a.attisdropped AND a.attname = $3; END; $$ LANGUAGE plpgsql; -- _cdi( table, column, default, description ) CREATE OR REPLACE FUNCTION _cdi ( NAME, NAME, anyelement, TEXT ) RETURNS TEXT AS $$ BEGIN IF NOT _cexists( $1, $2 ) THEN RETURN fail( $4 ) || E'\n' || diag (' Column ' || quote_ident($1) || '.' || quote_ident($2) || ' does not exist' ); END IF; IF NOT _has_def( $1, $2 ) THEN RETURN fail( $4 ) || E'\n' || diag (' Column ' || quote_ident($1) || '.' || quote_ident($2) || ' has no default' ); END IF; RETURN _def_is( pg_catalog.pg_get_expr(d.adbin, d.adrelid), display_type(a.atttypid, a.atttypmod), $3, $4 ) FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a, pg_catalog.pg_attrdef d WHERE c.oid = a.attrelid AND pg_table_is_visible(c.oid) AND a.atthasdef AND a.attrelid = d.adrelid AND a.attnum = d.adnum AND c.relname = $1 AND a.attnum > 0 AND NOT a.attisdropped AND a.attname = $2; END; $$ LANGUAGE plpgsql; -- _cdi( table, column, default ) CREATE OR REPLACE FUNCTION _cdi ( NAME, NAME, anyelement ) RETURNS TEXT AS $$ SELECT col_default_is( $1, $2, $3, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should default to ' || COALESCE( quote_literal($3), 'NULL') ); $$ LANGUAGE sql; -- col_default_is( schema, table, column, default, description ) CREATE OR REPLACE FUNCTION col_default_is ( NAME, NAME, NAME, anyelement, TEXT ) RETURNS TEXT AS $$ SELECT _cdi( $1, $2, $3, $4, $5 ); $$ LANGUAGE sql; -- col_default_is( schema, table, column, default, description ) CREATE OR REPLACE FUNCTION col_default_is ( NAME, NAME, NAME, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _cdi( $1, $2, $3, $4, $5 ); $$ LANGUAGE sql; -- col_default_is( table, column, default, description ) CREATE OR REPLACE FUNCTION col_default_is ( NAME, NAME, anyelement, TEXT ) RETURNS TEXT AS $$ SELECT _cdi( $1, $2, $3, $4 ); $$ LANGUAGE sql; -- col_default_is( table, column, default, description ) CREATE OR REPLACE FUNCTION col_default_is ( NAME, NAME, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _cdi( $1, $2, $3, $4 ); $$ LANGUAGE sql; -- col_default_is( table, column, default ) CREATE OR REPLACE FUNCTION col_default_is ( NAME, NAME, anyelement ) RETURNS TEXT AS $$ SELECT _cdi( $1, $2, $3 ); $$ LANGUAGE sql; -- col_default_is( table, column, default::text ) CREATE OR REPLACE FUNCTION col_default_is ( NAME, NAME, text ) RETURNS TEXT AS $$ SELECT _cdi( $1, $2, $3 ); $$ LANGUAGE sql; -- _hasc( schema, table, constraint_type ) CREATE OR REPLACE FUNCTION _hasc ( NAME, NAME, CHAR ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON c.relnamespace = n.oid JOIN pg_catalog.pg_constraint x ON c.oid = x.conrelid WHERE c.relhaspkey = true AND n.nspname = $1 AND c.relname = $2 AND x.contype = $3 ); $$ LANGUAGE sql; -- _hasc( table, constraint_type ) CREATE OR REPLACE FUNCTION _hasc ( NAME, CHAR ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_class c JOIN pg_catalog.pg_constraint x ON c.oid = x.conrelid WHERE c.relhaspkey = true AND pg_table_is_visible(c.oid) AND c.relname = $1 AND x.contype = $2 ); $$ LANGUAGE sql; -- has_pk( schema, table, description ) CREATE OR REPLACE FUNCTION has_pk ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _hasc( $1, $2, 'p' ), $3 ); $$ LANGUAGE sql; -- has_pk( table, description ) CREATE OR REPLACE FUNCTION has_pk ( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _hasc( $1, 'p' ), $2 ); $$ LANGUAGE sql; -- has_pk( table ) CREATE OR REPLACE FUNCTION has_pk ( NAME ) RETURNS TEXT AS $$ SELECT has_pk( $1, 'Table ' || quote_ident($1) || ' should have a primary key' ); $$ LANGUAGE sql; -- hasnt_pk( schema, table, description ) CREATE OR REPLACE FUNCTION hasnt_pk ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _hasc( $1, $2, 'p' ), $3 ); $$ LANGUAGE sql; -- hasnt_pk( table, description ) CREATE OR REPLACE FUNCTION hasnt_pk ( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _hasc( $1, 'p' ), $2 ); $$ LANGUAGE sql; -- hasnt_pk( table ) CREATE OR REPLACE FUNCTION hasnt_pk ( NAME ) RETURNS TEXT AS $$ SELECT hasnt_pk( $1, 'Table ' || quote_ident($1) || ' should not have a primary key' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _ident_array_to_string( name[], text ) RETURNS text AS $$ SELECT array_to_string(ARRAY( SELECT quote_ident($1[i]) FROM generate_series(1, array_upper($1, 1)) s(i) ORDER BY i ), $2); $$ LANGUAGE SQL immutable; -- Borrowed from newsysviews: http://pgfoundry.org/projects/newsysviews/ CREATE OR REPLACE FUNCTION _pg_sv_column_array( OID, SMALLINT[] ) RETURNS NAME[] AS $$ SELECT ARRAY( SELECT a.attname FROM pg_catalog.pg_attribute a JOIN generate_series(1, array_upper($2, 1)) s(i) ON a.attnum = $2[i] WHERE attrelid = $1 ORDER BY i ) $$ LANGUAGE SQL stable; -- Borrowed from newsysviews: http://pgfoundry.org/projects/newsysviews/ CREATE OR REPLACE FUNCTION _pg_sv_table_accessible( OID, OID ) RETURNS BOOLEAN AS $$ SELECT CASE WHEN has_schema_privilege($1, 'USAGE') THEN ( has_table_privilege($2, 'SELECT') OR has_table_privilege($2, 'INSERT') or has_table_privilege($2, 'UPDATE') OR has_table_privilege($2, 'DELETE') OR has_table_privilege($2, 'RULE') OR has_table_privilege($2, 'REFERENCES') OR has_table_privilege($2, 'TRIGGER') ) ELSE FALSE END; $$ LANGUAGE SQL immutable strict; -- Borrowed from newsysviews: http://pgfoundry.org/projects/newsysviews/ CREATE OR REPLACE VIEW pg_all_foreign_keys AS SELECT n1.nspname AS fk_schema_name, c1.relname AS fk_table_name, k1.conname AS fk_constraint_name, c1.oid AS fk_table_oid, _pg_sv_column_array(k1.conrelid,k1.conkey) AS fk_columns, n2.nspname AS pk_schema_name, c2.relname AS pk_table_name, k2.conname AS pk_constraint_name, c2.oid AS pk_table_oid, ci.relname AS pk_index_name, _pg_sv_column_array(k1.confrelid,k1.confkey) AS pk_columns, CASE k1.confmatchtype WHEN 'f' THEN 'FULL' WHEN 'p' THEN 'PARTIAL' WHEN 'u' THEN 'NONE' else null END AS match_type, CASE k1.confdeltype WHEN 'a' THEN 'NO ACTION' WHEN 'c' THEN 'CASCADE' WHEN 'd' THEN 'SET DEFAULT' WHEN 'n' THEN 'SET NULL' WHEN 'r' THEN 'RESTRICT' else null END AS on_delete, CASE k1.confupdtype WHEN 'a' THEN 'NO ACTION' WHEN 'c' THEN 'CASCADE' WHEN 'd' THEN 'SET DEFAULT' WHEN 'n' THEN 'SET NULL' WHEN 'r' THEN 'RESTRICT' ELSE NULL END AS on_update, k1.condeferrable AS is_deferrable, k1.condeferred AS is_deferred FROM pg_catalog.pg_constraint k1 JOIN pg_catalog.pg_namespace n1 ON (n1.oid = k1.connamespace) JOIN pg_catalog.pg_class c1 ON (c1.oid = k1.conrelid) JOIN pg_catalog.pg_class c2 ON (c2.oid = k1.confrelid) JOIN pg_catalog.pg_namespace n2 ON (n2.oid = c2.relnamespace) JOIN pg_catalog.pg_depend d ON ( d.classid = 'pg_constraint'::regclass AND d.objid = k1.oid AND d.objsubid = 0 AND d.deptype = 'n' AND d.refclassid = 'pg_class'::regclass AND d.refobjsubid=0 ) JOIN pg_catalog.pg_class ci ON (ci.oid = d.refobjid AND ci.relkind = 'i') LEFT JOIN pg_depend d2 ON ( d2.classid = 'pg_class'::regclass AND d2.objid = ci.oid AND d2.objsubid = 0 AND d2.deptype = 'i' AND d2.refclassid = 'pg_constraint'::regclass AND d2.refobjsubid = 0 ) LEFT JOIN pg_catalog.pg_constraint k2 ON ( k2.oid = d2.refobjid AND k2.contype IN ('p', 'u') ) WHERE k1.conrelid != 0 AND k1.confrelid != 0 AND k1.contype = 'f' AND _pg_sv_table_accessible(n1.oid, c1.oid); -- _keys( schema, table, constraint_type ) CREATE OR REPLACE FUNCTION _keys ( NAME, NAME, CHAR ) RETURNS SETOF NAME[] AS $$ SELECT _pg_sv_column_array(x.conrelid,x.conkey) FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace JOIN pg_catalog.pg_constraint x ON c.oid = x.conrelid WHERE n.nspname = $1 AND c.relname = $2 AND x.contype = $3 $$ LANGUAGE sql; -- _keys( table, constraint_type ) CREATE OR REPLACE FUNCTION _keys ( NAME, CHAR ) RETURNS SETOF NAME[] AS $$ SELECT _pg_sv_column_array(x.conrelid,x.conkey) FROM pg_catalog.pg_class c JOIN pg_catalog.pg_constraint x ON c.oid = x.conrelid AND c.relname = $1 AND x.contype = $2 $$ LANGUAGE sql; -- _ckeys( schema, table, constraint_type ) CREATE OR REPLACE FUNCTION _ckeys ( NAME, NAME, CHAR ) RETURNS NAME[] AS $$ SELECT * FROM _keys($1, $2, $3) LIMIT 1; $$ LANGUAGE sql; -- _ckeys( table, constraint_type ) CREATE OR REPLACE FUNCTION _ckeys ( NAME, CHAR ) RETURNS NAME[] AS $$ SELECT * FROM _keys($1, $2) LIMIT 1; $$ LANGUAGE sql; -- col_is_pk( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_is_pk ( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT is( _ckeys( $1, $2, 'p' ), $3, $4 ); $$ LANGUAGE sql; -- col_is_pk( table, column, description ) CREATE OR REPLACE FUNCTION col_is_pk ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT is( _ckeys( $1, 'p' ), $2, $3 ); $$ LANGUAGE sql; -- col_is_pk( table, column[] ) CREATE OR REPLACE FUNCTION col_is_pk ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT col_is_pk( $1, $2, 'Columns ' || quote_ident($1) || '(' || _ident_array_to_string($2, ', ') || ') should be a primary key' ); $$ LANGUAGE sql; -- col_is_pk( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_is_pk ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_is_pk( $1, $2, ARRAY[$3], $4 ); $$ LANGUAGE sql; -- col_is_pk( table, column, description ) CREATE OR REPLACE FUNCTION col_is_pk ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_is_pk( $1, ARRAY[$2], $3 ); $$ LANGUAGE sql; -- col_is_pk( table, column ) CREATE OR REPLACE FUNCTION col_is_pk ( NAME, NAME ) RETURNS TEXT AS $$ SELECT col_is_pk( $1, $2, 'Column ' || quote_ident($1) || '(' || quote_ident($2) || ') should be a primary key' ); $$ LANGUAGE sql; -- col_isnt_pk( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_isnt_pk ( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT isnt( _ckeys( $1, $2, 'p' ), $3, $4 ); $$ LANGUAGE sql; -- col_isnt_pk( table, column, description ) CREATE OR REPLACE FUNCTION col_isnt_pk ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT isnt( _ckeys( $1, 'p' ), $2, $3 ); $$ LANGUAGE sql; -- col_isnt_pk( table, column[] ) CREATE OR REPLACE FUNCTION col_isnt_pk ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT col_isnt_pk( $1, $2, 'Columns ' || quote_ident($1) || '(' || _ident_array_to_string($2, ', ') || ') should not be a primary key' ); $$ LANGUAGE sql; -- col_isnt_pk( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_isnt_pk ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_isnt_pk( $1, $2, ARRAY[$3], $4 ); $$ LANGUAGE sql; -- col_isnt_pk( table, column, description ) CREATE OR REPLACE FUNCTION col_isnt_pk ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_isnt_pk( $1, ARRAY[$2], $3 ); $$ LANGUAGE sql; -- col_isnt_pk( table, column ) CREATE OR REPLACE FUNCTION col_isnt_pk ( NAME, NAME ) RETURNS TEXT AS $$ SELECT col_isnt_pk( $1, $2, 'Column ' || quote_ident($1) || '(' || quote_ident($2) || ') should not be a primary key' ); $$ LANGUAGE sql; -- has_fk( schema, table, description ) CREATE OR REPLACE FUNCTION has_fk ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _hasc( $1, $2, 'f' ), $3 ); $$ LANGUAGE sql; -- has_fk( table, description ) CREATE OR REPLACE FUNCTION has_fk ( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _hasc( $1, 'f' ), $2 ); $$ LANGUAGE sql; -- has_fk( table ) CREATE OR REPLACE FUNCTION has_fk ( NAME ) RETURNS TEXT AS $$ SELECT has_fk( $1, 'Table ' || quote_ident($1) || ' should have a foreign key constraint' ); $$ LANGUAGE sql; -- hasnt_fk( schema, table, description ) CREATE OR REPLACE FUNCTION hasnt_fk ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _hasc( $1, $2, 'f' ), $3 ); $$ LANGUAGE sql; -- hasnt_fk( table, description ) CREATE OR REPLACE FUNCTION hasnt_fk ( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _hasc( $1, 'f' ), $2 ); $$ LANGUAGE sql; -- hasnt_fk( table ) CREATE OR REPLACE FUNCTION hasnt_fk ( NAME ) RETURNS TEXT AS $$ SELECT hasnt_fk( $1, 'Table ' || quote_ident($1) || ' should not have a foreign key constraint' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _fkexists ( NAME, NAME, NAME[] ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT TRUE FROM pg_all_foreign_keys WHERE fk_schema_name = $1 AND quote_ident(fk_table_name) = quote_ident($2) AND fk_columns = $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _fkexists ( NAME, NAME[] ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT TRUE FROM pg_all_foreign_keys WHERE quote_ident(fk_table_name) = quote_ident($1) AND fk_columns = $2 ); $$ LANGUAGE SQL; -- col_is_fk( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_is_fk ( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ DECLARE names text[]; BEGIN IF _fkexists($1, $2, $3) THEN RETURN pass( $4 ); END IF; -- Try to show the columns. SELECT ARRAY( SELECT _ident_array_to_string(fk_columns, ', ') FROM pg_all_foreign_keys WHERE fk_schema_name = $1 AND fk_table_name = $2 ORDER BY fk_columns ) INTO names; IF names[1] IS NOT NULL THEN RETURN fail($4) || E'\n' || diag( ' Table ' || quote_ident($1) || '.' || quote_ident($2) || E' has foreign key constraints on these columns:\n ' || array_to_string( names, E'\n ' ) ); END IF; -- No FKs in this table. RETURN fail($4) || E'\n' || diag( ' Table ' || quote_ident($1) || '.' || quote_ident($2) || ' has no foreign key columns' ); END; $$ LANGUAGE plpgsql; -- col_is_fk( table, column, description ) CREATE OR REPLACE FUNCTION col_is_fk ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ DECLARE names text[]; BEGIN IF _fkexists($1, $2) THEN RETURN pass( $3 ); END IF; -- Try to show the columns. SELECT ARRAY( SELECT _ident_array_to_string(fk_columns, ', ') FROM pg_all_foreign_keys WHERE fk_table_name = $1 ORDER BY fk_columns ) INTO names; IF NAMES[1] IS NOT NULL THEN RETURN fail($3) || E'\n' || diag( ' Table ' || quote_ident($1) || E' has foreign key constraints on these columns:\n ' || array_to_string( names, E'\n ' ) ); END IF; -- No FKs in this table. RETURN fail($3) || E'\n' || diag( ' Table ' || quote_ident($1) || ' has no foreign key columns' ); END; $$ LANGUAGE plpgsql; -- col_is_fk( table, column[] ) CREATE OR REPLACE FUNCTION col_is_fk ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT col_is_fk( $1, $2, 'Columns ' || quote_ident($1) || '(' || _ident_array_to_string($2, ', ') || ') should be a foreign key' ); $$ LANGUAGE sql; -- col_is_fk( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_is_fk ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_is_fk( $1, $2, ARRAY[$3], $4 ); $$ LANGUAGE sql; -- col_is_fk( table, column, description ) CREATE OR REPLACE FUNCTION col_is_fk ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_is_fk( $1, ARRAY[$2], $3 ); $$ LANGUAGE sql; -- col_is_fk( table, column ) CREATE OR REPLACE FUNCTION col_is_fk ( NAME, NAME ) RETURNS TEXT AS $$ SELECT col_is_fk( $1, $2, 'Column ' || quote_ident($1) || '(' || quote_ident($2) || ') should be a foreign key' ); $$ LANGUAGE sql; -- col_isnt_fk( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_isnt_fk ( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _fkexists( $1, $2, $3 ), $4 ); $$ LANGUAGE SQL; -- col_isnt_fk( table, column, description ) CREATE OR REPLACE FUNCTION col_isnt_fk ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _fkexists( $1, $2 ), $3 ); $$ LANGUAGE SQL; -- col_isnt_fk( table, column[] ) CREATE OR REPLACE FUNCTION col_isnt_fk ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT col_isnt_fk( $1, $2, 'Columns ' || quote_ident($1) || '(' || _ident_array_to_string($2, ', ') || ') should not be a foreign key' ); $$ LANGUAGE sql; -- col_isnt_fk( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_isnt_fk ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_isnt_fk( $1, $2, ARRAY[$3], $4 ); $$ LANGUAGE sql; -- col_isnt_fk( table, column, description ) CREATE OR REPLACE FUNCTION col_isnt_fk ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_isnt_fk( $1, ARRAY[$2], $3 ); $$ LANGUAGE sql; -- col_isnt_fk( table, column ) CREATE OR REPLACE FUNCTION col_isnt_fk ( NAME, NAME ) RETURNS TEXT AS $$ SELECT col_isnt_fk( $1, $2, 'Column ' || quote_ident($1) || '(' || quote_ident($2) || ') should not be a foreign key' ); $$ LANGUAGE sql; -- has_unique( schema, table, description ) CREATE OR REPLACE FUNCTION has_unique ( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT ok( _hasc( $1, $2, 'u' ), $3 ); $$ LANGUAGE sql; -- has_unique( table, description ) CREATE OR REPLACE FUNCTION has_unique ( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT ok( _hasc( $1, 'u' ), $2 ); $$ LANGUAGE sql; -- has_unique( table ) CREATE OR REPLACE FUNCTION has_unique ( TEXT ) RETURNS TEXT AS $$ SELECT has_unique( $1, 'Table ' || quote_ident($1) || ' should have a unique constraint' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _constraint ( NAME, NAME, CHAR, NAME[], TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE akey NAME[]; keys TEXT[] := '{}'; have TEXT; BEGIN FOR akey IN SELECT * FROM _keys($1, $2, $3) LOOP IF akey = $4 THEN RETURN pass($5); END IF; keys = keys || akey::text; END LOOP; IF array_upper(keys, 0) = 1 THEN have := 'No ' || $6 || ' constriants'; ELSE have := array_to_string(keys, E'\n '); END IF; RETURN fail($5) || E'\n' || diag( ' have: ' || have || E'\n want: ' || CASE WHEN $4 IS NULL THEN 'NULL' ELSE $4::text END ); END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _constraint ( NAME, CHAR, NAME[], TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE akey NAME[]; keys TEXT[] := '{}'; have TEXT; BEGIN FOR akey IN SELECT * FROM _keys($1, $2) LOOP IF akey = $3 THEN RETURN pass($4); END IF; keys = keys || akey::text; END LOOP; IF array_upper(keys, 0) = 1 THEN have := 'No ' || $5 || ' constriants'; ELSE have := array_to_string(keys, E'\n '); END IF; RETURN fail($4) || E'\n' || diag( ' have: ' || have || E'\n want: ' || CASE WHEN $3 IS NULL THEN 'NULL' ELSE $3::text END ); END; $$ LANGUAGE plpgsql; -- col_is_unique( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_is_unique ( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _constraint( $1, $2, 'u', $3, $4, 'unique' ); $$ LANGUAGE sql; -- col_is_unique( table, column, description ) CREATE OR REPLACE FUNCTION col_is_unique ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _constraint( $1, 'u', $2, $3, 'unique' ); $$ LANGUAGE sql; -- col_is_unique( table, column[] ) CREATE OR REPLACE FUNCTION col_is_unique ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT col_is_unique( $1, $2, 'Columns ' || quote_ident($1) || '(' || _ident_array_to_string($2, ', ') || ') should have a unique constraint' ); $$ LANGUAGE sql; -- col_is_unique( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_is_unique ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_is_unique( $1, $2, ARRAY[$3], $4 ); $$ LANGUAGE sql; -- col_is_unique( table, column, description ) CREATE OR REPLACE FUNCTION col_is_unique ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_is_unique( $1, ARRAY[$2], $3 ); $$ LANGUAGE sql; -- col_is_unique( table, column ) CREATE OR REPLACE FUNCTION col_is_unique ( NAME, NAME ) RETURNS TEXT AS $$ SELECT col_is_unique( $1, $2, 'Column ' || quote_ident($1) || '(' || quote_ident($2) || ') should have a unique constraint' ); $$ LANGUAGE sql; -- has_check( schema, table, description ) CREATE OR REPLACE FUNCTION has_check ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _hasc( $1, $2, 'c' ), $3 ); $$ LANGUAGE sql; -- has_check( table, description ) CREATE OR REPLACE FUNCTION has_check ( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _hasc( $1, 'c' ), $2 ); $$ LANGUAGE sql; -- has_check( table ) CREATE OR REPLACE FUNCTION has_check ( NAME ) RETURNS TEXT AS $$ SELECT has_check( $1, 'Table ' || quote_ident($1) || ' should have a check constraint' ); $$ LANGUAGE sql; -- col_has_check( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_has_check ( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _constraint( $1, $2, 'c', $3, $4, 'check' ); $$ LANGUAGE sql; -- col_has_check( table, column, description ) CREATE OR REPLACE FUNCTION col_has_check ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _constraint( $1, 'c', $2, $3, 'check' ); $$ LANGUAGE sql; -- col_has_check( table, column[] ) CREATE OR REPLACE FUNCTION col_has_check ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT col_has_check( $1, $2, 'Columns ' || quote_ident($1) || '(' || _ident_array_to_string($2, ', ') || ') should have a check constraint' ); $$ LANGUAGE sql; -- col_has_check( schema, table, column, description ) CREATE OR REPLACE FUNCTION col_has_check ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_has_check( $1, $2, ARRAY[$3], $4 ); $$ LANGUAGE sql; -- col_has_check( table, column, description ) CREATE OR REPLACE FUNCTION col_has_check ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT col_has_check( $1, ARRAY[$2], $3 ); $$ LANGUAGE sql; -- col_has_check( table, column ) CREATE OR REPLACE FUNCTION col_has_check ( NAME, NAME ) RETURNS TEXT AS $$ SELECT col_has_check( $1, $2, 'Column ' || quote_ident($1) || '(' || quote_ident($2) || ') should have a check constraint' ); $$ LANGUAGE sql; -- fk_ok( fk_schema, fk_table, fk_column[], pk_schema, pk_table, pk_column[], description ) CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME, NAME[], NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ DECLARE sch name; tab name; cols name[]; BEGIN SELECT pk_schema_name, pk_table_name, pk_columns FROM pg_all_foreign_keys WHERE fk_schema_name = $1 AND fk_table_name = $2 AND fk_columns = $3 INTO sch, tab, cols; RETURN is( -- have quote_ident($1) || '.' || quote_ident($2) || '(' || _ident_array_to_string( $3, ', ' ) || ') REFERENCES ' || COALESCE ( sch || '.' || tab || '(' || _ident_array_to_string( cols, ', ' ) || ')', 'NOTHING' ), -- want quote_ident($1) || '.' || quote_ident($2) || '(' || _ident_array_to_string( $3, ', ' ) || ') REFERENCES ' || $4 || '.' || $5 || '(' || _ident_array_to_string( $6, ', ' ) || ')', $7 ); END; $$ LANGUAGE plpgsql; -- fk_ok( fk_table, fk_column[], pk_table, pk_column[], description ) CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME[], NAME, NAME[], TEXT ) RETURNS TEXT AS $$ DECLARE tab name; cols name[]; BEGIN SELECT pk_table_name, pk_columns FROM pg_all_foreign_keys WHERE fk_table_name = $1 AND fk_columns = $2 INTO tab, cols; RETURN is( -- have $1 || '(' || _ident_array_to_string( $2, ', ' ) || ') REFERENCES ' || COALESCE( tab || '(' || _ident_array_to_string( cols, ', ' ) || ')', 'NOTHING'), -- want $1 || '(' || _ident_array_to_string( $2, ', ' ) || ') REFERENCES ' || $3 || '(' || _ident_array_to_string( $4, ', ' ) || ')', $5 ); END; $$ LANGUAGE plpgsql; -- fk_ok( fk_schema, fk_table, fk_column[], fk_schema, pk_table, pk_column[] ) CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME, NAME[], NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT fk_ok( $1, $2, $3, $4, $5, $6, quote_ident($1) || '.' || quote_ident($2) || '(' || _ident_array_to_string( $3, ', ' ) || ') should reference ' || $4 || '.' || $5 || '(' || _ident_array_to_string( $6, ', ' ) || ')' ); $$ LANGUAGE sql; -- fk_ok( fk_table, fk_column[], pk_table, pk_column[] ) CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME[], NAME, NAME[] ) RETURNS TEXT AS $$ SELECT fk_ok( $1, $2, $3, $4, $1 || '(' || _ident_array_to_string( $2, ', ' ) || ') should reference ' || $3 || '(' || _ident_array_to_string( $4, ', ' ) || ')' ); $$ LANGUAGE sql; -- fk_ok( fk_schema, fk_table, fk_column, pk_schema, pk_table, pk_column, description ) CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME, NAME, NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT fk_ok( $1, $2, ARRAY[$3], $4, $5, ARRAY[$6], $7 ); $$ LANGUAGE sql; -- fk_ok( fk_schema, fk_table, fk_column, pk_schema, pk_table, pk_column ) CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME, NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT fk_ok( $1, $2, ARRAY[$3], $4, $5, ARRAY[$6] ); $$ LANGUAGE sql; -- fk_ok( fk_table, fk_column, pk_table, pk_column, description ) CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT fk_ok( $1, ARRAY[$2], $3, ARRAY[$4], $5 ); $$ LANGUAGE sql; -- fk_ok( fk_table, fk_column, pk_table, pk_column ) CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT fk_ok( $1, ARRAY[$2], $3, ARRAY[$4] ); $$ LANGUAGE sql; CREATE OR REPLACE VIEW tap_funky AS SELECT p.oid AS oid, n.nspname AS schema, p.proname AS name, array_to_string(p.proargtypes::regtype[], ',') AS args, CASE p.proretset WHEN TRUE THEN 'setof ' ELSE '' END || p.prorettype::regtype AS returns, p.prolang AS langoid, p.proisstrict AS is_strict, p.proisagg AS is_agg, p.prosecdef AS is_definer, p.proretset AS returns_set, p.provolatile::char AS volatility, pg_catalog.pg_function_is_visible(p.oid) AS is_visible FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid ; CREATE OR REPLACE FUNCTION _got_func ( NAME, NAME, NAME[] ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT TRUE FROM tap_funky WHERE schema = $1 AND name = $2 AND args = array_to_string($3, ',') ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _got_func ( NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT TRUE FROM tap_funky WHERE schema = $1 AND name = $2 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _got_func ( NAME, NAME[] ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT TRUE FROM tap_funky WHERE name = $1 AND args = array_to_string($2, ',') AND is_visible ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _got_func ( NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT TRUE FROM tap_funky WHERE name = $1 AND is_visible); $$ LANGUAGE SQL; -- has_function( schema, function, args[], description ) CREATE OR REPLACE FUNCTION has_function ( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT ok( _got_func($1, $2, $3), $4 ); $$ LANGUAGE SQL; -- has_function( schema, function, args[] ) CREATE OR REPLACE FUNCTION has_function( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT ok( _got_func($1, $2, $3), 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' || array_to_string($3, ', ') || ') should exist' ); $$ LANGUAGE sql; -- has_function( schema, function, description ) CREATE OR REPLACE FUNCTION has_function ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _got_func($1, $2), $3 ); $$ LANGUAGE SQL; -- has_function( schema, function ) CREATE OR REPLACE FUNCTION has_function( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _got_func($1, $2), 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should exist' ); $$ LANGUAGE sql; -- has_function( function, args[], description ) CREATE OR REPLACE FUNCTION has_function ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT ok( _got_func($1, $2), $3 ); $$ LANGUAGE SQL; -- has_function( function, args[] ) CREATE OR REPLACE FUNCTION has_function( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT ok( _got_func($1, $2), 'Function ' || quote_ident($1) || '(' || array_to_string($2, ', ') || ') should exist' ); $$ LANGUAGE sql; -- has_function( function, description ) CREATE OR REPLACE FUNCTION has_function( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _got_func($1), $2 ); $$ LANGUAGE sql; -- has_function( function ) CREATE OR REPLACE FUNCTION has_function( NAME ) RETURNS TEXT AS $$ SELECT ok( _got_func($1), 'Function ' || quote_ident($1) || '() should exist' ); $$ LANGUAGE sql; -- hasnt_function( schema, function, args[], description ) CREATE OR REPLACE FUNCTION hasnt_function ( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _got_func($1, $2, $3), $4 ); $$ LANGUAGE SQL; -- hasnt_function( schema, function, args[] ) CREATE OR REPLACE FUNCTION hasnt_function( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT ok( NOT _got_func($1, $2, $3), 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' || array_to_string($3, ', ') || ') should not exist' ); $$ LANGUAGE sql; -- hasnt_function( schema, function, description ) CREATE OR REPLACE FUNCTION hasnt_function ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _got_func($1, $2), $3 ); $$ LANGUAGE SQL; -- hasnt_function( schema, function ) CREATE OR REPLACE FUNCTION hasnt_function( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _got_func($1, $2), 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should not exist' ); $$ LANGUAGE sql; -- hasnt_function( function, args[], description ) CREATE OR REPLACE FUNCTION hasnt_function ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _got_func($1, $2), $3 ); $$ LANGUAGE SQL; -- hasnt_function( function, args[] ) CREATE OR REPLACE FUNCTION hasnt_function( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT ok( NOT _got_func($1, $2), 'Function ' || quote_ident($1) || '(' || array_to_string($2, ', ') || ') should not exist' ); $$ LANGUAGE sql; -- hasnt_function( function, description ) CREATE OR REPLACE FUNCTION hasnt_function( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _got_func($1), $2 ); $$ LANGUAGE sql; -- hasnt_function( function ) CREATE OR REPLACE FUNCTION hasnt_function( NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _got_func($1), 'Function ' || quote_ident($1) || '() should not exist' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _pg_sv_type_array( OID[] ) RETURNS NAME[] AS $$ SELECT ARRAY( SELECT t.typname FROM pg_catalog.pg_type t JOIN generate_series(1, array_upper($1, 1)) s(i) ON t.oid = $1[i] ORDER BY i ) $$ LANGUAGE SQL stable; -- can( schema, functions[], description ) CREATE OR REPLACE FUNCTION can ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ DECLARE missing text[]; BEGIN SELECT ARRAY( SELECT quote_ident($2[i]) FROM generate_series(1, array_upper($2, 1)) s(i) LEFT JOIN tap_funky ON name = $2[i] AND schema = $1 WHERE oid IS NULL GROUP BY $2[i], s.i ORDER BY MIN(s.i) ) INTO missing; IF missing[1] IS NULL THEN RETURN ok( true, $3 ); END IF; RETURN ok( false, $3 ) || E'\n' || diag( ' ' || quote_ident($1) || '.' || array_to_string( missing, E'() missing\n ' || quote_ident($1) || '.') || '() missing' ); END; $$ LANGUAGE plpgsql; -- can( schema, functions[] ) CREATE OR REPLACE FUNCTION can ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT can( $1, $2, 'Schema ' || quote_ident($1) || ' can' ); $$ LANGUAGE sql; -- can( functions[], description ) CREATE OR REPLACE FUNCTION can ( NAME[], TEXT ) RETURNS TEXT AS $$ DECLARE missing text[]; BEGIN SELECT ARRAY( SELECT quote_ident($1[i]) FROM generate_series(1, array_upper($1, 1)) s(i) LEFT JOIN pg_catalog.pg_proc p ON $1[i] = p.proname AND pg_catalog.pg_function_is_visible(p.oid) WHERE p.oid IS NULL ORDER BY s.i ) INTO missing; IF missing[1] IS NULL THEN RETURN ok( true, $2 ); END IF; RETURN ok( false, $2 ) || E'\n' || diag( ' ' || array_to_string( missing, E'() missing\n ') || '() missing' ); END; $$ LANGUAGE plpgsql; -- can( functions[] ) CREATE OR REPLACE FUNCTION can ( NAME[] ) RETURNS TEXT AS $$ SELECT can( $1, 'Schema ' || _ident_array_to_string(current_schemas(true), ' or ') || ' can' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _ikeys( NAME, NAME, NAME) RETURNS NAME[] AS $$ SELECT ARRAY( SELECT a.attname FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace JOIN pg_catalog.pg_attribute a ON ct.oid = a.attrelid JOIN generate_series(0, current_setting('max_index_keys')::int - 1) s(i) ON a.attnum = x.indkey[s.i] WHERE ct.relname = $2 AND ci.relname = $3 AND n.nspname = $1 ORDER BY s.i ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _ikeys( NAME, NAME) RETURNS NAME[] AS $$ SELECT ARRAY( SELECT a.attname FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_attribute a ON ct.oid = a.attrelid JOIN generate_series(0, current_setting('max_index_keys')::int - 1) s(i) ON a.attnum = x.indkey[s.i] WHERE ct.relname = $1 AND ci.relname = $2 AND pg_catalog.pg_table_is_visible(ct.oid) ORDER BY s.i ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _have_index( NAME, NAME, NAME) RETURNS BOOLEAN AS $$ SELECT EXISTS ( SELECT TRUE FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace WHERE ct.relname = $2 AND ci.relname = $3 AND n.nspname = $1 ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _have_index( NAME, NAME) RETURNS BOOLEAN AS $$ SELECT EXISTS ( SELECT TRUE FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid WHERE ct.relname = $1 AND ci.relname = $2 ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _iexpr( NAME, NAME, NAME) RETURNS TEXT AS $$ SELECT pg_catalog.pg_get_expr( x.indexprs, ct.oid ) FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace WHERE ct.relname = $2 AND ci.relname = $3 AND n.nspname = $1 $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _iexpr( NAME, NAME) RETURNS TEXT AS $$ SELECT pg_catalog.pg_get_expr( x.indexprs, ct.oid ) FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid WHERE ct.relname = $1 AND ci.relname = $2 AND pg_catalog.pg_table_is_visible(ct.oid) $$ LANGUAGE sql; -- has_index( schema, table, index, columns[], description ) CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME, NAME[], text ) RETURNS TEXT AS $$ DECLARE index_cols name[]; BEGIN index_cols := _ikeys($1, $2, $3 ); IF index_cols IS NULL OR index_cols = '{}'::name[] THEN RETURN ok( false, $5 ) || E'\n' || diag( 'Index ' || quote_ident($3) || ' ON ' || quote_ident($1) || '.' || quote_ident($2) || ' not found'); END IF; RETURN is( quote_ident($3) || ' ON ' || quote_ident($1) || '.' || quote_ident($2) || '(' || _ident_array_to_string( index_cols, ', ' ) || ')', quote_ident($3) || ' ON ' || quote_ident($1) || '.' || quote_ident($2) || '(' || _ident_array_to_string( $4, ', ' ) || ')', $5 ); END; $$ LANGUAGE plpgsql; -- has_index( schema, table, index, columns[] ) CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT has_index( $1, $2, $3, $4, 'Index ' || quote_ident($3) || ' should exist' ); $$ LANGUAGE sql; -- has_index( schema, table, index, column/expression, description ) CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME, NAME, text ) RETURNS TEXT AS $$ DECLARE expr text; BEGIN IF $4 NOT LIKE '%(%' THEN -- Not a functional index. RETURN has_index( $1, $2, $3, ARRAY[$4], $5 ); END IF; -- Get the functional expression. expr := _iexpr($1, $2, $3); IF expr IS NULL THEN RETURN ok( false, $5 ) || E'\n' || diag( 'Index ' || quote_ident($3) || ' ON ' || quote_ident($1) || '.' || quote_ident($2) || ' not found'); END IF; RETURN is( quote_ident($3) || ' ON ' || quote_ident($1) || '.' || quote_ident($2) || '(' || expr || ')', quote_ident($3) || ' ON ' || quote_ident($1) || '.' || quote_ident($2) || '(' || $4 || ')', $5 ); END; $$ LANGUAGE plpgsql; -- has_index( schema, table, index, columns/expression ) CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT has_index( $1, $2, $3, $4, 'Index ' || quote_ident($3) || ' should exist' ); $$ LANGUAGE sql; -- has_index( table, index, columns[], description ) CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME[], text ) RETURNS TEXT AS $$ DECLARE index_cols name[]; BEGIN index_cols := _ikeys($1, $2 ); IF index_cols IS NULL OR index_cols = '{}'::name[] THEN RETURN ok( false, $4 ) || E'\n' || diag( 'Index ' || quote_ident($2) || ' ON ' || quote_ident($1) || ' not found'); END IF; RETURN is( quote_ident($2) || ' ON ' || quote_ident($1) || '(' || _ident_array_to_string( index_cols, ', ' ) || ')', quote_ident($2) || ' ON ' || quote_ident($1) || '(' || _ident_array_to_string( $3, ', ' ) || ')', $4 ); END; $$ LANGUAGE plpgsql; -- has_index( table, index, columns[], description ) CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT has_index( $1, $2, $3, 'Index ' || quote_ident($2) || ' should exist' ); $$ LANGUAGE sql; -- _is_schema( schema ) CREATE OR REPLACE FUNCTION _is_schema( NAME ) returns boolean AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_namespace WHERE nspname = $1 ); $$ LANGUAGE sql; -- has_index( table, index, column/expression, description ) -- has_index( schema, table, index, column/expression ) CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME, text ) RETURNS TEXT AS $$ DECLARE want_expr text; descr text; have_expr text; idx name; tab text; BEGIN IF $3 NOT LIKE '%(%' THEN -- Not a functional index. IF _is_schema( $1 ) THEN -- Looking for schema.table index. RETURN ok ( _have_index( $1, $2, $3 ), $4); END IF; -- Looking for particular columns. RETURN has_index( $1, $2, ARRAY[$3], $4 ); END IF; -- Get the functional expression. IF _is_schema( $1 ) THEN -- Looking for an index within a schema. have_expr := _iexpr($1, $2, $3); want_expr := $4; descr := 'Index ' || quote_ident($3) || ' should exist'; idx := $3; tab := quote_ident($1) || '.' || quote_ident($2); ELSE -- Looking for an index without a schema spec. have_expr := _iexpr($1, $2); want_expr := $3; descr := $4; idx := $2; tab := quote_ident($1); END IF; IF have_expr IS NULL THEN RETURN ok( false, descr ) || E'\n' || diag( 'Index ' || idx || ' ON ' || tab || ' not found'); END IF; RETURN is( quote_ident(idx) || ' ON ' || tab || '(' || have_expr || ')', quote_ident(idx) || ' ON ' || tab || '(' || want_expr || ')', descr ); END; $$ LANGUAGE plpgsql; -- has_index( table, index, column/expression ) -- has_index( schema, table, index ) CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME ) RETURNS TEXT AS $$ BEGIN IF _is_schema($1) THEN -- ( schema, table, index ) RETURN ok( _have_index( $1, $2, $3 ), 'Index ' || quote_ident($3) || ' should exist' ); ELSE -- ( table, index, column/expression ) RETURN has_index( $1, $2, $3, 'Index ' || quote_ident($2) || ' should exist' ); END IF; END; $$ LANGUAGE plpgsql; -- has_index( table, index, description ) CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, text ) RETURNS TEXT AS $$ SELECT CASE WHEN $3 LIKE '%(%' THEN has_index( $1, $2, $3::name ) ELSE ok( _have_index( $1, $2 ), $3 ) END; $$ LANGUAGE sql; -- has_index( table, index ) CREATE OR REPLACE FUNCTION has_index ( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _have_index( $1, $2 ), 'Index ' || quote_ident($2) || ' should exist' ); $$ LANGUAGE sql; -- hasnt_index( schema, table, index, description ) CREATE OR REPLACE FUNCTION hasnt_index ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ BEGIN RETURN ok( NOT _have_index( $1, $2, $3 ), $4 ); END; $$ LANGUAGE plpgSQL; -- hasnt_index( schema, table, index ) CREATE OR REPLACE FUNCTION hasnt_index ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _have_index( $1, $2, $3 ), 'Index ' || quote_ident($3) || ' should not exist' ); $$ LANGUAGE SQL; -- hasnt_index( table, index, description ) CREATE OR REPLACE FUNCTION hasnt_index ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _have_index( $1, $2 ), $3 ); $$ LANGUAGE SQL; -- hasnt_index( table, index ) CREATE OR REPLACE FUNCTION hasnt_index ( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _have_index( $1, $2 ), 'Index ' || quote_ident($2) || ' should not exist' ); $$ LANGUAGE SQL; -- index_is_unique( schema, table, index, description ) CREATE OR REPLACE FUNCTION index_is_unique ( NAME, NAME, NAME, text ) RETURNS TEXT AS $$ DECLARE res boolean; BEGIN SELECT x.indisunique FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace WHERE ct.relname = $2 AND ci.relname = $3 AND n.nspname = $1 INTO res; RETURN ok( COALESCE(res, false), $4 ); END; $$ LANGUAGE plpgsql; -- index_is_unique( schema, table, index ) CREATE OR REPLACE FUNCTION index_is_unique ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT index_is_unique( $1, $2, $3, 'Index ' || quote_ident($3) || ' should be unique' ); $$ LANGUAGE sql; -- index_is_unique( table, index ) CREATE OR REPLACE FUNCTION index_is_unique ( NAME, NAME ) RETURNS TEXT AS $$ DECLARE res boolean; BEGIN SELECT x.indisunique FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid WHERE ct.relname = $1 AND ci.relname = $2 AND pg_catalog.pg_table_is_visible(ct.oid) INTO res; RETURN ok( COALESCE(res, false), 'Index ' || quote_ident($2) || ' should be unique' ); END; $$ LANGUAGE plpgsql; -- index_is_unique( index ) CREATE OR REPLACE FUNCTION index_is_unique ( NAME ) RETURNS TEXT AS $$ DECLARE res boolean; BEGIN SELECT x.indisunique FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid WHERE ci.relname = $1 AND pg_catalog.pg_table_is_visible(ct.oid) INTO res; RETURN ok( COALESCE(res, false), 'Index ' || quote_ident($1) || ' should be unique' ); END; $$ LANGUAGE plpgsql; -- index_is_primary( schema, table, index, description ) CREATE OR REPLACE FUNCTION index_is_primary ( NAME, NAME, NAME, text ) RETURNS TEXT AS $$ DECLARE res boolean; BEGIN SELECT x.indisprimary FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace WHERE ct.relname = $2 AND ci.relname = $3 AND n.nspname = $1 INTO res; RETURN ok( COALESCE(res, false), $4 ); END; $$ LANGUAGE plpgsql; -- index_is_primary( schema, table, index ) CREATE OR REPLACE FUNCTION index_is_primary ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT index_is_primary( $1, $2, $3, 'Index ' || quote_ident($3) || ' should be on a primary key' ); $$ LANGUAGE sql; -- index_is_primary( table, index ) CREATE OR REPLACE FUNCTION index_is_primary ( NAME, NAME ) RETURNS TEXT AS $$ DECLARE res boolean; BEGIN SELECT x.indisprimary FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid WHERE ct.relname = $1 AND ci.relname = $2 AND pg_catalog.pg_table_is_visible(ct.oid) INTO res; RETURN ok( COALESCE(res, false), 'Index ' || quote_ident($2) || ' should be on a primary key' ); END; $$ LANGUAGE plpgsql; -- index_is_primary( index ) CREATE OR REPLACE FUNCTION index_is_primary ( NAME ) RETURNS TEXT AS $$ DECLARE res boolean; BEGIN SELECT x.indisprimary FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid WHERE ci.relname = $1 AND pg_catalog.pg_table_is_visible(ct.oid) INTO res; RETURN ok( COALESCE(res, false), 'Index ' || quote_ident($1) || ' should be on a primary key' ); END; $$ LANGUAGE plpgsql; -- is_clustered( schema, table, index, description ) CREATE OR REPLACE FUNCTION is_clustered ( NAME, NAME, NAME, text ) RETURNS TEXT AS $$ DECLARE res boolean; BEGIN SELECT x.indisclustered FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace WHERE ct.relname = $2 AND ci.relname = $3 AND n.nspname = $1 INTO res; RETURN ok( COALESCE(res, false), $4 ); END; $$ LANGUAGE plpgsql; -- is_clustered( schema, table, index ) CREATE OR REPLACE FUNCTION is_clustered ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT is_clustered( $1, $2, $3, 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should be clustered on index ' || quote_ident($3) ); $$ LANGUAGE sql; -- is_clustered( table, index ) CREATE OR REPLACE FUNCTION is_clustered ( NAME, NAME ) RETURNS TEXT AS $$ DECLARE res boolean; BEGIN SELECT x.indisclustered FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid WHERE ct.relname = $1 AND ci.relname = $2 INTO res; RETURN ok( COALESCE(res, false), 'Table ' || quote_ident($1) || ' should be clustered on index ' || quote_ident($2) ); END; $$ LANGUAGE plpgsql; -- is_clustered( index ) CREATE OR REPLACE FUNCTION is_clustered ( NAME ) RETURNS TEXT AS $$ DECLARE res boolean; BEGIN SELECT x.indisclustered FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid WHERE ci.relname = $1 INTO res; RETURN ok( COALESCE(res, false), 'Table should be clustered on index ' || quote_ident($1) ); END; $$ LANGUAGE plpgsql; -- index_is_type( schema, table, index, type, description ) CREATE OR REPLACE FUNCTION index_is_type ( NAME, NAME, NAME, NAME, text ) RETURNS TEXT AS $$ DECLARE aname name; BEGIN SELECT am.amname FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace JOIN pg_catalog.pg_am am ON ci.relam = am.oid WHERE ct.relname = $2 AND ci.relname = $3 AND n.nspname = $1 INTO aname; return is( aname, $4, $5 ); END; $$ LANGUAGE plpgsql; -- index_is_type( schema, table, index, type ) CREATE OR REPLACE FUNCTION index_is_type ( NAME, NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT index_is_type( $1, $2, $3, $4, 'Index ' || quote_ident($3) || ' should be a ' || quote_ident($4) || ' index' ); $$ LANGUAGE SQL; -- index_is_type( table, index, type ) CREATE OR REPLACE FUNCTION index_is_type ( NAME, NAME, NAME ) RETURNS TEXT AS $$ DECLARE aname name; BEGIN SELECT am.amname FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_am am ON ci.relam = am.oid WHERE ct.relname = $1 AND ci.relname = $2 INTO aname; return is( aname, $3, 'Index ' || quote_ident($2) || ' should be a ' || quote_ident($3) || ' index' ); END; $$ LANGUAGE plpgsql; -- index_is_type( index, type ) CREATE OR REPLACE FUNCTION index_is_type ( NAME, NAME ) RETURNS TEXT AS $$ DECLARE aname name; BEGIN SELECT am.amname FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_am am ON ci.relam = am.oid WHERE ci.relname = $1 INTO aname; return is( aname, $2, 'Index ' || quote_ident($1) || ' should be a ' || quote_ident($2) || ' index' ); END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _trig ( NAME, NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = $1 AND c.relname = $2 AND t.tgname = $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _trig ( NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid WHERE c.relname = $1 AND t.tgname = $2 ); $$ LANGUAGE SQL; -- has_trigger( schema, table, trigger, description ) CREATE OR REPLACE FUNCTION has_trigger ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _trig($1, $2, $3), $4); $$ LANGUAGE SQL; -- has_trigger( schema, table, trigger ) CREATE OR REPLACE FUNCTION has_trigger ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT has_trigger( $1, $2, $3, 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should have trigger ' || quote_ident($3) ); $$ LANGUAGE sql; -- has_trigger( table, trigger, description ) CREATE OR REPLACE FUNCTION has_trigger ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _trig($1, $2), $3); $$ LANGUAGE sql; -- has_trigger( table, trigger ) CREATE OR REPLACE FUNCTION has_trigger ( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _trig($1, $2), 'Table ' || quote_ident($1) || ' should have trigger ' || quote_ident($2)); $$ LANGUAGE SQL; -- hasnt_trigger( schema, table, trigger, description ) CREATE OR REPLACE FUNCTION hasnt_trigger ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _trig($1, $2, $3), $4); $$ LANGUAGE SQL; -- hasnt_trigger( schema, table, trigger ) CREATE OR REPLACE FUNCTION hasnt_trigger ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _trig($1, $2, $3), 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should not have trigger ' || quote_ident($3) ); $$ LANGUAGE sql; -- hasnt_trigger( table, trigger, description ) CREATE OR REPLACE FUNCTION hasnt_trigger ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _trig($1, $2), $3); $$ LANGUAGE sql; -- hasnt_trigger( table, trigger ) CREATE OR REPLACE FUNCTION hasnt_trigger ( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _trig($1, $2), 'Table ' || quote_ident($1) || ' should not have trigger ' || quote_ident($2)); $$ LANGUAGE SQL; -- trigger_is( schema, table, trigger, schema, function, description ) CREATE OR REPLACE FUNCTION trigger_is ( NAME, NAME, NAME, NAME, NAME, text ) RETURNS TEXT AS $$ DECLARE pname text; BEGIN SELECT quote_ident(ni.nspname) || '.' || quote_ident(p.proname) FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class ct ON ct.oid = t.tgrelid JOIN pg_catalog.pg_namespace nt ON nt.oid = ct.relnamespace JOIN pg_catalog.pg_proc p ON p.oid = t.tgfoid JOIN pg_catalog.pg_namespace ni ON ni.oid = p.pronamespace WHERE nt.nspname = $1 AND ct.relname = $2 AND t.tgname = $3 INTO pname; RETURN is( pname, quote_ident($4) || '.' || quote_ident($5), $6 ); END; $$ LANGUAGE plpgsql; -- trigger_is( schema, table, trigger, schema, function ) CREATE OR REPLACE FUNCTION trigger_is ( NAME, NAME, NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT trigger_is( $1, $2, $3, $4, $5, 'Trigger ' || quote_ident($3) || ' should call ' || quote_ident($4) || '.' || quote_ident($5) || '()' ); $$ LANGUAGE sql; -- trigger_is( table, trigger, function, description ) CREATE OR REPLACE FUNCTION trigger_is ( NAME, NAME, NAME, text ) RETURNS TEXT AS $$ DECLARE pname text; BEGIN SELECT p.proname FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class ct ON ct.oid = t.tgrelid JOIN pg_catalog.pg_proc p ON p.oid = t.tgfoid WHERE ct.relname = $1 AND t.tgname = $2 AND pg_catalog.pg_table_is_visible(ct.oid) INTO pname; RETURN is( pname, $3::text, $4 ); END; $$ LANGUAGE plpgsql; -- trigger_is( table, trigger, function ) CREATE OR REPLACE FUNCTION trigger_is ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT trigger_is( $1, $2, $3, 'Trigger ' || quote_ident($2) || ' should call ' || quote_ident($3) || '()' ); $$ LANGUAGE sql; -- has_schema( schema, description ) CREATE OR REPLACE FUNCTION has_schema( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( EXISTS( SELECT true FROM pg_catalog.pg_namespace WHERE nspname = $1 ), $2 ); $$ LANGUAGE sql; -- has_schema( schema ) CREATE OR REPLACE FUNCTION has_schema( NAME ) RETURNS TEXT AS $$ SELECT has_schema( $1, 'Schema ' || quote_ident($1) || ' should exist' ); $$ LANGUAGE sql; -- hasnt_schema( schema, description ) CREATE OR REPLACE FUNCTION hasnt_schema( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT EXISTS( SELECT true FROM pg_catalog.pg_namespace WHERE nspname = $1 ), $2 ); $$ LANGUAGE sql; -- hasnt_schema( schema ) CREATE OR REPLACE FUNCTION hasnt_schema( NAME ) RETURNS TEXT AS $$ SELECT hasnt_schema( $1, 'Schema ' || quote_ident($1) || ' should not exist' ); $$ LANGUAGE sql; -- has_tablespace( tablespace, location, description ) CREATE OR REPLACE FUNCTION has_tablespace( NAME, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT ok( EXISTS( SELECT true FROM pg_catalog.pg_tablespace WHERE spcname = $1 AND spclocation = $2 ), $3 ); $$ LANGUAGE sql; -- has_tablespace( tablespace, description ) CREATE OR REPLACE FUNCTION has_tablespace( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( EXISTS( SELECT true FROM pg_catalog.pg_tablespace WHERE spcname = $1 ), $2 ); $$ LANGUAGE sql; -- has_tablespace( tablespace ) CREATE OR REPLACE FUNCTION has_tablespace( NAME ) RETURNS TEXT AS $$ SELECT has_tablespace( $1, 'Tablespace ' || quote_ident($1) || ' should exist' ); $$ LANGUAGE sql; -- hasnt_tablespace( tablespace, description ) CREATE OR REPLACE FUNCTION hasnt_tablespace( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT EXISTS( SELECT true FROM pg_catalog.pg_tablespace WHERE spcname = $1 ), $2 ); $$ LANGUAGE sql; -- hasnt_tablespace( tablespace ) CREATE OR REPLACE FUNCTION hasnt_tablespace( NAME ) RETURNS TEXT AS $$ SELECT hasnt_tablespace( $1, 'Tablespace ' || quote_ident($1) || ' should not exist' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _has_type( NAME, NAME, CHAR[] ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid WHERE t.typisdefined AND n.nspname = $1 AND t.typname = $2 AND t.typtype = ANY( COALESCE($3, ARRAY['b', 'c', 'd', 'p', 'e']) ) ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _has_type( NAME, CHAR[] ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_type t WHERE t.typisdefined AND pg_catalog.pg_type_is_visible(t.oid) AND t.typname = $1 AND t.typtype = ANY( COALESCE($2, ARRAY['b', 'c', 'd', 'p', 'e']) ) ); $$ LANGUAGE sql; -- has_type( schema, type, description ) CREATE OR REPLACE FUNCTION has_type( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _has_type( $1, $2, NULL ), $3 ); $$ LANGUAGE sql; -- has_type( schema, type ) CREATE OR REPLACE FUNCTION has_type( NAME, NAME ) RETURNS TEXT AS $$ SELECT has_type( $1, $2, 'Type ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' ); $$ LANGUAGE sql; -- has_type( type, description ) CREATE OR REPLACE FUNCTION has_type( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _has_type( $1, NULL ), $2 ); $$ LANGUAGE sql; -- has_type( type ) CREATE OR REPLACE FUNCTION has_type( NAME ) RETURNS TEXT AS $$ SELECT ok( _has_type( $1, NULL ), ('Type ' || quote_ident($1) || ' should exist')::text ); $$ LANGUAGE sql; -- hasnt_type( schema, type, description ) CREATE OR REPLACE FUNCTION hasnt_type( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _has_type( $1, $2, NULL ), $3 ); $$ LANGUAGE sql; -- hasnt_type( schema, type ) CREATE OR REPLACE FUNCTION hasnt_type( NAME, NAME ) RETURNS TEXT AS $$ SELECT hasnt_type( $1, $2, 'Type ' || quote_ident($1) || '.' || quote_ident($2) || ' should not exist' ); $$ LANGUAGE sql; -- hasnt_type( type, description ) CREATE OR REPLACE FUNCTION hasnt_type( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _has_type( $1, NULL ), $2 ); $$ LANGUAGE sql; -- hasnt_type( type ) CREATE OR REPLACE FUNCTION hasnt_type( NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _has_type( $1, NULL ), ('Type ' || quote_ident($1) || ' should not exist')::text ); $$ LANGUAGE sql; -- has_domain( schema, domain, description ) CREATE OR REPLACE FUNCTION has_domain( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _has_type( $1, $2, ARRAY['d'] ), $3 ); $$ LANGUAGE sql; -- has_domain( schema, domain ) CREATE OR REPLACE FUNCTION has_domain( NAME, NAME ) RETURNS TEXT AS $$ SELECT has_domain( $1, $2, 'Domain ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' ); $$ LANGUAGE sql; -- has_domain( domain, description ) CREATE OR REPLACE FUNCTION has_domain( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _has_type( $1, ARRAY['d'] ), $2 ); $$ LANGUAGE sql; -- has_domain( domain ) CREATE OR REPLACE FUNCTION has_domain( NAME ) RETURNS TEXT AS $$ SELECT ok( _has_type( $1, ARRAY['d'] ), ('Domain ' || quote_ident($1) || ' should exist')::text ); $$ LANGUAGE sql; -- hasnt_domain( schema, domain, description ) CREATE OR REPLACE FUNCTION hasnt_domain( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _has_type( $1, $2, ARRAY['d'] ), $3 ); $$ LANGUAGE sql; -- hasnt_domain( schema, domain ) CREATE OR REPLACE FUNCTION hasnt_domain( NAME, NAME ) RETURNS TEXT AS $$ SELECT hasnt_domain( $1, $2, 'Domain ' || quote_ident($1) || '.' || quote_ident($2) || ' should not exist' ); $$ LANGUAGE sql; -- hasnt_domain( domain, description ) CREATE OR REPLACE FUNCTION hasnt_domain( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _has_type( $1, ARRAY['d'] ), $2 ); $$ LANGUAGE sql; -- hasnt_domain( domain ) CREATE OR REPLACE FUNCTION hasnt_domain( NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _has_type( $1, ARRAY['d'] ), ('Domain ' || quote_ident($1) || ' should not exist')::text ); $$ LANGUAGE sql; -- has_enum( schema, enum, description ) CREATE OR REPLACE FUNCTION has_enum( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _has_type( $1, $2, ARRAY['e'] ), $3 ); $$ LANGUAGE sql; -- has_enum( schema, enum ) CREATE OR REPLACE FUNCTION has_enum( NAME, NAME ) RETURNS TEXT AS $$ SELECT has_enum( $1, $2, 'Enum ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' ); $$ LANGUAGE sql; -- has_enum( enum, description ) CREATE OR REPLACE FUNCTION has_enum( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _has_type( $1, ARRAY['e'] ), $2 ); $$ LANGUAGE sql; -- has_enum( enum ) CREATE OR REPLACE FUNCTION has_enum( NAME ) RETURNS TEXT AS $$ SELECT ok( _has_type( $1, ARRAY['e'] ), ('Enum ' || quote_ident($1) || ' should exist')::text ); $$ LANGUAGE sql; -- hasnt_enum( schema, enum, description ) CREATE OR REPLACE FUNCTION hasnt_enum( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _has_type( $1, $2, ARRAY['e'] ), $3 ); $$ LANGUAGE sql; -- hasnt_enum( schema, enum ) CREATE OR REPLACE FUNCTION hasnt_enum( NAME, NAME ) RETURNS TEXT AS $$ SELECT hasnt_enum( $1, $2, 'Enum ' || quote_ident($1) || '.' || quote_ident($2) || ' should not exist' ); $$ LANGUAGE sql; -- hasnt_enum( enum, description ) CREATE OR REPLACE FUNCTION hasnt_enum( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _has_type( $1, ARRAY['e'] ), $2 ); $$ LANGUAGE sql; -- hasnt_enum( enum ) CREATE OR REPLACE FUNCTION hasnt_enum( NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _has_type( $1, ARRAY['e'] ), ('Enum ' || quote_ident($1) || ' should not exist')::text ); $$ LANGUAGE sql; -- enum_has_labels( schema, enum, labels, description ) CREATE OR REPLACE FUNCTION enum_has_labels( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT is( ARRAY( SELECT e.enumlabel FROM pg_catalog.pg_type t JOIN pg_catalog.pg_enum e ON t.oid = e.enumtypid JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid WHERE t.typisdefined AND n.nspname = $1 AND t.typname = $2 AND t.typtype = 'e' ORDER BY e.oid ), $3, $4 ); $$ LANGUAGE sql; -- enum_has_labels( schema, enum, labels ) CREATE OR REPLACE FUNCTION enum_has_labels( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT enum_has_labels( $1, $2, $3, 'Enum ' || quote_ident($1) || '.' || quote_ident($2) || ' should have labels (' || array_to_string( $3, ', ' ) || ')' ); $$ LANGUAGE sql; -- enum_has_labels( enum, labels, description ) CREATE OR REPLACE FUNCTION enum_has_labels( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT is( ARRAY( SELECT e.enumlabel FROM pg_catalog.pg_type t JOIN pg_catalog.pg_enum e ON t.oid = e.enumtypid WHERE t.typisdefined AND pg_catalog.pg_type_is_visible(t.oid) AND t.typname = $1 AND t.typtype = 'e' ORDER BY e.oid ), $2, $3 ); $$ LANGUAGE sql; -- enum_has_labels( enum, labels ) CREATE OR REPLACE FUNCTION enum_has_labels( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT enum_has_labels( $1, $2, 'Enum ' || quote_ident($1) || ' should have labels (' || array_to_string( $2, ', ' ) || ')' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _has_role( NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_roles WHERE rolname = $1 ); $$ LANGUAGE sql STRICT; -- has_role( role, description ) CREATE OR REPLACE FUNCTION has_role( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _has_role($1), $2 ); $$ LANGUAGE sql; -- has_role( role ) CREATE OR REPLACE FUNCTION has_role( NAME ) RETURNS TEXT AS $$ SELECT ok( _has_role($1), 'Role ' || quote_ident($1) || ' should exist' ); $$ LANGUAGE sql; -- hasnt_role( role, description ) CREATE OR REPLACE FUNCTION hasnt_role( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _has_role($1), $2 ); $$ LANGUAGE sql; -- hasnt_role( role ) CREATE OR REPLACE FUNCTION hasnt_role( NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _has_role($1), 'Role ' || quote_ident($1) || ' should not exist' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _has_user( NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_user WHERE usename = $1); $$ LANGUAGE sql STRICT; -- has_user( user, description ) CREATE OR REPLACE FUNCTION has_user( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _has_user($1), $2 ); $$ LANGUAGE sql; -- has_user( user ) CREATE OR REPLACE FUNCTION has_user( NAME ) RETURNS TEXT AS $$ SELECT ok( _has_user( $1 ), 'User ' || quote_ident($1) || ' should exist'); $$ LANGUAGE sql; -- hasnt_user( user, description ) CREATE OR REPLACE FUNCTION hasnt_user( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _has_user($1), $2 ); $$ LANGUAGE sql; -- hasnt_user( user ) CREATE OR REPLACE FUNCTION hasnt_user( NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _has_user( $1 ), 'User ' || quote_ident($1) || ' should not exist'); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _is_super( NAME ) RETURNS BOOLEAN AS $$ SELECT rolsuper FROM pg_catalog.pg_roles WHERE rolname = $1 $$ LANGUAGE sql STRICT; -- is_superuser( user, description ) CREATE OR REPLACE FUNCTION is_superuser( NAME, TEXT ) RETURNS TEXT AS $$ DECLARE is_super boolean := _is_super($1); BEGIN IF is_super IS NULL THEN RETURN fail( $2 ) || E'\n' || diag( ' User ' || quote_ident($1) || ' does not exist') ; END IF; RETURN ok( is_super, $2 ); END; $$ LANGUAGE plpgsql; -- is_superuser( user ) CREATE OR REPLACE FUNCTION is_superuser( NAME ) RETURNS TEXT AS $$ SELECT is_superuser( $1, 'User ' || quote_ident($1) || ' should be a super user' ); $$ LANGUAGE sql; -- isnt_superuser( user, description ) CREATE OR REPLACE FUNCTION isnt_superuser( NAME, TEXT ) RETURNS TEXT AS $$ DECLARE is_super boolean := _is_super($1); BEGIN IF is_super IS NULL THEN RETURN fail( $2 ) || E'\n' || diag( ' User ' || quote_ident($1) || ' does not exist') ; END IF; RETURN ok( NOT is_super, $2 ); END; $$ LANGUAGE plpgsql; -- isnt_superuser( user ) CREATE OR REPLACE FUNCTION isnt_superuser( NAME ) RETURNS TEXT AS $$ SELECT isnt_superuser( $1, 'User ' || quote_ident($1) || ' should not be a super user' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _has_group( NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_group WHERE groname = $1 ); $$ LANGUAGE sql STRICT; -- has_group( group, description ) CREATE OR REPLACE FUNCTION has_group( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _has_group($1), $2 ); $$ LANGUAGE sql; -- has_group( group ) CREATE OR REPLACE FUNCTION has_group( NAME ) RETURNS TEXT AS $$ SELECT ok( _has_group($1), 'Group ' || quote_ident($1) || ' should exist' ); $$ LANGUAGE sql; -- hasnt_group( group, description ) CREATE OR REPLACE FUNCTION hasnt_group( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _has_group($1), $2 ); $$ LANGUAGE sql; -- hasnt_group( group ) CREATE OR REPLACE FUNCTION hasnt_group( NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _has_group($1), 'Group ' || quote_ident($1) || ' should not exist' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _grolist ( NAME ) RETURNS oid[] AS $$ SELECT ARRAY( SELECT member FROM pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles r ON m.roleid = r.oid WHERE r.rolname = $1 ); $$ LANGUAGE sql; -- is_member_of( group, user[], description ) CREATE OR REPLACE FUNCTION is_member_of( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ DECLARE missing text[]; BEGIN IF NOT _has_role($1) THEN RETURN fail( $3 ) || E'\n' || diag ( ' Role ' || quote_ident($1) || ' does not exist' ); END IF; SELECT ARRAY( SELECT quote_ident($2[i]) FROM generate_series(1, array_upper($2, 1)) s(i) LEFT JOIN pg_catalog.pg_user ON usename = $2[i] WHERE usesysid IS NULL OR NOT usesysid = ANY ( _grolist($1) ) ORDER BY s.i ) INTO missing; IF missing[1] IS NULL THEN RETURN ok( true, $3 ); END IF; RETURN ok( false, $3 ) || E'\n' || diag( ' Users missing from the ' || quote_ident($1) || E' group:\n ' || array_to_string( missing, E'\n ') ); END; $$ LANGUAGE plpgsql; -- is_member_of( group, user, description ) CREATE OR REPLACE FUNCTION is_member_of( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT is_member_of( $1, ARRAY[$2], $3 ); $$ LANGUAGE SQL; -- is_member_of( group, user[] ) CREATE OR REPLACE FUNCTION is_member_of( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT is_member_of( $1, $2, 'Should have members of group ' || quote_ident($1) ); $$ LANGUAGE SQL; -- is_member_of( group, user ) CREATE OR REPLACE FUNCTION is_member_of( NAME, NAME ) RETURNS TEXT AS $$ SELECT is_member_of( $1, ARRAY[$2] ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _cmp_types(oid, name) RETURNS BOOLEAN AS $$ DECLARE dtype TEXT := display_type($1, NULL); BEGIN RETURN dtype = _quote_ident_like($2, dtype); END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _cast_exists ( NAME, NAME, NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS ( SELECT TRUE FROM pg_catalog.pg_cast c JOIN pg_catalog.pg_proc p ON c.castfunc = p.oid JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid WHERE _cmp_types(castsource, $1) AND _cmp_types(casttarget, $2) AND n.nspname = $3 AND p.proname = $4 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _cast_exists ( NAME, NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS ( SELECT TRUE FROM pg_catalog.pg_cast c JOIN pg_catalog.pg_proc p ON c.castfunc = p.oid WHERE _cmp_types(castsource, $1) AND _cmp_types(casttarget, $2) AND p.proname = $3 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _cast_exists ( NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS ( SELECT TRUE FROM pg_catalog.pg_cast c WHERE _cmp_types(castsource, $1) AND _cmp_types(casttarget, $2) ); $$ LANGUAGE SQL; -- has_cast( source_type, target_type, schema, function, description ) CREATE OR REPLACE FUNCTION has_cast ( NAME, NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _cast_exists( $1, $2, $3, $4 ), $5 ); $$ LANGUAGE SQL; -- has_cast( source_type, target_type, schema, function ) CREATE OR REPLACE FUNCTION has_cast ( NAME, NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _cast_exists( $1, $2, $3, $4 ), 'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2) || ') WITH FUNCTION ' || quote_ident($3) || '.' || quote_ident($4) || '() should exist' ); $$ LANGUAGE SQL; -- has_cast( source_type, target_type, function, description ) CREATE OR REPLACE FUNCTION has_cast ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _cast_exists( $1, $2, $3 ), $4 ); $$ LANGUAGE SQL; -- has_cast( source_type, target_type, function ) CREATE OR REPLACE FUNCTION has_cast ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _cast_exists( $1, $2, $3 ), 'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2) || ') WITH FUNCTION ' || quote_ident($3) || '() should exist' ); $$ LANGUAGE SQL; -- has_cast( source_type, target_type, description ) CREATE OR REPLACE FUNCTION has_cast ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _cast_exists( $1, $2 ), $3 ); $$ LANGUAGE SQL; -- has_cast( source_type, target_type ) CREATE OR REPLACE FUNCTION has_cast ( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _cast_exists( $1, $2 ), 'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2) || ') should exist' ); $$ LANGUAGE SQL; -- hasnt_cast( source_type, target_type, schema, function, description ) CREATE OR REPLACE FUNCTION hasnt_cast ( NAME, NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _cast_exists( $1, $2, $3, $4 ), $5 ); $$ LANGUAGE SQL; -- hasnt_cast( source_type, target_type, schema, function ) CREATE OR REPLACE FUNCTION hasnt_cast ( NAME, NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _cast_exists( $1, $2, $3, $4 ), 'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2) || ') WITH FUNCTION ' || quote_ident($3) || '.' || quote_ident($4) || '() should not exist' ); $$ LANGUAGE SQL; -- hasnt_cast( source_type, target_type, function, description ) CREATE OR REPLACE FUNCTION hasnt_cast ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _cast_exists( $1, $2, $3 ), $4 ); $$ LANGUAGE SQL; -- hasnt_cast( source_type, target_type, function ) CREATE OR REPLACE FUNCTION hasnt_cast ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _cast_exists( $1, $2, $3 ), 'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2) || ') WITH FUNCTION ' || quote_ident($3) || '() should not exist' ); $$ LANGUAGE SQL; -- hasnt_cast( source_type, target_type, description ) CREATE OR REPLACE FUNCTION hasnt_cast ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _cast_exists( $1, $2 ), $3 ); $$ LANGUAGE SQL; -- hasnt_cast( source_type, target_type ) CREATE OR REPLACE FUNCTION hasnt_cast ( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _cast_exists( $1, $2 ), 'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2) || ') should not exist' ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _expand_context( char ) RETURNS text AS $$ SELECT CASE $1 WHEN 'i' THEN 'implicit' WHEN 'a' THEN 'assignment' WHEN 'e' THEN 'explicit' ELSE 'unknown' END $$ LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION _get_context( NAME, NAME ) RETURNS "char" AS $$ SELECT c.castcontext FROM pg_catalog.pg_cast c WHERE _cmp_types(castsource, $1) AND _cmp_types(casttarget, $2) $$ LANGUAGE SQL; -- cast_context_is( source_type, target_type, context, description ) CREATE OR REPLACE FUNCTION cast_context_is( NAME, NAME, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE want char = substring(LOWER($3) FROM 1 FOR 1); have char := _get_context($1, $2); BEGIN IF have IS NOT NULL THEN RETURN is( _expand_context(have), _expand_context(want), $4 ); END IF; RETURN ok( false, $4 ) || E'\n' || diag( ' Cast (' || quote_ident($1) || ' AS ' || quote_ident($2) || ') does not exist' ); END; $$ LANGUAGE plpgsql; -- cast_context_is( source_type, target_type, context ) CREATE OR REPLACE FUNCTION cast_context_is( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT cast_context_is( $1, $2, $3, 'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2) || ') context should be ' || _expand_context(substring(LOWER($3) FROM 1 FOR 1)) ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _op_exists ( NAME, NAME, NAME, NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS ( SELECT TRUE FROM pg_catalog.pg_operator o JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid WHERE n.nspname = $2 AND o.oprname = $3 AND CASE o.oprkind WHEN 'l' THEN $1 IS NULL ELSE _cmp_types(o.oprleft, $1) END AND CASE o.oprkind WHEN 'r' THEN $4 IS NULL ELSE _cmp_types(o.oprright, $4) END AND _cmp_types(o.oprresult, $5) ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _op_exists ( NAME, NAME, NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS ( SELECT TRUE FROM pg_catalog.pg_operator o WHERE pg_catalog.pg_operator_is_visible(o.oid) AND o.oprname = $2 AND CASE o.oprkind WHEN 'l' THEN $1 IS NULL ELSE _cmp_types(o.oprleft, $1) END AND CASE o.oprkind WHEN 'r' THEN $3 IS NULL ELSE _cmp_types(o.oprright, $3) END AND _cmp_types(o.oprresult, $4) ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _op_exists ( NAME, NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS ( SELECT TRUE FROM pg_catalog.pg_operator o WHERE pg_catalog.pg_operator_is_visible(o.oid) AND o.oprname = $2 AND CASE o.oprkind WHEN 'l' THEN $1 IS NULL ELSE _cmp_types(o.oprleft, $1) END AND CASE o.oprkind WHEN 'r' THEN $3 IS NULL ELSE _cmp_types(o.oprright, $3) END ); $$ LANGUAGE SQL; -- has_operator( left_type, schema, name, right_type, return_type, description ) CREATE OR REPLACE FUNCTION has_operator ( NAME, NAME, NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _op_exists($1, $2, $3, $4, $5 ), $6 ); $$ LANGUAGE SQL; -- has_operator( left_type, schema, name, right_type, return_type ) CREATE OR REPLACE FUNCTION has_operator ( NAME, NAME, NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _op_exists($1, $2, $3, $4, $5 ), 'Operator ' || quote_ident($2) || '.' || $3 || '(' || $1 || ',' || $4 || ') RETURNS ' || $5 || ' should exist' ); $$ LANGUAGE SQL; -- has_operator( left_type, name, right_type, return_type, description ) CREATE OR REPLACE FUNCTION has_operator ( NAME, NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _op_exists($1, $2, $3, $4 ), $5 ); $$ LANGUAGE SQL; -- has_operator( left_type, name, right_type, return_type ) CREATE OR REPLACE FUNCTION has_operator ( NAME, NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _op_exists($1, $2, $3, $4 ), 'Operator ' || $2 || '(' || $1 || ',' || $3 || ') RETURNS ' || $4 || ' should exist' ); $$ LANGUAGE SQL; -- has_operator( left_type, name, right_type, description ) CREATE OR REPLACE FUNCTION has_operator ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _op_exists($1, $2, $3 ), $4 ); $$ LANGUAGE SQL; -- has_operator( left_type, name, right_type ) CREATE OR REPLACE FUNCTION has_operator ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _op_exists($1, $2, $3 ), 'Operator ' || $2 || '(' || $1 || ',' || $3 || ') should exist' ); $$ LANGUAGE SQL; -- has_leftop( schema, name, right_type, return_type, description ) CREATE OR REPLACE FUNCTION has_leftop ( NAME, NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _op_exists(NULL, $1, $2, $3, $4), $5 ); $$ LANGUAGE SQL; -- has_leftop( schema, name, right_type, return_type ) CREATE OR REPLACE FUNCTION has_leftop ( NAME, NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _op_exists(NULL, $1, $2, $3, $4 ), 'Left operator ' || quote_ident($1) || '.' || $2 || '(NONE,' || $3 || ') RETURNS ' || $4 || ' should exist' ); $$ LANGUAGE SQL; -- has_leftop( name, right_type, return_type, description ) CREATE OR REPLACE FUNCTION has_leftop ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _op_exists(NULL, $1, $2, $3), $4 ); $$ LANGUAGE SQL; -- has_leftop( name, right_type, return_type ) CREATE OR REPLACE FUNCTION has_leftop ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _op_exists(NULL, $1, $2, $3 ), 'Left operator ' || $1 || '(NONE,' || $2 || ') RETURNS ' || $3 || ' should exist' ); $$ LANGUAGE SQL; -- has_leftop( name, right_type, description ) CREATE OR REPLACE FUNCTION has_leftop ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _op_exists(NULL, $1, $2), $3 ); $$ LANGUAGE SQL; -- has_leftop( name, right_type ) CREATE OR REPLACE FUNCTION has_leftop ( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _op_exists(NULL, $1, $2 ), 'Left operator ' || $1 || '(NONE,' || $2 || ') should exist' ); $$ LANGUAGE SQL; -- has_rightop( left_type, schema, name, return_type, description ) CREATE OR REPLACE FUNCTION has_rightop ( NAME, NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _op_exists( $1, $2, $3, NULL, $4), $5 ); $$ LANGUAGE SQL; -- has_rightop( left_type, schema, name, return_type ) CREATE OR REPLACE FUNCTION has_rightop ( NAME, NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _op_exists($1, $2, $3, NULL, $4 ), 'Right operator ' || quote_ident($2) || '.' || $3 || '(' || $1 || ',NONE) RETURNS ' || $4 || ' should exist' ); $$ LANGUAGE SQL; -- has_rightop( left_type, name, return_type, description ) CREATE OR REPLACE FUNCTION has_rightop ( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _op_exists( $1, $2, NULL, $3), $4 ); $$ LANGUAGE SQL; -- has_rightop( left_type, name, return_type ) CREATE OR REPLACE FUNCTION has_rightop ( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _op_exists($1, $2, NULL, $3 ), 'Right operator ' || $2 || '(' || $1 || ',NONE) RETURNS ' || $3 || ' should exist' ); $$ LANGUAGE SQL; -- has_rightop( left_type, name, description ) CREATE OR REPLACE FUNCTION has_rightop ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _op_exists( $1, $2, NULL), $3 ); $$ LANGUAGE SQL; -- has_rightop( left_type, name ) CREATE OR REPLACE FUNCTION has_rightop ( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _op_exists($1, $2, NULL ), 'Right operator ' || $2 || '(' || $1 || ',NONE) should exist' ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _are ( text, name[], name[], TEXT ) RETURNS TEXT AS $$ DECLARE what ALIAS FOR $1; extras ALIAS FOR $2; missing ALIAS FOR $3; descr ALIAS FOR $4; msg TEXT := ''; res BOOLEAN := TRUE; BEGIN IF extras[1] IS NOT NULL THEN res = FALSE; msg := E'\n' || diag( ' Extra ' || what || E':\n ' || _ident_array_to_string( extras, E'\n ' ) ); END IF; IF missing[1] IS NOT NULL THEN res = FALSE; msg := msg || E'\n' || diag( ' Missing ' || what || E':\n ' || _ident_array_to_string( missing, E'\n ' ) ); END IF; RETURN ok(res, descr) || msg; END; $$ LANGUAGE plpgsql; -- tablespaces_are( tablespaces, description ) CREATE OR REPLACE FUNCTION tablespaces_are ( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'tablespaces', ARRAY( SELECT spcname FROM pg_catalog.pg_tablespace EXCEPT SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) ), ARRAY( SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) EXCEPT SELECT spcname FROM pg_catalog.pg_tablespace ), $2 ); $$ LANGUAGE SQL; -- tablespaces_are( tablespaces ) CREATE OR REPLACE FUNCTION tablespaces_are ( NAME[] ) RETURNS TEXT AS $$ SELECT tablespaces_are( $1, 'There should be the correct tablespaces' ); $$ LANGUAGE SQL; -- schemas_are( schemas, description ) CREATE OR REPLACE FUNCTION schemas_are ( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'schemas', ARRAY( SELECT nspname FROM pg_catalog.pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname <> 'information_schema' EXCEPT SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) ), ARRAY( SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) EXCEPT SELECT nspname FROM pg_catalog.pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname <> 'information_schema' ), $2 ); $$ LANGUAGE SQL; -- schemas_are( schemas ) CREATE OR REPLACE FUNCTION schemas_are ( NAME[] ) RETURNS TEXT AS $$ SELECT schemas_are( $1, 'There should be the correct schemas' ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _extras ( CHAR, NAME, NAME[] ) RETURNS NAME[] AS $$ SELECT ARRAY( SELECT c.relname FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace WHERE c.relkind = $1 AND n.nspname = $2 AND c.relname NOT IN('pg_all_foreign_keys', 'tap_funky', '__tresults___numb_seq', '__tcache___id_seq') EXCEPT SELECT $3[i] FROM generate_series(1, array_upper($3, 1)) s(i) ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _extras ( CHAR, NAME[] ) RETURNS NAME[] AS $$ SELECT ARRAY( SELECT c.relname FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace WHERE pg_catalog.pg_table_is_visible(c.oid) AND n.nspname <> 'pg_catalog' AND c.relkind = $1 AND c.relname NOT IN ('__tcache__', '__tresults__', 'pg_all_foreign_keys', 'tap_funky', '__tresults___numb_seq', '__tcache___id_seq') EXCEPT SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _missing ( CHAR, NAME, NAME[] ) RETURNS NAME[] AS $$ SELECT ARRAY( SELECT $3[i] FROM generate_series(1, array_upper($3, 1)) s(i) EXCEPT SELECT c.relname FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace WHERE c.relkind = $1 AND n.nspname = $2 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _missing ( CHAR, NAME[] ) RETURNS NAME[] AS $$ SELECT ARRAY( SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) EXCEPT SELECT c.relname FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace WHERE pg_catalog.pg_table_is_visible(c.oid) AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND c.relkind = $1 ); $$ LANGUAGE SQL; -- tables_are( schema, tables, description ) CREATE OR REPLACE FUNCTION tables_are ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'tables', _extras('r', $1, $2), _missing('r', $1, $2), $3); $$ LANGUAGE SQL; -- tables_are( tables, description ) CREATE OR REPLACE FUNCTION tables_are ( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'tables', _extras('r', $1), _missing('r', $1), $2); $$ LANGUAGE SQL; -- tables_are( schema, tables ) CREATE OR REPLACE FUNCTION tables_are ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT _are( 'tables', _extras('r', $1, $2), _missing('r', $1, $2), 'Schema ' || quote_ident($1) || ' should have the correct tables' ); $$ LANGUAGE SQL; -- tables_are( tables ) CREATE OR REPLACE FUNCTION tables_are ( NAME[] ) RETURNS TEXT AS $$ SELECT _are( 'tables', _extras('r', $1), _missing('r', $1), 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct tables' ); $$ LANGUAGE SQL; -- views_are( schema, views, description ) CREATE OR REPLACE FUNCTION views_are ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'views', _extras('v', $1, $2), _missing('v', $1, $2), $3); $$ LANGUAGE SQL; -- views_are( views, description ) CREATE OR REPLACE FUNCTION views_are ( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'views', _extras('v', $1), _missing('v', $1), $2); $$ LANGUAGE SQL; -- views_are( schema, views ) CREATE OR REPLACE FUNCTION views_are ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT _are( 'views', _extras('v', $1, $2), _missing('v', $1, $2), 'Schema ' || quote_ident($1) || ' should have the correct views' ); $$ LANGUAGE SQL; -- views_are( views ) CREATE OR REPLACE FUNCTION views_are ( NAME[] ) RETURNS TEXT AS $$ SELECT _are( 'views', _extras('v', $1), _missing('v', $1), 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct views' ); $$ LANGUAGE SQL; -- sequences_are( schema, sequences, description ) CREATE OR REPLACE FUNCTION sequences_are ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'sequences', _extras('S', $1, $2), _missing('S', $1, $2), $3); $$ LANGUAGE SQL; -- sequences_are( sequences, description ) CREATE OR REPLACE FUNCTION sequences_are ( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'sequences', _extras('S', $1), _missing('S', $1), $2); $$ LANGUAGE SQL; -- sequences_are( schema, sequences ) CREATE OR REPLACE FUNCTION sequences_are ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT _are( 'sequences', _extras('S', $1, $2), _missing('S', $1, $2), 'Schema ' || quote_ident($1) || ' should have the correct sequences' ); $$ LANGUAGE SQL; -- sequences_are( sequences ) CREATE OR REPLACE FUNCTION sequences_are ( NAME[] ) RETURNS TEXT AS $$ SELECT _are( 'sequences', _extras('S', $1), _missing('S', $1), 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct sequences' ); $$ LANGUAGE SQL; -- functions_are( schema, functions[], description ) CREATE OR REPLACE FUNCTION functions_are ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'functions', ARRAY( SELECT name FROM tap_funky WHERE schema = $1 EXCEPT SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) ), ARRAY( SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) EXCEPT SELECT name FROM tap_funky WHERE schema = $1 ), $3 ); $$ LANGUAGE SQL; -- functions_are( schema, functions[] ) CREATE OR REPLACE FUNCTION functions_are ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT functions_are( $1, $2, 'Schema ' || quote_ident($1) || ' should have the correct functions' ); $$ LANGUAGE SQL; -- functions_are( functions[], description ) CREATE OR REPLACE FUNCTION functions_are ( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'functions', ARRAY( SELECT name FROM tap_funky WHERE is_visible AND schema NOT IN ('pg_catalog', 'information_schema') EXCEPT SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) ), ARRAY( SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) EXCEPT SELECT name FROM tap_funky WHERE is_visible AND schema NOT IN ('pg_catalog', 'information_schema') ), $2 ); $$ LANGUAGE SQL; -- functions_are( functions[] ) CREATE OR REPLACE FUNCTION functions_are ( NAME[] ) RETURNS TEXT AS $$ SELECT functions_are( $1, 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct functions' ); $$ LANGUAGE SQL; -- indexes_are( schema, table, indexes[], description ) CREATE OR REPLACE FUNCTION indexes_are( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'indexes', ARRAY( SELECT ci.relname FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace WHERE ct.relname = $2 AND n.nspname = $1 EXCEPT SELECT $3[i] FROM generate_series(1, array_upper($3, 1)) s(i) ), ARRAY( SELECT $3[i] FROM generate_series(1, array_upper($3, 1)) s(i) EXCEPT SELECT ci.relname FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace WHERE ct.relname = $2 AND n.nspname = $1 ), $4 ); $$ LANGUAGE SQL; -- indexes_are( schema, table, indexes[] ) CREATE OR REPLACE FUNCTION indexes_are( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT indexes_are( $1, $2, $3, 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should have the correct indexes' ); $$ LANGUAGE SQL; -- indexes_are( table, indexes[], description ) CREATE OR REPLACE FUNCTION indexes_are( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'indexes', ARRAY( SELECT ci.relname FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace WHERE ct.relname = $1 AND pg_catalog.pg_table_is_visible(ct.oid) AND n.nspname NOT IN ('pg_catalog', 'information_schema') EXCEPT SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) ), ARRAY( SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) EXCEPT SELECT ci.relname FROM pg_catalog.pg_index x JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace WHERE ct.relname = $1 AND pg_catalog.pg_table_is_visible(ct.oid) AND n.nspname NOT IN ('pg_catalog', 'information_schema') ), $3 ); $$ LANGUAGE SQL; -- indexes_are( table, indexes[] ) CREATE OR REPLACE FUNCTION indexes_are( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT indexes_are( $1, $2, 'Table ' || quote_ident($1) || ' should have the correct indexes' ); $$ LANGUAGE SQL; -- users_are( users[], description ) CREATE OR REPLACE FUNCTION users_are( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'users', ARRAY( SELECT usename FROM pg_catalog.pg_user EXCEPT SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) ), ARRAY( SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) EXCEPT SELECT usename FROM pg_catalog.pg_user ), $2 ); $$ LANGUAGE SQL; -- users_are( users[] ) CREATE OR REPLACE FUNCTION users_are( NAME[] ) RETURNS TEXT AS $$ SELECT users_are( $1, 'There should be the correct users' ); $$ LANGUAGE SQL; -- groups_are( groups[], description ) CREATE OR REPLACE FUNCTION groups_are( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'groups', ARRAY( SELECT groname FROM pg_catalog.pg_group EXCEPT SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) ), ARRAY( SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) EXCEPT SELECT groname FROM pg_catalog.pg_group ), $2 ); $$ LANGUAGE SQL; -- groups_are( groups[] ) CREATE OR REPLACE FUNCTION groups_are( NAME[] ) RETURNS TEXT AS $$ SELECT groups_are( $1, 'There should be the correct groups' ); $$ LANGUAGE SQL; -- languages_are( languages[], description ) CREATE OR REPLACE FUNCTION languages_are( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'languages', ARRAY( SELECT lanname FROM pg_catalog.pg_language WHERE lanispl EXCEPT SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) ), ARRAY( SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) EXCEPT SELECT lanname FROM pg_catalog.pg_language WHERE lanispl ), $2 ); $$ LANGUAGE SQL; -- languages_are( languages[] ) CREATE OR REPLACE FUNCTION languages_are( NAME[] ) RETURNS TEXT AS $$ SELECT languages_are( $1, 'There should be the correct procedural languages' ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _is_trusted( NAME ) RETURNS BOOLEAN AS $$ SELECT lanpltrusted FROM pg_catalog.pg_language WHERE lanname = $1; $$ LANGUAGE SQL; -- has_language( language, description) CREATE OR REPLACE FUNCTION has_language( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _is_trusted($1) IS NOT NULL, $2 ); $$ LANGUAGE SQL; -- has_language( language ) CREATE OR REPLACE FUNCTION has_language( NAME ) RETURNS TEXT AS $$ SELECT ok( _is_trusted($1) IS NOT NULL, 'Procedural language ' || quote_ident($1) || ' should exist' ); $$ LANGUAGE SQL; -- hasnt_language( language, description) CREATE OR REPLACE FUNCTION hasnt_language( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _is_trusted($1) IS NULL, $2 ); $$ LANGUAGE SQL; -- hasnt_language( language ) CREATE OR REPLACE FUNCTION hasnt_language( NAME ) RETURNS TEXT AS $$ SELECT ok( _is_trusted($1) IS NULL, 'Procedural language ' || quote_ident($1) || ' should not exist' ); $$ LANGUAGE SQL; -- language_is_trusted( language, description ) CREATE OR REPLACE FUNCTION language_is_trusted( NAME, TEXT ) RETURNS TEXT AS $$ DECLARE is_trusted boolean := _is_trusted($1); BEGIN IF is_trusted IS NULL THEN RETURN fail( $2 ) || E'\n' || diag( ' Procedural language ' || quote_ident($1) || ' does not exist') ; END IF; RETURN ok( is_trusted, $2 ); END; $$ LANGUAGE plpgsql; -- language_is_trusted( language ) CREATE OR REPLACE FUNCTION language_is_trusted( NAME ) RETURNS TEXT AS $$ SELECT language_is_trusted($1, 'Procedural language ' || quote_ident($1) || ' should be trusted' ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _opc_exists( NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS ( SELECT TRUE FROM pg_catalog.pg_opclass oc JOIN pg_catalog.pg_namespace n ON oc.opcnamespace = n.oid WHERE n.nspname = COALESCE($1, n.nspname) AND oc.opcname = $2 ); $$ LANGUAGE SQL; -- has_opclass( schema, name, description ) CREATE OR REPLACE FUNCTION has_opclass( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _opc_exists( $1, $2 ), $3 ); $$ LANGUAGE SQL; -- has_opclass( schema, name ) CREATE OR REPLACE FUNCTION has_opclass( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _opc_exists( $1, $2 ), 'Operator class ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' ); $$ LANGUAGE SQL; -- has_opclass( name, description ) CREATE OR REPLACE FUNCTION has_opclass( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _opc_exists( NULL, $1 ), $2) $$ LANGUAGE SQL; -- has_opclass( name ) CREATE OR REPLACE FUNCTION has_opclass( NAME ) RETURNS TEXT AS $$ SELECT ok( _opc_exists( NULL, $1 ), 'Operator class ' || quote_ident($1) || ' should exist' ); $$ LANGUAGE SQL; -- hasnt_opclass( schema, name, description ) CREATE OR REPLACE FUNCTION hasnt_opclass( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _opc_exists( $1, $2 ), $3 ); $$ LANGUAGE SQL; -- hasnt_opclass( schema, name ) CREATE OR REPLACE FUNCTION hasnt_opclass( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _opc_exists( $1, $2 ), 'Operator class ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' ); $$ LANGUAGE SQL; -- hasnt_opclass( name, description ) CREATE OR REPLACE FUNCTION hasnt_opclass( NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( NOT _opc_exists( NULL, $1 ), $2) $$ LANGUAGE SQL; -- hasnt_opclass( name ) CREATE OR REPLACE FUNCTION hasnt_opclass( NAME ) RETURNS TEXT AS $$ SELECT ok( NOT _opc_exists( NULL, $1 ), 'Operator class ' || quote_ident($1) || ' should exist' ); $$ LANGUAGE SQL; -- opclasses_are( schema, opclasses[], description ) CREATE OR REPLACE FUNCTION opclasses_are ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'operator classes', ARRAY( SELECT oc.opcname FROM pg_catalog.pg_opclass oc JOIN pg_catalog.pg_namespace n ON oc.opcnamespace = n.oid WHERE n.nspname = $1 EXCEPT SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) ), ARRAY( SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) EXCEPT SELECT oc.opcname FROM pg_catalog.pg_opclass oc JOIN pg_catalog.pg_namespace n ON oc.opcnamespace = n.oid WHERE n.nspname = $1 ), $3 ); $$ LANGUAGE SQL; -- opclasses_are( schema, opclasses[] ) CREATE OR REPLACE FUNCTION opclasses_are ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT opclasses_are( $1, $2, 'Schema ' || quote_ident($1) || ' should have the correct operator classes' ); $$ LANGUAGE SQL; -- opclasses_are( opclasses[], description ) CREATE OR REPLACE FUNCTION opclasses_are ( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'operator classes', ARRAY( SELECT oc.opcname FROM pg_catalog.pg_opclass oc JOIN pg_catalog.pg_namespace n ON oc.opcnamespace = n.oid AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND pg_catalog.pg_opclass_is_visible(oc.oid) EXCEPT SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) ), ARRAY( SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) EXCEPT SELECT oc.opcname FROM pg_catalog.pg_opclass oc JOIN pg_catalog.pg_namespace n ON oc.opcnamespace = n.oid AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND pg_catalog.pg_opclass_is_visible(oc.oid) ), $2 ); $$ LANGUAGE SQL; -- opclasses_are( opclasses[] ) CREATE OR REPLACE FUNCTION opclasses_are ( NAME[] ) RETURNS TEXT AS $$ SELECT opclasses_are( $1, 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct operator classes' ); $$ LANGUAGE SQL; -- rules_are( schema, table, rules[], description ) CREATE OR REPLACE FUNCTION rules_are( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'rules', ARRAY( SELECT r.rulename FROM pg_catalog.pg_rewrite r JOIN pg_catalog.pg_class c ON c.oid = r.ev_class JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid WHERE c.relname = $2 AND n.nspname = $1 EXCEPT SELECT $3[i] FROM generate_series(1, array_upper($3, 1)) s(i) ), ARRAY( SELECT $3[i] FROM generate_series(1, array_upper($3, 1)) s(i) EXCEPT SELECT r.rulename FROM pg_catalog.pg_rewrite r JOIN pg_catalog.pg_class c ON c.oid = r.ev_class JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid WHERE c.relname = $2 AND n.nspname = $1 ), $4 ); $$ LANGUAGE SQL; -- rules_are( schema, table, rules[] ) CREATE OR REPLACE FUNCTION rules_are( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT rules_are( $1, $2, $3, 'Relation ' || quote_ident($1) || '.' || quote_ident($2) || ' should have the correct rules' ); $$ LANGUAGE SQL; -- rules_are( table, rules[], description ) CREATE OR REPLACE FUNCTION rules_are( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'rules', ARRAY( SELECT r.rulename FROM pg_catalog.pg_rewrite r JOIN pg_catalog.pg_class c ON c.oid = r.ev_class JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid WHERE c.relname = $1 AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND pg_catalog.pg_table_is_visible(c.oid) EXCEPT SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) ), ARRAY( SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) EXCEPT SELECT r.rulename FROM pg_catalog.pg_rewrite r JOIN pg_catalog.pg_class c ON c.oid = r.ev_class JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid AND c.relname = $1 AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND pg_catalog.pg_table_is_visible(c.oid) ), $3 ); $$ LANGUAGE SQL; -- rules_are( table, rules[] ) CREATE OR REPLACE FUNCTION rules_are( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT rules_are( $1, $2, 'Relation ' || quote_ident($1) || ' should have the correct rules' ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _is_instead( NAME, NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT r.is_instead FROM pg_catalog.pg_rewrite r JOIN pg_catalog.pg_class c ON c.oid = r.ev_class JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid WHERE r.rulename = $3 AND c.relname = $2 AND n.nspname = $1 $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _is_instead( NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT r.is_instead FROM pg_catalog.pg_rewrite r JOIN pg_catalog.pg_class c ON c.oid = r.ev_class WHERE r.rulename = $2 AND c.relname = $1 AND pg_catalog.pg_table_is_visible(c.oid) $$ LANGUAGE SQL; -- has_rule( schema, table, rule, description ) CREATE OR REPLACE FUNCTION has_rule( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _is_instead($1, $2, $3) IS NOT NULL, $4 ); $$ LANGUAGE SQL; -- has_rule( schema, table, rule ) CREATE OR REPLACE FUNCTION has_rule( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _is_instead($1, $2, $3) IS NOT NULL, 'Relation ' || quote_ident($1) || '.' || quote_ident($2) || ' should have rule ' || quote_ident($3) ); $$ LANGUAGE SQL; -- has_rule( table, rule, description ) CREATE OR REPLACE FUNCTION has_rule( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _is_instead($1, $2) IS NOT NULL, $3 ); $$ LANGUAGE SQL; -- has_rule( table, rule ) CREATE OR REPLACE FUNCTION has_rule( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _is_instead($1, $2) IS NOT NULL, 'Relation ' || quote_ident($1) || ' should have rule ' || quote_ident($2) ); $$ LANGUAGE SQL; -- hasnt_rule( schema, table, rule, description ) CREATE OR REPLACE FUNCTION hasnt_rule( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _is_instead($1, $2, $3) IS NULL, $4 ); $$ LANGUAGE SQL; -- hasnt_rule( schema, table, rule ) CREATE OR REPLACE FUNCTION hasnt_rule( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _is_instead($1, $2, $3) IS NULL, 'Relation ' || quote_ident($1) || '.' || quote_ident($2) || ' should not have rule ' || quote_ident($3) ); $$ LANGUAGE SQL; -- hasnt_rule( table, rule, description ) CREATE OR REPLACE FUNCTION hasnt_rule( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT ok( _is_instead($1, $2) IS NULL, $3 ); $$ LANGUAGE SQL; -- hasnt_rule( table, rule ) CREATE OR REPLACE FUNCTION hasnt_rule( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _is_instead($1, $2) IS NULL, 'Relation ' || quote_ident($1) || ' should not have rule ' || quote_ident($2) ); $$ LANGUAGE SQL; -- rule_is_instead( schema, table, rule, description ) CREATE OR REPLACE FUNCTION rule_is_instead( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ DECLARE is_it boolean := _is_instead($1, $2, $3); BEGIN IF is_it IS NOT NULL THEN RETURN ok( is_it, $4 ); END IF; RETURN ok( FALSE, $4 ) || E'\n' || diag( ' Rule ' || quote_ident($3) || ' does not exist' ); END; $$ LANGUAGE plpgsql; -- rule_is_instead( schema, table, rule ) CREATE OR REPLACE FUNCTION rule_is_instead( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT rule_is_instead( $1, $2, $3, 'Rule ' || quote_ident($3) || ' on relation ' || quote_ident($1) || '.' || quote_ident($2) || ' should be an INSTEAD rule' ); $$ LANGUAGE SQL; -- rule_is_instead( table, rule, description ) CREATE OR REPLACE FUNCTION rule_is_instead( NAME, NAME, TEXT ) RETURNS TEXT AS $$ DECLARE is_it boolean := _is_instead($1, $2); BEGIN IF is_it IS NOT NULL THEN RETURN ok( is_it, $3 ); END IF; RETURN ok( FALSE, $3 ) || E'\n' || diag( ' Rule ' || quote_ident($2) || ' does not exist' ); END; $$ LANGUAGE plpgsql; -- rule_is_instead( table, rule ) CREATE OR REPLACE FUNCTION rule_is_instead( NAME, NAME ) RETURNS TEXT AS $$ SELECT rule_is_instead($1, $2, 'Rule ' || quote_ident($2) || ' on relation ' || quote_ident($1) || ' should be an INSTEAD rule' ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _expand_on( char ) RETURNS text AS $$ SELECT CASE $1 WHEN '1' THEN 'SELECT' WHEN '2' THEN 'UPDATE' WHEN '3' THEN 'INSERT' WHEN '4' THEN 'DELETE' ELSE 'UNKNOWN' END $$ LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION _contract_on( TEXT ) RETURNS "char" AS $$ SELECT CASE substring(LOWER($1) FROM 1 FOR 1) WHEN 's' THEN '1'::"char" WHEN 'u' THEN '2'::"char" WHEN 'i' THEN '3'::"char" WHEN 'd' THEN '4'::"char" ELSE '0'::"char" END $$ LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION _rule_on( NAME, NAME, NAME ) RETURNS "char" AS $$ SELECT r.ev_type FROM pg_catalog.pg_rewrite r JOIN pg_catalog.pg_class c ON c.oid = r.ev_class JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid WHERE r.rulename = $3 AND c.relname = $2 AND n.nspname = $1 $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _rule_on( NAME, NAME ) RETURNS "char" AS $$ SELECT r.ev_type FROM pg_catalog.pg_rewrite r JOIN pg_catalog.pg_class c ON c.oid = r.ev_class WHERE r.rulename = $2 AND c.relname = $1 $$ LANGUAGE SQL; -- rule_is_on( schema, table, rule, event, description ) CREATE OR REPLACE FUNCTION rule_is_on( NAME, NAME, NAME, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE want char := _contract_on($4); have char := _rule_on($1, $2, $3); BEGIN IF have IS NOT NULL THEN RETURN is( _expand_on(have), _expand_on(want), $5 ); END IF; RETURN ok( false, $5 ) || E'\n' || diag( ' Rule ' || quote_ident($3) || ' does not exist on ' || quote_ident($1) || '.' || quote_ident($2) ); END; $$ LANGUAGE plpgsql; -- rule_is_on( schema, table, rule, event ) CREATE OR REPLACE FUNCTION rule_is_on( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT rule_is_on( $1, $2, $3, $4, 'Rule ' || quote_ident($3) || ' should be on ' || _expand_on(_contract_on($4)::char) || ' to ' || quote_ident($1) || '.' || quote_ident($2) ); $$ LANGUAGE SQL; -- rule_is_on( table, rule, event, description ) CREATE OR REPLACE FUNCTION rule_is_on( NAME, NAME, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE want char := _contract_on($3); have char := _rule_on($1, $2); BEGIN IF have IS NOT NULL THEN RETURN is( _expand_on(have), _expand_on(want), $4 ); END IF; RETURN ok( false, $4 ) || E'\n' || diag( ' Rule ' || quote_ident($2) || ' does not exist on ' || quote_ident($1) ); END; $$ LANGUAGE plpgsql; -- rule_is_on( table, rule, event ) CREATE OR REPLACE FUNCTION rule_is_on( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT rule_is_on( $1, $2, $3, 'Rule ' || quote_ident($2) || ' should be on ' || _expand_on(_contract_on($3)::char) || ' to ' || quote_ident($1) ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _nosuch( NAME, NAME, NAME[]) RETURNS TEXT AS $$ SELECT E'\n' || diag( ' Function ' || CASE WHEN $1 IS NOT NULL THEN quote_ident($1) || '.' ELSE '' END || quote_ident($2) || '(' || array_to_string($3, ', ') || ') does not exist' ); $$ LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION _func_compare( NAME, NAME, NAME[], anyelement, anyelement, TEXT) RETURNS TEXT AS $$ SELECT CASE WHEN $4 IS NULL THEN ok( FALSE, $6 ) || _nosuch($1, $2, $3) ELSE is( $4, $5, $6 ) END; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _func_compare( NAME, NAME, NAME[], boolean, TEXT) RETURNS TEXT AS $$ SELECT CASE WHEN $4 IS NULL THEN ok( FALSE, $5 ) || _nosuch($1, $2, $3) ELSE ok( $4, $5 ) END; $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _func_compare( NAME, NAME, anyelement, anyelement, TEXT) RETURNS TEXT AS $$ SELECT CASE WHEN $3 IS NULL THEN ok( FALSE, $5 ) || _nosuch($1, $2, '{}') ELSE is( $3, $4, $5 ) END; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _func_compare( NAME, NAME, boolean, TEXT) RETURNS TEXT AS $$ SELECT CASE WHEN $3 IS NULL THEN ok( FALSE, $4 ) || _nosuch($1, $2, '{}') ELSE ok( $3, $4 ) END; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _lang ( NAME, NAME, NAME[] ) RETURNS NAME AS $$ SELECT l.lanname FROM tap_funky f JOIN pg_catalog.pg_language l ON f.langoid = l.oid WHERE f.schema = $1 and f.name = $2 AND f.args = array_to_string($3, ',') $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _lang ( NAME, NAME ) RETURNS NAME AS $$ SELECT l.lanname FROM tap_funky f JOIN pg_catalog.pg_language l ON f.langoid = l.oid WHERE f.schema = $1 and f.name = $2 $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _lang ( NAME, NAME[] ) RETURNS NAME AS $$ SELECT l.lanname FROM tap_funky f JOIN pg_catalog.pg_language l ON f.langoid = l.oid WHERE f.name = $1 AND f.args = array_to_string($2, ',') AND f.is_visible; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _lang ( NAME ) RETURNS NAME AS $$ SELECT l.lanname FROM tap_funky f JOIN pg_catalog.pg_language l ON f.langoid = l.oid WHERE f.name = $1 AND f.is_visible; $$ LANGUAGE SQL; -- function_lang_is( schema, function, args[], language, description ) CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME, NAME[], NAME, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare($1, $2, $3, _lang($1, $2, $3), $4, $5 ); $$ LANGUAGE SQL; -- function_lang_is( schema, function, args[], language ) CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME, NAME[], NAME ) RETURNS TEXT AS $$ SELECT function_lang_is( $1, $2, $3, $4, 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' || array_to_string($3, ', ') || ') should be written in ' || quote_ident($4) ); $$ LANGUAGE SQL; -- function_lang_is( schema, function, language, description ) CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare($1, $2, _lang($1, $2), $3, $4 ); $$ LANGUAGE SQL; -- function_lang_is( schema, function, language ) CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME, NAME ) RETURNS TEXT AS $$ SELECT function_lang_is( $1, $2, $3, 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should be written in ' || quote_ident($3) ); $$ LANGUAGE SQL; -- function_lang_is( function, args[], language, description ) CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME[], NAME, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare(NULL, $1, $2, _lang($1, $2), $3, $4 ); $$ LANGUAGE SQL; -- function_lang_is( function, args[], language ) CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME[], NAME ) RETURNS TEXT AS $$ SELECT function_lang_is( $1, $2, $3, 'Function ' || quote_ident($1) || '(' || array_to_string($2, ', ') || ') should be written in ' || quote_ident($3) ); $$ LANGUAGE SQL; -- function_lang_is( function, language, description ) CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare(NULL, $1, _lang($1), $2, $3 ); $$ LANGUAGE SQL; -- function_lang_is( function, language ) CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME ) RETURNS TEXT AS $$ SELECT function_lang_is( $1, $2, 'Function ' || quote_ident($1) || '() should be written in ' || quote_ident($2) ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _returns ( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT returns FROM tap_funky WHERE schema = $1 AND name = $2 AND args = array_to_string($3, ',') $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _returns ( NAME, NAME ) RETURNS TEXT AS $$ SELECT returns FROM tap_funky WHERE schema = $1 AND name = $2 $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _returns ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT returns FROM tap_funky WHERE name = $1 AND args = array_to_string($2, ',') AND is_visible; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _returns ( NAME ) RETURNS TEXT AS $$ SELECT returns FROM tap_funky WHERE name = $1 AND is_visible; $$ LANGUAGE SQL; -- function_returns( schema, function, args[], type, description ) CREATE OR REPLACE FUNCTION function_returns( NAME, NAME, NAME[], TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare($1, $2, $3, _returns($1, $2, $3), $4, $5 ); $$ LANGUAGE SQL; -- function_returns( schema, function, args[], type ) CREATE OR REPLACE FUNCTION function_returns( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT function_returns( $1, $2, $3, $4, 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' || array_to_string($3, ', ') || ') should return ' || $4 ); $$ LANGUAGE SQL; -- function_returns( schema, function, type, description ) CREATE OR REPLACE FUNCTION function_returns( NAME, NAME, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare($1, $2, _returns($1, $2), $3, $4 ); $$ LANGUAGE SQL; -- function_returns( schema, function, type ) CREATE OR REPLACE FUNCTION function_returns( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT function_returns( $1, $2, $3, 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should return ' || $3 ); $$ LANGUAGE SQL; -- function_returns( function, args[], type, description ) CREATE OR REPLACE FUNCTION function_returns( NAME, NAME[], TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare(NULL, $1, $2, _returns($1, $2), $3, $4 ); $$ LANGUAGE SQL; -- function_returns( function, args[], type ) CREATE OR REPLACE FUNCTION function_returns( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT function_returns( $1, $2, $3, 'Function ' || quote_ident($1) || '(' || array_to_string($2, ', ') || ') should return ' || $3 ); $$ LANGUAGE SQL; -- function_returns( function, type, description ) CREATE OR REPLACE FUNCTION function_returns( NAME, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare(NULL, $1, _returns($1), $2, $3 ); $$ LANGUAGE SQL; -- function_returns( function, type ) CREATE OR REPLACE FUNCTION function_returns( NAME, TEXT ) RETURNS TEXT AS $$ SELECT function_returns( $1, $2, 'Function ' || quote_ident($1) || '() should return ' || $2 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _definer ( NAME, NAME, NAME[] ) RETURNS BOOLEAN AS $$ SELECT is_definer FROM tap_funky WHERE schema = $1 AND name = $2 AND args = array_to_string($3, ',') $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _definer ( NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT is_definer FROM tap_funky WHERE schema = $1 AND name = $2 $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _definer ( NAME, NAME[] ) RETURNS BOOLEAN AS $$ SELECT is_definer FROM tap_funky WHERE name = $1 AND args = array_to_string($2, ',') AND is_visible; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _definer ( NAME ) RETURNS BOOLEAN AS $$ SELECT is_definer FROM tap_funky WHERE name = $1 AND is_visible; $$ LANGUAGE SQL; -- is_definer( schema, function, args[], description ) CREATE OR REPLACE FUNCTION is_definer ( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _func_compare($1, $2, $3, _definer($1, $2, $3), $4 ); $$ LANGUAGE SQL; -- is_definer( schema, function, args[] ) CREATE OR REPLACE FUNCTION is_definer( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT ok( _definer($1, $2, $3), 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' || array_to_string($3, ', ') || ') should be security definer' ); $$ LANGUAGE sql; -- is_definer( schema, function, description ) CREATE OR REPLACE FUNCTION is_definer ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare($1, $2, _definer($1, $2), $3 ); $$ LANGUAGE SQL; -- is_definer( schema, function ) CREATE OR REPLACE FUNCTION is_definer( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _definer($1, $2), 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should be security definer' ); $$ LANGUAGE sql; -- is_definer( function, args[], description ) CREATE OR REPLACE FUNCTION is_definer ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _func_compare(NULL, $1, $2, _definer($1, $2), $3 ); $$ LANGUAGE SQL; -- is_definer( function, args[] ) CREATE OR REPLACE FUNCTION is_definer( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT ok( _definer($1, $2), 'Function ' || quote_ident($1) || '(' || array_to_string($2, ', ') || ') should be security definer' ); $$ LANGUAGE sql; -- is_definer( function, description ) CREATE OR REPLACE FUNCTION is_definer( NAME, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare(NULL, $1, _definer($1), $2 ); $$ LANGUAGE sql; -- is_definer( function ) CREATE OR REPLACE FUNCTION is_definer( NAME ) RETURNS TEXT AS $$ SELECT ok( _definer($1), 'Function ' || quote_ident($1) || '() should be security definer' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _agg ( NAME, NAME, NAME[] ) RETURNS BOOLEAN AS $$ SELECT is_agg FROM tap_funky WHERE schema = $1 AND name = $2 AND args = array_to_string($3, ',') $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _agg ( NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT is_agg FROM tap_funky WHERE schema = $1 AND name = $2 $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _agg ( NAME, NAME[] ) RETURNS BOOLEAN AS $$ SELECT is_agg FROM tap_funky WHERE name = $1 AND args = array_to_string($2, ',') AND is_visible; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _agg ( NAME ) RETURNS BOOLEAN AS $$ SELECT is_agg FROM tap_funky WHERE name = $1 AND is_visible; $$ LANGUAGE SQL; -- is_aggregate( schema, function, args[], description ) CREATE OR REPLACE FUNCTION is_aggregate ( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _func_compare($1, $2, $3, _agg($1, $2, $3), $4 ); $$ LANGUAGE SQL; -- is_aggregate( schema, function, args[] ) CREATE OR REPLACE FUNCTION is_aggregate( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT ok( _agg($1, $2, $3), 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' || array_to_string($3, ', ') || ') should be an aggregate function' ); $$ LANGUAGE sql; -- is_aggregate( schema, function, description ) CREATE OR REPLACE FUNCTION is_aggregate ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare($1, $2, _agg($1, $2), $3 ); $$ LANGUAGE SQL; -- is_aggregate( schema, function ) CREATE OR REPLACE FUNCTION is_aggregate( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _agg($1, $2), 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should be an aggregate function' ); $$ LANGUAGE sql; -- is_aggregate( function, args[], description ) CREATE OR REPLACE FUNCTION is_aggregate ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _func_compare(NULL, $1, $2, _agg($1, $2), $3 ); $$ LANGUAGE SQL; -- is_aggregate( function, args[] ) CREATE OR REPLACE FUNCTION is_aggregate( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT ok( _agg($1, $2), 'Function ' || quote_ident($1) || '(' || array_to_string($2, ', ') || ') should be an aggregate function' ); $$ LANGUAGE sql; -- is_aggregate( function, description ) CREATE OR REPLACE FUNCTION is_aggregate( NAME, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare(NULL, $1, _agg($1), $2 ); $$ LANGUAGE sql; -- is_aggregate( function ) CREATE OR REPLACE FUNCTION is_aggregate( NAME ) RETURNS TEXT AS $$ SELECT ok( _agg($1), 'Function ' || quote_ident($1) || '() should be an aggregate function' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _strict ( NAME, NAME, NAME[] ) RETURNS BOOLEAN AS $$ SELECT is_strict FROM tap_funky WHERE schema = $1 AND name = $2 AND args = array_to_string($3, ',') $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _strict ( NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT is_strict FROM tap_funky WHERE schema = $1 AND name = $2 $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _strict ( NAME, NAME[] ) RETURNS BOOLEAN AS $$ SELECT is_strict FROM tap_funky WHERE name = $1 AND args = array_to_string($2, ',') AND is_visible; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _strict ( NAME ) RETURNS BOOLEAN AS $$ SELECT is_strict FROM tap_funky WHERE name = $1 AND is_visible; $$ LANGUAGE SQL; -- is_strict( schema, function, args[], description ) CREATE OR REPLACE FUNCTION is_strict ( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _func_compare($1, $2, $3, _strict($1, $2, $3), $4 ); $$ LANGUAGE SQL; -- is_strict( schema, function, args[] ) CREATE OR REPLACE FUNCTION is_strict( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT ok( _strict($1, $2, $3), 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' || array_to_string($3, ', ') || ') should be strict' ); $$ LANGUAGE sql; -- is_strict( schema, function, description ) CREATE OR REPLACE FUNCTION is_strict ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare($1, $2, _strict($1, $2), $3 ); $$ LANGUAGE SQL; -- is_strict( schema, function ) CREATE OR REPLACE FUNCTION is_strict( NAME, NAME ) RETURNS TEXT AS $$ SELECT ok( _strict($1, $2), 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should be strict' ); $$ LANGUAGE sql; -- is_strict( function, args[], description ) CREATE OR REPLACE FUNCTION is_strict ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _func_compare(NULL, $1, $2, _strict($1, $2), $3 ); $$ LANGUAGE SQL; -- is_strict( function, args[] ) CREATE OR REPLACE FUNCTION is_strict( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT ok( _strict($1, $2), 'Function ' || quote_ident($1) || '(' || array_to_string($2, ', ') || ') should be strict' ); $$ LANGUAGE sql; -- is_strict( function, description ) CREATE OR REPLACE FUNCTION is_strict( NAME, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare(NULL, $1, _strict($1), $2 ); $$ LANGUAGE sql; -- is_strict( function ) CREATE OR REPLACE FUNCTION is_strict( NAME ) RETURNS TEXT AS $$ SELECT ok( _strict($1), 'Function ' || quote_ident($1) || '() should be strict' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _expand_vol( char ) RETURNS TEXT AS $$ SELECT CASE $1 WHEN 'i' THEN 'IMMUTABLE' WHEN 's' THEN 'STABLE' WHEN 'v' THEN 'VOLATILE' ELSE 'UNKNOWN' END $$ LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION _refine_vol( text ) RETURNS text AS $$ SELECT _expand_vol(substring(LOWER($1) FROM 1 FOR 1)::char); $$ LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION _vol ( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT _expand_vol(volatility) FROM tap_funky f WHERE f.schema = $1 and f.name = $2 AND f.args = array_to_string($3, ',') $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _vol ( NAME, NAME ) RETURNS TEXT AS $$ SELECT _expand_vol(volatility) FROM tap_funky f WHERE f.schema = $1 and f.name = $2 $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _vol ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT _expand_vol(volatility) FROM tap_funky f WHERE f.name = $1 AND f.args = array_to_string($2, ',') AND f.is_visible; $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _vol ( NAME ) RETURNS TEXT AS $$ SELECT _expand_vol(volatility) FROM tap_funky f WHERE f.name = $1 AND f.is_visible; $$ LANGUAGE SQL; -- volatility_is( schema, function, args[], volatility, description ) CREATE OR REPLACE FUNCTION volatility_is( NAME, NAME, NAME[], TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare($1, $2, $3, _vol($1, $2, $3), _refine_vol($4), $5 ); $$ LANGUAGE SQL; -- volatility_is( schema, function, args[], volatility ) CREATE OR REPLACE FUNCTION volatility_is( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT volatility_is( $1, $2, $3, $4, 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' || array_to_string($3, ', ') || ') should be ' || _refine_vol($4) ); $$ LANGUAGE SQL; -- volatility_is( schema, function, volatility, description ) CREATE OR REPLACE FUNCTION volatility_is( NAME, NAME, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare($1, $2, _vol($1, $2), _refine_vol($3), $4 ); $$ LANGUAGE SQL; -- volatility_is( schema, function, volatility ) CREATE OR REPLACE FUNCTION volatility_is( NAME, NAME, TEXT ) RETURNS TEXT AS $$ SELECT volatility_is( $1, $2, $3, 'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should be ' || _refine_vol($3) ); $$ LANGUAGE SQL; -- volatility_is( function, args[], volatility, description ) CREATE OR REPLACE FUNCTION volatility_is( NAME, NAME[], TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare(NULL, $1, $2, _vol($1, $2), _refine_vol($3), $4 ); $$ LANGUAGE SQL; -- volatility_is( function, args[], volatility ) CREATE OR REPLACE FUNCTION volatility_is( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT volatility_is( $1, $2, $3, 'Function ' || quote_ident($1) || '(' || array_to_string($2, ', ') || ') should be ' || _refine_vol($3) ); $$ LANGUAGE SQL; -- volatility_is( function, volatility, description ) CREATE OR REPLACE FUNCTION volatility_is( NAME, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _func_compare(NULL, $1, _vol($1), _refine_vol($2), $3 ); $$ LANGUAGE SQL; -- volatility_is( function, volatility ) CREATE OR REPLACE FUNCTION volatility_is( NAME, TEXT ) RETURNS TEXT AS $$ SELECT volatility_is( $1, $2, 'Function ' || quote_ident($1) || '() should be ' || _refine_vol($2) ); $$ LANGUAGE SQL; -- check_test( test_output, pass, name, description, diag, match_diag ) CREATE OR REPLACE FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT, TEXT, BOOLEAN ) RETURNS SETOF TEXT AS $$ DECLARE tnumb INTEGER; aok BOOLEAN; adescr TEXT; res BOOLEAN; descr TEXT; adiag TEXT; have ALIAS FOR $1; eok ALIAS FOR $2; name ALIAS FOR $3; edescr ALIAS FOR $4; ediag ALIAS FOR $5; matchit ALIAS FOR $6; BEGIN -- What test was it that just ran? tnumb := currval('__tresults___numb_seq'); -- Fetch the results. EXECUTE 'SELECT aok, descr FROM __tresults__ WHERE numb = ' || tnumb INTO aok, adescr; -- Now delete those results. EXECUTE 'DELETE FROM __tresults__ WHERE numb = ' || tnumb; EXECUTE 'ALTER SEQUENCE __tresults___numb_seq RESTART WITH ' || tnumb; -- Set up the description. descr := coalesce( name || ' ', 'Test ' ) || 'should '; -- So, did the test pass? RETURN NEXT is( aok, eok, descr || CASE eok WHEN true then 'pass' ELSE 'fail' END ); -- Was the description as expected? IF edescr IS NOT NULL THEN RETURN NEXT is( adescr, edescr, descr || 'have the proper description' ); END IF; -- Were the diagnostics as expected? IF ediag IS NOT NULL THEN -- Remove ok and the test number. adiag := substring( have FROM CASE WHEN aok THEN 4 ELSE 9 END + char_length(tnumb::text) ); -- Remove the description, if there is one. IF adescr <> '' THEN adiag := substring( adiag FROM 3 + char_length( diag( adescr ) ) ); END IF; -- Remove failure message from ok(). IF NOT aok THEN adiag := substring( adiag FROM 14 + char_length(tnumb::text) + CASE adescr WHEN '' THEN 3 ELSE 3 + char_length( diag( adescr ) ) END ); END IF; -- Remove the #s. adiag := replace( substring(adiag from 3), E'\n# ', E'\n' ); -- Now compare the diagnostics. IF matchit THEN RETURN NEXT matches( adiag, ediag, descr || 'have the proper diagnostics' ); ELSE RETURN NEXT is( adiag, ediag, descr || 'have the proper diagnostics' ); END IF; END IF; -- And we're done RETURN; END; $$ LANGUAGE plpgsql; -- check_test( test_output, pass, name, description, diag ) CREATE OR REPLACE FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT, TEXT ) RETURNS SETOF TEXT AS $$ SELECT * FROM check_test( $1, $2, $3, $4, $5, FALSE ); $$ LANGUAGE sql; -- check_test( test_output, pass, name, description ) CREATE OR REPLACE FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT ) RETURNS SETOF TEXT AS $$ SELECT * FROM check_test( $1, $2, $3, $4, NULL, FALSE ); $$ LANGUAGE sql; -- check_test( test_output, pass, name ) CREATE OR REPLACE FUNCTION check_test( TEXT, BOOLEAN, TEXT ) RETURNS SETOF TEXT AS $$ SELECT * FROM check_test( $1, $2, $3, NULL, NULL, FALSE ); $$ LANGUAGE sql; -- check_test( test_output, pass ) CREATE OR REPLACE FUNCTION check_test( TEXT, BOOLEAN ) RETURNS SETOF TEXT AS $$ SELECT * FROM check_test( $1, $2, NULL, NULL, NULL, FALSE ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION findfuncs( NAME, TEXT ) RETURNS TEXT[] AS $$ SELECT ARRAY( SELECT DISTINCT quote_ident(n.nspname) || '.' || quote_ident(p.proname) AS pname FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid WHERE n.nspname = $1 AND p.proname ~ $2 ORDER BY pname ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION findfuncs( TEXT ) RETURNS TEXT[] AS $$ SELECT ARRAY( SELECT DISTINCT quote_ident(n.nspname) || '.' || quote_ident(p.proname) AS pname FROM pg_catalog.pg_proc p JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid WHERE pg_catalog.pg_function_is_visible(p.oid) AND p.proname ~ $1 ORDER BY pname ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _runem( text[], boolean ) RETURNS SETOF TEXT AS $$ DECLARE tap text; lbound int := array_lower($1, 1); BEGIN IF lbound IS NULL THEN RETURN; END IF; FOR i IN lbound..array_upper($1, 1) LOOP -- Send the name of the function to diag if warranted. IF $2 THEN RETURN NEXT diag( $1[i] || '()' ); END IF; -- Execute the tap function and return its results. FOR tap IN EXECUTE 'SELECT * FROM ' || $1[i] || '()' LOOP RETURN NEXT tap; END LOOP; END LOOP; RETURN; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _is_verbose() RETURNS BOOLEAN AS $$ SELECT current_setting('client_min_messages') NOT IN ( 'warning', 'error', 'fatal', 'panic' ); $$ LANGUAGE sql STABLE; -- do_tap( schema, pattern ) CREATE OR REPLACE FUNCTION do_tap( name, text ) RETURNS SETOF TEXT AS $$ SELECT * FROM _runem( findfuncs($1, $2), _is_verbose() ); $$ LANGUAGE sql; -- do_tap( schema ) CREATE OR REPLACE FUNCTION do_tap( name ) RETURNS SETOF TEXT AS $$ SELECT * FROM _runem( findfuncs($1, '^test'), _is_verbose() ); $$ LANGUAGE sql; -- do_tap( pattern ) CREATE OR REPLACE FUNCTION do_tap( text ) RETURNS SETOF TEXT AS $$ SELECT * FROM _runem( findfuncs($1), _is_verbose() ); $$ LANGUAGE sql; -- do_tap() CREATE OR REPLACE FUNCTION do_tap( ) RETURNS SETOF TEXT AS $$ SELECT * FROM _runem( findfuncs('^test'), _is_verbose()); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _currtest() RETURNS INTEGER AS $$ BEGIN RETURN currval('__tresults___numb_seq'); EXCEPTION WHEN object_not_in_prerequisite_state THEN RETURN 0; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _cleanup() RETURNS boolean AS $$ DROP TABLE __tresults__; DROP SEQUENCE __tresults___numb_seq; DROP TABLE __tcache__; DROP SEQUENCE __tcache___id_seq; SELECT TRUE; $$ LANGUAGE sql; -- diag_test_name ( test_name ) CREATE OR REPLACE FUNCTION diag_test_name(TEXT) RETURNS TEXT AS $$ SELECT diag($1 || '()'); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _runner( text[], text[], text[], text[], text[] ) RETURNS SETOF TEXT AS $$ DECLARE startup ALIAS FOR $1; shutdown ALIAS FOR $2; setup ALIAS FOR $3; teardown ALIAS FOR $4; tests ALIAS FOR $5; tap text; verbos boolean := _is_verbose(); -- verbose is a reserved word in 8.5. num_faild INTEGER := 0; BEGIN BEGIN -- No plan support. PERFORM * FROM no_plan(); FOR tap IN SELECT * FROM _runem(startup, false) LOOP RETURN NEXT tap; END LOOP; EXCEPTION -- Catch all exceptions and simply rethrow custom exceptions. This -- will roll back everything in the above block. WHEN raise_exception THEN RAISE EXCEPTION '%', SQLERRM; END; BEGIN FOR i IN 1..array_upper(tests, 1) LOOP BEGIN -- What test are we running? IF verbos THEN RETURN NEXT diag_test_name(tests[i]); END IF; -- Run the setup functions. FOR tap IN SELECT * FROM _runem(setup, false) LOOP RETURN NEXT tap; END LOOP; -- Run the actual test function. FOR tap IN EXECUTE 'SELECT * FROM ' || tests[i] || '()' LOOP RETURN NEXT tap; END LOOP; -- Run the teardown functions. FOR tap IN SELECT * FROM _runem(teardown, false) LOOP RETURN NEXT tap; END LOOP; -- Remember how many failed and then roll back. num_faild := num_faild + num_failed(); RAISE EXCEPTION '__TAP_ROLLBACK__'; EXCEPTION WHEN raise_exception THEN IF SQLERRM <> '__TAP_ROLLBACK__' THEN -- We didn't raise it, so propagate it. RAISE EXCEPTION '%', SQLERRM; END IF; END; END LOOP; -- Run the shutdown functions. FOR tap IN SELECT * FROM _runem(shutdown, false) LOOP RETURN NEXT tap; END LOOP; -- Raise an exception to rollback any changes. RAISE EXCEPTION '__TAP_ROLLBACK__'; EXCEPTION WHEN raise_exception THEN IF SQLERRM <> '__TAP_ROLLBACK__' THEN -- We didn't raise it, so propagate it. RAISE EXCEPTION '%', SQLERRM; END IF; END; -- Finish up. FOR tap IN SELECT * FROM _finish( currval('__tresults___numb_seq')::integer, 0, num_faild ) LOOP RETURN NEXT tap; END LOOP; -- Clean up and return. PERFORM _cleanup(); RETURN; END; $$ LANGUAGE plpgsql; -- runtests( schema, match ) CREATE OR REPLACE FUNCTION runtests( NAME, TEXT ) RETURNS SETOF TEXT AS $$ SELECT * FROM _runner( findfuncs( $1, '^startup' ), findfuncs( $1, '^shutdown' ), findfuncs( $1, '^setup' ), findfuncs( $1, '^teardown' ), findfuncs( $1, $2 ) ); $$ LANGUAGE sql; -- runtests( schema ) CREATE OR REPLACE FUNCTION runtests( NAME ) RETURNS SETOF TEXT AS $$ SELECT * FROM runtests( $1, '^test' ); $$ LANGUAGE sql; -- runtests( match ) CREATE OR REPLACE FUNCTION runtests( TEXT ) RETURNS SETOF TEXT AS $$ SELECT * FROM _runner( findfuncs( '^startup' ), findfuncs( '^shutdown' ), findfuncs( '^setup' ), findfuncs( '^teardown' ), findfuncs( $1 ) ); $$ LANGUAGE sql; -- runtests( ) CREATE OR REPLACE FUNCTION runtests( ) RETURNS SETOF TEXT AS $$ SELECT * FROM runtests( '^test' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _temptable ( TEXT, TEXT ) RETURNS TEXT AS $$ BEGIN EXECUTE 'CREATE TEMP TABLE ' || $2 || ' AS ' || _query($1); return $2; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _temptable ( anyarray, TEXT ) RETURNS TEXT AS $$ BEGIN CREATE TEMP TABLE _____coltmp___ AS SELECT $1[i] FROM generate_series(array_lower($1, 1), array_upper($1, 1)) s(i); EXECUTE 'ALTER TABLE _____coltmp___ RENAME TO ' || $2; return $2; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _temptypes( TEXT ) RETURNS TEXT AS $$ SELECT array_to_string(ARRAY( SELECT pg_catalog.format_type(a.atttypid, a.atttypmod) FROM pg_catalog.pg_attribute a JOIN pg_catalog.pg_class c ON a.attrelid = c.oid WHERE c.oid = ('pg_temp.' || $1)::pg_catalog.regclass AND attnum > 0 AND NOT attisdropped ORDER BY attnum ), ','); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _docomp( TEXT, TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE have ALIAS FOR $1; want ALIAS FOR $2; extras TEXT[] := '{}'; missing TEXT[] := '{}'; res BOOLEAN := TRUE; msg TEXT := ''; rec RECORD; BEGIN BEGIN -- Find extra records. FOR rec in EXECUTE 'SELECT * FROM ' || have || ' EXCEPT ' || $4 || 'SELECT * FROM ' || want LOOP extras := extras || rec::text; END LOOP; -- Find missing records. FOR rec in EXECUTE 'SELECT * FROM ' || want || ' EXCEPT ' || $4 || 'SELECT * FROM ' || have LOOP missing := missing || rec::text; END LOOP; -- Drop the temporary tables. EXECUTE 'DROP TABLE ' || have; EXECUTE 'DROP TABLE ' || want; EXCEPTION WHEN syntax_error OR datatype_mismatch THEN msg := E'\n' || diag( E' Columns differ between queries:\n' || ' have: (' || _temptypes(have) || E')\n' || ' want: (' || _temptypes(want) || ')' ); EXECUTE 'DROP TABLE ' || have; EXECUTE 'DROP TABLE ' || want; RETURN ok(FALSE, $3) || msg; END; -- What extra records do we have? IF extras[1] IS NOT NULL THEN res := FALSE; msg := E'\n' || diag( E' Extra records:\n ' || array_to_string( extras, E'\n ' ) ); END IF; -- What missing records do we have? IF missing[1] IS NOT NULL THEN res := FALSE; msg := msg || E'\n' || diag( E' Missing records:\n ' || array_to_string( missing, E'\n ' ) ); END IF; RETURN ok(res, $3) || msg; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _relcomp( TEXT, TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _docomp( _temptable( $1, '__taphave__' ), _temptable( $2, '__tapwant__' ), $3, $4 ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _relcomp( TEXT, anyarray, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _docomp( _temptable( $1, '__taphave__' ), _temptable( $2, '__tapwant__' ), $3, $4 ); $$ LANGUAGE sql; -- set_eq( sql, sql, description ) CREATE OR REPLACE FUNCTION set_eq( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, $3, '' ); $$ LANGUAGE sql; -- set_eq( sql, sql ) CREATE OR REPLACE FUNCTION set_eq( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, NULL::text, '' ); $$ LANGUAGE sql; -- set_eq( sql, array, description ) CREATE OR REPLACE FUNCTION set_eq( TEXT, anyarray, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, $3, '' ); $$ LANGUAGE sql; -- set_eq( sql, array ) CREATE OR REPLACE FUNCTION set_eq( TEXT, anyarray ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, NULL::text, '' ); $$ LANGUAGE sql; -- bag_eq( sql, sql, description ) CREATE OR REPLACE FUNCTION bag_eq( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, $3, 'ALL ' ); $$ LANGUAGE sql; -- bag_eq( sql, sql ) CREATE OR REPLACE FUNCTION bag_eq( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, NULL::text, 'ALL ' ); $$ LANGUAGE sql; -- bag_eq( sql, array, description ) CREATE OR REPLACE FUNCTION bag_eq( TEXT, anyarray, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, $3, 'ALL ' ); $$ LANGUAGE sql; -- bag_eq( sql, array ) CREATE OR REPLACE FUNCTION bag_eq( TEXT, anyarray ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, NULL::text, 'ALL ' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _do_ne( TEXT, TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE have ALIAS FOR $1; want ALIAS FOR $2; extras TEXT[] := '{}'; missing TEXT[] := '{}'; res BOOLEAN := TRUE; msg TEXT := ''; BEGIN BEGIN -- Find extra records. EXECUTE 'SELECT EXISTS ( ' || '( SELECT * FROM ' || have || ' EXCEPT ' || $4 || ' SELECT * FROM ' || want || ' ) UNION ( ' || ' SELECT * FROM ' || want || ' EXCEPT ' || $4 || ' SELECT * FROM ' || have || ' ) LIMIT 1 )' INTO res; -- Drop the temporary tables. EXECUTE 'DROP TABLE ' || have; EXECUTE 'DROP TABLE ' || want; EXCEPTION WHEN syntax_error OR datatype_mismatch THEN msg := E'\n' || diag( E' Columns differ between queries:\n' || ' have: (' || _temptypes(have) || E')\n' || ' want: (' || _temptypes(want) || ')' ); EXECUTE 'DROP TABLE ' || have; EXECUTE 'DROP TABLE ' || want; RETURN ok(FALSE, $3) || msg; END; -- Return the value from the query. RETURN ok(res, $3); END; $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION _relne( TEXT, TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _do_ne( _temptable( $1, '__taphave__' ), _temptable( $2, '__tapwant__' ), $3, $4 ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _relne( TEXT, anyarray, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _do_ne( _temptable( $1, '__taphave__' ), _temptable( $2, '__tapwant__' ), $3, $4 ); $$ LANGUAGE sql; -- set_ne( sql, sql, description ) CREATE OR REPLACE FUNCTION set_ne( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relne( $1, $2, $3, '' ); $$ LANGUAGE sql; -- set_ne( sql, sql ) CREATE OR REPLACE FUNCTION set_ne( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relne( $1, $2, NULL::text, '' ); $$ LANGUAGE sql; -- set_ne( sql, array, description ) CREATE OR REPLACE FUNCTION set_ne( TEXT, anyarray, TEXT ) RETURNS TEXT AS $$ SELECT _relne( $1, $2, $3, '' ); $$ LANGUAGE sql; -- set_ne( sql, array ) CREATE OR REPLACE FUNCTION set_ne( TEXT, anyarray ) RETURNS TEXT AS $$ SELECT _relne( $1, $2, NULL::text, '' ); $$ LANGUAGE sql; -- bag_ne( sql, sql, description ) CREATE OR REPLACE FUNCTION bag_ne( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relne( $1, $2, $3, 'ALL ' ); $$ LANGUAGE sql; -- bag_ne( sql, sql ) CREATE OR REPLACE FUNCTION bag_ne( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relne( $1, $2, NULL::text, 'ALL ' ); $$ LANGUAGE sql; -- bag_ne( sql, array, description ) CREATE OR REPLACE FUNCTION bag_ne( TEXT, anyarray, TEXT ) RETURNS TEXT AS $$ SELECT _relne( $1, $2, $3, 'ALL ' ); $$ LANGUAGE sql; -- bag_ne( sql, array ) CREATE OR REPLACE FUNCTION bag_ne( TEXT, anyarray ) RETURNS TEXT AS $$ SELECT _relne( $1, $2, NULL::text, 'ALL ' ); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _relcomp( TEXT, TEXT, TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE have TEXT := _temptable( $1, '__taphave__' ); want TEXT := _temptable( $2, '__tapwant__' ); results TEXT[] := '{}'; res BOOLEAN := TRUE; msg TEXT := ''; rec RECORD; BEGIN BEGIN -- Find relevant records. FOR rec in EXECUTE 'SELECT * FROM ' || want || ' ' || $4 || ' SELECT * FROM ' || have LOOP results := results || rec::text; END LOOP; -- Drop the temporary tables. EXECUTE 'DROP TABLE ' || have; EXECUTE 'DROP TABLE ' || want; EXCEPTION WHEN syntax_error OR datatype_mismatch THEN msg := E'\n' || diag( E' Columns differ between queries:\n' || ' have: (' || _temptypes(have) || E')\n' || ' want: (' || _temptypes(want) || ')' ); EXECUTE 'DROP TABLE ' || have; EXECUTE 'DROP TABLE ' || want; RETURN ok(FALSE, $3) || msg; END; -- What records do we have? IF results[1] IS NOT NULL THEN res := FALSE; msg := msg || E'\n' || diag( ' ' || $5 || E' records:\n ' || array_to_string( results, E'\n ' ) ); END IF; RETURN ok(res, $3) || msg; END; $$ LANGUAGE plpgsql; -- set_has( sql, sql, description ) CREATE OR REPLACE FUNCTION set_has( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, $3, 'EXCEPT', 'Missing' ); $$ LANGUAGE sql; -- set_has( sql, sql ) CREATE OR REPLACE FUNCTION set_has( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, NULL::TEXT, 'EXCEPT', 'Missing' ); $$ LANGUAGE sql; -- bag_has( sql, sql, description ) CREATE OR REPLACE FUNCTION bag_has( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, $3, 'EXCEPT ALL', 'Missing' ); $$ LANGUAGE sql; -- bag_has( sql, sql ) CREATE OR REPLACE FUNCTION bag_has( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, NULL::TEXT, 'EXCEPT ALL', 'Missing' ); $$ LANGUAGE sql; -- set_hasnt( sql, sql, description ) CREATE OR REPLACE FUNCTION set_hasnt( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, $3, 'INTERSECT', 'Extra' ); $$ LANGUAGE sql; -- set_hasnt( sql, sql ) CREATE OR REPLACE FUNCTION set_hasnt( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, NULL::TEXT, 'INTERSECT', 'Extra' ); $$ LANGUAGE sql; -- bag_hasnt( sql, sql, description ) CREATE OR REPLACE FUNCTION bag_hasnt( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, $3, 'INTERSECT ALL', 'Extra' ); $$ LANGUAGE sql; -- bag_hasnt( sql, sql ) CREATE OR REPLACE FUNCTION bag_hasnt( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT _relcomp( $1, $2, NULL::TEXT, 'INTERSECT ALL', 'Extra' ); $$ LANGUAGE sql; -- results_eq( cursor, cursor, description ) CREATE OR REPLACE FUNCTION results_eq( refcursor, refcursor, text ) RETURNS TEXT AS $$ DECLARE have ALIAS FOR $1; want ALIAS FOR $2; have_rec RECORD; want_rec RECORD; have_found BOOLEAN; want_found BOOLEAN; rownum INTEGER := 1; BEGIN FETCH have INTO have_rec; have_found := FOUND; FETCH want INTO want_rec; want_found := FOUND; WHILE have_found OR want_found LOOP IF have_rec IS DISTINCT FROM want_rec OR have_found <> want_found THEN RETURN ok( false, $3 ) || E'\n' || diag( ' Results differ beginning at row ' || rownum || E':\n' || ' have: ' || CASE WHEN have_found THEN have_rec::text ELSE 'NULL' END || E'\n' || ' want: ' || CASE WHEN want_found THEN want_rec::text ELSE 'NULL' END ); END IF; rownum = rownum + 1; FETCH have INTO have_rec; have_found := FOUND; FETCH want INTO want_rec; want_found := FOUND; END LOOP; RETURN ok( true, $3 ); EXCEPTION WHEN datatype_mismatch THEN RETURN ok( false, $3 ) || E'\n' || diag( E' Columns differ between queries:\n' || ' have: ' || CASE WHEN have_found THEN have_rec::text ELSE 'NULL' END || E'\n' || ' want: ' || CASE WHEN want_found THEN want_rec::text ELSE 'NULL' END ); END; $$ LANGUAGE plpgsql; -- results_eq( cursor, cursor ) CREATE OR REPLACE FUNCTION results_eq( refcursor, refcursor ) RETURNS TEXT AS $$ SELECT results_eq( $1, $2, NULL::text ); $$ LANGUAGE sql; -- results_eq( sql, sql, description ) CREATE OR REPLACE FUNCTION results_eq( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE have REFCURSOR; want REFCURSOR; res TEXT; BEGIN OPEN have FOR EXECUTE _query($1); OPEN want FOR EXECUTE _query($2); res := results_eq(have, want, $3); CLOSE have; CLOSE want; RETURN res; END; $$ LANGUAGE plpgsql; -- results_eq( sql, sql ) CREATE OR REPLACE FUNCTION results_eq( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT results_eq( $1, $2, NULL::text ); $$ LANGUAGE sql; -- results_eq( sql, array, description ) CREATE OR REPLACE FUNCTION results_eq( TEXT, anyarray, TEXT ) RETURNS TEXT AS $$ DECLARE have REFCURSOR; want REFCURSOR; res TEXT; BEGIN OPEN have FOR EXECUTE _query($1); OPEN want FOR SELECT $2[i] FROM generate_series(array_lower($2, 1), array_upper($2, 1)) s(i); res := results_eq(have, want, $3); CLOSE have; CLOSE want; RETURN res; END; $$ LANGUAGE plpgsql; -- results_eq( sql, array ) CREATE OR REPLACE FUNCTION results_eq( TEXT, anyarray ) RETURNS TEXT AS $$ SELECT results_eq( $1, $2, NULL::text ); $$ LANGUAGE sql; -- results_eq( sql, cursor, description ) CREATE OR REPLACE FUNCTION results_eq( TEXT, refcursor, TEXT ) RETURNS TEXT AS $$ DECLARE have REFCURSOR; res TEXT; BEGIN OPEN have FOR EXECUTE _query($1); res := results_eq(have, $2, $3); CLOSE have; RETURN res; END; $$ LANGUAGE plpgsql; -- results_eq( sql, cursor ) CREATE OR REPLACE FUNCTION results_eq( TEXT, refcursor ) RETURNS TEXT AS $$ SELECT results_eq( $1, $2, NULL::text ); $$ LANGUAGE sql; -- results_eq( cursor, sql, description ) CREATE OR REPLACE FUNCTION results_eq( refcursor, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE want REFCURSOR; res TEXT; BEGIN OPEN want FOR EXECUTE _query($2); res := results_eq($1, want, $3); CLOSE want; RETURN res; END; $$ LANGUAGE plpgsql; -- results_eq( cursor, sql ) CREATE OR REPLACE FUNCTION results_eq( refcursor, TEXT ) RETURNS TEXT AS $$ SELECT results_eq( $1, $2, NULL::text ); $$ LANGUAGE sql; -- results_eq( cursor, array, description ) CREATE OR REPLACE FUNCTION results_eq( refcursor, anyarray, TEXT ) RETURNS TEXT AS $$ DECLARE want REFCURSOR; res TEXT; BEGIN OPEN want FOR SELECT $2[i] FROM generate_series(array_lower($2, 1), array_upper($2, 1)) s(i); res := results_eq($1, want, $3); CLOSE want; RETURN res; END; $$ LANGUAGE plpgsql; -- results_eq( cursor, array ) CREATE OR REPLACE FUNCTION results_eq( refcursor, anyarray ) RETURNS TEXT AS $$ SELECT results_eq( $1, $2, NULL::text ); $$ LANGUAGE sql; -- results_ne( cursor, cursor, description ) CREATE OR REPLACE FUNCTION results_ne( refcursor, refcursor, text ) RETURNS TEXT AS $$ DECLARE have ALIAS FOR $1; want ALIAS FOR $2; have_rec RECORD; want_rec RECORD; have_found BOOLEAN; want_found BOOLEAN; BEGIN FETCH have INTO have_rec; have_found := FOUND; FETCH want INTO want_rec; want_found := FOUND; WHILE have_found OR want_found LOOP IF have_rec IS DISTINCT FROM want_rec OR have_found <> want_found THEN RETURN ok( true, $3 ); ELSE FETCH have INTO have_rec; have_found := FOUND; FETCH want INTO want_rec; want_found := FOUND; END IF; END LOOP; RETURN ok( false, $3 ); EXCEPTION WHEN datatype_mismatch THEN RETURN ok( false, $3 ) || E'\n' || diag( E' Columns differ between queries:\n' || ' have: ' || CASE WHEN have_found THEN have_rec::text ELSE 'NULL' END || E'\n' || ' want: ' || CASE WHEN want_found THEN want_rec::text ELSE 'NULL' END ); END; $$ LANGUAGE plpgsql; -- results_ne( cursor, cursor ) CREATE OR REPLACE FUNCTION results_ne( refcursor, refcursor ) RETURNS TEXT AS $$ SELECT results_ne( $1, $2, NULL::text ); $$ LANGUAGE sql; -- results_ne( sql, sql, description ) CREATE OR REPLACE FUNCTION results_ne( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE have REFCURSOR; want REFCURSOR; res TEXT; BEGIN OPEN have FOR EXECUTE _query($1); OPEN want FOR EXECUTE _query($2); res := results_ne(have, want, $3); CLOSE have; CLOSE want; RETURN res; END; $$ LANGUAGE plpgsql; -- results_ne( sql, sql ) CREATE OR REPLACE FUNCTION results_ne( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT results_ne( $1, $2, NULL::text ); $$ LANGUAGE sql; -- results_ne( sql, array, description ) CREATE OR REPLACE FUNCTION results_ne( TEXT, anyarray, TEXT ) RETURNS TEXT AS $$ DECLARE have REFCURSOR; want REFCURSOR; res TEXT; BEGIN OPEN have FOR EXECUTE _query($1); OPEN want FOR SELECT $2[i] FROM generate_series(array_lower($2, 1), array_upper($2, 1)) s(i); res := results_ne(have, want, $3); CLOSE have; CLOSE want; RETURN res; END; $$ LANGUAGE plpgsql; -- results_ne( sql, array ) CREATE OR REPLACE FUNCTION results_ne( TEXT, anyarray ) RETURNS TEXT AS $$ SELECT results_ne( $1, $2, NULL::text ); $$ LANGUAGE sql; -- results_ne( sql, cursor, description ) CREATE OR REPLACE FUNCTION results_ne( TEXT, refcursor, TEXT ) RETURNS TEXT AS $$ DECLARE have REFCURSOR; res TEXT; BEGIN OPEN have FOR EXECUTE _query($1); res := results_ne(have, $2, $3); CLOSE have; RETURN res; END; $$ LANGUAGE plpgsql; -- results_ne( sql, cursor ) CREATE OR REPLACE FUNCTION results_ne( TEXT, refcursor ) RETURNS TEXT AS $$ SELECT results_ne( $1, $2, NULL::text ); $$ LANGUAGE sql; -- results_ne( cursor, sql, description ) CREATE OR REPLACE FUNCTION results_ne( refcursor, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE want REFCURSOR; res TEXT; BEGIN OPEN want FOR EXECUTE _query($2); res := results_ne($1, want, $3); CLOSE want; RETURN res; END; $$ LANGUAGE plpgsql; -- results_ne( cursor, sql ) CREATE OR REPLACE FUNCTION results_ne( refcursor, TEXT ) RETURNS TEXT AS $$ SELECT results_ne( $1, $2, NULL::text ); $$ LANGUAGE sql; -- results_ne( cursor, array, description ) CREATE OR REPLACE FUNCTION results_ne( refcursor, anyarray, TEXT ) RETURNS TEXT AS $$ DECLARE want REFCURSOR; res TEXT; BEGIN OPEN want FOR SELECT $2[i] FROM generate_series(array_lower($2, 1), array_upper($2, 1)) s(i); res := results_ne($1, want, $3); CLOSE want; RETURN res; END; $$ LANGUAGE plpgsql; -- results_ne( cursor, array ) CREATE OR REPLACE FUNCTION results_ne( refcursor, anyarray ) RETURNS TEXT AS $$ SELECT results_ne( $1, $2, NULL::text ); $$ LANGUAGE sql; -- isa_ok( value, regtype, description ) CREATE OR REPLACE FUNCTION isa_ok( anyelement, regtype, TEXT ) RETURNS TEXT AS $$ DECLARE typeof regtype := pg_typeof($1); BEGIN IF typeof = $2 THEN RETURN ok(true, $3 || ' isa ' || $2 ); END IF; RETURN ok(false, $3 || ' isa ' || $2 ) || E'\n' || diag(' ' || $3 || ' isn''t a "' || $2 || '" it''s a "' || typeof || '"'); END; $$ LANGUAGE plpgsql; -- isa_ok( value, regtype ) CREATE OR REPLACE FUNCTION isa_ok( anyelement, regtype ) RETURNS TEXT AS $$ SELECT isa_ok($1, $2, 'the value'); $$ LANGUAGE sql; -- is_empty( sql, description ) CREATE OR REPLACE FUNCTION is_empty( TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE extras TEXT[] := '{}'; res BOOLEAN := TRUE; msg TEXT := ''; rec RECORD; BEGIN -- Find extra records. FOR rec in EXECUTE _query($1) LOOP extras := extras || rec::text; END LOOP; -- What extra records do we have? IF extras[1] IS NOT NULL THEN res := FALSE; msg := E'\n' || diag( E' Unexpected records:\n ' || array_to_string( extras, E'\n ' ) ); END IF; RETURN ok(res, $2) || msg; END; $$ LANGUAGE plpgsql; -- is_empty( sql ) CREATE OR REPLACE FUNCTION is_empty( TEXT ) RETURNS TEXT AS $$ SELECT is_empty( $1, NULL ); $$ LANGUAGE sql; -- collect_tap( tap, tap, tap ) CREATE OR REPLACE FUNCTION collect_tap( VARIADIC text[] ) RETURNS TEXT AS $$ SELECT array_to_string($1, E'\n'); $$ LANGUAGE sql; -- collect_tap( tap[] ) CREATE OR REPLACE FUNCTION collect_tap( VARCHAR[] ) RETURNS TEXT AS $$ SELECT array_to_string($1, E'\n'); $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _tlike ( BOOLEAN, TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT ok( $1, $4 ) || CASE WHEN $1 THEN '' ELSE E'\n' || diag( ' error message: ' || COALESCE( quote_literal($2), 'NULL' ) || E'\n doesn''t match: ' || COALESCE( quote_literal($3), 'NULL' ) ) END; $$ LANGUAGE sql; -- throws_like ( sql, pattern, description ) CREATE OR REPLACE FUNCTION throws_like ( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ BEGIN EXECUTE _query($1); RETURN ok( FALSE, $3 ) || E'\n' || diag( ' no exception thrown' ); EXCEPTION WHEN OTHERS THEN return _tlike( SQLERRM ~~ $2, SQLERRM, $2, $3 ); END; $$ LANGUAGE plpgsql; -- throws_like ( sql, pattern ) CREATE OR REPLACE FUNCTION throws_like ( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT throws_like($1, $2, 'Should throw exception like ' || quote_literal($2) ); $$ LANGUAGE sql; -- throws_ilike ( sql, pattern, description ) CREATE OR REPLACE FUNCTION throws_ilike ( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ BEGIN EXECUTE _query($1); RETURN ok( FALSE, $3 ) || E'\n' || diag( ' no exception thrown' ); EXCEPTION WHEN OTHERS THEN return _tlike( SQLERRM ~~* $2, SQLERRM, $2, $3 ); END; $$ LANGUAGE plpgsql; -- throws_ilike ( sql, pattern ) CREATE OR REPLACE FUNCTION throws_ilike ( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT throws_ilike($1, $2, 'Should throw exception like ' || quote_literal($2) ); $$ LANGUAGE sql; -- throws_matching ( sql, pattern, description ) CREATE OR REPLACE FUNCTION throws_matching ( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ BEGIN EXECUTE _query($1); RETURN ok( FALSE, $3 ) || E'\n' || diag( ' no exception thrown' ); EXCEPTION WHEN OTHERS THEN return _tlike( SQLERRM ~ $2, SQLERRM, $2, $3 ); END; $$ LANGUAGE plpgsql; -- throws_matching ( sql, pattern ) CREATE OR REPLACE FUNCTION throws_matching ( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT throws_matching($1, $2, 'Should throw exception matching ' || quote_literal($2) ); $$ LANGUAGE sql; -- throws_imatching ( sql, pattern, description ) CREATE OR REPLACE FUNCTION throws_imatching ( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ BEGIN EXECUTE _query($1); RETURN ok( FALSE, $3 ) || E'\n' || diag( ' no exception thrown' ); EXCEPTION WHEN OTHERS THEN return _tlike( SQLERRM ~* $2, SQLERRM, $2, $3 ); END; $$ LANGUAGE plpgsql; -- throws_imatching ( sql, pattern ) CREATE OR REPLACE FUNCTION throws_imatching ( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT throws_imatching($1, $2, 'Should throw exception matching ' || quote_literal($2) ); $$ LANGUAGE sql; -- roles_are( roles[], description ) CREATE OR REPLACE FUNCTION roles_are( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'roles', ARRAY( SELECT rolname FROM pg_catalog.pg_roles EXCEPT SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) ), ARRAY( SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) EXCEPT SELECT rolname FROM pg_catalog.pg_roles ), $2 ); $$ LANGUAGE SQL; -- roles_are( roles[] ) CREATE OR REPLACE FUNCTION roles_are( NAME[] ) RETURNS TEXT AS $$ SELECT roles_are( $1, 'There should be the correct roles' ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _types_are ( NAME, NAME[], TEXT, CHAR[] ) RETURNS TEXT AS $$ SELECT _are( 'types', ARRAY( SELECT t.typname FROM pg_catalog.pg_type t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE ( t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) ) AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid) AND n.nspname = $1 AND t.typtype = ANY( COALESCE($4, ARRAY['b', 'c', 'd', 'p', 'e']) ) EXCEPT SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) ), ARRAY( SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) EXCEPT SELECT t.typname FROM pg_catalog.pg_type t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE ( t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) ) AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid) AND n.nspname = $1 AND t.typtype = ANY( COALESCE($4, ARRAY['b', 'c', 'd', 'p', 'e']) ) ), $3 ); $$ LANGUAGE SQL; -- types_are( schema, types[], description ) CREATE OR REPLACE FUNCTION types_are ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _types_are( $1, $2, $3, NULL ); $$ LANGUAGE SQL; -- types_are( schema, types[] ) CREATE OR REPLACE FUNCTION types_are ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT _types_are( $1, $2, 'Schema ' || quote_ident($1) || ' should have the correct types', NULL ); $$ LANGUAGE SQL; -- types_are( types[], description ) CREATE OR REPLACE FUNCTION _types_are ( NAME[], TEXT, CHAR[] ) RETURNS TEXT AS $$ SELECT _are( 'types', ARRAY( SELECT t.typname FROM pg_catalog.pg_type t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE ( t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) ) AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid) AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND pg_catalog.pg_type_is_visible(t.oid) AND t.typtype = ANY( COALESCE($3, ARRAY['b', 'c', 'd', 'p', 'e']) ) EXCEPT SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) ), ARRAY( SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) EXCEPT SELECT t.typname FROM pg_catalog.pg_type t LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace WHERE ( t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) ) AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid) AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND pg_catalog.pg_type_is_visible(t.oid) AND t.typtype = ANY( COALESCE($3, ARRAY['b', 'c', 'd', 'p', 'e']) ) ), $2 ); $$ LANGUAGE SQL; -- types_are( types[], description ) CREATE OR REPLACE FUNCTION types_are ( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _types_are( $1, $2, NULL ); $$ LANGUAGE SQL; -- types_are( types[] ) CREATE OR REPLACE FUNCTION types_are ( NAME[] ) RETURNS TEXT AS $$ SELECT _types_are( $1, 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct types', NULL ); $$ LANGUAGE SQL; -- domains_are( schema, domains[], description ) CREATE OR REPLACE FUNCTION domains_are ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _types_are( $1, $2, $3, ARRAY['d'] ); $$ LANGUAGE SQL; -- domains_are( schema, domains[] ) CREATE OR REPLACE FUNCTION domains_are ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT _types_are( $1, $2, 'Schema ' || quote_ident($1) || ' should have the correct domains', ARRAY['d'] ); $$ LANGUAGE SQL; -- domains_are( domains[], description ) CREATE OR REPLACE FUNCTION domains_are ( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _types_are( $1, $2, ARRAY['d'] ); $$ LANGUAGE SQL; -- domains_are( domains[] ) CREATE OR REPLACE FUNCTION domains_are ( NAME[] ) RETURNS TEXT AS $$ SELECT _types_are( $1, 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct domains', ARRAY['d'] ); $$ LANGUAGE SQL; -- enums_are( schema, enums[], description ) CREATE OR REPLACE FUNCTION enums_are ( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _types_are( $1, $2, $3, ARRAY['e'] ); $$ LANGUAGE SQL; -- enums_are( schema, enums[] ) CREATE OR REPLACE FUNCTION enums_are ( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT _types_are( $1, $2, 'Schema ' || quote_ident($1) || ' should have the correct enums', ARRAY['e'] ); $$ LANGUAGE SQL; -- enums_are( enums[], description ) CREATE OR REPLACE FUNCTION enums_are ( NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _types_are( $1, $2, ARRAY['e'] ); $$ LANGUAGE SQL; -- enums_are( enums[] ) CREATE OR REPLACE FUNCTION enums_are ( NAME[] ) RETURNS TEXT AS $$ SELECT _types_are( $1, 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct enums', ARRAY['e'] ); $$ LANGUAGE SQL; -- _dexists( schema, domain ) CREATE OR REPLACE FUNCTION _dexists ( NAME, NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_type t on n.oid = t.typnamespace WHERE n.nspname = $1 AND t.typname = $2 ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _dexists ( NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( SELECT true FROM pg_catalog.pg_type t WHERE t.typname = $1 AND pg_catalog.pg_type_is_visible(t.oid) ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _get_dtype( NAME, TEXT, BOOLEAN ) RETURNS TEXT AS $$ SELECT display_type(CASE WHEN $3 THEN tn.nspname ELSE NULL END, t.oid, t.typtypmod) FROM pg_catalog.pg_type d JOIN pg_catalog.pg_namespace dn ON d.typnamespace = dn.oid JOIN pg_catalog.pg_type t ON d.typbasetype = t.oid JOIN pg_catalog.pg_namespace tn ON d.typnamespace = tn.oid WHERE d.typisdefined AND dn.nspname = $1 AND d.typname = LOWER($2) AND d.typtype = 'd' $$ LANGUAGE sql; CREATE OR REPLACE FUNCTION _get_dtype( NAME ) RETURNS TEXT AS $$ SELECT display_type(t.oid, t.typtypmod) FROM pg_catalog.pg_type d JOIN pg_catalog.pg_type t ON d.typbasetype = t.oid WHERE d.typisdefined AND d.typname = LOWER($1) AND d.typtype = 'd' $$ LANGUAGE sql; -- domain_type_is( schema, domain, schema, type, description ) CREATE OR REPLACE FUNCTION domain_type_is( NAME, TEXT, NAME, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE actual_type TEXT := _get_dtype($1, $2, true); BEGIN IF actual_type IS NULL THEN RETURN fail( $5 ) || E'\n' || diag ( ' Domain ' || quote_ident($1) || '.' || $2 || ' does not exist' ); END IF; RETURN is( actual_type, quote_ident($3) || '.' || _quote_ident_like($4, actual_type), $5 ); END; $$ LANGUAGE plpgsql; -- domain_type_is( schema, domain, schema, type ) CREATE OR REPLACE FUNCTION domain_type_is( NAME, TEXT, NAME, TEXT ) RETURNS TEXT AS $$ SELECT domain_type_is( $1, $2, $3, $4, 'Domain ' || quote_ident($1) || '.' || $2 || ' should extend type ' || quote_ident($3) || '.' || $4 ); $$ LANGUAGE SQL; -- domain_type_is( schema, domain, type, description ) CREATE OR REPLACE FUNCTION domain_type_is( NAME, TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE actual_type TEXT := _get_dtype($1, $2, false); BEGIN IF actual_type IS NULL THEN RETURN fail( $4 ) || E'\n' || diag ( ' Domain ' || quote_ident($1) || '.' || $2 || ' does not exist' ); END IF; RETURN is( actual_type, _quote_ident_like($3, actual_type), $4 ); END; $$ LANGUAGE plpgsql; -- domain_type_is( schema, domain, type ) CREATE OR REPLACE FUNCTION domain_type_is( NAME, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT domain_type_is( $1, $2, $3, 'Domain ' || quote_ident($1) || '.' || $2 || ' should extend type ' || $3 ); $$ LANGUAGE SQL; -- domain_type_is( domain, type, description ) CREATE OR REPLACE FUNCTION domain_type_is( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE actual_type TEXT := _get_dtype($1); BEGIN IF actual_type IS NULL THEN RETURN fail( $3 ) || E'\n' || diag ( ' Domain ' || $1 || ' does not exist' ); END IF; RETURN is( actual_type, _quote_ident_like($2, actual_type), $3 ); END; $$ LANGUAGE plpgsql; -- domain_type_is( domain, type ) CREATE OR REPLACE FUNCTION domain_type_is( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT domain_type_is( $1, $2, 'Domain ' || $1 || ' should extend type ' || $2 ); $$ LANGUAGE SQL; -- domain_type_isnt( schema, domain, schema, type, description ) CREATE OR REPLACE FUNCTION domain_type_isnt( NAME, TEXT, NAME, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE actual_type TEXT := _get_dtype($1, $2, true); BEGIN IF actual_type IS NULL THEN RETURN fail( $5 ) || E'\n' || diag ( ' Domain ' || quote_ident($1) || '.' || $2 || ' does not exist' ); END IF; RETURN isnt( actual_type, quote_ident($3) || '.' || _quote_ident_like($4, actual_type), $5 ); END; $$ LANGUAGE plpgsql; -- domain_type_isnt( schema, domain, schema, type ) CREATE OR REPLACE FUNCTION domain_type_isnt( NAME, TEXT, NAME, TEXT ) RETURNS TEXT AS $$ SELECT domain_type_isnt( $1, $2, $3, $4, 'Domain ' || quote_ident($1) || '.' || $2 || ' should not extend type ' || quote_ident($3) || '.' || $4 ); $$ LANGUAGE SQL; -- domain_type_isnt( schema, domain, type, description ) CREATE OR REPLACE FUNCTION domain_type_isnt( NAME, TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE actual_type TEXT := _get_dtype($1, $2, false); BEGIN IF actual_type IS NULL THEN RETURN fail( $4 ) || E'\n' || diag ( ' Domain ' || quote_ident($1) || '.' || $2 || ' does not exist' ); END IF; RETURN isnt( actual_type, _quote_ident_like($3, actual_type), $4 ); END; $$ LANGUAGE plpgsql; -- domain_type_isnt( schema, domain, type ) CREATE OR REPLACE FUNCTION domain_type_isnt( NAME, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT domain_type_isnt( $1, $2, $3, 'Domain ' || quote_ident($1) || '.' || $2 || ' should not extend type ' || $3 ); $$ LANGUAGE SQL; -- domain_type_isnt( domain, type, description ) CREATE OR REPLACE FUNCTION domain_type_isnt( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE actual_type TEXT := _get_dtype($1); BEGIN IF actual_type IS NULL THEN RETURN fail( $3 ) || E'\n' || diag ( ' Domain ' || $1 || ' does not exist' ); END IF; RETURN isnt( actual_type, _quote_ident_like($2, actual_type), $3 ); END; $$ LANGUAGE plpgsql; -- domain_type_isnt( domain, type ) CREATE OR REPLACE FUNCTION domain_type_isnt( TEXT, TEXT ) RETURNS TEXT AS $$ SELECT domain_type_isnt( $1, $2, 'Domain ' || $1 || ' should not extend type ' || $2 ); $$ LANGUAGE SQL; -- row_eq( sql, record, description ) CREATE OR REPLACE FUNCTION row_eq( TEXT, anyelement, TEXT ) RETURNS TEXT AS $$ DECLARE rec RECORD; BEGIN EXECUTE _query($1) INTO rec; IF NOT rec IS DISTINCT FROM $2 THEN RETURN ok(true, $3); END IF; RETURN ok(false, $3 ) || E'\n' || diag( ' have: ' || CASE WHEN rec IS NULL THEN 'NULL' ELSE rec::text END || E'\n want: ' || CASE WHEN $2 IS NULL THEN 'NULL' ELSE $2::text END ); END; $$ LANGUAGE plpgsql; -- row_eq( sql, record ) CREATE OR REPLACE FUNCTION row_eq( TEXT, anyelement ) RETURNS TEXT AS $$ SELECT row_eq($1, $2, NULL ); $$ LANGUAGE sql; -- triggers_are( schema, table, triggers[], description ) CREATE OR REPLACE FUNCTION triggers_are( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'triggers', ARRAY( SELECT t.tgname FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = $1 AND c.relname = $2 EXCEPT SELECT $3[i] FROM generate_series(1, array_upper($3, 1)) s(i) ), ARRAY( SELECT $3[i] FROM generate_series(1, array_upper($3, 1)) s(i) EXCEPT SELECT t.tgname FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE n.nspname = $1 AND c.relname = $2 ), $4 ); $$ LANGUAGE SQL; -- triggers_are( schema, table, triggers[] ) CREATE OR REPLACE FUNCTION triggers_are( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT triggers_are( $1, $2, $3, 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should have the correct triggers' ); $$ LANGUAGE SQL; -- triggers_are( table, triggers[], description ) CREATE OR REPLACE FUNCTION triggers_are( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'triggers', ARRAY( SELECT t.tgname FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relname = $1 AND n.nspname NOT IN ('pg_catalog', 'information_schema') EXCEPT SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) ), ARRAY( SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) EXCEPT SELECT t.tgname FROM pg_catalog.pg_trigger t JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace AND n.nspname NOT IN ('pg_catalog', 'information_schema') ), $3 ); $$ LANGUAGE SQL; -- triggers_are( table, triggers[] ) CREATE OR REPLACE FUNCTION triggers_are( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT triggers_are( $1, $2, 'Table ' || quote_ident($1) || ' should have the correct triggers' ); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION _areni ( text, text[], text[], TEXT ) RETURNS TEXT AS $$ DECLARE what ALIAS FOR $1; extras ALIAS FOR $2; missing ALIAS FOR $3; descr ALIAS FOR $4; msg TEXT := ''; res BOOLEAN := TRUE; BEGIN IF extras[1] IS NOT NULL THEN res = FALSE; msg := E'\n' || diag( ' Extra ' || what || E':\n ' || array_to_string( extras, E'\n ' ) ); END IF; IF missing[1] IS NOT NULL THEN res = FALSE; msg := msg || E'\n' || diag( ' Missing ' || what || E':\n ' || array_to_string( missing, E'\n ' ) ); END IF; RETURN ok(res, descr) || msg; END; $$ LANGUAGE plpgsql; -- casts_are( casts[], description ) CREATE OR REPLACE FUNCTION casts_are ( TEXT[], TEXT ) RETURNS TEXT AS $$ SELECT _areni( 'casts', ARRAY( SELECT display_type(castsource, NULL) || ' AS ' || display_type(casttarget, NULL) FROM pg_catalog.pg_cast c EXCEPT SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) ), ARRAY( SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) EXCEPT SELECT display_type(castsource, NULL) || ' AS ' || display_type(casttarget, NULL) FROM pg_catalog.pg_cast c ), $2 ); $$ LANGUAGE sql; -- casts_are( casts[] ) CREATE OR REPLACE FUNCTION casts_are ( TEXT[] ) RETURNS TEXT AS $$ SELECT casts_are( $1, 'There should be the correct casts'); $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION display_oper ( NAME, OID ) RETURNS TEXT AS $$ SELECT $1 || substring($2::regoperator::text, '[(][^)]+[)]$') $$ LANGUAGE SQL; -- operators_are( schema, operators[], description ) CREATE OR REPLACE FUNCTION operators_are( NAME, TEXT[], TEXT ) RETURNS TEXT AS $$ SELECT _areni( 'operators', ARRAY( SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype FROM pg_catalog.pg_operator o JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid WHERE n.nspname = $1 EXCEPT SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) ), ARRAY( SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) EXCEPT SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype FROM pg_catalog.pg_operator o JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid WHERE n.nspname = $1 ), $3 ); $$ LANGUAGE SQL; -- operators_are( schema, operators[] ) CREATE OR REPLACE FUNCTION operators_are ( NAME, TEXT[] ) RETURNS TEXT AS $$ SELECT operators_are($1, $2, 'Schema ' || quote_ident($1) || ' should have the correct operators' ); $$ LANGUAGE SQL; -- operators_are( operators[], description ) CREATE OR REPLACE FUNCTION operators_are( TEXT[], TEXT ) RETURNS TEXT AS $$ SELECT _areni( 'operators', ARRAY( SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype FROM pg_catalog.pg_operator o JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid WHERE pg_catalog.pg_operator_is_visible(o.oid) AND n.nspname NOT IN ('pg_catalog', 'information_schema') EXCEPT SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) ), ARRAY( SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) EXCEPT SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype FROM pg_catalog.pg_operator o JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid WHERE pg_catalog.pg_operator_is_visible(o.oid) AND n.nspname NOT IN ('pg_catalog', 'information_schema') ), $2 ); $$ LANGUAGE SQL; -- operators_are( operators[] ) CREATE OR REPLACE FUNCTION operators_are ( TEXT[] ) RETURNS TEXT AS $$ SELECT operators_are($1, 'There should be the correct operators') $$ LANGUAGE SQL; -- columns_are( schema, table, columns[], description ) CREATE OR REPLACE FUNCTION columns_are( NAME, NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'columns', ARRAY( SELECT a.attname FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid WHERE n.nspname = $1 AND c.relname = $2 AND a.attnum > 0 AND NOT a.attisdropped EXCEPT SELECT $3[i] FROM generate_series(1, array_upper($3, 1)) s(i) ), ARRAY( SELECT $3[i] FROM generate_series(1, array_upper($3, 1)) s(i) EXCEPT SELECT a.attname FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid WHERE n.nspname = $1 AND c.relname = $2 AND a.attnum > 0 AND NOT a.attisdropped ), $4 ); $$ LANGUAGE SQL; -- columns_are( schema, table, columns[] ) CREATE OR REPLACE FUNCTION columns_are( NAME, NAME, NAME[] ) RETURNS TEXT AS $$ SELECT columns_are( $1, $2, $3, 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should have the correct columns' ); $$ LANGUAGE SQL; -- columns_are( table, columns[], description ) CREATE OR REPLACE FUNCTION columns_are( NAME, NAME[], TEXT ) RETURNS TEXT AS $$ SELECT _are( 'columns', ARRAY( SELECT a.attname FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid WHERE n.nspname NOT IN ('pg_catalog', 'information_schema') AND pg_catalog.pg_table_is_visible(c.oid) AND c.relname = $1 AND a.attnum > 0 AND NOT a.attisdropped EXCEPT SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) ), ARRAY( SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) EXCEPT SELECT a.attname FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid WHERE n.nspname NOT IN ('pg_catalog', 'information_schema') AND pg_catalog.pg_table_is_visible(c.oid) AND c.relname = $1 AND a.attnum > 0 AND NOT a.attisdropped ), $3 ); $$ LANGUAGE SQL; -- columns_are( table, columns[] ) CREATE OR REPLACE FUNCTION columns_are( NAME, NAME[] ) RETURNS TEXT AS $$ SELECT columns_are( $1, $2, 'Table ' || quote_ident($1) || ' should have the correct columns' ); $$ LANGUAGE SQL; -- _get_db_owner( dbname ) CREATE OR REPLACE FUNCTION _get_db_owner( NAME ) RETURNS NAME AS $$ SELECT pg_catalog.pg_get_userbyid(datdba) FROM pg_catalog.pg_database WHERE datname = $1; $$ LANGUAGE SQL; -- db_owner_is ( dbname, user, description ) CREATE OR REPLACE FUNCTION db_owner_is ( NAME, NAME, TEXT ) RETURNS TEXT AS $$ DECLARE dbowner NAME := _get_db_owner($1); BEGIN -- Make sure the database exists. IF dbowner IS NULL THEN RETURN ok(FALSE, $3) || E'\n' || diag( E' Database ' || quote_ident($1) || ' does not exist' ); END IF; RETURN is(dbowner, $2, $3); END; $$ LANGUAGE plpgsql; -- db_owner_is ( dbname, user ) CREATE OR REPLACE FUNCTION db_owner_is ( NAME, NAME ) RETURNS TEXT AS $$ SELECT db_owner_is( $1, $2, 'Database ' || quote_ident($1) || ' should be owned by ' || quote_ident($2) ); $$ LANGUAGE sql; pgtap-0.90.0/sql/._uninstall_pgtap.sql.in000644 000765 000024 00000000252 11666501762 020524 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/sql/uninstall_pgtap.sql.in000644 000765 000024 00000076537 11666501762 020332 0ustar00davidstaff000000 000000 DROP FUNCTION db_owner_is ( NAME, NAME ); DROP FUNCTION db_owner_is ( NAME, NAME, TEXT ); DROP FUNCTION _get_db_owner( NAME ); DROP FUNCTION columns_are( NAME, NAME[] ); DROP FUNCTION columns_are( NAME, NAME[], TEXT ); DROP FUNCTION columns_are( NAME, NAME, NAME[] ); DROP FUNCTION columns_are( NAME, NAME, NAME[], TEXT ); DROP FUNCTION operators_are ( TEXT[] ); DROP FUNCTION operators_are( TEXT[], TEXT ); DROP FUNCTION operators_are ( NAME, TEXT[] ); DROP FUNCTION operators_are( NAME, TEXT[], TEXT ); DROP FUNCTION display_oper ( NAME, OID ); DROP FUNCTION casts_are ( TEXT[] ); DROP FUNCTION casts_are ( TEXT[], TEXT ); DROP FUNCTION _areni ( text, text[], text[], TEXT ); DROP FUNCTION triggers_are( NAME, NAME[] ); DROP FUNCTION triggers_are( NAME, NAME[], TEXT ); DROP FUNCTION triggers_are( NAME, NAME, NAME[] ); DROP FUNCTION triggers_are( NAME, NAME, NAME[], TEXT ); DROP FUNCTION row_eq( TEXT, anyelement ); DROP FUNCTION row_eq( TEXT, anyelement, TEXT ); DROP FUNCTION domain_type_isnt( TEXT, TEXT ); DROP FUNCTION domain_type_isnt( TEXT, TEXT, TEXT ); DROP FUNCTION domain_type_isnt( NAME, TEXT, TEXT ); DROP FUNCTION domain_type_isnt( NAME, TEXT, TEXT, TEXT ); DROP FUNCTION domain_type_isnt( NAME, TEXT, NAME, TEXT ); DROP FUNCTION domain_type_isnt( NAME, TEXT, NAME, TEXT, TEXT ); DROP FUNCTION domain_type_is( TEXT, TEXT ); DROP FUNCTION domain_type_is( TEXT, TEXT, TEXT ); DROP FUNCTION domain_type_is( NAME, TEXT, TEXT ); DROP FUNCTION domain_type_is( NAME, TEXT, TEXT, TEXT ); DROP FUNCTION domain_type_is( NAME, TEXT, NAME, TEXT ); DROP FUNCTION domain_type_is( NAME, TEXT, NAME, TEXT, TEXT ); DROP FUNCTION _get_dtype( NAME ); DROP FUNCTION _get_dtype( NAME, TEXT, BOOLEAN ); DROP FUNCTION _dexists ( NAME ); DROP FUNCTION _dexists ( NAME, NAME ); DROP FUNCTION enums_are ( NAME[] ); DROP FUNCTION enums_are ( NAME[], TEXT ); DROP FUNCTION enums_are ( NAME, NAME[] ); DROP FUNCTION enums_are ( NAME, NAME[], TEXT ); DROP FUNCTION domains_are ( NAME[] ); DROP FUNCTION domains_are ( NAME[], TEXT ); DROP FUNCTION domains_are ( NAME, NAME[] ); DROP FUNCTION domains_are ( NAME, NAME[], TEXT ); DROP FUNCTION types_are ( NAME[] ); DROP FUNCTION types_are ( NAME[], TEXT ); DROP FUNCTION _types_are ( NAME[], TEXT, CHAR[] ); DROP FUNCTION types_are ( NAME, NAME[] ); DROP FUNCTION types_are ( NAME, NAME[], TEXT ); DROP FUNCTION _types_are ( NAME, NAME[], TEXT, CHAR[] ); DROP FUNCTION roles_are( NAME[] ); DROP FUNCTION roles_are( NAME[], TEXT ); DROP FUNCTION throws_imatching ( TEXT, TEXT ); DROP FUNCTION throws_imatching ( TEXT, TEXT, TEXT ); DROP FUNCTION throws_matching ( TEXT, TEXT ); DROP FUNCTION throws_matching ( TEXT, TEXT, TEXT ); DROP FUNCTION throws_ilike ( TEXT, TEXT ); DROP FUNCTION throws_ilike ( TEXT, TEXT, TEXT ); DROP FUNCTION throws_like ( TEXT, TEXT ); DROP FUNCTION throws_like ( TEXT, TEXT, TEXT ); DROP FUNCTION _tlike ( BOOLEAN, TEXT, TEXT, TEXT ); DROP FUNCTION collect_tap( VARCHAR[] ); DROP FUNCTION collect_tap( VARIADIC text[] ); DROP FUNCTION is_empty( TEXT ); DROP FUNCTION is_empty( TEXT, TEXT ); DROP FUNCTION isa_ok( anyelement, regtype ); DROP FUNCTION isa_ok( anyelement, regtype, TEXT ); DROP FUNCTION results_ne( refcursor, anyarray ); DROP FUNCTION results_ne( refcursor, anyarray, TEXT ); DROP FUNCTION results_ne( refcursor, TEXT ); DROP FUNCTION results_ne( refcursor, TEXT, TEXT ); DROP FUNCTION results_ne( TEXT, refcursor ); DROP FUNCTION results_ne( TEXT, refcursor, TEXT ); DROP FUNCTION results_ne( TEXT, anyarray ); DROP FUNCTION results_ne( TEXT, anyarray, TEXT ); DROP FUNCTION results_ne( TEXT, TEXT ); DROP FUNCTION results_ne( TEXT, TEXT, TEXT ); DROP FUNCTION results_ne( refcursor, refcursor ); DROP FUNCTION results_ne( refcursor, refcursor, text ); DROP FUNCTION results_eq( refcursor, anyarray ); DROP FUNCTION results_eq( refcursor, anyarray, TEXT ); DROP FUNCTION results_eq( refcursor, TEXT ); DROP FUNCTION results_eq( refcursor, TEXT, TEXT ); DROP FUNCTION results_eq( TEXT, refcursor ); DROP FUNCTION results_eq( TEXT, refcursor, TEXT ); DROP FUNCTION results_eq( TEXT, anyarray ); DROP FUNCTION results_eq( TEXT, anyarray, TEXT ); DROP FUNCTION results_eq( TEXT, TEXT ); DROP FUNCTION results_eq( TEXT, TEXT, TEXT ); DROP FUNCTION results_eq( refcursor, refcursor ); DROP FUNCTION results_eq( refcursor, refcursor, text ); DROP FUNCTION bag_hasnt( TEXT, TEXT ); DROP FUNCTION bag_hasnt( TEXT, TEXT, TEXT ); DROP FUNCTION set_hasnt( TEXT, TEXT ); DROP FUNCTION set_hasnt( TEXT, TEXT, TEXT ); DROP FUNCTION bag_has( TEXT, TEXT ); DROP FUNCTION bag_has( TEXT, TEXT, TEXT ); DROP FUNCTION set_has( TEXT, TEXT ); DROP FUNCTION set_has( TEXT, TEXT, TEXT ); DROP FUNCTION _relcomp( TEXT, TEXT, TEXT, TEXT, TEXT ); DROP FUNCTION bag_ne( TEXT, anyarray ); DROP FUNCTION bag_ne( TEXT, anyarray, TEXT ); DROP FUNCTION bag_ne( TEXT, TEXT ); DROP FUNCTION bag_ne( TEXT, TEXT, TEXT ); DROP FUNCTION set_ne( TEXT, anyarray ); DROP FUNCTION set_ne( TEXT, anyarray, TEXT ); DROP FUNCTION set_ne( TEXT, TEXT ); DROP FUNCTION set_ne( TEXT, TEXT, TEXT ); DROP FUNCTION _relne( TEXT, anyarray, TEXT, TEXT ); DROP FUNCTION _relne( TEXT, TEXT, TEXT, TEXT ); DROP FUNCTION _do_ne( TEXT, TEXT, TEXT, TEXT ); DROP FUNCTION bag_eq( TEXT, anyarray ); DROP FUNCTION bag_eq( TEXT, anyarray, TEXT ); DROP FUNCTION bag_eq( TEXT, TEXT ); DROP FUNCTION bag_eq( TEXT, TEXT, TEXT ); DROP FUNCTION set_eq( TEXT, anyarray ); DROP FUNCTION set_eq( TEXT, anyarray, TEXT ); DROP FUNCTION set_eq( TEXT, TEXT ); DROP FUNCTION set_eq( TEXT, TEXT, TEXT ); DROP FUNCTION _relcomp( TEXT, anyarray, TEXT, TEXT ); DROP FUNCTION _relcomp( TEXT, TEXT, TEXT, TEXT ); DROP FUNCTION _docomp( TEXT, TEXT, TEXT, TEXT ); DROP FUNCTION _temptypes( TEXT ); DROP FUNCTION _temptable ( anyarray, TEXT ); DROP FUNCTION _temptable ( TEXT, TEXT ); DROP FUNCTION runtests( ); DROP FUNCTION runtests( TEXT ); DROP FUNCTION runtests( NAME ); DROP FUNCTION runtests( NAME, TEXT ); DROP FUNCTION _runner( text[], text[], text[], text[], text[] ); DROP FUNCTION diag_test_name(TEXT); DROP FUNCTION _cleanup(); DROP FUNCTION _currtest(); DROP FUNCTION do_tap( ); DROP FUNCTION do_tap( text ); DROP FUNCTION do_tap( name ); DROP FUNCTION do_tap( name, text ); DROP FUNCTION _is_verbose(); DROP FUNCTION _runem( text[], boolean ); DROP FUNCTION findfuncs( TEXT ); DROP FUNCTION findfuncs( NAME, TEXT ); DROP FUNCTION check_test( TEXT, BOOLEAN ); DROP FUNCTION check_test( TEXT, BOOLEAN, TEXT ); DROP FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT ); DROP FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT, TEXT ); DROP FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT, TEXT, BOOLEAN ); DROP FUNCTION volatility_is( NAME, TEXT ); DROP FUNCTION volatility_is( NAME, TEXT, TEXT ); DROP FUNCTION volatility_is( NAME, NAME[], TEXT ); DROP FUNCTION volatility_is( NAME, NAME[], TEXT, TEXT ); DROP FUNCTION volatility_is( NAME, NAME, TEXT ); DROP FUNCTION volatility_is( NAME, NAME, TEXT, TEXT ); DROP FUNCTION volatility_is( NAME, NAME, NAME[], TEXT ); DROP FUNCTION volatility_is( NAME, NAME, NAME[], TEXT, TEXT ); DROP FUNCTION _vol ( NAME ); DROP FUNCTION _vol ( NAME, NAME[] ); DROP FUNCTION _vol ( NAME, NAME ); DROP FUNCTION _vol ( NAME, NAME, NAME[] ); DROP FUNCTION _refine_vol( text ); DROP FUNCTION _expand_vol( char ); DROP FUNCTION is_strict( NAME ); DROP FUNCTION is_strict( NAME, TEXT ); DROP FUNCTION is_strict( NAME, NAME[] ); DROP FUNCTION is_strict ( NAME, NAME[], TEXT ); DROP FUNCTION is_strict( NAME, NAME ); DROP FUNCTION is_strict ( NAME, NAME, TEXT ); DROP FUNCTION is_strict( NAME, NAME, NAME[] ); DROP FUNCTION is_strict ( NAME, NAME, NAME[], TEXT ); DROP FUNCTION _strict ( NAME ); DROP FUNCTION _strict ( NAME, NAME[] ); DROP FUNCTION _strict ( NAME, NAME ); DROP FUNCTION _strict ( NAME, NAME, NAME[] ); DROP FUNCTION is_aggregate( NAME ); DROP FUNCTION is_aggregate( NAME, TEXT ); DROP FUNCTION is_aggregate( NAME, NAME[] ); DROP FUNCTION is_aggregate ( NAME, NAME[], TEXT ); DROP FUNCTION is_aggregate( NAME, NAME ); DROP FUNCTION is_aggregate ( NAME, NAME, TEXT ); DROP FUNCTION is_aggregate( NAME, NAME, NAME[] ); DROP FUNCTION is_aggregate ( NAME, NAME, NAME[], TEXT ); DROP FUNCTION _agg ( NAME ); DROP FUNCTION _agg ( NAME, NAME[] ); DROP FUNCTION _agg ( NAME, NAME ); DROP FUNCTION _agg ( NAME, NAME, NAME[] ); DROP FUNCTION is_definer( NAME ); DROP FUNCTION is_definer( NAME, TEXT ); DROP FUNCTION is_definer( NAME, NAME[] ); DROP FUNCTION is_definer ( NAME, NAME[], TEXT ); DROP FUNCTION is_definer( NAME, NAME ); DROP FUNCTION is_definer ( NAME, NAME, TEXT ); DROP FUNCTION is_definer( NAME, NAME, NAME[] ); DROP FUNCTION is_definer ( NAME, NAME, NAME[], TEXT ); DROP FUNCTION _definer ( NAME ); DROP FUNCTION _definer ( NAME, NAME[] ); DROP FUNCTION _definer ( NAME, NAME ); DROP FUNCTION _definer ( NAME, NAME, NAME[] ); DROP FUNCTION function_returns( NAME, TEXT ); DROP FUNCTION function_returns( NAME, TEXT, TEXT ); DROP FUNCTION function_returns( NAME, NAME[], TEXT ); DROP FUNCTION function_returns( NAME, NAME[], TEXT, TEXT ); DROP FUNCTION function_returns( NAME, NAME, TEXT ); DROP FUNCTION function_returns( NAME, NAME, TEXT, TEXT ); DROP FUNCTION function_returns( NAME, NAME, NAME[], TEXT ); DROP FUNCTION function_returns( NAME, NAME, NAME[], TEXT, TEXT ); DROP FUNCTION _returns ( NAME ); DROP FUNCTION _returns ( NAME, NAME[] ); DROP FUNCTION _returns ( NAME, NAME ); DROP FUNCTION _returns ( NAME, NAME, NAME[] ); DROP FUNCTION function_lang_is( NAME, NAME ); DROP FUNCTION function_lang_is( NAME, NAME, TEXT ); DROP FUNCTION function_lang_is( NAME, NAME[], NAME ); DROP FUNCTION function_lang_is( NAME, NAME[], NAME, TEXT ); DROP FUNCTION function_lang_is( NAME, NAME, NAME ); DROP FUNCTION function_lang_is( NAME, NAME, NAME, TEXT ); DROP FUNCTION function_lang_is( NAME, NAME, NAME[], NAME ); DROP FUNCTION function_lang_is( NAME, NAME, NAME[], NAME, TEXT ); DROP FUNCTION _lang ( NAME ); DROP FUNCTION _lang ( NAME, NAME[] ); DROP FUNCTION _lang ( NAME, NAME ); DROP FUNCTION _lang ( NAME, NAME, NAME[] ); DROP FUNCTION _func_compare( NAME, NAME, boolean, TEXT); DROP FUNCTION _func_compare( NAME, NAME, anyelement, anyelement, TEXT); DROP FUNCTION _func_compare( NAME, NAME, NAME[], boolean, TEXT); DROP FUNCTION _func_compare( NAME, NAME, NAME[], anyelement, anyelement, TEXT); DROP FUNCTION _nosuch( NAME, NAME, NAME[]); DROP FUNCTION rule_is_on( NAME, NAME, TEXT ); DROP FUNCTION rule_is_on( NAME, NAME, TEXT, TEXT ); DROP FUNCTION rule_is_on( NAME, NAME, NAME, TEXT ); DROP FUNCTION rule_is_on( NAME, NAME, NAME, TEXT, TEXT ); DROP FUNCTION _rule_on( NAME, NAME ); DROP FUNCTION _rule_on( NAME, NAME, NAME ); DROP FUNCTION _contract_on( TEXT ); DROP FUNCTION _expand_on( char ); DROP FUNCTION rule_is_instead( NAME, NAME ); DROP FUNCTION rule_is_instead( NAME, NAME, TEXT ); DROP FUNCTION rule_is_instead( NAME, NAME, NAME ); DROP FUNCTION rule_is_instead( NAME, NAME, NAME, TEXT ); DROP FUNCTION hasnt_rule( NAME, NAME ); DROP FUNCTION hasnt_rule( NAME, NAME, TEXT ); DROP FUNCTION hasnt_rule( NAME, NAME, NAME ); DROP FUNCTION hasnt_rule( NAME, NAME, NAME, TEXT ); DROP FUNCTION has_rule( NAME, NAME ); DROP FUNCTION has_rule( NAME, NAME, TEXT ); DROP FUNCTION has_rule( NAME, NAME, NAME ); DROP FUNCTION has_rule( NAME, NAME, NAME, TEXT ); DROP FUNCTION _is_instead( NAME, NAME ); DROP FUNCTION _is_instead( NAME, NAME, NAME ); DROP FUNCTION rules_are( NAME, NAME[] ); DROP FUNCTION rules_are( NAME, NAME[], TEXT ); DROP FUNCTION rules_are( NAME, NAME, NAME[] ); DROP FUNCTION rules_are( NAME, NAME, NAME[], TEXT ); DROP FUNCTION opclasses_are ( NAME[] ); DROP FUNCTION opclasses_are ( NAME[], TEXT ); DROP FUNCTION opclasses_are ( NAME, NAME[] ); DROP FUNCTION opclasses_are ( NAME, NAME[], TEXT ); DROP FUNCTION hasnt_opclass( NAME ); DROP FUNCTION hasnt_opclass( NAME, TEXT ); DROP FUNCTION hasnt_opclass( NAME, NAME ); DROP FUNCTION hasnt_opclass( NAME, NAME, TEXT ); DROP FUNCTION has_opclass( NAME ); DROP FUNCTION has_opclass( NAME, TEXT ); DROP FUNCTION has_opclass( NAME, NAME ); DROP FUNCTION has_opclass( NAME, NAME, TEXT ); DROP FUNCTION _opc_exists( NAME, NAME ); DROP FUNCTION language_is_trusted( NAME ); DROP FUNCTION language_is_trusted( NAME, TEXT ); DROP FUNCTION hasnt_language( NAME ); DROP FUNCTION hasnt_language( NAME, TEXT ); DROP FUNCTION has_language( NAME ); DROP FUNCTION has_language( NAME, TEXT ); DROP FUNCTION _is_trusted( NAME ); DROP FUNCTION languages_are( NAME[] ); DROP FUNCTION languages_are( NAME[], TEXT ); DROP FUNCTION groups_are( NAME[] ); DROP FUNCTION groups_are( NAME[], TEXT ); DROP FUNCTION users_are( NAME[] ); DROP FUNCTION users_are( NAME[], TEXT ); DROP FUNCTION indexes_are( NAME, NAME[] ); DROP FUNCTION indexes_are( NAME, NAME[], TEXT ); DROP FUNCTION indexes_are( NAME, NAME, NAME[] ); DROP FUNCTION indexes_are( NAME, NAME, NAME[], TEXT ); DROP FUNCTION functions_are ( NAME[] ); DROP FUNCTION functions_are ( NAME[], TEXT ); DROP FUNCTION functions_are ( NAME, NAME[] ); DROP FUNCTION functions_are ( NAME, NAME[], TEXT ); DROP FUNCTION sequences_are ( NAME[] ); DROP FUNCTION sequences_are ( NAME, NAME[] ); DROP FUNCTION sequences_are ( NAME[], TEXT ); DROP FUNCTION sequences_are ( NAME, NAME[], TEXT ); DROP FUNCTION views_are ( NAME[] ); DROP FUNCTION views_are ( NAME, NAME[] ); DROP FUNCTION views_are ( NAME[], TEXT ); DROP FUNCTION views_are ( NAME, NAME[], TEXT ); DROP FUNCTION tables_are ( NAME[] ); DROP FUNCTION tables_are ( NAME, NAME[] ); DROP FUNCTION tables_are ( NAME[], TEXT ); DROP FUNCTION tables_are ( NAME, NAME[], TEXT ); DROP FUNCTION _missing ( CHAR, NAME[] ); DROP FUNCTION _missing ( CHAR, NAME, NAME[] ); DROP FUNCTION _extras ( CHAR, NAME[] ); DROP FUNCTION _extras ( CHAR, NAME, NAME[] ); DROP FUNCTION schemas_are ( NAME[] ); DROP FUNCTION schemas_are ( NAME[], TEXT ); DROP FUNCTION tablespaces_are ( NAME[] ); DROP FUNCTION tablespaces_are ( NAME[], TEXT ); DROP FUNCTION _are ( text, name[], name[], TEXT ); DROP FUNCTION has_rightop ( NAME, NAME ); DROP FUNCTION has_rightop ( NAME, NAME, TEXT ); DROP FUNCTION has_rightop ( NAME, NAME, NAME ); DROP FUNCTION has_rightop ( NAME, NAME, NAME, TEXT ); DROP FUNCTION has_rightop ( NAME, NAME, NAME, NAME ); DROP FUNCTION has_rightop ( NAME, NAME, NAME, NAME, TEXT ); DROP FUNCTION has_leftop ( NAME, NAME ); DROP FUNCTION has_leftop ( NAME, NAME, TEXT ); DROP FUNCTION has_leftop ( NAME, NAME, NAME ); DROP FUNCTION has_leftop ( NAME, NAME, NAME, TEXT ); DROP FUNCTION has_leftop ( NAME, NAME, NAME, NAME ); DROP FUNCTION has_leftop ( NAME, NAME, NAME, NAME, TEXT ); DROP FUNCTION has_operator ( NAME, NAME, NAME ); DROP FUNCTION has_operator ( NAME, NAME, NAME, TEXT ); DROP FUNCTION has_operator ( NAME, NAME, NAME, NAME ); DROP FUNCTION has_operator ( NAME, NAME, NAME, NAME, TEXT ); DROP FUNCTION has_operator ( NAME, NAME, NAME, NAME, NAME ); DROP FUNCTION has_operator ( NAME, NAME, NAME, NAME, NAME, TEXT ); DROP FUNCTION _op_exists ( NAME, NAME, NAME ); DROP FUNCTION _op_exists ( NAME, NAME, NAME, NAME ); DROP FUNCTION _op_exists ( NAME, NAME, NAME, NAME, NAME ); DROP FUNCTION cast_context_is( NAME, NAME, TEXT ); DROP FUNCTION cast_context_is( NAME, NAME, TEXT, TEXT ); DROP FUNCTION _get_context( NAME, NAME ); DROP FUNCTION _expand_context( char ); DROP FUNCTION hasnt_cast ( NAME, NAME ); DROP FUNCTION hasnt_cast ( NAME, NAME, TEXT ); DROP FUNCTION hasnt_cast ( NAME, NAME, NAME ); DROP FUNCTION hasnt_cast ( NAME, NAME, NAME, TEXT ); DROP FUNCTION hasnt_cast ( NAME, NAME, NAME, NAME ); DROP FUNCTION hasnt_cast ( NAME, NAME, NAME, NAME, TEXT ); DROP FUNCTION has_cast ( NAME, NAME ); DROP FUNCTION has_cast ( NAME, NAME, TEXT ); DROP FUNCTION has_cast ( NAME, NAME, NAME ); DROP FUNCTION has_cast ( NAME, NAME, NAME, TEXT ); DROP FUNCTION has_cast ( NAME, NAME, NAME, NAME ); DROP FUNCTION has_cast ( NAME, NAME, NAME, NAME, TEXT ); DROP FUNCTION _cast_exists ( NAME, NAME ); DROP FUNCTION _cast_exists ( NAME, NAME, NAME ); DROP FUNCTION _cast_exists ( NAME, NAME, NAME, NAME ); DROP FUNCTION _cmp_types(oid, name); DROP FUNCTION is_member_of( NAME, NAME ); DROP FUNCTION is_member_of( NAME, NAME[] ); DROP FUNCTION is_member_of( NAME, NAME, TEXT ); DROP FUNCTION is_member_of( NAME, NAME[], TEXT ); DROP FUNCTION _grolist ( NAME ); DROP FUNCTION hasnt_group( NAME ); DROP FUNCTION hasnt_group( NAME, TEXT ); DROP FUNCTION has_group( NAME ); DROP FUNCTION has_group( NAME, TEXT ); DROP FUNCTION _has_group( NAME ); DROP FUNCTION isnt_superuser( NAME ); DROP FUNCTION isnt_superuser( NAME, TEXT ); DROP FUNCTION is_superuser( NAME ); DROP FUNCTION is_superuser( NAME, TEXT ); DROP FUNCTION _is_super( NAME ); DROP FUNCTION hasnt_user( NAME ); DROP FUNCTION hasnt_user( NAME, TEXT ); DROP FUNCTION has_user( NAME ); DROP FUNCTION has_user( NAME, TEXT ); DROP FUNCTION _has_user( NAME ); DROP FUNCTION hasnt_role( NAME ); DROP FUNCTION hasnt_role( NAME, TEXT ); DROP FUNCTION has_role( NAME ); DROP FUNCTION has_role( NAME, TEXT ); DROP FUNCTION _has_role( NAME ); DROP FUNCTION enum_has_labels( NAME, NAME[] ); DROP FUNCTION enum_has_labels( NAME, NAME[], TEXT ); DROP FUNCTION enum_has_labels( NAME, NAME, NAME[] ); DROP FUNCTION enum_has_labels( NAME, NAME, NAME[], TEXT ); DROP FUNCTION hasnt_enum( NAME ); DROP FUNCTION hasnt_enum( NAME, TEXT ); DROP FUNCTION hasnt_enum( NAME, NAME ); DROP FUNCTION hasnt_enum( NAME, NAME, TEXT ); DROP FUNCTION has_enum( NAME ); DROP FUNCTION has_enum( NAME, TEXT ); DROP FUNCTION has_enum( NAME, NAME ); DROP FUNCTION has_enum( NAME, NAME, TEXT ); DROP FUNCTION hasnt_domain( NAME ); DROP FUNCTION hasnt_domain( NAME, TEXT ); DROP FUNCTION hasnt_domain( NAME, NAME ); DROP FUNCTION hasnt_domain( NAME, NAME, TEXT ); DROP FUNCTION has_domain( NAME ); DROP FUNCTION has_domain( NAME, TEXT ); DROP FUNCTION has_domain( NAME, NAME ); DROP FUNCTION has_domain( NAME, NAME, TEXT ); DROP FUNCTION hasnt_type( NAME ); DROP FUNCTION hasnt_type( NAME, TEXT ); DROP FUNCTION hasnt_type( NAME, NAME ); DROP FUNCTION hasnt_type( NAME, NAME, TEXT ); DROP FUNCTION has_type( NAME ); DROP FUNCTION has_type( NAME, TEXT ); DROP FUNCTION has_type( NAME, NAME ); DROP FUNCTION has_type( NAME, NAME, TEXT ); DROP FUNCTION _has_type( NAME, CHAR[] ); DROP FUNCTION _has_type( NAME, NAME, CHAR[] ); DROP FUNCTION hasnt_tablespace( NAME ); DROP FUNCTION hasnt_tablespace( NAME, TEXT ); DROP FUNCTION has_tablespace( NAME ); DROP FUNCTION has_tablespace( NAME, TEXT ); DROP FUNCTION has_tablespace( NAME, TEXT, TEXT ); DROP FUNCTION hasnt_schema( NAME ); DROP FUNCTION hasnt_schema( NAME, TEXT ); DROP FUNCTION has_schema( NAME ); DROP FUNCTION has_schema( NAME, TEXT ); DROP FUNCTION trigger_is ( NAME, NAME, NAME ); DROP FUNCTION trigger_is ( NAME, NAME, NAME, text ); DROP FUNCTION trigger_is ( NAME, NAME, NAME, NAME, NAME ); DROP FUNCTION trigger_is ( NAME, NAME, NAME, NAME, NAME, text ); DROP FUNCTION hasnt_trigger ( NAME, NAME ); DROP FUNCTION hasnt_trigger ( NAME, NAME, TEXT ); DROP FUNCTION hasnt_trigger ( NAME, NAME, NAME ); DROP FUNCTION hasnt_trigger ( NAME, NAME, NAME, TEXT ); DROP FUNCTION has_trigger ( NAME, NAME ); DROP FUNCTION has_trigger ( NAME, NAME, TEXT ); DROP FUNCTION has_trigger ( NAME, NAME, NAME ); DROP FUNCTION has_trigger ( NAME, NAME, NAME, TEXT ); DROP FUNCTION _trig ( NAME, NAME ); DROP FUNCTION _trig ( NAME, NAME, NAME ); DROP FUNCTION index_is_type ( NAME, NAME ); DROP FUNCTION index_is_type ( NAME, NAME, NAME ); DROP FUNCTION index_is_type ( NAME, NAME, NAME, NAME ); DROP FUNCTION index_is_type ( NAME, NAME, NAME, NAME, text ); DROP FUNCTION is_clustered ( NAME ); DROP FUNCTION is_clustered ( NAME, NAME ); DROP FUNCTION is_clustered ( NAME, NAME, NAME ); DROP FUNCTION is_clustered ( NAME, NAME, NAME, text ); DROP FUNCTION index_is_primary ( NAME ); DROP FUNCTION index_is_primary ( NAME, NAME ); DROP FUNCTION index_is_primary ( NAME, NAME, NAME ); DROP FUNCTION index_is_primary ( NAME, NAME, NAME, text ); DROP FUNCTION index_is_unique ( NAME ); DROP FUNCTION index_is_unique ( NAME, NAME ); DROP FUNCTION index_is_unique ( NAME, NAME, NAME ); DROP FUNCTION index_is_unique ( NAME, NAME, NAME, text ); DROP FUNCTION hasnt_index ( NAME, NAME ); DROP FUNCTION hasnt_index ( NAME, NAME, TEXT ); DROP FUNCTION hasnt_index ( NAME, NAME, NAME ); DROP FUNCTION hasnt_index ( NAME, NAME, NAME, TEXT ); DROP FUNCTION has_index ( NAME, NAME ); DROP FUNCTION has_index ( NAME, NAME, text ); DROP FUNCTION has_index ( NAME, NAME, NAME ); DROP FUNCTION has_index ( NAME, NAME, NAME, text ); DROP FUNCTION _is_schema( NAME ); DROP FUNCTION has_index ( NAME, NAME, NAME[] ); DROP FUNCTION has_index ( NAME, NAME, NAME[], text ); DROP FUNCTION has_index ( NAME, NAME, NAME, NAME ); DROP FUNCTION has_index ( NAME, NAME, NAME, NAME, text ); DROP FUNCTION has_index ( NAME, NAME, NAME, NAME[] ); DROP FUNCTION has_index ( NAME, NAME, NAME, NAME[], text ); DROP FUNCTION _iexpr( NAME, NAME); DROP FUNCTION _iexpr( NAME, NAME, NAME); DROP FUNCTION _have_index( NAME, NAME); DROP FUNCTION _have_index( NAME, NAME, NAME); DROP FUNCTION _ikeys( NAME, NAME); DROP FUNCTION _ikeys( NAME, NAME, NAME); DROP FUNCTION can ( NAME[] ); DROP FUNCTION can ( NAME[], TEXT ); DROP FUNCTION can ( NAME, NAME[] ); DROP FUNCTION can ( NAME, NAME[], TEXT ); DROP FUNCTION _pg_sv_type_array( OID[] ); DROP FUNCTION hasnt_function( NAME ); DROP FUNCTION hasnt_function( NAME, TEXT ); DROP FUNCTION hasnt_function( NAME, NAME[] ); DROP FUNCTION hasnt_function ( NAME, NAME[], TEXT ); DROP FUNCTION hasnt_function( NAME, NAME ); DROP FUNCTION hasnt_function ( NAME, NAME, TEXT ); DROP FUNCTION hasnt_function( NAME, NAME, NAME[] ); DROP FUNCTION hasnt_function ( NAME, NAME, NAME[], TEXT ); DROP FUNCTION has_function( NAME ); DROP FUNCTION has_function( NAME, TEXT ); DROP FUNCTION has_function( NAME, NAME[] ); DROP FUNCTION has_function ( NAME, NAME[], TEXT ); DROP FUNCTION has_function( NAME, NAME ); DROP FUNCTION has_function ( NAME, NAME, TEXT ); DROP FUNCTION has_function( NAME, NAME, NAME[] ); DROP FUNCTION has_function ( NAME, NAME, NAME[], TEXT ); DROP FUNCTION _got_func ( NAME ); DROP FUNCTION _got_func ( NAME, NAME[] ); DROP FUNCTION _got_func ( NAME, NAME ); DROP FUNCTION _got_func ( NAME, NAME, NAME[] ); DROP VIEW tap_funky; DROP FUNCTION fk_ok ( NAME, NAME, NAME, NAME ); DROP FUNCTION fk_ok ( NAME, NAME, NAME, NAME, TEXT ); DROP FUNCTION fk_ok ( NAME, NAME, NAME, NAME, NAME, TEXT ); DROP FUNCTION fk_ok ( NAME, NAME, NAME, NAME, NAME, NAME, TEXT ); DROP FUNCTION fk_ok ( NAME, NAME[], NAME, NAME[] ); DROP FUNCTION fk_ok ( NAME, NAME, NAME[], NAME, NAME, NAME[] ); DROP FUNCTION fk_ok ( NAME, NAME[], NAME, NAME[], TEXT ); DROP FUNCTION fk_ok ( NAME, NAME, NAME[], NAME, NAME, NAME[], TEXT ); DROP FUNCTION col_has_check ( NAME, NAME ); DROP FUNCTION col_has_check ( NAME, NAME, TEXT ); DROP FUNCTION col_has_check ( NAME, NAME, NAME, TEXT ); DROP FUNCTION col_has_check ( NAME, NAME[] ); DROP FUNCTION col_has_check ( NAME, NAME[], TEXT ); DROP FUNCTION col_has_check ( NAME, NAME, NAME[], TEXT ); DROP FUNCTION has_check ( NAME ); DROP FUNCTION has_check ( NAME, TEXT ); DROP FUNCTION has_check ( NAME, NAME, TEXT ); DROP FUNCTION col_is_unique ( NAME, NAME ); DROP FUNCTION col_is_unique ( NAME, NAME, TEXT ); DROP FUNCTION col_is_unique ( NAME, NAME, NAME, TEXT ); DROP FUNCTION col_is_unique ( NAME, NAME[] ); DROP FUNCTION col_is_unique ( NAME, NAME[], TEXT ); DROP FUNCTION col_is_unique ( NAME, NAME, NAME[], TEXT ); DROP FUNCTION _constraint ( NAME, CHAR, NAME[], TEXT, TEXT ); DROP FUNCTION _constraint ( NAME, NAME, CHAR, NAME[], TEXT, TEXT ); DROP FUNCTION has_unique ( TEXT ); DROP FUNCTION has_unique ( TEXT, TEXT ); DROP FUNCTION has_unique ( TEXT, TEXT, TEXT ); DROP FUNCTION col_isnt_fk ( NAME, NAME ); DROP FUNCTION col_isnt_fk ( NAME, NAME, TEXT ); DROP FUNCTION col_isnt_fk ( NAME, NAME, NAME, TEXT ); DROP FUNCTION col_isnt_fk ( NAME, NAME[] ); DROP FUNCTION col_isnt_fk ( NAME, NAME[], TEXT ); DROP FUNCTION col_isnt_fk ( NAME, NAME, NAME[], TEXT ); DROP FUNCTION col_is_fk ( NAME, NAME ); DROP FUNCTION col_is_fk ( NAME, NAME, TEXT ); DROP FUNCTION col_is_fk ( NAME, NAME, NAME, TEXT ); DROP FUNCTION col_is_fk ( NAME, NAME[] ); DROP FUNCTION col_is_fk ( NAME, NAME[], TEXT ); DROP FUNCTION col_is_fk ( NAME, NAME, NAME[], TEXT ); DROP FUNCTION _fkexists ( NAME, NAME[] ); DROP FUNCTION _fkexists ( NAME, NAME, NAME[] ); DROP FUNCTION hasnt_fk ( NAME ); DROP FUNCTION hasnt_fk ( NAME, TEXT ); DROP FUNCTION hasnt_fk ( NAME, NAME, TEXT ); DROP FUNCTION has_fk ( NAME ); DROP FUNCTION has_fk ( NAME, TEXT ); DROP FUNCTION has_fk ( NAME, NAME, TEXT ); DROP FUNCTION col_isnt_pk ( NAME, NAME ); DROP FUNCTION col_isnt_pk ( NAME, NAME, TEXT ); DROP FUNCTION col_isnt_pk ( NAME, NAME, NAME, TEXT ); DROP FUNCTION col_isnt_pk ( NAME, NAME[] ); DROP FUNCTION col_isnt_pk ( NAME, NAME[], TEXT ); DROP FUNCTION col_isnt_pk ( NAME, NAME, NAME[], TEXT ); DROP FUNCTION col_is_pk ( NAME, NAME ); DROP FUNCTION col_is_pk ( NAME, NAME, TEXT ); DROP FUNCTION col_is_pk ( NAME, NAME, NAME, TEXT ); DROP FUNCTION col_is_pk ( NAME, NAME[] ); DROP FUNCTION col_is_pk ( NAME, NAME[], TEXT ); DROP FUNCTION col_is_pk ( NAME, NAME, NAME[], TEXT ); DROP FUNCTION _ckeys ( NAME, CHAR ); DROP FUNCTION _ckeys ( NAME, NAME, CHAR ); DROP FUNCTION _keys ( NAME, CHAR ); DROP FUNCTION _keys ( NAME, NAME, CHAR ); DROP VIEW pg_all_foreign_keys; DROP FUNCTION _pg_sv_table_accessible( OID, OID ); DROP FUNCTION _pg_sv_column_array( OID, SMALLINT[] ); DROP FUNCTION _ident_array_to_string( name[], text ); DROP FUNCTION hasnt_pk ( NAME ); DROP FUNCTION hasnt_pk ( NAME, TEXT ); DROP FUNCTION hasnt_pk ( NAME, NAME, TEXT ); DROP FUNCTION has_pk ( NAME ); DROP FUNCTION has_pk ( NAME, TEXT ); DROP FUNCTION has_pk ( NAME, NAME, TEXT ); DROP FUNCTION _hasc ( NAME, CHAR ); DROP FUNCTION _hasc ( NAME, NAME, CHAR ); DROP FUNCTION col_default_is ( NAME, NAME, text ); DROP FUNCTION col_default_is ( NAME, NAME, anyelement ); DROP FUNCTION col_default_is ( NAME, NAME, TEXT, TEXT ); DROP FUNCTION col_default_is ( NAME, NAME, anyelement, TEXT ); DROP FUNCTION col_default_is ( NAME, NAME, NAME, TEXT, TEXT ); DROP FUNCTION col_default_is ( NAME, NAME, NAME, anyelement, TEXT ); DROP FUNCTION _cdi ( NAME, NAME, anyelement ); DROP FUNCTION _cdi ( NAME, NAME, anyelement, TEXT ); DROP FUNCTION _cdi ( NAME, NAME, NAME, anyelement, TEXT ); DROP FUNCTION _def_is( TEXT, TEXT, anyelement, TEXT ); DROP FUNCTION col_hasnt_default ( NAME, NAME ); DROP FUNCTION col_hasnt_default ( NAME, NAME, TEXT ); DROP FUNCTION col_hasnt_default ( NAME, NAME, NAME, TEXT ); DROP FUNCTION col_has_default ( NAME, NAME ); DROP FUNCTION col_has_default ( NAME, NAME, TEXT ); DROP FUNCTION col_has_default ( NAME, NAME, NAME, TEXT ); DROP FUNCTION _has_def ( NAME, NAME ); DROP FUNCTION _has_def ( NAME, NAME, NAME ); DROP FUNCTION col_type_is ( NAME, NAME, TEXT ); DROP FUNCTION col_type_is ( NAME, NAME, TEXT, TEXT ); DROP FUNCTION col_type_is ( NAME, NAME, NAME, TEXT ); DROP FUNCTION col_type_is ( NAME, NAME, NAME, TEXT, TEXT ); DROP FUNCTION col_type_is ( NAME, NAME, NAME, NAME, TEXT ); DROP FUNCTION col_type_is ( NAME, NAME, NAME, NAME, TEXT, TEXT ); DROP FUNCTION _quote_ident_like(TEXT, TEXT); DROP FUNCTION _get_col_ns_type ( NAME, NAME, NAME ); DROP FUNCTION _get_col_type ( NAME, NAME ); DROP FUNCTION _get_col_type ( NAME, NAME, NAME ); DROP FUNCTION display_type ( NAME, OID, INTEGER ); DROP FUNCTION display_type ( OID, INTEGER ); DROP FUNCTION col_is_null ( NAME, NAME ); DROP FUNCTION col_is_null ( NAME, NAME, NAME ); DROP FUNCTION col_is_null ( NAME, NAME, NAME, TEXT ); DROP FUNCTION col_not_null ( NAME, NAME ); DROP FUNCTION col_not_null ( NAME, NAME, TEXT ); DROP FUNCTION col_not_null ( NAME, NAME, NAME, TEXT ); DROP FUNCTION _col_is_null ( NAME, NAME, TEXT, bool ); DROP FUNCTION _col_is_null ( NAME, NAME, NAME, TEXT, bool ); DROP FUNCTION hasnt_column ( NAME, NAME ); DROP FUNCTION hasnt_column ( NAME, NAME, TEXT ); DROP FUNCTION hasnt_column ( NAME, NAME, NAME, TEXT ); DROP FUNCTION has_column ( NAME, NAME ); DROP FUNCTION has_column ( NAME, NAME, TEXT ); DROP FUNCTION has_column ( NAME, NAME, NAME, TEXT ); DROP FUNCTION _cexists ( NAME, NAME ); DROP FUNCTION _cexists ( NAME, NAME, NAME ); DROP FUNCTION hasnt_sequence ( NAME ); DROP FUNCTION hasnt_sequence ( NAME, TEXT ); DROP FUNCTION hasnt_sequence ( NAME, NAME, TEXT ); DROP FUNCTION has_sequence ( NAME ); DROP FUNCTION has_sequence ( NAME, TEXT ); DROP FUNCTION has_sequence ( NAME, NAME, TEXT ); DROP FUNCTION hasnt_view ( NAME ); DROP FUNCTION hasnt_view ( NAME, TEXT ); DROP FUNCTION hasnt_view ( NAME, NAME, TEXT ); DROP FUNCTION has_view ( NAME ); DROP FUNCTION has_view ( NAME, TEXT ); DROP FUNCTION has_view ( NAME, NAME, TEXT ); DROP FUNCTION hasnt_table ( NAME ); DROP FUNCTION hasnt_table ( NAME, TEXT ); DROP FUNCTION hasnt_table ( NAME, NAME, TEXT ); DROP FUNCTION has_table ( NAME ); DROP FUNCTION has_table ( NAME, TEXT ); DROP FUNCTION has_table ( NAME, NAME, TEXT ); DROP FUNCTION _rexists ( CHAR, NAME ); DROP FUNCTION _rexists ( CHAR, NAME, NAME ); DROP FUNCTION performs_ok ( TEXT, NUMERIC ); DROP FUNCTION performs_ok ( TEXT, NUMERIC, TEXT ); DROP FUNCTION lives_ok ( TEXT ); DROP FUNCTION lives_ok ( TEXT, TEXT ); DROP FUNCTION throws_ok ( TEXT, int4 ); DROP FUNCTION throws_ok ( TEXT, int4, TEXT ); DROP FUNCTION throws_ok ( TEXT, int4, TEXT, TEXT ); DROP FUNCTION throws_ok ( TEXT ); DROP FUNCTION throws_ok ( TEXT, TEXT ); DROP FUNCTION throws_ok ( TEXT, TEXT, TEXT ); DROP FUNCTION throws_ok ( TEXT, CHAR(5), TEXT, TEXT ); DROP FUNCTION _query( TEXT ); DROP FUNCTION skip( int ); DROP FUNCTION skip( int, text ); DROP FUNCTION skip ( text ); DROP FUNCTION skip ( why text, how_many int ); DROP FUNCTION _todo(); DROP FUNCTION todo_end (); DROP FUNCTION in_todo (); DROP FUNCTION todo_start (); DROP FUNCTION todo_start (text); DROP FUNCTION todo ( how_many int ); DROP FUNCTION todo ( why text ); DROP FUNCTION todo ( how_many int, why text ); DROP FUNCTION todo ( why text, how_many int ); DROP FUNCTION fail (); DROP FUNCTION fail ( text ); DROP FUNCTION pass (); DROP FUNCTION pass ( text ); DROP FUNCTION cmp_ok (anyelement, text, anyelement); DROP FUNCTION cmp_ok (anyelement, text, anyelement, text); DROP FUNCTION unialike ( anyelement, text ); DROP FUNCTION unialike ( anyelement, text, text ); DROP FUNCTION unalike ( anyelement, text ); DROP FUNCTION unalike ( anyelement, text, text ); DROP FUNCTION doesnt_imatch ( anyelement, text ); DROP FUNCTION doesnt_imatch ( anyelement, text, text ); DROP FUNCTION doesnt_match ( anyelement, text ); DROP FUNCTION doesnt_match ( anyelement, text, text ); DROP FUNCTION _unalike ( BOOLEAN, ANYELEMENT, TEXT, TEXT ); DROP FUNCTION ialike ( anyelement, text ); DROP FUNCTION ialike ( anyelement, text, text ); DROP FUNCTION alike ( anyelement, text ); DROP FUNCTION alike ( anyelement, text, text ); DROP FUNCTION imatches ( anyelement, text ); DROP FUNCTION imatches ( anyelement, text, text ); DROP FUNCTION matches ( anyelement, text ); DROP FUNCTION matches ( anyelement, text, text ); DROP FUNCTION _alike ( BOOLEAN, ANYELEMENT, TEXT, TEXT ); DROP FUNCTION isnt (anyelement, anyelement); DROP FUNCTION isnt (anyelement, anyelement, text); DROP FUNCTION is (anyelement, anyelement); DROP FUNCTION is (anyelement, anyelement, text); DROP FUNCTION ok ( boolean ); DROP FUNCTION ok ( boolean, text ); DROP FUNCTION diag( VARIADIC anyarray ); DROP FUNCTION diag( VARIADIC text[] ); DROP FUNCTION diag ( msg anyelement ); DROP FUNCTION diag ( msg text ); DROP FUNCTION finish (); DROP FUNCTION _finish ( INTEGER, INTEGER, INTEGER); DROP FUNCTION num_failed (); DROP FUNCTION add_result ( bool, bool, text, text, text ); DROP FUNCTION _add ( text, integer ); DROP FUNCTION _add ( text, integer, text ); DROP FUNCTION _set ( integer, integer ); DROP FUNCTION _set ( text, integer ); DROP FUNCTION _set ( text, integer, text ); DROP FUNCTION _get_note ( integer ); DROP FUNCTION _get_note ( text ); DROP FUNCTION _get_latest ( text, integer ); DROP FUNCTION _get_latest ( text ); DROP FUNCTION _get ( text ); DROP FUNCTION no_plan(); DROP FUNCTION plan( integer ); DROP FUNCTION pgtap_version(); DROP FUNCTION os_name(); DROP FUNCTION pg_version_num(); DROP FUNCTION pg_version(); pgtap-0.90.0/doc/._pgtap.mmd000644 000765 000024 00000000252 11666501762 015752 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/doc/pgtap.mmd000644 000765 000024 00000551166 11666501762 015554 0ustar00davidstaff000000 000000 pgTAP 0.90.0 ============ pgTAP is a unit testing framework for PostgreSQL written in PL/pgSQL and PL/SQL. It includes a comprehensive collection of [TAP](http://testanything.org)-emitting assertion functions, as well as the ability to integrate with other TAP-emitting test frameworks. It can also be used in the xUnit testing style. Synopsis ======== SELECT plan( 23 ); -- or SELECT * from no_plan(); -- Various ways to say "ok" SELECT ok( :have = :want, :test_description ); SELECT is( :have, :want, $test_description ); SELECT isnt( :have, :want, $test_description ); -- Rather than \echo # here's what went wrong SELECT diag( 'here''s what went wrong' ); -- Compare values with LIKE or regular expressions. SELECT alike( :have, :like_expression, $test_description ); SELECT unalike( :have, :like_expression, $test_description ); SELECT matches( :have, :regex, $test_description ); SELECT doesnt_match( :have, :regex, $test_description ); SELECT cmp_ok(:have, '=', :want, $test_description ); -- Skip tests based on runtime conditions. SELECT CASE WHEN :some_feature THEN collect_tap( ok( foo(), :test_description), is( foo(42), 23, :test_description) ) ELSE skip(:why, :how_many ) END; -- Mark some tests as to-do tests. SELECT todo(:why, :how_many); SELECT ok( foo(), :test_description); SELECT is( foo(42), 23, :test_description); -- Simple pass/fail. SELECT pass(:test_description); SELECT fail(:test_description); Installation ============ For the impatient, to install pgTAP into a PostgreSQL database, just do this: make make install make installcheck If you encounter an error such as: "Makefile", line 8: Need an operator You need to use GNU make, which may well be installed on your system as 'gmake': gmake gmake install gmake installcheck If you encounter an error such as: make: pg_config: Command not found Or: Makefile:52: *** pgTAP requires PostgreSQL 8.1 or later. This is . Stop. 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 && make installcheck And finally, if all that fails (and if you're on PostgreSQL 8.1, it likely will), copy the entire distribution directory to the `contrib/` subdirectory of the PostgreSQL source tree and try it there without `pg_config`: env NO_PGXS=1 make && make install && make installcheck If you encounter an error such as: ERROR: must be owner of database regression You need to run the test suite using a super user, such as the default "postgres" super user: make installcheck PGUSER=postgres Once pgTAP is installed, you can add it to a database. If you're running PostgreSQL 9.1.0 or greater, it's a simple as connecting to a database as a super user and running: CREATE EXTENSION pgtap; If you've upgraded your cluster to PostgreSQL 9.1 and already had pgTAP installed, you can upgrade it to a properly packaged extension with: CREATE EXTENSION pgtap FROM unpackaged; For versions of PostgreSQL less than 9.1.0, you'll need to run the installation script: psql -d mydb -f /path/to/pgsql/share/contrib/pgtap.sql If you want to install pgTAP and all of its supporting objects into a specific schema, use the `PGOPTIONS` environment variable to specify the schema, like so: PGOPTIONS=--search_path=tap psql -d mydb -f pgTAP.sql Testing pgTAP with pgTAP ------------------------ In addition to the PostgreSQL-standard `installcheck` target, the `test` target uses the `pg_prove` Perl program to do its testing, which will be installed with the [TAP::Parser::SourceHandler::pgTAP](http://search.cpan.org/dist/TAP-Parser-SourceHandler-pgTAP) CPAN distribution. You'll need to make sure that you use a database with PL/pgSQL loaded, or else the tests won't work. `pg_prove` supports a number of environment variables that you might need to use, including all the usual PostgreSQL client environment variables: * `$PGDATABASE` * `$PGHOST` * `$PGPORT` * `$PGUSER` You can use it to run the test suite as a database super user like so: make test PGUSER=postgres Adding pgTAP to a Database -------------------------- Once pgTAP has been built and tested, you can install it into a PL/pgSQL-enabled database: psql -d dbname -f pgtap.sql If you want pgTAP to be available to all new databases, install it into the "template1" database: psql -d template1 -f pgtap.sql If you want to remove pgTAP from a database, run the `uninstall_pgtap.sql` script: psql -d dbname -f uninstall_pgtap.sql Both scripts will also be installed in the `contrib` directory under the directory output by `pg_config --sharedir`. So you can always do this: psql -d template1 -f `pg_config --sharedir`/contrib/pgtap.sql But do be aware that, if you've specified a schema using `$TAPSCHEMA`, that schema will always be created and the pgTAP functions placed in it. pgTAP Test Scripts ================== You can distribute `pgtap.sql` with any PostgreSQL distribution, such as a custom data type. For such a case, if your users want to run your test suite using PostgreSQL's standard `installcheck` make target, just be sure to set variables to keep the tests quiet, start a transaction, load the functions in your test script, and then rollback the transaction at the end of the script. Here's an example: \set ECHO \set QUIET 1 -- Turn off echo and keep things quiet. -- Format the output for nice TAP. \pset format unaligned \pset tuples_only true \pset pager -- Revert all changes on failure. \set ON_ERROR_ROLLBACK 1 \set ON_ERROR_STOP true \set QUIET 1 -- Load the TAP functions. BEGIN; \i pgtap.sql -- Plan the tests. SELECT plan(1); -- Run the tests. SELECT pass( 'My test passed, w00t!' ); -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; Of course, if you already have the pgTAP functions in your testing database, you should skip `\i pgtap.sql` at the beginning of the script. The only other limitation is that the `pg_typoeof()` function, which is written in C, will not be available in 8.3 and lower. You'll want to comment-out its declaration in the bundled copy of `pgtap.sql` and then avoid using `cmp_ok()`, since that function relies on `pg_typeof()`. Note that `pg_typeof()` is included in PostgreSQL 8.4, so ou won't need to avoid it on that version or higher. Now you're ready to run your test script! % psql -d try -Xf test.sql 1..1 ok 1 - My test passed, w00t! You'll need to have all of those variables in the script to ensure that the output is proper TAP and that all changes are rolled back -- including the loading of the test functions -- in the event of an uncaught exception. Using `pg_prove` ---------------- Or save yourself some effort -- and run a batch of tests scripts or all of your xUnit test functions at once -- by using `pg_prove`, available in the [TAP::Parser::SourceHandler::pgTAP](http://search.cpan.org/dist/TAP-Parser-SourceHandler-pgTAP) CPAN distribution . If you're not relying on `installcheck`, your test scripts can be a lot less verbose; you don't need to set all the extra variables, because `pg_prove` takes care of that for you: -- Start transaction and plan the tests. BEGIN; SELECT plan(1); -- Run the tests. SELECT pass( 'My test passed, w00t!' ); -- Finish the tests and clean up. SELECT * FROM finish(); ROLLBACK; Now run the tests. Here's what it looks like when the pgTAP tests are run with `pg_prove`: % pg_prove -U postgres sql/*.sql sql/coltap.....ok sql/hastap.....ok sql/moretap....ok sql/pg73.......ok sql/pktap......ok All tests successful. Files=5, Tests=216, 1 wallclock secs ( 0.06 usr 0.02 sys + 0.08 cusr 0.07 csys = 0.23 CPU) Result: PASS If you're using xUnit tests and just want to have `pg_prove` run them all through the `runtests()` function, just tell it to do so: % pg_prove -d myapp --runtests Yep, that's all there is to it. Call `pg_prove --help` to see other supported options, and `pg_prove --man` to see its entire documentation. Using pgTAP =========== The purpose of pgTAP is to provide a wide range of testing utilities that output TAP. TAP, or the "Test Anything Protocol", is an emerging standard for representing the output from unit tests. It owes its success to its format as a simple text-based interface that allows for practical machine parsing and high legibility for humans. TAP started life as part of the test harness for Perl but now has implementations in C/C++, Python, PHP, JavaScript, Perl, and now PostgreSQL. There are two ways to use pgTAP: 1) In simple test scripts that use a plan to describe the tests in the script; or 2) In xUnit-style test functions that you install into your database and run all at once in the PostgreSQL client of your choice. I love it when a plan comes together ------------------------------------ Before anything else, you need a testing plan. This basically declares how many tests your script is going to run to protect against premature failure. The preferred way to do this is to declare a plan by calling the `plan()` function: SELECT plan( 42 ); There are rare cases when you will not know beforehand how many tests your script is going to run. In this case, you can declare that you have no plan. (Try to avoid using this as it weakens your test.) SELECT * FROM no_plan(); Often, though, you'll be able to calculate the number of tests, like so: SELECT plan( COUNT(*) ) FROM foo; At the end of your script, you should always tell pgTAP that the tests have completed, so that it can output any diagnostics about failures or a discrepancy between the planned number of tests and the number actually run: SELECT * FROM finish(); What a sweet unit! ------------------ If you're used to xUnit testing frameworks, you can collect all of your tests into database functions and run them all at once with `runtests()`. This is similar to how [PGUnit](http://en.dklab.ru/lib/dklab_pgunit/) and [Epic](http://www.epictest.org/) work. The `runtests()` function does all the work of finding and running your test functions in individual transactions. It even supports setup and teardown functions. To use it, write your unit test functions so that they return a set of text results, and then use the pgTAP assertion functions to return TAP values, like so: CREATE OR REPLACE FUNCTION setup_insert( ) RETURNS SETOF TEXT AS $$ RETURN NEXT is( MAX(nick), NULL, 'Should have no users') FROM users; INSERT INTO users (nick) VALUES ('theory'); $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION test_user( ) RETURNS SETOF TEXT AS $$ SELECT is( nick, 'theory', 'Should have nick') FROM users; END; $$ LANGUAGE sql; See below for details on the pgTAP assertion functions. Once you've defined your unit testing functions, you can run your tests at any time using the `runtests()` function: SELECT * FROM runtests(); Each test function will run within its own transaction, and rolled back when the function completes (or after any teardown functions have run). The TAP results will be sent to your client. Test names ---------- By convention, each test is assigned a number in order. This is largely done automatically for you. However, it's often very useful to assign a name to each test. Would you rather see this? ok 4 not ok 5 ok 6 Or this? ok 4 - basic multi-variable not ok 5 - simple exponential ok 6 - force == mass * acceleration The latter gives you some idea of what failed. It also makes it easier to find the test in your script, simply search for "simple exponential". All test functions take a name argument. It's optional, but highly suggested that you use it. Sometimes it's useful to extract test function names from pgtap output, especially when using xUnit style with Continuous Integration Server like Hudson or TeamCity. By default pgTAP displays this names as "comment", but you're able to change this behavior by overriding function `diag_test_name`: ### `diag_test_name()` ### CREATE OR REPLACE FUNCTION diag_test_name(TEXT) RETURNS TEXT AS $$ SELECT diag('test: ' || $1 ); $$ LANGUAGE SQL; **Parameters** `:test_name` : A test name. This will show # test: my_example_test_function_name instead of # my_example_test_function_name() This makes easy handling test name and differing test names from comments. I'm ok, you're not ok --------------------- The basic purpose of pgTAP--and of any TAP-emitting test framework, for that matter--is to print out either "ok #" or "not ok #", depending on whether a given test succeeded or failed. Everything else is just gravy. All of the following functions return "ok" or "not ok" depending on whether the test succeeded or failed. ### `ok()` ### SELECT ok( :boolean, :description ); SELECT ok( :boolean ); **Parameters** `:boolean` : A boolean value indicating success or failure. `:description` : A short description of the test. This function simply evaluates any boolean expression and uses it to determine if the test succeeded or failed. A true expression passes, a false one fails. Very simple. For example: SELECT ok( 9 ^ 2 = 81, 'simple exponential' ); SELECT ok( 9 < 10, 'simple comparison' ); SELECT ok( 'foo' ~ '^f', 'simple regex' ); SELECT ok( active = true, name || widget active' ) FROM widgets; (Mnemonic: "This is ok.") The `:description` is a very short description of the test that will be printed out. It makes it very easy to find a test in your script when it fails and gives others an idea of your intentions. The description is optional, but we *very* strongly encourage its use. Should an `ok()` fail, it will produce some diagnostics: not ok 18 - sufficient mucus # Failed test 18: "sufficient mucus" Furthermore, should the boolean test result argument be passed as a `NULL` rather than `true` or `false`, `ok()` will assume a test failure and attach an additional diagnostic: not ok 18 - sufficient mucus # Failed test 18: "sufficient mucus" # (test result was NULL) ### `is()` ### ### `isnt()` ### SELECT is( :have, :want, :description ); SELECT is( :have, :want ); SELECT isnt( :have, :want, :description ); SELECT isnt( :have, :want ); **Parameters** `:have` : Value to test. `:want` : Value that `:have` is expcted to be. Must be the same data type. `:description` : A short description of the test. Similar to `ok()`, `is()` and `isnt()` compare their two arguments with `IS NOT DISTINCT FROM` (`=`) AND `IS DISTINCT FROM` (`<>`) respectively and use the result of that to determine if the test succeeded or failed. So these: -- Is the ultimate answer 42? SELECT is( ultimate_answer(), 42, 'Meaning of Life' ); -- foo() doesn't return empty SELECT isnt( foo(), '', 'Got some foo' ); are similar to these: SELECT ok( ultimate_answer() = 42, 'Meaning of Life' ); SELECT isnt( foo() <> '', 'Got some foo' ); (Mnemonic: "This is that." "This isn't that.") *Note:* Thanks to the use of the `IS [ NOT ] DISTINCT FROM` construct, `NULL`s are not treated as unknowns by `is()` or `isnt()`. That is, if `:have` and `:want` are both `NULL`, the test will pass, and if only one of them is `NULL`, the test will fail. So why use these test functions? They produce better diagnostics on failure. `ok()` cannot know what you are testing for (beyond the description), but `is()` and `isnt()` know what the test was and why it failed. For example this test: \set foo '\'waffle\'' \set bar '\'yarblokos\'' SELECT is( :foo::text, :bar::text, 'Is foo the same as bar?' ); Will produce something like this: # Failed test 17: "Is foo the same as bar?" # have: waffle # want: yarblokos So you can figure out what went wrong without re-running the test. You are encouraged to use `is()` and `isnt()` over `ok()` where possible. You can even use them to compar records in PostgreSQL 8.4 and later: SELECT is( users.*, ROW(1, 'theory', true)::users ) FROM users WHERE nick = 'theory'; ### `matches()` ### SELECT matches( :have, :regex, :description ); SELECT matches( :have, :regex ); **Parameters** `:have` : Value to match. `:regex` : A regular expression. `:description` : A short description of the test. Similar to `ok()`, `matches()` matches `:have` against the regex `:regex`. So this: SELECT matches( :this, '^that', 'this is like that' ); is similar to: SELECT ok( :this ~ '^that', 'this is like that' ); (Mnemonic "This matches that".) Its advantages over `ok()` are similar to that of `is()` and `isnt()`: Better diagnostics on failure. ### `imatches()` ### SELECT imatches( :have, :regex, :description ); SELECT imatches( :have, :regex ); **Parameters** `:have` : Value to match. `:regex` : A regular expression. `:description` : A short description of the test. Just like `matches()` except that the regular expression is compared to `:have` case-insensitively. ### `doesnt_match()` ### ### `doesnt_imatch()` ### SELECT doesnt_match( :have, :regex, :description ); SELECT doesnt_match( :have, :regex ); SELECT doesnt_imatch( :have, :regex, :description ); SELECT doesnt_imatch( :have, :regex ); **Parameters** `:have` : Value to match. `:regex` : A regular expression. `:description` : A short description of the test. These functions work exactly as `matches()` and `imatches()` do, only they check if `:have` *does not* match the given pattern. ### `alike()` ### ### `ialike()` ### SELECT alike( :this, :like, :description ); SELECT alike( :this, :like ); SELECT ialike( :this, :like, :description ); SELECT ialike( :this, :like ); **Parameters** `:have` : Value to match. `:like` : A SQL `LIKE` pattern. `:description` : A short description of the test. Similar to `matches()`, `alike()` matches `:hve` against the SQL `LIKE` pattern `:like`. `ialike()` matches case-insensitively. So this: SELECT ialike( :have, 'that%', 'this is alike that' ); is similar to: SELECT ok( :have ILIKE 'that%', 'this is like that' ); (Mnemonic "This is like that".) Its advantages over `ok()` are similar to that of `is()` and `isnt()`: Better diagnostics on failure. ### `unalike()` ### ### `unialike()` ### SELECT unalike( :this, :like, :description ); SELECT unalike( :this, :like ); SELECT unialike( :this, :like, :description ); SELECT unialike( :this, :like ); **Parameters** `:have` : Value to match. `:like` : A SQL `LIKE` pattern. `:description` : A short description of the test. Works exactly as `alike()`, only it checks if `:have` *does not* match the given pattern. ### `cmp_ok()` ### SELECT cmp_ok( :have, :op, :want, :description ); SELECT cmp_ok( :have, :op, :want ); **Parameters** `:have` : Value to compare. `:op` : An SQL operator specified as a string. `:want` : Value to compare to `:have` using the `:op` operator. `:description` : A short description of the test. Halfway between `ok()` and `is()` lies `cmp_ok()`. This function allows you to compare two arguments using any binary operator. -- ok( :have = :want ); SELECT cmp_ok( :have, '=', :want, 'this = that' ); -- ok( :have >= :want ); SELECT cmp_ok( :have, '>=', :want, 'this >= that' ); -- ok( :have && :want ); SELECT cmp_ok( :have, '&&', :want, 'this && that' ); Its advantage over `ok()` is that when the test fails you'll know what `:have` and `:want` were: not ok 1 # Failed test 1: # '23' # && # NULL Note that if the value returned by the operation is `NULL`, the test will be considered to have failed. This may not be what you expect if your test was, for example: SELECT cmp_ok( NULL, '=', NULL ); But in that case, you should probably use `is()`, instead. ### `pass()` ### ### `fail()` ### SELECT pass( :description ); SELECT pass( ); SELECT fail( :description ); SELECT fail( ); **Parameters** `:description` : A short description of the test. Sometimes you just want to say that the tests have passed. Usually the case is you've got some complicated condition that is difficult to wedge into an `ok()`. In this case, you can simply use `pass()` (to declare the test ok) or `fail()` (for not ok). They are synonyms for `ok(1)` and `ok(0)`. Use these functions very, very, very sparingly. ### `isa_ok()` ### SELECT isa_ok( :have, :regtype, :name ); SELECT isa_ok( :have, :regtype ); **Parameters** `:have` : Value to check the type of. `:regtype` : Name of an SQL data type. `:name` : A name for the value being compared. Checks to see if the given value is of a particular type. The description and diagnostics of this test normally just refer to "the value". If you'd like them to be more specific, you can supply a `:name`. For example you might say "the return value" when yo're examing the result of a function call: SELECT isa_ok( length('foo'), 'integer', 'The return value from length()' ); In which case the description will be "The return value from length() isa integer". In the event of a failure, the diagnostic message will tell you what the type of the value actually is: not ok 12 - the value isa integer[] # the value isn't a "integer[]" it's a "boolean" Pursuing Your Query =================== Sometimes, you've just gotta test a query. I mean the results of a full blown query, not just the scalar assertion functions we've seen so far. pgTAP provides a number of functions to help you test your queries, each of which takes one or two SQL statements as arguments. For example: SELECT throws_ok('SELECT divide_by(0)'); Yes, as strings. Of course, you'll often need to do something complex in your SQL, and quoting SQL in strings in what is, after all, an SQL application, is an unnecessary PITA. Each of the query-executing functions in this section thus support an alternative to make your tests more SQLish: using prepared statements. [Prepared statements](http://www.postgresql.org/docs/current/static/sql-prepare.html "PostgreSQL Documentation: PREPARE") allow you to just write SQL and simply pass the prepared statement names to test functions. For example, the above example can be rewritten as: PREPARE mythrow AS SELECT divide_by(0); SELECT throws_ok('mythrow'); pgTAP assumes that an SQL argument without space characters or starting with a double quote character is a prepared statement and simply `EXECUTE`s it. If you need to pass arguments to a prepared statement, perhaps because you plan to use it in multiple tests to return different values, just `EXECUTE` it yourself. Here's an example with a prepared statement with a space in its name, and one where arguments need to be passed: PREPARE "my test" AS SELECT * FROM active_users() WHERE name LIKE 'A%'; PREPARE expect AS SELECT * FROM users WHERE active = $1 AND name LIKE $2; SELECT results_eq( '"my test"', 'EXECUTE expect( true, ''A%'' )' ); Since "my test" was declared with double quotes, it must be passed with double quotes. And since the call to "expect" included spaces (to keep it legible), the `EXECUTE` keyword was required. In PostgreSQL 8.2 and up, you can also use a `VALUES` statement, both in the query string or in a prepared statement. A useless example: PREPARE myvals AS VALUES (1, 2), (3, 4); SELECT set_eq( 'myvals', 'VALUES (1, 2), (3, 4)' ); Here's a bonus if you need to check the results from a query that returns a single column: for those functions that take two query arguments, the second can be an array. Check it out: SELECT results_eq( 'SELECT * FROM active_user_ids()', ARRAY[ 2, 3, 4, 5] ); The first query *must* return only one column of the same type as the values in the array. If you need to test more columns, you'll need to use two queries. Keeping these techniques in mind, read on for all of the query-testing goodness. To Error is Human ----------------- Sometimes you just want to know that a particular query will trigger an error. Or maybe you want to make sure a query *does not* trigger an error. For such cases, we provide a couple of test functions to make sure your queries are as error-prone as you think they should be. ### `throws_ok()` ### SELECT throws_ok( :sql, :errcode, :ermsg, :description ); SELECT throws_ok( :sql, :errcode, :ermsg ); SELECT throws_ok( :sql, :errcode ); SELECT throws_ok( :sql, :errmsg, :description ); SELECT throws_ok( :sql, :errmsg ); SELECT throws_ok( :sql ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:errcode` : A [PostgreSQL error code](http://www.postgresql.org/docs/current/static/errcodes-appendix.html "Appendix A. PostgreSQL Error Codes") `:errmsg` : An error message. `:description` : A short description of the test. When you want to make sure that an exception is thrown by PostgreSQL, use `throws_ok()` to test for it. The first argument should be the name of a prepared statement or else a string representing the query to be executed (see the [summary](#Pursuing+Your+Query) for query argument details). `throws_ok()` will use the PL/pgSQL `EXECUTE` statement to execute the query and catch any exception. The second argument should be an exception error code, which is a five-character string (if it happens to consist only of numbers and you pass it as an integer, it will still work). If this value is not `NULL`, `throws_ok()` will check the thrown exception to ensure that it is the expected exception. For a complete list of error codes, see [Appendix A.](http://www.postgresql.org/docs/current/static/errcodes-appendix.html "Appendix A. PostgreSQL Error Codes") in the [PostgreSQL documentation](http://www.postgresql.org/docs/current/static/). The third argument is an error message. This will be most useful for functions you've written that raise exceptions, so that you can test the exception message that you've thrown. Otherwise, for core errors, you'll need to be careful of localized error messages. One trick to get around localized error messages is to pass NULL as the third argument. This allows you to still pass a description as the fourth argument. The fourth argument is of course a brief test description. Here's a useful example: PREPARE my_thrower AS INSERT INTO try (id) VALUES (1); SELECT throws_ok( 'my_thrower', '23505', 'duplicate key value violates unique constraint "try_pkey"', 'We should get a unique violation for a duplicate PK' ); For the two- and three-argument forms of `throws_ok()`, if the second argument is exactly five bytes long, it is assumed to be an error code and the optional third argument is the error message. Otherwise, the second argument is assumed to be an error message and the third argument is a description. If for some reason you need to test an error message that is five bytes long, use the four-argument form. A failing `throws_ok()` test produces an appropriate diagnostic message. For example: # Failed test 81: "This should die a glorious death" # caught: 23505: duplicate key value violates unique constraint "try_pkey" # wanted: 23502: null value in column "id" violates not-null constraint Idea borrowed from the Test::Exception Perl module. ### `throws_like()` ### ### `throws_ilike()` ### SELECT throws_like( :sql, :like, :description ); SELECT throws_like( :sql, :like ); SELECT throws_ilike( :sql, :like, :description ); SELECT throws_ilike( :sql, :like ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:like` : An SQL `LIKE` pattern. `:description` : A short description of the test. Like `throws_ok()`, but tests that an exception error message matches an SQL `LIKE` pattern. The `throws_ilike()` variant matches case-insensitively. An example: PREPARE my_thrower AS INSERT INTO try (tz) VALUES ('America/Moscow'); SELECT throws_like( 'my_thrower', '%"timezone_check"', 'We should error for invalid time zone' ); A failing `throws_like()` test produces an appropriate diagnostic message. For example: # Failed test 85: "We should error for invalid time zone" # error message: 'value for domain timezone violates check constraint "tz_check"' # doesn't match: '%"timezone_check"' ### `throws_matching()` ### ### `throws_imatching()` ### SELECT throws_matching( :sql, :regex, :description ); SELECT throws_matching( :sql, :regex ); SELECT throws_imatching( :sql, :regex, :description ); SELECT throws_imatching( :sql, :regex ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:regex` : A regular expression. `:description` : A short description of the test. Like `throws_ok()`, but tests that an exception error message matches a regular expression. The `throws_imatching()` variant matches case-insensitively. An example: PREPARE my_thrower AS INSERT INTO try (tz) VALUES ('America/Moscow'); SELECT throws_matching( 'my_thrower', '.+"timezone_check"', 'We should error for invalid time zone' ); A failing `throws_matching()` test produces an appropriate diagnostic message. For example: # Failed test 85: "We should error for invalid time zone" # error message: 'value for domain timezone violates check constraint "tz_check"' # doesn't match: '.+"timezone_check"' ### `lives_ok()` ### SELECT lives_ok( :sql, :description ); SELECT lives_ok( :sql ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:description` : A short description of the test. The inverse of `throws_ok()`, `lives_ok()` ensures that an SQL statement does *not* throw an exception. Pass in the name of a prepared statement or string of SQL code (see the [summary](#Pursuing+Your+Query) for query argument details). The optional second argument is the test description. An example: SELECT lives_ok( 'INSERT INTO try (id) VALUES (1)', 'We should not get a unique violation for a new PK' ); A failing `lives_ok()` test produces an appropriate diagnostic message. For example: # Failed test 85: "don't die, little buddy!" # died: 23505: duplicate key value violates unique constraint "try_pkey" Idea borrowed from the Test::Exception Perl module. ### `performs_ok()` ### SELECT performs_ok( :sql, :milliseconds, :description ); SELECT performs_ok( :sql, :milliseconds ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:milliseconds` : Number of milliseconds. `:description` : A short description of the test. This function makes sure that an SQL statement performs well. It does so by timing its execution and failing if execution takes longer than the specified number of milliseconds. An example: PREPARE fast_query AS SELECT id FROM try WHERE name = 'Larry'; SELECT performs_ok( 'fast_query', 250, 'A select by name should be fast' ); The first argument should be the name of a prepared statement or a string representing the query to be executed (see the [summary](#Pursuing+Your+Query) for query argument details). `throws_ok()` will use the PL/pgSQL `EXECUTE` statement to execute the query. The second argument is the maximum number of milliseconds it should take for the SQL statement to execute. This argument is numeric, so you can even use fractions of milliseconds if it floats your boat. The third argument is the usual description. If not provided, `performs_ok()` will generate the description "Should run in less than $milliseconds ms". You'll likely want to provide your own description if you have more than a couple of these in a test script or function. Should a `performs_ok()` test fail it produces appropriate diagnostic messages. For example: # Failed test 19: "The lookup should be fast!" # runtime: 200.266 ms # exceeds: 200 ms *Note:* There is a little extra time included in the execution time for the the overhead of PL/pgSQL's `EXECUTE`, which must compile and execute the SQL string. You will want to account for this and pad your estimates accordingly. It's best to think of this as a brute force comparison of runtimes, in order to ensure that a query is not *really* slow (think seconds). Can You Relate? --------------- So you've got your basic scalar comparison functions, what about relations? Maybe you have some pretty hairy `SELECT` statements in views or functions to test? We've got your relation-testing functions right here. ### `results_eq()` ### SELECT results_eq( :sql, :sql, :description ); SELECT results_eq( :sql, :sql ); SELECT results_eq( :sql, :array, :description ); SELECT results_eq( :sql, :array ); SELECT results_eq( :cursor, :cursor, :description ); SELECT results_eq( :cursor, :cursor ); SELECT results_eq( :sql, :cursor, :description ); SELECT results_eq( :sql, :cursor ); SELECT results_eq( :cursor, :sql, :description ); SELECT results_eq( :cursor, :sql ); SELECT results_eq( :cursor, :array, :description ); SELECT results_eq( :cursor, :array ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:array` : An array of values representing a single-column row values. `:cursor` : A PostgreSQL `refcursor` value representing a named cursor. `:description` : A short description of the test. There are three ways to test result sets in pgTAP. Perhaps the most intuitive is to do a direct row-by-row comparison of results to ensure that they are exactly what you expect, in the order you expect. Coincidentally, this is exactly how `results_eq()` behaves. Here's how you use it: simply pass in two SQL statements or prepared statement names (or some combination; (see the [summary](#Pursuing+Your+Query) for query argument details) and an optional description. Yep, that's it. It will do the rest. For example, say that you have a function, `active_users()`, that returns a set of rows from the users table. To make sure that it returns the rows you expect, you might do something like this: SELECT results_eq( 'SELECT * FROM active_users()', 'SELECT * FROM users WHERE active', 'active_users() should return active users' ); Tip: If you're using PostgreSQL 8.2 and up and want to hard-code the values to compare, use a `VALUES` statement instead of a query, like so: SELECT results_eq( 'SELECT * FROM active_users()', $$VALUES ( 42, 'Anna'), (19, 'Strongrrl'), (39, 'Theory')$$, 'active_users() should return active users' ); If the results returned by the first argument consist of a single column, the second argument may be an array: SELECT results_eq( 'SELECT * FROM active_user_ids()', ARRAY[ 2, 3, 4, 5] ); In general, the use of prepared statements is highly recommended to keep your test code SQLish (you can even use `VALUES` in prepared statements in PostgreSQL 8.2 and up!). But note that, because `results_eq()` does a row-by-row comparison, the results of the two query arguments must be in exactly the same order, with exactly the same data types, in order to pass. In practical terms, it means that you must make sure that your results are never unambiguously ordered. For example, say that you want to compare queries against a `persons` table. The simplest way to sort is by `name`, as in: try=# select * from people order by name; name | age --------+----- Damian | 19 Larry | 53 Tom | 44 Tom | 35 (4 rows) But a different run of the same query could have the rows in different order: try=# select * from people order by name; name | age --------+----- Damian | 19 Larry | 53 Tom | 35 Tom | 44 (4 rows) Notice how the two "Tom" rows are reversed. The upshot is that you must ensure that your queries are always fully ordered. In a case like the above, it means sorting on both the `name` column and the `age` column. If the sort order of your results isn't important, consider using `set_eq()` or `bag_eq()` instead. Internally, `results_eq()` turns your SQL statements into cursors so that it can iterate over them one row at a time. Conveniently, this behavior is directly available to you, too. Rather than pass in some arbitrary SQL statement or the name of a prepared statement, simply create a cursor and pass *it* in, like so: DECLARE cwant CURSOR FOR SELECT * FROM active_users(); DECLARE chave CURSOR FOR SELECT * FROM users WHERE active ORDER BY name; SELECT results_eq( 'cwant'::refcursor, 'chave'::refcursor, 'Gotta have those active users!' ); The key is to ensure that the cursor names are passed as `refcursor`s. This allows `results_eq()` to disambiguate them from prepared statements. And of course, you can mix and match cursors, prepared statements, and SQL as much as you like. Here's an example using a prepared statement and a (reset) cursor for the expected results: PREPARE users_test AS SELECT * FROM active_users(); MOVE BACKWARD ALL IN chave; SELECT results_eq( 'users_test', 'chave'::refcursor, 'Gotta have those active users!' ); Regardless of which types of arguments you pass, in the event of a test failure, `results_eq()` will offer a nice diagnostic message to tell you at what row the results differ, something like: # Failed test 146 # Results differ beginning at row 3: # have: (1,Anna) # want: (22,Betty) If there are different numbers of rows in each result set, a non-existent row will be represented as "NULL": # Failed test 147 # Results differ beginning at row 5: # have: (1,Anna) # want: NULL On PostgreSQL 8.4 or higher, if the number of columns varies between result sets, or if results are of different data types, you'll get diagnostics like so: # Failed test 148 # Column types differ between queries: # have: (1) # want: (foo,1) On PostgreSQL 8.3 and down, the rows are cast to text for comparison, rather than compared as `record` objects. The downside to this necessity is that the test cannot detect incompatibilities in column numbers or types, or differences in columns that convert to the same text representation. For example, a `NULL` column will be equivalent to an empty string. The upshot: read failure diagnostics carefully and pay attention to data types on 8.3 and down. ### `results_ne()` ### SELECT results_ne( :sql, :sql, :description ); SELECT results_ne( :sql, :sql ); SELECT results_ne( :sql, :array, :description ); SELECT results_ne( :sql, :array ); SELECT results_ne( :cursor, :cursor, :description ); SELECT results_ne( :cursor, :cursor ); SELECT results_ne( :sql, :cursor, :description ); SELECT results_ne( :sql, :cursor ); SELECT results_ne( :cursor, :sql, :description ); SELECT results_ne( :cursor, :sql ); SELECT results_ne( :cursor, :array, :description ); SELECT results_ne( :cursor, :array ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:array` : An array of values representing a single-column row values. `:cursor` : A PostgreSQL `refcursor` value representing a named cursor. `:description` : A short description of the test. The inverse of `results_eq()`, this function tests that query results are not equivalent. Note that, like `results_ne()`, order matters, so you can actually have the same sets of results in the two query arguments and the test will pass if they're merely in a different order. More than likely what you really want is `results_eq()` or `set_ne()`. But this function is included for completeness and is kind of cute, so enjoy. If a `results_ne()` test fails, however, there will be no diagnostics, because, well, the results will be the same! Note that the caveats for `results_ne()` on PostgreSQL 8.3 and down apply to `results_ne()` as well. ### `set_eq()` ### SELECT set_eq( :sql, :sql, :description ); SELECT set_eq( :sql, :sql ); SELECT set_eq( :sql, :array, :description ); SELECT set_eq( :sql, :array ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:array` : An array of values representing a single-column row values. `:description` : A short description of the test. Sometimes you don't care what order query results are in, or if there are duplicates. In those cases, use `set_eq()` to do a simple set comparison of your result sets. As long as both queries return the same records, regardless of duplicates or ordering, a `set_eq()` test will pass. The SQL arguments can be the names of prepared statements or strings containing an SQL query (see the [summary](#Pursuing+Your+Query) for query argument details), or even one of each. If the results returned by the first argument consist of a single column, the second argument may be an array: SELECT set_eq( 'SELECT * FROM active_user_ids()', ARRAY[ 2, 3, 4, 5] ); In whatever case you choose to pass arguments, a failing test will yield useful diagnostics, such as: # Failed test 146 # Extra records: # (87,Jackson) # (1,Jacob) # Missing records: # (44,Anna) # (86,Angelina) In the event that you somehow pass queries that return rows with different types of columns, pgTAP will tell you that, too: # Failed test 147 # Columns differ between queries: # have: (integer,text) # want: (text,integer) This of course extends to sets with different numbers of columns: # Failed test 148 # Columns differ between queries: # have: (integer) # want: (text,integer) ### `set_ne()` ### SELECT set_ne( :sql, :sql, :description ); SELECT set_ne( :sql, :sql ); SELECT set_ne( :sql, :array, :description ); SELECT set_ne( :sql, :array ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:array` : An array of values representing a single-column row values. `:description` : A short description of the test. The inverse of `set_eq()`, this function tests that the results of two queries are *not* the same. The two queries can as usual be the names of prepared statements or strings containing an SQL query (see the [summary](#Pursuing+Your+Query) for query argument details), or even one of each. The two queries, however, must return results that are directly comparable -- that is, with the same number and types of columns in the same orders. If it happens that the query you're testing returns a single column, the second argument may be an array. ### `set_has()` ### SELECT set_has( :sql, :sql, :description ); SELECT set_has( :sql, :sql ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:description` : A short description of the test. When you need to test that a query returns at least some subset of records, `set_has()` is the hammer you're looking for. It tests that the the results of a query contain at least the results returned by another query, if not more. That is, the test passes if the second query's results are a subset of the first query's results. The second query can even return an empty set, in which case the test will pass no matter what the first query returns. Not very useful perhaps, but set-theoretically correct. As with `set_eq()`. the SQL arguments can be the names of prepared statements or strings containing an SQL query (see the [summary](#Pursuing+Your+Query) for query argument details), or one of each. If it happens that the query you're testing returns a single column, the second argument may be an array. In whatever case, a failing test will yield useful diagnostics just like: # Failed test 122 # Missing records: # (44,Anna) # (86,Angelina) As with `set_eq()`, `set_has()` will also provide useful diagnostics when the queries return incompatible columns. Internally, it uses an `EXCEPT` query to determine if there any any unexpectedly missing results. ### `set_hasnt()` ### SELECT set_hasnt( :sql, :sql, :description ); SELECT set_hasnt( :sql, :sql ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:description` : A short description of the test. This test function is the inverse of `set_has()`: the test passes when the results of the first query have none of the results of the second query. Diagnostics are similarly useful: # Failed test 198 # Extra records: # (44,Anna) # (86,Angelina) Internally, the function uses an `INTERSECT` query to determine if there is any unexpected overlap between the query results. ### `bag_eq()` ### SELECT bag_eq( :sql, :sql, :description ); SELECT bag_eq( :sql, :sql ); SELECT bag_eq( :sql, :array, :description ); SELECT bag_eq( :sql, :array ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:array` : An array of values representing a single-column row values. `:description` : A short description of the test. The `bag_eq()` function is just like `set_eq()`, except that it considers the results as bags rather than as sets. A bag is a set that allows duplicates. In practice, it mean that you can use `bag_eq()` to test result sets where order doesn't matter, but duplication does. In other words, if a two rows are the same in the first result set, the same row must appear twice in the second result set. Otherwise, this function behaves exactly like `set_eq()`, including the utility of its diagnostics. ### `bag_ne()` ### SELECT bag_ne( :sql, :sql, :description ); SELECT bag_ne( :sql, :sql ); SELECT bag_ne( :sql, :array, :description ); SELECT bag_ne( :sql, :array ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:array` : An array of values representing a single-column row values. `:description` : A short description of the test. The inverse of `bag_eq()`, this function tests that the results of two queries are *not* the same, including duplicates. The two queries can as usual be the names of prepared statements or strings containing an SQL query (see the [summary](#Pursuing+Your+Query) for query argument details), or even one of each. The two queries, however, must return results that are directly comparable -- that is, with the same number and types of columns in the same orders. If it happens that the query you're testing returns a single column, the second argument may be an array. ### `bag_has()` ### SELECT bag_has( :sql, :sql, :description ); SELECT bag_has( :sql, :sql ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:description` : A short description of the test. The `bag_has()` function is just like `set_has()`, except that it considers the results as bags rather than as sets. A bag is a set with duplicates. What practice this means that you can use `bag_has()` to test result sets where order doesn't matter, but duplication does. Internally, it uses an `EXCEPT ALL` query to determine if there any any unexpectedly missing results. ### `bag_hasnt()` ### SELECT bag_hasnt( :sql, :sql, :description ); SELECT bag_hasnt( :sql, :sql ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:description` : A short description of the test. This test function is the inverse of `bag_hasnt()`: the test passes when the results of the first query have none of the results of the second query. Diagnostics are similarly useful: # Failed test 198 # Extra records: # (44,Anna) # (86,Angelina) Internally, the function uses an `INTERSECT ALL` query to determine if there is any unexpected overlap between the query results. This means that a duplicate row in the first query will appear twice in the diagnostics if it is also duplicated in the second query. ### `is_empty()` ### SELECT is_empty( :sql, :description ); SELECT is_empty( :sql ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:description` : A short description of the test. The `is_empty()` function takes a single query string or prepared statement name as its first argument, and tests that said query returns no records. Internally it simply executes the query and if there are any results, the test fails and the results are displayed in the failure diagnostics, like so: # Failed test 494: "Should have no inactive users" # Records returned: # (1,Jacob,false) # (2,Emily,false) ### `row_eq()` ### SELECT row_eq( :sql, :record, :description ); SELECT row_eq( :sql, :record ); **Parameters** `:sql` : An SQL statement or the name of a prepared statement, passed as a string. `:record` : A row or value, also known as a [composite type](http://www.postgresql.org/docs/current/static/rowtypes.html). `:description` : A short description of the test. Compares the contents of a single row to a record. Due to the limitations of non-C functions in PostgreSQL, a bar `RECORD` value cannot be passed to the function. You must instead pass in a valid composite type value, and cast the record argument (the second argument) to the same type. Both explicitly created composite types and table types are supported. Thus, you can do this: CREATE TYPE sometype AS ( id INT, name TEXT ); SELECT row_eq( ROW(1, 'foo')::sometype, ROW(1, 'foo')::sometype ); And, of course, this: CREATE TABLE users ( id INT, name TEXT ); INSERT INTO users VALUES (1, 'theory'); SELECT row_eq( id, name), ROW(1, 'theory')::users ) FROM users; Compatible types can be compared, though. So if the `users` table actually included an `active` column, for example, and you only wanted to test the `id` and `name`, you could do this: SELECT row_eq( id, name), ROW(1, 'theory')::sometype ) FROM users; Note the use of the `sometype` composite type for the second argument. The upshot is that you can create composite types in your tests explicitly for comparing the rerutn values of your queries, if such queries don't return an existing valid type. Hopefully someday in the future we'll be able to support arbitrary `record` arguments. In the meantime, this is the 90% solution. Diagnostics on failure are similar to those from `is()`: # Failed test 322 # have: (1,Jacob) # want: (1,Larry) The Schema Things ================= Need to make sure that your database is designed just the way you think it should be? Use these test functions and rest easy. A note on comparisons: pgTAP uses a simple equivalence test (`=`) to compare all SQL identifiers, such as the names of tables, schemas, functions, indexes, and columns (but not data types). So in general, you should always use lowercase strings when passing identifier arguments to the functions below. Use mixed case strings only when the objects were declared in your schema using double-quotes. For example, if you created a table like so: CREATE TABLE Foo (id integer); Then you *must* test for it using only lowercase characters (if you want the test to pass): SELECT has_table('foo'); If, however, you declared the table using a double-quoted string, like so: CREATE TABLE "Foo" (id integer); Then you'd need to test for it using exactly the same string, including case, like so: SELECT has_table('Foo'); In general, this should not be an issue, as mixed-case objects are created only rarely. So if you just stick to lowercase-only arguments to these functions, you should be in good shape. I Object! --------- In a busy development environment, you might have a number of users who make changes to the database schema. Sometimes you have to really work to keep these folks in line. For example, do they add objects to the database without adding tests? Do they drop objects that they shouldn't? These assertions are designed to help you ensure that the objects in the database are exactly the objects that should be in the database, no more, no less. Each tests tests that all of the objects in the database are only the objects that *should* be there. In other words, given a list of objects, say tables in a call to `tables_are()`, this assertion will fail if there are tables that are not in the list, or if there are tables in the list that are missing from the database. It can also be useful for testing replication and the success or failure of schema change deployments. If you're more interested in the specifics of particular objects, skip to the next section. ### `tablespaces_are()` ### SELECT tablespaces_are( :tablespaces, :description ); SELECT tablespaces_are( :tablespaces ); **Parameters** `:tablespaces` : An array of tablespace names. `:description` : A short description of the test. This function tests that all of the tablespaces in the database only the tablespaces that *should* be there. Example: SELECT tablespaces_are(ARRAY[ 'dbspace', 'indexspace' ]); In the event of a failure, you'll see diagnostics listing the extra and/or missing tablespaces, like so: # Failed test 121: "There should be the correct tablespaces" # Extra tablespaces: # trigspace # Missing tablespaces: # indexspace ### `schemas_are()` ### SELECT schemas_are( :schemas, :description ); SELECT schemas_are( :schemas ); **Parameters** `:schemas` : An array of schema names. `:description` : A short description of the test. This function tests that all of the schemas in the database only the schemas that *should* be there, excluding system schemas and `information_schema`. Example: SELECT schemas_are(ARRAY[ 'public', 'contrib', 'tap' ]); In the event of a failure, you'll see diagnostics listing the extra and/or missing schemas, like so: # Failed test 106: "There should be the correct schemas" # Extra schemas: # __howdy__ # Missing schemas: # someschema ### `tables_are()` ### SELECT tables_are( :schema, :tables, :description ); SELECT tables_are( :schema, :tables ); SELECT tables_are( :tables, :description ); SELECT tables_are( :tables ); **Parameters** `:schema` : Name of a schema in which to find tables. `:tables` : An array of table names. `:description` : A short description of the test. This function tests that all of the tables in the named schema, or that are visible in the search path, are only the tables that *should* be there. If the `:schema` argument is omitted, tables will be sought in the search path, excluding `pg_catalog` and `information_schema` If the description is omitted, a generally useful default description will be generated. Example: SELECT tables_are( 'myschema', ARRAY[ 'users', 'widgets', 'gadgets', 'session' ] ); In the event of a failure, you'll see diagnostics listing the extra and/or missing tables, like so: # Failed test 91: "Schema public should have the correct tables" # Extra tables: # mallots # __test_table # Missing tables: # users # widgets ### `views_are()` ### SELECT views_are( :schema, :views, :description ); SELECT views_are( :schema, :views ); SELECT views_are( :views, :description ); SELECT views_are( :views ); **Parameters** `:schema` : Name of a schema in which to find views. `:views` : An array of view names. `:description` : A short description of the test. This function tests that all of the views in the named schema, or that are visible in the search path, are only the views that *should* be there. If the `:schema` argument is omitted, views will be sought in the search path, excluding `pg_catalog` and `information_schema` If the description is omitted, a generally useful default description will be generated. Example: SELECT views_are( 'myschema', ARRAY[ 'users', 'widgets', 'gadgets', 'session' ] ); In the event of a failure, you'll see diagnostics listing the extra and/or missing views, like so: # Failed test 92: "Schema public should have the correct views" # Extra views: # v_userlog_tmp # __test_view # Missing views: # v_userlog # eated ### `sequences_are()` ### SELECT sequences_are( :schema, :sequences, :description ); SELECT sequences_are( :schema, :sequences ); SELECT sequences_are( :sequences, :description ); SELECT sequences_are( :sequences ); **Parameters** `:schema` : Name of a schema in which to find sequences. `:sequences` : An array of sequence names. `:description` : A short description of the test. This function tests that all of the sequences in the named schema, or that are visible in the search path, are only the sequences that *should* be there. If the `:schema` argument is omitted, sequences will be sought in the search path, excluding `pg_catalog` and `information_schema`. If the description is omitted, a generally useful default description will be generated. Example: SELECT sequences_are( 'myschema', ARRAY[ 'users', 'widgets', 'gadgets', 'session' ] ); In the event of a failure, you'll see diagnostics listing the extra and/or missing sequences, like so: # Failed test 93: "Schema public should have the correct sequences" # These are extra sequences: # seq_mallots # __test_table_seq # These sequences are missing: # users_seq # widgets_seq ### `columns_are()` ### SELECT columns_are( :schema, :table, :columns, :description ); SELECT columns_are( :schema, :table, :columns ); SELECT columns_are( :table, :columns, :description ); SELECT columns_are( :table, :columns ); **Parameters** `:schema` : Name of a schema in which to find the `:table`. `:table` : Name of a table in which to find columns. `:columns` : An array of column names. `:description` : A short description of the test. This function tests that all of the columns on the named table are only the columns that *should* be on that table. If the `:schema` argument is omitted, the table must be visible in the search path, excluding `pg_catalog` and `information_schema`. If the description is omitted, a generally useful default description will be generated. Example: SELECT columns_are( 'myschema', 'atable', ARRAY[ 'id', 'name', 'rank', 'sn' ] ); In the event of a failure, you'll see diagnostics listing the extra and/or missing columns, like so: # Failed test 183: "Table users should have the correct columns" # Extra columns: # given_name # surname # Missing columns: # name ### `indexes_are()` ### SELECT indexes_are( :schema, :table, :indexes, :description ); SELECT indexes_are( :schema, :table, :indexes ); SELECT indexes_are( :table, :indexes, :description ); SELECT indexes_are( :table, :indexes ); **Parameters** `:schema` : Name of a schema in which to find the `:table`. `:table` : Name of a table in which to find indexes. `:indexes` : An array of index names. `:description` : A short description of the test. This function tests that all of the indexes on the named table are only the indexes that *should* be on that table. If the `:schema` argument is omitted, the table must be visible in the search path, excluding `pg_catalog` and `information_schema`. If the description is omitted, a generally useful default description will be generated. Example: SELECT indexes_are( 'myschema', 'atable', ARRAY[ 'atable_pkey', 'idx_atable_name' ] ); In the event of a failure, you'll see diagnostics listing the extra and/or missing indexes, like so: # Failed test 180: "Table fou should have the correct indexes" # Extra indexes: # fou_pkey # Missing indexes: # idx_fou_name ### `triggers_are()` ### SELECT triggers_are( :schema, :table, :triggers, :description ); SELECT triggers_are( :schema, :table, :triggers ); SELECT triggers_are( :table, :triggers, :description ); SELECT triggers_are( :table, :triggers ); **Parameters** `:schema` : Name of a schema in which to find the `:table`. `:table` : Name of a table in which to find triggers. `:triggers` : An array of trigger names. `:description` : A short description of the test. This function tests that all of the triggers on the named table are only the triggers that *should* be on that table. If the `:schema` argument is omitted, the table must be visible in the search path, excluding `pg_catalog` and `information_schema`. If the description is omitted, a generally useful default description will be generated. Example: SELECT triggers_are( 'myschema', 'atable', ARRAY[ 'atable_pkey', 'idx_atable_name' ] ); In the event of a failure, you'll see diagnostics listing the extra and/or missing triggers, like so: # Failed test 180: "Table fou should have the correct triggers" # Extra triggers: # set_user_pass # Missing triggers: # set_users_pass ### `functions_are()` ### SELECT functions_are( :schema, :functions, :description ); SELECT functions_are( :schema, :functions ); SELECT functions_are( :functions, :description ); SELECT functions_are( :functions ); **Parameters** `:schema` : Name of a schema in which to find functions. `:functions` : An array of function names. `:description` : A short description of the test. This function tests that all of the functions in the named schema, or that are visible in the search path, are only the functions that *should* be there. If the `:schema` argument is omitted, functions will be sought in the search path, excluding `pg_catalog` and `information_schema` If the description is omitted, a generally useful default description will be generated. Example: SELECT functions_are( 'myschema', ARRAY[ 'foo', 'bar', 'frobnitz' ] ); In the event of a failure, you'll see diagnostics listing the extra and/or missing functions, like so: # Failed test 150: "Schema someschema should have the correct functions" # Extra functions: # schnauzify # Missing functions: # frobnitz ### `roles_are()` ### SELECT roles_are( :roles, :description ); SELECT roles_are( :roles ); **Parameters** `:roles` : An array of role names. `:description` : A short description of the test. This function tests that all of the roles in the database only the roles that *should* be there. Example: SELECT roles_are(ARRAY[ 'postgres', 'someone', 'root' ]); In the event of a failure, you'll see diagnostics listing the extra and/or missing roles, like so: # Failed test 195: "There should be the correct roles" # Extra roles: # root # Missing roles: # bobby ### `users_are()` ### SELECT users_are( :users, :description ); SELECT users_are( :users ); **Parameters** `:users` : An array of user names. `:description` : A short description of the test. This function tests that all of the users in the database only the users that *should* be there. Example: SELECT users_are(ARRAY[ 'postgres', 'someone', 'root' ]); In the event of a failure, you'll see diagnostics listing the extra and/or missing users, like so: # Failed test 195: "There should be the correct users" # Extra users: # root # Missing users: # bobby ### `groups_are()` ### SELECT groups_are( :groups, :description ); SELECT groups_are( :groups ); **Parameters** `:groups` : An array of group names. `:description` : A short description of the test. This function tests that all of the groups in the database only the groups that *should* be there. Example: SELECT groups_are(ARRAY[ 'postgres', 'admins, 'l0s3rs' ]); In the event of a failure, you'll see diagnostics listing the extra and/or missing groups, like so: # Failed test 210: "There should be the correct groups" # Extra groups: # meanies # Missing groups: # __howdy__ ### `languages_are()` ### SELECT languages_are( :languages, :description ); SELECT languages_are( :languages ); **Parameters** `:languages` : An array of language names. `:description` : A short description of the test. This function tests that all of the languages in the database only the languages that *should* be there. Example: SELECT languages_are(ARRAY[ 'plpgsql', 'plperl', 'pllolcode' ]); In the event of a failure, you'll see diagnostics listing the extra and/or missing languages, like so: # Failed test 225: "There should be the correct procedural languages" # Extra languages: # pllolcode # Missing languages: # plpgsql ### `opclasses_are()` ### SELECT opclasses_are( :schema, :opclasses, :description ); SELECT opclasses_are( :schema, :opclasses ); SELECT opclasses_are( :opclasses, :description ); SELECT opclasses_are( :opclasses ); **Parameters** `:schema` : Name of a schema in which to find opclasses. `:opclasses` : An array of opclass names. `:description` : A short description of the test. This function tests that all of the operator classes in the named schema, or that are visible in the search path, are only the opclasses that *should* be there. If the `:schema` argument is omitted, opclasses will be sought in the search path, excluding `pg_catalog` and `information_schema`. If the description is omitted, a generally useful default description will be generated. Example: SELECT opclasses_are( 'myschema', ARRAY[ 'foo', 'bar', 'frobnitz' ] ); In the event of a failure, you'll see diagnostics listing the extra and/or missing opclasses, like so: # Failed test 251: "Schema public should have the correct operator classes" # Extra operator classes: # goofy_ops # Missing operator classes: # custom_ops ### `rules_are()` ### SELECT rules_are( :schema, :table, :rules, :description ); SELECT rules_are( :schema, :table, :rules ); SELECT rules_are( :table, :rules, :description ); SELECT rules_are( :table, :rules ); **Parameters** `:schema` : Name of a schema in which to find the `:table`. `:table` : Name of a table in which to find rules. `:rules` : An array of rule names. `:description` : A short description of the test. This function tests that all of the rules on the named relation are only the rules that *should* be on that relation (a table or a view). If the `:schema` argument is omitted, the rules must be visible in the search path, excluding `pg_catalog` and `information_schema`. If the description is omitted, a generally useful default description will be generated. Example: SELECT rules_are( 'myschema', 'atable', ARRAY[ 'on_insert', 'on_update', 'on_delete' ] ); In the event of a failure, you'll see diagnostics listing the extra and/or missing rules, like so: # Failed test 281: "Relation public.users should have the correct rules" # Extra rules: # on_select # Missing rules: # on_delete ### `types_are()` ### SELECT types_are( :schema, :types, :description ); SELECT types_are( :schema, :types ); SELECT types_are( :types, :description ); SELECT types_are( :types ); **Parameters** `:schema` : Name of a schema in which to find types. `:types` : An array of data type names. `:description` : A short description of the test. Tests that all of the types in the named schema are the only types in that schema, including base types, composite types, domains, enums, and pseudo-types. If the `:schema` argument is omitted, the types must be visible in the search path, excluding `pg_catalog` and `information_schema`. If the description is omitted, a generally useful default description will be generated. Example: SELECT types_are('myschema', ARRAY[ 'timezone', 'state' ]); In the event of a failure, you'll see diagnostics listing the extra and/or missing types, like so: # Failed test 307: "Schema someschema should have the correct types" # Extra types: # sometype # Missing types: # timezone ### `domains_are()` ### SELECT domains_are( :schema, :domains, :description ); SELECT domains_are( :schema, :domains ); SELECT domains_are( :domains, :description ); SELECT domains_are( :domains ); **Parameters** `:schema` : Name of a schema in which to find domains. `:domains` : An array of data domain names. `:description` : A short description of the test. Tests that all of the domains in the named schema are the only domains in that schema. If the `:schema` argument is omitted, the domains must be visible in the search path, excluding `pg_catalog` and `information_schema`. If the description is omitted, a generally useful default description will be generated. Example: SELECT domains_are('myschema', ARRAY[ 'timezone', 'state' ]); In the event of a failure, you'll see diagnostics listing the extra and/or missing domains, like so: # Failed test 327: "Schema someschema should have the correct domains" # Extra domains: # somedomain # Missing domains: # timezone ### `enums_are()` ### SELECT enums_are( :schema, :enums, :description ); SELECT enums_are( :schema, :enums ); SELECT enums_are( :enums, :description ); SELECT enums_are( :enums ); **Parameters** `:schema` : Name of a schema in which to find enums. `:enums` : An array of enum data type names. `:description` : A short description of the test. Tests that all of the enums in the named schema are the only enums in that schema. Enums are supported in PostgreSQL 8.3 and up. If the `:schema` argument is omitted, the enums must be visible in the search path, excluding `pg_catalog` and `information_schema`. If the description is omitted, a generally useful default description will be generated. Example: SELECT enums_are('myschema', ARRAY[ 'timezone', 'state' ]); In the event of a failure, you'll see diagnostics listing the extra and/or missing enums, like so: # Failed test 333: "Schema someschema should have the correct enums" # Extra enums: # someenum # Missing enums: # bug_status ### `casts_are()` ### SELECT casts_are( :casts, :description ); SELECT casts_are( :casts ); **Parameters** `:casts` : An array of cast names. `:description` : A short description of the test. This function tests that all of the casts in the database are only the casts that *should* be in that database. Casts are specified as strings in a syntax similarly to how they're declared via `CREATE CAST`. The pattern is `:source_type AS :target_type`. If either type was created with double-quotes to force mixed case or special characers, then you must use double quotes in the cast strings. Example: SELECT casts_are(ARRAY[ 'integer AS "myInteger"', 'integer AS double precision', 'integer AS reltime', 'integer AS numeric', ]); If the description is omitted, a generally useful default description will be generated. In the event of a failure, you'll see diagnostics listing the extra and/or missing casts, like so: # Failed test 302: "There should be the correct casts" # Extra casts: # lseg AS point # Missing casts: # lseg AS integer ### `operators_are()` ### SELECT operators_are( :schema, :operators, :description ); SELECT operators_are( :schema, :operators ); SELECT operators_are( :operators, :description ); SELECT operators_are( :operators ); **Parameters** `:schema` : Name of a schema in which to find operators. `:operators` : An array of operators. `:description` : A short description of the test. Tests that all of the operators in the named schema are the only operators in that schema. If the `:schema` argument is omitted, the operators must be visible in the search path, excluding `pg_catalog` and `information_schema`. If the description is omitted, a generally useful default description will be generated. The `:operators` argument is specified as an array of strings in which each operator is defined similarly to the display of the `:regoperator` type. The format is `:op(:leftop,:rightop) RETURNS :return_type`. For left operators the left argument type should be `NONE`. For right operators, the right argument type should be `NONE`. The example above shows one one of each of the operator types. `=(citext,citext)` is an infix operator, `-(bigint,NONE)` is a left operator, and `!(NONE,bigint)` is a right operator. Example: SELECT operators_are( 'public', ARRAY[ '=(citext,citext) RETURNS boolean', '-(NONE,bigint) RETURNS bigint', '!(bigint,NONE) RETURNS numeric' ] ); In the event of a failure, you'll see diagnostics listing the extra and/or missing operators, like so: # Failed test 453: "Schema public should have the correct operators" # Extra operators: # +(integer,integer) RETURNS integer # Missing enums: # +(integer,text) RETURNS text To Have or Have Not ------------------- Perhaps you're not so concerned with ensuring the [precise correlation of database objects](#I+Object! "I Object!"). Perhaps you just need to make sure that certain objects exist (or that certain objects *don't* exist). You've come to the right place. ### `has_tablespace()` ### SELECT has_tablespace( :tablespace, :location, :description ); SELECT has_tablespace( :tablespace, :description ); SELECT has_tablespace( :tablespace ); **Parameters** `:tablespace` : Name of a tablespace. `:location` : The tablespace's Location on disk. `:description` : A short description of the test. This function tests whether or not a tablespace exists in the database. The first argument is a tablespace name. The second is either the a file system path for the database or a test description. If you specify a location path, you must pass a description as the third argument; otherwise, if you omit the test description, it will be set to "Tablespace `:tablespace` should exist". Example: SELECT has_tablespace('sometablespace', '/data/dbs'); ### `hasnt_tablespace()` ### SELECT hasnt_tablespace( :tablespace, :description ); SELECT hasnt_tablespace( :tablespace ); **Parameters** `:tablespace` : Name of a tablespace. `:description` : A short description of the test. This function is the inverse of `has_tablespace()`. The test passes if the specified tablespace does *not* exist. ### `has_schema()` ### SELECT has_schema( :schema, :description ); SELECT has_schema( :schema ); **Parameters** `:schema` : Name of a schema. `:description` : A short description of the test. This function tests whether or not a schema exists in the database. The first argument is a schema name and the second is the test description. If you omit the test description, it will be set to "Schema `:schema` should exist". ### `hasnt_schema( schema, description )` ### ### `hasnt_schema( schema )` ### SELECT hasnt_schema( 'someschema', 'There should be no schema someschema' ); This function is the inverse of `has_schema()`. The test passes if the specified schema does *not* exist. ### `has_table()` ### SELECT has_table( :schema, :table, :description ); SELECT has_table( :table, :description ); SELECT has_table( :table ); **Parameters** `:schema` : Name of a schema in which to find the table. `:table` : Name of a table. `:description` : A short description of the test. This function tests whether or not a table exists in the database. The first argument is a schema name, the second is a table name, and the third is the test description. If you omit the schema, the table must be visible in the search path. Example: SELECT has_table('myschema', 'sometable'); If you omit the test description, it will be set to "Table `:table` should exist". ### `hasnt_table()` ### SELECT hasnt_table( :schema, :table, :description ); SELECT hasnt_table( :table, :description ); SELECT hasnt_table( :table ); **Parameters** `:schema` : Name of a schema in which to find the table. `:table` : Name of a table. `:description` : A short description of the test. This function is the inverse of `has_table()`. The test passes if the specified table does *not* exist. ### `has_view()` ### SELECT has_view( :schema, :view, :description ); SELECT has_view( :view, :description ); SELECT has_view( :view ); **Parameters** `:schema` : Name of a schema in which to find the view. `:view` : Name of a view. `:description` : A short description of the test. This function tests whether or not a view exists in the database. The first argument is a schema name, the second is a view name, and the third is the test description. If you omit the schema, the view must be visible in the search path. Example: SELECT has_view('myschema', 'someview'); If you omit the test description, it will be set to "View `:view` should exist". ### `hasnt_view()` ### SELECT hasnt_view( :schema, :view, :description ); SELECT hasnt_view( :view, :description ); SELECT hasnt_view( :view ); **Parameters** `:schema` : Name of a schema in which to find the view. `:view` : Name of a view. `:description` : A short description of the test. This function is the inverse of `has_view()`. The test passes if the specified view does *not* exist. ### `has_sequence()` ### SELECT has_sequence( :schema, :sequence, :description ); SELECT has_sequence( :sequence, :description ); SELECT has_sequence( :sequence ); **Parameters** `:schema` : Name of a schema in which to find the sequence. `:sequence` : Name of a sequence. `:description` : A short description of the test. This function tests whether or not a sequence exists in the database. The first argument is a schema name, the second is a sequence name, and the third is the test description. If you omit the schema, the sequence must be visible in the search path. Example: SELECT has_sequence('myschema', 'somesequence'); If you omit the test description, it will be set to "Sequence `:sequence` should exist". ### `hasnt_sequence()` ### SELECT hasnt_sequence( :schema, :sequence, :description ); SELECT hasnt_sequence( :sequence, :description ); SELECT hasnt_sequence( :sequence ); **Parameters** `:schema` : Name of a schema in which to find the sequence. `:sequence` : Name of a sequence. `:description` : A short description of the test. This function is the inverse of `has_sequence()`. The test passes if the specified sequence does *not* exist. ### `has_type()` ### SLEECT has_type( schema, type, description ); SELECT has_type( schema, type ); SELECT has_type( type, description ); SELECT has_type( type ); **Parameters** `:schema` : Name of a schema in which to find the sequence. `:type` : Name of a data type. `:description` : A short description of the test. This function tests whether or not a type exists in the database. Detects all types of types, including base types, composite types, domains, enums, and pseudo-types. The first argument is a schema name, the second is a type name, and the third is the test description. If you omit the schema, the type must be visible in the search path. If you omit the test description, it will be set to "Type `:type` should exist". If you're passing a schema and type rather than type and description, be sure to cast the arguments to `name` values so that your type name doesn't get treated as a description. Example: SELECT has_type( 'myschema', 'sometype' ); If you've created a composite type and want to test that the composed types are a part of it, use the column testing functions to verify them, like so: CREATE TYPE foo AS (id int, name text); SELECT has_type( 'foo' ); SELECT has_column( 'foo', 'id' ); SELECT col_type_is( 'foo', 'id', 'integer' ); ### `hasnt_type()` ### SLEECT hasnt_type( schema, type, description ); SELECT hasnt_type( schema, type ); SELECT hasnt_type( type, description ); SELECT hasnt_type( type ); **Parameters** `:schema` : Name of a schema in which to find the sequence. `:type` : Name of a data type. `:description` : A short description of the test. This function is the inverse of `has_type()`. The test passes if the specified type does *not* exist. ### `has_domain()` ### SLEECT has_domain( schema, domain, description ); SELECT has_domain( schema, domain ); SELECT has_domain( domain, description ); SELECT has_domain( domain ); **Parameters** `:schema` : Name of a schema in which to find the sequence. `:domain` : Name of a domain. `:description` : A short description of the test. This function tests whether or not a domain exists in the database. The first argument is a schema name, the second is the name of a domain, and the third is the test description. If you omit the schema, the domain must be visible in the search path. If you omit the test description, it will be set to "Domain `:domain` should exist". Example: SELECT has_domain( 'myschema', 'somedomain' ); If you're passing a schema and domain rather than domain and description, be sure to cast the arguments to `name` values so that your domain name doesn't get treated as a description. ### `hasnt_domain()` ### SLEECT hasnt_domain( schema, domain, description ); SELECT hasnt_domain( schema, domain ); SELECT hasnt_domain( domain, description ); SELECT hasnt_domain( domain ); **Parameters** `:schema` : Name of a schema in which to find the sequence. `:domain` : Name of a domain. `:description` : A short description of the test. This function is the inverse of `has_domain()`. The test passes if the specified domain does *not* exist. ### `has_enum()` ### SLEECT has_enum( schema, enum, description ); SELECT has_enum( schema, enum ); SELECT has_enum( enum, description ); SELECT has_enum( enum ); **Parameters** `:schema` : Name of a schema in which to find the sequence. `:enum` : Name of a enum. `:description` : A short description of the test. This function tests whether or not a enum exists in the database. Enums are supported in PostgreSQL 8.3 or higher. The first argument is a schema name, the second is the an enum name, and the third is the test description. If you omit the schema, the enum must be visible in the search path. If you omit the test description, it will be set to "Enum `:enum` should exist". Example: SELECT has_enum( 'myschema', 'someenum' ); If you're passing a schema and enum rather than enum and description, be sure to cast the arguments to `name` values so that your enum name doesn't get treated as a description. ### `hasnt_enum()` ### SLEECT hasnt_enum( schema, enum, description ); SELECT hasnt_enum( schema, enum ); SELECT hasnt_enum( enum, description ); SELECT hasnt_enum( enum ); **Parameters** `:schema` : Name of a schema in which to find the sequence. `:enum` : Name of a enum. `:description` : A short description of the test. This function is the inverse of `has_enum()`. The test passes if the specified enum does *not* exist. ### `has_index()` ### SELECT has_index( :schema, :table, :index, :columns, :description ); SELECT has_index( :schema, :table, :index, :columns ); SELECT has_index( :schema, :table, :index, :column, :description ); SELECT has_index( :schema, :table, :index, :column ); SELECT has_index( :table, :index, :columns, :description ); SELECT has_index( :table, :index, :columns, :description ); SELECT has_index( :table, :index, :column, :description ); SELECT has_index( :schema, :table, :index, :column ); SELECT has_index( :table, :index, :column ); SELECT has_index( :schema, :table, :index ); SELECT has_index( :table, :index, :description ); SELECT has_index( :table, :index ); **Parameters** `:schema` : Name of a schema in which to find the index. `:table` : Name of a table in which to find index. `:index` : Name of an index. `:columns` : Array of the columns in the index. `:column` : Idexed column name or expression. `:description` : A short description of the test. Checks for the existence of an index associated with the named table. The `:schema` argument is optional, as is the column name or names or expression, and the description. The columns argument may be a string naming one column or an array of column names. It may also be a string representing an expression, such as `lower(foo)`. For expressions, you must use lowercase for all SQL keywords and functions to properly compare to PostgreSQL's internal form of the expression. A few examples: SELECT has_index( 'myschema', 'sometable', 'myindex', ARRAY[ 'somecolumn', 'anothercolumn' ], 'Index "myindex" should exist' ); SELECT has_index('myschema', 'sometable', 'anidx', 'somecolumn'); SELECT has_index('myschema', 'sometable', 'loweridx', 'LOWER(somecolumn)'); SELECT has_index('sometable', 'someindex'); If you find that the function call seems to be getting confused, cast the index name to the `NAME` type: SELECT has_index( 'public', 'sometab', 'idx_foo', 'name'::name ); If the index does not exist, `has_index()` will output a diagnostic message such as: # Index "blah" ON public.sometab not found If the index was found but the column specification or expression is incorrect, the diagnostics will look more like this: # have: "idx_baz" ON public.sometab(lower(name)) # want: "idx_baz" ON public.sometab(lower(lname)) ### `hasnt_index()` ### SELECT hasnt_index( schema, table, index, description ); SELECT hasnt_index( schema, table, index ); SELECT hasnt_index( table, index, description ); SELECT hasnt_index( table, index ); **Parameters** `:schema` : Name of a schema in which to not find the index. `:table` : Name of a table in which to not find the index. `:index` : Name of an index. `:description` : A short description of the test. This function is the inverse of `has_index()`. The test passes if the specified index does *not* exist. ### `has_trigger()` ### SELECT has_trigger( :schema, :table, :trigger, :description ); SELECT has_trigger( :schema, :table, :trigger ); SELECT has_trigger( :table, :trigger, :description ); SELECT has_trigger( :table, :trigger )` ### **Parameters** `:schema` : Name of a schema in which to find the trigger. `:table` : Name of a table in which to find the trigger. `:trigger` : Name of an trigger. `:description` : A short description of the test. Tests to see if the specified table has the named trigger. The `:description` is optional, and if the schema is omitted, the table with which the trigger is associated must be visible in the search path. ### `hasnt_trigger()` ### SELECT hasnt_trigger( :schema, :table, :trigger, :description ); SELECT hasnt_trigger( :schema, :table, :trigger ); SELECT hasnt_trigger( :table, :trigger, :description ); SELECT hasnt_trigger( :table, :trigger )` ### **Parameters** `:schema` : Name of a schema in which to not find the trigger. `:table` : Name of a table in which to not find the trigger. `:trigger` : Name of an trigger. `:description` : A short description of the test. This function is the inverse of `has_trigger()`. The test passes if the specified trigger does *not* exist. ### `has_rule()` ### SELECT has_rule( :schema, :table, :rule, :description ); SELECT has_rule( :schema, :table, :rule ); SELECT has_rule( :table, :rule, :description ); SELECT has_rule( :table, :rule )` ### **Parameters** `:schema` : Name of a schema in which to find the rule. `:table` : Name of a table in which to find the rule. `:rule` : Name of an rule. `:description` : A short description of the test. Tests to see if the specified table has the named rule. The `:description` is optional, and if the schema is omitted, the table with which the rule is associated must be visible in the search path. ### `hasnt_rule()` ### SELECT hasnt_rule( :schema, :table, :rule, :description ); SELECT hasnt_rule( :schema, :table, :rule ); SELECT hasnt_rule( :table, :rule, :description ); SELECT hasnt_rule( :table, :rule )` ### **Parameters** `:schema` : Name of a schema in which to not find the rule. `:table` : Name of a table in which to not find the rule. `:rule` : Name of an rule. `:description` : A short description of the test. This function is the inverse of `has_rule()`. The test passes if the specified rule does *not* exist. ### `has_function()` ### SELECT has_function( :schema, :function, :args, :description ); SELECT has_function( :schema, :function, :args ); SELECT has_function( :schema, :function, :description ); SELECT has_function( :schema, :function ); SELECT has_function( :function, :args, :description ); SELECT has_function( :function, :args ); SELECT has_function( :function, :description ); SELECT has_function( :function ); **Parameters** `:schema` : Name of a schema in which to not find the function. `:function` : Name of a function. `:args` : Array of data types of the function arguments. `:description` : A short description of the test. Checks to be sure that the given function exists in the named schema and with the specified argument data types. If `:schema` is omitted, `has_function()` will search for the function in the schemas defined in the search path. If `:args` is omitted, `has_function()` will see if the function exists without regard to its arguments. Some examples: SELECT has_function( 'pg_catalog', 'decode', ARRAY[ 'text', 'text' ], 'Function decode(text, text) should exist' ); SELECT has_function( 'do_something' ); SELECT has_function( 'do_something', ARRAY['integer'] ); SELECT has_function( 'do_something', ARRAY['numeric'] ); The `:args` argument should be formatted as it would be displayed in the view of a function using the `\df` command in `psql`. For example, even if you have a numeric column with a precision of 8, you should specify `ARRAY['numeric']`". If you created a `varchar(64)` column, you should pass the `:args` argument as `ARRAY['character varying']`. If you wish to use the two-argument form of `has_function()`, specifying only the schema and the function name, you must cast the `:function` argument to `:name` in order to disambiguate it from from the `has_function(:function, :description)` form. If you neglect to do so, your results will be unexpected. Also, if you use the string form to specify the `:args` array, be sure to cast it to `name` to disambiguate it from a text string: SELECT has_function( 'lower', '{text}'::name[] ); **Deprecation notice:** The old name for this test function, `can_ok()`, is still available, but emits a warning when called. It will be removed in a future version of pgTAP. ### `hasnt_function()` ### SELECT hasnt_function( :schema, :function, :args, :description ); SELECT hasnt_function( :schema, :function, :args ); SELECT hasnt_function( :schema, :function, :description ); SELECT hasnt_function( :schema, :function ); SELECT hasnt_function( :function, :args, :description ); SELECT hasnt_function( :function, :args ); SELECT hasnt_function( :function, :description ); SELECT hasnt_function( :function ); **Parameters** `:schema` : Name of a schema in which not to find the function. `:function` : Name of a function. `:args` : Array of data types of the function arguments. `:description` : A short description of the test. This function is the inverse of `has_function()`. The test passes if the specified function (optionally with the specified signature) does *not* exist. ### `has_cast()` ### SELECT has_cast( :source_type, :target_type, :schema, :function, :description ); SELECT has_cast( :source_type, :target_type, :schema, :function ); SELECT has_cast( :source_type, :target_type, :function, :description ); SELECT has_cast( :source_type, :target_type, :function ); SELECT has_cast( :source_type, :target_type, :description ); SELECT has_cast( :source_type, :target_type ); **Parameters** `:source_type` : Data type of the source value. `:target_type` : Data type of the target value. `:schema` : Schema in which to find the operator function. `:function` : Name of the operator function. `:description` : A short description of the test. Tests for the existence of a cast. A cast consists of a source data type, a target data type, and perhaps a (possibly schema-qualified) function. An example: SELECT has_cast( 'integer', 'bigint', 'pg_catalog', 'int8' ); If you omit the description four the 3- or 4-argument version, you'll need to cast the function name to the `NAME` data type so that PostgreSQL doesn't resolve the function name as a description. For example: SELECT has_cast( 'integer', 'bigint', 'int8'::NAME ); pgTAP will generate a useful description if you don't provide one. ### `hasnt_cast()` ### SELECT hasnt_cast( :source_type, :target_type, :schema, :function, :description ); SELECT hasnt_cast( :source_type, :target_type, :schema, :function ); SELECT hasnt_cast( :source_type, :target_type, :function, :description ); SELECT hasnt_cast( :source_type, :target_type, :function ); SELECT hasnt_cast( :source_type, :target_type, :description ); SELECT hasnt_cast( :source_type, :target_type ); **Parameters** `:source_type` : Data type of the source value. `:target_type` : Data type of the target value. `:schema` : Schema in which not to find the operator function. `:function` : Name of the operator function. `:description` : A short description of the test. This function is the inverse of `has_cast()`: the test passes if the specified cast does *not* exist. SELECT has_operator( :left_type, :schema, :name, :right_type, :return_type, :description ); SELECT has_operator( :left_type, :schema, :name, :right_type, :return_type ); SELECT has_operator( :left_type, :name, :right_type, :return_type, :description ); SELECT has_operator( :left_type, :name, :right_type, :return_type ); SELECT has_operator( :left_type, :name, :right_type, :description ); SELECT has_operator( :left_type, :name, :right_type ); **Parameters** `:left_type` : Data type of the left operand. `:schema` : Schema in which to find the operator. `:name` : Name of the operator. `:right_type` : Data type of the right operand. `:return_type` : Data type of the return value. `:description` : A short description of the test. Tests for the presence of a binary operator. If the operator exists with the given schema, name, left and right arguments, and return value, the test will fail. If the operator does not exist, the test will fail. Example: SELECT has_operator( 'integer', 'pg_catalog', '<=', 'integer', 'boolean' ); If you omit the schema name, then the operator must be visible in the search path. If you omit the test description, pgTAP will generate a reasonable one for you. The return value is also optional. If you need to test for a left or right unary operator, use `has_leftop()` or `has_rightop()` instead. ### `has_leftop()` ### SELECT has_leftop( :schema, :name, :type, :return_type, :description ); SELECT has_leftop( :schema, :name, :type, :return_type ); SELECT has_leftop( :name, :type, :return_type, :description ); SELECT has_leftop( :name, :type, :return_type ); SELECT has_leftop( :name, :type, :description ); SELECT has_leftop( :name, :type ); **Parameters** `:schema` : Schema in which to find the operator. `:name` : Name of the operator. `:type` : Data type of the operand. `:return_type` : Data type of the return value. `:description` : A short description of the test. Tests for the presence of a left-unary operator. If the operator exists with the given schema, name, right argument, and return value, the test will fail. If the operator does not exist, the test will fail. Example: SELECT has_leftop( 'pg_catalog', '!!', 'bigint', 'numeric' ); If you omit the schema name, then the operator must be visible in the search path. If you omit the test description, pgTAP will generate a reasonable one for you. The return type is also optional. ### `has_rightop()` ### SELECT has_rightop( :schema, :name, :type, :return_type, :description ); SELECT has_rightop( :schema, :name, :type, :return_type ); SELECT has_rightop( :name, :type, :return_type, :description ); SELECT has_rightop( :name, :type, :return_type ); SELECT has_rightop( :name, :type, :description ); SELECT has_rightop( :name, :type ); **Parameters** `:schema` : Schema in which to find the operator. `:name` : Name of the operator. `:type` : Data type of the operand. `:return_type` : Data type of the return value. `:description` : A short description of the test. Tests for the presence of a right-unary operator. If the operator exists with the given left argument, schema, name, and return value, the test will fail. If the operator does not exist, the test will fail. Example: SELECT has_rightop( 'bigint', 'pg_catalog', '!', 'numeric' ); If you omit the schema name, then the operator must be visible in the search path. If you omit the test description, pgTAP will generate a reasonable one for you. The return type is also optional. ### `has_opclass()` ### SELECT has_opclass( :schema, :name, :description ); SELECT has_opclass( :schema, :name ); SELECT has_opclass( :name, :description ); SELECT has_opclass( :name ); **Parameters** `:schema` : Schema in which to find the operator class. `:name` : Name of the operator class. `:description` : A short description of the test. Tests for the presence of an operator class. If you omit the schema name, then the operator must be visible in the search path. If you omit the test description, pgTAP will generate a reasonable one for you. The return value is also optional. ### `hasnt_opclass()` ### SELECT hasnt_opclass( :schema, :name, :description ); SELECT hasnt_opclass( :schema, :name ); SELECT hasnt_opclass( :name, :description ); SELECT hasnt_opclass( :name ); **Parameters** `:schema` : Schema in which not to find the operator class. `:name` : Name of the operator class. `:description` : A short description of the test. This function is the inverse of `has_opclass()`. The test passes if the specified operator class does *not* exist. ### `has_role()` ### SELECT has_role( :role, :description ); SELECT has_role( :role ); **Parameters** `:role` : Name of the role. `:description` : A short description of the test. Checks to ensure that a database role exists. If the description is omitted, it will default to "Role `:role` should exist". ### `hasnt_role()` ### SELECT hasnt_role( :role, :description ); SELECT hasnt_role( :role ); **Parameters** `:role` : Name of the role. `:description` : A short description of the test. The inverse of `has_role()`, this function tests for the *absence* of a database role. ### `has_user()` ### SELECT has_user( :user, :description ); SELECT has_user( :user ); **Parameters** `:user` : Name of the user. `:description` : A short description of the test. Checks to ensure that a database user exists. If the description is omitted, it will default to "User `:user` should exist". ### `hasnt_user()` ### SELECT hasnt_user( :user, :description ); SELECT hasnt_user( :user ); **Parameters** `:user` : Name of the user. `:description` : A short description of the test. The inverse of `has_user()`, this function tests for the *absence* of a database user. ### `has_group()` ### SELECT has_group( :group, :description ); SELECT has_group( :group ); **Parameters** `:group` : Name of the group. `:description` : A short description of the test. Checks to ensure that a database group exists. If the description is omitted, it will default to "Group `:group` should exist". ### `hasnt_group()` ### SELECT hasnt_group( :group, :description ); SELECT hasnt_group( :group ); **Parameters** `:group` : Name of the group. `:description` : A short description of the test. The inverse of `has_group()`, this function tests for the *absence* of a database group. ### `has_language()` ### SELECT has_language( :language, :description ); SELECT has_language( :language ); **Parameters** `:language` : Name of the language. `:description` : A short description of the test. Checks to ensure that a procedural language exists. If the description is omitted, it will default to "Procedural language `:language` should exist". ### `hasnt_language()` ### SELECT hasnt_language( :language, :description ); SELECT hasnt_language( :language ); **Parameters** `:language` : Name of the language. `:description` : A short description of the test. The inverse of `has_language()`, this function tests for the *absence* of a procedural language. Table For One ------------- Okay, you're sure that your database has exactly the [right schema](#I+Object! "I Object!") and that all of the objects you need [are there](#To+Have+or+Have+Not "To Have or Have Not"). So let's take a closer look at tables. There are a lot of ways to look at tables, to make sure that they have all the columns, indexes, constraints, keys, and indexes they need. So we have the assertions to validate 'em. ### `has_column()` ### SELECT has_column( :schema, :table, :column, :description ); SELECT has_column( :table, :column, :description ); SELECT has_column( :table, :column ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table. `:column` : Name of the column. `:description` : A short description of the test. Tests whether or not a column exists in a given table, view, or composite type. The first argument is the schema name, the second the table name, the third the column name, and the fourth is the test description. If the schema is omitted, the table must be visible in the search path. If the test description is omitted, it will be set to "Column `:table.:column` should exist". ### `hasnt_column()` ### SELECT hasnt_column( :schema, :table, :column, :description ); SELECT hasnt_column( :table, :column, :description ); SELECT hasnt_column( :table, :column ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table. `:column` : Name of the column. `:description` : A short description of the test. This function is the inverse of `has_column()`. The test passes if the specified column does *not* exist in the specified table, view, or composite type. ### `col_not_null()` ### SELECT col_not_null( :schema, :table, :column, :description ); SELECT col_not_null( :table, :column, :description ); SELECT col_not_null( :table, :column ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table. `:column` : Name of the column. `:description` : A short description of the test. Tests whether the specified column has a `NOT NULL` constraint. The first argument is the schema name, the second the table name, the third the column name, and the fourth is the test description. If the schema is omitted, the table must be visible in the search path. If the test description is omitted, it will be set to "Column `:table.:column` should be NOT NULL". Note that this test will fail with a useful diagnostic message if the table or column in question does not exist. But use `has_column()` to make sure the column exists first, eh? ### `col_is_null()` ### SELECT col_is_null( :schema, :table, :column, :description ); SELECT col_is_null( :table, :column, :description ); SELECT col_is_null( :table, :column ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table. `:column` : Name of the column. `:description` : A short description of the test. This function is the inverse of `col_not_null()`: the test passes if the column does not have a `NOT NULL` constraint. The first argument is the schema name, the second the table name, the third the column name, and the fourth is the test description. If the schema is omitted, the table must be visible in the search path. If the test description is omitted, it will be set to "Column `:table.:column` should allow NULL". Note that this test will fail with a useful diagnostic message if the table or column in question does not exist. But use `has_column()` to make sure the column exists first, eh? ### `col_has_default()` ### SELECT col_has_default( :schema, :table, :column, :description ); SELECT col_has_default( :table, :column, :description ); SELECT col_has_default( :table, :column ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table. `:column` : Name of the column. `:description` : A short description of the test. Tests whether or not a column has a default value. Fails if the column doesn't have a default value. It will also fail if the column doesn't exist, and emit useful diagnostics to let you know: # Failed test 136: "desc" # Column public.sometab.__asdfasdfs__ does not exist ### `col_hasnt_default()` ### SELECT col_hasnt_default( :schema, :table, :column, :description ); SELECT col_hasnt_default( :table, :column, :description ); SELECT col_hasnt_default( :table, :column ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table. `:column` : Name of the column. `:description` : A short description of the test. This function is the inverse of `col_has_default()`. The test passes if the specified column does *not* have a default. It will still fail if the column does not exist, and emit useful diagnostics to let you know. SELECT col_type_is( :schema, :table, :column, :type_schema, :type, :description ); SELECT col_type_is( :schema, :table, :column, :type_schema, :type ); SELECT col_type_is( :schema, :table, :column, :type, :description ); SELECT col_type_is( :schema, :table, :column, :type ); SELECT col_type_is( :table, :column, :type, :description ); SELECT col_type_is( :table, :column, :type ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table. `:column` : Name of the column. `:type_schema` : Schema in which to find the data type. `:type` : Name of a data type. `:description` : A short description of the test. This function tests that the specified column is of a particular type. If it fails, it will emit diagnostics naming the actual type. The first argument is the schema name, the second the table name, the third the column name, the fourth the type's schema, the fifth the type, and the sixth is the test description. Example: If the table schema is omitted, the table and the type must be visible in the search path. If the test description is omitted, it will be set to "Column `:schema.:table.:column` should be type `:schema.:type`". Note that this test will fail if the table or column in question does not exist. The type argument should be formatted as it would be displayed in the view of a table using the `\d` command in `psql`. For example, if you have a numeric column with a precision of 8, you should specify "numeric(8,0)". If you created a `varchar(64)` column, you should pass the type as "character varying(64)". Example: SELECT col_type_is( 'myschema', 'sometable', 'somecolumn', 'numeric(10,2)' ); If the test fails, it will output useful diagnostics. For example this test: SELECT col_type_is( 'pg_catalog', 'pg_type', 'typname', 'text' ); Will produce something like this: # Failed test 138: "Column pg_catalog.pg_type.typname should be type text" # have: name # want: text It will even tell you if the test fails because a column doesn't exist or actually has no default. But use `has_column()` to make sure the column exists first, eh? ### `col_default_is()` ### SELECT col_default_is( :schema, :table, :column, :default, :description ); SELECT col_default_is( :table, :column, :default, :description ); SELECT col_default_is( :table, :column, :default ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table. `:column` : Name of the column. `:default` : Default value expressed as a string. `:description` : A short description of the test. Tests the default value of a column. If it fails, it will emit diagnostics showing the actual default value. The first argument is the schema name, the second the table name, the third the column name, the fourth the default value, and the fifth is the test description. If the schema is omitted, the table must be visible in the search path. If the test description is omitted, it will be set to "Column `:table.:column` should default to `:default`". Note that this test will fail if the table or column in question does not exist. The default argument must have an unambiguous type in order for the call to succeed. If you see an error such as 'ERROR: could not determine polymorphic type because input has type "unknown"', it's because you forgot to cast the expected value, probably a `NULL` (which, by the way, you can only properly test for in PostgreSQL 8.3 and later), to its proper type. IOW, this will fail: SELECT col_default_is( 'tab', age, NULL ); But this will not: SELECT col_default_is( 'tab', age, NULL::integer ); You can also test for functional defaults. Just specify the function call as a string: SELECT col_default_is( 'user', 'created_at', 'now()' ); If the test fails, it will output useful diagnostics. For example, this test: SELECT col_default_is( 'pg_catalog', 'pg_type', 'typname', 'foo', 'check typname' ); Will produce something like this: # Failed test 152: "check typname" # have: NULL # want: foo And if the test fails because the table or column in question does not exist, the diagnostics will tell you that, too. But you use `has_column()` and `col_has_default()` to test those conditions before you call `col_default_is()`, right? *Right???* Yeah, good, I thought so. ### `has_pk()` ### SELECT has_pk( :schema, :table, :description ); SELECT has_pk( :table, :description ); SELECT has_pk( :table ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table. `:description` : A short description of the test. Tests whether or not a table has a primary key. The first argument is the schema name, the second the table name, the the third is the test description. If the schema is omitted, the table must be visible in the search path. If the test description is omitted, it will be set to "Table `:table` should have a primary key". Note that this test will fail if the table in question does not exist. ### `hasnt_pk()` ### SELECT hasnt_pk( :schema, :table, :description ); SELECT hasnt_pk( :table, :description ); SELECT hasnt_pk( :table ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table. `:description` : A short description of the test. This function is the inverse of `has_pk()`. The test passes if the specified primary key does *not* exist. ### `has_fk()` ### SELECT has_fk( :schema, :table, :description ); SELECT has_fk( :table, :description ); SELECT has_fk( :table ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table. `:description` : A short description of the test. Tests whether or not a table has a foreign key constraint. The first argument is the schema name, the second the table name, the the third is the test description. If the schema is omitted, the table must be visible in the search path. If the test description is omitted, it will be set to "Table `:table` should have a foreign key constraint". Note that this test will fail if the table in question does not exist. ### `hasnt_fk()` ### SELECT hasnt_fk( :schema, :table, :description ); SELECT hasnt_fk( :table, :description ); SELECT hasnt_fk( :table ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table. `:description` : A short description of the test. This function is the inverse of `has_fk()`. The test passes if the specified foreign key does *not* exist. ### `col_is_pk()` ### SELECT col_is_pk( :schema, :table, :columns, :description ); SELECT col_is_pk( :schema, :table, :column, :description ); SELECT col_is_pk( :table, :columns, :description ); SELECT col_is_pk( :table, :column, :description ); SELECT col_is_pk( :table, :columns ); SELECT col_is_pk( :table, :column ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table containing the primary key. `:columns` : Array of the names of the primary key columns. `:column` : Name of the primary key column. `:description` : A short description of the test. Tests whether the specified column or columns in a table is/are the primary key for that table. If it fails, it will emit diagnostics showing the actual primary key columns, if any. The first argument is the schema name, the second the table name, the third the column name or an array of column names, and the fourth is the test description. Examples: SELECT col_is_pk( 'myschema', 'sometable', 'id' ); SELECT col_is_pk( 'persons', ARRAY['given_name', 'surname'] ); If the schema is omitted, the table must be visible in the search path. If the test description is omitted, it will be set to "Column `:table(:column)` should be a primary key". Note that this test will fail if the table or column in question does not exist. If the test fails, it will output useful diagnostics. For example this test: SELECT col_is_pk( 'pg_type', 'id' ); Will produce something like this: # Failed test 178: "Column pg_type.id should be a primary key" # have: {} # want: {id} ### `col_isnt_pk()` ### SELECT col_isnt_pk( :schema, :table, :columns, :description ); SELECT col_isnt_pk( :schema, :table, :column, :description ); SELECT col_isnt_pk( :table, :columns, :description ); SELECT col_isnt_pk( :table, :column, :description ); SELECT col_isnt_pk( :table, :columns ); SELECT col_isnt_pk( :table, :column ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table not containing the primary key. `:columns` : Array of the names of the primary key columns. `:column` : Name of the primary key column. `:description` : A short description of the test. This function is the inverse of `col_is_pk()`. The test passes if the specified column or columns are not a primary key. ### `col_is_fk()` ### SELECT col_is_fk( :schema, :table, :columns, :description ); SELECT col_is_fk( :schema, :table, :column, :description ); SELECT col_is_fk( :table, :columns, :description ); SELECT col_is_fk( :table, :column, :description ); SELECT col_is_fk( :table, :columns ); SELECT col_is_fk( :table, :column ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table containing the foreign key constraint. `:columns` : Array of the names of the foreign key columns. `:column` : Name of the foreign key column. `:description` : A short description of the test. Just like `col_is_fk()`, except that it test that the column or array of columns are a primary key. The diagnostics on failure are a bit different, too. Since the table might have more than one foreign key, the diagnostics simply list all of the foreign key constraint columns, like so: # Table widget has foreign key constraints on these columns: # {thingy_id} # {surname,given_name} ### `col_isnt_fk()` ### SELECT col_isnt_fk( :schema, :table, :columns, :description ); SELECT col_isnt_fk( :schema, :table, :column, :description ); SELECT col_isnt_fk( :table, :columns, :description ); SELECT col_isnt_fk( :table, :column, :description ); SELECT col_isnt_fk( :table, :columns ); SELECT col_isnt_fk( :table, :column ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table not containing the foreign key constraint. `:columns` : Array of the names of the foreign key columns. `:column` : Name of the foreign key column. `:description` : A short description of the test. This function is the inverse of `col_is_fk()`. The test passes if the specified column or columns are not a foreign key. ### `fk_ok()` ### SELECT fk_ok( :fk_schema, :fk_table, :fk_columns, :pk_schema, :pk_table, :pk_columns, :description ); SELECT fk_ok( :fk_schema, :fk_table, :fk_columns, :fk_schema, :pk_table, :pk_columns ); SELECT fk_ok( :fk_table, :fk_columns, :pk_table, :pk_columns, :description ); SELECT fk_ok( :fk_table, :fk_columns, :pk_table, :pk_columns ); SELECT fk_ok( :fk_schema, :fk_table, :fk_column, :pk_schema, :pk_table, :pk_column, :description ); SELECT fk_ok( :fk_schema, :fk_table, :fk_column, :pk_schema, :pk_table, :pk_column ); SELECT fk_ok( :fk_table, :fk_column, :pk_table, :pk_column, :description ); SELECT fk_ok( :fk_table, :fk_column, :pk_table, :pk_column ); **Parameters** `:fk_schema` : Schema in which to find the table with the foreign key `:fk_table` : Name of a table containing the foreign key. `:fk_columns` : Array of the names of the foreign key columns. `:fk_column` : Name of the foreign key column. `:pk_schema` : Schema in which to find the table with the primary key `:pk_table` : Name of a table containing the primary key. `:pk_columns` : Array of the names of the primary key columns. `:pk_column` : Name of the primary key column. `:description` : A short description of the test. This function combines `col_is_fk()` and `col_is_pk()` into a single test that also happens to determine that there is in fact a foreign key relationship between the foreign and primary key tables. To properly test your relationships, this should be your main test function of choice. The first three arguments are the schema, table, and column or array of columns that constitute the foreign key constraint. The schema name is optional, and the columns can be specified as a string for a single column or an array of strings for multiple columns. The next three arguments are the schema, table, and column or columns that constitute the corresponding primary key. Again, the schema is optional and the columns may be a string or array of strings (though of course it should have the same number of elements as the foreign key column argument). The seventh argument is an optional description If it's not included, it will be set to `:fk_schema.:fk_table(:fk_column)` should reference `:pk_column.pk_table(:pk_column)`. Some examples: SELECT fk_ok( 'myschema', 'sometable', 'big_id', 'myschema', 'bigtable', 'id' ); SELECT fk_ok( 'contacts', ARRAY['person_given_name', 'person_surname'], 'persons', ARRAY['given_name', 'surname'], ); If the test fails, it will output useful diagnostics. For example this test: SELECT fk_ok( 'contacts', 'person_id', 'persons', 'id' ); Will produce something like this: # Failed test 178: "Column contacts(person_id) should reference persons(id)" # have: contacts(person_id) REFERENCES persons(id)" # want: contacts(person_nick) REFERENCES persons(nick)" ### `has_unique()` ### SELECT has_unique( :schema, :table, :description ); SELECT has_unique( :table, :description ); SELECT has_unique( :table ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table containing the unique constraint. `:description` : A short description of the test. Tests whether or not a table has a unique constraint. The first argument is the schema name, the second the table name, the the third is the test description. If the schema is omitted, the table must be visible in the search path. If the test description is omitted, it will be set to "Table `:table` should have a unique constraint". Note that this test will fail if the table in question does not exist. ### `col_is_unique()` ### SELECT col_is_unique( schema, table, columns, description ); SELECT col_is_unique( schema, table, column, description ); SELECT col_is_unique( table, columns, description ); SELECT col_is_unique( table, column, description ); SELECT col_is_unique( table, columns ); SELECT col_is_unique( table, column ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table containing the unique constraint. `:columns` : Array of the names of the unique columns. `:column` : Name of the unique column. `:description` : A short description of the test. Just like `col_is_pk()`, except that it test that the column or array of columns have a unique constraint on them. Examples: SELECT col_is_unique( 'myschema', 'sometable', 'other_id' ); SELECT col_is_unique( 'contacts', ARRAY['given_name', 'surname'] ); In the event of failure, the diagnostics will list the unique constraints that were actually found, if any: Failed test 40: "users.email should be unique" have: {username} {first_name,last_name} want: {email} ### `has_check()` ### SELECT has_check( :schema, :table, :description ); SELECT has_check( :table, :description ); SELECT has_check( :table ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table containing the check constraint. `:description` : A short description of the test. Tests whether or not a table has a check constraint. The first argument is the schema name, the second the table name, the the third is the test description. If the schema is omitted, the table must be visible in the search path. If the test description is omitted, it will be set to "Table `:table` should have a check constraint". Note that this test will fail if the table in question does not exist. In the event of failure, the diagnostics will list the columns on the table that do have check constraints, if any: Failed test 41: "users.email should have a check constraint" have: {username} want: {email} ### `col_has_check()` ### SELECT col_has_check( :schema, :table, :columns, :description ); SELECT col_has_check( :schema, :table, :column, :description ); SELECT col_has_check( :table, :columns, :description ); SELECT col_has_check( :table, :column, :description ); SELECT col_has_check( :table, :columns ); SELECT col_has_check( :table, :column ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table containing the check constraint. `:columns` : Array of the names of the check constraint columns. `:column` : Name of the check constraint column. `:description` : A short description of the test. Just like `col_is_pk()`, except that it test that the column or array of columns have a check constraint on them. ### `index_is_unique()` ### SELECT index_is_unique( :schema, :table, :index, :description ); SELECT index_is_unique( :schema, :table, :index ); SELECT index_is_unique( :table, :index ); SELECT index_is_unique( :index ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table containing the index. `:index` : Name of the index. `:description` : A short description of the test. Tests whether an index is unique. ### `index_is_primary()` ### SELECT index_is_primary( :schema, :table, :index, :description ); SELECT index_is_primary( :schema, :table, :index ); SELECT index_is_primary( :table, :index ); SELECT index_is_primary( :index ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table containing the index. `:index` : Name of the index. `:description` : A short description of the test. Tests whether an index is on a primary key. ### `is_clustered()` ### SELECT is_clustered( :schema, :table, :index, :description ); SELECT is_clustered( :schema, :table, :index ); SELECT is_clustered( :table, :index ); SELECT is_clustered( :index ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table containing the index. `:index` : Name of the index. `:description` : A short description of the test. Tests whether a table is clustered on the given index. A table is clustered on an index when the SQL command `CLUSTER TABLE INDEXNAME` has been executed. Clustering reorganizes the table tuples so that they are stored on disk in the order defined by the index. ### `index_is_type()` ### SELECT index_is_type( :schema, :table, :index, :type, :description ); SELECT index_is_type( :schema, :table, :index, :type ); SELECT index_is_type( :table, :index, :type ); SELECT index_is_type( :index, :type ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Name of a table containing the index. `:index` : Name of the index. `:type` : The index Type. `:description` : A short description of the test. Tests to ensure that an index is of a particular type. At the time of this writing, the supported types are: * btree * hash * gist * gin If the test fails, it will emit a diagnostic message with the actual index type, like so: # Failed test 175: "Index idx_bar should be a hash index" # have: btree # want: hash Feeling Funky ------------- Perhaps more important than testing the database schema is testing your custom functions. Especially if you write functions that provide the interface for clients to interact with the database, making sure that they work will save you time in the long run. So check out these assertions to maintain your sanity. ### `can()` ### SELECT can( :schema, :functions, :description ); SELECT can( :schema, :functions ); SELECT can( :functions, :description ); SELECT can( :functions ); **Parameters** `:schema` : Schema in which to find the functions. `:functions` : Array of function names. `:description` : A short description of the test. Checks to be sure that `:schema` has `:functions` defined. This is subtly different from `functions_are()`. `functions_are()` fails if the functions defined in `:schema` are not exactly the functions defined in `:functions`. `can()`, on the other hand, just makes sure that `:functions` exist. If `:schema` is omitted, then `can()` will look for functions defined in schemas defined in the search path. No matter how many functions are listed in `:functions`, a single call to `can()` counts as one test. If you want otherwise, call `can()` once for each function -- or better yet, use `has_function()`. Example: SELECT can( 'pg_catalog', ARRAY['upper', 'lower'] ); If any of the functions are not defined, the test will fail and the diagnostics will output a list of the functions that are missing, like so: # Failed test 52: "Schema pg_catalog can" # pg_catalog.foo() missing # pg_catalog.bar() missing ### `function_lang_is()` ### SELECT function_lang_is( :schema, :function, :args, :language, :description ); SELECT function_lang_is( :schema, :function, :args, :language ); SELECT function_lang_is( :schema, :function, :language, :description ); SELECT function_lang_is( :schema, :function, :language ); SELECT function_lang_is( :function, :args, :language, :description ); SELECT function_lang_is( :function, :args, :language ); SELECT function_lang_is( :function, :language, :description ); SELECT function_lang_is( :function, :language ); **Parameters** `:schema` : Schema in which to find the function. `:function` : Function name. `:args` : Array of data types for the function arguments. `:language` : Name of the procedural language. `:description` : A short description of the test. Tests that a particular function is implemented in a particular procedural language. The function name is required. If the `:schema` argument is omitted, then the function must be visible in the search path. If the `:args[]` argument is passed, then the function with that argument signature will be the one tested; otherwise, a function with any signature will be checked (pass an empty array to specify a function with an empty signature). If the `:description` is omitted, a reasonable substitute will be created. Examples: SELECT function_lang_is( 'myschema', 'foo', ARRAY['integer', 'text'], 'plperl' ); SELECT function_lang_is( 'do_something', 'sql' ); SELECT function_lang_is( 'do_something', ARRAY['integer'], 'plpgsql' ); SELECT function_lang_is( 'do_something', ARRAY['numeric'], 'plpgsql' ); In the event of a failure, you'll useful diagnostics will tell you what went wrong, for example: # Failed test 211: "Function mychema.eat(integer, text) should be written in perl" # have: plpgsql # want: perl If the function does not exist, you'll be told that, too. # Failed test 212: "Function myschema.grab() should be written in sql # Function myschema.grab() does not exist But then you check with `has_function()` first, right? ### `function_returns()` ### SELECT function_returns( :schema, :function, :args, :type, :description ); SELECT function_returns( :schema, :function, :args, :type ); SELECT function_returns( :schema, :function, :type, :description ); SELECT function_returns( :schema, :function, :type ); SELECT function_returns( :function, :args, :type, :description ); SELECT function_returns( :function, :args, :type ); SELECT function_returns( :function, :type, :description ); SELECT function_returns( :function, :type ); **Parameters** `:schema` : Schema in which to find the function. `:function` : Function name. `:args` : Array of data types for the function arguments. `:Type` : Return value data type. `:description` : A short description of the test. Tests that a particular function returns a particular data type. The `:args[]` and `:type` arguments should be formatted as they would be displayed in the view of a function using the `\df` command in `psql`. For example, use "character varying" rather than "varchar", and "boolean" rather than "bool". For set returning functions, the `:type` argument should start with "setof " (yes, lowercase). Examples: SELECT function_returns( 'myschema', 'foo', ARRAY['integer', 'text'], 'integer' ); SELECT function_returns( 'do_something', 'setof bool' ); SELECT function_returns( 'do_something', ARRAY['integer'], 'boolean' ); SELECT function_returns( 'do_something', ARRAY['numeric'], 'numeric' ); If the `:schema` argument is omitted, then the function must be visible in the search path. If the `:args[]` argument is passed, then the function with that argument signature will be the one tested; otherwise, a function with any signature will be checked (pass an empty array to specify a function with an empty signature). If the `:description` is omitted, a reasonable substitute will be created. In the event of a failure, you'll useful diagnostics will tell you what went wrong, for example: # Failed test 283: "Function oww(integer, text) should return integer" # have: bool # want: integer If the function does not exist, you'll be told that, too. # Failed test 284: "Function oui(integer, text) should return integer" # Function oui(integer, text) does not exist But then you check with `has_function()` first, right? ### `is_definer()` ### SELECT is_definer( :schema, :function, :args, :description ); SELECT is_definer( :schema, :function, :args ); SELECT is_definer( :schema, :function, :description ); SELECT is_definer( :schema, :function ); SELECT is_definer( :function, :args, :description ); SELECT is_definer( :function, :args ); SELECT is_definer( :function, :description ); SELECT is_definer( :function ); **Parameters** `:schema` : Schema in which to find the function. `:function` : Function name. `:args` : Array of data types for the function arguments. `:description` : A short description of the test. Tests that a function is a security definer (i.e., a "setuid" function). If the `:schema` argument is omitted, then the function must be visible in the search path. If the `:args` argument is passed, then the function with that argument signature will be the one tested; otherwise, a function with any signature will be checked (pass an empty array to specify a function with an empty signature). If the `:description` is omitted, a reasonable substitute will be created. Examples: SELECT is_definer( 'myschema', 'foo', ARRAY['integer', 'text'] ); SELECT is_definer( 'do_something' ); SELECT is_definer( 'do_something', ARRAY['integer'] ); SELECT is_definer( 'do_something', ARRAY['numeric'] ); If the function does not exist, a handy diagnostic message will let you know: # Failed test 290: "Function nasty() should be security definer" # Function nasty() does not exist But then you check with `has_function()` first, right? ### `is_strict()` ### SELECT is_strict( :schema, :function, :args, :description ); SELECT is_strict( :schema, :function, :args ); SELECT is_strict( :schema, :function, :description ); SELECT is_strict( :schema, :function ); SELECT is_strict( :function, :args, :description ); SELECT is_strict( :function, :args ); SELECT is_strict( :function, :description ); SELECT is_strict( :function ); **Parameters** `:schema` : Schema in which to find the function. `:function` : Function name. `:args` : Array of data types for the function arguments. `:description` : A short description of the test. Tests that a function is a strict, meaning that the function returns null if any argument is null. If the `:schema` argument is omitted, then the function must be visible in the search path. If the `:args` argument is passed, then the function with that argument signature will be the one tested; otherwise, a function with any signature will be checked (pass an empty array to specify a function with an empty signature). If the `:description` is omitted, a reasonable substitute will be created. Examples: SELECT is_strict( 'myschema', 'foo', ARRAY['integer', 'text'] ); SELECT is_strict( 'do_something' ); SELECT is_strict( 'do_something', ARRAY['integer'] ); SELECT is_strict( 'do_something', ARRAY['numeric'] ); If the function does not exist, a handy diagnostic message will let you know: # Failed test 290: "Function nasty() should be strict # Function nasty() does not exist But then you check with `has_function()` first, right? ### `is_aggregate()` ### SELECT is_aggregate( :schema, :function, :args, :description ); SELECT is_aggregate( :schema, :function, :args ); SELECT is_aggregate( :schema, :function, :description ); SELECT is_aggregate( :schema, :function ); SELECT is_aggregate( :function, :args, :description ); SELECT is_aggregate( :function, :args ); SELECT is_aggregate( :function, :description ); SELECT is_aggregate( :function ); **Parameters** `:schema` : Schema in which to find the function. `:function` : Function name. `:args` : Array of data types for the function arguments. `:description` : A short description of the test. Tests that a function is an aggregate function. If the `:schema` argument is omitted, then the function must be visible in the search path. If the `:args[]` argument is passed, then the function with that argument signature will be the one tested; otherwise, a function with any signature will be checked (pass an empty array to specify a function with an empty signature). If the `:description` is omitted, a reasonable substitute will be created. Examples: SELECT is_aggregate( 'myschema', 'foo', ARRAY['integer', 'text'] ); SELECT is_aggregate( 'do_something' ); SELECT is_aggregate( 'do_something', ARRAY['integer'] ); SELECT is_aggregate( 'do_something', ARRAY['numeric'] ); If the function does not exist, a handy diagnostic message will let you know: # Failed test 290: "Function nasty() should be strict # Function nasty() does not exist But then you check with `has_function()` first, right? ### `volatility_is()` ### SELECT volatility_is( :schema, :function, :args, :volatility, :description ); SELECT volatility_is( :schema, :function, :args, :volatility ); SELECT volatility_is( :schema, :function, :volatility, :description ); SELECT volatility_is( :schema, :function, :volatility ); SELECT volatility_is( :function, :args, :volatility, :description ); SELECT volatility_is( :function, :args, :volatility ); SELECT volatility_is( :function, :volatility, :description ); SELECT volatility_is( :function, :volatility ); **Parameters** `:schema` : Schema in which to find the function. `:function` : Function name. `:args` : Array of data types for the function arguments. `:volatility` : Volatility level. `:description` : A short description of the test. Tests the volatility of a function. Supported volatilities are "volatile", "stable", and "immutable". Consult the [`CREATE FUNCTION` documentation](http://www.postgresql.org/docs/current/static/sql-createfunction.html) for details. The function name is required. If the `:schema` argument is omitted, then the function must be visible in the search path. If the `:args[]` argument is passed, then the function with that argument signature will be the one tested; otherwise, a function with any signature will be checked (pass an empty array to specify a function with an empty signature). If the `:description` is omitted, a reasonable substitute will be created. Examples: SELECT volatility_is( 'myschema', 'foo', ARRAY['integer', 'text'], 'stable' ); SELECT volatility_is( 'do_something', 'immutable' ); SELECT volatility_is( 'do_something', ARRAY['integer'], 'stable' ); SELECT volatility_is( 'do_something', ARRAY['numeric'], 'volatile' ); In the event of a failure, you'll useful diagnostics will tell you what went wrong, for example: # Failed test 211: "Function mychema.eat(integer, text) should be IMMUTABLE" # have: VOLATILE # want: IMMUTABLE If the function does not exist, you'll be told that, too. # Failed test 212: "Function myschema.grab() should be IMMUTABLE # Function myschema.grab() does not exist But then you check with `has_function()` first, right? ### `trigger_is()` ### SELECT trigger_is( :schema, :table, :trigger, :func_schema, :function, :description ); SELECT trigger_is( :schema, :table, :trigger, :func_schema, :function ); SELECT trigger_is( :table, :trigger, :function, :description ); SELECT trigger_is( :table, :trigger, :function ); **Parameters** `:schema` : Schema in which to find the table. `:table` : Table in which to find the trigger. `:trigger` : Trigger name. `:func_schema` : Schema in which to find the trigger function. `:function` : Function name. `:description` : A short description of the test. Tests that the specified trigger calls the named function. If not, it outputs a useful diagnostic: # Failed test 31: "Trigger set_users_pass should call hash_password()" # have: hash_pass # want: hash_password Database Deets -------------- Tables and functions aren't the only objects in the database, as you well know. These assertions close the gap by letting you test the attributes of other database objects. ### `language_is_trusted()` ### SELECT language_is_trusted( language, description ); SELECT language_is_trusted( language ); **Parameters** `:language` : Name of a procedural language. `:description` : A short description of the test. Tests that the specified procedural language is trusted. See the [CREATE LANGUAGE](http://www.postgresql.org/docs/current/static/sql-createlanguage.html "CREATE LANGUAGE") documentation for details on trusted and untrusted procedural languages. If the `:description` argument is not passed, a suitably useful default will be created. In the event that the language in question does not exist in the database, `language_is_trusted()` will emit a diagnostic message to alert you to this fact, like so: # Failed test 523: "Procedural language plomgwtf should be trusted" # Procedural language plomgwtf does not exist But you really ought to call `has_language()` first so that you never get that far. ### `enum_has_labels()` ### SELECT enum_has_labels( :schema, :enum, :labels, :description ); SELECT enum_has_labels( :schema, :enum, :labels ); SELECT enum_has_labels( :enum, :labels, :description ); SELECT enum_has_labels( :enum, :labels ); **Parameters** `:schema` : Schema in which to find the enum. `:enum` : Enum name. `:labels` : An array of the enum labels. `:description` : A short description of the test. This function tests that an enum consists of an expected list of labels. Enums are supported in PostgreSQL 8.3 or higher. The first argument is a schema name, the second an enum name, the third an array of enum labels, and the fourth a description. Example: SELECT enum_has_labels( 'myschema', 'someenum', ARRAY['foo', 'bar'] ); If you omit the schema, the enum must be visible in the search path. If you omit the test description, it will be set to "Enum `:enum` should have labels (`:labels`)". ### `domain_type_is()` ### SELECT domain_type_is( :schema, :domain, :type_schema, :type, :description ); SELECT domain_type_is( :schema, :domain, :type_schema, :type ); SELECT domain_type_is( :schema, :domain, :type, :description ); SELECT domain_type_is( :schema, :domain, :type ); SELECT domain_type_is( :domain, :type, :description ); SELECT domain_type_is( :domain, :type ); **Parameters** `:schema` : Schema in which to find the domain. `:domain` : Domain name. `:type_schema` : Schema in which to find the data type. `:type` : Domain data type. `:description` : A short description of the test. Tests the data type underlying a domain. The first two are arguments are the schema and name of the domain. The second two are the schema and name of the type that the domain should extend. The fifth argument is a description. If there is no description, a reasonable default description will be created. The schema arguments are also optional (though if there is no schema for the domain then there cannot be one for the type). For the 3- and 4-argument forms with schemas, cast the schemas to `NAME` to avoid ambiguities. Example: SELECT domain_type_is( 'public'::name, 'us_postal_code', 'public'::name, 'text' ); If the data type does not match the type that the domain extends, the test will fail and output diagnostics like so: # Failed test 631: "Domain public.us_postal_code should extend type public.integer" # have: public.text # want: public.integer If the domain in question does not actually exist, the test will fail with diagnostics that tell you so: # Failed test 632: "Domain public.zip_code should extend type public.text" # Domain public.zip_code does not exist ### `domain_type_isnt()` ### SELECT domain_type_isnt( :schema, :domain, :type_schema, :type, :description ); SELECT domain_type_isnt( :schema, :domain, :type_schema, :type ); SELECT domain_type_isnt( :schema, :domain, :type, :description ); SELECT domain_type_isnt( :schema, :domain, :type ); SELECT domain_type_isnt( :domain, :type, :description ); SELECT domain_type_isnt( :domain, :type ); **Parameters** `:schema` : Schema in which to find the domain. `:domain` : Domain name. `:type_schema` : Schema in which to find the data type. `:type` : Domain data type. `:description` : A short description of the test. The inverse of `domain_type_is()`, this function tests that a domain does *not* extend a particular data type. For example, a US postal code domain should probably extned the `text` type, not `integer`, since leading 0s are valid and required. Example: SELECT domain_type_isnt( 'public', 'us_postal_code', 'public', 'integer', 'The us_postal_code domain should not extend the integer type' ); The arguments are the same as for `domain_type_is()`. ### `cast_context_is()` ### SELECT cast_context_is( :source_type, :target_type, :context, :description ); SELECT cast_context_is( :source_type, :target_type, :context ); **Parameters** `:source_type` : The type cast from. `:target_type` : The type cast to. `:context` : The context for the cast, one of "implicit", "assignment", or "explicit". Test that a cast from a source to a target data type has a particular context. Example: SELECT cast_context_is( 'integer', 'bigint', 'implicit' ); The data types should be passed as they are displayed by `pg_catalog.format_type()`. For example, you would need to pass "character varying", and not "VARCHAR". The The supported contexts are "implicit", "assignment", and "explicit". You can also just pass in "i", "a", or "e". Consult the PostgreSQL [`CREATE CAST`](http://www.postgresql.org/docs/current/static/sql-createcast.html) documentation for the differences between these contexts (hint: they correspond to the default context, `AS IMPLICIT`, and `AS ASSIGNMENT`). If you don't supply a test description, pgTAP will create a reasonable one for you. Test failure will result in useful diagnostics, such as: # Failed test 124: "Cast ("integer" AS "bigint") context should be explicit" # have: implicit # want: explicit If the cast doesn't exist, you'll be told that, too: # Failed test 199: "Cast ("integer" AS foo) context should be explicit" # Cast ("integer" AS foo) does not exist But you've already used `has_cast()` to make sure of that, right? ### `is_superuser()` ### SELECT is_superuser( :user, :description ); SELECT is_superuser( :user ); **Parameters** `:user` : Name of a PostgreSQL user. `:description` : A short description of the test. Tests that a database user is a super user. If the description is omitted, it will default to "User `:user` should be a super user". Example: SELECT is_superuser('theory' ; If the user does not exist in the database, the diagnostics will say so. ### `isnt_superuser( user, description )` ### ### `isnt_superuser( user )` ### SELECT is_superuser( 'dr_evil', 'User "dr_evil" should not be a super user' ); The inverse of `is_superuser()`, this function tests that a database user is *not* a super user. Note that if the named user does not exist in the database, the test is still considered a failure, and the diagnostics will say so. ### `is_member_of()` ### SELECT is_member_of( :group, :users, :description ); SELECT is_member_of( :group, :users ); SELECT is_member_of( :group, :user, :description ); SELECT is_member_of( :group, :user ); **Parameters** `:group` : Name of a PostgreSQL group. `:users` : Array of names of users that should be members of the group. `:user` : Name of a user that should be a member of the group. `:description` : A short description of the test. SELECT is_member_of( 'sweeties', 'anna' 'Anna should be a sweetie' ); SELECT is_member_of( 'meanies', ARRAY['dr_evil', 'dr_no' ] ); Checks whether a group contains a user or all of an array of users. If the description is omitted, it will default to "Should have members of group `:group`." On failure, `is_member_of()` will output diagnostics listing the missing users, like so: # Failed test 370: "Should have members of group meanies" # Users missing from the meanies group: # theory # agliodbs If the group does not exist, the diagnostics will tell you that, instead. But you use `has_group()` to make sure the group exists before you check its members, don't you? Of course you do. ### `rule_is_instead()` ### SELECT rule_is_instead( :schema, :table, :rule, :description ); SELECT rule_is_instead( :schema, :table, :rule ); SELECT rule_is_instead( :table, :rule, :description ); SELECT rule_is_instead( :table, :rule ); **Parameters** `:schema` : Name of a schema in which to find the table. `:table` : Name of the table to which the rule is applied. `:rule` : A rule name. `:description` : A short description of the test. Checks whether a rule on the specified relation is an `INSTEAD` rule. See the [`CREATE RULE` Documentation](http://www.postgresql.org/docs/current/static/sql-createrule.html) for details. If the `:schema` argument is omitted, the relation must be visible in the search path. If the `:description` argument is omitted, an appropriate description will be created. An example: SELECT rule_is_instead('public', 'users', 'on_insert'); In the event that the test fails because the rule in question does not actually exist, you will see an appropriate diagnostic such as: # Failed test 625: "Rule on_insert on relation public.users should be an INSTEAD rule" # Rule on_insert does not exist ### `rule_is_on()` ### SELECT rule_is_on( :schema, :table, :rule, :event, :description ); SELECT rule_is_on( :schema, :table, :rule, :event ); SELECT rule_is_on( :table, :rule, :event, :description ); SELECT rule_is_on( :table, :rule, :event ); **Parameters** `:schema` : Name of a schema in which to find the table. `:table` : Name of the table to which the rule is applied. `:rule` : A rule name. `:event` : Name of a rule event, one of "SELECT", "INSERT", "UPDATE", or "DELETE". `:description` : A short description of the test. Tests the event for a rule, which may be one of "SELECT", "INSERT", "UPDATE", or "DELETE". For the `:event` argument, you can specify the name of the event in any case, or even with a single letter ("s", "i", "u", or "d"). If the `:schema` argument is omitted, then the table must be visible in the search path. If the `:description` is omitted, a reasonable default will be created. Example: SELECT rule_is_on('public', 'users', 'on_insert', 'INSERT'); If the test fails, you'll see useful diagnostics, such as: # Failed test 133: "Rule ins_me should be on INSERT to public.widgets" # have: UPDATE # want: INSERT If the rule in question does not exist, you'll be told that, too: # Failed test 134: "Rule upd_me should be on UPDATE to public.widgets" # Rule upd_me does not exist on public.widgets But then you run `has_rule()` first, don't you? Who owns me? ------------ After testing the availability of several objects, we often need to know who owns an object. ### `db_owner_is ()` ### SELECT db_owner_is ( :dbname, :user, :description ); SELECT db_owner_is ( :dbname, :user ); **Parameters** `:dbname` : Name of a database. `:user` : Name of a user. `:description` : A short description of the test. Tests the ownership of the database. If the `:description` argument is omitted, an appropriate description will be created. Examples: SELECT db_owner_is( 'mydb', 'someuser', 'mydb should be owned by someuser' ); SELECT db_owner_is( current_database(), current_user ); In the event that the test fails because the database in question does not actually exist, you will see an appropriate diagnostic such as: # Failed test 16: "Database foo should be owned by www" # Database foo does not exist If the test fails because the database is not owned by the specified user, the diagnostics will look something like: # Failed test 17: "Database bar should be owned by root" # have: postgres # want: root No Test for the Wicked ====================== There is more to pgTAP. Oh *so* much more! You can output your own [diagnostics](#Diagnostics). You can write [conditional tests](#Conditional+Tests) based on the output of [utility functions](#Utility+Functions). You can [batch up tests in functions](#Tap+That+Batch). Read on to learn all about it. Diagnostics ----------- If you pick the right test function, you'll usually get a good idea of what went wrong when it failed. But sometimes it doesn't work out that way. So here we have ways for you to write your own diagnostic messages which are safer than just `\echo` or `SELECT foo`. ### `diag()` ### SELECT diag( :lines ); **Parameters** `:lines` : A list of one or more SQL values of the same type. Returns a diagnostic message which is guaranteed not to interfere with test output. Handy for this sort of thing: -- Output a diagnostic message if the collation is not en_US.UTF-8. SELECT diag( E'These tests expect LC_COLLATE to be en_US.UTF-8,\n', 'but yours is set to ', setting, E'.\n', 'As a result, some tests may fail. YMMV.' ) FROM pg_settings WHERE name = 'lc_collate' AND setting <> 'en_US.UTF-8'; Which would produce: # These tests expect LC_COLLATE to be en_US.UTF-8, # but yours is set to en_US.ISO8859-1. # As a result, some tests may fail. YMMV. You can pass data of any type to `diag()` on PostgreSQL 8.3 and higher and it will all be converted to text for the diagnostics. On PostgreSQL 8.4 and higher, you can pass any number of arguments (as long as they are all the same data type) and they will be concatenated together. Conditional Tests ----------------- Sometimes running a test under certain conditions will cause the test script or function to die. A certain function or feature isn't implemented (such as `pg_sleep()` prior to PostgreSQL 8.2), some resource isn't available (like a procedural language), or a contrib module isn't available. In these cases it's necessary to skip tests, or declare that they are supposed to fail but will work in the future (a todo test). ### `skip()` ### SELECT skip( :why, :how_many ); SELECT skip( :how_many, :why ); SELECT skip( :why ); SELECT skip( :how_many ); **Parameters** `:why` : Reason for skipping the tests. `:how_many` : Number of tests to skip Outputs SKIP test results. Use it in a conditional expression within a `SELECT` statement to replace the output of a test that you otherwise would have run. SELECT CASE WHEN pg_version_num() < 80300 THEN skip('has_enum() not supported before 8.3', 2 ) ELSE collect_tap( has_enum( 'bug_status' ), has_enum( 'bug_status', 'mydesc' ) ) END; Note how use of the conditional `CASE` statement has been used to determine whether or not to run a couple of tests. If they are to be run, they are run through `collect_tap()`, so that we can run a few tests in the same query. If we don't want to run them, we call `skip()` and tell it how many tests we're skipping. If you don't specify how many tests to skip, `skip()` will assume that you're skipping only one. This is useful for the simple case, of course: SELECT CASE current_schema() WHEN 'public' THEN is( :this, :that ) ELSE skip( 'Tests not running in the "public" schema' ) END; But you can also use it in a `SELECT` statement that would otherwise return multiple rows: SELECT CASE current_schema() WHEN 'public' THEN is( nspname, 'public' ) ELSE skip( 'Cannot see the public schema' ) END FROM pg_namespace; This will cause it to skip the same number of rows as would have been tested had the `WHEN` condition been true. ### `todo()` ### SELECT todo( :why, :how_many ); SELECT todo( :how_many, :why ); SELECT todo( :why ); SELECT todo( :how_many ); **Parameters** `:why` : Reason for marking tests as to dos. `:how_many` : Number of tests to mark as to dos. Declares a series of tests that you expect to fail and why. Perhaps it's because you haven't fixed a bug or haven't finished a new feature: SELECT todo('URIGeller not finished', 2); \set card '\'Eight of clubs\'' SELECT is( URIGeller.yourCard(), :card, 'Is THIS your card?' ); SELECT is( URIGeller.bendSpoon(), 'bent', 'Spoon bending, how original' ); With `todo()`, `:how_many` specifies how many tests are expected to fail. If `:how_many` is omitted, it defaults to 1. pgTAP will run the tests normally, but print out special flags indicating they are "todo" tests. The test harness will interpret these failures as ok. Should any todo test pass, the harness will report it as an unexpected success. You then know that the thing you had todo is done and can remove the call to `todo()`. The nice part about todo tests, as opposed to simply commenting out a block of tests, is that they're like a programmatic todo list. You know how much work is left to be done, you're aware of what bugs there are, and you'll know immediately when they're fixed. ### `todo_start( why )` ### ### `todo_start( )` ### This function allows you declare all subsequent tests as TODO tests, up until the `todo_end()` function is called. The `todo()` syntax is generally pretty good about figuring out whether or not we're in a TODO test. However, often we find it difficult to specify the *number* of tests that are TODO tests. Thus, you can instead use `todo_start()` and `todo_end()` to more easily define the scope of your TODO tests. Note that you can nest TODO tests, too: SELECT todo_start('working on this'); -- lots of code SELECT todo_start('working on that'); -- more code SELECT todo_end(); SELECT todo_end(); This is generally not recommended, but large testing systems often have weird internal needs. The `todo_start()` and `todo_end()` function should also work with the `todo()` function, although it's not guaranteed and its use is also discouraged: SELECT todo_start('working on this'); -- lots of code SELECT todo('working on that', 2); -- Two tests for which the above line applies -- Followed by more tests scoped till the following line. SELECT todo_end(); We recommend that you pick one style or another of TODO to be on the safe side. ### `todo_end()` ### Stops running tests as TODO tests. This function is fatal if called without a preceding `todo_start()` method call. ### `in_todo()` ### Returns true if the test is currently inside a TODO block. Utility Functions ----------------- Along with the usual array of testing, planning, and diagnostic functions, pTAP provides a few extra functions to make the work of testing more pleasant. ### `pgtap_version()` ### SELECT pgtap_version(); Returns the version of pgTAP installed in the server. The value is `NUMERIC`, and thus suitable for comparing to a decimal value: SELECT CASE WHEN pgtap_version() < 0.17 THEN skip('No sequence assertions before pgTAP 0.17') ELSE has_sequence('my_big_seq') END; ### `pg_version()` ### SELECT pg_version(); Returns the server version number against which pgTAP was compiled. This is the stringified version number displayed in the first part of the core `version()` function and stored in the "server_version" setting: try=% select current_setting( 'server_version'), pg_version(); current_setting | pg_version -----------------+------------ 8.3.4 | 8.3.4 (1 row) ### `pg_version_num()` ### SELECT pg_version_num(); Returns an integer representation of the server version number against which pgTAP was compiled. This function is useful for determining whether or not certain tests should be run or skipped (using `skip()`) depending on the version of PostgreSQL. For example: SELECT CASE WHEN pg_version_num() < 80100 THEN skip('has_enum() not supported before 8.3' ) ELSE has_enum( 'bug_status', 'mydesc' ) END; The revision level is in the tens position, the minor version in the thousands position, and the major version in the ten thousands position and above (assuming PostgreSQL 10 is ever released, it will be in the hundred thousands position). This value is the same as the `server_version_num` setting available in PostgreSQL 8.2 and higher, but supported by this function back to PostgreSQL 8.1: try=% select current_setting( 'server_version_num'), pg_version_num(); current_setting | pg_version_num -----------------+---------------- 80304 | 80304 ### `os_name()` ### SELECT os_name(); Returns a string representing the name of the operating system on which pgTAP was compiled. This can be useful for determining whether or not to skip tests on certain operating systems. This is usually the same a the output of `uname`, but converted to lower case. There are some semantics in the pgTAP build process to detect other operating systems, though assistance in improving such detection would be greatly appreciated. **NOTE:** The values returned by this function may change in the future, depending on how good the pgTAP build process gets at detecting a OS. ### `collect_tap()` ### SELECT collect_tap(:lines); **Parameters** `:lines` : A list of one or more lines of TAP. Collects the results of one or more pgTAP tests and returns them all. Useful when used in combination with `skip()`: SELECT CASE os_name() WHEN 'darwin' THEN collect_tap( cmp_ok( 'BjΓΈrn'::text, '>', 'Bjorn', 'ΓΈ > o' ), cmp_ok( 'PΔ±nar'::text, '>', 'Pinar', 'Δ± > i' ), cmp_ok( 'JosΓ©'::text, '>', 'Jose', 'Γ© > e' ), cmp_ok( 'TΓ€p'::text, '>', 'Tap', 'Γ€ > a' ) ) ELSE skip('Collation-specific test', 4) END; On PostgreSQL 8.4 and higher, it can take any number of arguments. Lower than 8.4 requires the explicit use of an array: SELECT collect_tap(ARRAY[ ok(true, 'This should pass'), ok(false, 'This should fail) ]); ### `display_type()` ### SELECT display_type( :schema, :typeoid, typemod ); SELECT display_type( :typeoid, :typemod ); **Parameters** `:schema` : Schema in which to find the type. `:typeoid` : OID of the type. `:typemod` : Typemode for the type. Like `pg_catalog.format_type()`, except that the returned value is not prepended with the schema name unless it is passed as the first argument. Some examples: SELECT display_type('public', 'varchar'::regtype, NULL ); SELECT display_type('numeric'::regtype, 196612 ); Used internally by pgTAP to compare type names, but may be more generally useful. ### `display_oper()` ### SELECT display_oper( :opername, :operoid ); **Parameters** `:opername` : Operator name. `:operoid` : Operator OID. Similar to casting an operator OID to regoperator, only the schema is not included in the display. For example: SELECT display_type(oprname, oid ) FROM pg_operator; Used internally by pgTAP to compare operators, but may be more generally useful. ### `pg_typeof()` ### SELECT pg_typeof(:any); **Parameters** `:any` : Any SQL value. Returns a `regtype` identifying the type of value passed to the function. This function is used internally by `cmp_ok()` to properly construct types when executing the comparison, but might be generally useful. try=% select pg_typeof(12), pg_typeof(100.2); pg_typeof | pg_typeof -----------+----------- integer | numeric *Note:* pgTAP does not build `pg_typeof()` on PostgreSQL 8.4 or higher, because it's in core in 8.4. You only need to worry about this if you depend on the function being in particular schema. It will always be in `pg_catalog` in 8.4 and higher. ### `findfuncs()` ### SELECT findfuncs( :schema, :pattern ); SELECT findfuncs( :pattern ); **Parameters** `:schema` : Schema to search for functions. `:pattern` : Regular expression pattern against which to match function names. This function searches the named schema or, if no schema is passed, the search patch, for all functions that match the regular expression pattern. The functions it finds are returned as an array of text values, with each value consisting of the schema name, a dot, and the function name. For example: SELECT findfuncs('tests', '^test); findfuncs ----------------------------------- {tests.test_foo,tests."test bar"} (1 row) Tap that Batch -------------- Sometimes it can be useful to batch a lot of TAP tests into a function. The simplest way to do so is to define a function that `RETURNS SETOF TEXT` and then simply call `RETURN NEXT` for each TAP test. Here's a simple example: CREATE OR REPLACE FUNCTION my_tests( ) RETURNS SETOF TEXT AS $$ BEGIN RETURN NEXT pass( 'plpgsql simple' ); RETURN NEXT pass( 'plpgsql simple 2' ); END; $$ LANGUAGE plpgsql; Then you can just call the function to run all of your TAP tests at once: SELECT plan(2); SELECT * FROM my_tests(); SELECT * FROM finish(); ### `do_tap()` ### SELECT do_tap( :schema, :pattern ); SELECT do_tap( :schema ); SELECT do_tap( :pattern ); SELECT do_tap(); **Parameters** `:schema` : Name of a schema containing pgTAP test functions. `:pattern` : Regular expression pattern against which to match function names. If you like you can create a whole slew of these batched tap functions, and then use the `do_tap()` function to run them all at once. If passed no arguments, it will attempt to find all visible functions that start with "test". If passed a schema name, it will look for and run test functions only in that schema (be sure to cast the schema to `name` if it is the only argument). If passed a regular expression pattern, it will look for function names that match that pattern in the search path. If passed both, it will of course only search for test functions that match the function in the named schema. This can be very useful if you prefer to keep all of your TAP tests in functions defined in the database. Simply call `plan()`, use `do_tap()` to execute all of your tests, and then call `finish()`. A dead simple example: SELECT plan(32); SELECT * FROM do_tap('testschema'::name); SELECT * FROM finish(); As a bonus, if `client_min_messages` is set to "warning", "error", "fatal", or "panic", the name of each function will be emitted as a diagnostic message before it is called. For example, if `do_tap()` found and executed two TAP testing functions an `client_min_messages` is set to "warning", output will look something like this: # public.test_this() ok 1 - simple pass ok 2 - another simple pass # public.test_that() ok 3 - that simple ok 4 - that simple 2 Which will make it much easier to tell what functions need to be examined for failing tests. ### `runtests()` ### SELECT runtests( :schema, :pattern ); SELECT runtests( :schema ); SELECT runtests( :pattern ); SELECT runtests( ); **Parameters** `:schema` : Name of a schema containing pgTAP test functions. `:pattern` : Regular expression pattern against which to match function names. If you'd like pgTAP to plan, run all of your tests functions, and finish all in one fell swoop, use `runtests()`. This most closely emulates the xUnit testing environment, similar to the functionality of [PGUnit](http://en.dklab.ru/lib/dklab_pgunit/) and [Epic](http://www.epictest.org/). Example: SELECT * FROM runtests( 'testschema', '^test' ); As with `do_tap()`, you can pass in a schema argument and/or a pattern that the names of the tests functions can match. If you pass in only the schema argument, be sure to cast it to `name` to identify it as a schema name rather than a pattern: SELECT * FROM runtests('testschema'::name); Unlike `do_tap()`, `runtests()` fully supports startup, shutdown, setup, and teardown functions, as well as transactional rollbacks between tests. It also outputs the test plan and fishes the tests, so you don't have to call `plan()` or `finish()` yourself. The fixture functions run by `runtests()` are as follows: * `^startup` - Functions whose names start with "startup" are run in alphabetical order before any test functions are run. * `^setup` - Functions whose names start with "setup" are run in alphabetical order before each test function is run. * `^teardown` - Functions whose names start with "teardown" are run in alphabetical order after each test function is run. They will not be run, however, after a test that has died. * `^shutdown` - Functions whose names start with "shutdown" are run in alphabetical order after all test functions have been run. Note that all tests executed by `runtests()` are run within a single transaction, and each test is run in a subtransaction that also includes execution all the setup and teardown functions. All transactions are rolled back after each test function, and at the end of testing, leaving your database in largely the same condition as it was in when you started it (the one exception I'm aware of being sequences, which are not rolled back to the value used at the beginning of a rolled-back transaction). Compose Yourself ================ So, you've been using pgTAP for a while, and now you want to write your own test functions. Go ahead; I don't mind. In fact, I encourage it. How? Why, by providing a function you can use to test your tests, of course! But first, a brief primer on writing your own test functions. There isn't much to it, really. Just write your function to do whatever comparison you want. As long as you have a boolean value indicating whether or not the test passed, you're golden. Just then use `ok()` to ensure that everything is tracked appropriately by a test script. For example, say that you wanted to create a function to ensure that two text values always compare case-insensitively. Sure you could do this with `is()` and the `LOWER()` function, but if you're doing this all the time, you might want to simplify things. Here's how to go about it: CREATE OR REPLACE FUNCTION lc_is (text, text, text) RETURNS TEXT AS $$ DECLARE result BOOLEAN; BEGIN result := LOWER($1) = LOWER($2); RETURN ok( result, $3 ) || CASE WHEN result THEN '' ELSE E'\n' || diag( ' Have: ' || $1 || E'\n Want: ' || $2; ) END; END; $$ LANGUAGE plpgsql; Yep, that's it. The key is to always use pgTAP's `ok()` function to guarantee that the output is properly formatted, uses the next number in the sequence, and the results are properly recorded in the database for summarization at the end of the test script. You can also provide diagnostics as appropriate; just append them to the output of `ok()` as we've done here. Of course, you don't have to directly use `ok()`; you can also use another pgTAP function that ultimately calls `ok()`. IOW, while the above example is instructive, this version is easier on the eyes: CREATE OR REPLACE FUNCTION lc_is ( TEXT, TEXT, TEXT ) RETURNS TEXT AS $$ SELECT is( LOWER($1), LOWER($2), $3); $$ LANGUAGE sql; But either way, let pgTAP handle recording the test results and formatting the output. Testing Test Functions ---------------------- Now you've written your test function. So how do you test it? Why, with this handy-dandy test function! ### `check_test()` ### SELECT check_test( :test_output, :is_ok, :name, :want_description, :want_diag, :match_diag ); SELECT check_test( :test_output, :is_ok, :name, :want_description, :want_diag ); SELECT check_test( :test_output, :is_ok, :name, :want_description ); SELECT check_test( :test_output, :is_ok, :name ); SELECT check_test( :test_output, :is_ok ); **Parameters** `:schema` : Name of a schema containing pgTAP test functions. `:test_output` : The output from your test. Usually it's just returned by a call to the test function itself. Required. `:is_ok` : Boolean indicating whether or not the test is expected to pass. Required. `:name` : A brief name for your test, to make it easier to find failures in your test script. Optional. `:want_description` : Expected test description to be output by the test. Optional. Use an empty string to test that no description is output. `:want_diag` : Expected diagnostic message output during the execution of a test. Must always follow whatever is output by the call to `ok()`. Optional. Use an empty string to test that no description is output. `:match_diag` : Use `matches()` to compare the diagnostics rather than `:is()`. Useful for those situations where you're not sure what will be in the output, but you can match it with a regular expression. This function runs anywhere between one and three tests against a test function. At its simplest, you just pass in the output of your test function (and it must be one and **only one** test function's output, or you'll screw up the count, so don't do that!) and a boolean value indicating whether or not you expect the test to have passed. That looks something like this: SELECT * FROM check_test( lc_eq('This', 'THIS', 'eq'), true ); All other arguments are optional, but I recommend that you *always* include a short test name to make it easier to track down failures in your test script. `check_test()` uses this name to construct descriptions of all of the tests it runs. For example, without a short name, the above example will yield output like so: not ok 14 - Test should pass Yeah, but which test? So give it a very succinct name and you'll know what test. If you have a lot of these, it won't be much help. So give each call to `check_test()` a name: SELECT * FROM check_test( lc_eq('This', 'THIS', 'eq'), true, 'Simple lc_eq test', ); Then you'll get output more like this: not ok 14 - Simple lc_test should pass Which will make it much easier to find the failing test in your test script. The optional fourth argument is the description you expect to be output. This is especially important if your test function generates a description when none is passed to it. You want to make sure that your function generates the test description you think it should! This will cause a second test to be run on your test function. So for something like this: SELECT * FROM check_test( lc_eq( ''this'', ''THIS'' ), true, 'lc_eq() test', 'this is THIS' ); The output then would look something like this, assuming that the `lc_eq()` function generated the proper description (the above example does not): ok 42 - lc_eq() test should pass ok 43 - lc_eq() test should have the proper description See how there are two tests run for a single call to `check_test()`? Be sure to adjust your plan accordingly. Also note how the test name was used in the descriptions for both tests. If the test had failed, it would output a nice diagnostics. Internally it just uses `is()` to compare the strings: # Failed test 43: "lc_eq() test should have the proper description" # have: 'this is this' # want: 'this is THIS' The fifth argument, `:want_diag`, which is also optional, compares the diagnostics generated during the test to an expected string. Such diagnostics **must** follow whatever is output by the call to `ok()` in your test. Your test function should not call `diag()` until after it calls `ok()` or things will get truly funky. Assuming you've followed that rule in your `lc_eq()` test function, see what happens when a `lc_eq()` fails. Write your test to test the diagnostics like so: SELECT * FROM check_test( lc_eq( ''this'', ''THat'' ), false, 'lc_eq() failing test', 'this is THat', E' Want: this\n Have: THat ); This of course triggers a third test to run. The output will look like so: ok 44 - lc_eq() failing test should fail ok 45 - lc_eq() failing test should have the proper description ok 46 - lc_eq() failing test should have the proper diagnostics And of course, it the diagnostic test fails, it will output diagnostics just like a description failure would, something like this: # Failed test 46: "lc_eq() failing test should have the proper diagnostics" # have: Have: this # Want: that # want: Have: this # Want: THat If you pass in the optional sixth argument, `:match_diag`, the `:want_diag` argument will be compared to the actual diagnostic output using `matches()` instead of `is()`. This allows you to use a regular expression in the `:want_diag` argument to match the output, for those situations where some part of the output might vary, such as time-based diagnostics. I realize that all of this can be a bit confusing, given the various haves and wants, but it gets the job done. Of course, if your diagnostics use something other than indented "have" and "want", such failures will be easier to read. But either way, *do* test your diagnostics! Compatibility ============= Here are some notes on how pgTAP is built for particular versions of PostgreSQL. This helps you to understand any side-effects. If you'd rather not have these changes in your schema, build `pgTAP` with a schema just for it, instead: make TAPSCHEMA=tap To see the specifics for each version of PostgreSQL, consult the files in the `compat/` directory in the pgTAP distribution. 8.4 and Up ---------- No changes. Everything should just work. 8.3 and Down ------------ * A patch is applied to modify `results_eq()` and `row_eq()` to cast records to text before comparing them. This means that things will mainly be correct, but it also means that two queries with incompatible types that convert to the same text string may be considered incorrectly equivalent. * A C function, `pg_typeof()`, is built and installed in a DSO. This is for compatibility with the same function that ships in 8.4 core, and is required for `cmp_ok()` and `isa_ok()` to work. * The variadic forms of `diag()` and `collect_tap()` are not available. You can pass an array of TAP to `collect_tap()`, however. 8.2 and Down ------------ * A patch is applied that removes the `enum_has_labels()`, the `diag(anyelement)` function and `col_has_default()` cannot be used to test for columns specified with `DEFAULT NULL` (even though that's the implied default default). The `has_enums()` function won't work. Also, a number of assignments casts are added to increase compatibility. The casts are: + `boolean` to `text` + `text[]` to `text` + `name[]` to `text` + `regtype` to `text` * Two operators, `=` and `<>`, are added to compare `name[]` values. To Do ===== * Add parameter names matching the docs so parameters can be passed by name on 9.0 and higher. * Add `isnt_empty()` to complement `is_empty()`. * Add variants of `set_eq()`, `bag_eq()`, and `results_eq()` that take an array of records as the second argument. * Add `schema, table, colname` variations of the table-checking functions (`table_has_column()`, `col_type_is()`, etc.). That is, allow the description to be optional if the schema is included in the function call. * Add functions to test for object ownership. + `table_owner_is()` + `view_owner_is()` + `sequence_owner_is()` + `function_owner_is()` + etc. * Add some sort of tests for permisions. Something like: `table_privs_are(:table, :user, :privs[])`, and would have variations for database, sequence, function, language, schema, and tablespace. * Have `has_function()` manage OUT, INOUT, and VARIADIC arguments. * Useful schema testing functions to consider adding: + `sequence_has_range()` + `sequence_increments_by()` + `sequence_starts_at()` + `sequence_cycles()` * Useful result testing function to consider adding (but might require C code): `rowtype_is()` * Split test functions into separate files (and maybe distributions?): + One with scalar comparison functions: `ok()`, `is()`, `like()`, etc. + One with relation comparison functions: `set_eq()`, `results_eq()`, etc. + One with schema testing functions: `has_table()`, `tables_are()`, etc. * Add useful negation function tests: + `isnt_definer()` + `isnt_strict()` + `isnt_aggregate()` * Modify function testing assertions so that functions can be specified with full signatures, so that a polymorphic functions can be independently tested for language, volatility, etc. Metadata ======== Public Repository ----------------- The source code for pgTAP is available on [GitHub](http://github.com/theory/pgtap/tree/). Please feel free to fork and contribute! Mail List --------- Join the pgTAP community by subscribing to the [pgtap-users mail list](http://pgfoundry.org/mailman/listinfo/pgtap-users). All questions, comments, suggestions, and bug reports are welcomed there. Author ------ [David E. Wheeler](http://justatheory.com/) Credits ------- * Michael Schwern and chromatic for Test::More. * Adrian Howard for Test::Exception. Copyright and License --------------------- Copyright (c) 2008-2011 David E. Wheeler. Some rights reserved. 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 DAVID E. WHEELER 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 DAVID E. WHEELER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DAVID E. WHEELER 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 DAVID E. WHEELER HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. pgtap-0.90.0/contrib/._pgtap.spec000644 000765 000024 00000000252 11666501762 017022 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/contrib/pgtap.spec000644 000765 000024 00000003745 11666501762 016617 0ustar00davidstaff000000 000000 Summary: Unit testing suite for PostgreSQL Name: pgtap Version: 0.90.0 Release: 2%{?dist} Group: Applications/Databases License: BSD URL: http://pgtap.projects.postgresql.org Source0: http://master.pgxn.org/dist/pgtap/%{version}/pgtap-%{version}.zip BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root %description pgTAP is a unit testing framework for PostgreSQL written in PL/pgSQL and PL/SQL. It includes a comprehensive collection of TAP-emitting assertion functions, as well as the ability to integrate with other TAP-emitting test frameworks. It can also be used in the xUnit testing style. %define postgresver %(pg_config --version|awk '{print $2}'| cut -d. -f1,2) Requires: postgresql-server = %{postgresver}, perl-Test-Harness >= 3.0 BuildRequires: postgresql-devel = %{postgresver} %if "%{postgresver}" != "8.4" BuildArch: noarch %endif %prep %setup -q %build make %install %{__rm} -rf %{buildroot} make install USE_PGXS=1 DESTDIR=%{buildroot} %clean %{__rm} -rf %{buildroot} %files %defattr(-,root,root,-) %if "%{postgresver}" == "8.3" %{_libdir}/pgsql/pgtap.so %endif %{_datadir}/pgsql/contrib/* %{_docdir}/pgsql/contrib/README.pgtap %changelog * Tue Aug 23 2011 David Wheeler 0.90.0 - Removed USE_PGXS from Makefile; it has not been supported in some time. - Removed TAPSCHEMA from Makefile; use PGOPTIONS=--search_path=tap with psql instead. * Tue Feb 01 2011 David Wheeler 0.25.0 - Removed pg_prove and pg_tapgen, which are now distributed via CPAN. * Sun Mar 01 2010 Darrell Fuhriman 0.24-2 - Make install work where the pgtap.so library is needed. * Sun Dec 27 2009 David Wheeler 0.24-1 - Updated Source URL to a more predictable format. * Mon Aug 24 2009 David Fetter 0.23-1 - Got corrected .spec from Devrim GUNDUZ - Bumped version to 0.23. * Wed Aug 19 2009 Darrell Fuhriman 0.22-1 - initial RPM pgtap-0.90.0/compat/._gencore000644 000765 000024 00000000252 11666501762 016223 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/compat/gencore000644 000765 000024 00000011460 11666501762 016011 0ustar00davidstaff000000 000000 #!/usr/bin/perl -w use strict; use warnings; my $invert = shift; my %keep = map { chomp; $_ => 1 } ; my ($name, $type) = $invert ? ('Schema', 'schema-testing') : ('Core', 'assertion'); print qq{ -- This file defines pgTAP $name, a portable collection of $type -- functions for TAP-based unit testing on PostgreSQL 8.3 or higher. It is -- distributed under the revised FreeBSD license. The home page for the pgTAP -- project is: -- -- http://pgtap.org/ -- }; print "-- Requires pgtap-core.sql\n--\n" if $invert; my $print = 0; while (<>) { if (/^CREATE OR REPLACE \w+ (\w+)/) { if ($1 eq 'os_name' || $1 eq 'pg_typeof') { # Never keep this one. $print = 0; } elsif ($invert ? !$keep{$1} : $keep{$1}) { $print = 1; print; } else { $print = 0; } } else { print if $print; } } __DATA__ pg_version pg_version_num pgtap_version plan no_plan _get _get_latest _get_latest _get_note _get_note _set _set _set _add _add add_result num_failed _finish finish diag diag diag diag ok ok is is isnt isnt _alike matches matches imatches imatches alike alike ialike ialike _unalike doesnt_match doesnt_match doesnt_imatch doesnt_imatch unalike unalike unialike unialike cmp_ok cmp_ok cmp_ok cmp_ok pass pass fail fail todo todo todo todo todo_start todo_start in_todo todo_end _todo skip skip skip skip _query throws_ok throws_ok throws_ok throws_ok throws_ok throws_ok throws_ok lives_ok lives_ok performs_ok _ident_array_to_string tap_funky _got_func _got_func _got_func _got_func has_function has_function has_function has_function has_function has_function has_function has_function hasnt_function hasnt_function hasnt_function hasnt_function hasnt_function hasnt_function hasnt_function hasnt_function _pg_sv_type_array can can can can _has_type _has_type has_type has_type has_type has_type hasnt_type hasnt_type hasnt_type hasnt_type has_domain has_domain has_domain has_domain hasnt_domain hasnt_domain hasnt_domain hasnt_domain has_enum has_enum has_enum has_enum hasnt_enum hasnt_enum hasnt_enum hasnt_enum enum_has_labels enum_has_labels enum_has_labels enum_has_labels display_type display_type _cmp_types _cast_exists _cast_exists _cast_exists has_cast has_cast has_cast has_cast has_cast has_cast hasnt_cast hasnt_cast hasnt_cast hasnt_cast hasnt_cast hasnt_cast _expand_context _get_context cast_context_is cast_context_is _op_exists _op_exists _op_exists has_operator has_operator has_operator has_operator has_operator has_operator has_leftop has_leftop has_leftop has_leftop has_leftop has_leftop has_rightop has_rightop has_rightop has_rightop has_rightop has_rightop _is_trusted has_language has_language hasnt_language hasnt_language language_is_trusted language_is_trusted _opc_exists has_opclass has_opclass has_opclass has_opclass hasnt_opclass hasnt_opclass hasnt_opclass hasnt_opclass _nosuch _func_compare _func_compare _func_compare _func_compare _lang _lang _lang _lang function_lang_is function_lang_is function_lang_is function_lang_is function_lang_is function_lang_is function_lang_is function_lang_is _returns _returns _returns _returns function_returns function_returns function_returns function_returns function_returns function_returns function_returns function_returns _definer _definer _definer _definer is_definer is_definer is_definer is_definer is_definer is_definer is_definer is_definer _agg _agg _agg _agg is_aggregate is_aggregate is_aggregate is_aggregate is_aggregate is_aggregate is_aggregate is_aggregate _strict _strict _strict _strict is_strict is_strict is_strict is_strict is_strict is_strict is_strict is_strict _expand_vol _refine_vol _vol _vol _vol _vol volatility_is volatility_is volatility_is volatility_is volatility_is volatility_is volatility_is volatility_is findfuncs findfuncs _runem _is_verbose do_tap do_tap do_tap do_tap _currtest _cleanup _runner runtests runtests runtests runtests _temptable _temptable _temptypes _docomp _relcomp _relcomp set_eq set_eq set_eq set_eq bag_eq bag_eq bag_eq bag_eq _do_ne _relne _relne set_ne set_ne set_ne set_ne bag_ne bag_ne bag_ne bag_ne _relcomp set_has set_has bag_has bag_has set_hasnt set_hasnt bag_hasnt bag_hasnt results_eq results_eq results_eq results_eq results_eq results_eq results_eq results_eq results_eq results_eq results_eq results_eq results_ne results_ne results_ne results_ne results_ne results_ne results_ne results_ne results_ne results_ne results_ne results_ne isa_ok isa_ok is_empty is_empty collect_tap _tlike throws_like throws_like throws_ilike throws_ilike throws_matching throws_matching throws_imatching throws_imatching _dexists _dexists _get_dtype _get_dtype domain_type_is domain_type_is domain_type_is domain_type_is domain_type_is domain_type_is domain_type_isnt domain_type_isnt domain_type_isnt domain_type_isnt domain_type_isnt domain_type_isnt row_eq row_eq pgtap-0.90.0/compat/._install-8.1.patch000644 000765 000024 00000000252 11666501762 017651 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/compat/install-8.1.patch000644 000765 000024 00000011243 11666501762 017436 0ustar00davidstaff000000 000000 --- sql/pgtap.sql.saf 2011-11-10 15:49:06.000000000 -0800 +++ sql/pgtap.sql 2011-11-10 15:49:12.000000000 -0800 @@ -1993,13 +1993,13 @@ CREATE OR REPLACE FUNCTION _constraint ( NAME, NAME, CHAR, NAME[], TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE - akey NAME[]; + rec record; keys TEXT[] := '{}'; have TEXT; BEGIN - FOR akey IN SELECT * FROM _keys($1, $2, $3) LOOP - IF akey = $4 THEN RETURN pass($5); END IF; - keys = keys || akey::text; + FOR rec IN SELECT * FROM _keys($1, $2, $3) AS b(a) LOOP + IF rec.a = $4 THEN RETURN pass($5); END IF; + keys = keys || rec.a::text; END LOOP; IF array_upper(keys, 0) = 1 THEN have := 'No ' || $6 || ' constriants'; @@ -2017,13 +2017,13 @@ CREATE OR REPLACE FUNCTION _constraint ( NAME, CHAR, NAME[], TEXT, TEXT ) RETURNS TEXT AS $$ DECLARE - akey NAME[]; + rec record; keys TEXT[] := '{}'; have TEXT; BEGIN - FOR akey IN SELECT * FROM _keys($1, $2) LOOP - IF akey = $3 THEN RETURN pass($4); END IF; - keys = keys || akey::text; + FOR rec IN SELECT * FROM _keys($1, $2) AS b(a) LOOP + IF rec.a = $3 THEN RETURN pass($4); END IF; + keys = keys || rec.a::text; END LOOP; IF array_upper(keys, 0) = 1 THEN have := 'No ' || $5 || ' constriants'; @@ -5677,7 +5677,7 @@ CREATE OR REPLACE FUNCTION _runem( text[], boolean ) RETURNS SETOF TEXT AS $$ DECLARE - tap text; + rec record; lbound int := array_lower($1, 1); BEGIN IF lbound IS NULL THEN RETURN; END IF; @@ -5685,8 +5685,8 @@ -- Send the name of the function to diag if warranted. IF $2 THEN RETURN NEXT diag( $1[i] || '()' ); END IF; -- Execute the tap function and return its results. - FOR tap IN EXECUTE 'SELECT * FROM ' || $1[i] || '()' LOOP - RETURN NEXT tap; + FOR rec IN EXECUTE 'SELECT * FROM ' || $1[i] || '() AS b(a)' LOOP + RETURN NEXT rec.a; END LOOP; END LOOP; RETURN; @@ -5756,14 +5756,14 @@ setup ALIAS FOR $3; teardown ALIAS FOR $4; tests ALIAS FOR $5; - tap text; + rec record; verbos boolean := _is_verbose(); -- verbose is a reserved word in 8.5. num_faild INTEGER := 0; BEGIN BEGIN -- No plan support. PERFORM * FROM no_plan(); - FOR tap IN SELECT * FROM _runem(startup, false) LOOP RETURN NEXT tap; END LOOP; + FOR rec IN SELECT * FROM _runem(startup, false) AS b(a) LOOP RETURN NEXT rec.a; END LOOP; EXCEPTION -- Catch all exceptions and simply rethrow custom exceptions. This -- will roll back everything in the above block. @@ -5778,15 +5778,15 @@ IF verbos THEN RETURN NEXT diag_test_name(tests[i]); END IF; -- Run the setup functions. - FOR tap IN SELECT * FROM _runem(setup, false) LOOP RETURN NEXT tap; END LOOP; + FOR rec IN SELECT * FROM _runem(setup, false) AS b(a) LOOP RETURN NEXT rec.a; END LOOP; -- Run the actual test function. - FOR tap IN EXECUTE 'SELECT * FROM ' || tests[i] || '()' LOOP - RETURN NEXT tap; + FOR rec IN EXECUTE 'SELECT * FROM ' || tests[i] || '() AS b(a)' LOOP + RETURN NEXT rec.a; END LOOP; -- Run the teardown functions. - FOR tap IN SELECT * FROM _runem(teardown, false) LOOP RETURN NEXT tap; END LOOP; + FOR rec IN SELECT * FROM _runem(teardown, false) AS b(a) LOOP RETURN NEXT rec.a; END LOOP; -- Remember how many failed and then roll back. num_faild := num_faild + num_failed(); @@ -5801,7 +5801,7 @@ END LOOP; -- Run the shutdown functions. - FOR tap IN SELECT * FROM _runem(shutdown, false) LOOP RETURN NEXT tap; END LOOP; + FOR rec IN SELECT * FROM _runem(shutdown, false) AS b(a) LOOP RETURN NEXT rec.a; END LOOP; -- Raise an exception to rollback any changes. RAISE EXCEPTION '__TAP_ROLLBACK__'; @@ -5812,8 +5812,8 @@ END IF; END; -- Finish up. - FOR tap IN SELECT * FROM _finish( currval('__tresults___numb_seq')::integer, 0, num_faild ) LOOP - RETURN NEXT tap; + FOR rec IN SELECT * FROM _finish( currval('__tresults___numb_seq')::integer, 0, num_faild ) AS b(a) LOOP + RETURN NEXT rec.a; END LOOP; -- Clean up and return. @@ -7042,7 +7042,7 @@ DECLARE rec RECORD; BEGIN - EXECUTE _query($1) INTO rec; + FOR rec in EXECUTE _query($1) LOOP END LOOP; IF NOT textin(record_out(rec)) IS DISTINCT FROM textin(record_out($2)) THEN RETURN ok(true, $3); END IF; pgtap-0.90.0/compat/._install-8.2.patch000644 000765 000024 00000000252 11666501762 017652 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/compat/install-8.2.patch000644 000765 000024 00000037334 11666501762 017450 0ustar00davidstaff000000 000000 --- sql/pgtap.sql.saf 2011-11-10 15:40:08.000000000 -0800 +++ sql/pgtap.sql 2011-11-10 15:40:43.000000000 -0800 @@ -8,6 +8,59 @@ -- -- http://pgtap.org/ +-- Cast booleans to text like 8.3 does. +CREATE OR REPLACE FUNCTION booltext(boolean) +RETURNS text AS 'SELECT CASE WHEN $1 then ''true'' ELSE ''false'' END;' +LANGUAGE sql IMMUTABLE STRICT; + +CREATE CAST (boolean AS text) WITH FUNCTION booltext(boolean) AS ASSIGNMENT; + +-- Cast text[]s to text like 8.3 does. +CREATE OR REPLACE FUNCTION textarray_text(text[]) +RETURNS TEXT AS 'SELECT textin(array_out($1));' +LANGUAGE sql IMMUTABLE STRICT; + +CREATE CAST (text[] AS text) WITH FUNCTION textarray_text(text[]) AS ASSIGNMENT; + +-- Cast name[]s to text like 8.3 does. +CREATE OR REPLACE FUNCTION namearray_text(name[]) +RETURNS TEXT AS 'SELECT textin(array_out($1));' +LANGUAGE sql IMMUTABLE STRICT; + +CREATE CAST (name[] AS text) WITH FUNCTION namearray_text(name[]) AS ASSIGNMENT; + +-- Compare name[]s more or less like 8.3 does. +CREATE OR REPLACE FUNCTION namearray_eq( name[], name[] ) +RETURNS bool +AS 'SELECT $1::text = $2::text;' +LANGUAGE sql IMMUTABLE STRICT; + +CREATE OPERATOR = ( + LEFTARG = name[], + RIGHTARG = name[], + NEGATOR = <>, + PROCEDURE = namearray_eq +); + +CREATE OR REPLACE FUNCTION namearray_ne( name[], name[] ) +RETURNS bool +AS 'SELECT $1::text <> $2::text;' +LANGUAGE sql IMMUTABLE STRICT; + +CREATE OPERATOR <> ( + LEFTARG = name[], + RIGHTARG = name[], + NEGATOR = =, + PROCEDURE = namearray_ne +); + +-- Cast regtypes to text like 8.3 does. +CREATE OR REPLACE FUNCTION regtypetext(regtype) +RETURNS text AS 'SELECT textin(regtypeout($1))' +LANGUAGE sql IMMUTABLE STRICT; + +CREATE CAST (regtype AS text) WITH FUNCTION regtypetext(regtype) AS ASSIGNMENT; + CREATE OR REPLACE FUNCTION pg_version() RETURNS text AS 'SELECT current_setting(''server_version'')' LANGUAGE SQL IMMUTABLE; @@ -191,11 +244,11 @@ RETURNS integer AS $$ BEGIN EXECUTE 'INSERT INTO __tresults__ ( ok, aok, descr, type, reason ) - VALUES( ' || $1 || ', ' - || $2 || ', ' - || quote_literal(COALESCE($3, '')) || ', ' - || quote_literal($4) || ', ' - || quote_literal($5) || ' )'; + VALUES( ' || $1::text || ', ' + || $2::text || ', ' + || quote_literal(COALESCE($3, '')::text) || ', ' + || quote_literal($4::text) || ', ' + || quote_literal($5::text) || ' )'; RETURN currval('__tresults___numb_seq'); END; $$ LANGUAGE plpgsql; @@ -270,21 +323,6 @@ ); $$ LANGUAGE sql strict; -CREATE OR REPLACE FUNCTION diag ( msg anyelement ) -RETURNS TEXT AS $$ - SELECT diag($1::text); -$$ LANGUAGE sql; - -CREATE OR REPLACE FUNCTION diag( VARIADIC text[] ) -RETURNS TEXT AS $$ - SELECT diag(array_to_string($1, '')); -$$ LANGUAGE sql; - -CREATE OR REPLACE FUNCTION diag( VARIADIC anyarray ) -RETURNS TEXT AS $$ - SELECT diag(array_to_string($1, '')); -$$ LANGUAGE sql; - CREATE OR REPLACE FUNCTION ok ( boolean, text ) RETURNS TEXT AS $$ DECLARE @@ -497,9 +535,9 @@ output TEXT; BEGIN EXECUTE 'SELECT ' || - COALESCE(quote_literal( have ), 'NULL') || '::' || pg_typeof(have) || ' ' + COALESCE(quote_literal( have ), 'NULL') || '::' || pg_typeof(have)::text || ' ' || op || ' ' || - COALESCE(quote_literal( want ), 'NULL') || '::' || pg_typeof(want) + COALESCE(quote_literal( want ), 'NULL') || '::' || pg_typeof(want)::text INTO result; output := ok( COALESCE(result, FALSE), descr ); RETURN output || CASE result WHEN TRUE THEN '' ELSE E'\n' || diag( @@ -1103,7 +1141,7 @@ SELECT COALESCE(substring( pg_catalog.format_type($1, $2), '(("(?!")([^"]|"")+"|[^.]+)([(][^)]+[)])?)$' - ), '') + ) || CASE WHEN $2 IS NULL OR $2 < 0 OR pg_catalog.format_type($1, $2) LIKE '%)' THEN '' ELSE '(' || $2 || ')' END, '') $$ LANGUAGE SQL; CREATE OR REPLACE FUNCTION display_type ( NAME, OID, INTEGER ) @@ -2194,7 +2232,7 @@ p.proname AS name, array_to_string(p.proargtypes::regtype[], ',') AS args, CASE p.proretset WHEN TRUE THEN 'setof ' ELSE '' END - || p.prorettype::regtype AS returns, + || p.prorettype::regtype::text AS returns, p.prolang AS langoid, p.proisstrict AS is_strict, p.proisagg AS is_agg, @@ -3399,63 +3437,6 @@ SELECT ok( NOT _has_type( $1, ARRAY['e'] ), ('Enum ' || quote_ident($1) || ' should not exist')::text ); $$ LANGUAGE sql; --- enum_has_labels( schema, enum, labels, description ) -CREATE OR REPLACE FUNCTION enum_has_labels( NAME, NAME, NAME[], TEXT ) -RETURNS TEXT AS $$ - SELECT is( - ARRAY( - SELECT e.enumlabel - FROM pg_catalog.pg_type t - JOIN pg_catalog.pg_enum e ON t.oid = e.enumtypid - JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid - WHERE t.typisdefined - AND n.nspname = $1 - AND t.typname = $2 - AND t.typtype = 'e' - ORDER BY e.oid - ), - $3, - $4 - ); -$$ LANGUAGE sql; - --- enum_has_labels( schema, enum, labels ) -CREATE OR REPLACE FUNCTION enum_has_labels( NAME, NAME, NAME[] ) -RETURNS TEXT AS $$ - SELECT enum_has_labels( - $1, $2, $3, - 'Enum ' || quote_ident($1) || '.' || quote_ident($2) || ' should have labels (' || array_to_string( $3, ', ' ) || ')' - ); -$$ LANGUAGE sql; - --- enum_has_labels( enum, labels, description ) -CREATE OR REPLACE FUNCTION enum_has_labels( NAME, NAME[], TEXT ) -RETURNS TEXT AS $$ - SELECT is( - ARRAY( - SELECT e.enumlabel - FROM pg_catalog.pg_type t - JOIN pg_catalog.pg_enum e ON t.oid = e.enumtypid - WHERE t.typisdefined - AND pg_catalog.pg_type_is_visible(t.oid) - AND t.typname = $1 - AND t.typtype = 'e' - ORDER BY e.oid - ), - $2, - $3 - ); -$$ LANGUAGE sql; - --- enum_has_labels( enum, labels ) -CREATE OR REPLACE FUNCTION enum_has_labels( NAME, NAME[] ) -RETURNS TEXT AS $$ - SELECT enum_has_labels( - $1, $2, - 'Enum ' || quote_ident($1) || ' should have labels (' || array_to_string( $2, ', ' ) || ')' - ); -$$ LANGUAGE sql; - CREATE OR REPLACE FUNCTION _has_role( NAME ) RETURNS BOOLEAN AS $$ SELECT EXISTS( @@ -5924,13 +5905,13 @@ -- Find extra records. FOR rec in EXECUTE 'SELECT * FROM ' || have || ' EXCEPT ' || $4 || 'SELECT * FROM ' || want LOOP - extras := extras || rec::text; + extras := array_append(extras, textin(record_out(rec))); END LOOP; -- Find missing records. FOR rec in EXECUTE 'SELECT * FROM ' || want || ' EXCEPT ' || $4 || 'SELECT * FROM ' || have LOOP - missing := missing || rec::text; + missing := array_append(missing, textin(record_out(rec))); END LOOP; -- Drop the temporary tables. @@ -6154,7 +6135,7 @@ -- Find relevant records. FOR rec in EXECUTE 'SELECT * FROM ' || want || ' ' || $4 || ' SELECT * FROM ' || have LOOP - results := results || rec::text; + results := array_append(results, textin(record_out(rec))); END LOOP; -- Drop the temporary tables. @@ -6249,11 +6230,11 @@ FETCH want INTO want_rec; want_found := FOUND; WHILE have_found OR want_found LOOP - IF have_rec::text IS DISTINCT FROM want_rec::text OR have_found <> want_found THEN + IF textin(record_out(have_rec)) IS DISTINCT FROM textin(record_out(want_rec)) OR have_found <> want_found THEN RETURN ok( false, $3 ) || E'\n' || diag( ' Results differ beginning at row ' || rownum || E':\n' || - ' have: ' || CASE WHEN have_found THEN have_rec::text ELSE 'NULL' END || E'\n' || - ' want: ' || CASE WHEN want_found THEN want_rec::text ELSE 'NULL' END + ' have: ' || CASE WHEN have_found THEN textin(record_out(have_rec)) ELSE 'NULL' END || E'\n' || + ' want: ' || CASE WHEN want_found THEN textin(record_out(want_rec)) ELSE 'NULL' END ); END IF; rownum = rownum + 1; @@ -6268,8 +6249,8 @@ WHEN datatype_mismatch THEN RETURN ok( false, $3 ) || E'\n' || diag( E' Columns differ between queries:\n' || - ' have: ' || CASE WHEN have_found THEN have_rec::text ELSE 'NULL' END || E'\n' || - ' want: ' || CASE WHEN want_found THEN want_rec::text ELSE 'NULL' END + ' have: ' || CASE WHEN have_found THEN textin(record_out(have_rec)) ELSE 'NULL' END || E'\n' || + ' want: ' || CASE WHEN want_found THEN textin(record_out(want_rec)) ELSE 'NULL' END ); END; $$ LANGUAGE plpgsql; @@ -6404,7 +6385,7 @@ FETCH want INTO want_rec; want_found := FOUND; WHILE have_found OR want_found LOOP - IF have_rec::text IS DISTINCT FROM want_rec::text OR have_found <> want_found THEN + IF textin(record_out(have_rec)) IS DISTINCT FROM textin(record_out(want_rec)) OR have_found <> want_found THEN RETURN ok( true, $3 ); ELSE FETCH have INTO have_rec; @@ -6418,8 +6399,8 @@ WHEN datatype_mismatch THEN RETURN ok( false, $3 ) || E'\n' || diag( E' Columns differ between queries:\n' || - ' have: ' || CASE WHEN have_found THEN have_rec::text ELSE 'NULL' END || E'\n' || - ' want: ' || CASE WHEN want_found THEN want_rec::text ELSE 'NULL' END + ' have: ' || CASE WHEN have_found THEN textin(record_out(have_rec)) ELSE 'NULL' END || E'\n' || + ' want: ' || CASE WHEN want_found THEN textin(record_out(want_rec)) ELSE 'NULL' END ); END; $$ LANGUAGE plpgsql; @@ -6544,9 +6525,9 @@ DECLARE typeof regtype := pg_typeof($1); BEGIN - IF typeof = $2 THEN RETURN ok(true, $3 || ' isa ' || $2 ); END IF; - RETURN ok(false, $3 || ' isa ' || $2 ) || E'\n' || - diag(' ' || $3 || ' isn''t a "' || $2 || '" it''s a "' || typeof || '"'); + IF typeof = $2 THEN RETURN ok(true, $3 || ' isa ' || $2::text ); END IF; + RETURN ok(false, $3 || ' isa ' || $2::text ) || E'\n' || + diag(' ' || $3 || ' isn''t a "' || $2::text || '" it''s a "' || typeof::text || '"'); END; $$ LANGUAGE plpgsql; @@ -6567,7 +6548,7 @@ BEGIN -- Find extra records. FOR rec in EXECUTE _query($1) LOOP - extras := extras || rec::text; + extras := extras || textin(record_out(rec)); END LOOP; -- What extra records do we have? @@ -6712,7 +6693,7 @@ t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) ) - AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid) + AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem) AND n.nspname = $1 AND t.typtype = ANY( COALESCE($4, ARRAY['b', 'c', 'd', 'p', 'e']) ) EXCEPT @@ -6730,7 +6711,7 @@ t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) ) - AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid) + AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem) AND n.nspname = $1 AND t.typtype = ANY( COALESCE($4, ARRAY['b', 'c', 'd', 'p', 'e']) ) ), @@ -6763,7 +6744,7 @@ t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) ) - AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid) + AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem) AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND pg_catalog.pg_type_is_visible(t.oid) AND t.typtype = ANY( COALESCE($3, ARRAY['b', 'c', 'd', 'p', 'e']) ) @@ -6782,7 +6763,7 @@ t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) ) - AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid) + AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem) AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND pg_catalog.pg_type_is_visible(t.oid) AND t.typtype = ANY( COALESCE($3, ARRAY['b', 'c', 'd', 'p', 'e']) ) @@ -7062,10 +7043,12 @@ rec RECORD; BEGIN EXECUTE _query($1) INTO rec; - IF NOT rec::text IS DISTINCT FROM $2::text THEN RETURN ok(true, $3); END IF; + IF NOT textin(record_out(rec)) IS DISTINCT FROM textin(record_out($2)) + THEN RETURN ok(true, $3); + END IF; RETURN ok(false, $3 ) || E'\n' || diag( - ' have: ' || CASE WHEN rec IS NULL THEN 'NULL' ELSE rec::text END || - E'\n want: ' || CASE WHEN $2 IS NULL THEN 'NULL' ELSE $2::text END + ' have: ' || CASE WHEN rec IS NULL THEN 'NULL' ELSE textin(record_out(rec)) END || + E'\n want: ' || CASE WHEN $2 IS NULL THEN 'NULL' ELSE textin(record_out($2)) END ); END; $$ LANGUAGE plpgsql; @@ -7210,7 +7193,7 @@ CREATE OR REPLACE FUNCTION display_oper ( NAME, OID ) RETURNS TEXT AS $$ - SELECT $1 || substring($2::regoperator::text, '[(][^)]+[)]$') + SELECT $1 || substring(textin(regoperatorout($2::regoperator)), '[(][^)]+[)]$') $$ LANGUAGE SQL; -- operators_are( schema, operators[], description ) @@ -7219,7 +7202,7 @@ SELECT _areni( 'operators', ARRAY( - SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype + SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype::text FROM pg_catalog.pg_operator o JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid WHERE n.nspname = $1 @@ -7231,7 +7214,7 @@ SELECT $2[i] FROM generate_series(1, array_upper($2, 1)) s(i) EXCEPT - SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype + SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype::text FROM pg_catalog.pg_operator o JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid WHERE n.nspname = $1 @@ -7252,7 +7235,7 @@ SELECT _areni( 'operators', ARRAY( - SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype + SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype::text FROM pg_catalog.pg_operator o JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid WHERE pg_catalog.pg_operator_is_visible(o.oid) @@ -7265,7 +7248,7 @@ SELECT $1[i] FROM generate_series(1, array_upper($1, 1)) s(i) EXCEPT - SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype + SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype::text FROM pg_catalog.pg_operator o JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid WHERE pg_catalog.pg_operator_is_visible(o.oid) pgtap-0.90.0/compat/._install-8.3.patch000644 000765 000024 00000000252 11666501762 017653 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/compat/install-8.3.patch000644 000765 000024 00000004242 11666501762 017441 0ustar00davidstaff000000 000000 --- sql/pgtap.sql.saf 2011-11-10 14:58:17.000000000 -0800 +++ sql/pgtap.sql 2011-11-10 14:59:43.000000000 -0800 @@ -12,6 +12,11 @@ RETURNS text AS 'SELECT current_setting(''server_version'')' LANGUAGE SQL IMMUTABLE; +CREATE OR REPLACE FUNCTION pg_typeof("any") +RETURNS regtype +AS '$libdir/pgtap' +LANGUAGE C STABLE; + CREATE OR REPLACE FUNCTION pg_version_num() RETURNS integer AS $$ SELECT s.a[1]::int * 10000 @@ -6244,7 +6249,7 @@ FETCH want INTO want_rec; want_found := FOUND; WHILE have_found OR want_found LOOP - IF have_rec IS DISTINCT FROM want_rec OR have_found <> want_found THEN + IF have_rec::text IS DISTINCT FROM want_rec::text OR have_found <> want_found THEN RETURN ok( false, $3 ) || E'\n' || diag( ' Results differ beginning at row ' || rownum || E':\n' || ' have: ' || CASE WHEN have_found THEN have_rec::text ELSE 'NULL' END || E'\n' || @@ -6399,7 +6404,7 @@ FETCH want INTO want_rec; want_found := FOUND; WHILE have_found OR want_found LOOP - IF have_rec IS DISTINCT FROM want_rec OR have_found <> want_found THEN + IF have_rec::text IS DISTINCT FROM want_rec::text OR have_found <> want_found THEN RETURN ok( true, $3 ); ELSE FETCH have INTO have_rec; @@ -6585,13 +6590,7 @@ $$ LANGUAGE sql; -- collect_tap( tap, tap, tap ) -CREATE OR REPLACE FUNCTION collect_tap( VARIADIC text[] ) -RETURNS TEXT AS $$ - SELECT array_to_string($1, E'\n'); -$$ LANGUAGE sql; - --- collect_tap( tap[] ) -CREATE OR REPLACE FUNCTION collect_tap( VARCHAR[] ) +CREATE OR REPLACE FUNCTION collect_tap( text[] ) RETURNS TEXT AS $$ SELECT array_to_string($1, E'\n'); $$ LANGUAGE sql; @@ -7063,7 +7062,7 @@ rec RECORD; BEGIN EXECUTE _query($1) INTO rec; - IF NOT rec IS DISTINCT FROM $2 THEN RETURN ok(true, $3); END IF; + IF NOT rec::text IS DISTINCT FROM $2::text THEN RETURN ok(true, $3); END IF; RETURN ok(false, $3 ) || E'\n' || diag( ' have: ' || CASE WHEN rec IS NULL THEN 'NULL' ELSE rec::text END || E'\n want: ' || CASE WHEN $2 IS NULL THEN 'NULL' ELSE $2::text END pgtap-0.90.0/compat/._uninstall-8.2.patch000644 000765 000024 00000000252 11666501762 020215 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/compat/uninstall-8.2.patch000644 000765 000024 00000002751 11666501762 020006 0ustar00davidstaff000000 000000 --- sql/uninstall_pgtap.sql.saf 2011-11-10 15:40:19.000000000 -0800 +++ sql/uninstall_pgtap.sql 2011-11-10 15:40:43.000000000 -0800 @@ -370,10 +370,6 @@ DROP FUNCTION has_role( NAME ); DROP FUNCTION has_role( NAME, TEXT ); DROP FUNCTION _has_role( NAME ); -DROP FUNCTION enum_has_labels( NAME, NAME[] ); -DROP FUNCTION enum_has_labels( NAME, NAME[], TEXT ); -DROP FUNCTION enum_has_labels( NAME, NAME, NAME[] ); -DROP FUNCTION enum_has_labels( NAME, NAME, NAME[], TEXT ); DROP FUNCTION hasnt_enum( NAME ); DROP FUNCTION hasnt_enum( NAME, TEXT ); DROP FUNCTION hasnt_enum( NAME, NAME ); @@ -683,9 +679,6 @@ DROP FUNCTION is (anyelement, anyelement, text); DROP FUNCTION ok ( boolean ); DROP FUNCTION ok ( boolean, text ); -DROP FUNCTION diag( VARIADIC anyarray ); -DROP FUNCTION diag( VARIADIC text[] ); -DROP FUNCTION diag ( msg anyelement ); DROP FUNCTION diag ( msg text ); DROP FUNCTION finish (); DROP FUNCTION _finish ( INTEGER, INTEGER, INTEGER); @@ -708,3 +701,15 @@ DROP FUNCTION os_name(); DROP FUNCTION pg_version_num(); DROP FUNCTION pg_version(); +DROP CAST (regtype AS text); +DROP FUNCTION regtypetext(regtype); +DROP OPERATOR <> ( name[], name[] ); +DROP FUNCTION namearray_ne( name[], name[] ); +DROP OPERATOR = ( name[], name[] ); +DROP FUNCTION namearray_eq( name[], name[] ); +DROP CAST (name[] AS text); +DROP FUNCTION namearray_text(name[]); +DROP CAST (text[] AS text); +DROP FUNCTION textarray_text(text[]); +DROP CAST (boolean AS char(1)); +DROP FUNCTION booltext(boolean); pgtap-0.90.0/compat/._uninstall-8.3.patch000644 000765 000024 00000000252 11666501762 020216 0ustar00davidstaff000000 000000 Mac OS X  2xͺATTRͺ˜˜com.apple.quarantineq/0001;00000000;;pgtap-0.90.0/compat/uninstall-8.3.patch000644 000765 000024 00000001403 11666501762 020000 0ustar00davidstaff000000 000000 --- sql/uninstall_pgtap.sql.saf 2011-11-10 15:00:44.000000000 -0800 +++ sql/uninstall_pgtap.sql 2011-11-10 15:00:53.000000000 -0800 @@ -60,8 +60,7 @@ DROP FUNCTION throws_like ( TEXT, TEXT ); DROP FUNCTION throws_like ( TEXT, TEXT, TEXT ); DROP FUNCTION _tlike ( BOOLEAN, TEXT, TEXT, TEXT ); -DROP FUNCTION collect_tap( VARCHAR[] ); -DROP FUNCTION collect_tap( VARIADIC text[] ); +DROP FUNCTION collect_tap( text[] ); DROP FUNCTION is_empty( TEXT ); DROP FUNCTION is_empty( TEXT, TEXT ); DROP FUNCTION isa_ok( anyelement, regtype ); @@ -704,6 +703,7 @@ DROP FUNCTION _get ( text ); DROP FUNCTION no_plan(); DROP FUNCTION plan( integer ); +DROP FUNCTION pg_typeof("any"); DROP FUNCTION pgtap_version(); DROP FUNCTION os_name(); DROP FUNCTION pg_version_num();