Skip to content

Commit 754f2d2

Browse files
committed
Add strict comparison operators that error out when dimensions of arguments do not match: << <<= == <<>> >>= >>.
1 parent 247d2d4 commit 754f2d2

File tree

7 files changed

+277
-0
lines changed

7 files changed

+277
-0
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
trusty.
1010
* Support send/receive via the binary protocol.
1111
* Support Infinity and NaN.
12+
* Add strict comparison operators that error out when dimensions of arguments
13+
do not match: << <<= == <<>> >>= >>.
1214

1315
6.0: Mar 7, 2018
1416
----------------

debian/changelog

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ postgresql-unit (7.0-1) UNRELEASED; urgency=medium
99
trusty.
1010
* Support send/receive via the binary protocol.
1111
* Support Infinity and NaN.
12+
* Add strict comparison operators that error out when dimensions of
13+
arguments do not match: << <<= == <<>> >>= >>.
1214

1315
-- Christoph Berg <[email protected]> Sun, 08 Jul 2018 21:46:17 +0200
1416

expected/compare.out

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,52 @@ EXPLAIN (COSTS OFF) SELECT * FROM u WHERE u = '300' * kilogram();
183183
Index Cond: (u = '300 kg'::unit)
184184
(2 rows)
185185

186+
-- test strict operators
187+
SELECT '1 m'::unit << '1 m'::unit;
188+
?column?
189+
----------
190+
f
191+
(1 row)
192+
193+
SELECT '1 m'::unit << '1 A'::unit;
194+
ERROR: dimension mismatch in "strict comparison" operation: "1 m", "1 A"
195+
SELECT '1 m'::unit <<= '1 m'::unit;
196+
?column?
197+
----------
198+
t
199+
(1 row)
200+
201+
SELECT '1 m'::unit <<= '1 A'::unit;
202+
ERROR: dimension mismatch in "strict comparison" operation: "1 m", "1 A"
203+
SELECT '1 m'::unit == '1 m'::unit;
204+
?column?
205+
----------
206+
t
207+
(1 row)
208+
209+
SELECT '1 m'::unit == '1 A'::unit;
210+
ERROR: dimension mismatch in "strict comparison" operation: "1 m", "1 A"
211+
SELECT '1 m'::unit <<>> '1 m'::unit;
212+
?column?
213+
----------
214+
f
215+
(1 row)
216+
217+
SELECT '1 m'::unit <<>> '1 A'::unit;
218+
ERROR: dimension mismatch in "strict comparison" operation: "1 m", "1 A"
219+
SELECT '1 m'::unit >>= '1 m'::unit;
220+
?column?
221+
----------
222+
t
223+
(1 row)
224+
225+
SELECT '1 m'::unit >>= '1 A'::unit;
226+
ERROR: dimension mismatch in "strict comparison" operation: "1 m", "1 A"
227+
SELECT '1 m'::unit >> '1 m'::unit;
228+
?column?
229+
----------
230+
f
231+
(1 row)
232+
233+
SELECT '1 m'::unit >> '1 A'::unit;
234+
ERROR: dimension mismatch in "strict comparison" operation: "1 m", "1 A"

sql/compare.sql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,17 @@ SELECT * FROM u WHERE u = meter(400);
3737
SELECT * FROM u WHERE u = '300' * kilogram();
3838
EXPLAIN (COSTS OFF) SELECT * FROM u WHERE u = meter(400);
3939
EXPLAIN (COSTS OFF) SELECT * FROM u WHERE u = '300' * kilogram();
40+
41+
-- test strict operators
42+
SELECT '1 m'::unit << '1 m'::unit;
43+
SELECT '1 m'::unit << '1 A'::unit;
44+
SELECT '1 m'::unit <<= '1 m'::unit;
45+
SELECT '1 m'::unit <<= '1 A'::unit;
46+
SELECT '1 m'::unit == '1 m'::unit;
47+
SELECT '1 m'::unit == '1 A'::unit;
48+
SELECT '1 m'::unit <<>> '1 m'::unit;
49+
SELECT '1 m'::unit <<>> '1 A'::unit;
50+
SELECT '1 m'::unit >>= '1 m'::unit;
51+
SELECT '1 m'::unit >>= '1 A'::unit;
52+
SELECT '1 m'::unit >> '1 m'::unit;
53+
SELECT '1 m'::unit >> '1 A'::unit;

