• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #4905

29 Dec 2025 02:08PM UTC coverage: 65.423% (-0.3%) from 65.734%
#4905

push

travis-ci

web-flow
enh: sign connect request (#34067)

23 of 29 new or added lines in 4 files covered. (79.31%)

11614 existing lines in 186 files now uncovered.

193476 of 295730 relevant lines covered (65.42%)

115752566.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.32
/source/dnode/mnode/impl/src/mndFunc.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#define _DEFAULT_SOURCE
17
#include "mndFunc.h"
18
#include "mndPrivilege.h"
19
#include "mndShow.h"
20
#include "mndSync.h"
21
#include "mndTrans.h"
22
#include "mndUser.h"
23

24
#define SDB_FUNC_VER          2
25
#define SDB_FUNC_RESERVE_SIZE 64
26

27
static SSdbRaw *mndFuncActionEncode(SFuncObj *pFunc);
28
static SSdbRow *mndFuncActionDecode(SSdbRaw *pRaw);
29
static int32_t  mndFuncActionInsert(SSdb *pSdb, SFuncObj *pFunc);
30
static int32_t  mndFuncActionDelete(SSdb *pSdb, SFuncObj *pFunc);
31
static int32_t  mndFuncActionUpdate(SSdb *pSdb, SFuncObj *pOld, SFuncObj *pNew);
32
static int32_t  mndCreateFunc(SMnode *pMnode, SRpcMsg *pReq, SCreateFuncReq *pCreate);
33
static int32_t  mndDropFunc(SMnode *pMnode, SRpcMsg *pReq, SFuncObj *pFunc);
34
static int32_t  mndProcessCreateFuncReq(SRpcMsg *pReq);
35
static int32_t  mndProcessDropFuncReq(SRpcMsg *pReq);
36
static int32_t  mndProcessRetrieveFuncReq(SRpcMsg *pReq);
37
static int32_t  mndRetrieveFuncs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
38
static void     mndCancelGetNextFunc(SMnode *pMnode, void *pIter);
39

40
int32_t mndInitFunc(SMnode *pMnode) {
384,121✔
41
  SSdbTable table = {
384,121✔
42
      .sdbType = SDB_FUNC,
43
      .keyType = SDB_KEY_BINARY,
44
      .encodeFp = (SdbEncodeFp)mndFuncActionEncode,
45
      .decodeFp = (SdbDecodeFp)mndFuncActionDecode,
46
      .insertFp = (SdbInsertFp)mndFuncActionInsert,
47
      .updateFp = (SdbUpdateFp)mndFuncActionUpdate,
48
      .deleteFp = (SdbDeleteFp)mndFuncActionDelete,
49
  };
50

51
  mndSetMsgHandle(pMnode, TDMT_MND_CREATE_FUNC, mndProcessCreateFuncReq);
384,121✔
52
  mndSetMsgHandle(pMnode, TDMT_MND_DROP_FUNC, mndProcessDropFuncReq);
384,121✔
53
  mndSetMsgHandle(pMnode, TDMT_MND_RETRIEVE_FUNC, mndProcessRetrieveFuncReq);
384,121✔
54

55
  mndAddShowRetrieveHandle(pMnode, TSDB_MGMT_TABLE_FUNC, mndRetrieveFuncs);
384,121✔
56
  mndAddShowFreeIterHandle(pMnode, TSDB_MGMT_TABLE_FUNC, mndCancelGetNextFunc);
384,121✔
57

58
  return sdbSetTable(pMnode->pSdb, table);
384,121✔
59
}
60

61
void mndCleanupFunc(SMnode *pMnode) {}
384,058✔
62

63
static SSdbRaw *mndFuncActionEncode(SFuncObj *pFunc) {
27,206✔
64
  int32_t code = 0;
27,206✔
65
  int32_t lino = 0;
27,206✔
66
  terrno = TSDB_CODE_OUT_OF_MEMORY;
27,206✔
67

68
  int32_t  size = pFunc->commentSize + pFunc->codeSize + sizeof(SFuncObj) + SDB_FUNC_RESERVE_SIZE;
27,206✔
69
  SSdbRaw *pRaw = sdbAllocRaw(SDB_FUNC, SDB_FUNC_VER, size);
27,206✔
70
  if (pRaw == NULL) goto _OVER;
27,206✔
71

72
  int32_t dataPos = 0;
27,206✔
73
  SDB_SET_BINARY(pRaw, dataPos, pFunc->name, TSDB_FUNC_NAME_LEN, _OVER)
27,206✔
74
  SDB_SET_INT64(pRaw, dataPos, pFunc->createdTime, _OVER)
27,206✔
75
  SDB_SET_INT8(pRaw, dataPos, pFunc->funcType, _OVER)
27,206✔
76
  SDB_SET_INT8(pRaw, dataPos, pFunc->scriptType, _OVER)
27,206✔
77
  SDB_SET_INT8(pRaw, dataPos, pFunc->align, _OVER)
27,206✔
78
  SDB_SET_INT8(pRaw, dataPos, pFunc->outputType, _OVER)
27,206✔
79
  SDB_SET_INT32(pRaw, dataPos, pFunc->outputLen, _OVER)
27,206✔
80
  SDB_SET_INT32(pRaw, dataPos, pFunc->bufSize, _OVER)
27,206✔
81
  SDB_SET_INT64(pRaw, dataPos, pFunc->signature, _OVER)
27,206✔
82
  SDB_SET_INT32(pRaw, dataPos, pFunc->commentSize, _OVER)
27,206✔
83
  SDB_SET_INT32(pRaw, dataPos, pFunc->codeSize, _OVER)
27,206✔
84
  if (pFunc->commentSize > 0) {
27,206✔
85
    SDB_SET_BINARY(pRaw, dataPos, pFunc->pComment, pFunc->commentSize, _OVER)
×
86
  }
87
  SDB_SET_BINARY(pRaw, dataPos, pFunc->pCode, pFunc->codeSize, _OVER)
27,206✔
88
  SDB_SET_INT32(pRaw, dataPos, pFunc->funcVersion, _OVER)
27,206✔
89
  SDB_SET_RESERVE(pRaw, dataPos, SDB_FUNC_RESERVE_SIZE, _OVER)
27,206✔
90
  SDB_SET_DATALEN(pRaw, dataPos, _OVER);
27,206✔
91

92
  terrno = 0;
27,206✔
93

94
_OVER:
27,206✔
95
  if (terrno != 0) {
27,206✔
96
    mError("func:%s, failed to encode to raw:%p since %s", pFunc->name, pRaw, terrstr());
×
97
    sdbFreeRaw(pRaw);
×
98
    return NULL;
×
99
  }
100

101
  mTrace("func:%s, encode to raw:%p, row:%p", pFunc->name, pRaw, pFunc);
27,206✔
102
  return pRaw;
27,206✔
103
}
104

105
static SSdbRow *mndFuncActionDecode(SSdbRaw *pRaw) {
19,176✔
106
  int32_t code = 0;
19,176✔
107
  int32_t lino = 0;
19,176✔
108
  terrno = TSDB_CODE_OUT_OF_MEMORY;
19,176✔
109
  SSdbRow  *pRow = NULL;
19,176✔
110
  SFuncObj *pFunc = NULL;
19,176✔
111

112
  int8_t sver = 0;
19,176✔
113
  if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
19,176✔
114

115
  if (sver != 1 && sver != 2) {
19,176✔
116
    terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
×
117
    goto _OVER;
×
118
  }
119

120
  pRow = sdbAllocRow(sizeof(SFuncObj));
19,176✔
121
  if (pRow == NULL) goto _OVER;
19,176✔
122

123
  pFunc = sdbGetRowObj(pRow);
19,176✔
124
  if (pFunc == NULL) goto _OVER;
19,176✔
125

126
  int32_t dataPos = 0;
19,176✔
127
  SDB_GET_BINARY(pRaw, dataPos, pFunc->name, TSDB_FUNC_NAME_LEN, _OVER)
19,176✔
128
  SDB_GET_INT64(pRaw, dataPos, &pFunc->createdTime, _OVER)
19,176✔
129
  SDB_GET_INT8(pRaw, dataPos, &pFunc->funcType, _OVER)
19,176✔
130
  SDB_GET_INT8(pRaw, dataPos, &pFunc->scriptType, _OVER)
19,176✔
131
  SDB_GET_INT8(pRaw, dataPos, &pFunc->align, _OVER)
19,176✔
132
  SDB_GET_INT8(pRaw, dataPos, &pFunc->outputType, _OVER)
19,176✔
133
  SDB_GET_INT32(pRaw, dataPos, &pFunc->outputLen, _OVER)
19,176✔
134
  SDB_GET_INT32(pRaw, dataPos, &pFunc->bufSize, _OVER)
19,176✔
135
  SDB_GET_INT64(pRaw, dataPos, &pFunc->signature, _OVER)
19,176✔
136
  SDB_GET_INT32(pRaw, dataPos, &pFunc->commentSize, _OVER)
19,176✔
137
  SDB_GET_INT32(pRaw, dataPos, &pFunc->codeSize, _OVER)
19,176✔
138

139
  if (pFunc->commentSize > 0) {
19,176✔
140
    pFunc->pComment = taosMemoryCalloc(1, pFunc->commentSize);
×
141
    if (pFunc->pComment == NULL) {
×
142
      goto _OVER;
×
143
    }
144
    SDB_GET_BINARY(pRaw, dataPos, pFunc->pComment, pFunc->commentSize, _OVER)
×
145
  }
146

147
  pFunc->pCode = taosMemoryCalloc(1, pFunc->codeSize);
19,176✔
148
  if (pFunc->pCode == NULL) {
19,176✔
149
    goto _OVER;
×
150
  }
151
  SDB_GET_BINARY(pRaw, dataPos, pFunc->pCode, pFunc->codeSize, _OVER)
19,176✔
152

153
  if (sver >= 2) {
19,176✔
154
    SDB_GET_INT32(pRaw, dataPos, &pFunc->funcVersion, _OVER)
19,176✔
155
  }
156

157
  SDB_GET_RESERVE(pRaw, dataPos, SDB_FUNC_RESERVE_SIZE, _OVER)
19,176✔
158

159
  taosInitRWLatch(&pFunc->lock);
19,176✔
160

161
  terrno = 0;
19,176✔
162

163
_OVER:
19,176✔
164
  if (terrno != 0) {
19,176✔
165
    mError("func:%s, failed to decode from raw:%p since %s", pFunc == NULL ? "null" : pFunc->name, pRaw, terrstr());
×
166
    taosMemoryFreeClear(pRow);
×
167
    return NULL;
×
168
  }
169

170
  mTrace("func:%s, decode from raw:%p, row:%p", pFunc->name, pRaw, pFunc);
19,176✔
171
  return pRow;
19,176✔
172
}
173

174
static int32_t mndFuncActionInsert(SSdb *pSdb, SFuncObj *pFunc) {
6,965✔
175
  mTrace("func:%s, perform insert action, row:%p", pFunc->name, pFunc);
6,965✔
176
  return 0;
6,965✔
177
}
178

179
static int32_t mndFuncActionDelete(SSdb *pSdb, SFuncObj *pFunc) {
19,176✔
180
  mTrace("func:%s, perform delete action, row:%p", pFunc->name, pFunc);
19,176✔
181
  taosMemoryFreeClear(pFunc->pCode);
19,176✔
182
  taosMemoryFreeClear(pFunc->pComment);
19,176✔
183
  return 0;
19,176✔
184
}
185

186
static int32_t mndFuncActionUpdate(SSdb *pSdb, SFuncObj *pOld, SFuncObj *pNew) {
8,481✔
187
  int32_t code = 0;
8,481✔
188
  mTrace("func:%s, perform update action, old row:%p new row:%p", pOld->name, pOld, pNew);
8,481✔
189

190
  taosWLockLatch(&pOld->lock);
8,481✔
191

192
  pOld->align = pNew->align;
8,481✔
193
  pOld->bufSize = pNew->bufSize;
8,481✔
194
  pOld->codeSize = pNew->codeSize;
8,481✔
195
  pOld->commentSize = pNew->commentSize;
8,481✔
196
  pOld->createdTime = pNew->createdTime;
8,481✔
197
  pOld->funcType = pNew->funcType;
8,481✔
198
  pOld->funcVersion = pNew->funcVersion;
8,481✔
199
  pOld->outputLen = pNew->outputLen;
8,481✔
200
  pOld->outputType = pNew->outputType;
8,481✔
201

202
  if (pOld->pComment != NULL) {
8,481✔
203
    taosMemoryFree(pOld->pComment);
×
204
    pOld->pComment = NULL;
×
205
  }
206
  if (pNew->commentSize > 0 && pNew->pComment != NULL) {
8,481✔
207
    pOld->commentSize = pNew->commentSize;
×
208
    pOld->pComment = taosMemoryMalloc(pOld->commentSize);
×
209
    if (pOld->pComment == NULL) {
×
210
      code = terrno;
×
211
      taosWUnLockLatch(&pOld->lock);
×
212
      return code;
×
213
    }
214
    (void)memcpy(pOld->pComment, pNew->pComment, pOld->commentSize);
×
215
  }
216

217
  if (pOld->pCode != NULL) {
8,481✔
218
    taosMemoryFree(pOld->pCode);
8,481✔
219
    pOld->pCode = NULL;
8,481✔
220
  }
221
  if (pNew->codeSize > 0 && pNew->pCode != NULL) {
8,481✔
222
    pOld->codeSize = pNew->codeSize;
8,481✔
223
    pOld->pCode = taosMemoryMalloc(pOld->codeSize);
8,481✔
224
    if (pOld->pCode == NULL) {
8,481✔
225
      code = terrno;
×
226
      taosWUnLockLatch(&pOld->lock);
×
227
      return code;
×
228
    }
229
    (void)memcpy(pOld->pCode, pNew->pCode, pOld->codeSize);
8,481✔
230
  }
231

232
  pOld->scriptType = pNew->scriptType;
8,481✔
233
  pOld->signature = pNew->signature;
8,481✔
234

235
  taosWUnLockLatch(&pOld->lock);
8,481✔
236

237
  return 0;
8,481✔
238
}
239

240
static SFuncObj *mndAcquireFunc(SMnode *pMnode, char *funcName) {
108,652✔
241
  terrno = 0;
108,652✔
242
  SSdb     *pSdb = pMnode->pSdb;
108,652✔
243
  SFuncObj *pFunc = sdbAcquire(pSdb, SDB_FUNC, funcName);
108,652✔
244
  if (pFunc == NULL && terrno == TSDB_CODE_SDB_OBJ_NOT_THERE) {
108,652✔
245
    terrno = TSDB_CODE_MND_FUNC_NOT_EXIST;
14,043✔
246
  }
247
  return pFunc;
108,652✔
248
}
249

250
static void mndReleaseFunc(SMnode *pMnode, SFuncObj *pFunc) {
99,360✔
251
  SSdb *pSdb = pMnode->pSdb;
99,360✔
252
  sdbRelease(pSdb, pFunc);
99,360✔
253
}
99,360✔
254

255
static int32_t mndCreateFunc(SMnode *pMnode, SRpcMsg *pReq, SCreateFuncReq *pCreate) {
4,751✔
256
  int32_t code = -1;
4,751✔
257
  STrans *pTrans = NULL;
4,751✔
258

259
  if ((code = grantCheck(TSDB_GRANT_USER)) < 0) {
4,751✔
260
    return code;
×
261
  }
262

263
  SFuncObj func = {0};
4,751✔
264
  (void)memcpy(func.name, pCreate->name, TSDB_FUNC_NAME_LEN);
4,751✔
265
  func.createdTime = taosGetTimestampMs();
4,751✔
266
  func.funcType = pCreate->funcType;
4,751✔
267
  func.scriptType = pCreate->scriptType;
4,751✔
268
  func.outputType = pCreate->outputType;
4,751✔
269
  func.outputLen = pCreate->outputLen;
4,751✔
270
  func.bufSize = pCreate->bufSize;
4,751✔
271
  func.signature = pCreate->signature;
4,751✔
272
  if (NULL != pCreate->pComment) {
4,751✔
273
    func.commentSize = strlen(pCreate->pComment) + 1;
×
274
    func.pComment = taosMemoryMalloc(func.commentSize);
×
275
    if (func.pComment == NULL) {
×
276
      code = terrno;
×
277
      goto _OVER;
×
278
    }
279
  }
280
  func.codeSize = pCreate->codeLen;
4,751✔
281
  func.pCode = taosMemoryMalloc(func.codeSize);
4,751✔
282
  if (func.pCode == NULL || func.pCode == NULL) {
4,751✔
283
    code = terrno;
×
284
    goto _OVER;
×
285
  }
286

287
  if (func.commentSize > 0) {
4,751✔
288
    (void)memcpy(func.pComment, pCreate->pComment, func.commentSize);
×
289
  }
290
  (void)memcpy(func.pCode, pCreate->pCode, func.codeSize);
4,751✔
291

292
  pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "create-func");
4,751✔
293
  if (pTrans == NULL) {
4,751✔
294
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
295
    if (terrno != 0) code = terrno;
×
296
    goto _OVER;
×
297
  }
298
  mInfo("trans:%d, used to create func:%s", pTrans->id, pCreate->name);
4,751✔
299

300
  SFuncObj *oldFunc = mndAcquireFunc(pMnode, pCreate->name);
4,751✔
301
  if (pCreate->orReplace == 1 && oldFunc != NULL) {
4,751✔
302
    func.funcVersion = oldFunc->funcVersion + 1;
×
303
    func.createdTime = oldFunc->createdTime;
×
304

305
    SSdbRaw *pRedoRaw = mndFuncActionEncode(oldFunc);
×
306
    if (pRedoRaw == NULL) {
×
307
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
308
      if (terrno != 0) code = terrno;
×
309
      goto _OVER;
×
310
    }
311
    TAOS_CHECK_GOTO(mndTransAppendRedolog(pTrans, pRedoRaw), NULL, _OVER);
×
312
    TAOS_CHECK_GOTO(sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY), NULL, _OVER);
×
313

314
    SSdbRaw *pUndoRaw = mndFuncActionEncode(oldFunc);
×
315
    if (pUndoRaw == NULL) {
×
316
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
317
      if (terrno != 0) code = terrno;
×
318
      goto _OVER;
×
319
    }
320
    TAOS_CHECK_GOTO(mndTransAppendUndolog(pTrans, pUndoRaw), NULL, _OVER);
×
321
    TAOS_CHECK_GOTO(sdbSetRawStatus(pUndoRaw, SDB_STATUS_READY), NULL, _OVER);
×
322

323
    SSdbRaw *pCommitRaw = mndFuncActionEncode(&func);
×
324
    if (pCommitRaw == NULL) {
×
325
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
326
      if (terrno != 0) code = terrno;
×
327
      goto _OVER;
×
328
    }
329
    TAOS_CHECK_GOTO(mndTransAppendCommitlog(pTrans, pCommitRaw), NULL, _OVER);
×
330
    TAOS_CHECK_GOTO(sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY), NULL, _OVER);
