homework-jianmu/tests/script/sh/extract_avg.c

129 lines
4.2 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "taos.h"
#include "taoserror.h"
#include "taosudf.h"
// Define a structure to store sum and count
typedef struct {
double sum;
int count;
} SumCount;
// initialization function
DLL_EXPORT int32_t extract_avg_init() {
udfTrace("extract_avg_init: Initializing UDF");
return TSDB_CODE_SUCCESS;
}
DLL_EXPORT int32_t extract_avg_start(SUdfInterBuf *interBuf) {
int32_t bufLen = sizeof(SumCount);
if (interBuf->bufLen < bufLen) {
udfError("extract_avg_start: Failed to execute UDF since input buflen:%d < %d", interBuf->bufLen, bufLen);
return TSDB_CODE_UDF_INVALID_BUFSIZE;
}
// Initialize sum and count
SumCount *sumCount = (SumCount *)interBuf->buf;
sumCount->sum = 0.0;
sumCount->count = 0;
interBuf->numOfResult = 0;
udfTrace("extract_avg_start: Initialized sum=0.0, count=0");
return TSDB_CODE_SUCCESS;
}
DLL_EXPORT int32_t extract_avg(SUdfDataBlock *inputBlock, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf) {
udfTrace("extract_avg: Processing data block with %d rows", inputBlock->numOfRows);
// Check the number of columns in the input data block
if (inputBlock->numOfCols != 1) {
udfError("extract_avg: Invalid number of columns. Expected 1, got %d", inputBlock->numOfCols);
return TSDB_CODE_UDF_INVALID_INPUT;
}
// Get the input column
SUdfColumn *inputCol = inputBlock->udfCols[0];
if (inputCol->colMeta.type != TSDB_DATA_TYPE_VARCHAR) {
udfError("extract_avg: Invalid data type. Expected VARCHAR, got %d", inputCol->colMeta.type);
return TSDB_CODE_UDF_INVALID_INPUT;
}
// Read the current sum and count from interBuf
SumCount *sumCount = (SumCount *)interBuf->buf;
udfTrace("extract_avg: Starting with sum=%f, count=%d", sumCount->sum, sumCount->count);
for (int i = 0; i < inputBlock->numOfRows; i++) {
if (udfColDataIsNull(inputCol, i)) {
udfTrace("extract_avg: Skipping NULL value at row %d", i);
continue;
}
char *buf = (char *)udfColDataGetData(inputCol, i);
char data[64];
memset(data, 0, 64);
memcpy(data, varDataVal(buf), varDataLen(buf));
udfTrace("extract_avg: Processing row %d, data='%s'", i, data);
char *rest = data;
char *token;
while ((token = strtok_r(rest, ",", &rest))) {
while (*token == ' ') token++;
int tokenLen = strlen(token);
while (tokenLen > 0 && token[tokenLen - 1] == ' ') token[--tokenLen] = '\0';
if (tokenLen == 0) {
udfTrace("extract_avg: Empty string encountered at row %d", i);
continue;
}
char *endPtr;
double value = strtod(token, &endPtr);
if (endPtr == token || *endPtr != '\0') {
udfError("extract_avg: Failed to convert string '%s' to double at row %d", token, i);
continue;
}
sumCount->sum += value;
sumCount->count++;
udfTrace("extract_avg: Updated sum=%f, count=%d", sumCount->sum, sumCount->count);
}
}
newInterBuf->bufLen = sizeof(SumCount);
newInterBuf->buf = (char *)malloc(newInterBuf->bufLen);
if (newInterBuf->buf == NULL) {
udfError("extract_avg: Failed to allocate memory for newInterBuf");
return TSDB_CODE_UDF_INTERNAL_ERROR;
}
memcpy(newInterBuf->buf, sumCount, newInterBuf->bufLen);
newInterBuf->numOfResult = 0;
udfTrace("extract_avg: Final sum=%f, count=%d", sumCount->sum, sumCount->count);
return TSDB_CODE_SUCCESS;
}
DLL_EXPORT int32_t extract_avg_finish(SUdfInterBuf *interBuf, SUdfInterBuf *result) {
SumCount *sumCount = (SumCount *)interBuf->buf;
double avg = (sumCount->count > 0) ? (sumCount->sum / sumCount->count) : 0.0;
*(double *)result->buf = avg;
result->bufLen = sizeof(double);
result->numOfResult = sumCount->count > 0 ? 1 : 0;
udfTrace("extract_avg_finish: Final result=%f (sum=%f, count=%d)", avg, sumCount->sum, sumCount->count);
return TSDB_CODE_SUCCESS;
}
DLL_EXPORT int32_t extract_avg_destroy() {
udfTrace("extract_avg_destroy: Cleaning up UDF");
return TSDB_CODE_SUCCESS;
}