functionMgt.c 7.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * 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.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "functionMgt.h"

18 19
#include "builtins.h"
#include "catalog.h"
20 21 22 23
#include "functionMgtInt.h"
#include "taos.h"
#include "taoserror.h"
#include "thash.h"
S
shenglian zhou 已提交
24
#include "tudf.h"
25 26 27 28 29

typedef struct SFuncMgtService {
  SHashObj* pFuncNameHashTable;
} SFuncMgtService;

30 31
typedef struct SUdfInfo {
  SDataType outputDt;
32
  int8_t    funcType;
33 34
} SUdfInfo;

35
static SFuncMgtService gFunMgtService;
36 37
static TdThreadOnce    functionHashTableInit = PTHREAD_ONCE_INIT;
static int32_t         initFunctionCode = 0;
38

39
static void doInitFunctionTable() {
40 41
  gFunMgtService.pFuncNameHashTable =
      taosHashInit(funcMgtBuiltinsNum, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
42
  if (NULL == gFunMgtService.pFuncNameHashTable) {
H
Haojun Liao 已提交
43 44
    initFunctionCode = TSDB_CODE_FAILED;
    return;
45
  }
H
Haojun Liao 已提交
46

47
  for (int32_t i = 0; i < funcMgtBuiltinsNum; ++i) {
48 49
    if (TSDB_CODE_SUCCESS != taosHashPut(gFunMgtService.pFuncNameHashTable, funcMgtBuiltins[i].name,
                                         strlen(funcMgtBuiltins[i].name), &i, sizeof(int32_t))) {
H
Haojun Liao 已提交
50 51
      initFunctionCode = TSDB_CODE_FAILED;
      return;
52
    }
53
  }
D
dapan1121 已提交
54 55
}

56
static bool isSpecificClassifyFunc(int32_t funcId, uint64_t classification) {
D
dapan1121 已提交
57
  if (fmIsUserDefinedFunc(funcId)) {
58 59 60
    return FUNC_MGT_AGG_FUNC == classification
               ? FUNC_AGGREGATE_UDF_ID == funcId
               : (FUNC_MGT_SCALAR_FUNC == classification ? FUNC_SCALAR_UDF_ID == funcId : false);
D
dapan1121 已提交
61
  }
62 63 64 65 66 67
  if (funcId < 0 || funcId >= funcMgtBuiltinsNum) {
    return false;
  }
  return FUNC_MGT_TEST_MASK(funcMgtBuiltins[funcId].classification, classification);
}

68
static int32_t getUdfInfo(SFmGetFuncInfoParam* pParam, SFunctionNode* pFunc) {
D
dapan1121 已提交
69
  SFuncInfo* pInfo = NULL;
70
  int32_t    code = catalogGetUdfInfo(pParam->pCtg, pParam->pRpc, pParam->pMgmtEps, pFunc->functionName, &pInfo);
71 72 73 74 75 76 77 78 79 80 81 82
  if (TSDB_CODE_SUCCESS != code) {
    return code;
  }
  if (NULL == pInfo) {
    snprintf(pParam->pErrBuf, pParam->errBufLen, "Invalid function name: %s", pFunc->functionName);
    return TSDB_CODE_FUNC_INVALID_FUNTION;
  }
  pFunc->funcType = FUNCTION_TYPE_UDF;
  pFunc->funcId = TSDB_FUNC_TYPE_AGGREGATE == pInfo->funcType ? FUNC_AGGREGATE_UDF_ID : FUNC_SCALAR_UDF_ID;
  pFunc->node.resType.type = pInfo->outputType;
  pFunc->node.resType.bytes = pInfo->outputLen;
  pFunc->udfBufSize = pInfo->bufSize;
D
dapan1121 已提交
83 84
  tFreeSFuncInfo(pInfo);
  taosMemoryFree(pInfo);
85 86 87
  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
88
int32_t fmFuncMgtInit() {
89
  taosThreadOnce(&functionHashTableInit, doInitFunctionTable);
H
Haojun Liao 已提交
90
  return initFunctionCode;
91 92
}

93 94 95 96 97 98
int32_t fmGetFuncInfo(SFmGetFuncInfoParam* pParam, SFunctionNode* pFunc) {
  void* pVal = taosHashGet(gFunMgtService.pFuncNameHashTable, pFunc->functionName, strlen(pFunc->functionName));
  if (NULL != pVal) {
    pFunc->funcId = *(int32_t*)pVal;
    pFunc->funcType = funcMgtBuiltins[pFunc->funcId].type;
    return funcMgtBuiltins[pFunc->funcId].translateFunc(pFunc, pParam->pErrBuf, pParam->errBufLen);
99
  }
100
  return getUdfInfo(pParam, pFunc);
101 102
}

103 104 105 106
bool fmIsBuiltinFunc(const char* pFunc) {
  return NULL != taosHashGet(gFunMgtService.pFuncNameHashTable, pFunc, strlen(pFunc));
}

107
EFuncDataRequired fmFuncDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
108
  if (fmIsUserDefinedFunc(pFunc->funcId) || pFunc->funcId < 0 || pFunc->funcId >= funcMgtBuiltinsNum) {
109
    return FUNC_DATA_REQUIRED_DATA_LOAD;
110 111
  }
  if (NULL == funcMgtBuiltins[pFunc->funcId].dataRequiredFunc) {
112
    return FUNC_DATA_REQUIRED_DATA_LOAD;
113 114 115 116
  }
  return funcMgtBuiltins[pFunc->funcId].dataRequiredFunc(pFunc, pTimeWindow);
}

X
Xiaoyu Wang 已提交
117
int32_t fmGetFuncExecFuncs(int32_t funcId, SFuncExecFuncs* pFpSet) {
118
  if (fmIsUserDefinedFunc(funcId) || funcId < 0 || funcId >= funcMgtBuiltinsNum) {
X
Xiaoyu Wang 已提交
119 120 121 122 123 124 125 126 127
    return TSDB_CODE_FAILED;
  }
  pFpSet->getEnv = funcMgtBuiltins[funcId].getEnvFunc;
  pFpSet->init = funcMgtBuiltins[funcId].initFunc;
  pFpSet->process = funcMgtBuiltins[funcId].processFunc;
  pFpSet->finalize = funcMgtBuiltins[funcId].finalizeFunc;
  return TSDB_CODE_SUCCESS;
}

128 129 130 131
int32_t fmGetUdafExecFuncs(int32_t funcId, SFuncExecFuncs* pFpSet) {
  if (!fmIsUserDefinedFunc(funcId)) {
    return TSDB_CODE_FAILED;
  }
S
shenglian zhou 已提交
132 133 134 135 136 137 138
  pFpSet->getEnv = udfAggGetEnv;
  pFpSet->init = udfAggInit;
  pFpSet->process = udfAggProcess;
  pFpSet->finalize = udfAggFinalize;
  return TSDB_CODE_SUCCESS;
}

D
dapan1121 已提交
139
int32_t fmGetScalarFuncExecFuncs(int32_t funcId, SScalarFuncExecFuncs* pFpSet) {
140
  if (fmIsUserDefinedFunc(funcId) || funcId < 0 || funcId >= funcMgtBuiltinsNum) {
D
dapan1121 已提交
141 142 143
    return TSDB_CODE_FAILED;
  }
  pFpSet->process = funcMgtBuiltins[funcId].sprocessFunc;
144
  pFpSet->getEnv = funcMgtBuiltins[funcId].getEnvFunc;
D
dapan1121 已提交
145 146 147
  return TSDB_CODE_SUCCESS;
}

148
bool fmIsAggFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_AGG_FUNC); }
149