×
331
  } else {
332
    SSdbRaw *pRedoRaw = mndFuncActionEncode(&func);
4,751✔
333
    if (pRedoRaw == NULL) {
4,751✔
334
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
335
      if (terrno != 0) code = terrno;
×
336
      goto _OVER;
×
337
    }
338
    TAOS_CHECK_GOTO(mndTransAppendRedolog(pTrans, pRedoRaw), NULL, _OVER);
4,751✔
339
    TAOS_CHECK_GOTO(sdbSetRawStatus(pRedoRaw, SDB_STATUS_CREATING), NULL, _OVER);
4,751✔
340

341
    SSdbRaw *pUndoRaw = mndFuncActionEncode(&func);
4,751✔
342
    if (pUndoRaw == NULL) {
4,751✔
343
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
344
      if (terrno != 0) code = terrno;
×
345
      goto _OVER;
×
346
    }
347
    TAOS_CHECK_GOTO(mndTransAppendUndolog(pTrans, pUndoRaw), NULL, _OVER);
4,751✔
348
    TAOS_CHECK_GOTO(sdbSetRawStatus(pUndoRaw, SDB_STATUS_DROPPED), NULL, _OVER);
4,751✔
349

350
    SSdbRaw *pCommitRaw = mndFuncActionEncode(&func);
4,751✔
351
    if (pCommitRaw == NULL) {
4,751✔
352
      code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
353
      if (terrno != 0) code = terrno;
×
354
      goto _OVER;
×
355
    }
356
    TAOS_CHECK_GOTO(mndTransAppendCommitlog(pTrans, pCommitRaw), NULL, _OVER);
4,751✔
357
    TAOS_CHECK_GOTO(sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY), NULL, _OVER);