unit--6--7.sql.in

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,65 @@ CREATE OPERATOR @ (
3535
procedure = unit_at
3636
);
3737

38+
-- strict comparisons
39+
40+
CREATE FUNCTION unit_strict_lt(unit, unit) RETURNS bool
41+
AS '$libdir/unit' LANGUAGE C IMMUTABLE STRICT;
42+
CREATE FUNCTION unit_strict_le(unit, unit) RETURNS bool
43+
AS '$libdir/unit' LANGUAGE C IMMUTABLE STRICT;
44+
CREATE FUNCTION unit_strict_eq(unit, unit) RETURNS bool
45+
AS '$libdir/unit' LANGUAGE C IMMUTABLE STRICT;
46+
CREATE FUNCTION unit_strict_ne(unit, unit) RETURNS bool
47+
AS '$libdir/unit' LANGUAGE C IMMUTABLE STRICT;
48+
CREATE FUNCTION unit_strict_ge(unit, unit) RETURNS bool
49+
AS '$libdir/unit' LANGUAGE C IMMUTABLE STRICT;
50+
CREATE FUNCTION unit_strict_gt(unit, unit) RETURNS bool
51+
AS '$libdir/unit' LANGUAGE C IMMUTABLE STRICT;
52+
53+
CREATE OPERATOR << (
54+
leftarg = unit, rightarg = unit, procedure = unit_strict_lt,
55+
commutator = >> , negator = >>= ,
56+
restrict = scalarltsel, join = scalarltjoinsel
57+
);
58+
CREATE OPERATOR <<= (
59+
leftarg = unit, rightarg = unit, procedure = unit_strict_le,
60+
commutator = >>= , negator = >> ,
61+
restrict = scalarltsel, join = scalarltjoinsel
62+
);
63+
CREATE OPERATOR == (
64+
leftarg = unit, rightarg = unit, procedure = unit_strict_eq,
65+
commutator = == , negator = <<>> ,
66+
restrict = eqsel, join = eqjoinsel
67+
);
68+
CREATE OPERATOR <<>> (
69+
leftarg = unit, rightarg = unit, procedure = unit_strict_ne,
70+
commutator = <<>> , negator = == ,
71+
restrict = neqsel, join = neqjoinsel
72+
);
73+
CREATE OPERATOR >>= (
74+
leftarg = unit, rightarg = unit, procedure = unit_strict_ge,
75+
commutator = <<= , negator = << ,
76+
restrict = scalargtsel, join = scalargtjoinsel
77+
);
78+
CREATE OPERATOR >> (
79+
leftarg = unit, rightarg = unit, procedure = unit_strict_gt,
80+
commutator = << , negator = <<= ,
81+
restrict = scalargtsel, join = scalargtjoinsel
82+
);
83+
84+
CREATE FUNCTION unit_strict_cmp(unit, unit)
85+
RETURNS int4
86+
AS '$libdir/unit'
87+
LANGUAGE C IMMUTABLE STRICT;
88+
89+
CREATE OPERATOR CLASS unit_strict_ops
90+
FOR TYPE unit USING btree AS
91+
OPERATOR 1 << ,
92+
OPERATOR 2 <<= ,
93+
OPERATOR 3 == ,
94+
OPERATOR 4 >>= ,
95+
OPERATOR 5 >> ,
96+
FUNCTION 1 unit_strict_cmp(unit, unit);
97+
3898
-- load prefixes and units tables
3999
SELECT unit_load();

