unsupported-type-fix-v2.patch
text/x-patch
Filename: unsupported-type-fix-v2.patch
Type: text/x-patch
Part: 0
Patch
Format: unified
Series: patch v2
| File | + | − |
|---|---|---|
| src/backend/utils/adt/network.c | 2 | 2 |
| src/backend/utils/adt/selfuncs.c | 73 | 25 |
| src/include/utils/builtins.h | 2 | 1 |
| src/test/regress/expected/convert_to_scalar.out | 105 | 0 |
| src/test/regress/parallel_schedule | 1 | 1 |
| src/test/regress/serial_schedule | 1 | 0 |
| src/test/regress/sql/convert_to_scalar.sql | 105 | 0 |
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index aac7621..34cf336 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -904,7 +904,7 @@ inet_merge(PG_FUNCTION_ARGS)
* involving network types.
*/
double
-convert_network_to_scalar(Datum value, Oid typid)
+convert_network_to_scalar(Datum value, Oid typid, bool *unknown_type)
{
switch (typid)
{
@@ -960,7 +960,7 @@ convert_network_to_scalar(Datum value, Oid typid)
* Can't get here unless someone tries to use scalarineqsel() on an
* operator with one network and one non-network operand.
*/
- elog(ERROR, "unsupported type: %u", typid);
+ *unknown_type = true;
return 0;
}
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index fcc8323..b210541 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -176,7 +176,7 @@ static bool estimate_multivariate_ndistinct(PlannerInfo *root,
static bool convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
Datum lobound, Datum hibound, Oid boundstypid,
double *scaledlobound, double *scaledhibound);
-static double convert_numeric_to_scalar(Datum value, Oid typid);
+static double convert_numeric_to_scalar(Datum value, Oid typid, bool *unknown_type);
static void convert_string_to_scalar(char *value,
double *scaledvalue,
char *lobound,
@@ -193,8 +193,9 @@ static double convert_one_string_to_scalar(char *value,
int rangelo, int rangehi);
static double convert_one_bytea_to_scalar(unsigned char *value, int valuelen,
int rangelo, int rangehi);
-static char *convert_string_datum(Datum value, Oid typid);
-static double convert_timevalue_to_scalar(Datum value, Oid typid);
+static char *convert_string_datum(Datum value, Oid typid, bool *unknown_type);
+static double convert_timevalue_to_scalar(Datum value, Oid typid,
+ bool *unknown_type);
static void examine_simple_variable(PlannerInfo *root, Var *var,
VariableStatData *vardata);
static bool get_variable_range(PlannerInfo *root, VariableStatData *vardata,
@@ -4071,10 +4072,18 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
case REGDICTIONARYOID:
case REGROLEOID:
case REGNAMESPACEOID:
- *scaledvalue = convert_numeric_to_scalar(value, valuetypid);
- *scaledlobound = convert_numeric_to_scalar(lobound, boundstypid);
- *scaledhibound = convert_numeric_to_scalar(hibound, boundstypid);
- return true;
+ {
+ bool unknown_type = false;
+
+ *scaledvalue = convert_numeric_to_scalar(value, valuetypid,
+ &unknown_type);
+ *scaledlobound = convert_numeric_to_scalar(lobound, boundstypid,
+ &unknown_type);
+ *scaledhibound = convert_numeric_to_scalar(hibound, boundstypid,
+ &unknown_type);
+
+ return (!unknown_type);
+ }
/*
* Built-in string types
@@ -4085,9 +4094,18 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
case TEXTOID:
case NAMEOID:
{
- char *valstr = convert_string_datum(value, valuetypid);
- char *lostr = convert_string_datum(lobound, boundstypid);
- char *histr = convert_string_datum(hibound, boundstypid);
+ bool unknown_type = false;
+
+ char *valstr = convert_string_datum(value, valuetypid,
+ &unknown_type);
+ char *lostr = convert_string_datum(lobound, boundstypid,
+ &unknown_type);
+ char *histr = convert_string_datum(hibound, boundstypid,
+ &unknown_type);
+
+ /* bail out if any of the values is not a string */
+ if (unknown_type)
+ return false;
convert_string_to_scalar(valstr, scaledvalue,
lostr, scaledlobound,
@@ -4103,6 +4121,18 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
*/
case BYTEAOID:
{
+ TypeCacheEntry *typcache;
+
+ /*
+ * Ensure parameters passed to convert_bytea_to_scalar are
+ * all varlena. We're dealing with bytea values, but this
+ * seems like a reasonable way to handle custom types.
+ */
+ typcache = lookup_type_cache(boundstypid, 0);
+
+ if (typcache->typlen != -1)
+ return false;
+
convert_bytea_to_scalar(value, scaledvalue,
lobound, scaledlobound,
hibound, scaledhibound);
@@ -4121,10 +4151,18 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
case TINTERVALOID:
case TIMEOID:
case TIMETZOID:
- *scaledvalue = convert_timevalue_to_scalar(value, valuetypid);
- *scaledlobound = convert_timevalue_to_scalar(lobound, boundstypid);
- *scaledhibound = convert_timevalue_to_scalar(hibound, boundstypid);
- return true;
+ {
+ bool unknown_type = false;
+
+ *scaledvalue = convert_timevalue_to_scalar(value, valuetypid,
+ &unknown_type);
+ *scaledlobound = convert_timevalue_to_scalar(lobound, boundstypid,
+ &unknown_type);
+ *scaledhibound = convert_timevalue_to_scalar(hibound, boundstypid,
+ &unknown_type);
+
+ return (!unknown_type);
+ }
/*
* Built-in network types
@@ -4133,10 +4171,18 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
case CIDROID:
case MACADDROID:
case MACADDR8OID:
- *scaledvalue = convert_network_to_scalar(value, valuetypid);
- *scaledlobound = convert_network_to_scalar(lobound, boundstypid);
- *scaledhibound = convert_network_to_scalar(hibound, boundstypid);
- return true;
+ {
+ bool unknown_type = false;
+
+ *scaledvalue = convert_network_to_scalar(value, valuetypid,
+ &unknown_type);
+ *scaledlobound = convert_network_to_scalar(lobound, boundstypid,
+ &unknown_type);
+ *scaledhibound = convert_network_to_scalar(hibound, boundstypid,
+ &unknown_type);
+
+ return (!unknown_type);
+ }
}
/* Don't know how to convert */
*scaledvalue = *scaledlobound = *scaledhibound = 0;
@@ -4147,7 +4193,7 @@ convert_to_scalar(Datum value, Oid valuetypid, double *scaledvalue,
* Do convert_to_scalar()'s work for any numeric data type.
*/
static double
-convert_numeric_to_scalar(Datum value, Oid typid)
+convert_numeric_to_scalar(Datum value, Oid typid, bool *unknown_type)
{
switch (typid)
{
@@ -4185,9 +4231,11 @@ convert_numeric_to_scalar(Datum value, Oid typid)
/*
* Can't get here unless someone tries to use scalarineqsel() on an
- * operator with one numeric and one non-numeric operand.
+ * operator with one numeric and one non-numeric operand. Or more
+ * precisely, operand that we don't know how to transform to scalar.
*/
- elog(ERROR, "unsupported type: %u", typid);
+ *unknown_type = true;
+
return 0;
}
@@ -4340,7 +4388,7 @@ convert_one_string_to_scalar(char *value, int rangelo, int rangehi)
* before continuing, so as to generate correct locale-specific results.
*/
static char *
-convert_string_datum(Datum value, Oid typid)
+convert_string_datum(Datum value, Oid typid, bool *unknown_type)
{
char *val;
@@ -4369,7 +4417,7 @@ convert_string_datum(Datum value, Oid typid)
* Can't get here unless someone tries to use scalarineqsel() on
* an operator with one string and one non-string operand.
*/
- elog(ERROR, "unsupported type: %u", typid);
+ *unknown_type = true;
return NULL;
}
@@ -4524,7 +4572,7 @@ convert_one_bytea_to_scalar(unsigned char *value, int valuelen,
* Do convert_to_scalar()'s work for any timevalue data type.
*/
static double
-convert_timevalue_to_scalar(Datum value, Oid typid)
+convert_timevalue_to_scalar(Datum value, Oid typid, bool *unknown_type)
{
switch (typid)
{
@@ -4574,7 +4622,7 @@ convert_timevalue_to_scalar(Datum value, Oid typid)
* Can't get here unless someone tries to use scalarineqsel() on an
* operator with one timevalue and one non-timevalue operand.
*/
- elog(ERROR, "unsupported type: %u", typid);
+ *unknown_type = true;
return 0;
}
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 3e462f1..630eeba 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -103,7 +103,8 @@ extern int inet_net_pton(int af, const char *src,
void *dst, size_t size);
/* network.c */
-extern double convert_network_to_scalar(Datum value, Oid typid);
+extern double convert_network_to_scalar(Datum value, Oid typid,
+ bool *unknown_type);
extern Datum network_scan_first(Datum in);
extern Datum network_scan_last(Datum in);
extern void clean_ipv6_addr(int addr_family, char *addr);
diff --git a/src/test/regress/expected/convert_to_scalar.out b/src/test/regress/expected/convert_to_scalar.out
new file mode 100644
index 0000000..7b4fe2b
--- /dev/null
+++ b/src/test/regress/expected/convert_to_scalar.out
@@ -0,0 +1,105 @@
+-- tables used in these tests
+create table scalar_text (a text);
+insert into scalar_text select i::text from generate_series(1,1000) s(i);
+analyze scalar_text;
+create table scalar_int (a int);
+insert into scalar_int select i from generate_series(1,1000) s(i);
+analyze scalar_int;
+-- convert_bytea_to_scalar
+CREATE OR REPLACE FUNCTION int_bytea_proc(int, bytea) RETURNS bool AS $$
+BEGIN
+ RETURN ($1 > 500);
+END;
+$$ LANGUAGE plpgsql;
+CREATE OPERATOR > (
+ LEFTARG = int,
+ RIGHTARG = bytea,
+ PROCEDURE = int_bytea_proc,
+ RESTRICT = scalargtsel
+);
+EXPLAIN (COSTS OFF) SELECT * FROM scalar_int
+WHERE a > E'\x37666565353'::bytea;
+ QUERY PLAN
+-------------------------------------------------
+ Seq Scan on scalar_int
+ Filter: (a > '\x37363636353635333533'::bytea)
+(2 rows)
+
+-- convert_numeric_to_scalar
+CREATE OR REPLACE FUNCTION text_int_proc(text, int) RETURNS bool AS $$
+BEGIN
+ RETURN ($1::int > 500);
+END;
+$$ LANGUAGE plpgsql;
+CREATE OPERATOR > (
+ LEFTARG = text,
+ RIGHTARG = int,
+ PROCEDURE = text_int_proc,
+ RESTRICT = scalargtsel
+);
+EXPLAIN (COSTS OFF) SELECT * FROM scalar_text WHERE a > 30;
+ QUERY PLAN
+-------------------------
+ Seq Scan on scalar_text
+ Filter: (a > 30)
+(2 rows)
+
+-- convert_string_datum
+CREATE OR REPLACE FUNCTION int_text_proc(int, text) RETURNS bool AS $$
+BEGIN
+ RETURN ($1 > 500);
+END;
+$$ LANGUAGE plpgsql;
+CREATE OPERATOR > (
+ LEFTARG = int,
+ RIGHTARG = text,
+ PROCEDURE = int_text_proc,
+ RESTRICT = scalargtsel
+);
+EXPLAIN (COSTS OFF) SELECT * FROM scalar_int WHERE a > '30'::text;
+ QUERY PLAN
+----------------------------
+ Seq Scan on scalar_int
+ Filter: (a > '30'::text)
+(2 rows)
+
+-- convert_timevalue_to_scalar
+CREATE OR REPLACE FUNCTION int_timestamp_proc(int, timestamptz) RETURNS bool AS $$
+BEGIN
+ RETURN ($1 > 500);
+END;
+$$ LANGUAGE plpgsql;
+CREATE OPERATOR > (
+ LEFTARG = int,
+ RIGHTARG = timestamptz,
+ PROCEDURE = int_timestamp_proc,
+ RESTRICT = scalargtsel
+);
+EXPLAIN (COSTS OFF) SELECT * FROM scalar_int WHERE a > now();
+ QUERY PLAN
+------------------------
+ Seq Scan on scalar_int
+ Filter: (a > now())
+(2 rows)
+
+-- convert_network_to_scalar
+CREATE OR REPLACE FUNCTION int_inet_proc(int, inet) RETURNS bool AS $$
+BEGIN
+ RETURN ($1 > 500);
+END;
+$$ LANGUAGE plpgsql;
+CREATE OPERATOR > (
+ LEFTARG = int,
+ RIGHTARG = inet,
+ PROCEDURE = int_inet_proc,
+ RESTRICT = scalargtsel
+);
+EXPLAIN (COSTS OFF) SELECT * FROM scalar_int WHERE a > '127.0.0.1'::inet;
+ QUERY PLAN
+-----------------------------------
+ Seq Scan on scalar_int
+ Filter: (a > '127.0.0.1'::inet)
+(2 rows)
+
+DROP TABLE scalar_int;
+DROP TABLE scalar_text;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index ad9434f..019dcf5 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -60,7 +60,7 @@ test: create_index create_view
# ----------
# Another group of parallel tests
# ----------
-test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views rolenames roleattributes create_am hash_func
+test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views rolenames roleattributes create_am hash_func convert_to_scalar
# ----------
# sanity_check does a vacuum, affecting the sort order of SELECT *
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 27cd498..050421e 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -69,6 +69,7 @@ test: create_view
test: create_aggregate
test: create_function_3
test: create_cast
+test: convert_to_scalar
test: constraints
test: triggers
test: inherit
diff --git a/src/test/regress/sql/convert_to_scalar.sql b/src/test/regress/sql/convert_to_scalar.sql
new file mode 100644
index 0000000..f984f48
--- /dev/null
+++ b/src/test/regress/sql/convert_to_scalar.sql
@@ -0,0 +1,105 @@
+-- tables used in these tests
+
+create table scalar_text (a text);
+
+insert into scalar_text select i::text from generate_series(1,1000) s(i);
+
+analyze scalar_text;
+
+
+create table scalar_int (a int);
+
+insert into scalar_int select i from generate_series(1,1000) s(i);
+
+analyze scalar_int;
+
+
+-- convert_bytea_to_scalar
+
+CREATE OR REPLACE FUNCTION int_bytea_proc(int, bytea) RETURNS bool AS $$
+BEGIN
+ RETURN ($1 > 500);
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OPERATOR > (
+ LEFTARG = int,
+ RIGHTARG = bytea,
+ PROCEDURE = int_bytea_proc,
+ RESTRICT = scalargtsel
+);
+
+EXPLAIN (COSTS OFF) SELECT * FROM scalar_int
+WHERE a > E'\x37666565353'::bytea;
+
+
+-- convert_numeric_to_scalar
+
+CREATE OR REPLACE FUNCTION text_int_proc(text, int) RETURNS bool AS $$
+BEGIN
+ RETURN ($1::int > 500);
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OPERATOR > (
+ LEFTARG = text,
+ RIGHTARG = int,
+ PROCEDURE = text_int_proc,
+ RESTRICT = scalargtsel
+);
+
+EXPLAIN (COSTS OFF) SELECT * FROM scalar_text WHERE a > 30;
+
+-- convert_string_datum
+
+CREATE OR REPLACE FUNCTION int_text_proc(int, text) RETURNS bool AS $$
+BEGIN
+ RETURN ($1 > 500);
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OPERATOR > (
+ LEFTARG = int,
+ RIGHTARG = text,
+ PROCEDURE = int_text_proc,
+ RESTRICT = scalargtsel
+);
+
+EXPLAIN (COSTS OFF) SELECT * FROM scalar_int WHERE a > '30'::text;
+
+-- convert_timevalue_to_scalar
+
+CREATE OR REPLACE FUNCTION int_timestamp_proc(int, timestamptz) RETURNS bool AS $$
+BEGIN
+ RETURN ($1 > 500);
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OPERATOR > (
+ LEFTARG = int,
+ RIGHTARG = timestamptz,
+ PROCEDURE = int_timestamp_proc,
+ RESTRICT = scalargtsel
+);
+
+EXPLAIN (COSTS OFF) SELECT * FROM scalar_int WHERE a > now();
+
+-- convert_network_to_scalar
+
+CREATE OR REPLACE FUNCTION int_inet_proc(int, inet) RETURNS bool AS $$
+BEGIN
+ RETURN ($1 > 500);
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OPERATOR > (
+ LEFTARG = int,
+ RIGHTARG = inet,
+ PROCEDURE = int_inet_proc,
+ RESTRICT = scalargtsel
+);
+
+EXPLAIN (COSTS OFF) SELECT * FROM scalar_int WHERE a > '127.0.0.1'::inet;
+
+DROP TABLE scalar_int;
+DROP TABLE scalar_text;