4,751✔
358
  }
359

360
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
4,751✔
361

362
  code = 0;
4,751✔
363

364
_OVER:
4,751✔
365
  if (oldFunc != NULL) {
4,751✔
366
    mndReleaseFunc(pMnode, oldFunc);
×
367
  }
368

369
  taosMemoryFree(func.pCode);
4,751✔
370
  taosMemoryFree(func.pComment);
4,751✔
371
  mndTransDrop(pTrans);
4,751✔
372
  TAOS_RETURN(code);
4,751✔
373
}
374

375
static int32_t mndDropFunc(SMnode *pMnode, SRpcMsg *pReq, SFuncObj *pFunc) {
3,730✔
376
  int32_t code = -1;
3,730✔
377
  STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_NOTHING, pReq, "drop-func");
3,730✔
378
  if (pTrans == NULL) {
3,730✔
379
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
380
    if (terrno != 0) code = terrno;
×
381
    goto _OVER;
×
382
  }
383

384
  mInfo("trans:%d, used to drop user:%s", pTrans->id, pFunc->name);
3,730✔
385

386
  SSdbRaw *pRedoRaw = mndFuncActionEncode(pFunc);
3,730✔
387
  if (pRedoRaw == NULL) {
3,730✔
388
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
389
    if (terrno != 0) code = terrno;
×
390
    goto _OVER;
×
391
  }
