--- sql/pgtap.sql +++ sql/pgtap.sql @@ -9,6 +9,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 current_setting('server_version_num')::integer; @@ -2483,7 +2488,7 @@ JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid ; -CREATE OR REPLACE FUNCTION _funkargs ( NAME[] ) +CREATE OR REPLACE FUNCTION _funkargs ( TEXT[] ) RETURNS TEXT AS $$ BEGIN RETURN array_to_string($1::regtype[], ','); @@ -6819,7 +6824,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' || @@ -6976,7 +6981,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; @@ -7185,13 +7190,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; @@ -7667,7 +7666,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 @@ -9856,358 +9855,3 @@ 'Table ' || quote_ident( $1 ) || ' should not have descendents' ); $$ LANGUAGE SQL; - -/* -* Internal function to test whether the schema-qualified table is an ancestor of -* the other schema-qualified table. The integer value is the length of the -* inheritance chain: a direct ancestor has has a chain length of 1. -*/ -CREATE OR REPLACE FUNCTION _ancestor_of( NAME, NAME, NAME, NAME, INT ) -RETURNS BOOLEAN AS $$ - WITH RECURSIVE inheritance_chain AS ( - -- select the ancestor tuple - SELECT i.inhrelid AS descendent_id, 1 AS inheritance_level - FROM pg_catalog.pg_inherits i - WHERE i.inhparent = ( - SELECT c1.oid - FROM pg_catalog.pg_class c1 - JOIN pg_catalog.pg_namespace n1 - ON c1.relnamespace = n1.oid - WHERE c1.relname = $2 - AND n1.nspname = $1 - ) - UNION - -- select the descendents - SELECT i.inhrelid AS descendent_id, - p.inheritance_level + 1 AS inheritance_level - FROM pg_catalog.pg_inherits i - JOIN inheritance_chain p - ON p.descendent_id = i.inhparent - WHERE i.inhrelid = ( - SELECT c1.oid - FROM pg_catalog.pg_class c1 - JOIN pg_catalog.pg_namespace n1 - ON c1.relnamespace = n1.oid - WHERE c1.relname = $4 - AND n1.nspname = $3 - ) - ) - SELECT EXISTS( - SELECT true - FROM inheritance_chain - WHERE inheritance_level = COALESCE($5, inheritance_level) - AND descendent_id = ( - SELECT c1.oid - FROM pg_catalog.pg_class c1 - JOIN pg_catalog.pg_namespace n1 - ON c1.relnamespace = n1.oid - WHERE c1.relname = $4 - AND n1.nspname = $3 - ) - ); -$$ LANGUAGE SQL; - -/* - * Internal function to check if not-qualified tables - * within the search_path are connected by an inheritance chain. - */ -CREATE OR REPLACE FUNCTION _ancestor_of( NAME, NAME, INT ) -RETURNS BOOLEAN AS $$ - WITH RECURSIVE inheritance_chain AS ( - -- select the ancestor tuple - SELECT i.inhrelid AS descendent_id, 1 AS inheritance_level - FROM pg_catalog.pg_inherits i - WHERE i.inhparent = ( - SELECT c1.oid - FROM pg_catalog.pg_class c1 - JOIN pg_catalog.pg_namespace n1 - ON c1.relnamespace = n1.oid - WHERE c1.relname = $1 - AND pg_catalog.pg_table_is_visible( c1.oid ) - ) - UNION - -- select the descendents - SELECT i.inhrelid AS descendent_id, - p.inheritance_level + 1 AS inheritance_level - FROM pg_catalog.pg_inherits i - JOIN inheritance_chain p - ON p.descendent_id = i.inhparent - WHERE i.inhrelid = ( - SELECT c1.oid - FROM pg_catalog.pg_class c1 - JOIN pg_catalog.pg_namespace n1 - ON c1.relnamespace = n1.oid - WHERE c1.relname = $2 - AND pg_catalog.pg_table_is_visible( c1.oid ) - ) - ) - SELECT EXISTS( - SELECT true - FROM inheritance_chain - WHERE inheritance_level = COALESCE($3, inheritance_level) - AND descendent_id = ( - SELECT c1.oid - FROM pg_catalog.pg_class c1 - JOIN pg_catalog.pg_namespace n1 - ON c1.relnamespace = n1.oid - WHERE c1.relname = $2 - AND pg_catalog.pg_table_is_visible( c1.oid ) - ) - ); -$$ LANGUAGE SQL; - --- is_ancestor_of( schema, table, schema, table, depth, description ) -CREATE OR REPLACE FUNCTION is_ancestor_of( NAME, NAME, NAME, NAME, INT, TEXT ) -RETURNS TEXT AS $$ - SELECT ok( _ancestor_of( $1, $2, $3, $4, $5 ), $6 ); -$$ LANGUAGE SQL; - --- is_ancestor_of( schema, table, schema, table, depth ) -CREATE OR REPLACE FUNCTION is_ancestor_of( NAME, NAME, NAME, NAME, INT ) -RETURNS TEXT AS $$ - SELECT ok( - _ancestor_of( $1, $2, $3, $4, $5 ), - 'Table ' || quote_ident( $1 ) || '.' || quote_ident( $2 ) - || ' should be ancestor ' || $5 || ' for ' - || quote_ident( $3 ) || '.' || quote_ident( $4 ) - ); -$$ LANGUAGE SQL; - --- is_ancestor_of( schema, table, schema, table, description ) -CREATE OR REPLACE FUNCTION is_ancestor_of( NAME, NAME, NAME, NAME, TEXT ) -RETURNS TEXT AS $$ - SELECT ok( _ancestor_of( $1, $2, $3, $4, NULL ), $5 ); -$$ LANGUAGE SQL; - --- is_ancestor_of( schema, table, schema, table ) -CREATE OR REPLACE FUNCTION is_ancestor_of( NAME, NAME, NAME, NAME ) -RETURNS TEXT AS $$ - SELECT ok( - _ancestor_of( $1, $2, $3, $4, NULL ), - 'Table ' || quote_ident( $1 ) || '.' || quote_ident( $2 ) - || ' should be an ancestor of ' - || quote_ident( $3 ) || '.' || quote_ident( $4 ) - ); -$$ LANGUAGE SQL; - --- is_ancestor_of( table, table, depth, description ) -CREATE OR REPLACE FUNCTION is_ancestor_of( NAME, NAME, INT, TEXT ) -RETURNS TEXT AS $$ - SELECT ok( _ancestor_of( $1, $2, $3 ), $4 ); -$$ LANGUAGE SQL; - --- is_ancestor_of( table, table, depth ) -CREATE OR REPLACE FUNCTION is_ancestor_of( NAME, NAME, INT ) -RETURNS TEXT AS $$ - SELECT ok( - _ancestor_of( $1, $2, $3 ), - 'Table ' || quote_ident( $1 ) || ' should be ancestor ' || $3 || ' of ' || quote_ident( $2) - ); -$$ LANGUAGE SQL; - --- is_ancestor_of( table, table, description ) -CREATE OR REPLACE FUNCTION is_ancestor_of( NAME, NAME, TEXT ) -RETURNS TEXT AS $$ - SELECT ok( _ancestor_of( $1, $2, NULL ), $3 ); -$$ LANGUAGE SQL; - --- is_ancestor_of( table, table ) -CREATE OR REPLACE FUNCTION is_ancestor_of( NAME, NAME ) -RETURNS TEXT AS $$ - SELECT ok( - _ancestor_of( $1, $2, NULL ), - 'Table ' || quote_ident( $1 ) || ' should be an ancestor of ' || quote_ident( $2) - ); -$$ LANGUAGE SQL; - --- isnt_ancestor_of( schema, table, schema, table, depth, description ) -CREATE OR REPLACE FUNCTION isnt_ancestor_of( NAME, NAME, NAME, NAME, INT, TEXT ) -RETURNS TEXT AS $$ - SELECT ok( NOT _ancestor_of( $1, $2, $3, $4, $5 ), $6 ); -$$ LANGUAGE SQL; - --- isnt_ancestor_of( schema, table, schema, table, depth ) -CREATE OR REPLACE FUNCTION isnt_ancestor_of( NAME, NAME, NAME, NAME, INT ) -RETURNS TEXT AS $$ - SELECT ok( - NOT _ancestor_of( $1, $2, $3, $4, $5 ), - 'Table ' || quote_ident( $1 ) || '.' || quote_ident( $2 ) - || ' should not be ancestor ' || $5 || ' for ' - || quote_ident( $3 ) || '.' || quote_ident( $4 ) - ); -$$ LANGUAGE SQL; - --- isnt_ancestor_of( schema, table, schema, table, description ) -CREATE OR REPLACE FUNCTION isnt_ancestor_of( NAME, NAME, NAME, NAME, TEXT ) -RETURNS TEXT AS $$ - SELECT ok( NOT _ancestor_of( $1, $2, $3, $4, NULL ), $5 ); -$$ LANGUAGE SQL; - --- isnt_ancestor_of( schema, table, schema, table ) -CREATE OR REPLACE FUNCTION isnt_ancestor_of( NAME, NAME, NAME, NAME ) -RETURNS TEXT AS $$ - SELECT ok( - NOT _ancestor_of( $1, $2, $3, $4, NULL ), - 'Table ' || quote_ident( $1 ) || '.' || quote_ident( $2 ) - || ' should not be an ancestor of ' - || quote_ident( $3 ) || '.' || quote_ident( $4 ) - ); -$$ LANGUAGE SQL; - --- isnt_ancestor_of( table, table, depth, description ) -CREATE OR REPLACE FUNCTION isnt_ancestor_of( NAME, NAME, INT, TEXT ) -RETURNS TEXT AS $$ - SELECT ok( NOT _ancestor_of( $1, $2, $3 ), $4 ); -$$ LANGUAGE SQL; - --- isnt_ancestor_of( table, table, depth ) -CREATE OR REPLACE FUNCTION isnt_ancestor_of( NAME, NAME, INT ) -RETURNS TEXT AS $$ - SELECT ok( - NOT _ancestor_of( $1, $2, $3 ), - 'Table ' || quote_ident( $1 ) || ' should not be ancestor ' || $3 || ' of ' || quote_ident( $2) - ); -$$ LANGUAGE SQL; - --- isnt_ancestor_of( table, table, description ) -CREATE OR REPLACE FUNCTION isnt_ancestor_of( NAME, NAME, TEXT ) -RETURNS TEXT AS $$ - SELECT ok( NOT _ancestor_of( $1, $2, NULL ), $3 ); -$$ LANGUAGE SQL; - --- isnt_ancestor_of( table, table ) -CREATE OR REPLACE FUNCTION isnt_ancestor_of( NAME, NAME ) -RETURNS TEXT AS $$ - SELECT ok( - NOT _ancestor_of( $1, $2, NULL ), - 'Table ' || quote_ident( $1 ) || ' should not be an ancestor of ' || quote_ident( $2) - ); -$$ LANGUAGE SQL; - --- is_descendent_of( schema, table, schema, table, depth, description ) -CREATE OR REPLACE FUNCTION is_descendent_of( NAME, NAME, NAME, NAME, INT, TEXT ) -RETURNS TEXT AS $$ - SELECT ok( _ancestor_of( $3, $4, $1, $2, $5 ), $6 ); -$$ LANGUAGE SQL; - --- is_descendent_of( schema, table, schema, table, depth ) -CREATE OR REPLACE FUNCTION is_descendent_of( NAME, NAME, NAME, NAME, INT ) -RETURNS TEXT AS $$ - SELECT ok( - _ancestor_of( $3, $4, $1, $2, $5 ), - 'Table ' || quote_ident( $1 ) || '.' || quote_ident( $2 ) - || ' should be descendent ' || $5 || ' from ' - || quote_ident( $3 ) || '.' || quote_ident( $4 ) - ); -$$ LANGUAGE SQL; - --- is_descendent_of( schema, table, schema, table, description ) -CREATE OR REPLACE FUNCTION is_descendent_of( NAME, NAME, NAME, NAME, TEXT ) -RETURNS TEXT AS $$ - SELECT ok( _ancestor_of( $3, $4, $1, $2, NULL ), $5 ); -$$ LANGUAGE SQL; - --- is_descendent_of( schema, table, schema, table ) -CREATE OR REPLACE FUNCTION is_descendent_of( NAME, NAME, NAME, NAME ) -RETURNS TEXT AS $$ - SELECT ok( - _ancestor_of( $3, $4, $1, $2, NULL ), - 'Table ' || quote_ident( $1 ) || '.' || quote_ident( $2 ) - || ' should be a descendent of ' - || quote_ident( $3 ) || '.' || quote_ident( $4 ) - ); -$$ LANGUAGE SQL; - --- is_descendent_of( table, table, depth, description ) -CREATE OR REPLACE FUNCTION is_descendent_of( NAME, NAME, INT, TEXT ) -RETURNS TEXT AS $$ - SELECT ok( _ancestor_of( $2, $1, $3 ), $4 ); -$$ LANGUAGE SQL; - --- is_descendent_of( table, table, depth ) -CREATE OR REPLACE FUNCTION is_descendent_of( NAME, NAME, INT ) -RETURNS TEXT AS $$ - SELECT ok( - _ancestor_of( $2, $1, $3 ), - 'Table ' || quote_ident( $1 ) || ' should be descendent ' || $3 || ' from ' || quote_ident( $2) - ); -$$ LANGUAGE SQL; - --- is_descendent_of( table, table, description ) -CREATE OR REPLACE FUNCTION is_descendent_of( NAME, NAME, TEXT ) -RETURNS TEXT AS $$ - SELECT ok( _ancestor_of( $2, $1, NULL ), $3 ); -$$ LANGUAGE SQL; - --- is_descendent_of( table, table ) -CREATE OR REPLACE FUNCTION is_descendent_of( NAME, NAME ) -RETURNS TEXT AS $$ - SELECT ok( - _ancestor_of( $2, $1, NULL ), - 'Table ' || quote_ident( $1 ) || ' should be a descendent of ' || quote_ident( $2) - ); -$$ LANGUAGE SQL; - --- isnt_descendent_of( schema, table, schema, table, depth, description ) -CREATE OR REPLACE FUNCTION isnt_descendent_of( NAME, NAME, NAME, NAME, INT, TEXT ) -RETURNS TEXT AS $$ - SELECT ok(NOT _ancestor_of( $3, $4, $1, $2, $5 ), $6 ); -$$ LANGUAGE SQL; - --- isnt_descendent_of( schema, table, schema, table, depth ) -CREATE OR REPLACE FUNCTION isnt_descendent_of( NAME, NAME, NAME, NAME, INT ) -RETURNS TEXT AS $$ - SELECT ok( - NOT _ancestor_of( $3, $4, $1, $2, $5 ), - 'Table ' || quote_ident( $1 ) || '.' || quote_ident( $2 ) - || ' should not be descendent ' || $5 || ' from ' - || quote_ident( $3 ) || '.' || quote_ident( $4 ) - ); -$$ LANGUAGE SQL; - --- isnt_descendent_of( schema, table, schema, table, description ) -CREATE OR REPLACE FUNCTION isnt_descendent_of( NAME, NAME, NAME, NAME, TEXT ) -RETURNS TEXT AS $$ - SELECT ok(NOT _ancestor_of( $3, $4, $1, $2, NULL ), $5 ); -$$ LANGUAGE SQL; - --- isnt_descendent_of( schema, table, schema, table ) -CREATE OR REPLACE FUNCTION isnt_descendent_of( NAME, NAME, NAME, NAME ) -RETURNS TEXT AS $$ - SELECT ok( - NOT _ancestor_of( $3, $4, $1, $2, NULL ), - 'Table ' || quote_ident( $1 ) || '.' || quote_ident( $2 ) - || ' should not be a descendent of ' - || quote_ident( $3 ) || '.' || quote_ident( $4 ) - ); -$$ LANGUAGE SQL; - --- isnt_descendent_of( table, table, depth, description ) -CREATE OR REPLACE FUNCTION isnt_descendent_of( NAME, NAME, INT, TEXT ) -RETURNS TEXT AS $$ - SELECT ok(NOT _ancestor_of( $2, $1, $3 ), $4 ); -$$ LANGUAGE SQL; - --- isnt_descendent_of( table, table, depth ) -CREATE OR REPLACE FUNCTION isnt_descendent_of( NAME, NAME, INT ) -RETURNS TEXT AS $$ - SELECT ok( - NOT _ancestor_of( $2, $1, $3 ), - 'Table ' || quote_ident( $1 ) || ' should not be descendent ' || $3 || ' from ' || quote_ident( $2) - ); -$$ LANGUAGE SQL; - --- isnt_descendent_of( table, table, description ) -CREATE OR REPLACE FUNCTION isnt_descendent_of( NAME, NAME, TEXT ) -RETURNS TEXT AS $$ - SELECT ok(NOT _ancestor_of( $2, $1, NULL ), $3 ); -$$ LANGUAGE SQL; - --- isnt_descendent_of( table, table ) -CREATE OR REPLACE FUNCTION isnt_descendent_of( NAME, NAME ) -RETURNS TEXT AS $$ - SELECT ok( - NOT _ancestor_of( $2, $1, NULL ), - 'Table ' || quote_ident( $1 ) || ' should not be a descendent of ' || quote_ident( $2) - ); -$$ LANGUAGE SQL;