1-- 2-- Tests for PL/pgSQL handling of composite (record) variables 3-- 4create type two_int4s as (f1 int4, f2 int4); 5create type two_int8s as (q1 int8, q2 int8); 6-- base-case return of a composite type 7create function retc(int) returns two_int8s language plpgsql as 8$$ begin return row($1,1)::two_int8s; end $$; 9select retc(42); 10 retc 11-------- 12 (42,1) 13(1 row) 14 15-- ok to return a matching record type 16create or replace function retc(int) returns two_int8s language plpgsql as 17$$ begin return row($1::int8, 1::int8); end $$; 18select retc(42); 19 retc 20-------- 21 (42,1) 22(1 row) 23 24-- we don't currently support implicit casting 25create or replace function retc(int) returns two_int8s language plpgsql as 26$$ begin return row($1,1); end $$; 27select retc(42); 28ERROR: returned record type does not match expected record type 29DETAIL: Returned type integer does not match expected type bigint in column 1. 30CONTEXT: PL/pgSQL function retc(integer) while casting return value to function's return type 31-- nor extra columns 32create or replace function retc(int) returns two_int8s language plpgsql as 33$$ begin return row($1::int8, 1::int8, 42); end $$; 34select retc(42); 35ERROR: returned record type does not match expected record type 36DETAIL: Number of returned columns (3) does not match expected column count (2). 37CONTEXT: PL/pgSQL function retc(integer) while casting return value to function's return type 38-- same cases with an intermediate "record" variable 39create or replace function retc(int) returns two_int8s language plpgsql as 40$$ declare r record; begin r := row($1::int8, 1::int8); return r; end $$; 41select retc(42); 42 retc 43-------- 44 (42,1) 45(1 row) 46 47create or replace function retc(int) returns two_int8s language plpgsql as 48$$ declare r record; begin r := row($1,1); return r; end $$; 49select retc(42); 50ERROR: returned record type does not match expected record type 51DETAIL: Returned type integer does not match expected type bigint in column 1. 52CONTEXT: PL/pgSQL function retc(integer) while casting return value to function's return type 53create or replace function retc(int) returns two_int8s language plpgsql as 54$$ declare r record; begin r := row($1::int8, 1::int8, 42); return r; end $$; 55select retc(42); 56ERROR: returned record type does not match expected record type 57DETAIL: Number of returned columns (3) does not match expected column count (2). 58CONTEXT: PL/pgSQL function retc(integer) while casting return value to function's return type 59-- but, for mostly historical reasons, we do convert when assigning 60-- to a named-composite-type variable 61create or replace function retc(int) returns two_int8s language plpgsql as 62$$ declare r two_int8s; begin r := row($1::int8, 1::int8, 42); return r; end $$; 63select retc(42); 64 retc 65-------- 66 (42,1) 67(1 row) 68 69do $$ declare c two_int8s; 70begin c := row(1,2); raise notice 'c = %', c; end$$; 71NOTICE: c = (1,2) 72do $$ declare c two_int8s; 73begin for c in select 1,2 loop raise notice 'c = %', c; end loop; end$$; 74NOTICE: c = (1,2) 75do $$ declare c4 two_int4s; c8 two_int8s; 76begin 77 c8 := row(1,2); 78 c4 := c8; 79 c8 := c4; 80 raise notice 'c4 = %', c4; 81 raise notice 'c8 = %', c8; 82end$$; 83NOTICE: c4 = (1,2) 84NOTICE: c8 = (1,2) 85-- check passing composite result to another function 86create function getq1(two_int8s) returns int8 language plpgsql as $$ 87declare r two_int8s; begin r := $1; return r.q1; end $$; 88select getq1(retc(344)); 89 getq1 90------- 91 344 92(1 row) 93 94select getq1(row(1,2)); 95 getq1 96------- 97 1 98(1 row) 99 100do $$ 101declare r1 two_int8s; r2 record; x int8; 102begin 103 r1 := retc(345); 104 perform getq1(r1); 105 x := getq1(r1); 106 raise notice 'x = %', x; 107 r2 := retc(346); 108 perform getq1(r2); 109 x := getq1(r2); 110 raise notice 'x = %', x; 111end$$; 112NOTICE: x = 345 113NOTICE: x = 346 114-- check assignments of composites 115do $$ 116declare r1 two_int8s; r2 two_int8s; r3 record; r4 record; 117begin 118 r1 := row(1,2); 119 raise notice 'r1 = %', r1; 120 r1 := r1; -- shouldn't do anything 121 raise notice 'r1 = %', r1; 122 r2 := r1; 123 raise notice 'r1 = %', r1; 124 raise notice 'r2 = %', r2; 125 r2.q2 = r1.q1 + 3; -- check that r2 has distinct storage 126 raise notice 'r1 = %', r1; 127 raise notice 'r2 = %', r2; 128 r1 := null; 129 raise notice 'r1 = %', r1; 130 raise notice 'r2 = %', r2; 131 r1 := row(7,11)::two_int8s; 132 r2 := r1; 133 raise notice 'r1 = %', r1; 134 raise notice 'r2 = %', r2; 135 r3 := row(1,2); 136 r4 := r3; 137 raise notice 'r3 = %', r3; 138 raise notice 'r4 = %', r4; 139 r4.f1 := r4.f1 + 3; -- check that r4 has distinct storage 140 raise notice 'r3 = %', r3; 141 raise notice 'r4 = %', r4; 142 r1 := r3; 143 raise notice 'r1 = %', r1; 144 r4 := r1; 145 raise notice 'r4 = %', r4; 146 r4.q2 := r4.q2 + 1; -- r4's field names have changed 147 raise notice 'r4 = %', r4; 148end$$; 149NOTICE: r1 = (1,2) 150NOTICE: r1 = (1,2) 151NOTICE: r1 = (1,2) 152NOTICE: r2 = (1,2) 153NOTICE: r1 = (1,2) 154NOTICE: r2 = (1,4) 155NOTICE: r1 = <NULL> 156NOTICE: r2 = (1,4) 157NOTICE: r1 = (7,11) 158NOTICE: r2 = (7,11) 159NOTICE: r3 = (1,2) 160NOTICE: r4 = (1,2) 161NOTICE: r3 = (1,2) 162NOTICE: r4 = (4,2) 163NOTICE: r1 = (1,2) 164NOTICE: r4 = (1,2) 165NOTICE: r4 = (1,3) 166-- fields of named-type vars read as null if uninitialized 167do $$ 168declare r1 two_int8s; 169begin 170 raise notice 'r1 = %', r1; 171 raise notice 'r1.q1 = %', r1.q1; 172 raise notice 'r1.q2 = %', r1.q2; 173 raise notice 'r1 = %', r1; 174end$$; 175NOTICE: r1 = <NULL> 176NOTICE: r1.q1 = <NULL> 177NOTICE: r1.q2 = <NULL> 178NOTICE: r1 = <NULL> 179do $$ 180declare r1 two_int8s; 181begin 182 raise notice 'r1.q1 = %', r1.q1; 183 raise notice 'r1.q2 = %', r1.q2; 184 raise notice 'r1 = %', r1; 185 raise notice 'r1.nosuchfield = %', r1.nosuchfield; 186end$$; 187NOTICE: r1.q1 = <NULL> 188NOTICE: r1.q2 = <NULL> 189NOTICE: r1 = <NULL> 190ERROR: record "r1" has no field "nosuchfield" 191CONTEXT: SQL statement "SELECT r1.nosuchfield" 192PL/pgSQL function inline_code_block line 7 at RAISE 193-- records, not so much 194do $$ 195declare r1 record; 196begin 197 raise notice 'r1 = %', r1; 198 raise notice 'r1.f1 = %', r1.f1; 199 raise notice 'r1.f2 = %', r1.f2; 200 raise notice 'r1 = %', r1; 201end$$; 202NOTICE: r1 = <NULL> 203ERROR: record "r1" is not assigned yet 204DETAIL: The tuple structure of a not-yet-assigned record is indeterminate. 205CONTEXT: SQL statement "SELECT r1.f1" 206PL/pgSQL function inline_code_block line 5 at RAISE 207-- but OK if you assign first 208do $$ 209declare r1 record; 210begin 211 raise notice 'r1 = %', r1; 212 r1 := row(1,2); 213 raise notice 'r1.f1 = %', r1.f1; 214 raise notice 'r1.f2 = %', r1.f2; 215 raise notice 'r1 = %', r1; 216 raise notice 'r1.nosuchfield = %', r1.nosuchfield; 217end$$; 218NOTICE: r1 = <NULL> 219NOTICE: r1.f1 = 1 220NOTICE: r1.f2 = 2 221NOTICE: r1 = (1,2) 222ERROR: record "r1" has no field "nosuchfield" 223CONTEXT: SQL statement "SELECT r1.nosuchfield" 224PL/pgSQL function inline_code_block line 9 at RAISE 225-- check repeated assignments to composite fields 226create table some_table (id int, data text); 227do $$ 228declare r some_table; 229begin 230 r := (23, 'skidoo'); 231 for i in 1 .. 10 loop 232 r.id := r.id + i; 233 r.data := r.data || ' ' || i; 234 end loop; 235 raise notice 'r = %', r; 236end$$; 237NOTICE: r = (78,"skidoo 1 2 3 4 5 6 7 8 9 10") 238-- check behavior of function declared to return "record" 239create function returnsrecord(int) returns record language plpgsql as 240$$ begin return row($1,$1+1); end $$; 241select returnsrecord(42); 242 returnsrecord 243--------------- 244 (42,43) 245(1 row) 246 247select * from returnsrecord(42) as r(x int, y int); 248 x | y 249----+---- 250 42 | 43 251(1 row) 252 253select * from returnsrecord(42) as r(x int, y int, z int); -- fail 254ERROR: returned record type does not match expected record type 255DETAIL: Number of returned columns (2) does not match expected column count (3). 256CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type 257select * from returnsrecord(42) as r(x int, y bigint); -- fail 258ERROR: returned record type does not match expected record type 259DETAIL: Returned type integer does not match expected type bigint in column 2. 260CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type 261-- same with an intermediate record variable 262create or replace function returnsrecord(int) returns record language plpgsql as 263$$ declare r record; begin r := row($1,$1+1); return r; end $$; 264select returnsrecord(42); 265 returnsrecord 266--------------- 267 (42,43) 268(1 row) 269 270select * from returnsrecord(42) as r(x int, y int); 271 x | y 272----+---- 273 42 | 43 274(1 row) 275 276select * from returnsrecord(42) as r(x int, y int, z int); -- fail 277ERROR: returned record type does not match expected record type 278DETAIL: Number of returned columns (2) does not match expected column count (3). 279CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type 280select * from returnsrecord(42) as r(x int, y bigint); -- fail 281ERROR: returned record type does not match expected record type 282DETAIL: Returned type integer does not match expected type bigint in column 2. 283CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type 284-- should work the same with a missing column in the actual result value 285create table has_hole(f1 int, f2 int, f3 int); 286alter table has_hole drop column f2; 287create or replace function returnsrecord(int) returns record language plpgsql as 288$$ begin return row($1,$1+1)::has_hole; end $$; 289select returnsrecord(42); 290 returnsrecord 291--------------- 292 (42,43) 293(1 row) 294 295select * from returnsrecord(42) as r(x int, y int); 296 x | y 297----+---- 298 42 | 43 299(1 row) 300 301select * from returnsrecord(42) as r(x int, y int, z int); -- fail 302ERROR: returned record type does not match expected record type 303DETAIL: Number of returned columns (2) does not match expected column count (3). 304CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type 305select * from returnsrecord(42) as r(x int, y bigint); -- fail 306ERROR: returned record type does not match expected record type 307DETAIL: Returned type integer does not match expected type bigint in column 2. 308CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type 309-- same with an intermediate record variable 310create or replace function returnsrecord(int) returns record language plpgsql as 311$$ declare r record; begin r := row($1,$1+1)::has_hole; return r; end $$; 312select returnsrecord(42); 313 returnsrecord 314--------------- 315 (42,43) 316(1 row) 317 318select * from returnsrecord(42) as r(x int, y int); 319 x | y 320----+---- 321 42 | 43 322(1 row) 323 324select * from returnsrecord(42) as r(x int, y int, z int); -- fail 325ERROR: returned record type does not match expected record type 326DETAIL: Number of returned columns (2) does not match expected column count (3). 327CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type 328select * from returnsrecord(42) as r(x int, y bigint); -- fail 329ERROR: returned record type does not match expected record type 330DETAIL: Returned type integer does not match expected type bigint in column 2. 331CONTEXT: PL/pgSQL function returnsrecord(integer) while casting return value to function's return type 332-- check access to a field of an argument declared "record" 333create function getf1(x record) returns int language plpgsql as 334$$ begin return x.f1; end $$; 335select getf1(1); 336ERROR: function getf1(integer) does not exist 337LINE 1: select getf1(1); 338 ^ 339HINT: No function matches the given name and argument types. You might need to add explicit type casts. 340select getf1(row(1,2)); 341 getf1 342------- 343 1 344(1 row) 345 346-- a CLOBBER_CACHE_ALWAYS build will report this error with a different 347-- context stack than other builds, so suppress context output 348\set SHOW_CONTEXT never 349select getf1(row(1,2)::two_int8s); 350ERROR: record "x" has no field "f1" 351\set SHOW_CONTEXT errors 352select getf1(row(1,2)); 353 getf1 354------- 355 1 356(1 row) 357 358-- check behavior when assignment to FOR-loop variable requires coercion 359do $$ 360declare r two_int8s; 361begin 362 for r in select i, i+1 from generate_series(1,4) i 363 loop 364 raise notice 'r = %', r; 365 end loop; 366end$$; 367NOTICE: r = (1,2) 368NOTICE: r = (2,3) 369NOTICE: r = (3,4) 370NOTICE: r = (4,5) 371-- check behavior when returning setof composite 372create function returnssetofholes() returns setof has_hole language plpgsql as 373$$ 374declare r record; 375 h has_hole; 376begin 377 return next h; 378 r := (1,2); 379 h := (3,4); 380 return next r; 381 return next h; 382 return next row(5,6); 383 return next row(7,8)::has_hole; 384end$$; 385select returnssetofholes(); 386 returnssetofholes 387------------------- 388 (,) 389 (1,2) 390 (3,4) 391 (5,6) 392 (7,8) 393(5 rows) 394 395create or replace function returnssetofholes() returns setof has_hole language plpgsql as 396$$ 397declare r record; 398begin 399 return next r; -- fails, not assigned yet 400end$$; 401select returnssetofholes(); 402ERROR: record "r" is not assigned yet 403DETAIL: The tuple structure of a not-yet-assigned record is indeterminate. 404CONTEXT: PL/pgSQL function returnssetofholes() line 4 at RETURN NEXT 405create or replace function returnssetofholes() returns setof has_hole language plpgsql as 406$$ 407begin 408 return next row(1,2,3); -- fails 409end$$; 410select returnssetofholes(); 411ERROR: returned record type does not match expected record type 412DETAIL: Number of returned columns (3) does not match expected column count (2). 413CONTEXT: PL/pgSQL function returnssetofholes() line 3 at RETURN NEXT 414-- check behavior with changes of a named rowtype 415create table mutable(f1 int, f2 text); 416create function sillyaddone(int) returns int language plpgsql as 417$$ declare r mutable; begin r.f1 := $1; return r.f1 + 1; end $$; 418select sillyaddone(42); 419 sillyaddone 420------------- 421 43 422(1 row) 423 424-- test for change of type of column f1 should be here someday; 425-- for now see plpgsql_cache test 426alter table mutable drop column f1; 427select sillyaddone(42); -- fail 428ERROR: record "r" has no field "f1" 429CONTEXT: PL/pgSQL function sillyaddone(integer) line 1 at assignment 430create function getf3(x mutable) returns int language plpgsql as 431$$ begin return x.f3; end $$; 432select getf3(null::mutable); -- doesn't work yet 433ERROR: record "x" has no field "f3" 434CONTEXT: SQL statement "SELECT x.f3" 435PL/pgSQL function getf3(mutable) line 1 at RETURN 436alter table mutable add column f3 int; 437select getf3(null::mutable); -- now it works 438 getf3 439------- 440 441(1 row) 442 443alter table mutable drop column f3; 444-- a CLOBBER_CACHE_ALWAYS build will report this error with a different 445-- context stack than other builds, so suppress context output 446\set SHOW_CONTEXT never 447select getf3(null::mutable); -- fails again 448ERROR: record "x" has no field "f3" 449\set SHOW_CONTEXT errors 450-- check behavior with creating/dropping a named rowtype 451set check_function_bodies = off; -- else reference to nonexistent type fails 452create function sillyaddtwo(int) returns int language plpgsql as 453$$ declare r mutable2; begin r.f1 := $1; return r.f1 + 2; end $$; 454reset check_function_bodies; 455select sillyaddtwo(42); -- fail 456ERROR: type "mutable2" does not exist 457LINE 1: declare r mutable2; begin r.f1 := $1; return r.f1 + 2; end 458 ^ 459QUERY: declare r mutable2; begin r.f1 := $1; return r.f1 + 2; end 460CONTEXT: compilation of PL/pgSQL function "sillyaddtwo" near line 1 461create table mutable2(f1 int, f2 text); 462select sillyaddtwo(42); 463 sillyaddtwo 464------------- 465 44 466(1 row) 467 468drop table mutable2; 469select sillyaddtwo(42); -- fail 470ERROR: type "mutable2" does not exist 471CONTEXT: PL/pgSQL function sillyaddtwo(integer) line 1 at assignment 472create table mutable2(f0 text, f1 int, f2 text); 473select sillyaddtwo(42); 474 sillyaddtwo 475------------- 476 44 477(1 row) 478 479select sillyaddtwo(43); 480 sillyaddtwo 481------------- 482 45 483(1 row) 484 485-- check access to system columns in a record variable 486create function sillytrig() returns trigger language plpgsql as 487$$begin 488 raise notice 'old.ctid = %', old.ctid; 489 raise notice 'old.tableoid = %', old.tableoid::regclass; 490 return new; 491end$$; 492create trigger mutable_trig before update on mutable for each row 493execute procedure sillytrig(); 494insert into mutable values ('foo'), ('bar'); 495update mutable set f2 = f2 || ' baz'; 496NOTICE: old.ctid = (0,1) 497NOTICE: old.tableoid = mutable 498NOTICE: old.ctid = (0,2) 499NOTICE: old.tableoid = mutable 500table mutable; 501 f2 502--------- 503 foo baz 504 bar baz 505(2 rows) 506 507-- check returning a composite datum from a trigger 508create or replace function sillytrig() returns trigger language plpgsql as 509$$begin 510 return row(new.*); 511end$$; 512update mutable set f2 = f2 || ' baz'; 513table mutable; 514 f2 515------------- 516 foo baz baz 517 bar baz baz 518(2 rows) 519 520create or replace function sillytrig() returns trigger language plpgsql as 521$$declare r record; 522begin 523 r := row(new.*); 524 return r; 525end$$; 526update mutable set f2 = f2 || ' baz'; 527table mutable; 528 f2 529----------------- 530 foo baz baz baz 531 bar baz baz baz 532(2 rows) 533 534-- 535-- Domains of composite 536-- 537create domain ordered_int8s as two_int8s check((value).q1 <= (value).q2); 538create function read_ordered_int8s(p ordered_int8s) returns int8 as $$ 539begin return p.q1 + p.q2; end 540$$ language plpgsql; 541select read_ordered_int8s(row(1, 2)); 542 read_ordered_int8s 543-------------------- 544 3 545(1 row) 546 547select read_ordered_int8s(row(2, 1)); -- fail 548ERROR: value for domain ordered_int8s violates check constraint "ordered_int8s_check" 549create function build_ordered_int8s(i int8, j int8) returns ordered_int8s as $$ 550begin return row(i,j); end 551$$ language plpgsql; 552select build_ordered_int8s(1,2); 553 build_ordered_int8s 554--------------------- 555 (1,2) 556(1 row) 557 558select build_ordered_int8s(2,1); -- fail 559ERROR: value for domain ordered_int8s violates check constraint "ordered_int8s_check" 560CONTEXT: PL/pgSQL function build_ordered_int8s(bigint,bigint) while casting return value to function's return type 561create function build_ordered_int8s_2(i int8, j int8) returns ordered_int8s as $$ 562declare r record; begin r := row(i,j); return r; end 563$$ language plpgsql; 564select build_ordered_int8s_2(1,2); 565 build_ordered_int8s_2 566----------------------- 567 (1,2) 568(1 row) 569 570select build_ordered_int8s_2(2,1); -- fail 571ERROR: value for domain ordered_int8s violates check constraint "ordered_int8s_check" 572CONTEXT: PL/pgSQL function build_ordered_int8s_2(bigint,bigint) while casting return value to function's return type 573create function build_ordered_int8s_3(i int8, j int8) returns ordered_int8s as $$ 574declare r two_int8s; begin r := row(i,j); return r; end 575$$ language plpgsql; 576select build_ordered_int8s_3(1,2); 577 build_ordered_int8s_3 578----------------------- 579 (1,2) 580(1 row) 581 582select build_ordered_int8s_3(2,1); -- fail 583ERROR: value for domain ordered_int8s violates check constraint "ordered_int8s_check" 584CONTEXT: PL/pgSQL function build_ordered_int8s_3(bigint,bigint) while casting return value to function's return type 585create function build_ordered_int8s_4(i int8, j int8) returns ordered_int8s as $$ 586declare r ordered_int8s; begin r := row(i,j); return r; end 587$$ language plpgsql; 588select build_ordered_int8s_4(1,2); 589 build_ordered_int8s_4 590----------------------- 591 (1,2) 592(1 row) 593 594select build_ordered_int8s_4(2,1); -- fail 595ERROR: value for domain ordered_int8s violates check constraint "ordered_int8s_check" 596CONTEXT: PL/pgSQL function build_ordered_int8s_4(bigint,bigint) line 2 at assignment 597create function build_ordered_int8s_a(i int8, j int8) returns ordered_int8s[] as $$ 598begin return array[row(i,j), row(i,j+1)]; end 599$$ language plpgsql; 600select build_ordered_int8s_a(1,2); 601 build_ordered_int8s_a 602----------------------- 603 {"(1,2)","(1,3)"} 604(1 row) 605 606select build_ordered_int8s_a(2,1); -- fail 607ERROR: value for domain ordered_int8s violates check constraint "ordered_int8s_check" 608CONTEXT: PL/pgSQL function build_ordered_int8s_a(bigint,bigint) while casting return value to function's return type 609-- check field assignment 610do $$ 611declare r ordered_int8s; 612begin 613 r.q1 := null; 614 r.q2 := 43; 615 r.q1 := 42; 616 r.q2 := 41; -- fail 617end$$; 618ERROR: value for domain ordered_int8s violates check constraint "ordered_int8s_check" 619CONTEXT: PL/pgSQL function inline_code_block line 7 at assignment 620-- check whole-row assignment 621do $$ 622declare r ordered_int8s; 623begin 624 r := null; 625 r := row(null,null); 626 r := row(1,2); 627 r := row(2,1); -- fail 628end$$; 629ERROR: value for domain ordered_int8s violates check constraint "ordered_int8s_check" 630CONTEXT: PL/pgSQL function inline_code_block line 7 at assignment 631-- check assignment in for-loop 632do $$ 633declare r ordered_int8s; 634begin 635 for r in values (1,2),(3,4),(6,5) loop 636 raise notice 'r = %', r; 637 end loop; 638end$$; 639NOTICE: r = (1,2) 640NOTICE: r = (3,4) 641ERROR: value for domain ordered_int8s violates check constraint "ordered_int8s_check" 642CONTEXT: PL/pgSQL function inline_code_block line 4 at FOR over SELECT rows 643-- check behavior with toastable fields, too 644create type two_texts as (f1 text, f2 text); 645create domain ordered_texts as two_texts check((value).f1 <= (value).f2); 646create table sometable (id int, a text, b text); 647-- b should be compressed, but in-line 648insert into sometable values (1, 'a', repeat('ffoob',1000)); 649-- this b should be out-of-line 650insert into sometable values (2, 'a', repeat('ffoob',100000)); 651-- this pair should fail the domain check 652insert into sometable values (3, 'z', repeat('ffoob',100000)); 653do $$ 654declare d ordered_texts; 655begin 656 for d in select a, b from sometable loop 657 raise notice 'succeeded at "%"', d.f1; 658 end loop; 659end$$; 660NOTICE: succeeded at "a" 661NOTICE: succeeded at "a" 662ERROR: value for domain ordered_texts violates check constraint "ordered_texts_check" 663CONTEXT: PL/pgSQL function inline_code_block line 4 at FOR over SELECT rows 664do $$ 665declare r record; d ordered_texts; 666begin 667 for r in select * from sometable loop 668 raise notice 'processing row %', r.id; 669 d := row(r.a, r.b); 670 end loop; 671end$$; 672NOTICE: processing row 1 673NOTICE: processing row 2 674NOTICE: processing row 3 675ERROR: value for domain ordered_texts violates check constraint "ordered_texts_check" 676CONTEXT: PL/pgSQL function inline_code_block line 6 at assignment 677do $$ 678declare r record; d ordered_texts; 679begin 680 for r in select * from sometable loop 681 raise notice 'processing row %', r.id; 682 d := null; 683 d.f1 := r.a; 684 d.f2 := r.b; 685 end loop; 686end$$; 687NOTICE: processing row 1 688NOTICE: processing row 2 689NOTICE: processing row 3 690ERROR: value for domain ordered_texts violates check constraint "ordered_texts_check" 691CONTEXT: PL/pgSQL function inline_code_block line 8 at assignment 692-- check coercion of a record result to named-composite function output type 693create function compresult(int8) returns two_int8s language plpgsql as 694$$ declare r record; begin r := row($1,$1); return r; end $$; 695create table two_int8s_tab (f1 two_int8s); 696insert into two_int8s_tab values (compresult(42)); 697-- reconnect so we lose any local knowledge of anonymous record types 698\c - 699table two_int8s_tab; 700 f1 701--------- 702 (42,42) 703(1 row) 704 705