4 -- Make both a standalone composite type and a table rowtype
5 create type complex as (r float8, i float8);
6 create temp table fullname (first text, last text);
8 create type quad as (c1 complex, c2 complex);
9 -- Some simple tests of I/O conversions and row construction
10 select (1.1,2.2)::complex, row((3.3,4.4),(5.5,null))::quad;
12 -----------+------------------------
13 (1.1,2.2) | ("(3.3,4.4)","(5.5,)")
16 select row('Joe', 'Blow')::fullname, '(Joe,Blow)'::fullname;
18 ------------+------------
19 (Joe,Blow) | (Joe,Blow)
22 select '(Joe,von Blow)'::fullname, '(Joe,d''Blow)'::fullname;
24 ------------------+--------------
25 (Joe,"von Blow") | (Joe,d'Blow)
28 select '(Joe,"von""Blow")'::fullname, E'(Joe,d\\\\Blow)'::fullname;
30 -------------------+-----------------
31 (Joe,"von""Blow") | (Joe,"d\\Blow")
34 select '(Joe,"Blow,Jr")'::fullname;
40 select '(Joe,)'::fullname; -- ok, null 2nd column
46 select '(Joe)'::fullname; -- bad
47 ERROR: malformed record literal: "(Joe)"
48 LINE 1: select '(Joe)'::fullname;
50 DETAIL: Too few columns.
51 select '(Joe,,)'::fullname; -- bad
52 ERROR: malformed record literal: "(Joe,,)"
53 LINE 1: select '(Joe,,)'::fullname;
55 DETAIL: Too many columns.
56 select '[]'::fullname; -- bad
57 ERROR: malformed record literal: "[]"
58 LINE 1: select '[]'::fullname;
60 DETAIL: Missing left parenthesis.
61 select ' (Joe,Blow) '::fullname; -- ok, extra whitespace
67 select '(Joe,Blow) /'::fullname; -- bad
68 ERROR: malformed record literal: "(Joe,Blow) /"
69 LINE 1: select '(Joe,Blow) /'::fullname;
71 DETAIL: Junk after right parenthesis.
72 create temp table quadtable(f1 int, q quad);
73 insert into quadtable values (1, ((3.3,4.4),(5.5,6.6)));
74 insert into quadtable values (2, ((null,4.4),(5.5,6.6)));
75 select * from quadtable;
77 ----+---------------------------
78 1 | ("(3.3,4.4)","(5.5,6.6)")
79 2 | ("(,4.4)","(5.5,6.6)")
82 select f1, q.c1 from quadtable; -- fails, q is a table reference
83 ERROR: missing FROM-clause entry for table "q"
84 LINE 1: select f1, q.c1 from quadtable;
86 select f1, (q).c1, (qq.q).c1.i from quadtable qq;
88 ----+-----------+-----
93 create temp table people (fn fullname, bd date);
94 insert into people values ('(Joe,Blow)', '1984-01-10');
97 ------------+------------
98 (Joe,Blow) | 01-10-1984
101 -- at the moment this will not work due to ALTER TABLE inadequacy:
102 alter table fullname add column suffix text default '';
103 ERROR: cannot alter table "fullname" because column "people.fn" uses its row type
104 -- but this should work:
105 alter table fullname add column suffix text default null;
106 select * from people;
108 -------------+------------
109 (Joe,Blow,) | 01-10-1984
112 -- test insertion/updating of subfields
113 update people set fn.suffix = 'Jr';
114 select * from people;
116 ---------------+------------
117 (Joe,Blow,Jr) | 01-10-1984
120 insert into quadtable (f1, q.c1.r, q.c2.i) values(44,55,66);
121 update quadtable set q.c1.r = 12 where f1 = 2;
122 update quadtable set q.c1 = 12; -- error, type mismatch
123 ERROR: subfield "c1" is of type complex but expression is of type integer
124 LINE 1: update quadtable set q.c1 = 12;
126 HINT: You will need to rewrite or cast the expression.
127 select * from quadtable;
129 ----+---------------------------
130 1 | ("(3.3,4.4)","(5.5,6.6)")
131 44 | ("(55,)","(,66)")
132 2 | ("(12,4.4)","(5.5,6.6)")
135 -- The object here is to ensure that toasted references inside
136 -- composite values don't cause problems. The large f1 value will
137 -- be toasted inside pp, it must still work after being copied to people.
138 create temp table pp (f1 text);
139 insert into pp values (repeat('abcdefghijkl', 100000));
140 insert into people select ('Jim', f1, null)::fullname, current_date from pp;
141 select (fn).first, substr((fn).last, 1, 20), length((fn).last) from people;
142 first | substr | length
143 -------+----------------------+---------
145 Jim | abcdefghijklabcdefgh | 1200000
148 -- Test row comparison semantics. Prior to PG 8.2 we did this in a totally
149 -- non-spec-compliant way.
150 select ROW(1,2) < ROW(1,3) as true;
156 select ROW(1,2) < ROW(1,1) as false;
162 select ROW(1,2) < ROW(1,NULL) as null;
168 select ROW(1,2,3) < ROW(1,3,NULL) as true; -- the NULL is not examined
174 select ROW(11,'ABC') < ROW(11,'DEF') as true;
180 select ROW(11,'ABC') > ROW(11,'DEF') as false;
186 select ROW(12,'ABC') > ROW(11,'DEF') as true;
192 -- = and <> have different NULL-behavior than < etc
193 select ROW(1,2,3) < ROW(1,NULL,4) as null;
199 select ROW(1,2,3) = ROW(1,NULL,4) as false;
205 select ROW(1,2,3) <> ROW(1,NULL,4) as true;
211 -- We allow operators beyond the six standard ones, if they have btree
213 select ROW('ABC','DEF') ~<=~ ROW('DEF','ABC') as true;
219 select ROW('ABC','DEF') ~>=~ ROW('DEF','ABC') as false;
225 select ROW('ABC','DEF') ~~ ROW('DEF','ABC') as fail;
226 ERROR: could not determine interpretation of row comparison operator ~~
227 LINE 1: select ROW('ABC','DEF') ~~ ROW('DEF','ABC') as fail;
229 HINT: Row comparison operators must be associated with btree operator families.
230 -- Comparisons of ROW() expressions can cope with some type mismatches
231 select ROW(1,2) = ROW(1,2::int8);
237 select ROW(1,2) in (ROW(3,4), ROW(1,2));
243 select ROW(1,2) in (ROW(3,4), ROW(1,2::int8));
249 -- Check row comparison with a subselect
250 select unique1, unique2 from tenk1
251 where (unique1, unique2) < any (select ten, ten from tenk1 where hundred < 3)
260 -- Also check row comparison with an indexable condition
262 select thousand, tenthous from tenk1
263 where (thousand, tenthous) >= (997, 5000)
264 order by thousand, tenthous;
266 -----------------------------------------------------------
267 Index Only Scan using tenk1_thous_tenthous on tenk1
268 Index Cond: (ROW(thousand, tenthous) >= ROW(997, 5000))
271 select thousand, tenthous from tenk1
272 where (thousand, tenthous) >= (997, 5000)
273 order by thousand, tenthous;
275 ----------+----------
304 select thousand, tenthous, four from tenk1
305 where (thousand, tenthous, four) > (998, 5000, 3)
306 order by thousand, tenthous;
308 -----------------------------------------------------------------------
310 Sort Key: thousand, tenthous
311 -> Bitmap Heap Scan on tenk1
312 Filter: (ROW(thousand, tenthous, four) > ROW(998, 5000, 3))
313 -> Bitmap Index Scan on tenk1_thous_tenthous
314 Index Cond: (ROW(thousand, tenthous) >= ROW(998, 5000))
317 select thousand, tenthous, four from tenk1
318 where (thousand, tenthous, four) > (998, 5000, 3)
319 order by thousand, tenthous;
320 thousand | tenthous | four
321 ----------+----------+------
340 select thousand, tenthous from tenk1
341 where (998, 5000) < (thousand, tenthous)
342 order by thousand, tenthous;
344 ----------------------------------------------------------
345 Index Only Scan using tenk1_thous_tenthous on tenk1
346 Index Cond: (ROW(thousand, tenthous) > ROW(998, 5000))
349 select thousand, tenthous from tenk1
350 where (998, 5000) < (thousand, tenthous)
351 order by thousand, tenthous;
353 ----------+----------
372 select thousand, hundred from tenk1
373 where (998, 5000) < (thousand, hundred)
374 order by thousand, hundred;
376 -----------------------------------------------------------
378 Sort Key: thousand, hundred
379 -> Bitmap Heap Scan on tenk1
380 Filter: (ROW(998, 5000) < ROW(thousand, hundred))
381 -> Bitmap Index Scan on tenk1_thous_tenthous
382 Index Cond: (thousand >= 998)
385 select thousand, hundred from tenk1
386 where (998, 5000) < (thousand, hundred)
387 order by thousand, hundred;
402 -- Test case for bug #14010: indexed row comparisons fail with nulls
403 create temp table test_table (a text, b text);
404 insert into test_table values ('a', 'b');
405 insert into test_table select 'a', null from generate_series(1,1000);
406 insert into test_table values ('b', 'a');
407 create index on test_table (a,b);
408 set enable_sort = off;
410 select a,b from test_table where (a,b) > ('a','a') order by a,b;
412 --------------------------------------------------------
413 Index Only Scan using test_table_a_b_idx on test_table
414 Index Cond: (ROW(a, b) > ROW('a'::text, 'a'::text))
417 select a,b from test_table where (a,b) > ('a','a') order by a,b;
425 -- Check row comparisons with IN
426 select * from int8_tbl i8 where i8 in (row(123,456)); -- fail, type mismatch
427 ERROR: cannot compare dissimilar column types bigint and integer at record column 1
429 select * from int8_tbl i8
430 where i8 in (row(123,456)::int8_tbl, '(4567890123456789,123)');
432 -------------------------------------------------------------------------------
433 Seq Scan on int8_tbl i8
434 Filter: (i8.* = ANY ('{"(123,456)","(4567890123456789,123)"}'::int8_tbl[]))
437 select * from int8_tbl i8
438 where i8 in (row(123,456)::int8_tbl, '(4567890123456789,123)');
440 ------------------+-----
442 4567890123456789 | 123
445 -- Check ability to select columns from an anonymous rowtype
446 select (row(1, 2.0)).f1;
452 select (row(1, 2.0)).f2;
458 select (row(1, 2.0)).nosuch; -- fail
459 ERROR: could not identify column "nosuch" in record data type
460 LINE 1: select (row(1, 2.0)).nosuch;
462 select (row(1, 2.0)).*;
468 select (r).f1 from (select row(1, 2.0) as r) ss;
474 select (r).f3 from (select row(1, 2.0) as r) ss; -- fail
475 ERROR: could not identify column "f3" in record data type
476 LINE 1: select (r).f3 from (select row(1, 2.0) as r) ss;
478 select (r).* from (select row(1, 2.0) as r) ss;
484 -- Check some corner cases involving empty rowtypes
491 select ROW() IS NULL;
497 select ROW() = ROW();
498 ERROR: cannot compare rows of zero length
499 LINE 1: select ROW() = ROW();
501 -- Check ability to create arrays of anonymous rowtypes
502 select array[ row(1,2), row(3,4), row(5,6) ];
504 ---------------------------
505 {"(1,2)","(3,4)","(5,6)"}
508 -- Check ability to compare an anonymous row to elements of an array
509 select row(1,1.1) = any (array[ row(7,7.7), row(1,1.1), row(0,0.0) ]);
515 select row(1,1.1) = any (array[ row(7,7.7), row(1,1.0), row(0,0.0) ]);
521 -- Check behavior with a non-comparable rowtype
522 create type cantcompare as (p point, r float8);
523 create temp table cc (f1 cantcompare);
524 insert into cc values('("(1,2)",3)');
525 insert into cc values('("(4,5)",6)');
526 select * from cc order by f1; -- fail, but should complain about cantcompare
527 ERROR: could not identify an ordering operator for type cantcompare
528 LINE 1: select * from cc order by f1;
530 HINT: Use an explicit ordering operator or modify the query.
532 -- Tests for record_{eq,cmp}
534 create type testtype1 as (a int, b int);
536 select row(1, 2)::testtype1 < row(1, 3)::testtype1;
542 select row(1, 2)::testtype1 <= row(1, 3)::testtype1;
548 select row(1, 2)::testtype1 = row(1, 2)::testtype1;
554 select row(1, 2)::testtype1 <> row(1, 3)::testtype1;
560 select row(1, 3)::testtype1 >= row(1, 2)::testtype1;
566 select row(1, 3)::testtype1 > row(1, 2)::testtype1;
573 select row(1, -2)::testtype1 < row(1, -3)::testtype1;
579 select row(1, -2)::testtype1 <= row(1, -3)::testtype1;
585 select row(1, -2)::testtype1 = row(1, -3)::testtype1;
591 select row(1, -2)::testtype1 <> row(1, -2)::testtype1;
597 select row(1, -3)::testtype1 >= row(1, -2)::testtype1;
603 select row(1, -3)::testtype1 > row(1, -2)::testtype1;
609 -- true, but see *< below
610 select row(1, -2)::testtype1 < row(1, 3)::testtype1;
617 create type testtype3 as (a int, b text);
618 select row(1, 2)::testtype1 < row(1, 'abc')::testtype3;
619 ERROR: cannot compare dissimilar column types integer and text at record column 2
620 select row(1, 2)::testtype1 <> row(1, 'abc')::testtype3;
621 ERROR: cannot compare dissimilar column types integer and text at record column 2
622 create type testtype5 as (a int);
623 select row(1, 2)::testtype1 < row(1)::testtype5;
624 ERROR: cannot compare record types with different numbers of columns
625 select row(1, 2)::testtype1 <> row(1)::testtype5;
626 ERROR: cannot compare record types with different numbers of columns
627 -- non-comparable types
628 create type testtype6 as (a int, b point);
629 select row(1, '(1,2)')::testtype6 < row(1, '(1,3)')::testtype6;
630 ERROR: could not identify a comparison function for type point
631 select row(1, '(1,2)')::testtype6 <> row(1, '(1,3)')::testtype6;
632 ERROR: could not identify an equality operator for type point
633 drop type testtype1, testtype3, testtype5, testtype6;
635 -- Tests for record_image_{eq,cmp}
637 create type testtype1 as (a int, b int);
639 select row(1, 2)::testtype1 *< row(1, 3)::testtype1;
645 select row(1, 2)::testtype1 *<= row(1, 3)::testtype1;
651 select row(1, 2)::testtype1 *= row(1, 2)::testtype1;
657 select row(1, 2)::testtype1 *<> row(1, 3)::testtype1;
663 select row(1, 3)::testtype1 *>= row(1, 2)::testtype1;
669 select row(1, 3)::testtype1 *> row(1, 2)::testtype1;
676 select row(1, -2)::testtype1 *< row(1, -3)::testtype1;
682 select row(1, -2)::testtype1 *<= row(1, -3)::testtype1;
688 select row(1, -2)::testtype1 *= row(1, -3)::testtype1;
694 select row(1, -2)::testtype1 *<> row(1, -2)::testtype1;
700 select row(1, -3)::testtype1 *>= row(1, -2)::testtype1;
706 select row(1, -3)::testtype1 *> row(1, -2)::testtype1;
712 -- This returns the "wrong" order because record_image_cmp works on
713 -- unsigned datums without knowing about the actual data type.
714 select row(1, -2)::testtype1 *< row(1, 3)::testtype1;
721 create type testtype2 as (a smallint, b bool); -- byval different sizes
722 select row(1, true)::testtype2 *< row(2, true)::testtype2;
728 select row(-2, true)::testtype2 *< row(-1, true)::testtype2;
734 select row(0, false)::testtype2 *< row(0, true)::testtype2;
740 select row(0, false)::testtype2 *<> row(0, true)::testtype2;
746 create type testtype3 as (a int, b text); -- variable length
747 select row(1, 'abc')::testtype3 *< row(1, 'abd')::testtype3;
753 select row(1, 'abc')::testtype3 *< row(1, 'abcd')::testtype3;
759 select row(1, 'abc')::testtype3 *> row(1, 'abd')::testtype3;
765 select row(1, 'abc')::testtype3 *<> row(1, 'abd')::testtype3;
771 create type testtype4 as (a int, b point); -- by ref, fixed length
772 select row(1, '(1,2)')::testtype4 *< row(1, '(1,3)')::testtype4;
778 select row(1, '(1,2)')::testtype4 *<> row(1, '(1,3)')::testtype4;
785 select row(1, 2)::testtype1 *< row(1, 'abc')::testtype3;
786 ERROR: cannot compare dissimilar column types integer and text at record column 2
787 select row(1, 2)::testtype1 *<> row(1, 'abc')::testtype3;
788 ERROR: cannot compare dissimilar column types integer and text at record column 2
789 create type testtype5 as (a int);
790 select row(1, 2)::testtype1 *< row(1)::testtype5;
791 ERROR: cannot compare record types with different numbers of columns
792 select row(1, 2)::testtype1 *<> row(1)::testtype5;
793 ERROR: cannot compare record types with different numbers of columns
794 -- non-comparable types
795 create type testtype6 as (a int, b point);
796 select row(1, '(1,2)')::testtype6 *< row(1, '(1,3)')::testtype6;
802 select row(1, '(1,2)')::testtype6 *>= row(1, '(1,3)')::testtype6;
808 select row(1, '(1,2)')::testtype6 *<> row(1, '(1,3)')::testtype6;
814 -- anonymous rowtypes in coldeflists
815 select q.a, q.b = row(2), q.c = array[row(3)], q.d = row(row(4)) from
816 unnest(array[row(1, row(2), array[row(3)], row(row(4))),
817 row(2, row(3), array[row(4)], row(row(5)))])
818 as q(a int, b record, c record[], d record);
819 a | ?column? | ?column? | ?column?
820 ---+----------+----------+----------
825 drop type testtype1, testtype2, testtype3, testtype4, testtype5, testtype6;
827 -- Test case derived from bug #5716: check multiple uses of a rowtype result
831 id SERIAL PRIMARY KEY,
832 active BOOLEAN NOT NULL,
835 CREATE TYPE price_input AS (
839 CREATE TYPE price_key AS (
842 CREATE FUNCTION price_key_from_table(price) RETURNS price_key AS $$
845 CREATE FUNCTION price_key_from_input(price_input) RETURNS price_key AS $$
848 insert into price values (1,false,42), (10,false,100), (11,true,17.99);
850 SET active = true, price = input_prices.price
851 FROM unnest(ARRAY[(10, 123.00), (11, 99.99)]::price_input[]) input_prices
852 WHERE price_key_from_table(price.*) = price_key_from_input(input_prices.*);
855 ----+--------+--------
863 -- Test case derived from bug #9085: check * qualification of composite
864 -- parameters for SQL functions
866 create temp table compos (f1 int, f2 text);
867 create function fcompos1(v compos) returns void as $$
868 insert into compos values (v); -- fail
870 ERROR: column "f1" is of type integer but expression is of type compos
871 LINE 2: insert into compos values (v); -- fail
873 HINT: You will need to rewrite or cast the expression.
874 create function fcompos1(v compos) returns void as $$
875 insert into compos values (v.*);
877 create function fcompos2(v compos) returns void as $$
880 create function fcompos3(v compos) returns void as $$
881 select fcompos1(fcompos3.v.*);
883 select fcompos1(row(1,'one'));
889 select fcompos2(row(2,'two'));
895 select fcompos3(row(3,'three'));
901 select * from compos;
910 -- We allow I/O conversion casts from composite types to strings to be
911 -- invoked via cast syntax, but not functional syntax. This is because
912 -- the latter is too prone to be invoked unintentionally.
914 select cast (fullname as text) from fullname;
919 select fullname::text from fullname;
924 select text(fullname) from fullname; -- error
925 ERROR: function text(fullname) does not exist
926 LINE 1: select text(fullname) from fullname;
928 HINT: No function matches the given name and argument types. You might need to add explicit type casts.
929 select fullname.text from fullname; -- error
930 ERROR: column fullname.text does not exist
931 LINE 1: select fullname.text from fullname;
933 -- same, but RECORD instead of named composite type:
934 select cast (row('Jim', 'Beam') as text);
940 select (row('Jim', 'Beam'))::text;
946 select text(row('Jim', 'Beam')); -- error
947 ERROR: function text(record) does not exist
948 LINE 1: select text(row('Jim', 'Beam'));
950 HINT: No function matches the given name and argument types. You might need to add explicit type casts.
951 select (row('Jim', 'Beam')).text; -- error
952 ERROR: could not identify column "text" in record data type
953 LINE 1: select (row('Jim', 'Beam')).text;
956 -- Check the equivalence of functional and column notation
958 insert into fullname values ('Joe', 'Blow');
959 select f.last from fullname f;
965 select last(f) from fullname f;
971 create function longname(fullname) returns text language sql
972 as $$select $1.first || ' ' || $1.last$$;
973 select f.longname from fullname f;
979 select longname(f) from fullname f;
985 -- Starting in v11, the notational form does matter if there's ambiguity
986 alter table fullname add column longname text;
987 select f.longname from fullname f;
993 select longname(f) from fullname f;
1000 -- Test that composite values are seen to have the correct column names
1001 -- (bug #11210 and other reports)
1003 select row_to_json(i) from int8_tbl i;
1005 ------------------------------------------------
1007 {"q1":123,"q2":4567890123456789}
1008 {"q1":4567890123456789,"q2":123}
1009 {"q1":4567890123456789,"q2":4567890123456789}
1010 {"q1":4567890123456789,"q2":-4567890123456789}
1013 select row_to_json(i) from int8_tbl i(x,y);
1015 ----------------------------------------------
1017 {"x":123,"y":4567890123456789}
1018 {"x":4567890123456789,"y":123}
1019 {"x":4567890123456789,"y":4567890123456789}
1020 {"x":4567890123456789,"y":-4567890123456789}
1023 create temp view vv1 as select * from int8_tbl;
1024 select row_to_json(i) from vv1 i;
1026 ------------------------------------------------
1028 {"q1":123,"q2":4567890123456789}
1029 {"q1":4567890123456789,"q2":123}
1030 {"q1":4567890123456789,"q2":4567890123456789}
1031 {"q1":4567890123456789,"q2":-4567890123456789}
1034 select row_to_json(i) from vv1 i(x,y);
1036 ----------------------------------------------
1038 {"x":123,"y":4567890123456789}
1039 {"x":4567890123456789,"y":123}
1040 {"x":4567890123456789,"y":4567890123456789}
1041 {"x":4567890123456789,"y":-4567890123456789}
1044 select row_to_json(ss) from
1045 (select q1, q2 from int8_tbl) as ss;
1047 ------------------------------------------------
1049 {"q1":123,"q2":4567890123456789}
1050 {"q1":4567890123456789,"q2":123}
1051 {"q1":4567890123456789,"q2":4567890123456789}
1052 {"q1":4567890123456789,"q2":-4567890123456789}
1055 select row_to_json(ss) from
1056 (select q1, q2 from int8_tbl offset 0) as ss;
1058 ------------------------------------------------
1060 {"q1":123,"q2":4567890123456789}
1061 {"q1":4567890123456789,"q2":123}
1062 {"q1":4567890123456789,"q2":4567890123456789}
1063 {"q1":4567890123456789,"q2":-4567890123456789}
1066 select row_to_json(ss) from
1067 (select q1 as a, q2 as b from int8_tbl) as ss;
1069 ----------------------------------------------
1071 {"a":123,"b":4567890123456789}
1072 {"a":4567890123456789,"b":123}
1073 {"a":4567890123456789,"b":4567890123456789}
1074 {"a":4567890123456789,"b":-4567890123456789}
1077 select row_to_json(ss) from
1078 (select q1 as a, q2 as b from int8_tbl offset 0) as ss;
1080 ----------------------------------------------
1082 {"a":123,"b":4567890123456789}
1083 {"a":4567890123456789,"b":123}
1084 {"a":4567890123456789,"b":4567890123456789}
1085 {"a":4567890123456789,"b":-4567890123456789}
1088 select row_to_json(ss) from
1089 (select q1 as a, q2 as b from int8_tbl) as ss(x,y);
1091 ----------------------------------------------
1093 {"x":123,"y":4567890123456789}
1094 {"x":4567890123456789,"y":123}
1095 {"x":4567890123456789,"y":4567890123456789}
1096 {"x":4567890123456789,"y":-4567890123456789}
1099 select row_to_json(ss) from
1100 (select q1 as a, q2 as b from int8_tbl offset 0) as ss(x,y);
1102 ----------------------------------------------
1104 {"x":123,"y":4567890123456789}
1105 {"x":4567890123456789,"y":123}
1106 {"x":4567890123456789,"y":4567890123456789}
1107 {"x":4567890123456789,"y":-4567890123456789}
1111 select row_to_json(q) from
1112 (select thousand, tenthous from tenk1
1113 where thousand = 42 and tenthous < 2000 offset 0) q;
1115 -------------------------------------------------------------
1117 -> Index Only Scan using tenk1_thous_tenthous on tenk1
1118 Index Cond: ((thousand = 42) AND (tenthous < 2000))
1121 select row_to_json(q) from
1122 (select thousand, tenthous from tenk1
1123 where thousand = 42 and tenthous < 2000 offset 0) q;
1125 ---------------------------------
1126 {"thousand":42,"tenthous":42}
1127 {"thousand":42,"tenthous":1042}
1130 select row_to_json(q) from
1131 (select thousand as x, tenthous as y from tenk1
1132 where thousand = 42 and tenthous < 2000 offset 0) q;
1139 select row_to_json(q) from
1140 (select thousand as x, tenthous as y from tenk1
1141 where thousand = 42 and tenthous < 2000 offset 0) q(a,b);
1148 create temp table tt1 as select * from int8_tbl limit 2;
1149 create temp table tt2 () inherits(tt1);
1150 insert into tt2 values(0,0);
1151 select row_to_json(r) from (select q2,q1 from tt1 offset 0) r;
1153 ----------------------------------
1155 {"q2":4567890123456789,"q1":123}
1159 -- check no-op rowtype conversions
1160 create temp table tt3 () inherits(tt2);
1161 insert into tt3 values(33,44);
1162 select row_to_json(tt3::tt2::tt1) from tt3;
1169 -- IS [NOT] NULL should not recurse into nested composites (bug #14235)
1171 explain (verbose, costs off)
1172 select r, r is null as isnull, r is not null as isnotnull
1173 from (values (1,row(1,2)), (1,row(null,null)), (1,null),
1174 (null,row(1,2)), (null,row(null,null)), (null,null) ) r(a,b);
1176 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1177 Values Scan on "*VALUES*"
1178 Output: ROW("*VALUES*".column1, "*VALUES*".column2), (("*VALUES*".column1 IS NULL) AND ("*VALUES*".column2 IS NOT DISTINCT FROM NULL)), (("*VALUES*".column1 IS NOT NULL) AND ("*VALUES*".column2 IS DISTINCT FROM NULL))
1181 select r, r is null as isnull, r is not null as isnotnull
1182 from (values (1,row(1,2)), (1,row(null,null)), (1,null),
1183 (null,row(1,2)), (null,row(null,null)), (null,null) ) r(a,b);
1184 r | isnull | isnotnull
1185 -------------+--------+-----------
1194 explain (verbose, costs off)
1195 with r(a,b) as materialized
1196 (values (1,row(1,2)), (1,row(null,null)), (1,null),
1197 (null,row(1,2)), (null,row(null,null)), (null,null) )
1198 select r, r is null as isnull, r is not null as isnotnull from r;
1200 ----------------------------------------------------------
1202 Output: r.*, (r.* IS NULL), (r.* IS NOT NULL)
1204 -> Values Scan on "*VALUES*"
1205 Output: "*VALUES*".column1, "*VALUES*".column2
1208 with r(a,b) as materialized
1209 (values (1,row(1,2)), (1,row(null,null)), (1,null),
1210 (null,row(1,2)), (null,row(null,null)), (null,null) )
1211 select r, r is null as isnull, r is not null as isnotnull from r;
1212 r | isnull | isnotnull
1213 -------------+--------+-----------
1223 -- Tests for component access / FieldSelect
1225 CREATE TABLE compositetable(a text, b text);
1226 INSERT INTO compositetable(a, b) VALUES('fa', 'fb');
1227 -- composite type columns can't directly be accessed (error)
1228 SELECT d.a FROM (SELECT compositetable AS d FROM compositetable) s;
1229 ERROR: missing FROM-clause entry for table "d"
1230 LINE 1: SELECT d.a FROM (SELECT compositetable AS d FROM compositeta...
1232 -- but can be accessed with proper parens
1233 SELECT (d).a, (d).b FROM (SELECT compositetable AS d FROM compositetable) s;
1239 -- system columns can't be accessed in composite types (error)
1240 SELECT (d).ctid FROM (SELECT compositetable AS d FROM compositetable) s;
1241 ERROR: column "ctid" not found in data type compositetable
1242 LINE 1: SELECT (d).ctid FROM (SELECT compositetable AS d FROM compos...
1244 -- accessing non-existing column in NULL datum errors out
1245 SELECT (NULL::compositetable).nonexistent;
1246 ERROR: column "nonexistent" not found in data type compositetable
1247 LINE 1: SELECT (NULL::compositetable).nonexistent;
1249 -- existing column in a NULL composite yield NULL
1250 SELECT (NULL::compositetable).a;
1256 -- oids can't be accessed in composite types (error)
1257 SELECT (NULL::compositetable).oid;
1258 ERROR: column "oid" not found in data type compositetable
1259 LINE 1: SELECT (NULL::compositetable).oid;
1261 DROP TABLE compositetable;