392
  TAOS_CHECK_GOTO(mndTransAppendRedolog(pTrans, pRedoRaw), NULL, _OVER);
3,730✔
393
  TAOS_CHECK_GOTO(sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPING), NULL, _OVER);
3,730✔
394

395
  SSdbRaw *pUndoRaw = mndFuncActionEncode(pFunc);
3,730✔
396
  if (pUndoRaw == NULL) {
3,730✔
397
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
398
    if (terrno != 0) code = terrno;
×
399
    goto _OVER;
×
400
  }
401
  TAOS_CHECK_GOTO(mndTransAppendUndolog(pTrans, pUndoRaw), NULL, _OVER);
3,730✔
402
  TAOS_CHECK_GOTO(sdbSetRawStatus(pUndoRaw, SDB_STATUS_READY), NULL, _OVER);
3,730✔
403

404
  SSdbRaw *pCommitRaw = mndFuncActionEncode(pFunc);
3,730✔
405
  if (pCommitRaw == NULL) {
3,730✔
406
    code = TSDB_CODE_MND_RETURN_VALUE_NULL;
×
407
    if (terrno != 0) code = terrno;
×
408
    goto _OVER;
×
409
  }
410
  TAOS_CHECK_GOTO(mndTransAppendCommitlog(pTrans, pCommitRaw), NULL, _OVER);