150
bool fmIsScalarFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SCALAR_FUNC); }
151

152 153
bool fmIsSelectFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SELECT_FUNC); }

X
Xiaoyu Wang 已提交
154 155
bool fmIsTimelineFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_TIMELINE_FUNC); }

156
bool fmIsPseudoColumnFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_PSEUDO_COLUMN_FUNC); }
X
Xiaoyu Wang 已提交
157

158
bool fmIsScanPseudoColumnFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SCAN_PC_FUNC); }
159

160
bool fmIsWindowPseudoColumnFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_WINDOW_PC_FUNC); }
X
Xiaoyu Wang 已提交
161

162 163 164
bool fmIsWindowClauseFunc(int32_t funcId) { return fmIsAggFunc(funcId) || fmIsWindowPseudoColumnFunc(funcId); }

bool fmIsNonstandardSQLFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_NONSTANDARD_SQL_FUNC); }
H
Haojun Liao 已提交
165

166 167 168 169 170 171 172
bool fmIsSpecialDataRequiredFunc(int32_t funcId) {
  return isSpecificClassifyFunc(funcId, FUNC_MGT_SPECIAL_DATA_REQUIRED);
}

bool fmIsDynamicScanOptimizedFunc(int32_t funcId) {
  return isSpecificClassifyFunc(funcId, FUNC_MGT_DYNAMIC_SCAN_OPTIMIZED);
}
H
Haojun Liao 已提交
173

174
bool fmIsMultiResFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_MULTI_RES_FUNC); }
175

X
Xiaoyu Wang 已提交
176 177
bool fmIsRepeatScanFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_REPEAT_SCAN_FUNC); }

178
bool fmIsUserDefinedFunc(int32_t funcId) { return funcId > FUNC_UDF_ID_START; }
179

X
Xiaoyu Wang 已提交
180 181
void fmFuncMgtDestroy() {
  void* m = gFunMgtService.pFuncNameHashTable;
wafwerar's avatar
wafwerar 已提交
182
  if (m != NULL && atomic_val_compare_exchange_ptr((void**)&gFunMgtService.pFuncNameHashTable, m, 0) == m) {
X
Xiaoyu Wang 已提交
183 184 185
    taosHashCleanup(m);
  }
}
5
54liuyao 已提交
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205

int32_t fmSetInvertFunc(int32_t funcId, SFuncExecFuncs* pFpSet) {
  if (fmIsUserDefinedFunc(funcId) || funcId < 0 || funcId >= funcMgtBuiltinsNum) {
    return TSDB_CODE_FAILED;
  }
  pFpSet->process = funcMgtBuiltins[funcId].invertFunc;
  return TSDB_CODE_SUCCESS;
}

int32_t fmSetNormalFunc(int32_t funcId, SFuncExecFuncs* pFpSet) {
  if (fmIsUserDefinedFunc(funcId) || funcId < 0 || funcId >= funcMgtBuiltinsNum) {
    return TSDB_CODE_FAILED;
  }
  pFpSet->process = funcMgtBuiltins[funcId].processFunc;
  return TSDB_CODE_SUCCESS;
}

bool fmIsInvertible(int32_t funcId) {
  bool res = false;
  switch (funcMgtBuiltins[funcId].type) {
X
Xiaoyu Wang 已提交
206 207 208 209
    case FUNCTION_TYPE_COUNT:
    case FUNCTION_TYPE_SUM:
    case FUNCTION_TYPE_STDDEV:
    case FUNCTION_TYPE_AVG:
210 211 212
    case FUNCTION_TYPE_WSTARTTS:
    case FUNCTION_TYPE_WENDTS:
    case FUNCTION_TYPE_WDURATION:
X
Xiaoyu Wang 已提交
213 214 215 216
      res = true;
      break;
    default:
      break;
5
54liuyao 已提交
217 218 219
  }
  return res;
}