Direct converting numeric types to bool
Attached patch allow direct convertion of numeric types to bool like
integer::bool.
Supported types:
- smallint;
- bigint;
- real;
- double precision;
- decimal(numeric).
This functionality is helped with migration from Oracle.
--
Nikita Zhuchkov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company
n.zhuchkov@postgrespro.ru писал 2018-02-28 18:04:
Show quoted text
Attached patch allow direct convertion of numeric types to bool like
integer::bool.
Supported types:
- smallint;
- bigint;
- real;
- double precision;
- decimal(numeric).This functionality is helped with migration from Oracle.
Attachments:
cast_bool_numeric_types_master.patchtext/x-diff; name=cast_bool_numeric_types_master.patchDownload
diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql
index 686528c..6cbfcf5 100644
--- a/src/backend/catalog/information_schema.sql
+++ b/src/backend/catalog/information_schema.sql
@@ -2970,3 +2970,83 @@ CREATE VIEW user_mappings AS
FROM _pg_user_mappings;
GRANT SELECT ON user_mappings TO PUBLIC;
+
+-- bool --> smallint(int2)
+CREATE OR REPLACE FUNCTION bool_smallint(boolean)
+ RETURNS smallint AS
+ 'bool_int2'
+ LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE
+ COST 1;
+CREATE CAST (boolean AS smallint) WITH FUNCTION bool_smallint(boolean) as implicit;
+
+-- smallint(int2) --> bool
+CREATE OR REPLACE FUNCTION smallint_bool(smallint)
+ RETURNS bool AS
+ 'int2_bool'
+ LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE
+ COST 1;
+CREATE CAST (smallint AS boolean) WITH FUNCTION smallint_bool(smallint) as implicit;
+
+-- bigint(int8) --> bool
+CREATE OR REPLACE FUNCTION bool_bigint(boolean)
+ RETURNS bigint AS
+ 'bool_int8'
+ LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE
+ COST 1;
+CREATE CAST (boolean AS bigint) WITH FUNCTION bool_bigint(boolean) as implicit;
+
+-- bool --> bigint(int8)
+CREATE OR REPLACE FUNCTION bigint_bool(bigint)
+ RETURNS bool AS
+ 'int8_bool'
+ LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE
+ COST 1;
+CREATE CAST (bigint AS boolean) WITH FUNCTION bigint_bool(bigint) as implicit;
+
+-- double precision(float8) --> bool
+CREATE OR REPLACE FUNCTION double_precision_bool(double precision)
+ RETURNS bool AS
+ 'float8_bool'
+ LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE
+ COST 1;
+CREATE CAST (double precision AS boolean) WITH FUNCTION double_precision_bool(double precision) as implicit;
+
+-- bool --> double precision(float8)
+CREATE OR REPLACE FUNCTION bool_double_precision(boolean)
+ RETURNS double precision AS
+ 'bool_float8'
+ LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE
+ COST 1;
+CREATE CAST (boolean AS double precision) WITH FUNCTION bool_double_precision(boolean) as implicit;
+
+-- real(float4) --> bool
+CREATE OR REPLACE FUNCTION real_bool(real)
+ RETURNS bool AS
+ 'float4_bool'
+ LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE
+ COST 1;
+CREATE CAST (real AS boolean) WITH FUNCTION real_bool(real) as implicit;
+
+-- bool --> real(float4)
+CREATE OR REPLACE FUNCTION bool_real(boolean)
+ RETURNS real AS
+ 'bool_float4'
+ LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE
+ COST 1;
+CREATE CAST (boolean AS real) WITH FUNCTION bool_real(boolean) as implicit;
+
+-- numeric(decimal) --> bool
+CREATE OR REPLACE FUNCTION numeric_bool(decimal)
+ RETURNS bool AS
+ 'numeric_bool'
+ LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE
+ COST 1;
+CREATE CAST (decimal AS boolean) WITH FUNCTION numeric_bool(decimal) as implicit;
+
+-- bool --> numeric(decimal)
+CREATE OR REPLACE FUNCTION bool_numeric(boolean)
+ RETURNS decimal AS
+ 'bool_numeric'
+ LANGUAGE internal IMMUTABLE STRICT PARALLEL SAFE
+ COST 1;
+CREATE CAST (boolean AS decimal) WITH FUNCTION bool_numeric(boolean) as implicit;
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index bc6a3e0..a687104 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -1331,6 +1331,53 @@ i2tof(PG_FUNCTION_ARGS)
PG_RETURN_FLOAT4((float4) num);
}
+ /*
+ * float4_bool - converts a float4 number to a bool
+ * epsilon - machine epsilon gives an upper bound on the relative error
+ * due to rounding in floating point arithmetic.
+ */
+Datum
+float4_bool(PG_FUNCTION_ARGS)
+{
+ float epsilon = 5.96e-08;
+
+ if (fabs(PG_GETARG_FLOAT4(0)) <= epsilon)
+ PG_RETURN_BOOL(false);
+ else
+ PG_RETURN_BOOL(true);
+}
+
+/*
+ * bool_float4 - converts a bool to a float4 number
+ */
+Datum
+bool_float4(PG_FUNCTION_ARGS)
+{
+ if (PG_GETARG_BOOL(0) == false)
+ PG_RETURN_FLOAT4(0);
+ else
+ PG_RETURN_FLOAT4(1);
+}
+
+/*
+ * float8_bool - converts a float4 number to a bool
+ * epsilon - machine epsilon gives an upper bound on the relative error
+ * due to rounding in floating point arithmetic.
+ */
+Datum
+float8_bool(PG_FUNCTION_ARGS)
+{
+ float epsilon = 1.11e-16;
+
+ if (fabs(PG_GETARG_FLOAT8(0)) <= epsilon)
+ PG_RETURN_BOOL(false);
+ else
+ PG_RETURN_BOOL(true);
+}
+
+/*
+ * bool_float8 - converts a bool to a float4 number
+ */
+Datum
+bool_float8(PG_FUNCTION_ARGS)
+{
+ if (PG_GETARG_BOOL(0) == false)
+ PG_RETURN_FLOAT8(0);
+ else
+ PG_RETURN_FLOAT8(1);
+}
/*
* =======================
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index 559c365..a6ea79b 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -354,6 +354,26 @@ bool_int4(PG_FUNCTION_ARGS)
PG_RETURN_INT32(1);
}
+/* Cast int2 -> bool */
+Datum
+int2_bool(PG_FUNCTION_ARGS)
+{
+ if (PG_GETARG_INT16(0) == 0)
+ PG_RETURN_BOOL(false);
+ else
+ PG_RETURN_BOOL(true);
+}
+
+/* Cast bool -> int2 */
+Datum
+bool_int2(PG_FUNCTION_ARGS)
+{
+ if (PG_GETARG_BOOL(0) == false)
+ PG_RETURN_INT16(0);
+ else
+ PG_RETURN_INT16(1);
+}
+
/*
* ============================
* COMPARISON OPERATOR ROUTINES
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index e6bae68..06ec92d 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -1357,3 +1357,23 @@ generate_series_step_int8(PG_FUNCTION_ARGS)
/* do when there is no more left */
SRF_RETURN_DONE(funcctx);
}
+
+/* Cast int8 -> bool */
+Datum
+int8_bool(PG_FUNCTION_ARGS)
+{
+ if (PG_GETARG_INT64(0) == 0)
+ PG_RETURN_BOOL(false);
+ else
+ PG_RETURN_BOOL(true);
+}
+
+/* Cast bool -> int8 */
+Datum
+bool_int8(PG_FUNCTION_ARGS)
+{
+ if (PG_GETARG_BOOL(0) == false)
+ PG_RETURN_INT64(0);
+ else
+ PG_RETURN_INT64(1);
+}
\ No newline at end of file
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 5b34bad..513dabb 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -3184,6 +3184,38 @@ numeric_float8(PG_FUNCTION_ARGS)
PG_RETURN_DATUM(result);
}
+Datum
+bool_numeric(PG_FUNCTION_ARGS)
+{
+ bool val = PG_GETARG_BOOL(0);
+ Numeric res;
+ NumericVar result;
+
+ init_var(&result);
+
+ int64_to_numericvar((int64) val, &result);
+
+ res = make_result(&result);
+
+ free_var(&result);
+
+ PG_RETURN_NUMERIC(res);
+}
+
+Datum
+numeric_bool(PG_FUNCTION_ARGS)
+{
+ Numeric num = PG_GETARG_NUMERIC(0);
+ Numeric num2;
+ NumericVar num2v;
+
+ init_var(&num2v);
+
+ int64_to_numericvar((int64) 0, &num2v);
+ num2 = make_result(&num2v);
+
+ PG_RETURN_BOOL(cmp_numerics(num, num2) != 0);
+}
/*
* Convert numeric to float8; if out of range, return +/- HUGE_VAL
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 2a53213..28b823f 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -5561,6 +5561,32 @@ DESCR("list of files in the WAL directory");
DATA(insert OID = 5028 ( satisfies_hash_partition PGNSP PGUID 12 1 0 2276 0 f f f f f f i s 4 0 16 "26 23 23 2276" _null_ "{i,i,i,v}" _null_ _null_ _null_ satisfies_hash_partition _null_ _null_ _null_ ));
DESCR("hash partition CHECK constraint");
+/* Convertation type->bool and bool->type for numeric types exclude int4 */
+DATA(insert OID = 7557 ( bool PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 16 "20" _null_ _null_ _null_ _null_ _null_ int8_bool _null_ _null_ _null_ ));
+DESCR("convert int8 to boolean");
+DATA(insert OID = 7558 ( int8 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 20 "16" _null_ _null_ _null_ _null_ _null_ bool_int8 _null_ _null_ _null_ ));
+DESCR("convert boolean to int8");
+
+DATA(insert OID = 7559 ( bool PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 16 "21" _null_ _null_ _null_ _null_ _null_ int2_bool _null_ _null_ _null_ ));
+DESCR("convert int2 to boolean");
+DATA(insert OID = 7560 ( int2 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 21 "16" _null_ _null_ _null_ _null_ _null_ bool_int2 _null_ _null_ _null_ ));
+DESCR("convert boolean to int2");
+
+DATA(insert OID = 7561 ( bool PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 16 "701" _null_ _null_ _null_ _null_ _null_ float8_bool _null_ _null_ _null_ ));
+DESCR("convert float8 to boolean");
+DATA(insert OID = 7562 ( float8 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 701 "16" _null_ _null_ _null_ _null_ _null_ bool_float8 _null_ _null_ _null_ ));
+DESCR("convert boolean to float8");
+
+DATA(insert OID = 7563 ( bool PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 16 "700" _null_ _null_ _null_ _null_ _null_ float4_bool _null_ _null_ _null_ ));
+DESCR("convert float4 to boolean");
+DATA(insert OID = 7564 ( float4 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 700 "16" _null_ _null_ _null_ _null_ _null_ bool_float4 _null_ _null_ _null_ ));
+DESCR("convert boolean to float4");
+
+DATA(insert OID = 7565 ( numeric PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 1700 "16" _null_ _null_ _null_ _null_ _null_ bool_numeric _null_ _null_ _null_ ));
+DESCR("convert numeric to boolean");
+DATA(insert OID = 7566 ( bool PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 16 "1700" _null_ _null_ _null_ _null_ _null_ numeric_bool _null_ _null_ _null_ ));
+DESCR("convert boolean to numeric");
+
/*
* Symbolic values for provolatile column: these indicate whether the result
* of a function is dependent *only* on the values of its explicit arguments,
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index af416ad..d9ffe98 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -1851,8 +1851,8 @@ select * from anothertab;
(2 rows)
alter table anothertab alter column atcol1 type boolean; -- fails
-ERROR: column "atcol1" cannot be cast automatically to type boolean
-HINT: You might need to specify "USING atcol1::boolean".
+ERROR: operator is not unique: boolean <= integer
+HINT: Could not choose a best candidate operator. You might need to add explicit type casts.
alter table anothertab alter column atcol1 type boolean using atcol1::int; -- fails
ERROR: result of USING clause for column "atcol1" cannot be cast automatically to type boolean
HINT: You might need to add an explicit cast.
@@ -1890,12 +1890,13 @@ select * from anothertab;
alter table anothertab alter column atcol1 type boolean
using case when atcol1 % 2 = 0 then true else false end; -- fails
-ERROR: default for column "atcol1" cannot be cast automatically to type boolean
+ERROR: operator is not unique: boolean <= integer
+HINT: Could not choose a best candidate operator. You might need to add explicit type casts.
alter table anothertab alter column atcol1 drop default;
alter table anothertab alter column atcol1 type boolean
using case when atcol1 % 2 = 0 then true else false end; -- fails
-ERROR: operator does not exist: boolean <= integer
-HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
+ERROR: operator is not unique: boolean <= integer
+HINT: Could not choose a best candidate operator. You might need to add explicit type casts.
alter table anothertab drop constraint anothertab_chk;
alter table anothertab drop constraint anothertab_chk; -- fails
ERROR: constraint "anothertab_chk" of relation "anothertab" does not exist
diff --git a/src/test/regress/expected/float4.out b/src/test/regress/expected/float4.out
index fd46a4a..342b671 100644
--- a/src/test/regress/expected/float4.out
+++ b/src/test/regress/expected/float4.out
@@ -257,3 +257,77 @@ SELECT '' AS five, * FROM FLOAT4_TBL;
| -1.23457e-20
(5 rows)
+-- strict direct convertation from real(float4) to bool
+select 2.2::real::bool;
+ bool
+------
+ t
+(1 row)
+
+select 0.2::real::bool;
+ bool
+------
+ t
+(1 row)
+
+select 0.0::real::bool;
+ bool
+------
+ f
+(1 row)
+
+select 'NaN'::real::bool;
+ bool
+------
+ t
+(1 row)
+
+select '+infinity'::real::bool;
+ bool
+------
+ t
+(1 row)
+
+select '-infinity'::real::bool;
+ bool
+------
+ t
+(1 row)
+
+select 2.22e-16::real::bool;
+ bool
+------
+ f
+(1 row)
+
+select 6.96e-08::real::bool;
+ bool
+------
+ t
+(1 row)
+
+select 5.96e-08::real::bool;
+ bool
+------
+ f
+(1 row)
+
+select (-2.22e-16)::real::bool;
+ bool
+------
+ f
+(1 row)
+
+select (-6.96e-08)::real::bool;
+ bool
+------
+ t
+(1 row)
+
+select (-5.96e-08)::real::bool;
+ bool
+------
+ f
+(1 row)
+
+-- strict direct convertation from bool to real(float4)
+select true::bool::real;
+ float4
+--------
+ 1
+(1 row)
+
+select false::bool::real;
+ float4
+--------
+ 0
+(1 row)
+
diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out
index 20c985e..acb340c 100644
--- a/src/test/regress/expected/float8.out
+++ b/src/test/regress/expected/float8.out
@@ -548,3 +548,77 @@ FROM (SELECT 10*cosd(a), 10*sind(a)
(5 rows)
RESET extra_float_digits;
+-- strict direct convertation from double precision(float8) to bool
+select 2.2::double precision::bool;
+ bool
+------
+ t
+(1 row)
+
+select 0.2::double precision::bool;
+ bool
+------
+ t
+(1 row)
+
+select 0.0::double precision::bool;
+ bool
+------
+ f
+(1 row)
+
+select 'NaN'::double precision::bool;
+ bool
+------
+ t
+(1 row)
+
+select '+infinity'::double precision::bool;
+ bool
+------
+ t
+(1 row)
+
+select '-infinity'::double precision::bool;
+ bool
+------
+ t
+(1 row)
+
+select 0.11e-16::double precision::bool;
+ bool
+------
+ f
+(1 row)
+
+select 2.96e-08::double precision::bool;
+ bool
+------
+ t
+(1 row)
+
+select 1.11e-16::double precision::bool;
+ bool
+------
+ f
+(1 row)
+
+select (-0.15e-17)::double precision::bool;
+ bool
+------
+ f
+(1 row)
+
+select (-2.96e-08)::double precision::bool;
+ bool
+------
+ t
+(1 row)
+
+select (-1.11e-16)::double precision::bool;
+ bool
+------
+ f
+(1 row)
+
+-- strict direct convertation from bool to double precision(float8)
+select true::bool::double precision;
+ float8
+--------
+ 1
+(1 row)
+
+select false::bool::double precision;
+ float8
+--------
+ 0
+(1 row)
+
diff --git a/src/test/regress/expected/int2.out b/src/test/regress/expected/int2.out
index 3ea4ed9..d5c81d1 100644
--- a/src/test/regress/expected/int2.out
+++ b/src/test/regress/expected/int2.out
@@ -306,3 +306,41 @@ FROM (VALUES (-2.5::numeric),
2.5 | 3
(7 rows)
+-- strict direct convertation from bool to smallint(int2)
+SELECT 1::bool::smallint;
+ int2
+------
+ 1
+(1 row)
+
+SELECT 0::bool::smallint;
+ int2
+------
+ 0
+(1 row)
+
+SELECT 100::bool::smallint;
+ int2
+------
+ 1
+(1 row)
+
+-- strict direct convertation from smallint(int2) to bool
+SELECT 1::smallint::bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT 0::smallint::bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT 100::smallint::bool;
+ bool
+------
+ t
+(1 row)
+
diff --git a/src/test/regress/expected/int8.out b/src/test/regress/expected/int8.out
index ed0bd34..f5b9277 100644
--- a/src/test/regress/expected/int8.out
+++ b/src/test/regress/expected/int8.out
@@ -886,3 +886,41 @@ FROM (VALUES (-2.5::numeric),
2.5 | 3
(7 rows)
+-- strict direct convertation from bool to bigint(int8)
+SELECT 1::bool::bigint;
+ int8
+------
+ 1
+(1 row)
+
+SELECT 0::bool::bigint;
+ int8
+------
+ 0
+(1 row)
+
+SELECT 1234567890::bool::bigint;
+ int8
+------
+ 1
+(1 row)
+
+-- strict direct convertation from bigint(int8) to bool
+SELECT 1::bigint::bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT 0::bigint::bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT 1234567890::bigint::bool;
+ bool
+------
+ t
+(1 row)
+
diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out
index 17985e8..2b426a4 100644
--- a/src/test/regress/expected/numeric.out
+++ b/src/test/regress/expected/numeric.out
@@ -2063,3 +2063,41 @@ SELECT SUM((-9999)::numeric) FROM generate_series(1, 100000);
-999900000
(1 row)
+-- strict direct convertation from bool to decimal(numeric)
+SELECT 1::bool::decimal;
+ numeric
+---------
+ 1
+(1 row)
+
+SELECT 0::bool::decimal;
+ numeric
+---------
+ 0
+(1 row)
+
+SELECT 1234567890::bool::decimal;
+ numeric
+---------
+ 1
+(1 row)
+
+-- strict direct convertation from decimal(numeric) to bool
+SELECT 1::decimal::bool;
+ bool
+------
+ t
+(1 row)
+
+SELECT 0::decimal::bool;
+ bool
+------
+ f
+(1 row)
+
+SELECT 1234567890::decimal::bool;
+ bool
+------
+ t
+(1 row)
+
diff --git a/src/test/regress/expected/prepare.out b/src/test/regress/expected/prepare.out
index 7016e82..460e78f 100644
--- a/src/test/regress/expected/prepare.out
+++ b/src/test/regress/expected/prepare.out
@@ -112,7 +112,7 @@ ERROR: wrong number of parameters for prepared statement "q3"
DETAIL: Expected 6 parameters but got 7.
-- wrong param types
EXECUTE q3(5::smallint, 10.5::float, false, 500::oid, 4::bigint, 'bytea');
-ERROR: parameter $3 of type boolean cannot be coerced to the expected type double precision
+ERROR: parameter $4 of type oid cannot be coerced to the expected type boolean
HINT: You will need to rewrite or cast the expression.
-- invalid type
PREPARE q4(nonexistenttype) AS SELECT $1;
diff --git a/src/test/regress/sql/float4.sql b/src/test/regress/sql/float4.sql
index 3b363f9..9a48085 100644
--- a/src/test/regress/sql/float4.sql
+++ b/src/test/regress/sql/float4.sql
@@ -81,3 +81,19 @@ UPDATE FLOAT4_TBL
WHERE FLOAT4_TBL.f1 > '0.0';
SELECT '' AS five, * FROM FLOAT4_TBL;
+
+-- strict direct convertation from real(float4) to bool
+select 2.2::real::bool;
+select 0.2::real::bool;
+select 0.0::real::bool;
+select 'NaN'::real::bool;
+select '+infinity'::real::bool;
+select '-infinity'::real::bool;
+select 2.22e-16::real::bool;
+select 6.96e-08::real::bool;
+select 5.96e-08::real::bool;
+select (-2.22e-16)::real::bool;
+select (-6.96e-08)::real::bool;
+select (-5.96e-08)::real::bool;
+
+-- strict direct convertation from bool to real(float4)
+select true::bool::real;
+select false::bool::real;
\ No newline at end of file
diff --git a/src/test/regress/sql/float8.sql b/src/test/regress/sql/float8.sql
index 215e7a4..5b85cfc 100644
--- a/src/test/regress/sql/float8.sql
+++ b/src/test/regress/sql/float8.sql
@@ -213,3 +213,19 @@ FROM (SELECT 10*cosd(a), 10*sind(a)
FROM generate_series(0, 360, 90) AS t(a)) AS t(x,y);
RESET extra_float_digits;
+
+-- strict direct convertation from double precision(float8) to bool
+select 2.2::double precision::bool;
+select 0.2::double precision::bool;
+select 0.0::double precision::bool;
+select 'NaN'::double precision::bool;
+select '+infinity'::double precision::bool;
+select '-infinity'::double precision::bool;
+select 0.11e-16::double precision::bool;
+select 2.96e-08::double precision::bool;
+select 1.11e-16::double precision::bool;
+select (-0.15e-17)::double precision::bool;
+select (-2.96e-08)::double precision::bool;
+select (-1.11e-16)::double precision::bool;
+
+-- strict direct convertation from bool to double precision(float8)
+select true::bool::double precision;
+select false::bool::double precision;
\ No newline at end of file
diff --git a/src/test/regress/sql/int2.sql b/src/test/regress/sql/int2.sql
index 7dbafb6..3652271 100644
--- a/src/test/regress/sql/int2.sql
+++ b/src/test/regress/sql/int2.sql
@@ -112,3 +112,13 @@ FROM (VALUES (-2.5::numeric),
(0.5::numeric),
(1.5::numeric),
(2.5::numeric)) t(x);
+
+-- strict direct convertation from bool to smallint(int2)
+SELECT 1::bool::smallint;
+SELECT 0::bool::smallint;
+SELECT 100::bool::smallint;
+
+-- strict direct convertation from smallint(int2) to bool
+SELECT 1::smallint::bool;
+SELECT 0::smallint::bool;
+SELECT 100::smallint::bool;
\ No newline at end of file
diff --git a/src/test/regress/sql/int8.sql b/src/test/regress/sql/int8.sql
index e890452..aaa2b19 100644
--- a/src/test/regress/sql/int8.sql
+++ b/src/test/regress/sql/int8.sql
@@ -225,3 +225,13 @@ FROM (VALUES (-2.5::numeric),
(0.5::numeric),
(1.5::numeric),
(2.5::numeric)) t(x);
+
+-- strict direct convertation from bool to bigint(int8)
+SELECT 1::bool::bigint;
+SELECT 0::bool::bigint;
+SELECT 1234567890::bool::bigint;
+
+-- strict direct convertation from bigint(int8) to bool
+SELECT 1::bigint::bool;
+SELECT 0::bigint::bool;
+SELECT 1234567890::bigint::bool;
\ No newline at end of file
diff --git a/src/test/regress/sql/numeric.sql b/src/test/regress/sql/numeric.sql
index d77504e..4398594 100644
--- a/src/test/regress/sql/numeric.sql
+++ b/src/test/regress/sql/numeric.sql
@@ -1036,3 +1036,13 @@ select scale(-13.000000000000000);
-- cases that need carry propagation
SELECT SUM(9999::numeric) FROM generate_series(1, 100000);
SELECT SUM((-9999)::numeric) FROM generate_series(1, 100000);
+
+-- strict direct convertation from bool to decimal(numeric)
+SELECT 1::bool::decimal;
+SELECT 0::bool::decimal;
+SELECT 1234567890::bool::decimal;
+
+-- strict direct convertation from decimal(numeric) to bool
+SELECT 1::decimal::bool;
+SELECT 0::decimal::bool;
+SELECT 1234567890::decimal::bool;
\ No newline at end of file
n.zhuchkov@postgrespro.ru writes:
Attached patch allow direct convertion of numeric types to bool like
integer::bool.
Supported types:
- smallint;
- bigint;
- real;
- double precision;
- decimal(numeric).
This functionality is helped with migration from Oracle.
I think you forgot to attach the patch, but in any case: is this
really a behavior we want? "Oracle has it" is not a good argument
in my view, nor do I recall people complaining that they need such
a behavior to migrate.
regards, tom lane
Hi
2018-02-28 16:06 GMT+01:00 <n.zhuchkov@postgrespro.ru>:
n.zhuchkov@postgrespro.ru писал 2018-02-28 18:04:
Attached patch allow direct convertion of numeric types to bool like
integer::bool.
Supported types:
- smallint;
- bigint;
- real;
- double precision;
- decimal(numeric).This functionality is helped with migration from Oracle.
Looks little bit obscure to upstream code (can lives as extension outside)
all work can be done be function
CREATE OR REPLACE FUNCTION public.to_bool(anyelement)
RETURNS boolean
LANGUAGE sql
IMMUTABLE STRICT
AS $function$
select $1::int::boolean $function$
I really doesn't see any sense to allow cast from double to boolean
-1 from me
Regards
Pavel
2018-02-28 16:13 GMT+01:00 Pavel Stehule <pavel.stehule@gmail.com>:
Hi
2018-02-28 16:06 GMT+01:00 <n.zhuchkov@postgrespro.ru>:
n.zhuchkov@postgrespro.ru писал 2018-02-28 18:04:
Attached patch allow direct convertion of numeric types to bool like
integer::bool.
Supported types:
- smallint;
- bigint;
- real;
- double precision;
- decimal(numeric).This functionality is helped with migration from Oracle.
Looks little bit obscure to upstream code (can lives as extension outside)
all work can be done be function
CREATE OR REPLACE FUNCTION public.to_bool(anyelement)
RETURNS boolean
LANGUAGE sql
IMMUTABLE STRICT
AS $function$
select $1::int::boolean $function$I really doesn't see any sense to allow cast from double to boolean
Long time Oracle had not boolean, so some ugly tricks was necessary there.
There are not reason do same in Postgres.
Show quoted text
-1 from me
Regards
Pavel
-----Original Message-----
From: n.zhuchkov@postgrespro.ru [mailto:n.zhuchkov@postgrespro.ru]
Sent: Wednesday, February 28, 2018 6:04 PM
To: pgsql-hackers <pgsql-hackers@postgresql.org>
Subject: Direct converting numeric types to bool
Attached patch allow direct convertion of numeric types to bool like
integer::bool.
Supported types:
- smallint;
- bigint;
- real;
- double precision;
- decimal(numeric).
This functionality is helped with migration from Oracle.
--
Nikita Zhuchkov
Postgres Professional: http://www.postgrespro.com The Russian Postgres
Company
Hello!
What prevent us from:
postgres=# select 1::bigint::int::boolean;
bool
------
t
(1 row)
It is just one additional casting and required no additional patching
--
Alex Ignatov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company
Thanks for your feedback!
Really, support migration from Oracle isn't the best argumentation for
this patch.
Yes, in postgres already exists int::boolean casting and in case:
select 10::bigint::int::boolean;
it will perfectly work. But if you want to cast more significant number:
select (2^32)::bigint::int::boolean;
you receive the boundary value error.
Also in operations with floating-point numbers, may arise a fault in the
results of calculations, because of which the number will always be cast
in true
Thus it sounds like not a bad idea to support direct casting from
numeric types to boolean. What do you think?
Alex Ignatov писал 2018-02-28 18:23:
Show quoted text
-----Original Message-----
From: n.zhuchkov@postgrespro.ru [mailto:n.zhuchkov@postgrespro.ru]
Sent: Wednesday, February 28, 2018 6:04 PM
To: pgsql-hackers <pgsql-hackers@postgresql.org>
Subject: Direct converting numeric types to boolAttached patch allow direct convertion of numeric types to bool like
integer::bool.
Supported types:
- smallint;
- bigint;
- real;
- double precision;
- decimal(numeric).This functionality is helped with migration from Oracle.
--
Nikita Zhuchkov
Postgres Professional: http://www.postgrespro.com The Russian Postgres
CompanyHello!
What prevent us from:
postgres=# select 1::bigint::int::boolean;
bool
------
t
(1 row)It is just one additional casting and required no additional patching
--
Alex Ignatov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company
n.zhuchkov@postgrespro.ru writes:
Yes, in postgres already exists int::boolean casting and in case:
select 10::bigint::int::boolean;
it will perfectly work. But if you want to cast more significant number:
select (2^32)::bigint::int::boolean;
you receive the boundary value error.
Right. I don't see a reason why we shouldn't create a bigint-to-bool
cast to fix that, and smallint-to-bool maybe for completeness. However,
I'm less excited about float or numeric to bool, because I don't think
there is any very principled argument about what such a cast should do
with infinities, NaNs, or denormalized numbers. Somebody who knows
what should happen for their own application can create their own cast
that handles those cases ... but I'm unsure that there's a one-size-
fits-all answer that we could put into a default behavior.
regards, tom lane