1 /* Copyright (C) 2017 MariaDB Corporation
2
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License
5 as published by the Free Software Foundation; version 2 of
6 the License.
7
8 This program 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
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 MA 02110-1301, USA. */
17
18 #include <sstream>
19 #include <cstring>
20 #include <typeinfo>
21 #include "regr_avgx.h"
22 #include "bytestream.h"
23 #include "objectreader.h"
24
25 using namespace mcsv1sdk;
26
27 class Add_regr_avgx_ToUDAFMap
28 {
29 public:
Add_regr_avgx_ToUDAFMap()30 Add_regr_avgx_ToUDAFMap()
31 {
32 UDAFMap::getMap()["regr_avgx"] = new regr_avgx();
33 }
34 };
35
36 static Add_regr_avgx_ToUDAFMap addToMap;
37
38 #define DATATYPE double
39
40 // Use the simple data model
41 struct regr_avgx_data
42 {
43 long double sum;
44 uint64_t cnt;
45 };
46
47
init(mcsv1Context * context,ColumnDatum * colTypes)48 mcsv1_UDAF::ReturnCode regr_avgx::init(mcsv1Context* context,
49 ColumnDatum* colTypes)
50 {
51 if (context->getParameterCount() != 2)
52 {
53 // The error message will be prepended with
54 // "The storage engine for the table doesn't support "
55 context->setErrorMessage("regr_avgx() with other than 2 arguments");
56 return mcsv1_UDAF::ERROR;
57 }
58
59 if (!(isNumeric(colTypes[1].dataType)))
60 {
61 // The error message will be prepended with
62 // "The storage engine for the table doesn't support "
63 context->setErrorMessage("regr_avgx() with a non-numeric x argument");
64 return mcsv1_UDAF::ERROR;
65 }
66
67 context->setUserDataSize(sizeof(regr_avgx_data));
68 context->setResultType(execplan::CalpontSystemCatalog::DOUBLE);
69 context->setColWidth(8);
70 context->setScale(colTypes[1].scale + 4);
71 context->setPrecision(19);
72 context->setRunFlag(mcsv1sdk::UDAF_IGNORE_NULLS);
73 return mcsv1_UDAF::SUCCESS;
74
75 }
76
reset(mcsv1Context * context)77 mcsv1_UDAF::ReturnCode regr_avgx::reset(mcsv1Context* context)
78 {
79 struct regr_avgx_data* data = (struct regr_avgx_data*)context->getUserData()->data;
80 data->sum = 0;
81 data->cnt = 0;
82 return mcsv1_UDAF::SUCCESS;
83 }
84
nextValue(mcsv1Context * context,ColumnDatum * valsIn)85 mcsv1_UDAF::ReturnCode regr_avgx::nextValue(mcsv1Context* context, ColumnDatum* valsIn)
86 {
87 static_any::any& valIn_x = valsIn[1].columnData;
88 struct regr_avgx_data* data = (struct regr_avgx_data*)context->getUserData()->data;
89 DATATYPE val = convertAnyTo<double>(valIn_x);
90
91 // For decimal types, we need to move the decimal point.
92 uint32_t scale = valsIn[1].scale;
93 if (val != 0 && scale > 0)
94 {
95 val /= pow(10.0, (double)scale);
96 }
97
98 data->sum += val;
99 ++data->cnt;
100
101 return mcsv1_UDAF::SUCCESS;
102 }
103
subEvaluate(mcsv1Context * context,const UserData * userDataIn)104 mcsv1_UDAF::ReturnCode regr_avgx::subEvaluate(mcsv1Context* context, const UserData* userDataIn)
105 {
106 if (!userDataIn)
107 {
108 return mcsv1_UDAF::SUCCESS;
109 }
110
111 struct regr_avgx_data* outData = (struct regr_avgx_data*)context->getUserData()->data;
112
113 struct regr_avgx_data* inData = (struct regr_avgx_data*)userDataIn->data;
114
115 outData->sum += inData->sum;
116
117 outData->cnt += inData->cnt;
118
119 return mcsv1_UDAF::SUCCESS;
120 }
121
evaluate(mcsv1Context * context,static_any::any & valOut)122 mcsv1_UDAF::ReturnCode regr_avgx::evaluate(mcsv1Context* context, static_any::any& valOut)
123 {
124 struct regr_avgx_data* data = (struct regr_avgx_data*)context->getUserData()->data;
125
126 if (data->cnt > 0)
127 {
128 valOut = static_cast<double>(data->sum / (long double)data->cnt);
129 }
130
131 return mcsv1_UDAF::SUCCESS;
132 }
133
dropValue(mcsv1Context * context,ColumnDatum * valsDropped)134 mcsv1_UDAF::ReturnCode regr_avgx::dropValue(mcsv1Context* context, ColumnDatum* valsDropped)
135 {
136 static_any::any& valIn_x = valsDropped[1].columnData;
137 struct regr_avgx_data* data = (struct regr_avgx_data*)context->getUserData()->data;
138 double val = convertAnyTo<double>(valIn_x);
139
140 // For decimal types, we need to move the decimal point.
141 uint32_t scale = valsDropped[1].scale;
142 if (val != 0 && scale > 0)
143 {
144 val /= pow(10.0, (double)scale);
145 }
146
147 data->sum -= val;
148 --data->cnt;
149
150 return mcsv1_UDAF::SUCCESS;
151 }
152
153