Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b163baa

Browse files
committed
Clean up some problems with redundant cross-type arithmetic operators. Add
int2-and-int8 implementations of the basic arithmetic operators +, -, *, /. This doesn't really add any new functionality, but it avoids "operator is not unique" failures that formerly occurred in these cases because the parser couldn't decide whether to promote the int2 to int4 or int8. We could alternatively have removed the existing cross-type operators, but experimentation shows that the cost of an additional type coercion expression node is noticeable compared to such cheap operators; so let's not give up any performance here. On the other hand, I removed the int2-and-int4 modulo (%) operators since they didn't seem as important from a performance standpoint. Per a complaint last January from ykhuang.
1 parent 4274726 commit b163baa

File tree

7 files changed

+223
-50
lines changed

7 files changed

+223
-50
lines changed

src/backend/utils/adt/int.c

+1-31
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.81 2008/01/01 19:45:52 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.82 2008/06/17 19:10:56 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1085,36 +1085,6 @@ int2mod(PG_FUNCTION_ARGS)
10851085
PG_RETURN_INT16(arg1 % arg2);
10861086
}
10871087

1088-
Datum
1089-
int24mod(PG_FUNCTION_ARGS)
1090-
{
1091-
int16 arg1 = PG_GETARG_INT16(0);
1092-
int32 arg2 = PG_GETARG_INT32(1);
1093-
1094-
if (arg2 == 0)
1095-
ereport(ERROR,
1096-
(errcode(ERRCODE_DIVISION_BY_ZERO),
1097-
errmsg("division by zero")));
1098-
/* No overflow is possible */
1099-
1100-
PG_RETURN_INT32(arg1 % arg2);
1101-
}
1102-
1103-
Datum
1104-
int42mod(PG_FUNCTION_ARGS)
1105-
{
1106-
int32 arg1 = PG_GETARG_INT32(0);
1107-
int16 arg2 = PG_GETARG_INT16(1);
1108-
1109-
if (arg2 == 0)
1110-
ereport(ERROR,
1111-
(errcode(ERRCODE_DIVISION_BY_ZERO),
1112-
errmsg("division by zero")));
1113-
/* No overflow is possible */
1114-
1115-
PG_RETURN_INT32(arg1 % arg2);
1116-
}
1117-
11181088

