Skip to content

Commit

Permalink
Fix Issue 1329 - agtype_to_int4 crash
Browse files Browse the repository at this point in the history
Fixed issue 1329 where `agtype_to_int`<8,4,2> and `agtype_to_int4_array`
crashed due to not properly checking input.

As these functions take "any" input, the input has to be properly
checked before casting it to a specific type. The input section
assumed it was agtype, which caused crashes for non-agtypes.

The functions `agtype_to_int`<8,4,2> will convert non-agtypes into
agtype. However, there were no regression tests for this.

The functions `agtype_to_int`<8,4,2> will convert non-agtypes to
agtype ints but, did not for their string equivs. Meaning, passing
a ('true') or ('3.14') would fail but, passing a (true) or (3.14)
would not. This has been corrected for all 3 functions.

TODO -
The function `agtype_to_int4_array` only takes agtype, currently,
and we should consider allowing it to take "any" types.

Added regression tests.
Added missing regression tests.
  • Loading branch information
jrgemignani committed Nov 1, 2023
1 parent 34c738f commit 7efc5e7
Show file tree
Hide file tree
Showing 5 changed files with 720 additions and 66 deletions.
324 changes: 316 additions & 8 deletions regress/expected/agtype.out
Expand Up @@ -2744,6 +2744,91 @@ SELECT agtype_to_int8(agtype_in('false'));
0
(1 row)

-- should return SQL NULL
SELECT agtype_to_int8(agtype_in('null'));
agtype_to_int8
----------------

(1 row)

SELECT agtype_to_int8(NULL);
agtype_to_int8
----------------

(1 row)

-- non agtype input
SELECT agtype_to_int8(1);
agtype_to_int8
----------------
1
(1 row)

SELECT agtype_to_int8(3.14);
agtype_to_int8
----------------
3
(1 row)

SELECT agtype_to_int8(3.14::numeric);
agtype_to_int8
----------------
3
(1 row)

SELECT agtype_to_int8('3');
agtype_to_int8
----------------
3
(1 row)

SELECT agtype_to_int8(true);
agtype_to_int8
----------------
1
(1 row)

SELECT agtype_to_int8(false);
agtype_to_int8
----------------
0
(1 row)

SELECT agtype_to_int8('3.14');
agtype_to_int8
----------------
3
(1 row)

SELECT agtype_to_int8('true');
agtype_to_int8
----------------
1
(1 row)

SELECT agtype_to_int8('false');
agtype_to_int8
----------------
0
(1 row)

-- should fail
SELECT agtype_to_int8('neither');
ERROR: invalid input syntax for type agtype
DETAIL: Expected agtype value, but found "neither".
CONTEXT: agtype data, line 1: neither
SELECT agtype_to_int8('NaN');
ERROR: bigint out of range
SELECT agtype_to_int8('Inf');
ERROR: bigint out of range
SELECT agtype_to_int8(NaN);
ERROR: column "nan" does not exist
LINE 1: SELECT agtype_to_int8(NaN);
^
SELECT agtype_to_int8(Inf);
ERROR: column "inf" does not exist
LINE 1: SELECT agtype_to_int8(Inf);
^
--
-- Test boolean to integer cast
--
Expand All @@ -2759,14 +2844,8 @@ SELECT agtype_to_int4(agtype_in('false'));
0
(1 row)

SELECT agtype_to_int4(agtype_in('null'));
agtype_to_int4
----------------

(1 row)

--
-- Test agtype to integer cast
-- Test agtype to integer4 cast
--
SELECT agtype_to_int4(agtype_in('1'));
agtype_to_int4
Expand All @@ -2788,11 +2867,228 @@ SELECT agtype_to_int4(agtype_in('1.444::numeric'));

-- These should all fail
SELECT agtype_to_int4(agtype_in('"string"'));
ERROR: invalid input syntax for type integer: "string"
ERROR: invalid input syntax for type agtype
DETAIL: Expected agtype value, but found "string".
CONTEXT: agtype data, line 1: string
SELECT agtype_to_int4(agtype_in('[1, 2, 3]'));
ERROR: cannot cast agtype array to type int
SELECT agtype_to_int4(agtype_in('{"int":1}'));
ERROR: cannot cast agtype object to type int
-- should return SQL NULL
SELECT agtype_to_int4(agtype_in('null'));
agtype_to_int4
----------------

(1 row)

SELECT agtype_to_int4(NULL);
agtype_to_int4
----------------

(1 row)

-- non agtype input
SELECT agtype_to_int4(1);
agtype_to_int4
----------------
1
(1 row)

SELECT agtype_to_int4(3.14);
agtype_to_int4
----------------
3
(1 row)

SELECT agtype_to_int4(3.14::numeric);
agtype_to_int4
----------------
3
(1 row)

