diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index dba39fe86..c4486ddd5 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -25,3 +25,5 @@ add_subdirectory(thrift)
add_subdirectory(querytele)
add_subdirectory(clusterTester)
add_subdirectory(libmysql_client)
+add_subdirectory(regr)
+
diff --git a/utils/regr/regr.vpj b/utils/regr/regr.vpj
new file mode 100644
index 000000000..d99a1d436
--- /dev/null
+++ b/utils/regr/regr.vpj
@@ -0,0 +1,220 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/utils/udfsdk/regr_avgx.cpp b/utils/regr/regr_avgx.cpp
similarity index 95%
rename from utils/udfsdk/regr_avgx.cpp
rename to utils/regr/regr_avgx.cpp
index e99871f97..1230df84c 100644
--- a/utils/udfsdk/regr_avgx.cpp
+++ b/utils/regr/regr_avgx.cpp
@@ -24,6 +24,17 @@
using namespace mcsv1sdk;
+class Add_regr_avgx_ToUDAFMap
+{
+public:
+ Add_regr_avgx_ToUDAFMap()
+ {
+ UDAFMap::getMap()["regr_avgx"] = new regr_avgx();
+ }
+};
+
+static Add_regr_avgx_ToUDAFMap addToMap;
+
#define DATATYPE double
// Use the simple data model
@@ -196,6 +207,10 @@ mcsv1_UDAF::ReturnCode regr_avgx::dropValue(mcsv1Context* context, ColumnDatum*
struct regr_avgx_data* data = (struct regr_avgx_data*)context->getUserData()->data;
DATATYPE val = 0.0;
+ if (context->isParamNull(0) || context->isParamNull(1))
+ {
+ return mcsv1_UDAF::SUCCESS; // Ought not happen when UDAF_IGNORE_NULLS is on.
+ }
if (valIn_x.empty() || valIn_y.empty())
{
return mcsv1_UDAF::SUCCESS; // Ought not happen when UDAF_IGNORE_NULLS is on.
diff --git a/utils/udfsdk/regr_avgx.h b/utils/regr/regr_avgx.h
similarity index 99%
rename from utils/udfsdk/regr_avgx.h
rename to utils/regr/regr_avgx.h
index 27b8708f7..75791f769 100644
--- a/utils/udfsdk/regr_avgx.h
+++ b/utils/regr/regr_avgx.h
@@ -26,7 +26,7 @@
*
*
* CREATE AGGREGATE FUNCTION regr_avgx returns REAL soname
- * 'libudf_mysql.so';
+ * 'libregr_mysql.so';
*
*/
#ifndef HEADER_regr_avgx
diff --git a/utils/regr/regr_avgy.cpp b/utils/regr/regr_avgy.cpp
new file mode 100644
index 000000000..667019a33
--- /dev/null
+++ b/utils/regr/regr_avgy.cpp
@@ -0,0 +1,281 @@
+/* Copyright (C) 2017 MariaDB Corporaton
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; version 2 of
+ the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include
+#include
+#include
+#include "regr_avgy.h"
+#include "bytestream.h"
+#include "objectreader.h"
+
+using namespace mcsv1sdk;
+
+class Add_regr_avgy_ToUDAFMap
+{
+public:
+ Add_regr_avgy_ToUDAFMap()
+ {
+ UDAFMap::getMap()["regr_avgy"] = new regr_avgy();
+ }
+};
+
+static Add_regr_avgy_ToUDAFMap addToMap;
+
+#define DATATYPE double
+
+// Use the simple data model
+struct regr_avgy_data
+{
+ double sum;
+ uint64_t cnt;
+};
+
+
+mcsv1_UDAF::ReturnCode regr_avgy::init(mcsv1Context* context,
+ ColumnDatum* colTypes)
+{
+ if (context->getParameterCount() != 2)
+ {
+ // The error message will be prepended with
+ // "The storage engine for the table doesn't support "
+ context->setErrorMessage("regr_avgy() with other than 2 arguments");
+ return mcsv1_UDAF::ERROR;
+ }
+
+ if (!(isNumeric(colTypes[0].dataType)))
+ {
+ // The error message will be prepended with
+ // "The storage engine for the table doesn't support "
+ context->setErrorMessage("regr_avgy() with a non-numeric x argument");
+ return mcsv1_UDAF::ERROR;
+ }
+
+ context->setUserDataSize(sizeof(regr_avgy_data));
+ context->setResultType(CalpontSystemCatalog::DOUBLE);
+ context->setColWidth(8);
+ context->setScale(colTypes[0].scale + 4);
+ context->setPrecision(19);
+ context->setRunFlag(mcsv1sdk::UDAF_IGNORE_NULLS);
+ return mcsv1_UDAF::SUCCESS;
+
+}
+
+mcsv1_UDAF::ReturnCode regr_avgy::reset(mcsv1Context* context)
+{
+ struct regr_avgy_data* data = (struct regr_avgy_data*)context->getUserData()->data;
+ data->sum = 0;
+ data->cnt = 0;
+ return mcsv1_UDAF::SUCCESS;
+}
+
+mcsv1_UDAF::ReturnCode regr_avgy::nextValue(mcsv1Context* context, ColumnDatum* valsIn)
+{
+ static_any::any& valIn_y = valsIn[0].columnData;
+ static_any::any& valIn_x = valsIn[1].columnData;
+ struct regr_avgy_data* data = (struct regr_avgy_data*)context->getUserData()->data;
+ DATATYPE val = 0.0;
+
+ if (context->isParamNull(0) || context->isParamNull(1))
+ {
+ return mcsv1_UDAF::SUCCESS; // Ought not happen when UDAF_IGNORE_NULLS is on.
+ }
+ if (valIn_x.empty() || valIn_y.empty()) // Usually empty if NULL. Probably redundant
+ {
+ return mcsv1_UDAF::SUCCESS; // Ought not happen when UDAF_IGNORE_NULLS is on.
+ }
+
+ if (valIn_y.compatible(longTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(charTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(scharTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(shortTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(intTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(llTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(ucharTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(ushortTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(uintTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(ulongTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(ullTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(floatTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(doubleTypeId))
+ {
+ val = valIn_y.cast();
+ }
+
+ // For decimal types, we need to move the decimal point.
+ uint32_t scale = valsIn[0].scale;
+
+ if (val != 0 && scale > 0)
+ {
+ val /= pow(10.0, (double)scale);
+ }
+
+ data->sum += val;
+ ++data->cnt;
+
+ return mcsv1_UDAF::SUCCESS;
+}
+
+mcsv1_UDAF::ReturnCode regr_avgy::subEvaluate(mcsv1Context* context, const UserData* userDataIn)
+{
+ if (!userDataIn)
+ {
+ return mcsv1_UDAF::SUCCESS;
+ }
+
+ struct regr_avgy_data* outData = (struct regr_avgy_data*)context->getUserData()->data;
+ struct regr_avgy_data* inData = (struct regr_avgy_data*)userDataIn->data;
+
+ outData->sum += inData->sum;
+ outData->cnt += inData->cnt;
+
+ return mcsv1_UDAF::SUCCESS;
+}
+
+mcsv1_UDAF::ReturnCode regr_avgy::evaluate(mcsv1Context* context, static_any::any& valOut)
+{
+ struct regr_avgy_data* data = (struct regr_avgy_data*)context->getUserData()->data;
+
+ if (data->cnt == 0)
+ {
+ valOut = 0;
+ }
+ else
+ {
+ valOut = data->sum / (double)data->cnt;
+ }
+ return mcsv1_UDAF::SUCCESS;
+}
+
+mcsv1_UDAF::ReturnCode regr_avgy::dropValue(mcsv1Context* context, ColumnDatum* valsDropped)
+{
+ static_any::any& valIn_y = valsDropped[0].columnData;
+ static_any::any& valIn_x = valsDropped[1].columnData;
+ struct regr_avgy_data* data = (struct regr_avgy_data*)context->getUserData()->data;
+ DATATYPE val = 0.0;
+
+ if (context->isParamNull(0) || context->isParamNull(1))
+ {
+ return mcsv1_UDAF::SUCCESS; // Ought not happen when UDAF_IGNORE_NULLS is on.
+ }
+ if (valIn_x.empty() || valIn_y.empty())
+ {
+ return mcsv1_UDAF::SUCCESS; // Ought not happen when UDAF_IGNORE_NULLS is on.
+ }
+
+ if (valIn_y.compatible(charTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(scharTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(shortTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(intTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(longTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(llTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(ucharTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(ushortTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(uintTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(ulongTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(ullTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(floatTypeId))
+ {
+ val = valIn_y.cast();
+ }
+ else if (valIn_y.compatible(doubleTypeId))
+ {
+ val = valIn_y.cast();
+ }
+
+ // For decimal types, we need to move the decimal point.
+ uint32_t scale = valsDropped[0].scale;
+
+ if (val != 0 && scale > 0)
+ {
+ val /= pow(10.0, (double)scale);
+ }
+
+ data->sum -= val;
+ --data->cnt;
+
+ return mcsv1_UDAF::SUCCESS;
+}
+
diff --git a/utils/regr/regr_avgy.h b/utils/regr/regr_avgy.h
new file mode 100644
index 000000000..c99021f9f
--- /dev/null
+++ b/utils/regr/regr_avgy.h
@@ -0,0 +1,88 @@
+/* Copyright (C) 2017 MariaDB Corporaton
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; version 2 of
+ the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/***********************************************************************
+* $Id$
+*
+* regr_avgy.h
+***********************************************************************/
+
+/**
+ * Columnstore interface for for the regr_avgy function
+ *
+ *
+ * CREATE AGGREGATE FUNCTION regr_avgy returns REAL soname
+ * 'libregr_mysql.so';
+ *
+ */
+#ifndef HEADER_regr_avgy
+#define HEADER_regr_avgy
+
+#include
+#include
+#include
+#ifdef _MSC_VER
+#include
+#else
+#include
+#endif
+
+#include "mcsv1_udaf.h"
+#include "calpontsystemcatalog.h"
+#include "windowfunctioncolumn.h"
+using namespace execplan;
+
+#if defined(_MSC_VER) && defined(xxxRGNODE_DLLEXPORT)
+#define EXPORT __declspec(dllexport)
+#else
+#define EXPORT
+#endif
+
+namespace mcsv1sdk
+{
+
+// Return the regr_avgy value of the dataset
+
+class regr_avgy : public mcsv1_UDAF
+{
+public:
+ // Defaults OK
+ regr_avgy() : mcsv1_UDAF() {};
+ virtual ~regr_avgy() {};
+
+ virtual ReturnCode init(mcsv1Context* context,
+ ColumnDatum* colTypes);
+
+ virtual ReturnCode reset(mcsv1Context* context);
+
+ virtual ReturnCode nextValue(mcsv1Context* context, ColumnDatum* valsIn);
+
+ virtual ReturnCode subEvaluate(mcsv1Context* context, const UserData* valIn);
+
+ virtual ReturnCode evaluate(mcsv1Context* context, static_any::any& valOut);
+
+ virtual ReturnCode dropValue(mcsv1Context* context, ColumnDatum* valsDropped);
+
+protected:
+};
+
+}; // namespace
+
+#undef EXPORT
+
+#endif // HEADER_regr_avgy.h
+
diff --git a/utils/regr/regr_count.cpp b/utils/regr/regr_count.cpp
new file mode 100644
index 000000000..c65a1f4a6
--- /dev/null
+++ b/utils/regr/regr_count.cpp
@@ -0,0 +1,131 @@
+/* Copyright (C) 2017 MariaDB Corporaton
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; version 2 of
+ the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include
+#include
+#include
+#include "regr_count.h"
+#include "bytestream.h"
+#include "objectreader.h"
+
+using namespace mcsv1sdk;
+
+class Add_regr_count_ToUDAFMap
+{
+public:
+ Add_regr_count_ToUDAFMap()
+ {
+ UDAFMap::getMap()["regr_count"] = new regr_count();
+ }
+};
+
+static Add_regr_count_ToUDAFMap addToMap;
+
+// Use the simple data model
+struct regr_count_data
+{
+ uint64_t cnt;
+};
+
+
+mcsv1_UDAF::ReturnCode regr_count::init(mcsv1Context* context,
+ ColumnDatum* colTypes)
+{
+ if (context->getParameterCount() != 2)
+ {
+ // The error message will be prepended with
+ // "The storage engine for the table doesn't support "
+ context->setErrorMessage("regr_count() with other than 2 arguments");
+ return mcsv1_UDAF::ERROR;
+ }
+
+ context->setUserDataSize(sizeof(regr_count_data));
+ context->setResultType(CalpontSystemCatalog::BIGINT);
+ context->setColWidth(8);
+ context->setRunFlag(mcsv1sdk::UDAF_IGNORE_NULLS);
+ return mcsv1_UDAF::SUCCESS;
+
+}
+
+mcsv1_UDAF::ReturnCode regr_count::reset(mcsv1Context* context)
+{
+ struct regr_count_data* data = (struct regr_count_data*)context->getUserData()->data;
+ data->cnt = 0;
+ return mcsv1_UDAF::SUCCESS;
+}
+
+mcsv1_UDAF::ReturnCode regr_count::nextValue(mcsv1Context* context, ColumnDatum* valsIn)
+{
+ static_any::any& valIn_y = valsIn[0].columnData;
+ static_any::any& valIn_x = valsIn[1].columnData;
+ struct regr_count_data* data = (struct regr_count_data*)context->getUserData()->data;
+
+ if (context->isParamNull(0) || context->isParamNull(1))
+ {
+ return mcsv1_UDAF::SUCCESS; // Ought not happen when UDAF_IGNORE_NULLS is on.
+ }
+ if (valIn_x.empty() || valIn_y.empty()) // Usually empty if NULL. Probably redundant
+ {
+ return mcsv1_UDAF::SUCCESS; // Ought not happen when UDAF_IGNORE_NULLS is on.
+ }
+ ++data->cnt;
+
+ return mcsv1_UDAF::SUCCESS;
+}
+
+mcsv1_UDAF::ReturnCode regr_count::subEvaluate(mcsv1Context* context, const UserData* userDataIn)
+{
+ if (!userDataIn)
+ {
+ return mcsv1_UDAF::SUCCESS;
+ }
+
+ struct regr_count_data* outData = (struct regr_count_data*)context->getUserData()->data;
+ struct regr_count_data* inData = (struct regr_count_data*)userDataIn->data;
+
+ outData->cnt += inData->cnt;
+
+ return mcsv1_UDAF::SUCCESS;
+}
+
+mcsv1_UDAF::ReturnCode regr_count::evaluate(mcsv1Context* context, static_any::any& valOut)
+{
+ struct regr_count_data* data = (struct regr_count_data*)context->getUserData()->data;
+
+ valOut = data->cnt;
+ return mcsv1_UDAF::SUCCESS;
+}
+
+mcsv1_UDAF::ReturnCode regr_count::dropValue(mcsv1Context* context, ColumnDatum* valsDropped)
+{
+ static_any::any& valIn_y = valsDropped[0].columnData;
+ static_any::any& valIn_x = valsDropped[1].columnData;
+ struct regr_count_data* data = (struct regr_count_data*)context->getUserData()->data;
+
+ if (context->isParamNull(0) || context->isParamNull(1))
+ {
+ return mcsv1_UDAF::SUCCESS; // Ought not happen when UDAF_IGNORE_NULLS is on.
+ }
+ if (valIn_x.empty() || valIn_y.empty())
+ {
+ return mcsv1_UDAF::SUCCESS; // Ought not happen when UDAF_IGNORE_NULLS is on.
+ }
+ --data->cnt;
+
+ return mcsv1_UDAF::SUCCESS;
+}
+
diff --git a/utils/regr/regr_count.h b/utils/regr/regr_count.h
new file mode 100644
index 000000000..4f4fc558e
--- /dev/null
+++ b/utils/regr/regr_count.h
@@ -0,0 +1,88 @@
+/* Copyright (C) 2017 MariaDB Corporaton
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; version 2 of
+ the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/***********************************************************************
+* $Id$
+*
+* regr_count.h
+***********************************************************************/
+
+/**
+ * Columnstore interface for for the regr_count function
+ *
+ *
+ * CREATE AGGREGATE FUNCTION regr_count returns INTEGER
+ * soname 'libregr_mysql.so';
+ *
+ */
+#ifndef HEADER_regr_count
+#define HEADER_regr_count
+
+#include
+#include
+#include
+#ifdef _MSC_VER
+#include
+#else
+#include
+#endif
+
+#include "mcsv1_udaf.h"
+#include "calpontsystemcatalog.h"
+#include "windowfunctioncolumn.h"
+using namespace execplan;
+
+#if defined(_MSC_VER) && defined(xxxRGNODE_DLLEXPORT)
+#define EXPORT __declspec(dllexport)
+#else
+#define EXPORT
+#endif
+
+namespace mcsv1sdk
+{
+
+// Return the regr_count value of the dataset
+
+class regr_count : public mcsv1_UDAF
+{
+public:
+ // Defaults OK
+ regr_count() : mcsv1_UDAF() {};
+ virtual ~regr_count() {};
+
+ virtual ReturnCode init(mcsv1Context* context,
+ ColumnDatum* colTypes);
+
+ virtual ReturnCode reset(mcsv1Context* context);
+
+ virtual ReturnCode nextValue(mcsv1Context* context, ColumnDatum* valsIn);
+
+ virtual ReturnCode subEvaluate(mcsv1Context* context, const UserData* valIn);
+
+ virtual ReturnCode evaluate(mcsv1Context* context, static_any::any& valOut);
+
+ virtual ReturnCode dropValue(mcsv1Context* context, ColumnDatum* valsDropped);
+
+protected:
+};
+
+}; // namespace
+
+#undef EXPORT
+
+#endif // HEADER_regr_count.h
+
diff --git a/utils/regr/regrmysql.cpp b/utils/regr/regrmysql.cpp
new file mode 100644
index 000000000..6870f3050
--- /dev/null
+++ b/utils/regr/regrmysql.cpp
@@ -0,0 +1,374 @@
+#include
+#include
+#include
+#include
+using namespace std;
+
+#include "idb_mysql.h"
+
+namespace
+{
+inline double cvtArgToDouble(int t, const char* v)
+{
+ double d = 0.0;
+
+ switch (t)
+ {
+ case INT_RESULT:
+ d = (double)(*((long long*)v));
+ break;
+
+ case REAL_RESULT:
+ d = *((double*)v);
+ break;
+
+ case DECIMAL_RESULT:
+ case STRING_RESULT:
+ d = strtod(v, 0);
+ break;
+
+ case ROW_RESULT:
+ break;
+ }
+
+ return d;
+}
+inline long long cvtArgToInt(int t, const char* v)
+{
+ long long ll = 0;
+
+ switch (t)
+ {
+ case INT_RESULT:
+ ll = *((long long*)v);
+ break;
+
+ case REAL_RESULT:
+ ll = (long long)(*((double*)v));
+ break;
+
+ case DECIMAL_RESULT:
+ case STRING_RESULT:
+ ll = strtoll(v, 0, 0);
+ break;
+
+ case ROW_RESULT:
+ break;
+ }
+
+ return ll;
+}
+inline string cvtArgToString(int t, const char* v)
+{
+ string str;
+
+ switch (t)
+ {
+ case INT_RESULT:
+ {
+ long long ll;
+ ll = *((long long*)v);
+ ostringstream oss;
+ oss << ll;
+ str = oss.str();
+ break;
+ }
+
+ case REAL_RESULT:
+ {
+ double d;
+ d = *((double*)v);
+ ostringstream oss;
+ oss << d;
+ str = oss.str();
+ break;
+ }
+
+ case DECIMAL_RESULT:
+ case STRING_RESULT:
+ str = v;
+ break;
+
+ case ROW_RESULT:
+ break;
+ }
+
+ return str;
+}
+}
+
+/****************************************************************************
+ * UDF function interface for MariaDB connector to recognize is defined in
+ * this section. MariaDB's UDF function creation guideline needs to be followed.
+ *
+ * Three interface need to be defined on the connector for each UDF function.
+ *
+ * XXX_init: To allocate the necessary memory for the UDF function and validate
+ * the input.
+ * XXX_deinit: To clean up the memory.
+ * XXX: The function implementation.
+ * Detailed instruction can be found at MariaDB source directory:
+ * ~/sql/udf_example.cc.
+ *
+ * Please note that the implementation of the function defined on the connector
+ * will only be called when all the input arguments are constant. e.g.,
+ * mcs_add(2,3). That way, the function does not run in a distributed fashion
+ * and could be slow. If there is a need for the UDF function to run with
+ * pure constant input, then one needs to put a implementation in the XXX
+ * body, which is very similar to the ones in getXXXval API. If there's no
+ * such need for a given UDF, then the XXX interface can just return a dummy
+ * result because this function will never be called.
+ */
+extern "C"
+{
+
+//=======================================================================
+
+ /**
+ * regr_avgx connector stub
+ */
+ struct regr_avgx_data
+ {
+ double sumx;
+ int64_t cnt;
+ };
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ my_bool regr_avgx_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
+ {
+ struct regr_avgx_data* data;
+ if (args->arg_count != 2)
+ {
+ strcpy(message,"regr_avgx() requires two arguments");
+ return 1;
+ }
+
+ if (!(data = (struct regr_avgx_data*) malloc(sizeof(struct regr_avgx_data))))
+ {
+ strmov(message,"Couldn't allocate memory");
+ return 1;
+ }
+ data->sumx = 0;
+ data->cnt = 0;
+
+ initid->ptr = (char*)data;
+ return 0;
+ }
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ void regr_avgx_deinit(UDF_INIT* initid)
+ {
+ free(initid->ptr);
+ }
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ void
+ regr_avgx_clear(UDF_INIT* initid, char* is_null __attribute__((unused)),
+ char* message __attribute__((unused)))
+ {
+ struct regr_avgx_data* data = (struct regr_avgx_data*)initid->ptr;
+ data->sumx = 0;
+ data->cnt = 0;
+ }
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ void
+ regr_avgx_add(UDF_INIT* initid, UDF_ARGS* args,
+ char* is_null,
+ char* message __attribute__((unused)))
+ {
+ // Test for NULL in x and y
+ if (args->args[0] == 0 || args->args[1] == 0)
+ {
+ return;
+ }
+ struct regr_avgx_data* data = (struct regr_avgx_data*)initid->ptr;
+ double xval = cvtArgToDouble(args->arg_type[1], args->args[1]);
+ ++data->cnt;
+ data->sumx += xval;
+ }
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ long long regr_avgx(UDF_INIT* initid, UDF_ARGS* args __attribute__((unused)),
+ char* is_null, char* error __attribute__((unused)))
+ {
+ struct regr_avgx_data* data = (struct regr_avgx_data*)initid->ptr;
+ return data->sumx / data->cnt;
+ }
+
+//=======================================================================
+
+ /**
+ * regr_avgy connector stub
+ */
+ struct regr_avgy_data
+ {
+ double sumy;
+ int64_t cnt;
+ };
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ my_bool regr_avgy_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
+ {
+ struct regr_avgy_data* data;
+ if (args->arg_count != 2)
+ {
+ strcpy(message,"regr_avgy() requires two arguments");
+ return 1;
+ }
+
+ if (!(data = (struct regr_avgy_data*) malloc(sizeof(struct regr_avgy_data))))
+ {
+ strmov(message,"Couldn't allocate memory");
+ return 1;
+ }
+ data->sumy = 0;
+ data->cnt = 0;
+
+ initid->ptr = (char*)data;
+ return 0;
+ }
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ void regr_avgy_deinit(UDF_INIT* initid)
+ {
+ free(initid->ptr);
+ }
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ void
+ regr_avgy_clear(UDF_INIT* initid, char* is_null __attribute__((unused)),
+ char* message __attribute__((unused)))
+ {
+ struct regr_avgy_data* data = (struct regr_avgy_data*)initid->ptr;
+ data->sumy = 0;
+ data->cnt = 0;
+ }
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ void
+ regr_avgy_add(UDF_INIT* initid, UDF_ARGS* args,
+ char* is_null,
+ char* message __attribute__((unused)))
+ {
+ // Test for NULL in x and y
+ if (args->args[0] == 0 || args->args[1] == 0)
+ {
+ return;
+ }
+ struct regr_avgy_data* data = (struct regr_avgy_data*)initid->ptr;
+ double yval = cvtArgToDouble(args->arg_type[0], args->args[0]);
+ ++data->cnt;
+ data->sumy += yval;
+ }
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ long long regr_avgy(UDF_INIT* initid, UDF_ARGS* args __attribute__((unused)),
+ char* is_null, char* error __attribute__((unused)))
+ {
+ struct regr_avgy_data* data = (struct regr_avgy_data*)initid->ptr;
+ return data->sumy / data->cnt;
+ }
+
+//=======================================================================
+
+ /**
+ * regr_count connector stub
+ */
+ struct regr_count_data
+ {
+ int64_t cnt;
+ };
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ my_bool regr_count_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
+ {
+ struct regr_count_data* data;
+ if (args->arg_count != 2)
+ {
+ strcpy(message,"regr_count() requires two arguments");
+ return 1;
+ }
+
+ if (!(data = (struct regr_count_data*) malloc(sizeof(struct regr_count_data))))
+ {
+ strmov(message,"Couldn't allocate memory");
+ return 1;
+ }
+ data->cnt = 0;
+
+ initid->ptr = (char*)data;
+ return 0;
+ }
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ void regr_count_deinit(UDF_INIT* initid)
+ {
+ free(initid->ptr);
+ }
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ void
+ regr_count_clear(UDF_INIT* initid, char* is_null __attribute__((unused)),
+ char* message __attribute__((unused)))
+ {
+ struct regr_count_data* data = (struct regr_count_data*)initid->ptr;
+ data->cnt = 0;
+ }
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ void
+ regr_count_add(UDF_INIT* initid, UDF_ARGS* args,
+ char* is_null,
+ char* message __attribute__((unused)))
+ {
+ // Test for NULL in x and y
+ if (args->args[0] == 0 || args->args[1] == 0)
+ {
+ return;
+ }
+ struct regr_count_data* data = (struct regr_count_data*)initid->ptr;
+ ++data->cnt;
+ }
+
+ #ifdef _MSC_VER
+ __declspec(dllexport)
+ #endif
+ long long regr_count(UDF_INIT* initid, UDF_ARGS* args __attribute__((unused)),
+ char* is_null, char* error __attribute__((unused)))
+ {
+ struct regr_count_data* data = (struct regr_count_data*)initid->ptr;
+ return data->cnt;
+ }
+//=======================================================================
+}
+// vim:ts=4 sw=4:
+
diff --git a/utils/utils.vpj b/utils/utils.vpj
index 53da962f3..d81586008 100755
--- a/utils/utils.vpj
+++ b/utils/utils.vpj
@@ -292,6 +292,8 @@
Filters="*.bmp"/>
+ Filters="">
+
+