3,730✔
411
  TAOS_CHECK_GOTO(sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED), NULL, _OVER);
3,730✔
412

413
  TAOS_CHECK_GOTO(mndTransPrepare(pMnode, pTrans), NULL, _OVER);
3,730✔
414

415
  code = 0;
3,730✔
416

417
_OVER:
3,730✔
418
  mndTransDrop(pTrans);
3,730✔
419
  return code;
3,730✔
420
}
421

422
static int32_t mndProcessCreateFuncReq(SRpcMsg *pReq) {
4,751✔
423
  SMnode        *pMnode = pReq->info.node;
4,751✔
424
  int32_t        code = -1;
4,751✔
425
  SFuncObj      *pFunc = NULL;
4,751✔
426
  SCreateFuncReq createReq = {0};
4,751✔
427

428
  TAOS_CHECK_GOTO(tDeserializeSCreateFuncReq(pReq->pCont, pReq->contLen, &createReq), NULL, _OVER);
4,751✔
429

430
#ifdef WINDOWS
431
  code = TSDB_CODE_MND_INVALID_PLATFORM;
432
  goto _OVER;
433
#endif
434
  mInfo("func:%s, start to create, size:%d", createReq.name, createReq.codeLen);
4,751✔
435
  TAOS_CHECK_GOTO(mndCheckOperPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_CREATE_FUNC), NULL, _OVER);
4,751✔
436

437
  pFunc = mndAcquireFunc(pMnode, createReq.name);
4,751✔
438
  if (pFunc != NULL) {
4,751✔
439
    if (createReq.igExists) {
×
440
      mInfo("func:%s, already exist, ignore exist is set", createReq.name);
×
441
      code = 0;
×
442
      goto _OVER;
×
443
    } else if (createReq.orReplace) {
×
444
      mInfo("func:%s, replace function is set", createReq.name);
×
445
      code = 0;
×
446
    } else {
447
      code = TSDB_CODE_MND_FUNC_ALREADY_EXIST;
×
448
      goto _OVER;
×
449
    }
450
  } else if (terrno == TSDB_CODE_MND_FUNC_ALREADY_EXIST) {
4,751✔
451
    goto _OVER;
×
452
  }
453

454
  if (createReq.name[0] == 0) {
4,751✔
455
    code = TSDB_CODE_MND_INVALID_FUNC_NAME;
×
456
    goto _OVER;
×
457
  }
458

459
  if (createReq.pCode == NULL) {
4,751✔
460
    code = TSDB_CODE_MND_INVALID_FUNC_CODE;
×
461
    goto _OVER;
×
462
  }
463

464
  if (createReq.codeLen <= 1) {
4,751✔
465
    code = TSDB_CODE_MND_INVALID_FUNC_CODE;
×
466
    goto _OVER;
×
467
  }
468

469
  if (createReq.bufSize < 0 || createReq.bufSize > TSDB_FUNC_BUF_SIZE) {
4,751✔
470
    code = TSDB_CODE_MND_INVALID_FUNC_BUFSIZE;
×
471
    goto _OVER;
×
472
  }
473

474
  code = mndCreateFunc(pMnode, pReq, &createReq);
4,751✔
475
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
4,751✔
476

477
_OVER:
4,751✔
478
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
4,751✔
479
    mError("func:%s, failed to create since %s", createReq.name, tstrerror(code));
×
480
  }
481

482
  mndReleaseFunc(pMnode, pFunc);
4,751✔
483
  tFreeSCreateFuncReq(&createReq);
4,751✔
484
  TAOS_RETURN(code);
