660 lines
18 KiB
Plaintext
660 lines
18 KiB
Plaintext
--
|
|
-- ROWTYPES
|
|
--
|
|
-- Make both a standalone composite type and a table rowtype
|
|
create type complex as (r float8, i float8);
|
|
create temp table fullname (first text, last text);
|
|
-- Nested composite
|
|
create type quad as (c1 complex, c2 complex);
|
|
-- Some simple tests of I/O conversions and row construction
|
|
select (1.1,2.2)::complex, row((3.3,4.4),(5.5,null))::quad;
|
|
row | row
|
|
-----------+------------------------
|
|
(1.1,2.2) | ("(3.3,4.4)","(5.5,)")
|
|
(1 row)
|
|
|
|
select row('Joe', 'Blow')::fullname, '(Joe,Blow)'::fullname;
|
|
row | fullname
|
|
------------+------------
|
|
(Joe,Blow) | (Joe,Blow)
|
|
(1 row)
|
|
|
|
select '(Joe,von Blow)'::fullname, '(Joe,d''Blow)'::fullname;
|
|
fullname | fullname
|
|
------------------+--------------
|
|
(Joe,"von Blow") | (Joe,d'Blow)
|
|
(1 row)
|
|
|
|
select '(Joe,"von""Blow")'::fullname, E'(Joe,d\\\\Blow)'::fullname;
|
|
fullname | fullname
|
|
-------------------+-----------------
|
|
(Joe,"von""Blow") | (Joe,"d\\Blow")
|
|
(1 row)
|
|
|
|
select '(Joe,"Blow,Jr")'::fullname;
|
|
fullname
|
|
-----------------
|
|
(Joe,"Blow,Jr")
|
|
(1 row)
|
|
|
|
select '(Joe,)'::fullname; -- ok, null 2nd column
|
|
fullname
|
|
----------
|
|
(Joe,)
|
|
(1 row)
|
|
|
|
select '(Joe)'::fullname; -- bad
|
|
ERROR: malformed record literal: "(Joe)"
|
|
LINE 1: select '(Joe)'::fullname;
|
|
^
|
|
DETAIL: Too few columns.
|
|
select '(Joe,,)'::fullname; -- bad
|
|
ERROR: malformed record literal: "(Joe,,)"
|
|
LINE 1: select '(Joe,,)'::fullname;
|
|
^
|
|
DETAIL: Too many columns.
|
|
create temp table quadtable(f1 int, q quad);
|
|
insert into quadtable values (1, ((3.3,4.4),(5.5,6.6)));
|
|
insert into quadtable values (2, ((null,4.4),(5.5,6.6)));
|
|
select * from quadtable;
|
|
f1 | q
|
|
----+---------------------------
|
|
1 | ("(3.3,4.4)","(5.5,6.6)")
|
|
2 | ("(,4.4)","(5.5,6.6)")
|
|
(2 rows)
|
|
|
|
select f1, q.c1 from quadtable; -- fails, q is a table reference
|
|
ERROR: missing FROM-clause entry for table "q"
|
|
LINE 1: select f1, q.c1 from quadtable;
|
|
^
|
|
select f1, (q).c1, (qq.q).c1.i from quadtable qq;
|
|
f1 | c1 | i
|
|
----+-----------+-----
|
|
1 | (3.3,4.4) | 4.4
|
|
2 | (,4.4) | 4.4
|
|
(2 rows)
|
|
|
|
create temp table people (fn fullname, bd date);
|
|
insert into people values ('(Joe,Blow)', '1984-01-10');
|
|
select * from people;
|
|
fn | bd
|
|
------------+------------
|
|
(Joe,Blow) | 01-10-1984
|
|
(1 row)
|
|
|
|
-- at the moment this will not work due to ALTER TABLE inadequacy:
|
|
alter table fullname add column suffix text default '';
|
|
ERROR: cannot alter table "fullname" because column "people.fn" uses its row type
|
|
-- but this should work:
|
|
alter table fullname add column suffix text default null;
|
|
select * from people;
|
|
fn | bd
|
|
-------------+------------
|
|
(Joe,Blow,) | 01-10-1984
|
|
(1 row)
|
|
|
|
-- test insertion/updating of subfields
|
|
update people set fn.suffix = 'Jr';
|
|
select * from people;
|
|
fn | bd
|
|
---------------+------------
|
|
(Joe,Blow,Jr) | 01-10-1984
|
|
(1 row)
|
|
|
|
insert into quadtable (f1, q.c1.r, q.c2.i) values(44,55,66);
|
|
select * from quadtable;
|
|
f1 | q
|
|
----+---------------------------
|
|
1 | ("(3.3,4.4)","(5.5,6.6)")
|
|
2 | ("(,4.4)","(5.5,6.6)")
|
|
44 | ("(55,)","(,66)")
|
|
(3 rows)
|
|
|
|
-- The object here is to ensure that toasted references inside
|
|
-- composite values don't cause problems. The large f1 value will
|
|
-- be toasted inside pp, it must still work after being copied to people.
|
|
create temp table pp (f1 text);
|
|
insert into pp values (repeat('abcdefghijkl', 100000));
|
|
insert into people select ('Jim', f1, null)::fullname, current_date from pp;
|
|
select (fn).first, substr((fn).last, 1, 20), length((fn).last) from people;
|
|
first | substr | length
|
|
-------+----------------------+---------
|
|
Joe | Blow | 4
|
|
Jim | abcdefghijklabcdefgh | 1200000
|
|
(2 rows)
|
|
|
|
-- Test row comparison semantics. Prior to PG 8.2 we did this in a totally
|
|
-- non-spec-compliant way.
|
|
select ROW(1,2) < ROW(1,3) as true;
|
|
true
|
|
------
|
|
t
|
|
(1 row)
|
|
|
|
select ROW(1,2) < ROW(1,1) as false;
|
|
false
|
|
-------
|
|
f
|
|
(1 row)
|
|
|
|
select ROW(1,2) < ROW(1,NULL) as null;
|
|
null
|
|
------
|
|
|
|
(1 row)
|
|
|
|
select ROW(1,2,3) < ROW(1,3,NULL) as true; -- the NULL is not examined
|
|
true
|
|
------
|
|
t
|
|
(1 row)
|
|
|
|
select ROW(11,'ABC') < ROW(11,'DEF') as true;
|
|
true
|
|
------
|
|
t
|
|
(1 row)
|
|
|
|
select ROW(11,'ABC') > ROW(11,'DEF') as false;
|
|
false
|
|
-------
|
|
f
|
|
(1 row)
|
|
|
|
select ROW(12,'ABC') > ROW(11,'DEF') as true;
|
|
true
|
|
------
|
|
t
|
|
(1 row)
|
|
|
|
-- = and <> have different NULL-behavior than < etc
|
|
select ROW(1,2,3) < ROW(1,NULL,4) as null;
|
|
null
|
|
------
|
|
|
|
(1 row)
|
|
|
|
select ROW(1,2,3) = ROW(1,NULL,4) as false;
|
|
false
|
|
-------
|
|
f
|
|
(1 row)
|
|
|
|
select ROW(1,2,3) <> ROW(1,NULL,4) as true;
|
|
true
|
|
------
|
|
t
|
|
(1 row)
|
|
|
|
-- We allow operators beyond the six standard ones, if they have btree
|
|
-- operator classes.
|
|
select ROW('ABC','DEF') ~<=~ ROW('DEF','ABC') as true;
|
|
true
|
|
------
|
|
t
|
|
(1 row)
|
|
|
|
select ROW('ABC','DEF') ~>=~ ROW('DEF','ABC') as false;
|
|
false
|
|
-------
|
|
f
|
|
(1 row)
|
|
|
|
select ROW('ABC','DEF') ~~ ROW('DEF','ABC') as fail;
|
|
ERROR: could not determine interpretation of row comparison operator ~~
|
|
LINE 1: select ROW('ABC','DEF') ~~ ROW('DEF','ABC') as fail;
|
|
^
|
|
HINT: Row comparison operators must be associated with btree operator families.
|
|
-- Comparisons of ROW() expressions can cope with some type mismatches
|
|
select ROW(1,2) = ROW(1,2::int8);
|
|
?column?
|
|
----------
|
|
t
|
|
(1 row)
|
|
|
|
select ROW(1,2) in (ROW(3,4), ROW(1,2));
|
|
?column?
|
|
----------
|
|
t
|
|
(1 row)
|
|
|
|
select ROW(1,2) in (ROW(3,4), ROW(1,2::int8));
|
|
?column?
|
|
----------
|
|
t
|
|
(1 row)
|
|
|
|
-- Check row comparison with a subselect
|
|
select unique1, unique2 from tenk1
|
|
where (unique1, unique2) < any (select ten, ten from tenk1 where hundred < 3)
|
|
and unique1 <= 20
|
|
order by 1;
|
|
unique1 | unique2
|
|
---------+---------
|
|
0 | 9998
|
|
1 | 2838
|
|
(2 rows)
|
|
|
|
-- Also check row comparison with an indexable condition
|
|
explain (costs off)
|
|
select thousand, tenthous from tenk1
|
|
where (thousand, tenthous) >= (997, 5000)
|
|
order by thousand, tenthous;
|
|
QUERY PLAN
|
|
-----------------------------------------------------------
|
|
Index Only Scan using tenk1_thous_tenthous on tenk1
|
|
Index Cond: (ROW(thousand, tenthous) >= ROW(997, 5000))
|
|
(2 rows)
|
|
|
|
select thousand, tenthous from tenk1
|
|
where (thousand, tenthous) >= (997, 5000)
|
|
order by thousand, tenthous;
|
|
thousand | tenthous
|
|
----------+----------
|
|
997 | 5997
|
|
997 | 6997
|
|
997 | 7997
|
|
997 | 8997
|
|
997 | 9997
|
|
998 | 998
|
|
998 | 1998
|
|
998 | 2998
|
|
998 | 3998
|
|
998 | 4998
|
|
998 | 5998
|
|
998 | 6998
|
|
998 | 7998
|
|
998 | 8998
|
|
998 | 9998
|
|
999 | 999
|
|
999 | 1999
|
|
999 | 2999
|
|
999 | 3999
|
|
999 | 4999
|
|
999 | 5999
|
|
999 | 6999
|
|
999 | 7999
|
|
999 | 8999
|
|
999 | 9999
|
|
(25 rows)
|
|
|
|
-- Test case for bug #14010: indexed row comparisons fail with nulls
|
|
create temp table test_table (a text, b text);
|
|
insert into test_table values ('a', 'b');
|
|
insert into test_table select 'a', null from generate_series(1,1000);
|
|
insert into test_table values ('b', 'a');
|
|
create index on test_table (a,b);
|
|
set enable_sort = off;
|
|
explain (costs off)
|
|
select a,b from test_table where (a,b) > ('a','a') order by a,b;
|
|
QUERY PLAN
|
|
--------------------------------------------------------
|
|
Index Only Scan using test_table_a_b_idx on test_table
|
|
Index Cond: (ROW(a, b) > ROW('a'::text, 'a'::text))
|
|
(2 rows)
|
|
|
|
select a,b from test_table where (a,b) > ('a','a') order by a,b;
|
|
a | b
|
|
---+---
|
|
a | b
|
|
b | a
|
|
(2 rows)
|
|
|
|
reset enable_sort;
|
|
-- Check row comparisons with IN
|
|
select * from int8_tbl i8 where i8 in (row(123,456)); -- fail, type mismatch
|
|
ERROR: cannot compare dissimilar column types bigint and integer at record column 1
|
|
explain (costs off)
|
|
select * from int8_tbl i8
|
|
where i8 in (row(123,456)::int8_tbl, '(4567890123456789,123)');
|
|
QUERY PLAN
|
|
-----------------------------------------------------------------------------------------------------------------
|
|
Seq Scan on int8_tbl i8
|
|
Filter: (i8.* = ANY (ARRAY[ROW('123'::bigint, '456'::bigint)::int8_tbl, '(4567890123456789,123)'::int8_tbl]))
|
|
(2 rows)
|
|
|
|
select * from int8_tbl i8
|
|
where i8 in (row(123,456)::int8_tbl, '(4567890123456789,123)');
|
|
q1 | q2
|
|
------------------+-----
|
|
123 | 456
|
|
4567890123456789 | 123
|
|
(2 rows)
|
|
|
|
-- Check some corner cases involving empty rowtypes
|
|
select ROW();
|
|
row
|
|
-----
|
|
()
|
|
(1 row)
|
|
|
|
select ROW() IS NULL;
|
|
?column?
|
|
----------
|
|
t
|
|
(1 row)
|
|
|
|
select ROW() = ROW();
|
|
ERROR: cannot compare rows of zero length
|
|
LINE 1: select ROW() = ROW();
|
|
^
|
|
-- Check ability to create arrays of anonymous rowtypes
|
|
select array[ row(1,2), row(3,4), row(5,6) ];
|
|
array
|
|
---------------------------
|
|
{"(1,2)","(3,4)","(5,6)"}
|
|
(1 row)
|
|
|
|
-- Check ability to compare an anonymous row to elements of an array
|
|
select row(1,1.1) = any (array[ row(7,7.7), row(1,1.1), row(0,0.0) ]);
|
|
?column?
|
|
----------
|
|
t
|
|
(1 row)
|
|
|
|
select row(1,1.1) = any (array[ row(7,7.7), row(1,1.0), row(0,0.0) ]);
|
|
?column?
|
|
----------
|
|
f
|
|
(1 row)
|
|
|
|
-- Check behavior with a non-comparable rowtype
|
|
create type cantcompare as (p point, r float8);
|
|
create temp table cc (f1 cantcompare);
|
|
insert into cc values('("(1,2)",3)');
|
|
insert into cc values('("(4,5)",6)');
|
|
select * from cc order by f1; -- fail, but should complain about cantcompare
|
|
ERROR: could not identify an ordering operator for type cantcompare
|
|
LINE 1: select * from cc order by f1;
|
|
^
|
|
HINT: Use an explicit ordering operator or modify the query.
|
|
--
|
|
-- Test case derived from bug #5716: check multiple uses of a rowtype result
|
|
--
|
|
BEGIN;
|
|
CREATE TABLE price (
|
|
id SERIAL PRIMARY KEY,
|
|
active BOOLEAN NOT NULL,
|
|
price NUMERIC
|
|
);
|
|
CREATE TYPE price_input AS (
|
|
id INTEGER,
|
|
price NUMERIC
|
|
);
|
|
CREATE TYPE price_key AS (
|
|
id INTEGER
|
|
);
|
|
CREATE FUNCTION price_key_from_table(price) RETURNS price_key AS $$
|
|
SELECT $1.id
|
|
$$ LANGUAGE SQL;
|
|
CREATE FUNCTION price_key_from_input(price_input) RETURNS price_key AS $$
|
|
SELECT $1.id
|
|
$$ LANGUAGE SQL;
|
|
insert into price values (1,false,42), (10,false,100), (11,true,17.99);
|
|
UPDATE price
|
|
SET active = true, price = input_prices.price
|
|
FROM unnest(ARRAY[(10, 123.00), (11, 99.99)]::price_input[]) input_prices
|
|
WHERE price_key_from_table(price.*) = price_key_from_input(input_prices.*);
|
|
select * from price;
|
|
id | active | price
|
|
----+--------+--------
|
|
1 | f | 42
|
|
10 | t | 123.00
|
|
11 | t | 99.99
|
|
(3 rows)
|
|
|
|
rollback;
|
|
--
|
|
-- Test case derived from bug #9085: check * qualification of composite
|
|
-- parameters for SQL functions
|
|
--
|
|
create temp table compos (f1 int, f2 text);
|
|
create function fcompos1(v compos) returns void as $$
|
|
insert into compos values (v); -- fail
|
|
$$ language sql;
|
|
ERROR: column "f1" is of type integer but expression is of type compos
|
|
LINE 2: insert into compos values (v); -- fail
|
|
^
|
|
HINT: You will need to rewrite or cast the expression.
|
|
create function fcompos1(v compos) returns void as $$
|
|
insert into compos values (v.*);
|
|
$$ language sql;
|
|
create function fcompos2(v compos) returns void as $$
|
|
select fcompos1(v);
|
|
$$ language sql;
|
|
create function fcompos3(v compos) returns void as $$
|
|
select fcompos1(fcompos3.v.*);
|
|
$$ language sql;
|
|
select fcompos1(row(1,'one'));
|
|
fcompos1
|
|
----------
|
|
|
|
(1 row)
|
|
|
|
select fcompos2(row(2,'two'));
|
|
fcompos2
|
|
----------
|
|
|
|
(1 row)
|
|
|
|
select fcompos3(row(3,'three'));
|
|
fcompos3
|
|
----------
|
|
|
|
(1 row)
|
|
|
|
select * from compos;
|
|
f1 | f2
|
|
----+-------
|
|
1 | one
|
|
2 | two
|
|
3 | three
|
|
(3 rows)
|
|
|
|
--
|
|
-- We allow I/O conversion casts from composite types to strings to be
|
|
-- invoked via cast syntax, but not functional syntax. This is because
|
|
-- the latter is too prone to be invoked unintentionally.
|
|
--
|
|
select cast (fullname as text) from fullname;
|
|
fullname
|
|
----------
|
|
(0 rows)
|
|
|
|
select fullname::text from fullname;
|
|
fullname
|
|
----------
|
|
(0 rows)
|
|
|
|
select text(fullname) from fullname; -- error
|
|
ERROR: function text(fullname) does not exist
|
|
LINE 1: select text(fullname) from fullname;
|
|
^
|
|
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
|
|
select fullname.text from fullname; -- error
|
|
ERROR: column fullname.text does not exist
|
|
LINE 1: select fullname.text from fullname;
|
|
^
|
|
-- same, but RECORD instead of named composite type:
|
|
select cast (row('Jim', 'Beam') as text);
|
|
row
|
|
------------
|
|
(Jim,Beam)
|
|
(1 row)
|
|
|
|
select (row('Jim', 'Beam'))::text;
|
|
row
|
|
------------
|
|
(Jim,Beam)
|
|
(1 row)
|
|
|
|
select text(row('Jim', 'Beam')); -- error
|
|
ERROR: function text(record) does not exist
|
|
LINE 1: select text(row('Jim', 'Beam'));
|
|
^
|
|
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
|
|
select (row('Jim', 'Beam')).text; -- error
|
|
ERROR: could not identify column "text" in record data type
|
|
LINE 1: select (row('Jim', 'Beam')).text;
|
|
^
|
|
--
|
|
-- Test that composite values are seen to have the correct column names
|
|
-- (bug #11210 and other reports)
|
|
--
|
|
select row_to_json(i) from int8_tbl i;
|
|
row_to_json
|
|
------------------------------------------------
|
|
{"q1":123,"q2":456}
|
|
{"q1":123,"q2":4567890123456789}
|
|
{"q1":4567890123456789,"q2":123}
|
|
{"q1":4567890123456789,"q2":4567890123456789}
|
|
{"q1":4567890123456789,"q2":-4567890123456789}
|
|
(5 rows)
|
|
|
|
select row_to_json(i) from int8_tbl i(x,y);
|
|
row_to_json
|
|
----------------------------------------------
|
|
{"x":123,"y":456}
|
|
{"x":123,"y":4567890123456789}
|
|
{"x":4567890123456789,"y":123}
|
|
{"x":4567890123456789,"y":4567890123456789}
|
|
{"x":4567890123456789,"y":-4567890123456789}
|
|
(5 rows)
|
|
|
|
create temp view vv1 as select * from int8_tbl;
|
|
select row_to_json(i) from vv1 i;
|
|
row_to_json
|
|
------------------------------------------------
|
|
{"q1":123,"q2":456}
|
|
{"q1":123,"q2":4567890123456789}
|
|
{"q1":4567890123456789,"q2":123}
|
|
{"q1":4567890123456789,"q2":4567890123456789}
|
|
{"q1":4567890123456789,"q2":-4567890123456789}
|
|
(5 rows)
|
|
|
|
select row_to_json(i) from vv1 i(x,y);
|
|
row_to_json
|
|
----------------------------------------------
|
|
{"x":123,"y":456}
|
|
{"x":123,"y":4567890123456789}
|
|
{"x":4567890123456789,"y":123}
|
|
{"x":4567890123456789,"y":4567890123456789}
|
|
{"x":4567890123456789,"y":-4567890123456789}
|
|
(5 rows)
|
|
|
|
select row_to_json(ss) from
|
|
(select q1, q2 from int8_tbl) as ss;
|
|
row_to_json
|
|
------------------------------------------------
|
|
{"q1":123,"q2":456}
|
|
{"q1":123,"q2":4567890123456789}
|
|
{"q1":4567890123456789,"q2":123}
|
|
{"q1":4567890123456789,"q2":4567890123456789}
|
|
{"q1":4567890123456789,"q2":-4567890123456789}
|
|
(5 rows)
|
|
|
|
select row_to_json(ss) from
|
|
(select q1, q2 from int8_tbl offset 0) as ss;
|
|
row_to_json
|
|
------------------------------------------------
|
|
{"q1":123,"q2":456}
|
|
{"q1":123,"q2":4567890123456789}
|
|
{"q1":4567890123456789,"q2":123}
|
|
{"q1":4567890123456789,"q2":4567890123456789}
|
|
{"q1":4567890123456789,"q2":-4567890123456789}
|
|
(5 rows)
|
|
|
|
select row_to_json(ss) from
|
|
(select q1 as a, q2 as b from int8_tbl) as ss;
|
|
row_to_json
|
|
----------------------------------------------
|
|
{"a":123,"b":456}
|
|
{"a":123,"b":4567890123456789}
|
|
{"a":4567890123456789,"b":123}
|
|
{"a":4567890123456789,"b":4567890123456789}
|
|
{"a":4567890123456789,"b":-4567890123456789}
|
|
(5 rows)
|
|
|
|
select row_to_json(ss) from
|
|
(select q1 as a, q2 as b from int8_tbl offset 0) as ss;
|
|
row_to_json
|
|
----------------------------------------------
|
|
{"a":123,"b":456}
|
|
{"a":123,"b":4567890123456789}
|
|
{"a":4567890123456789,"b":123}
|
|
{"a":4567890123456789,"b":4567890123456789}
|
|
{"a":4567890123456789,"b":-4567890123456789}
|
|
(5 rows)
|
|
|
|
select row_to_json(ss) from
|
|
(select q1 as a, q2 as b from int8_tbl) as ss(x,y);
|
|
row_to_json
|
|
----------------------------------------------
|
|
{"x":123,"y":456}
|
|
{"x":123,"y":4567890123456789}
|
|
{"x":4567890123456789,"y":123}
|
|
{"x":4567890123456789,"y":4567890123456789}
|
|
{"x":4567890123456789,"y":-4567890123456789}
|
|
(5 rows)
|
|
|
|
select row_to_json(ss) from
|
|
(select q1 as a, q2 as b from int8_tbl offset 0) as ss(x,y);
|
|
row_to_json
|
|
----------------------------------------------
|
|
{"x":123,"y":456}
|
|
{"x":123,"y":4567890123456789}
|
|
{"x":4567890123456789,"y":123}
|
|
{"x":4567890123456789,"y":4567890123456789}
|
|
{"x":4567890123456789,"y":-4567890123456789}
|
|
(5 rows)
|
|
|
|
explain (costs off)
|
|
select row_to_json(q) from
|
|
(select thousand, tenthous from tenk1
|
|
where thousand = 42 and tenthous < 2000 offset 0) q;
|
|
QUERY PLAN
|
|
-------------------------------------------------------------
|
|
Subquery Scan on q
|
|
-> Index Only Scan using tenk1_thous_tenthous on tenk1
|
|
Index Cond: ((thousand = 42) AND (tenthous < 2000))
|
|
(3 rows)
|
|
|
|
select row_to_json(q) from
|
|
(select thousand, tenthous from tenk1
|
|
where thousand = 42 and tenthous < 2000 offset 0) q;
|
|
row_to_json
|
|
---------------------------------
|
|
{"thousand":42,"tenthous":42}
|
|
{"thousand":42,"tenthous":1042}
|
|
(2 rows)
|
|
|
|
select row_to_json(q) from
|
|
(select thousand as x, tenthous as y from tenk1
|
|
where thousand = 42 and tenthous < 2000 offset 0) q;
|
|
row_to_json
|
|
-------------------
|
|
{"x":42,"y":42}
|
|
{"x":42,"y":1042}
|
|
(2 rows)
|
|
|
|
select row_to_json(q) from
|
|
(select thousand as x, tenthous as y from tenk1
|
|
where thousand = 42 and tenthous < 2000 offset 0) q(a,b);
|
|
row_to_json
|
|
-------------------
|
|
{"a":42,"b":42}
|
|
{"a":42,"b":1042}
|
|
(2 rows)
|
|
|
|
create temp table tt1 as select * from int8_tbl limit 2;
|
|
create temp table tt2 () inherits(tt1);
|
|
insert into tt2 values(0,0);
|
|
select row_to_json(r) from (select q2,q1 from tt1 offset 0) r;
|
|
row_to_json
|
|
----------------------------------
|
|
{"q2":456,"q1":123}
|
|
{"q2":4567890123456789,"q1":123}
|
|
{"q2":0,"q1":0}
|
|
(3 rows)
|
|
|