}
else
{
+ /* this is currently unreachable */
econtext->caseValue_datum =
array_get_slice(array_source, i,
upper.indx, lower.indx,
{{5,6},{8,9}}
(1 row)
+--
+-- check subscription corner cases
+--
+-- More subscripts than MAXDIMS(6)
+SELECT ('{}'::int[])[1][2][3][4][5][6][7];
+ERROR: number of array dimensions (7) exceeds the maximum allowed (6)
+-- NULL index yields NULL when selecting
+SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][NULL][1];
+ int4
+------
+
+(1 row)
+
+SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][NULL:1][1];
+ int4
+------
+
+(1 row)
+
+SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][1:NULL][1];
+ int4
+------
+
+(1 row)
+
+-- NULL index in assignment is an error
+UPDATE arrtest
+ SET c[NULL] = '{"can''t assign"}'
+ WHERE array_dims(c) is not null;
+ERROR: array subscript in assignment must not be null
+UPDATE arrtest
+ SET c[NULL:1] = '{"can''t assign"}'
+ WHERE array_dims(c) is not null;
+ERROR: array subscript in assignment must not be null
+UPDATE arrtest
+ SET c[1:NULL] = '{"can''t assign"}'
+ WHERE array_dims(c) is not null;
+ERROR: array subscript in assignment must not be null
-- test slices with empty lower and/or upper index
CREATE TEMP TABLE arrtest_s (
a int2[],
ERROR: slices of fixed-length arrays not implemented
SELECT f1[:] FROM POINT_TBL;
ERROR: slices of fixed-length arrays not implemented
+-- subscript assignments to fixed-width result in NULL if previous value is NULL
+UPDATE point_tbl SET f1[0] = 10 WHERE f1 IS NULL RETURNING *;
+ f1
+----
+
+(1 row)
+
+INSERT INTO point_tbl(f1[0]) VALUES(0) RETURNING *;
+ f1
+----
+
+(1 row)
+
+-- NULL assignments get ignored
+UPDATE point_tbl SET f1[0] = NULL WHERE f1::text = '(10,10)'::point::text RETURNING *;
+ f1
+---------
+ (10,10)
+(1 row)
+
+-- but non-NULL subscript assignments work
+UPDATE point_tbl SET f1[0] = -10, f1[1] = -10 WHERE f1::text = '(10,10)'::point::text RETURNING *;
+ f1
+-----------
+ (-10,-10)
+(1 row)
+
+-- but not to expand the range
+UPDATE point_tbl SET f1[3] = 10 WHERE f1::text = '(-10,-10)'::point::text RETURNING *;
+ERROR: array subscript out of range
--
-- test array extension
--
{{{{{{a,bb,ccc}}}}}}
(1 row)
+SELECT NULL::text[]::int[] AS "NULL";
+ NULL
+------
+
+(1 row)
+
-- scalar op any/all (array)
select 33 = any ('{1,2,3}');
?column?
(1 row)
+-- nulls later in the bitmap
+SELECT -1 != ALL(ARRAY(SELECT NULLIF(g.i, 900) FROM generate_series(1,1000) g(i)));
+ ?column?
+----------
+
+(1 row)
+
-- test indexes on arrays
create temp table arr_tbl (f1 int[] unique);
insert into arr_tbl values ('{1,2,3}');
| f
(4 rows)
+--
+-- Tests for BooleanTest
+--
+CREATE TABLE BOOLTBL3 (d text, b bool, o int);
+INSERT INTO BOOLTBL3 (d, b, o) VALUES ('true', true, 1);
+INSERT INTO BOOLTBL3 (d, b, o) VALUES ('false', false, 2);
+INSERT INTO BOOLTBL3 (d, b, o) VALUES ('null', null, 3);
+SELECT
+ d,
+ b IS TRUE AS istrue,
+ b IS NOT TRUE AS isnottrue,
+ b IS FALSE AS isfalse,
+ b IS NOT FALSE AS isnotfalse,
+ b IS UNKNOWN AS isunknown,
+ b IS NOT UNKNOWN AS isnotunknown
+FROM booltbl3 ORDER BY o;
+ d | istrue | isnottrue | isfalse | isnotfalse | isunknown | isnotunknown
+-------+--------+-----------+---------+------------+-----------+--------------
+ true | t | f | f | t | f | t
+ false | f | t | t | f | f | t
+ null | f | t | f | t | t | f
+(3 rows)
+
--
-- Clean up
-- Many tables are retained by the regression test, but these do not seem
--
DROP TABLE BOOLTBL1;
DROP TABLE BOOLTBL2;
+DROP TABLE BOOLTBL3;
6 | 6
(1 row)
+SELECT '7' AS "None",
+ CASE WHEN random() < 0 THEN 1
+ END AS "NULL on no matches";
+ None | NULL on no matches
+------+--------------------
+ 7 |
+(1 row)
+
-- Constant-expression folding shouldn't evaluate unreachable subexpressions
SELECT CASE WHEN 1=0 THEN 1/0 WHEN 1=1 THEN 1 ELSE 2/0 END;
case
--- /dev/null
+--
+-- expression evaluated tests that don't fit into a more specific file
+--
+--
+-- Tests for SQLVAlueFunction
+--
+-- current_date (always matches because of transactional behaviour)
+SELECT date(now())::text = current_date::text;
+ ?column?
+----------
+ t
+(1 row)
+
+-- current_time / localtime
+SELECT now()::timetz::text = current_time::text;
+ ?column?
+----------
+ t
+(1 row)
+
+SELECT now()::time::text = localtime::text;
+ ?column?
+----------
+ t
+(1 row)
+
+-- current_timestamp / localtimestamp (always matches because of transactional behaviour)
+SELECT current_timestamp = NOW();
+ ?column?
+----------
+ t
+(1 row)
+
+-- precision
+SELECT length(current_timestamp::text) >= length(current_timestamp(0)::text);
+ ?column?
+----------
+ t
+(1 row)
+
+-- localtimestamp
+SELECT now()::timestamp::text = localtimestamp::text;
+ ?column?
+----------
+ t
+(1 row)
+
+-- current_role/user/user is tested in rolnames.sql
+-- current database / catalog
+SELECT current_catalog = current_database();
+ ?column?
+----------
+ t
+(1 row)
+
+-- current_schema
+SELECT current_schema;
+ current_schema
+----------------
+ public
+(1 row)
+
+SET search_path = 'notme';
+SELECT current_schema;
+ current_schema
+----------------
+
+(1 row)
+
+SET search_path = 'pg_catalog';
+SELECT current_schema;
+ current_schema
+----------------
+ pg_catalog
+(1 row)
+
+RESET search_path;
(0)
(1 row)
+select NULL::derived::base;
+ base
+------
+
+(1 row)
+
drop table derived;
drop table base;
create table p1(ff1 int);
DROP FUNCTION testfunc1(int); -- ok
-- restore to sanity
GRANT ALL PRIVILEGES ON LANGUAGE sql TO PUBLIC;
+-- verify privilege checks on coercions
+BEGIN;
+SELECT NULL::int4[]::int8[];
+ int8
+------
+
+(1 row)
+
+SELECT '{1}'::int4[]::int8[];
+ int8
+------
+ {1}
+(1 row)
+
+REVOKE ALL ON FUNCTION int8(integer) FROM PUBLIC;
+SELECT NULL::int4[]::int8[];
+ int8
+------
+
+(1 row)
+
+SELECT '{1}'::int4[]::int8[]; --superuser, suceed
+ int8
+------
+ {1}
+(1 row)
+
+SET SESSION AUTHORIZATION regress_user4;
+SELECT NULL::int4[]::int8[]; --other user, no elements to convert
+ int8
+------
+
+(1 row)
+
+SELECT '{1}'::int4[]::int8[]; --other user, fail
+ERROR: permission denied for function int8
+ROLLBACK;
-- privileges on types
-- switch to superuser
\c -
(,) | t | f
(6 rows)
+--
+-- Tests for component access / FieldSelect
+--
+CREATE TABLE compositetable(a text, b text) WITH OIDS;
+INSERT INTO compositetable(a, b) VALUES('fa', 'fb');
+-- composite type columns can't directly be accessed (error)
+SELECT d.a FROM (SELECT compositetable AS d FROM compositetable) s;
+ERROR: missing FROM-clause entry for table "d"
+LINE 1: SELECT d.a FROM (SELECT compositetable AS d FROM compositeta...
+ ^
+-- but can be accessed with proper parens
+SELECT (d).a, (d).b FROM (SELECT compositetable AS d FROM compositetable) s;
+ a | b
+----+----
+ fa | fb
+(1 row)
+
+-- oids can't be accessed in composite types (error)
+SELECT (d).oid FROM (SELECT compositetable AS d FROM compositetable) s;
+ERROR: column "oid" not found in data type compositetable
+LINE 1: SELECT (d).oid FROM (SELECT compositetable AS d FROM composi...
+ ^
+-- accessing non-existing column in NULL datum errors out
+SELECT (NULL::compositetable).nonexistant;
+ERROR: column "nonexistant" not found in data type compositetable
+LINE 1: SELECT (NULL::compositetable).nonexistant;
+ ^
+-- existing column in a NULL composite yield NULL
+SELECT (NULL::compositetable).a;
+ a
+---
+
+(1 row)
+
+-- oids can't be accessed in composite types (error)
+SELECT (NULL::compositetable).oid;
+ERROR: column "oid" not found in data type compositetable
+LINE 1: SELECT (NULL::compositetable).oid;
+ ^
+DROP TABLE compositetable;
# geometry depends on point, lseg, box, path, polygon and circle
# horology depends on interval, timetz, timestamp, timestamptz, reltime and abstime
# ----------
-test: geometry horology regex oidjoins type_sanity opr_sanity
+test: geometry horology regex oidjoins type_sanity opr_sanity expressions
# ----------
# These four each depend on the previous one
test: oidjoins
test: type_sanity
test: opr_sanity
+test: expressions
test: insert
test: insert_conflict
test: create_function_1
select '[0:2][0:2]={{1,2,3},{4,5,6},{7,8,9}}'::int[];
select ('[0:2][0:2]={{1,2,3},{4,5,6},{7,8,9}}'::int[])[1:2][2];
+--
+-- check subscription corner cases
+--
+-- More subscripts than MAXDIMS(6)
+SELECT ('{}'::int[])[1][2][3][4][5][6][7];
+-- NULL index yields NULL when selecting
+SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][NULL][1];
+SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][NULL:1][1];
+SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][1:NULL][1];
+-- NULL index in assignment is an error
+UPDATE arrtest
+ SET c[NULL] = '{"can''t assign"}'
+ WHERE array_dims(c) is not null;
+UPDATE arrtest
+ SET c[NULL:1] = '{"can''t assign"}'
+ WHERE array_dims(c) is not null;
+UPDATE arrtest
+ SET c[1:NULL] = '{"can''t assign"}'
+ WHERE array_dims(c) is not null;
+
-- test slices with empty lower and/or upper index
CREATE TEMP TABLE arrtest_s (
a int2[],
SELECT f1[:1] FROM POINT_TBL;
SELECT f1[:] FROM POINT_TBL;
+-- subscript assignments to fixed-width result in NULL if previous value is NULL
+UPDATE point_tbl SET f1[0] = 10 WHERE f1 IS NULL RETURNING *;
+INSERT INTO point_tbl(f1[0]) VALUES(0) RETURNING *;
+-- NULL assignments get ignored
+UPDATE point_tbl SET f1[0] = NULL WHERE f1::text = '(10,10)'::point::text RETURNING *;
+-- but non-NULL subscript assignments work
+UPDATE point_tbl SET f1[0] = -10, f1[1] = -10 WHERE f1::text = '(10,10)'::point::text RETURNING *;
+-- but not to expand the range
+UPDATE point_tbl SET f1[3] = 10 WHERE f1::text = '(-10,-10)'::point::text RETURNING *;
+
--
-- test array extension
--
SELECT ARRAY[['a','bc'],['def','hijk']]::text[]::varchar[] AS "{{a,bc},{def,hijk}}";
SELECT ARRAY[['a','bc'],['def','hijk']]::text[]::varchar[] is of (varchar[]) as "TRUE";
SELECT CAST(ARRAY[[[[[['a','bb','ccc']]]]]] as text[]) as "{{{{{{a,bb,ccc}}}}}}";
+SELECT NULL::text[]::int[] AS "NULL";
-- scalar op any/all (array)
select 33 = any ('{1,2,3}');
select null::int = all ('{1,2,3}');
select 33 = all ('{1,null,3}');
select 33 = all ('{33,null,33}');
+-- nulls later in the bitmap
+SELECT -1 != ALL(ARRAY(SELECT NULLIF(g.i, 900) FROM generate_series(1,1000) g(i)));
-- test indexes on arrays
create temp table arr_tbl (f1 int[] unique);
FROM BOOLTBL2
WHERE f1 IS NOT TRUE;
+--
+-- Tests for BooleanTest
+--
+CREATE TABLE BOOLTBL3 (d text, b bool, o int);
+INSERT INTO BOOLTBL3 (d, b, o) VALUES ('true', true, 1);
+INSERT INTO BOOLTBL3 (d, b, o) VALUES ('false', false, 2);
+INSERT INTO BOOLTBL3 (d, b, o) VALUES ('null', null, 3);
+
+SELECT
+ d,
+ b IS TRUE AS istrue,
+ b IS NOT TRUE AS isnottrue,
+ b IS FALSE AS isfalse,
+ b IS NOT FALSE AS isnotfalse,
+ b IS UNKNOWN AS isunknown,
+ b IS NOT UNKNOWN AS isnotunknown
+FROM booltbl3 ORDER BY o;
+
--
-- Clean up
-- Many tables are retained by the regression test, but these do not seem
DROP TABLE BOOLTBL1;
DROP TABLE BOOLTBL2;
+
+DROP TABLE BOOLTBL3;
ELSE 7
END AS "Two WHEN with default";
+
+SELECT '7' AS "None",
+ CASE WHEN random() < 0 THEN 1
+ END AS "NULL on no matches";
+
-- Constant-expression folding shouldn't evaluate unreachable subexpressions
SELECT CASE WHEN 1=0 THEN 1/0 WHEN 1=1 THEN 1 ELSE 2/0 END;
SELECT CASE 1 WHEN 0 THEN 1/0 WHEN 1 THEN 1 ELSE 2/0 END;
--- /dev/null
+--
+-- expression evaluated tests that don't fit into a more specific file
+--
+
+--
+-- Tests for SQLVAlueFunction
+--
+
+
+-- current_date (always matches because of transactional behaviour)
+SELECT date(now())::text = current_date::text;
+
+
+-- current_time / localtime
+SELECT now()::timetz::text = current_time::text;
+SELECT now()::time::text = localtime::text;
+
+-- current_timestamp / localtimestamp (always matches because of transactional behaviour)
+SELECT current_timestamp = NOW();
+-- precision
+SELECT length(current_timestamp::text) >= length(current_timestamp(0)::text);
+-- localtimestamp
+SELECT now()::timestamp::text = localtimestamp::text;
+
+-- current_role/user/user is tested in rolnames.sql
+
+-- current database / catalog
+SELECT current_catalog = current_database();
+
+-- current_schema
+SELECT current_schema;
+SET search_path = 'notme';
+SELECT current_schema;
+SET search_path = 'pg_catalog';
+SELECT current_schema;
+RESET search_path;
create table derived () inherits (base);
insert into derived (i) values (0);
select derived::base from derived;
+select NULL::derived::base;
drop table derived;
drop table base;
-- restore to sanity
GRANT ALL PRIVILEGES ON LANGUAGE sql TO PUBLIC;
+-- verify privilege checks on coercions
+BEGIN;
+SELECT NULL::int4[]::int8[];
+SELECT '{1}'::int4[]::int8[];
+REVOKE ALL ON FUNCTION int8(integer) FROM PUBLIC;
+SELECT NULL::int4[]::int8[];
+SELECT '{1}'::int4[]::int8[]; --superuser, suceed
+SET SESSION AUTHORIZATION regress_user4;
+SELECT NULL::int4[]::int8[]; --other user, no elements to convert
+SELECT '{1}'::int4[]::int8[]; --other user, fail
+ROLLBACK;
+
-- privileges on types
-- switch to superuser
(values (1,row(1,2)), (1,row(null,null)), (1,null),
(null,row(1,2)), (null,row(null,null)), (null,null) )
select r, r is null as isnull, r is not null as isnotnull from r;
+
+
+--
+-- Tests for component access / FieldSelect
+--
+CREATE TABLE compositetable(a text, b text) WITH OIDS;
+INSERT INTO compositetable(a, b) VALUES('fa', 'fb');
+
+-- composite type columns can't directly be accessed (error)
+SELECT d.a FROM (SELECT compositetable AS d FROM compositetable) s;
+-- but can be accessed with proper parens
+SELECT (d).a, (d).b FROM (SELECT compositetable AS d FROM compositetable) s;
+-- oids can't be accessed in composite types (error)
+SELECT (d).oid FROM (SELECT compositetable AS d FROM compositetable) s;
+
+-- accessing non-existing column in NULL datum errors out
+SELECT (NULL::compositetable).nonexistant;
+-- existing column in a NULL composite yield NULL
+SELECT (NULL::compositetable).a;
+-- oids can't be accessed in composite types (error)
+SELECT (NULL::compositetable).oid;
+
+DROP TABLE compositetable;