4,751✔
485
}
486

487
static int32_t mndProcessDropFuncReq(SRpcMsg *pReq) {
3,730✔
488
  SMnode      *pMnode = pReq->info.node;
3,730✔
489
  int32_t      code = -1;
3,730✔
490
  SFuncObj    *pFunc = NULL;
3,730✔
491
  SDropFuncReq dropReq = {0};
3,730✔
492

493
  TAOS_CHECK_GOTO(tDeserializeSDropFuncReq(pReq->pCont, pReq->contLen, &dropReq), NULL, _OVER);
3,730✔
494

495
  mInfo("func:%s, start to drop", dropReq.name);
3,730✔
496
  TAOS_CHECK_GOTO(mndCheckOperPrivilege(pMnode, RPC_MSG_USER(pReq), RPC_MSG_TOKEN(pReq), MND_OPER_DROP_FUNC), NULL, _OVER);
3,730✔
497

498
  if (dropReq.name[0] == 0) {
3,730✔
499
    code = TSDB_CODE_MND_INVALID_FUNC_NAME;
×
500
    goto _OVER;
×
501
  }
502

503
  pFunc = mndAcquireFunc(pMnode, dropReq.name);
3,730✔
504
  if (pFunc == NULL) {
3,730✔
505
    if (dropReq.igNotExists) {
×
506
      mInfo("func:%s, not exist, ignore not exist is set", dropReq.name);
×
507
      code = 0;
×
508
      goto _OVER;
×
509
    } else {
510
      code = TSDB_CODE_MND_FUNC_NOT_EXIST;
×
511
      goto _OVER;
×
512
    }
513
  }
514

515
  code = mndDropFunc(pMnode, pReq, pFunc);
3,730✔
516
  if (code == 0) code = TSDB_CODE_ACTION_IN_PROGRESS;
3,730✔
517

518
_OVER:
3,730✔
519
  if (code != 0 && code != TSDB_CODE_ACTION_IN_PROGRESS) {
3,730✔
520
    mError("func:%s, failed to drop since %s", dropReq.name, tstrerror(code));
×
521
  }
522

523
  mndReleaseFunc(pMnode, pFunc);
3,730✔
524
  TAOS_RETURN(code);
3,730✔
525
}
526

527
static int32_t mndProcessRetrieveFuncReq(SRpcMsg *pReq) {
95,420✔
528
  SMnode          *pMnode = pReq->info.node;
95,420✔
529
  int32_t          code = -1;
95,420✔
530
  SRetrieveFuncReq retrieveReq = {0};
95,420✔
531
  SRetrieveFuncRsp retrieveRsp = {0};
95,420✔
532

533
  if (tDeserializeSRetrieveFuncReq(pReq->pCont, pReq->contLen, &retrieveReq) != 0) {
95,420✔
534
    code = TSDB_CODE_INVALID_MSG;
×
535
    goto RETRIEVE_FUNC_OVER;
×
536
  }
537

538
  if (retrieveReq.numOfFuncs <= 0 || retrieveReq.numOfFuncs > TSDB_FUNC_MAX_RETRIEVE) {
95,420✔
539
    code = TSDB_CODE_MND_INVALID_FUNC_RETRIEVE;
×
540
    goto RETRIEVE_FUNC_OVER;
×
541
  }
542

543
  retrieveRsp.numOfFuncs = retrieveReq.numOfFuncs;
95,420✔
544
  retrieveRsp.pFuncInfos = taosArrayInit(retrieveReq.numOfFuncs, sizeof(SFuncInfo));
95,420✔
545
  if (retrieveRsp.pFuncInfos == NULL) {
95,420✔
546
    code = terrno;
×
547
    goto RETRIEVE_FUNC_OVER;
×
548
  }
549

550
  retrieveRsp.pFuncExtraInfos = taosArrayInit(retrieveReq.numOfFuncs, sizeof(SFuncExtraInfo));
95,420✔
551
  if (retrieveRsp.pFuncExtraInfos == NULL) {
95,420✔
552
    code = terrno;
×
553
    goto RETRIEVE_FUNC_OVER;
×
554
  }
555

556
  for (int32_t i = 0; i < retrieveReq.numOfFuncs; ++i) {
186,299✔
557
    char *funcName = taosArrayGet(retrieveReq.pFuncNames, i);
95,420✔
558

559
    SFuncObj *pFunc = mndAcquireFunc(pMnode, funcName);
95,420✔
560
    if (pFunc == NULL) {
95,420✔
561
      if (terrno != 0) code = terrno;
4,541✔
562
      goto RETRIEVE_FUNC_OVER;
4,541✔
563
    }
564

565
    SFuncInfo funcInfo = {0};
90,879✔
566
    (void)memcpy(funcInfo.name, pFunc->name, TSDB_FUNC_NAME_LEN);
90,879✔
567
    funcInfo.funcType = pFunc->funcType;
90,879✔
568
    funcInfo.scriptType = pFunc->scriptType;
90,879✔
569
    funcInfo.outputType = pFunc->outputType;
90,879✔
570
    funcInfo.outputLen = pFunc->outputLen;
90,879✔
571
    funcInfo.bufSize = pFunc->bufSize;
90,879✔
572
    funcInfo.signature = pFunc->signature;
90,879✔
573
    if (retrieveReq.ignoreCodeComment) {
90,879✔
574
      funcInfo.commentSize = 0;
67,393✔
575
      funcInfo.codeSize = 0;
67,393✔
576
    } else {
577
      funcInfo.commentSize = pFunc->commentSize;
23,486✔
578
      funcInfo.codeSize = pFunc->codeSize;
23,486✔
579
      funcInfo.pCode = taosMemoryCalloc(1, funcInfo.codeSize);
23,486✔
580
      if (funcInfo.pCode == NULL) {
23,486✔
581
        terrno = terrno;
×
582
        goto RETRIEVE_FUNC_OVER;
×
583
      }
584
      (void)memcpy(funcInfo.pCode, pFunc->pCode, pFunc->codeSize);
23,486✔
585
      if (funcInfo.commentSize > 0) {
23,486✔
586
        funcInfo.pComment = taosMemoryCalloc(1, funcInfo.commentSize);
×
587
        if (funcInfo.pComment == NULL) {
×
588
          terrno = terrno;
×
589
          goto RETRIEVE_FUNC_OVER;
×
590
        }
591
        (void)memcpy(funcInfo.pComment, pFunc->pComment, pFunc->commentSize);
×
592
      }
593
    }
594
    if (taosArrayPush(retrieveRsp.pFuncInfos, &funcInfo) == NULL) {
181,758✔
595
      terrno = terrno;
×
596
      goto RETRIEVE_FUNC_OVER;
×
597
    }
598
    SFuncExtraInfo extraInfo = {0};
90,879✔
599
    extraInfo.funcVersion = pFunc->funcVersion;
90,879✔
600
    extraInfo.funcCreatedTime = pFunc->createdTime;
90,879✔
601
    if (taosArrayPush(retrieveRsp.pFuncExtraInfos, &extraInfo) == NULL) {
181,758✔
602
      terrno = terrno;
×
603
      goto RETRIEVE_FUNC_OVER;
×
604
    }
605

606
    mndReleaseFunc(pMnode, pFunc);
90,879✔
607
  }
608

609
  int32_t contLen = tSerializeSRetrieveFuncRsp(NULL, 0, &retrieveRsp);
90,879✔
610
  void   *pRsp = rpcMallocCont(contLen);
90,879✔
611
  if (pRsp == NULL) {
90,879✔
612
    code = terrno;
×
613
    goto RETRIEVE_FUNC_OVER;
×
614
  }
615

616
  if ((contLen = tSerializeSRetrieveFuncRsp(pRsp, contLen, &retrieveRsp)) <= 0) {
90,879✔
617
    code = contLen;
×
618
    goto RETRIEVE_FUNC_OVER;
×
619
  }
620

621
  pReq->info.rsp = pRsp;
90,879✔
622
  pReq->info.rspLen = contLen;
90,879✔
623

624
  code = 0;
90,879✔
625

626
RETRIEVE_FUNC_OVER:
95,420✔
627
  tFreeSRetrieveFuncReq(&retrieveReq);
95,420✔
628
  tFreeSRetrieveFuncRsp(&retrieveRsp);
95,420✔
629

630
  TAOS_RETURN(code);
95,420✔
631
}
632

