text: -- suppress CONTEXT so that function OIDs aren't in output
  \set VERBOSITY terse
  
  -- Test composite-type arguments
  select tcl_composite_arg_ref1(row('tkey', 42, 'ref2'));
  select tcl_composite_arg_ref2(row('tkey', 42, 'ref2'));
  
  -- More tests for composite argument/result types
  
  create domain d_comp1 as T_comp1 check ((value).ref1 > 0);
  
  create function tcl_record_arg(record, fldname text) returns int as '
      return $1($2)
  ' language pltcl;
  
  select tcl_record_arg(row('tkey', 42, 'ref2')::T_comp1, 'ref1');
  select tcl_record_arg(row('tkey', 42, 'ref2')::d_comp1, 'ref1');
  select tcl_record_arg(row(2,4), 'f2');
  
  create function tcl_cdomain_arg(d_comp1) returns int as '
      return $1(ref1)
  ' language pltcl;
  
  select tcl_cdomain_arg(row('tkey', 42, 'ref2'));
  select tcl_cdomain_arg(row('tkey', 42, 'ref2')::T_comp1);
  select tcl_cdomain_arg(row('tkey', -1, 'ref2'));  -- fail
  
  -- Test argisnull primitive
  select tcl_argisnull('foo');
  select tcl_argisnull('');
  select tcl_argisnull(null);
  
  -- test some error cases
  create function tcl_error(out a int, out b int) as $$return {$$ language pltcl;
  select tcl_error();
  
  create function bad_record(out a text, out b text) as $$return [list a]$$ language pltcl;
  select bad_record();
  
  create function bad_field(out a text, out b text) as $$return [list a 1 b 2 cow 3]$$ language pltcl;
  select bad_field();
  
  -- test compound return
  select * from tcl_test_cube_squared(5);
  
  -- test SRF
  select * from tcl_test_squared_rows(0,5);
  
  select * from tcl_test_sequence(0,5) as a;
  
  select 1, tcl_test_sequence(0,5);
  
  create function non_srf() returns int as $$return_next 1$$ language pltcl;
  select non_srf();
  
  create function bad_record_srf(out a text, out b text) returns setof record as $$
  return_next [list a]
  $$ language pltcl;
  select bad_record_srf();
  
  create function bad_field_srf(out a text, out b text) returns setof record as $$
  return_next [list a 1 b 2 cow 3]
  $$ language pltcl;
  select bad_field_srf();
  
  -- test composite and domain-over-composite results
  create function tcl_composite_result(int) returns T_comp1 as $$
  return [list tkey tkey1 ref1 $1 ref2 ref22]
  $$ language pltcl;
  select tcl_composite_result(1001);
  select * from tcl_composite_result(1002);
  
  create function tcl_dcomposite_result(int) returns d_comp1 as $$
  return [list tkey tkey2 ref1 $1 ref2 ref42]
  $$ language pltcl;
  select tcl_dcomposite_result(1001);
  select * from tcl_dcomposite_result(1002);
  select * from tcl_dcomposite_result(-1);  -- fail
  
  create function tcl_record_result(int) returns record as $$
  return [list q1 sometext q2 $1 q3 moretext]
  $$ language pltcl;
  select tcl_record_result(42);  -- fail
  select * from tcl_record_result(42);  -- fail
  select * from tcl_record_result(42) as (q1 text, q2 int, q3 text);
  select * from tcl_record_result(42) as (q1 text, q2 int, q3 text, q4 int);
  select * from tcl_record_result(42) as (q1 text, q2 int, q4 int);  -- fail
  
  -- test quote
  select tcl_eval('quote foo bar');
  select tcl_eval('quote [format %c 39]');
  select tcl_eval('quote [format %c 92]');
  
  -- Test argisnull
  select tcl_eval('argisnull');
  select tcl_eval('argisnull 14');
  select tcl_eval('argisnull abc');
  
  -- Test return_null
  select tcl_eval('return_null 14');
  
  -- Test spi_exec
  select tcl_eval('spi_exec');
  select tcl_eval('spi_exec -count');
  select tcl_eval('spi_exec -array');
  select tcl_eval('spi_exec -count abc');
  select tcl_eval('spi_exec query loop body toomuch');
  select tcl_eval('spi_exec "begin; rollback;"');
  
  -- Test spi_execp
  select tcl_eval('spi_execp');
  select tcl_eval('spi_execp -count');
  select tcl_eval('spi_execp -array');
  select tcl_eval('spi_execp -count abc');
  select tcl_eval('spi_execp -nulls');
  select tcl_eval('spi_execp ""');
  
  -- test spi_prepare
  select tcl_eval('spi_prepare');
  select tcl_eval('spi_prepare a b');
  select tcl_eval('spi_prepare a "b {"');
  select tcl_error_handling_test($tcl$spi_prepare "select moo" []$tcl$);
  
  -- test full error text
  select tcl_error_handling_test($tcl$
  spi_exec "DO $$
  BEGIN
  RAISE 'my message'
  	USING HINT = 'my hint'
  	, DETAIL = 'my detail'
  	, SCHEMA = 'my schema'
  	, TABLE = 'my table'
  	, COLUMN = 'my column'
  	, CONSTRAINT = 'my constraint'
  	, DATATYPE = 'my datatype'
  ;
  END$$;"
  $tcl$);
  
  -- verify tcl_error_handling_test() properly reports non-postgres errors
  select tcl_error_handling_test('moo');
  
  -- test elog
  select tcl_eval('elog');
  select tcl_eval('elog foo bar');
  
  -- test forced error
  select tcl_eval('error "forced error"');
  
  -- test loop control in spi_exec[p]
  select tcl_spi_exec(true, 'break');
  select tcl_spi_exec(true, 'continue');
  select tcl_spi_exec(true, 'error');
  select tcl_spi_exec(true, 'return');
  select tcl_spi_exec(false, 'break');
  select tcl_spi_exec(false, 'continue');
  select tcl_spi_exec(false, 'error');
  select tcl_spi_exec(false, 'return');
  
  -- forcibly run the Tcl event loop for awhile, to check that we have not
  -- messed things up too badly by disabling the Tcl notifier subsystem
  select tcl_eval($$
    unset -nocomplain ::tcl_vwait
    after 100 {set ::tcl_vwait 1}
    vwait ::tcl_vwait
    unset -nocomplain ::tcl_vwait$$);
  