unit--7.sql.in

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,66 @@ CREATE OPERATOR CLASS unit_ops
516516
OPERATOR 5 > ,
517517
FUNCTION 1 unit_cmp(unit, unit);
518518

519+
-- strict comparisons
520+
521+
CREATE FUNCTION unit_strict_lt(unit, unit) RETURNS bool
522+
AS '$libdir/unit' LANGUAGE C IMMUTABLE STRICT;
523+
CREATE FUNCTION unit_strict_le(unit, unit) RETURNS bool
524+
AS '$libdir/unit' LANGUAGE C IMMUTABLE STRICT;
525+
CREATE FUNCTION unit_strict_eq(unit, unit) RETURNS bool
526+
AS '$libdir/unit' LANGUAGE C IMMUTABLE STRICT;
527+
CREATE FUNCTION unit_strict_ne(unit, unit) RETURNS bool
528+
AS '$libdir/unit' LANGUAGE C IMMUTABLE STRICT;
529+
CREATE FUNCTION unit_strict_ge(unit, unit) RETURNS bool
530+
AS '$libdir/unit' LANGUAGE C IMMUTABLE STRICT;
531+
CREATE FUNCTION unit_strict_gt(unit, unit) RETURNS bool
532+
AS '$libdir/unit' LANGUAGE C IMMUTABLE STRICT;
533+
534+
CREATE OPERATOR << (
535+
leftarg = unit, rightarg = unit, procedure = unit_strict_lt,
536+
commutator = >> , negator = >>= ,
537+
restrict = scalarltsel, join = scalarltjoinsel
538+
);
539+
CREATE OPERATOR <<= (
540+
leftarg = unit, rightarg = unit, procedure = unit_strict_le,
541+
commutator = >>= , negator = >> ,
542+
restrict = scalarltsel, join = scalarltjoinsel
543+
);
544+
CREATE OPERATOR == (
545+
leftarg = unit, rightarg = unit, procedure = unit_strict_eq,
546+
commutator = == , negator = <<>> ,
547+
restrict = eqsel, join = eqjoinsel
548+
);
549+
CREATE OPERATOR <<>> (
550+
leftarg = unit, rightarg = unit, procedure = unit_strict_ne,
551+
commutator = <<>> , negator = == ,
552+
restrict = neqsel, join = neqjoinsel
553+
);
554+
CREATE OPERATOR >>= (
555+
leftarg = unit, rightarg = unit, procedure = unit_strict_ge,
556+
commutator = <<= , negator = << ,
557+
restrict = scalargtsel, join = scalargtjoinsel
558+
);
559+
CREATE OPERATOR >> (
560+
leftarg = unit, rightarg = unit, procedure = unit_strict_gt,
561+
commutator = << , negator = <<= ,
562+
restrict = scalargtsel, join = scalargtjoinsel
563+
);
564+
565+
CREATE FUNCTION unit_strict_cmp(unit, unit)
566+
RETURNS int4
567+
AS '$libdir/unit'
568+
LANGUAGE C IMMUTABLE STRICT;
569+
570+
CREATE OPERATOR CLASS unit_strict_ops
571+
FOR TYPE unit USING btree AS
572+
OPERATOR 1 << ,
573+
OPERATOR 2 <<= ,
574+
OPERATOR 3 == ,
575+
OPERATOR 4 >>= ,
576+
OPERATOR 5 >> ,
577+
FUNCTION 1 unit_strict_cmp(unit, unit);
578+
519579
-- aggregates
520580

521581
CREATE AGGREGATE sum(unit)

unit.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,96 @@ unit_cmp(PG_FUNCTION_ARGS)
11401140
PG_RETURN_INT32(unit_cmp_internal(a, b));
11411141
}
11421142

