blob: 0e6617c10ee065893a8fe7426e0031e3b18917c0 [file] [log] [blame]
--
-- CASE
-- Test the case statement
--
CREATE TABLE CASE_TBL (
dummy serial,
i integer,
f double precision
);
CREATE TABLE CASE2_TBL (
i integer,
j integer
);
INSERT INTO CASE_TBL VALUES (1, 10.1);
INSERT INTO CASE_TBL VALUES (2, 20.2);
INSERT INTO CASE_TBL VALUES (3, -30.3);
INSERT INTO CASE_TBL VALUES (4, NULL);
INSERT INTO CASE2_TBL VALUES (1, -1);
INSERT INTO CASE2_TBL VALUES (2, -2);
INSERT INTO CASE2_TBL VALUES (3, -3);
INSERT INTO CASE2_TBL VALUES (2, -4);
INSERT INTO CASE2_TBL VALUES (1, NULL);
INSERT INTO CASE2_TBL VALUES (NULL, -6);
--
-- Simplest examples without tables
--
SELECT '3' AS "One",
CASE
WHEN 1 < 2 THEN 3
END AS "Simple WHEN";
SELECT '<NULL>' AS "One",
CASE
WHEN 1 > 2 THEN 3
END AS "Simple default";
SELECT '3' AS "One",
CASE
WHEN 1 < 2 THEN 3
ELSE 4
END AS "Simple ELSE";
SELECT '4' AS "One",
CASE
WHEN 1 > 2 THEN 3
ELSE 4
END AS "ELSE default";
SELECT '6' AS "One",
CASE
WHEN 1 > 2 THEN 3
WHEN 4 < 5 THEN 6
ELSE 7
END AS "Two WHEN with default";
-- 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;
-- However we do not currently suppress folding of potentially
-- reachable subexpressions (but MPP does... So we get different answer from postgres).
--SELECT CASE WHEN i > 100 THEN 1/0 ELSE 0 END FROM case_tbl;
-- Test for cases involving untyped literals in test expression
SELECT CASE 'a' WHEN 'a' THEN 1 ELSE 2 END;
--
-- Examples of targets involving tables
--
SELECT '' AS "Five",
CASE
WHEN i >= 3 THEN i
END AS ">= 3 or Null"
FROM CASE_TBL ORDER BY 2;
SELECT '' AS "Five",
CASE WHEN i >= 3 THEN (i + i)
ELSE i
END AS "Simplest Math"
FROM CASE_TBL ORDER BY 2;
SELECT '' AS "Five", i AS "Value",
CASE WHEN (i < 0) THEN 'small'
WHEN (i = 0) THEN 'zero'
WHEN (i = 1) THEN 'one'
WHEN (i = 2) THEN 'two'
ELSE 'big'
END AS "Category"
FROM CASE_TBL ORDER BY 2,3;
SELECT '' AS "Five",
CASE WHEN ((i < 0) or (i < 0)) THEN 'small'
WHEN ((i = 0) or (i = 0)) THEN 'zero'
WHEN ((i = 1) or (i = 1)) THEN 'one'
WHEN ((i = 2) or (i = 2)) THEN 'two'
ELSE 'big'
END AS "Category"
FROM CASE_TBL ORDER BY 2;
--
-- Examples of qualifications involving tables
--
--
-- NULLIF() and COALESCE()
-- Shorthand forms for typical CASE constructs
-- defined in the SQL92 standard.
--
SELECT i,f FROM CASE_TBL WHERE COALESCE(f,i) = 4 ORDER BY 1;
SELECT i,f FROM CASE_TBL WHERE NULLIF(f,i) = 2 ORDER BY 1;
SELECT COALESCE(a.f, b.i, b.j)
FROM CASE_TBL a, CASE2_TBL b ORDER BY 1;
SELECT a.i,a.f,b.i,b.j
FROM CASE_TBL a, CASE2_TBL b
WHERE COALESCE(a.f, b.i, b.j) = 2 ORDER BY 1,2,3,4;
SELECT '' AS Five, NULLIF(a.i,b.i) AS "NULLIF(a.i,b.i)",
NULLIF(b.i, 4) AS "NULLIF(b.i,4)"
FROM CASE_TBL a, CASE2_TBL b ORDER BY 2,3,4,5;
SELECT '' AS "Two", a.i,a.f,b.i,b.j
FROM CASE_TBL a, CASE2_TBL b
WHERE COALESCE(f,b.i) = 2 ORDER BY 2,3,4,5;
--
-- Examples of updates involving tables
--
UPDATE CASE_TBL
SET i = CASE WHEN i >= 3 THEN (- i)
ELSE (2 * i) END;
SELECT i,f FROM CASE_TBL ORDER BY 1,2;
UPDATE CASE_TBL
SET i = CASE WHEN i >= 2 THEN (2 * i)
ELSE (3 * i) END;
SELECT i,f FROM CASE_TBL ORDER BY 1,2;
--UPDATE CASE_TBL
-- SET i = CASE WHEN b.i >= 2 THEN (2 * j)
-- ELSE (3 * j) END
-- FROM CASE2_TBL b
-- WHERE j = -CASE_TBL.i;
SELECT i,f FROM CASE_TBL ORDER BY 1,2;
--
-- CASE ... WHEN IS NOT DISTINCT FROM ...
--
DROP TABLE IF EXISTS mytable CASCADE;
CREATE TABLE mytable (a int, b int, c varchar(1));
INSERT INTO mytable values (1,2,'t'),
(2,3,'e'),
(3,4,'o'),
(4,5,'o'),
(4,4,'o'),
(5,5,'t'),
(6,6,'t'),
(7,6,'a'),
(8,7,'t'),
(9,8,'a');
CREATE OR REPLACE FUNCTION negate(int) RETURNS int
AS 'SELECT $1 * (-1)'
LANGUAGE sql
IMMUTABLE
RETURNS null ON null input;
DROP VIEW IF EXISTS myview;
CREATE VIEW myview AS
SELECT a,b, CASE a WHEN IS NOT DISTINCT FROM b THEN b*10
WHEN IS NOT DISTINCT FROM b+1 THEN b*100
WHEN b-1 THEN b*1000
WHEN b*10 THEN b*10000
WHEN negate(b) THEN b*(-1.0)
ELSE b END AS newb
FROM mytable;
SELECT * FROM myview ORDER BY a,b;
-- Test deparse
select pg_get_viewdef('myview',true);
DROP TABLE IF EXISTS products CASCADE;
CREATE TABLE products (id serial, name text, price numeric);
INSERT INTO products (name, price) values ('keyboard', 124.99);
INSERT INTO products (name, price) values ('monitor', 299.99);
INSERT INTO products (name, price) values ('mouse', 45.59);
SELECT id,name,price as old_price,
CASE name WHEN IS NOT DISTINCT FROM 'keyboard' THEN products.price*1.5
WHEN IS NOT DISTINCT FROM 'monitor' THEN price*1.2
WHEN 'keyboard tray' THEN price*.9
END AS new_price
FROM products;
-- testexpr should be evaluated only once
DROP FUNCTION IF EXISTS blip(int);
DROP TABLE IF EXISTS calls_to_blip;
CREATE TABLE calls_to_blip (n serial, v int) DISTRIBUTED RANDOMLY;
CREATE OR REPLACE FUNCTION blip(int) RETURNS int
LANGUAGE plpgsql
VOLATILE
AS $$
DECLARE
x alias for $1;
BEGIN
INSERT INTO calls_to_blip(v) VALUES (x);
RETURN x;
END;
$$;
SELECT CASE blip(1)
WHEN IS NOT DISTINCT FROM blip(2) THEN blip(20)
WHEN IS NOT DISTINCT FROM blip(3) THEN blip(30)
WHEN IS NOT DISTINCT FROM blip(4) THEN blip(40)
ELSE blip(666)
END AS answer;
SELECT * FROM calls_to_blip ORDER BY 1;
-- Negative test
-- 1. wrong syntax
-- 2. type mismatches
SELECT a,b,CASE WHEN IS NOT DISTINCT FROM b THEN b*100 ELSE b*1000 END FROM mytable;
SELECT a,b,c,CASE c WHEN IS NOT DISTINCT FROM b THEN a
WHEN IS NOT DISTINCT FROM b+1 THEN a*100
ELSE c END
FROM mytable;
--
-- DECODE(): Oracle compatibility
--
SELECT decode(null,null,true,false);
SELECT decode(NULL, 1, 100, NULL, 200, 300);
SELECT decode('1'::text, '1', 100, '2', 200);
SELECT decode(2, 1, 'ABC', 2, 'DEF');
SELECT decode('2009-02-05'::date, '2009-02-05', 'ok');
SELECT decode('2009-02-05 01:02:03'::timestamp, '2009-02-05 01:02:03', 'ok');
SELECT b,c,decode(c,'a',b*10,'e',b*100,'o',b*1000,'u',b*10000,'i',b*100000) as newb from mytable;
SELECT b,c,decode(c,'a',ARRAY[1,2],'e',ARRAY[3,4],'o',ARRAY[5,6],'u',ARRAY[7,8],'i',ARRAY[9,10],ARRAY[0]) as newb from mytable;
DROP VIEW IF EXISTS myview;
CREATE VIEW myview as
SELECT id, name, price, DECODE(id, 1, 'Southlake',
2, 'San Francisco',
3, 'New Jersey',
4, 'Seattle',
5, 'Portland',
6, 'San Francisco',
7, 'Portland',
'Non domestic') Location
FROM products
WHERE id < 100;
SELECT * FROM myview ORDER BY id, location;
-- Test deparse
select pg_get_viewdef('myview',true);
-- User-defined DECODE function
CREATE OR REPLACE FUNCTION "decode"(int, int, int) RETURNS int
AS 'select $1 * $2 - $3;'
LANGUAGE sql
IMMUTABLE
RETURNS null ON null input;
SELECT decode(11,8,11);
SELECT "decode"(11,8,11);
SELECT public.decode(11,8,11);
-- Test CASE x WHEN IS NOT DISTINCT FROM y with DECODE
SELECT a,b,decode(a,1,1),
CASE decode(a,1,1) WHEN IS NOT DISTINCT FROM 1 THEN b*100
WHEN IS NOT DISTINCT FROM 4 THEN b*1000 ELSE b END as newb
FROM mytable ORDER BY a,b;
-- Test CASE WHEN x IS NOT DISTINCT FROM y with DECODE
SELECT a,b,decode(a,1,1),
CASE WHEN decode(a,1,1) IS NOT DISTINCT FROM 1 THEN b*100
WHEN decode(a,1,1) IS NOT DISTINCT FROM 4 THEN b*1000 ELSE b END as newb
FROM mytable ORDER BY a,b;
SELECT a,b,"decode"(a,1,1),
CASE WHEN "decode"(a,1,1) IS NOT DISTINCT FROM 1 THEN b*100
WHEN "decode"(a,1,1) IS NOT DISTINCT FROM 4 THEN b*1000 ELSE b END as newb
FROM mytable ORDER BY a,b;
-- Negative test: type mismatches
SELECT b,c,decode(c,'a',ARRAY[1,2],'e',ARRAY[3,4],'o',ARRAY[5,6],'u',ARRAY[7,8],'i',ARRAY[9,10],0) as newb from mytable;
--
-- Clean up
--
DROP TABLE CASE_TBL;
DROP TABLE CASE2_TBL;
DROP TABLE mytable CASCADE;
DROP TABLE products CASCADE;
DROP TABLE calls_to_blip;
DROP FUNCTION negate(int);
DROP FUNCTION "decode"(int, int, int);
DROP FUNCTION blip(int);