633
static void *mnodeGenTypeStr(char *buf, int32_t buflen, uint8_t type, int32_t len) {
4,751✔
634
  char *msg = "unknown";
4,751✔
635
  if (type >= sizeof(tDataTypes) / sizeof(tDataTypes[0])) {
4,751✔
636
    return msg;
×
637
  }
638

639
  if (type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_VARBINARY || type == TSDB_DATA_TYPE_BINARY ||
4,751✔
640
      type == TSDB_DATA_TYPE_GEOMETRY) {
641
    int32_t bytes = len > 0 ? (int32_t)(len - VARSTR_HEADER_SIZE) : len;
×
642

643
    (void)snprintf(buf, buflen - 1, "%s(%d)", tDataTypes[type].name, type == TSDB_DATA_TYPE_NCHAR ? bytes / 4 : bytes);
×
644
    buf[buflen - 1] = 0;
×
645

646
    return buf;
×
647
  }
648

649
  return tDataTypes[type].name;
4,751✔
650
}
651

652
static int32_t mndRetrieveFuncs(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows) {
7,488✔
653
  SMnode   *pMnode = pReq->info.node;
7,488✔
654
  SSdb     *pSdb = pMnode->pSdb;
7,488✔
655
  int32_t   numOfRows = 0;
7,488✔
656
  SFuncObj *pFunc = NULL;
7,488✔
657
  int32_t   cols = 0;
7,488✔
658
  int32_t   code = 0, lino = 0;
7,488✔
659
  char      buf[TSDB_TYPE_STR_MAX_LEN];
7,488✔
660

661
  while (numOfRows < rows) {
12,239✔
662
    pShow->pIter = sdbFetch(pSdb, SDB_FUNC, pShow->pIter, (void **)&pFunc);
12,239✔
663
    if (pShow->pIter == NULL) break;
12,239✔
664

665
    cols = 0;
4,751✔
666

667
    char b1[tListLen(pFunc->name) + VARSTR_HEADER_SIZE] = {0};
4,751✔
668
    STR_WITH_MAXSIZE_TO_VARSTR(b1, pFunc->name, pShow->pMeta->pSchemas[cols].bytes);
4,751✔
669

670
    SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
4,751✔
671
    COL_DATA_SET_VAL_GOTO((const char *)b1, false, pFunc, pShow->pIter, _OVER);
4,751✔
672

673
    if (pFunc->pComment) {
4,751✔
674
      char *b2 = taosMemoryCalloc(1, pShow->pMeta->pSchemas[cols].bytes);
×
675
      STR_WITH_MAXSIZE_TO_VARSTR(b2, pFunc->pComment, pShow->pMeta->pSchemas[cols].bytes);
×
676

677
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
×
678
      code = colDataSetVal(pColInfo, numOfRows, (const char *)b2, false);
×
679
      if (code != 0) {
×
680
        sdbCancelFetch(pSdb, pShow->pIter);
×
681
        sdbRelease(pSdb, pFunc);
×
682
        taosMemoryFree(b2);
×
UNCOV
683
        goto _OVER;
×
684
      }
UNCOV
685
      taosMemoryFree(b2);
×
686
    } else {
687
      pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
4,751✔
688
      COL_DATA_SET_VAL_GOTO(NULL, true, pFunc, pShow->pIter, _OVER);
4,751✔
689
      if (code != 0) {
4,751✔
690
        sdbCancelFetch(pSdb, pShow->pIter);
×
UNCOV
691
        sdbRelease(pSdb, pFunc);
×
UNCOV
692
        goto _OVER;
×
693
      }
694
    }
695

696
    int32_t isAgg = (pFunc->funcType == TSDB_FUNC_TYPE_AGGREGATE) ? 1 : 0;
4,751✔
697

698
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
4,751✔
699
    COL_DATA_SET_VAL_GOTO((const char *)&isAgg, false, pFunc, pShow->pIter, _OVER);
4,751✔
700
    char b3[TSDB_TYPE_STR_MAX_LEN + 1] = {0};
4,751✔
701
    STR_WITH_MAXSIZE_TO_VARSTR(b3, mnodeGenTypeStr(buf, TSDB_TYPE_STR_MAX_LEN, pFunc->outputType, pFunc->outputLen),
4,751✔
702
                               pShow->pMeta->pSchemas[cols].bytes);
703

704
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
4,751✔
705
    COL_DATA_SET_VAL_GOTO((const char *)b3, false, pFunc, pShow->pIter, _OVER);
4,751✔
706

707
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
4,751✔
708
    COL_DATA_SET_VAL_GOTO((const char *)&pFunc->createdTime, false, pFunc, pShow->pIter, _OVER);
4,751✔
709

710
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
4,751✔
711
    COL_DATA_SET_VAL_GOTO((const char *)&pFunc->codeSize, false, pFunc, pShow->pIter, _OVER);
4,751✔
712

713
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
4,751✔
714
    COL_DATA_SET_VAL_GOTO( (const char *)&pFunc->bufSize, false, pFunc, pShow->pIter, _OVER);
4,751✔
715

716
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
4,751✔
717
    char *language = "";
4,751✔
718
    if (pFunc->scriptType == TSDB_FUNC_SCRIPT_BIN_LIB) {
4,751✔
719
      language = "C";
4,751✔
UNCOV
720
    } else if (pFunc->scriptType == TSDB_FUNC_SCRIPT_PYTHON) {
×
721
      language = "Python";
×
722
    }
723
    char varLang[TSDB_TYPE_STR_MAX_LEN + 1] = {0};
4,751✔
724
    varDataSetLen(varLang, strlen(language));
4,751✔
725
    tstrncpy(varDataVal(varLang), language, sizeof(varLang) - VARSTR_HEADER_SIZE);
4,751✔
726
    COL_DATA_SET_VAL_GOTO((const char *)varLang, false, pFunc, pShow->pIter, _OVER);
4,751✔
727

728
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
4,751✔
729
    int32_t varCodeLen = (pFunc->codeSize + VARSTR_HEADER_SIZE) > TSDB_MAX_BINARY_LEN
4,751✔
730
                             ? TSDB_MAX_BINARY_LEN
731
                             : pFunc->codeSize + VARSTR_HEADER_SIZE;
4,751✔
732
    char   *b4 = taosMemoryMalloc(varCodeLen);
4,751✔
733
    if (b4 == NULL) {
4,751✔
UNCOV
734
      code = terrno;
×
735
      sdbCancelFetch(pSdb, pShow->pIter);
×
736
      sdbRelease(pSdb, pFunc);
×
737
      goto _OVER;
×
738
    }
739
    (void)memcpy(varDataVal(b4), pFunc->pCode, varCodeLen - VARSTR_HEADER_SIZE);
4,751✔
740
    varDataSetLen(b4, varCodeLen - VARSTR_HEADER_SIZE);
4,751✔
741
    code = colDataSetVal(pColInfo, numOfRows, (const char *)b4, false);
4,751✔
742
    if (code < 0) {
4,751✔
743
      sdbCancelFetch(pSdb, pShow->pIter);
×
744
      sdbRelease(pSdb, pFunc);
×
745
      taosMemoryFree(b4);
×
UNCOV
746
      goto _OVER;
×
747
    }
748
    taosMemoryFree(b4);
4,751✔
749

750
    pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
4,751✔
751
    COL_DATA_SET_VAL_GOTO((const char *)&pFunc->funcVersion, false, pFunc, pShow->pIter, _OVER);
4,751✔
752

753
    numOfRows++;
4,751✔
754
    sdbRelease(pSdb, pFunc);
4,751✔
755
  }
756
_OVER:
7,488✔
757
  pShow->numOfRows += numOfRows;
7,488✔
758
  return numOfRows;
7,488✔
759
}
760

761
static void mndCancelGetNextFunc(SMnode *pMnode, void *pIter) {
×
762
  SSdb *pSdb = pMnode->pSdb;
×
763
  sdbCancelFetchByType(pSdb, pIter, SDB_FUNC);
×
764
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc