\set ECHO none \i test/pgxntool/setup.sql CREATE FUNCTION pg_temp.exec_out( ) RETURNS text LANGUAGE sql IMMUTABLE AS $$ SELECT ' at EXECUTE' || CASE WHEN current_setting('server_version_num')::int < 90500 THEN ' statement' ELSE '' END $$; CREATE TEMP TABLE good( seq serial , code text , description text , _row_count int ); INSERT INTO good(code, description, _row_count) VALUES ('INSERT INTO test SELECT generate_series(1,42)', 'INSERT', 42) , ('SELECT count(*) FROM test', 'SELECT', 1) , ('SELECT * FROM test', 'SELECT', 42) , ('UPDATE test SET i = -i WHERE i <= 10', 'UPDATE 10 rows', 10) , ('UPDATE test SET i = -i WHERE i = 0', 'UPDATE no rows', 0) ; CREATE TEMP TABLE test_bad( must_be_true boolean CHECK(must_be_true) ); CREATE TEMP TABLE bad( code text , description text , sqlstate text , message text , hint text , detail text , context text , schema_name text , table_name text , column_name text , constraint_name text , type_name text ); -- TODO: test using raise() to verify all values work INSERT INTO bad VALUES ('bogus', 'syntax error' , '42601' , 'syntax error at or near "bogus"' , '' , '' , 'PL/pgSQL function error_schema.try(text) line 3' || pg_temp.exec_out() , '' , '' , '' , '' , '' ) , ('INSERT INTO test_bad VALUES(false)', 'CHECK constraint error' , '23514' , 'new row for relation "test_bad" violates check constraint "test_bad_must_be_true_check"' , '' , 'Failing row contains (f).' , E'SQL statement "INSERT INTO test_bad VALUES(false)"\nPL/pgSQL function error_schema.try(text) line 3' || pg_temp.exec_out() , (SELECT nspname FROM pg_namespace WHERE oid = pg_my_temp_schema()) , 'test_bad' , '' , 'test_bad_must_be_true_check' , '' ) ; SELECT plan( 0 + 2 -- try_into() + 4 -- error_data() + 1 -- simple raise + 2 * (SELECT count(*)::int FROM good) + (11+1) * (SELECT count(*)::int FROM bad) ); SELECT is( (error_schema.try_into('SELECT 1', 0::int)).result , 1 , $$error_schema.try_into('SELECT 1', 0::int)$$ ); SELECT is( (error_schema.try_into('VALUES(1),(2)', NULL::int, strict := true)).error , error_schema.error_data( 'P0003' , 'query returned more than one row' , context := 'PL/pgSQL function error_schema.try_into(text,anyelement,boolean) line 4' || pg_temp.exec_out() ) , 'error_schema.try_into() with strict = true' ); SELECT is( error_schema.error_data() , row( '' , '' , '' , '' , '' , '' , '' , '' , '' , '' )::error_schema.error_data , 'Verify error_schema.error_data() defaults' ); SELECT is( error_schema.error_data( sqlstate := 'sqlstate_1' , message := 'message_1' , hint := 'hint_1' , detail := 'detail_1' , context := 'context_1' , schema_name := 'schema_name_1' , table_name := 'table_name_1' , column_name := 'column_name_1' , constraint_name := 'constraint_name_1' , type_name := 'type_name_1' ) , row( 'sqlstate_1' , 'message_1' , 'hint_1' , 'detail_1' , 'context_1' , 'schema_name_1' , 'table_name_1' , 'column_name_1' , 'constraint_name_1' , 'type_name_1' )::error_schema.error_data , 'Verify error_schema.error_data()' ); SELECT is( error_schema.error_data( sqlstate := 'sqlstate_2' , message := 'message_2' , hint := 'hint_2' , detail := 'detail_2' , context := 'context_2' , schema_name := 'schema_name_2' , table_name := 'table_name_2' , column_name := 'column_name_2' , constraint_name := 'constraint_name_2' , type_name := 'type_name_2' ) , row( 'sqlstate_2' , 'message_2' , 'hint_2' , 'detail_2' , 'context_2' , 'schema_name_2' , 'table_name_2' , 'column_name_2' , 'constraint_name_2' , 'type_name_2' )::error_schema.error_data , 'Verify error_schema.error_data()' ); SELECT throws_ok( $$SELECT error_schema.raise( 'message_1', 'EXCEPTION' , sqlstate := 'sqlstate_1' , hint := 'hint_1' , detail := 'detail_1' , schema_name := 'schema_name_1' , table_name := 'table_name_1' , column_name := 'column_name_1' , constraint_name := 'constraint_name_1' , type_name := 'type_name_1' ) $$ , '42601' , $$invalid SQLSTATE code at or near "'sqlstate_1'"$$ , 'Check invalid sql state' ); SELECT throws_ok( $$SELECT error_schema.raise( 'message_1', 'EXCEPTION' , hint := 'hint_1' , detail := 'detail_1' , schema_name := 'schema_name_1' , table_name := 'table_name_1' , column_name := 'column_name_1' , constraint_name := 'constraint_name_1' , type_name := 'type_name_1' ) $$ , 'P0001' , $$message_1$$ , 'Check simple error_schema.raise()' ); -- TODO: full suite of raise() tests CREATE TEMP TABLE bad_results AS SELECT b.*, t.error, t.row_count FROM bad b, error_schema.try(code) t ; SELECT is( row_count , NULL , description || ' check value of row_count' ) || E'\n' || "is"((error).sqlstate, b.sqlstate, description || ' check sqlstate') || E'\n' || "is"((error).message, b.message, description || ' check message') || E'\n' || "is"((error).hint, b.hint, description || ' check hint') || E'\n' || "is"((error).detail, b.detail, description || ' check detail') || E'\n' || "is"('"' || (error).context || '"', '"' || b.context || '"', description || ' check context') || E'\n' || "is"((error).schema_name, b.schema_name, description || ' check schema_name') || E'\n' || "is"((error).table_name, b.table_name, description || ' check table_name') || E'\n' || "is"((error).column_name, b.column_name, description || ' check column_name') || E'\n' || "is"((error).constraint_name, b.constraint_name, description || ' check constraint_name') || E'\n' || "is"((error).type_name, b.type_name, description || ' check type_name') FROM bad_results b ; SELECT throws_ok( format($$SELECT error_schema.raise(%L::error_schema.error_data)$$, error) , sqlstate , message ) FROM bad_results ; CREATE TEMP TABLE test( i int ); SELECT is( row_count , _row_count , description || ' check value of row_count' ) || E'\n' || "is"( error , NULL , description || ' error is null' ) FROM good, error_schema.try(code) ORDER BY seq ; \set VERBOSITY default \echo \echo Should output two warnings \echo SELECT error_schema.raise(error, 'warning') FROM bad_results; \i test/pgxntool/finish.sql -- vi: expandtab ts=2 sw=2