1143+
/* strict comparisons (error out when dimensions do not match) */
1144+
1145+
static int
1146+
unit_strict_cmp_internal(Unit *a, Unit *b)
1147+
{
1148+
test_same_dimension("strict comparison", a, b);
1149+
if (a->value < b->value)
1150+
return -1;
1151+
if (a->value > b->value)
1152+
return 1;
1153+
return memcmp(a->units, b->units, N_UNITS);
1154+
}
1155+
1156+
PG_FUNCTION_INFO_V1(unit_strict_lt);
1157+
1158+
Datum
1159+
unit_strict_lt(PG_FUNCTION_ARGS)
1160+
{
1161+
Unit *a = (Unit *) PG_GETARG_POINTER(0);
1162+
Unit *b = (Unit *) PG_GETARG_POINTER(1);
1163+
1164+
PG_RETURN_BOOL(unit_strict_cmp_internal(a, b) < 0);
1165+
}
1166+
1167+
PG_FUNCTION_INFO_V1(unit_strict_le);
1168+
1169+
Datum
1170+
unit_strict_le(PG_FUNCTION_ARGS)
1171+
{
1172+
Unit *a = (Unit *) PG_GETARG_POINTER(0);
1173+
Unit *b = (Unit *) PG_GETARG_POINTER(1);
1174+
1175+
PG_RETURN_BOOL(unit_strict_cmp_internal(a, b) <= 0);
1176+
}
1177+
1178+
PG_FUNCTION_INFO_V1(unit_strict_eq);
1179+
1180+
Datum
1181+
unit_strict_eq(PG_FUNCTION_ARGS)
1182+
{
1183+
Unit *a = (Unit *) PG_GETARG_POINTER(0);
1184+
Unit *b = (Unit *) PG_GETARG_POINTER(1);
1185+
1186+
PG_RETURN_BOOL(unit_strict_cmp_internal(a, b) == 0);
1187+
}
1188+
1189+
PG_FUNCTION_INFO_V1(unit_strict_ne);
1190+
1191+
Datum
1192+
unit_strict_ne(PG_FUNCTION_ARGS)
1193+
{
1194+
Unit *a = (Unit *) PG_GETARG_POINTER(0);
1195+
Unit *b = (Unit *) PG_GETARG_POINTER(1);
1196+
1197+
PG_RETURN_BOOL(unit_strict_cmp_internal(a, b) != 0);
1198+
}
1199+
1200+
PG_FUNCTION_INFO_V1(unit_strict_ge);
1201+
1202+
Datum
1203+
unit_strict_ge(PG_FUNCTION_ARGS)
1204+
{
1205+
Unit *a = (Unit *) PG_GETARG_POINTER(0);
1206+
Unit *b = (Unit *) PG_GETARG_POINTER(1);
1207+
1208+
PG_RETURN_BOOL(unit_strict_cmp_internal(a, b) >= 0);
1209+
}
1210+
1211+
PG_FUNCTION_INFO_V1(unit_strict_gt);
1212+
1213+
Datum
1214+
unit_strict_gt(PG_FUNCTION_ARGS)
1215+
{
1216+
Unit *a = (Unit *) PG_GETARG_POINTER(0);
1217+
Unit *b = (Unit *) PG_GETARG_POINTER(1);
1218+
1219+
PG_RETURN_BOOL(unit_strict_cmp_internal(a, b) > 0);
1220+
}
1221+
1222+
PG_FUNCTION_INFO_V1(unit_strict_cmp);
1223+
1224+
Datum
1225+
unit_strict_cmp(PG_FUNCTION_ARGS)
1226+
{
1227+
Unit *a = (Unit *) PG_GETARG_POINTER(0);
1228+
Unit *b = (Unit *) PG_GETARG_POINTER(1);
1229+
1230+
PG_RETURN_INT32(unit_strict_cmp_internal(a, b));
1231+
}
1232+
11431233
PG_FUNCTION_INFO_V1(unit_least);
11441234

11451235
Datum

0 commit comments

Comments
 (0)