1 /* -*- c-basic-offset: 2 -*- */
2 /* Copyright(C) 2009-2015 Brazil
3 
4   This library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Lesser General Public
6   License version 2.1 as published by the Free Software Foundation.
7 
8   This library is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   Lesser General Public License for more details.
12 
13   You should have received a copy of the GNU Lesser General Public
14   License along with this library; if not, write to the Free Software
15   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1335  USA
16 */
17 #include "grn_db.h"
18 
19 uint32_t
grn_rset_recinfo_calc_values_size(grn_ctx * ctx,grn_table_group_flags flags)20 grn_rset_recinfo_calc_values_size(grn_ctx *ctx, grn_table_group_flags flags)
21 {
22   uint32_t size = 0;
23 
24   if (flags & GRN_TABLE_GROUP_CALC_MAX) {
25     size += GRN_RSET_MAX_SIZE;
26   }
27   if (flags & GRN_TABLE_GROUP_CALC_MIN) {
28     size += GRN_RSET_MIN_SIZE;
29   }
30   if (flags & GRN_TABLE_GROUP_CALC_SUM) {
31     size += GRN_RSET_SUM_SIZE;
32   }
33   if (flags & GRN_TABLE_GROUP_CALC_AVG) {
34     size += GRN_RSET_AVG_SIZE;
35   }
36 
37   return size;
38 }
39 
40 void
grn_rset_recinfo_update_calc_values(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table,grn_obj * value)41 grn_rset_recinfo_update_calc_values(grn_ctx *ctx,
42                                     grn_rset_recinfo *ri,
43                                     grn_obj *table,
44                                     grn_obj *value)
45 {
46   grn_table_group_flags flags;
47   byte *values;
48   grn_obj value_int64;
49   grn_obj value_float;
50 
51   flags = DB_OBJ(table)->flags.group;
52 
53   values = (((byte *)ri->subrecs) +
54             GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size,
55                                   DB_OBJ(table)->max_n_subrecs));
56 
57   GRN_INT64_INIT(&value_int64, 0);
58   GRN_FLOAT_INIT(&value_float, 0);
59 
60   if (flags & (GRN_TABLE_GROUP_CALC_MAX |
61                GRN_TABLE_GROUP_CALC_MIN |
62                GRN_TABLE_GROUP_CALC_SUM)) {
63     grn_obj_cast(ctx, value, &value_int64, GRN_FALSE);
64   }
65   if (flags & GRN_TABLE_GROUP_CALC_AVG) {
66     grn_obj_cast(ctx, value, &value_float, GRN_FALSE);
67   }
68 
69   if (flags & GRN_TABLE_GROUP_CALC_MAX) {
70     int64_t current_max = *((int64_t *)values);
71     int64_t value_raw = GRN_INT64_VALUE(&value_int64);
72     if (ri->n_subrecs == 1 || value_raw > current_max) {
73       *((int64_t *)values) = value_raw;
74     }
75     values += GRN_RSET_MAX_SIZE;
76   }
77   if (flags & GRN_TABLE_GROUP_CALC_MIN) {
78     int64_t current_min = *((int64_t *)values);
79     int64_t value_raw = GRN_INT64_VALUE(&value_int64);
80     if (ri->n_subrecs == 1 || value_raw < current_min) {
81       *((int64_t *)values) = value_raw;
82     }
83     values += GRN_RSET_MIN_SIZE;
84   }
85   if (flags & GRN_TABLE_GROUP_CALC_SUM) {
86     int64_t value_raw = GRN_INT64_VALUE(&value_int64);
87     *((int64_t *)values) += value_raw;
88     values += GRN_RSET_SUM_SIZE;
89   }
90   if (flags & GRN_TABLE_GROUP_CALC_AVG) {
91     double current_average = *((double *)values);
92     double value_raw = GRN_FLOAT_VALUE(&value_float);
93     *((double *)values) += (value_raw - current_average) / ri->n_subrecs;
94     values += GRN_RSET_AVG_SIZE;
95   }
96 
97   GRN_OBJ_FIN(ctx, &value_float);
98   GRN_OBJ_FIN(ctx, &value_int64);
99 }
100 
101 int64_t *
grn_rset_recinfo_get_max_(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table)102 grn_rset_recinfo_get_max_(grn_ctx *ctx,
103                           grn_rset_recinfo *ri,
104                           grn_obj *table)
105 {
106   grn_table_group_flags flags;
107   byte *values;
108 
109   flags = DB_OBJ(table)->flags.group;
110   if (!(flags & GRN_TABLE_GROUP_CALC_MAX)) {
111     return NULL;
112   }
113 
114   values = (((byte *)ri->subrecs) +
115             GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size,
116                                   DB_OBJ(table)->max_n_subrecs));
117 
118   return (int64_t *)values;
119 }
120 
121 int64_t
grn_rset_recinfo_get_max(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table)122 grn_rset_recinfo_get_max(grn_ctx *ctx,
123                          grn_rset_recinfo *ri,
124                          grn_obj *table)
125 {
126   int64_t *max_address;
127 
128   max_address = grn_rset_recinfo_get_max_(ctx, ri, table);
129   if (max_address) {
130     return *max_address;
131   } else {
132     return 0;
133   }
134 }
135 
136 void
grn_rset_recinfo_set_max(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table,int64_t max)137 grn_rset_recinfo_set_max(grn_ctx *ctx,
138                          grn_rset_recinfo *ri,
139                          grn_obj *table,
140                          int64_t max)
141 {
142   int64_t *max_address;
143 
144   max_address = grn_rset_recinfo_get_max_(ctx, ri, table);
145   if (!max_address) {
146     return;
147   }
148 
149   *max_address = max;
150 }
151 
152 int64_t *
grn_rset_recinfo_get_min_(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table)153 grn_rset_recinfo_get_min_(grn_ctx *ctx,
154                           grn_rset_recinfo *ri,
155                           grn_obj *table)
156 {
157   grn_table_group_flags flags;
158   byte *values;
159 
160   flags = DB_OBJ(table)->flags.group;
161   if (!(flags & GRN_TABLE_GROUP_CALC_MIN)) {
162     return NULL;
163   }
164 
165   values = (((byte *)ri->subrecs) +
166             GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size,
167                                   DB_OBJ(table)->max_n_subrecs));
168 
169   if (flags & GRN_TABLE_GROUP_CALC_MAX) {
170     values += GRN_RSET_MAX_SIZE;
171   }
172 
173   return (int64_t *)values;
174 }
175 
176 int64_t
grn_rset_recinfo_get_min(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table)177 grn_rset_recinfo_get_min(grn_ctx *ctx,
178                          grn_rset_recinfo *ri,
179                          grn_obj *table)
180 {
181   int64_t *min_address;
182 
183   min_address = grn_rset_recinfo_get_min_(ctx, ri, table);
184   if (min_address) {
185     return *min_address;
186   } else {
187     return 0;
188   }
189 }
190 
191 void
grn_rset_recinfo_set_min(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table,int64_t min)192 grn_rset_recinfo_set_min(grn_ctx *ctx,
193                          grn_rset_recinfo *ri,
194                          grn_obj *table,
195                          int64_t min)
196 {
197   int64_t *min_address;
198 
199   min_address = grn_rset_recinfo_get_min_(ctx, ri, table);
200   if (!min_address) {
201     return;
202   }
203 
204   *min_address = min;
205 }
206 
207 int64_t *
grn_rset_recinfo_get_sum_(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table)208 grn_rset_recinfo_get_sum_(grn_ctx *ctx,
209                           grn_rset_recinfo *ri,
210                           grn_obj *table)
211 {
212   grn_table_group_flags flags;
213   byte *values;
214 
215   flags = DB_OBJ(table)->flags.group;
216   if (!(flags & GRN_TABLE_GROUP_CALC_SUM)) {
217     return NULL;
218   }
219 
220   values = (((byte *)ri->subrecs) +
221             GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size,
222                                   DB_OBJ(table)->max_n_subrecs));
223 
224   if (flags & GRN_TABLE_GROUP_CALC_MAX) {
225     values += GRN_RSET_MAX_SIZE;
226   }
227   if (flags & GRN_TABLE_GROUP_CALC_MIN) {
228     values += GRN_RSET_MIN_SIZE;
229   }
230 
231   return (int64_t *)values;
232 }
233 
234 int64_t
grn_rset_recinfo_get_sum(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table)235 grn_rset_recinfo_get_sum(grn_ctx *ctx,
236                          grn_rset_recinfo *ri,
237                          grn_obj *table)
238 {
239   int64_t *sum_address;
240 
241   sum_address = grn_rset_recinfo_get_sum_(ctx, ri, table);
242   if (sum_address) {
243     return *sum_address;
244   } else {
245     return 0;
246   }
247 }
248 
249 void
grn_rset_recinfo_set_sum(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table,int64_t sum)250 grn_rset_recinfo_set_sum(grn_ctx *ctx,
251                          grn_rset_recinfo *ri,
252                          grn_obj *table,
253                          int64_t sum)
254 {
255   int64_t *sum_address;
256 
257   sum_address = grn_rset_recinfo_get_sum_(ctx, ri, table);
258   if (!sum_address) {
259     return;
260   }
261 
262   *sum_address = sum;
263 }
264 
265 double *
grn_rset_recinfo_get_avg_(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table)266 grn_rset_recinfo_get_avg_(grn_ctx *ctx,
267                           grn_rset_recinfo *ri,
268                           grn_obj *table)
269 {
270   grn_table_group_flags flags;
271   byte *values;
272 
273   flags = DB_OBJ(table)->flags.group;
274   if (!(flags & GRN_TABLE_GROUP_CALC_AVG)) {
275     return NULL;
276   }
277 
278   values = (((byte *)ri->subrecs) +
279             GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size,
280                                   DB_OBJ(table)->max_n_subrecs));
281 
282   if (flags & GRN_TABLE_GROUP_CALC_MAX) {
283     values += GRN_RSET_MAX_SIZE;
284   }
285   if (flags & GRN_TABLE_GROUP_CALC_MIN) {
286     values += GRN_RSET_MIN_SIZE;
287   }
288   if (flags & GRN_TABLE_GROUP_CALC_SUM) {
289     values += GRN_RSET_SUM_SIZE;
290   }
291 
292   return (double *)values;
293 }
294 
295 double
grn_rset_recinfo_get_avg(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table)296 grn_rset_recinfo_get_avg(grn_ctx *ctx,
297                          grn_rset_recinfo *ri,
298                          grn_obj *table)
299 {
300   double *avg_address;
301 
302   avg_address = grn_rset_recinfo_get_avg_(ctx, ri, table);
303   if (avg_address) {
304     return *avg_address;
305   } else {
306     return 0;
307   }
308 }
309 
310 void
grn_rset_recinfo_set_avg(grn_ctx * ctx,grn_rset_recinfo * ri,grn_obj * table,double avg)311 grn_rset_recinfo_set_avg(grn_ctx *ctx,
312                          grn_rset_recinfo *ri,
313                          grn_obj *table,
314                          double avg)
315 {
316   double *avg_address;
317 
318   avg_address = grn_rset_recinfo_get_avg_(ctx, ri, table);
319   if (!avg_address) {
320     return;
321   }
322 
323   *avg_address = avg;
324 }
325