14
14
* Copyright (c) 1998-2007, PostgreSQL Global Development Group
15
15
*
16
16
* IDENTIFICATION
17
- * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.99 2007/01/16 21:41:13 neilc Exp $
17
+ * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.100 2007/02/17 00:55:57 momjian Exp $
18
18
*
19
19
*-------------------------------------------------------------------------
20
20
*/
@@ -2165,6 +2165,40 @@ do_numeric_accum(ArrayType *transarray, Numeric newval)
2165
2165
return result ;
2166
2166
}
2167
2167
2168
+ /*
2169
+ * Improve avg performance by not caclulating sum(X*X).
2170
+ */
2171
+ static ArrayType *
2172
+ do_numeric_avg_accum (ArrayType * transarray , Numeric newval )
2173
+ {
2174
+ Datum * transdatums ;
2175
+ int ndatums ;
2176
+ Datum N ,
2177
+ sumX ;
2178
+ ArrayType * result ;
2179
+
2180
+ /* We assume the input is array of numeric */
2181
+ deconstruct_array (transarray ,
2182
+ NUMERICOID , -1 , false, 'i' ,
2183
+ & transdatums , NULL , & ndatums );
2184
+ if (ndatums != 2 )
2185
+ elog (ERROR , "expected 2-element numeric array" );
2186
+ N = transdatums [0 ];
2187
+ sumX = transdatums [1 ];
2188
+
2189
+ N = DirectFunctionCall1 (numeric_inc , N );
2190
+ sumX = DirectFunctionCall2 (numeric_add , sumX ,
2191
+ NumericGetDatum (newval ));
2192
+
2193
+ transdatums [0 ] = N ;
2194
+ transdatums [1 ] = sumX ;
2195
+
2196
+ result = construct_array (transdatums , 2 ,
2197
+ NUMERICOID , -1 , false, 'i' );
2198
+
2199
+ return result ;
2200
+ }
2201
+
2168
2202
Datum
2169
2203
numeric_accum (PG_FUNCTION_ARGS )
2170
2204
{
@@ -2174,6 +2208,18 @@ numeric_accum(PG_FUNCTION_ARGS)
2174
2208
PG_RETURN_ARRAYTYPE_P (do_numeric_accum (transarray , newval ));
2175
2209
}
2176
2210
2211
+ /*
2212
+ * Optimized case for average of numeric.
2213
+ */
2214
+ Datum
2215
+ numeric_avg_accum (PG_FUNCTION_ARGS )
2216
+ {
2217
+ ArrayType * transarray = PG_GETARG_ARRAYTYPE_P (0 );
2218
+ Numeric newval = PG_GETARG_NUMERIC (1 );
2219
+
2220
+ PG_RETURN_ARRAYTYPE_P (do_numeric_avg_accum (transarray , newval ));
2221
+ }
2222
+
2177
2223
/*
2178
2224
* Integer data types all use Numeric accumulators to share code and
2179
2225
* avoid risk of overflow. For int2 and int4 inputs, Numeric accumulation
@@ -2219,6 +2265,22 @@ int8_accum(PG_FUNCTION_ARGS)
2219
2265
PG_RETURN_ARRAYTYPE_P (do_numeric_accum (transarray , newval ));
2220
2266
}
2221
2267
2268
+ /*
2269
+ * Optimized case for average of int8.
2270
+ */
2271
+ Datum
2272
+ int8_avg_accum (PG_FUNCTION_ARGS )
2273
+ {
2274
+ ArrayType * transarray = PG_GETARG_ARRAYTYPE_P (0 );
2275
+ Datum newval8 = PG_GETARG_DATUM (1 );
2276
+ Numeric newval ;
2277
+
2278
+ newval = DatumGetNumeric (DirectFunctionCall1 (int8_numeric , newval8 ));
2279
+
2280
+ PG_RETURN_ARRAYTYPE_P (do_numeric_avg_accum (transarray , newval ));
2281
+ }
2282
+
2283
+
2222
2284
Datum
2223
2285
numeric_avg (PG_FUNCTION_ARGS )
2224
2286
{
@@ -2232,11 +2294,10 @@ numeric_avg(PG_FUNCTION_ARGS)
2232
2294
deconstruct_array (transarray ,
2233
2295
NUMERICOID , -1 , false, 'i' ,
2234
2296
& transdatums , NULL , & ndatums );
2235
- if (ndatums != 3 )
2236
- elog (ERROR , "expected 3 -element numeric array" );
2297
+ if (ndatums != 2 )
2298
+ elog (ERROR , "expected 2 -element numeric array" );
2237
2299
N = DatumGetNumeric (transdatums [0 ]);
2238
2300
sumX = DatumGetNumeric (transdatums [1 ]);
2239
- /* ignore sumX2 */
2240
2301
2241
2302
/* SQL92 defines AVG of no values to be NULL */
2242
2303
/* N is zero iff no digits (cf. numeric_uminus) */
0 commit comments