Skip to content

Commit 829bc40

Browse files
committed
Drop restrictions on extract field + more consistency in numeric casts
1 parent caa0612 commit 829bc40

File tree

3 files changed

+14
-54
lines changed

3 files changed

+14
-54
lines changed

src/query/allowed_objects.c

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
static const char *const g_allowed_casts[] = {
1616
"i2tod", "i2tof", "i2toi4", "i4toi2", "i4tod", "i4tof", "i8tod", "i8tof", "int48", "int84",
1717
"ftod", "dtof",
18-
"int4_numeric", "float4_numeric", "float8_numeric",
18+
"int2_numeric", "int4_numeric", "int8_numeric", "float4_numeric", "float8_numeric",
1919
"numeric_float4", "numeric_float8",
2020
"date_timestamptz",
2121
/**/
@@ -138,12 +138,6 @@ static const char *const g_extract_functions[] = {
138138
/**/
139139
};
140140

141-
static const char *const g_integer_extract_fields[] = {
142-
"minute", "hour", "day", "dow", "isodow", "doy", "week", "month", "quarter", "year", "isoyear", "decade",
143-
"century", "millennium",
144-
/**/
145-
};
146-
147141
static void prepare_pg_catalog_allowed(Oid relation_oid, AllowedCols *allowed_cols)
148142
{
149143
MemoryContext old_context = MemoryContextSwitchTo(TopMemoryContext);
@@ -256,27 +250,14 @@ bool is_allowed_cast(const FuncExpr *func_expr)
256250
}
257251
else if (is_funcname_member_of(func_expr->funcid, g_decimal_integer_casts, ARRAY_LENGTH(g_decimal_integer_casts)))
258252
{
259-
/*
260-
* Special case, where a `numeric_int4` cast is called on variants of `extract` which return
261-
* integer numbers, e.g. `cast(extract(minute from ...) as integer)`.
262-
*/
253+
/* Handle cases like `cast(extract(minute from ...) as integer)`. */
263254
Node *cast_arg = linitial(func_expr->args);
264255
if (IsA(cast_arg, FuncExpr))
265256
{
266257
FuncExpr *cast_arg_expr = (FuncExpr *)cast_arg;
267258
if (is_funcname_member_of(cast_arg_expr->funcid, g_extract_functions, ARRAY_LENGTH(g_extract_functions)) ||
268259
cast_arg_expr->funcid == F_DATE_PART_TEXT_DATE)
269-
{
270-
Node *extract_field = linitial(cast_arg_expr->args);
271-
if (IsA(extract_field, Const))
272-
{
273-
Const *extract_field_const = (Const *)extract_field;
274-
Assert(extract_field_const->consttype == TEXTOID);
275-
const char *field = TextDatumGetCString(extract_field_const->constvalue);
276-
277-
return is_member_of(field, g_integer_extract_fields, ARRAY_LENGTH(g_integer_extract_fields));
278-
}
279-
}
260+
return true;
280261
}
281262
}
282263
return false;

test/expected/datetime.out

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -97,32 +97,17 @@ SELECT count(*) FROM test_datetime WHERE date_part('century', ts) = 21;
9797
9
9898
(1 row)
9999

100-
-- Datetime cast normalization
101-
-- Allowed because the cast is a noop
100+
-- Datetime extract cast to integer
102101
SELECT cast(extract(minute from ts) as integer) as extract FROM test_datetime GROUP BY 1;
103102
extract
104103
---------
105104
0
106105
(1 row)
107106

108-
-- Disallowed because the cast is rounding
109-
SELECT cast(extract(epoch from ts) as integer) FROM test_datetime GROUP BY 1;
110-
ERROR: [PG_DIFFIX] Primary argument for a generalization function has to be a simple column reference.
111-
LINE 1: SELECT cast(extract(epoch from ts) as integer) FROM test_dat...
112-
^
113-
SELECT cast(extract(second from ts) as integer) FROM test_datetime GROUP BY 1;
114-
ERROR: [PG_DIFFIX] Primary argument for a generalization function has to be a simple column reference.
115-
LINE 1: SELECT cast(extract(second from ts) as integer) FROM test_da...
116-
^
117-
SELECT cast(extract(millisecond from ts) as integer) FROM test_datetime GROUP BY 1;
118-
ERROR: [PG_DIFFIX] Primary argument for a generalization function has to be a simple column reference.
119-
LINE 1: SELECT cast(extract(millisecond from ts) as integer) FROM te...
120-
^
121-
SELECT cast(extract(microsecond from ts) as integer) FROM test_datetime GROUP BY 1;
122-
ERROR: [PG_DIFFIX] Primary argument for a generalization function has to be a simple column reference.
123-
LINE 1: SELECT cast(extract(microsecond from ts) as integer) FROM te...
124-
^
125-
SELECT cast(extract(julian from ts) as integer) FROM test_datetime GROUP BY 1;
126-
ERROR: [PG_DIFFIX] Primary argument for a generalization function has to be a simple column reference.
127-
LINE 1: SELECT cast(extract(julian from ts) as integer) FROM test_da...
128-
^
107+
-- Allowed despite the cast being rounding
108+
SELECT cast(extract(second from ts) as integer) as extract FROM test_datetime GROUP BY 1;
109+
extract
110+
---------
111+
0
112+
(1 row)
113+

test/sql/datetime.sql

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,7 @@ SELECT count(*) FROM test_datetime WHERE date_trunc('year', ts) = '2012-01-01'::
5959
SELECT count(*) FROM test_datetime WHERE extract(century from ts) = 21;
6060
SELECT count(*) FROM test_datetime WHERE date_part('century', ts) = 21;
6161

62-
-- Datetime cast normalization
63-
-- Allowed because the cast is a noop
62+
-- Datetime extract cast to integer
6463
SELECT cast(extract(minute from ts) as integer) as extract FROM test_datetime GROUP BY 1;
65-
66-
-- Disallowed because the cast is rounding
67-
SELECT cast(extract(epoch from ts) as integer) FROM test_datetime GROUP BY 1;
68-
SELECT cast(extract(second from ts) as integer) FROM test_datetime GROUP BY 1;
69-
SELECT cast(extract(millisecond from ts) as integer) FROM test_datetime GROUP BY 1;
70-
SELECT cast(extract(microsecond from ts) as integer) FROM test_datetime GROUP BY 1;
71-
SELECT cast(extract(julian from ts) as integer) FROM test_datetime GROUP BY 1;
64+
-- Allowed despite the cast being rounding
65+
SELECT cast(extract(second from ts) as integer) as extract FROM test_datetime GROUP BY 1;

0 commit comments

Comments
 (0)