SELECT agtype_to_int4('3');
agtype_to_int4
----------------
3
(1 row)

SELECT agtype_to_int4(true);
agtype_to_int4
----------------
1
(1 row)

SELECT agtype_to_int4(false);
agtype_to_int4
----------------
0
(1 row)

SELECT agtype_to_int4('3.14');
agtype_to_int4
----------------
3
(1 row)

SELECT agtype_to_int4('true');
agtype_to_int4
----------------
1
(1 row)

SELECT agtype_to_int4('false');
agtype_to_int4
----------------
0
(1 row)

-- should error
SELECT agtype_to_int4('neither');
ERROR: invalid input syntax for type agtype
DETAIL: Expected agtype value, but found "neither".
CONTEXT: agtype data, line 1: neither
SELECT agtype_to_int4('NaN');
ERROR: integer out of range
SELECT agtype_to_int4('Inf');
ERROR: integer out of range
SELECT agtype_to_int4(NaN);
ERROR: column "nan" does not exist
LINE 1: SELECT agtype_to_int4(NaN);
^
SELECT agtype_to_int4(Inf);
ERROR: column "inf" does not exist
LINE 1: SELECT agtype_to_int4(Inf);
^
--
-- Test boolean to integer2 cast
--
SELECT agtype_to_int2(agtype_in('true'));
agtype_to_int2
----------------
1
(1 row)

SELECT agtype_to_int2(agtype_in('false'));
agtype_to_int2
----------------
0
(1 row)

--
-- Test agtype to integer2 cast
--
SELECT agtype_to_int2(agtype_in('1'));
agtype_to_int2
----------------
1
(1 row)

SELECT agtype_to_int2(agtype_in('1.45'));
agtype_to_int2
----------------
1
(1 row)

SELECT agtype_to_int2(agtype_in('1.444::numeric'));
agtype_to_int2
----------------
1
(1 row)

-- These should all fail
SELECT agtype_to_int2(agtype_in('"string"'));
ERROR: invalid input syntax for type agtype
DETAIL: Expected agtype value, but found "string".
CONTEXT: agtype data, line 1: string
SELECT agtype_to_int2(agtype_in('[1, 2, 3]'));
ERROR: cannot cast agtype array to type int
SELECT agtype_to_int2(agtype_in('{"int":1}'));
ERROR: cannot cast agtype object to type int
-- should return SQL NULL
SELECT agtype_to_int2(agtype_in('null'));
agtype_to_int2
----------------

(1 row)

SELECT agtype_to_int2(NULL);
agtype_to_int2
----------------

(1 row)

-- non agtype input
SELECT agtype_to_int2(1);
agtype_to_int2
----------------
1
(1 row)

SELECT agtype_to_int2(3.14);
agtype_to_int2
----------------
3
(1 row)

SELECT agtype_to_int2(3.14::numeric);
agtype_to_int2
----------------
3
(1 row)

SELECT agtype_to_int2('3');
agtype_to_int2
----------------
3
(1 row)

SELECT agtype_to_int2(true);
agtype_to_int2
----------------
1
(1 row)

SELECT agtype_to_int2(false);
agtype_to_int2
----------------
0
(1 row)

SELECT agtype_to_int2('3.14');
agtype_to_int2
----------------
3
(1 row)

SELECT agtype_to_int2('true');
agtype_to_int2
----------------
1
(1 row)

SELECT agtype_to_int2('false');
agtype_to_int2
----------------
0
(1 row)

-- should error
SELECT agtype_to_int2('neither');
ERROR: invalid input syntax for type agtype
DETAIL: Expected agtype value, but found "neither".
CONTEXT: agtype data, line 1: neither
SELECT agtype_to_int2('NaN');
ERROR: smallint out of range
SELECT agtype_to_int2('Inf');
ERROR: smallint out of range
SELECT agtype_to_int2(NaN);
ERROR: column "nan" does not exist
LINE 1: SELECT agtype_to_int2(NaN);
^
SELECT agtype_to_int2(Inf);
ERROR: column "inf" does not exist
LINE 1: SELECT agtype_to_int2(Inf);
^
--
-- Test agtype to int[]
--
Expand All @@ -2814,6 +3110,18 @@ SELECT agtype_to_int4_array(agtype_in('["6","7",3.66]'));
{6,7,4}
(1 row)

-- should error
SELECT agtype_to_int4_array(bool('true'));
ERROR: argument must resolve to agtype
SELECT agtype_to_int4_array((1,2,3,4,5));
ERROR: argument must resolve to agtype
-- should return SQL NULL
SELECT agtype_to_int4_array(NULL);
agtype_to_int4_array
----------------------

(1 row)

--
-- Map Literal
--
Expand Down

0 comments on commit 7efc5e7

Please sign in to comment.