11191089
/* int[24]abs()
11201090
* Absolute value

src/backend/utils/adt/int8.c

+179-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.69 2008/04/21 00:26:45 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.70 2008/06/17 19:10:56 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -922,6 +922,184 @@ int48div(PG_FUNCTION_ARGS)
922922
PG_RETURN_INT64((int64) arg1 / arg2);
923923
}
924924

925+
Datum
926+
int82pl(PG_FUNCTION_ARGS)
927+
{
928+
int64 arg1 = PG_GETARG_INT64(0);
929+
int16 arg2 = PG_GETARG_INT16(1);
930+
int64 result;
931+
932+
result = arg1 + arg2;
933+
934+
/*
935+
* Overflow check. If the inputs are of different signs then their sum
936+
* cannot overflow. If the inputs are of the same sign, their sum had
937+
* better be that sign too.
938+
*/
939+
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
940+
ereport(ERROR,
941+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
942+
errmsg("bigint out of range")));
943+
PG_RETURN_INT64(result);
944+
}
945+
946+
Datum
947+
int82mi(PG_FUNCTION_ARGS)
948+
{
949+
int64 arg1 = PG_GETARG_INT64(0);
950+
int16 arg2 = PG_GETARG_INT16(1);
951+
int64 result;
952+
953+
result = arg1 - arg2;
954+
955+
/*
956+
* Overflow check. If the inputs are of the same sign then their
957+
* difference cannot overflow. If they are of different signs then the
958+
* result should be of the same sign as the first input.
959+
*/
960+
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
961+
ereport(ERROR,
962+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
963+
errmsg("bigint out of range")));
964+
PG_RETURN_INT64(result);
965+
}
966+
967+
Datum
968+
int82mul(PG_FUNCTION_ARGS)
969+
{
970+
int64 arg1 = PG_GETARG_INT64(0);
971+
int16 arg2 = PG_GETARG_INT16(1);
972+
int64 result;
973+
974+
result = arg1 * arg2;
975+
976+
/*
977+
* Overflow check. We basically check to see if result / arg1 gives arg2
978+
* again. There is one case where this fails: arg1 = 0 (which cannot
979+
* overflow).
980+
*
981+
* Since the division is likely much more expensive than the actual
982+
* multiplication, we'd like to skip it where possible. The best bang for
983+
* the buck seems to be to check whether both inputs are in the int32
984+
* range; if so, no overflow is possible.
985+
*/
986+
if (arg1 != (int64) ((int32) arg1) &&
987+
result / arg1 != arg2)
988+
ereport(ERROR,
989+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
990+
errmsg("bigint out of range")));
991+
PG_RETURN_INT64(result);
992+
}
993+
994+
Datum
995+
int82div(PG_FUNCTION_ARGS)
996+
{
997+
int64 arg1 = PG_GETARG_INT64(0);
998+
int16 arg2 = PG_GETARG_INT16(1);
999+
int64 result;
1000+
1001+
if (arg2 == 0)
1002+
ereport(ERROR,
1003+
(errcode(ERRCODE_DIVISION_BY_ZERO),
1004+
errmsg("division by zero")));
1005+
1006+
result = arg1 / arg2;
1007+
1008+
/*
1009+
* Overflow check. The only possible overflow case is for arg1 =
1010+
* INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN, which
1011+
* can't be represented on a two's-complement machine.
1012+
*/
1013+
if (arg2 == -1 && arg1 < 0 && result < 0)
1014+
ereport(ERROR,
1015+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1016+
errmsg("bigint out of range")));
1017+
PG_RETURN_INT64(result);
1018+
}
1019+
1020+
Datum
1021+
int28pl(PG_FUNCTION_ARGS)
1022+
{
1023+
int16 arg1 = PG_GETARG_INT16(0);
1024+
int64 arg2 = PG_GETARG_INT64(1);
1025+
int64 result;
1026+
1027+
result = arg1 + arg2;
1028+
1029+
/*
1030+
* Overflow check. If the inputs are of different signs then their sum
1031+
* cannot overflow. If the inputs are of the same sign, their sum had
1032+
* better be that sign too.
1033+
*/
1034+
if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
1035+
ereport(ERROR,
1036+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1037+
errmsg("bigint out of range")));
1038+
PG_RETURN_INT64(result);
1039+
}
1040+
1041+
Datum
1042+
int28mi(PG_FUNCTION_ARGS)
1043+
{
1044+
int16 arg1 = PG_GETARG_INT16(0);
1045+
int64 arg2 = PG_GETARG_INT64(1);
1046+
int64 result;
1047+
1048+
result = arg1 - arg2;
1049+
1050+
/*
1051+
* Overflow check. If the inputs are of the same sign then their
1052+
* difference cannot overflow. If they are of different signs then the
1053+
* result should be of the same sign as the first input.
1054+
*/
1055+
if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
1056+
ereport(ERROR,
1057+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1058+
errmsg("bigint out of range")));
1059+
PG_RETURN_INT64(result);
1060+
}
1061+
1062+
Datum
1063+
int28mul(PG_FUNCTION_ARGS)
1064+
{
1065+
int16 arg1 = PG_GETARG_INT16(0);
1066+
int64 arg2 = PG_GETARG_INT64(1);
1067+
int64 result;
1068+
1069+
result = arg1 * arg2;
1070+
1071+
/*
1072+
* Overflow check. We basically check to see if result / arg2 gives arg1
1073+
* again. There is one case where this fails: arg2 = 0 (which cannot
1074+
* overflow).
1075+
*
1076+
* Since the division is likely much more expensive than the actual
1077+
* multiplication, we'd like to skip it where possible. The best bang for
1078+
* the buck seems to be to check whether both inputs are in the int32
1079+
* range; if so, no overflow is possible.
1080+
*/
1081+
if (arg2 != (int64) ((int32) arg2) &&
1082+
result / arg2 != arg1)
1083+
ereport(ERROR,
1084+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1085+
errmsg("bigint out of range")));
1086+
PG_RETURN_INT64(result);
1087+
}
1088+
1089+
Datum
1090+
int28div(PG_FUNCTION_ARGS)
1091+
{
1092+
int16 arg1 = PG_GETARG_INT16(0);
1093+
int64 arg2 = PG_GETARG_INT64(1);
1094+
1095+
if (arg2 == 0)
1096+
ereport(ERROR,
1097+
(errcode(ERRCODE_DIVISION_BY_ZERO),
1098+
errmsg("division by zero")));
1099+
/* No overflow is possible */
1100+
PG_RETURN_INT64((int64) arg1 / arg2);
1101+
}
1102+
9251103
/* Binary arithmetics
9261104
*
9271105
* int8and - returns arg1 & arg2

src/include/catalog/catversion.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.462 2008/05/27 00:13:09 tgl Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.463 2008/06/17 19:10:56 tgl Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 200805261
56+
#define CATALOG_VERSION_NO 200806171
5757

5858
#endif

src/include/catalog/pg_operator.h

+11-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
11-
* $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.159 2008/05/27 00:13:09 tgl Exp $
11+
* $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.160 2008/06/17 19:10:56 tgl Exp $
1212
*
1313
* NOTES
1414
* the genbki.sh script reads this file and generates .bki
@@ -204,8 +204,6 @@ DATA(insert OID = 544 ( "*" PGNSP PGUID b f f 21 23 23 545 0 int24mul - - )
204204
DATA(insert OID = 545 ( "*" PGNSP PGUID b f f 23 21 23 544 0 int42mul - - ));
205205
DATA(insert OID = 546 ( "/" PGNSP PGUID b f f 21 23 23 0 0 int24div - - ));
206206
DATA(insert OID = 547 ( "/" PGNSP PGUID b f f 23 21 23 0 0 int42div - - ));
207-
DATA(insert OID = 548 ( "%" PGNSP PGUID b f f 21 23 23 0 0 int24mod - - ));
208-
DATA(insert OID = 549 ( "%" PGNSP PGUID b f f 23 21 23 0 0 int42mod - - ));
209207
DATA(insert OID = 550 ( "+" PGNSP PGUID b f f 21 21 21 550 0 int2pl - - ));
210208
DATA(insert OID = 551 ( "+" PGNSP PGUID b f f 23 23 23 551 0 int4pl - - ));
211209
DATA(insert OID = 552 ( "+" PGNSP PGUID b f f 21 23 23 553 0 int24pl - - ));
@@ -321,6 +319,7 @@ DATA(insert OID = 684 ( "+" PGNSP PGUID b f f 20 20 20 684 0 int8pl - - ));
321319
DATA(insert OID = 685 ( "-" PGNSP PGUID b f f 20 20 20 0 0 int8mi - - ));
322320
DATA(insert OID = 686 ( "*" PGNSP PGUID b f f 20 20 20 686 0 int8mul - - ));
323321
DATA(insert OID = 687 ( "/" PGNSP PGUID b f f 20 20 20 0 0 int8div - - ));
322+
324323
DATA(insert OID = 688 ( "+" PGNSP PGUID b f f 20 23 20 692 0 int84pl - - ));
325324
DATA(insert OID = 689 ( "-" PGNSP PGUID b f f 20 23 20 0 0 int84mi - - ));
326325
DATA(insert OID = 690 ( "*" PGNSP PGUID b f f 20 23 20 694 0 int84mul - - ));
@@ -330,6 +329,15 @@ DATA(insert OID = 693 ( "-" PGNSP PGUID b f f 23 20 20 0 0 int48mi - - ));
330329
DATA(insert OID = 694 ( "*" PGNSP PGUID b f f 23 20 20 690 0 int48mul - - ));
331330
DATA(insert OID = 695 ( "/" PGNSP PGUID b f f 23 20 20 0 0 int48div - - ));
332331

332+
DATA(insert OID = 818 ( "+" PGNSP PGUID b f f 20 21 20 822 0 int82pl - - ));
333+
DATA(insert OID = 819 ( "-" PGNSP PGUID b f f 20 21 20 0 0 int82mi - - ));
334+
DATA(insert OID = 820 ( "*" PGNSP PGUID b f f 20 21 20 824 0 int82mul - - ));
335+
DATA(insert OID = 821 ( "/" PGNSP PGUID b f f 20 21 20 0 0 int82div - - ));
336+
DATA(insert OID = 822 ( "+" PGNSP PGUID b f f 21 20 20 818 0 int28pl - - ));
337+
DATA(insert OID = 823 ( "-" PGNSP PGUID b f f 21 20 20 0 0 int28mi - - ));
338+
DATA(insert OID = 824 ( "*" PGNSP PGUID b f f 21 20 20 820 0 int28mul - - ));
339+
DATA(insert OID = 825 ( "/" PGNSP PGUID b f f 21 20 20 0 0 int28div - - ));
340+
333341
DATA(insert OID = 706 ( "<->" PGNSP PGUID b f f 603 603 701 706 0 box_distance - - ));
334342
DATA(insert OID = 707 ( "<->" PGNSP PGUID b f f 602 602 701 707 0 path_distance - - ));
335343
DATA(insert OID = 708 ( "<->" PGNSP PGUID b f f 628 628 701 708 0 line_distance - - ));

src/include/catalog/pg_proc.h

+18-9
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.502 2008/05/29 22:48:07 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.503 2008/06/17 19:10:56 tgl Exp $
1111
*
1212
* NOTES
1313
* The script catalog/genbki.sh reads this file and generates .bki
@@ -351,10 +351,6 @@ DATA(insert OID = 172 ( int24div PGNSP PGUID 12 1 0 f f t f i 2 23 "21 23"
351351
DESCR("divide");
352352
DATA(insert OID = 173 ( int42div PGNSP PGUID 12 1 0 f f t f i 2 23 "23 21" _null_ _null_ _null_ int42div - _null_ _null_ ));
353353
DESCR("divide");
354-
DATA(insert OID = 174 ( int24mod PGNSP PGUID 12 1 0 f f t f i 2 23 "21 23" _null_ _null_ _null_ int24mod - _null_ _null_ ));
355-
DESCR("modulus");
356-
DATA(insert OID = 175 ( int42mod PGNSP PGUID 12 1 0 f f t f i 2 23 "23 21" _null_ _null_ _null_ int42mod - _null_ _null_ ));
357-
DESCR("modulus");
358354
DATA(insert OID = 176 ( int2pl PGNSP PGUID 12 1 0 f f t f i 2 21 "21 21" _null_ _null_ _null_ int2pl - _null_ _null_ ));
359355
DESCR("add");
360356
DATA(insert OID = 177 ( int4pl PGNSP PGUID 12 1 0 f f t f i 2 23 "23 23" _null_ _null_ _null_ int4pl - _null_ _null_ ));
@@ -1177,10 +1173,6 @@ DATA(insert OID = 940 ( mod PGNSP PGUID 12 1 0 f f t f i 2 21 "21 21" _nul
11771173
DESCR("modulus");
11781174
DATA(insert OID = 941 ( mod PGNSP PGUID 12 1 0 f f t f i 2 23 "23 23" _null_ _null_ _null_ int4mod - _null_ _null_ ));
11791175
DESCR("modulus");
1180-
DATA(insert OID = 942 ( mod PGNSP PGUID 12 1 0 f f t f i 2 23 "21 23" _null_ _null_ _null_ int24mod - _null_ _null_ ));
1181-
DESCR("modulus");
1182-
DATA(insert OID = 943 ( mod PGNSP PGUID 12 1 0 f f t f i 2 23 "23 21" _null_ _null_ _null_ int42mod - _null_ _null_ ));
1183-
DESCR("modulus");
11841176

11851177
DATA(insert OID = 945 ( int8mod PGNSP PGUID 12 1 0 f f t f i 2 20 "20 20" _null_ _null_ _null_ int8mod - _null_ _null_ ));
11861178
DESCR("modulus");
@@ -1570,6 +1562,23 @@ DESCR("multiply");
15701562
DATA(insert OID = 1281 ( int48div PGNSP PGUID 12 1 0 f f t f i 2 20 "23 20" _null_ _null_ _null_ int48div - _null_ _null_ ));
15711563
DESCR("divide");
15721564

1565+
DATA(insert OID = 837 ( int82pl PGNSP PGUID 12 1 0 f f t f i 2 20 "20 21" _null_ _null_ _null_ int82pl - _null_ _null_ ));
1566+
DESCR("add");
1567+
DATA(insert OID = 838 ( int82mi PGNSP PGUID 12 1 0 f f t f i 2 20 "20 21" _null_ _null_ _null_ int82mi - _null_ _null_ ));
1568+
DESCR("subtract");
1569+
DATA(insert OID = 839 ( int82mul PGNSP PGUID 12 1 0 f f t f i 2 20 "20 21" _null_ _null_ _null_ int82mul - _null_ _null_ ));
1570+
DESCR("multiply");
1571+
DATA(insert OID = 840 ( int82div PGNSP PGUID 12 1 0 f f t f i 2 20 "20 21" _null_ _null_ _null_ int82div - _null_ _null_ ));
1572+
DESCR("divide");
1573+
DATA(insert OID = 841 ( int28pl PGNSP PGUID 12 1 0 f f t f i 2 20 "21 20" _null_ _null_ _null_ int28pl - _null_ _null_ ));
1574+
DESCR("add");
1575+
DATA(insert OID = 942 ( int28mi PGNSP PGUID 12 1 0 f f t f i 2 20 "21 20" _null_ _null_ _null_ int28mi - _null_ _null_ ));
1576+
DESCR("subtract");
1577+
DATA(insert OID = 943 ( int28mul PGNSP PGUID 12 1 0 f f t f i 2 20 "21 20" _null_ _null_ _null_ int28mul - _null_ _null_ ));
1578+
DESCR("multiply");
1579+
DATA(insert OID = 948 ( int28div PGNSP PGUID 12 1 0 f f t f i 2 20 "21 20" _null_ _null_ _null_ int28div - _null_ _null_ ));
1580+
DESCR("divide");
1581+
15731582
DATA(insert OID = 1287 ( oid PGNSP PGUID 12 1 0 f f t f i 1 26 "20" _null_ _null_ _null_ i8tooid - _null_ _null_ ));
15741583
DESCR("convert int8 to oid");
15751584
DATA(insert OID = 1288 ( int8 PGNSP PGUID 12 1 0 f f t f i 1 20 "26" _null_ _null_ _null_ oidtoi8 - _null_ _null_ ));

src/include/utils/builtins.h

+1-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.316 2008/05/27 00:13:09 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.317 2008/06/17 19:10:56 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -190,8 +190,6 @@ extern Datum int42mul(PG_FUNCTION_ARGS);
190190
extern Datum int42div(PG_FUNCTION_ARGS);
191191
extern Datum int4mod(PG_FUNCTION_ARGS);
192192
extern Datum int2mod(PG_FUNCTION_ARGS);
193-
extern Datum int24mod(PG_FUNCTION_ARGS);
194-
extern Datum int42mod(PG_FUNCTION_ARGS);
195193
extern Datum int2larger(PG_FUNCTION_ARGS);
196194
extern Datum int2smaller(PG_FUNCTION_ARGS);
197195
extern Datum int4larger(PG_FUNCTION_ARGS);

src/include/utils/int8.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/utils/int8.h,v 1.48 2008/01/01 19:45:59 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/utils/int8.h,v 1.49 2008/06/17 19:10:56 tgl Exp $
1111
*
1212
* NOTES
1313
* These data types are supported on all 64-bit architectures, and may
@@ -96,6 +96,16 @@ extern Datum int48mi(PG_FUNCTION_ARGS);
9696
extern Datum int48mul(PG_FUNCTION_ARGS);
9797
extern Datum int48div(PG_FUNCTION_ARGS);
9898

99+
extern Datum int82pl(PG_FUNCTION_ARGS);
100+
extern Datum int82mi(PG_FUNCTION_ARGS);
101+
extern Datum int82mul(PG_FUNCTION_ARGS);
102+
extern Datum int82div(PG_FUNCTION_ARGS);
103+
104+
extern Datum int28pl(PG_FUNCTION_ARGS);
105+
extern Datum int28mi(PG_FUNCTION_ARGS);
106+
extern Datum int28mul(PG_FUNCTION_ARGS);
107+
extern Datum int28div(PG_FUNCTION_ARGS);
108+
99109
extern Datum int48(PG_FUNCTION_ARGS);
100110
extern Datum int84(PG_FUNCTION_ARGS);
101111

0 commit comments

Comments
 (0)