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

taosdata / TDengine / #3620

21 Feb 2025 09:00AM UTC coverage: 63.573% (+0.2%) from 63.423%
#3620

push

travis-ci

web-flow
ci: taosBenchmark add coverage cases branch 3.0 (#29788)

* fix: add unit test for taos-tools

* fix: only .cpp include

* fix: remove no use function

* fix: restore toolsSys.c

* fix: add toolsSys case

* fix: rebuild error fixed

* fix: fix build error

* fix: support get vgroups with core and memory limit

* fix: build error for strcasecmp

* fix: add insertBasic.py case

* fix: add command line set vgroups=3

* fix: change with ns database

* toolscJson read with int replace float and add insertPrecison.py

* fix: add insertBindVGroup.json case

* fix: remove public fun removeQuotation

* fix: vgroups change method

* fix: memory leak for runInsertLimitThread slot

* insertPrecision.py word write wrong

* fix: check isFloat number

* fix: vgroups change logic error

* fix: insertBasic.py real and expect error

* fix: adjust default vgroups

* fix: adjust default vgroups modify comment

148962 of 300203 branches covered (49.62%)

Branch coverage included in aggregate %.

15 of 16 new or added lines in 1 file covered. (93.75%)

2018 existing lines in 133 files now uncovered.

233201 of 300933 relevant lines covered (77.49%)

18174406.98 hits per line

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

66.37
/source/dnode/vnode/src/meta/metaTable.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
#include "meta.h"
17

18
extern SDmNotifyHandle dmNotifyHdl;
19

20
int32_t metaAddTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, STableMetaRsp *pRsp);
21
int32_t metaDropTableColumn(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, STableMetaRsp *pRsp);
22
int32_t metaAlterTableColumnName(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, STableMetaRsp *pRsp);
23
int32_t metaAlterTableColumnBytes(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, STableMetaRsp *pRsp);
24
int32_t metaUpdateTableTagValue(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq);
25
int32_t metaUpdateTableMultiTagValue(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq);
26
int32_t metaUpdateTableOptions2(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq);
27
int32_t metaUpdateTableColCompress2(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq);
28

29
int32_t metaSaveJsonVarToIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const SSchema *pSchema);
30

31
int32_t    metaDelJsonVarFromIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const SSchema *pSchema);
32
static int metaUpdateChangeTime(SMeta *pMeta, tb_uid_t uid, int64_t changeTimeMs);
33
static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type, tb_uid_t *pSuid, int8_t *pSysTbl);
34
void       metaDestroyTagIdxKey(STagIdxKey *pTagIdxKey);
35
// opt ins_tables query
36
static int metaDeleteBtimeIdx(SMeta *pMeta, const SMetaEntry *pME);
37
static int metaDeleteNcolIdx(SMeta *pMeta, const SMetaEntry *pME);
38

39
int32_t updataTableColCmpr(SColCmprWrapper *pWp, SSchema *pSchema, int8_t add, uint32_t compress) {
141✔
40
  int32_t nCols = pWp->nCols;
141✔
41
  int32_t ver = pWp->version;
141✔
42
  if (add) {
141✔
43
    SColCmpr *p = taosMemoryRealloc(pWp->pColCmpr, sizeof(SColCmpr) * (nCols + 1));
82!
44
    if (p == NULL) {
82!
45
      return terrno;
×
46
    }
47
    pWp->pColCmpr = p;
82✔
48

49
    SColCmpr *pCol = p + nCols;
82✔
50
    pCol->id = pSchema->colId;
82✔
51
    pCol->alg = compress;
82✔
52
    pWp->nCols = nCols + 1;
82✔
53
    pWp->version = ver;
82✔
54
  } else {
55
    for (int32_t i = 0; i < nCols; i++) {
184!
56
      SColCmpr *pOCmpr = &pWp->pColCmpr[i];
184✔
57
      if (pOCmpr->id == pSchema->colId) {
184✔
58
        int32_t left = (nCols - i - 1) * sizeof(SColCmpr);
59✔
59
        if (left) {
59✔
60
          memmove(pWp->pColCmpr + i, pWp->pColCmpr + i + 1, left);
42✔
61
        }
62
        nCols--;
59✔
63
        break;
59✔
64
      }
65
    }
66
    pWp->nCols = nCols;
59✔
67
    pWp->version = ver;
59✔
68
  }
69
  return 0;
141✔
70
}
71

72
int metaUpdateMetaRsp(tb_uid_t uid, char *tbName, SSchemaWrapper *pSchema, STableMetaRsp *pMetaRsp) {
14,650✔
73
  pMetaRsp->pSchemas = taosMemoryMalloc(pSchema->nCols * sizeof(SSchema));
14,650!
74
  if (NULL == pMetaRsp->pSchemas) {
14,650!
75
    return terrno;
×
76
  }
77

78
  pMetaRsp->pSchemaExt = taosMemoryMalloc(pSchema->nCols * sizeof(SSchemaExt));
14,650!
79
  if (pMetaRsp->pSchemaExt == NULL) {
14,650!
80
    taosMemoryFree(pMetaRsp->pSchemas);
×
81
    return terrno;
×
82
  }
83

84
  tstrncpy(pMetaRsp->tbName, tbName, TSDB_TABLE_NAME_LEN);
14,650✔
85
  pMetaRsp->numOfColumns = pSchema->nCols;
14,650✔
86
  pMetaRsp->tableType = TSDB_NORMAL_TABLE;
14,650✔
87
  pMetaRsp->sversion = pSchema->version;
14,650✔
88
  pMetaRsp->tuid = uid;
14,650✔
89

90
  memcpy(pMetaRsp->pSchemas, pSchema->pSchema, pSchema->nCols * sizeof(SSchema));
14,650✔
91

92
  return 0;
14,650✔
93
}
94

95
int metaSaveJsonVarToIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const SSchema *pSchema) {
195✔
96
  int32_t code = 0;
195✔
97

98
#ifdef USE_INVERTED_INDEX
99
  if (pMeta->pTagIvtIdx == NULL || pCtbEntry == NULL) {
195!
100
    return TSDB_CODE_INVALID_PARA;
×
101
  }
102
  void       *data = pCtbEntry->ctbEntry.pTags;
195✔
103
  const char *tagName = pSchema->name;
195✔
104

105
  tb_uid_t    suid = pCtbEntry->ctbEntry.suid;
195✔
106
  tb_uid_t    tuid = pCtbEntry->uid;
195✔
107
  const void *pTagData = pCtbEntry->ctbEntry.pTags;
195✔
108
  int32_t     nTagData = 0;
195✔
109

110
  SArray *pTagVals = NULL;
195✔
111
  code = tTagToValArray((const STag *)data, &pTagVals);
195✔
112
  if (code) {
195!
113
    return code;
×
114
  }
115

116
  SIndexMultiTerm *terms = indexMultiTermCreate();
195✔
117
  if (terms == NULL) {
195!
118
    return terrno;
×
119
  }
120

121
  int16_t nCols = taosArrayGetSize(pTagVals);
195✔
122
  for (int i = 0; i < nCols; i++) {
432✔
123
    STagVal *pTagVal = (STagVal *)taosArrayGet(pTagVals, i);
237✔
124
    char     type = pTagVal->type;
237✔
125

126
    char   *key = pTagVal->pKey;
237✔
127
    int32_t nKey = strlen(key);
237✔
128

129
    SIndexTerm *term = NULL;
237✔
130
    if (type == TSDB_DATA_TYPE_NULL) {
237✔
131
      term = indexTermCreate(suid, ADD_VALUE, TSDB_DATA_TYPE_VARCHAR, key, nKey, NULL, 0);
24✔
132
    } else if (type == TSDB_DATA_TYPE_NCHAR) {
213✔
133
      if (pTagVal->nData > 0) {
110✔
134
        char *val = taosMemoryCalloc(1, pTagVal->nData + VARSTR_HEADER_SIZE);
94!
135
        if (val == NULL) {
94!
136
          TAOS_CHECK_GOTO(terrno, NULL, _exception);
×
137
        }
138
        int32_t len = taosUcs4ToMbs((TdUcs4 *)pTagVal->pData, pTagVal->nData, val + VARSTR_HEADER_SIZE, NULL);
94✔
139
        if (len < 0) {
94!
140
          TAOS_CHECK_GOTO(len, NULL, _exception);
×
141
        }
142
        memcpy(val, (uint16_t *)&len, VARSTR_HEADER_SIZE);
94✔
143
        type = TSDB_DATA_TYPE_VARCHAR;
94✔
144
        term = indexTermCreate(suid, ADD_VALUE, type, key, nKey, val, len);
94✔
145
        taosMemoryFree(val);
94!
146
      } else if (pTagVal->nData == 0) {
16!
147
        term = indexTermCreate(suid, ADD_VALUE, TSDB_DATA_TYPE_VARCHAR, key, nKey, pTagVal->pData, 0);
16✔
148
      }
149
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
103✔
150
      double val = *(double *)(&pTagVal->i64);
79✔
151
      int    len = sizeof(val);
79✔
152
      term = indexTermCreate(suid, ADD_VALUE, type, key, nKey, (const char *)&val, len);
79✔
153
    } else if (type == TSDB_DATA_TYPE_BOOL) {
24!
154
      int val = *(int *)(&pTagVal->i64);
24✔
155
      int len = sizeof(val);
24✔
156
      term = indexTermCreate(suid, ADD_VALUE, TSDB_DATA_TYPE_BOOL, key, nKey, (const char *)&val, len);
24✔
157
    }
158

159
    if (term != NULL) {
237!
160
      int32_t ret = indexMultiTermAdd(terms, term);
237✔
161
      if (ret < 0) {
237!
162
        metaError("vgId:%d, failed to add term to multi term, uid: %" PRId64 ", key: %s, type: %d, ret: %d",
×
163
                  TD_VID(pMeta->pVnode), tuid, key, type, ret);
164
      }
165
    } else {
166
      code = terrno;
×
167
      goto _exception;
×
168
    }
169
  }
170
  code = indexJsonPut(pMeta->pTagIvtIdx, terms, tuid);
195✔
171
  indexMultiTermDestroy(terms);
195✔
172

173
  taosArrayDestroy(pTagVals);
195✔
174
#endif
175
  return code;
195✔
176
_exception:
×
177
  indexMultiTermDestroy(terms);
×
178
  taosArrayDestroy(pTagVals);
×
179
  return code;
×
180
}
181
int metaDelJsonVarFromIdx(SMeta *pMeta, const SMetaEntry *pCtbEntry, const SSchema *pSchema) {
16✔
182
#ifdef USE_INVERTED_INDEX
183
  if (pMeta->pTagIvtIdx == NULL || pCtbEntry == NULL) {
16!
184
    return TSDB_CODE_INVALID_PARA;
×
185
  }
186
  void       *data = pCtbEntry->ctbEntry.pTags;
16✔
187
  const char *tagName = pSchema->name;
16✔
188

189
  tb_uid_t    suid = pCtbEntry->ctbEntry.suid;
16✔
190
  tb_uid_t    tuid = pCtbEntry->uid;
16✔
191
  const void *pTagData = pCtbEntry->ctbEntry.pTags;
16✔
192
  int32_t     nTagData = 0;
16✔
193

194
  SArray *pTagVals = NULL;
16✔
195
  int32_t code = tTagToValArray((const STag *)data, &pTagVals);
16✔
196
  if (code) {
16!
197
    return code;
×
198
  }
199

200
  SIndexMultiTerm *terms = indexMultiTermCreate();
16✔
201
  if (terms == NULL) {
16!
202
    return terrno;
×
203
  }
204

205
  int16_t nCols = taosArrayGetSize(pTagVals);
16✔
206
  for (int i = 0; i < nCols; i++) {
48✔
207
    STagVal *pTagVal = (STagVal *)taosArrayGet(pTagVals, i);
32✔
208
    char     type = pTagVal->type;
32✔
209

210
    char   *key = pTagVal->pKey;
32✔
211
    int32_t nKey = strlen(key);
32✔
212

213
    SIndexTerm *term = NULL;
32✔
214
    if (type == TSDB_DATA_TYPE_NULL) {
32!
215
      term = indexTermCreate(suid, DEL_VALUE, TSDB_DATA_TYPE_VARCHAR, key, nKey, NULL, 0);
×
216
    } else if (type == TSDB_DATA_TYPE_NCHAR) {
32✔
217
      if (pTagVal->nData > 0) {
12!
218
        char *val = taosMemoryCalloc(1, pTagVal->nData + VARSTR_HEADER_SIZE);
12!
219
        if (val == NULL) {
12!
220
          TAOS_CHECK_GOTO(terrno, NULL, _exception);
×
221
        }
222
        int32_t len = taosUcs4ToMbs((TdUcs4 *)pTagVal->pData, pTagVal->nData, val + VARSTR_HEADER_SIZE, NULL);
12✔
223
        if (len < 0) {
12!
224
          TAOS_CHECK_GOTO(len, NULL, _exception);
×
225
        }
226
        memcpy(val, (uint16_t *)&len, VARSTR_HEADER_SIZE);
12✔
227
        type = TSDB_DATA_TYPE_VARCHAR;
12✔
228
        term = indexTermCreate(suid, DEL_VALUE, type, key, nKey, val, len);
12✔
229
        taosMemoryFree(val);
12!
230
      } else if (pTagVal->nData == 0) {
×
231
        term = indexTermCreate(suid, DEL_VALUE, TSDB_DATA_TYPE_VARCHAR, key, nKey, pTagVal->pData, 0);
×
232
      }
233
    } else if (type == TSDB_DATA_TYPE_DOUBLE) {
20✔
234
      double val = *(double *)(&pTagVal->i64);
12✔
235
      int    len = sizeof(val);
12✔
236
      term = indexTermCreate(suid, DEL_VALUE, type, key, nKey, (const char *)&val, len);
12✔
237
    } else if (type == TSDB_DATA_TYPE_BOOL) {
8!
238
      int val = *(int *)(&pTagVal->i64);
8✔
239
      int len = sizeof(val);
8✔
240
      term = indexTermCreate(suid, DEL_VALUE, TSDB_DATA_TYPE_BOOL, key, nKey, (const char *)&val, len);
8✔
241
    }
242
    if (term != NULL) {
32!
243
      int32_t ret = indexMultiTermAdd(terms, term);
32✔
244
      if (ret < 0) {
32!
245
        metaError("vgId:%d, failed to add term to multi term, uid: %" PRId64 ", key: %s, type: %d, ret: %d",
×
246
                  TD_VID(pMeta->pVnode), tuid, key, type, ret);
247
      }
248
    } else {
249
      code = terrno;
×
250
      goto _exception;
×
251
    }
252
  }
253
  code = indexJsonPut(pMeta->pTagIvtIdx, terms, tuid);
16✔
254
  indexMultiTermDestroy(terms);
16✔
255
  taosArrayDestroy(pTagVals);
16✔
256
#endif
257
  return code;
16✔
258
_exception:
×
259
  indexMultiTermDestroy(terms);
×
260
  taosArrayDestroy(pTagVals);
×
261
  return code;
×
262
}
263

264
static int32_t metaDropTables(SMeta *pMeta, SArray *tbUids) {
29✔
265
  int32_t code = 0;
29✔
266
  if (taosArrayGetSize(tbUids) == 0) return TSDB_CODE_SUCCESS;
29!
267

268
  int64_t    nCtbDropped = 0;
29✔
269
  SSHashObj *suidHash = tSimpleHashInit(16, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT));
29✔
270
  if (suidHash == NULL) {
29!
271
    return terrno;
×
272
  }
273

274
  metaWLock(pMeta);
29✔
275
  for (int i = 0; i < taosArrayGetSize(tbUids); ++i) {
1,514✔
276
    tb_uid_t uid = *(tb_uid_t *)taosArrayGet(tbUids, i);
1,485✔
277
    tb_uid_t suid = 0;
1,485✔
278
    int8_t   sysTbl = 0;
1,485✔
279
    int      type;
280
    code = metaDropTableByUid(pMeta, uid, &type, &suid, &sysTbl);
1,485✔
281
    if (code) return code;
1,485!
282
    if (!sysTbl && type == TSDB_CHILD_TABLE && suid != 0 && suidHash) {
1,485!
283
      int64_t *pVal = tSimpleHashGet(suidHash, &suid, sizeof(tb_uid_t));
1,484✔
284
      if (pVal) {
1,484✔
285
        nCtbDropped = *pVal + 1;
1,456✔
286
      } else {
287
        nCtbDropped = 1;
28✔
288
      }
289
      code = tSimpleHashPut(suidHash, &suid, sizeof(tb_uid_t), &nCtbDropped, sizeof(int64_t));
1,484✔
290
      if (code) return code;
1,484!
291
    }
292
    /*
293
    if (!TSDB_CACHE_NO(pMeta->pVnode->config)) {
294
      tsdbCacheDropTable(pMeta->pVnode->pTsdb, uid, suid, NULL);
295
    }
296
    */
297
    metaDebug("batch drop table:%" PRId64, uid);
1,485✔
298
  }
299
  metaULock(pMeta);
29✔
300

301
  // update timeseries
302
  void   *pCtbDropped = NULL;
29✔
303
  int32_t iter = 0;
29✔
304
  while ((pCtbDropped = tSimpleHashIterate(suidHash, pCtbDropped, &iter))) {
57✔
305
    tb_uid_t    *pSuid = tSimpleHashGetKey(pCtbDropped, NULL);
28✔
306
    int32_t      nCols = 0;
28✔
307
    SVnodeStats *pStats = &pMeta->pVnode->config.vndStats;
28✔
308
    if (metaGetStbStats(pMeta->pVnode, *pSuid, NULL, &nCols) == 0) {
28!
309
      pStats->numOfTimeSeries -= *(int64_t *)pCtbDropped * (nCols - 1);
28✔
310
    }
311
  }
312
  tSimpleHashCleanup(suidHash);
29✔
313

314
  pMeta->changed = true;
29✔
315
  return 0;
29✔
316
}
317

318
static int32_t metaFilterTableByHash(SMeta *pMeta, SArray *uidList) {
32✔
319
  int32_t code = 0;
32✔
320
  // 1, tranverse table's
321
  // 2, validate table name using vnodeValidateTableHash
322
  // 3, push invalidated table's uid into uidList
323

324
  TBC *pCur;
325
  code = tdbTbcOpen(pMeta->pTbDb, &pCur, NULL);
32✔
326
  if (code < 0) {
32!
UNCOV
327
    return code;
×
328
  }
329

330
  code = tdbTbcMoveToFirst(pCur);
32✔
331
  if (code) {
32!
UNCOV
332
    tdbTbcClose(pCur);
×
UNCOV
333
    return code;
×
334
  }
335

336
  void *pData = NULL, *pKey = NULL;
32✔
337
  int   nData = 0, nKey = 0;
32✔
338

339
  while (1) {
3,000✔
340
    int32_t ret = tdbTbcNext(pCur, &pKey, &nKey, &pData, &nData);
3,032✔
341
    if (ret < 0) {
3,032✔
342
      break;
32✔
343
    }
344

345
    SMetaEntry me = {0};
3,000✔
346
    SDecoder   dc = {0};
3,000✔
347
    tDecoderInit(&dc, pData, nData);
3,000✔
348
    code = metaDecodeEntry(&dc, &me);
3,000✔
349
    if (code < 0) {
3,000!
UNCOV
350
      tDecoderClear(&dc);
×
UNCOV
351
      return code;
×
352
    }
353

354
    if (me.type != TSDB_SUPER_TABLE) {
3,000✔
355
      char tbFName[TSDB_TABLE_FNAME_LEN + 1];
356
      snprintf(tbFName, sizeof(tbFName), "%s.%s", pMeta->pVnode->config.dbname, me.name);
2,970✔
357
      tbFName[TSDB_TABLE_FNAME_LEN] = '\0';
2,970✔
358
      int32_t ret = vnodeValidateTableHash(pMeta->pVnode, tbFName);
2,970✔
359
      if (ret < 0 && terrno == TSDB_CODE_VND_HASH_MISMATCH) {
2,970!
360
        if (taosArrayPush(uidList, &me.uid) == NULL) {
1,485!
UNCOV
361
          code = terrno;
×
UNCOV
362
          break;
×
363
        }
364
      }
365
    }
366
    tDecoderClear(&dc);
3,000✔
367
  }
368
  tdbFree(pData);
32✔
369
  tdbFree(pKey);
32✔
370
  tdbTbcClose(pCur);
32✔
371

372
  return 0;
32✔
373
}
374

375
int32_t metaTrimTables(SMeta *pMeta, int64_t version) {
32✔
376
  int32_t code = 0;
32✔
377

378
  SArray *tbUids = taosArrayInit(8, sizeof(int64_t));
32✔
379
  if (tbUids == NULL) {
32!
UNCOV
380
    return terrno;
×
381
  }
382

383
  code = metaFilterTableByHash(pMeta, tbUids);
32✔
384
  if (code != 0) {
32!
UNCOV
385
    goto end;
×
386
  }
387
  if (TARRAY_SIZE(tbUids) == 0) {
32✔
388
    goto end;
3✔
389
  }
390

391
  metaInfo("vgId:%d, trim %ld tables", TD_VID(pMeta->pVnode), taosArrayGetSize(tbUids));
29!
392
  code = metaDropTables(pMeta, tbUids);
29✔
393
  if (code) goto end;
29!
394

395
end:
29✔
396
  taosArrayDestroy(tbUids);
32✔
397

398
  return code;
32✔
399
}
400

401
int metaTtlFindExpired(SMeta *pMeta, int64_t timePointMs, SArray *tbUids, int32_t ttlDropMaxCount) {
100,275✔
402
  metaRLock(pMeta);
100,275✔
403

404
  int ret = ttlMgrFindExpired(pMeta->pTtlMgr, timePointMs, tbUids, ttlDropMaxCount);
100,374✔
405

406
  metaULock(pMeta);
99,996✔
407

408
  if (ret != 0) {
100,314!
UNCOV
409
    metaError("ttl failed to find expired table, ret:%d", ret);
×
410
  }
411

412
  return ret;
100,142✔
413
}
414

415
static int metaBuildBtimeIdxKey(SBtimeIdxKey *btimeKey, const SMetaEntry *pME) {
1,485✔
416
  int64_t btime;
417
  if (pME->type == TSDB_CHILD_TABLE) {
1,485✔
418
    btime = pME->ctbEntry.btime;
1,484✔
419
  } else if (pME->type == TSDB_NORMAL_TABLE) {
1!
420
    btime = pME->ntbEntry.btime;
1✔
421
  } else {
UNCOV
422
    return TSDB_CODE_FAILED;
×
423
  }
424

425
  btimeKey->btime = btime;
1,485✔
426
  btimeKey->uid = pME->uid;
1,485✔
427
  return 0;
1,485✔
428
}
429

430
static int metaBuildNColIdxKey(SNcolIdxKey *ncolKey, const SMetaEntry *pME) {
1✔
431
  if (pME->type == TSDB_NORMAL_TABLE) {
1!
432
    ncolKey->ncol = pME->ntbEntry.schemaRow.nCols;
1✔
433
    ncolKey->uid = pME->uid;
1✔
434
  } else {
UNCOV
435
    return TSDB_CODE_FAILED;
×
436
  }
437
  return 0;
1✔
438
}
439

440
static void metaDeleteTtl(SMeta *pMeta, const SMetaEntry *pME) {
1,485✔
441
  if (pME->type != TSDB_CHILD_TABLE && pME->type != TSDB_NORMAL_TABLE) return;
1,485!
442

443
  STtlDelTtlCtx ctx = {.uid = pME->uid, .pTxn = pMeta->txn};
1,485✔
444
  if (pME->type == TSDB_CHILD_TABLE) {
1,485✔
445
    ctx.ttlDays = pME->ctbEntry.ttlDays;
1,484✔
446
  } else {
447
    ctx.ttlDays = pME->ntbEntry.ttlDays;
1✔
448
  }
449

450
  int32_t ret = ttlMgrDeleteTtl(pMeta->pTtlMgr, &ctx);
1,485✔
451
  if (ret < 0) {
1,485!
UNCOV
452
    metaError("vgId:%d, failed to delete ttl for table:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), pME->name,
×
453
              pME->uid, tstrerror(ret));
454
  }
455
  return;
1,485✔
456
}
457

458
static int metaDropTableByUid(SMeta *pMeta, tb_uid_t uid, int *type, tb_uid_t *pSuid, int8_t *pSysTbl) {
1,485✔
459
  void      *pData = NULL;
1,485✔
460
  int        nData = 0;
1,485✔
461
  int        rc = 0;
1,485✔
462
  SMetaEntry e = {0};
1,485✔
463
  SDecoder   dc = {0};
1,485✔
464
  int32_t    ret = 0;
1,485✔
465

466
  rc = tdbTbGet(pMeta->pUidIdx, &uid, sizeof(uid), &pData, &nData);
1,485✔
467
  if (rc < 0) {
1,485!
UNCOV
468
    return rc;
×
469
  }
470
  int64_t version = ((SUidIdxVal *)pData)[0].version;
1,485✔
471

472
  rc = tdbTbGet(pMeta->pTbDb, &(STbDbKey){.version = version, .uid = uid}, sizeof(STbDbKey), &pData, &nData);
1,485✔
473
  if (rc < 0) {
1,485!
UNCOV
474
    tdbFree(pData);
×
UNCOV
475
    return rc;
×
476
  }
477

478
  tDecoderInit(&dc, pData, nData);
1,485✔
479
  rc = metaDecodeEntry(&dc, &e);
1,485✔
480
  if (rc < 0) {
1,485!
UNCOV
481
    tDecoderClear(&dc);
×
482
    return rc;
×
483
  }
484

485
  if (type) *type = e.type;
1,485!
486

487
  if (e.type == TSDB_CHILD_TABLE) {
1,485✔
488
    if (pSuid) *pSuid = e.ctbEntry.suid;
1,484!
489
    void *tData = NULL;
1,484✔
490
    int   tLen = 0;
1,484✔
491

492
    if (tdbTbGet(pMeta->pUidIdx, &e.ctbEntry.suid, sizeof(tb_uid_t), &tData, &tLen) == 0) {
1,484!
493
      STbDbKey tbDbKey = {.uid = e.ctbEntry.suid, .version = ((SUidIdxVal *)tData)[0].version};
1,484✔
494
      if (tdbTbGet(pMeta->pTbDb, &tbDbKey, sizeof(tbDbKey), &tData, &tLen) == 0) {
1,484!
495
        SDecoder   tdc = {0};
1,484✔
496
        SMetaEntry stbEntry = {0};
1,484✔
497

498
        tDecoderInit(&tdc, tData, tLen);
1,484✔
499
        int32_t ret = metaDecodeEntry(&tdc, &stbEntry);
1,484✔
500
        if (ret < 0) {
1,484!
UNCOV
501
          tDecoderClear(&tdc);
×
UNCOV
502
          metaError("vgId:%d, failed to decode child table:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), e.name,
×
503
                    e.ctbEntry.suid, tstrerror(ret));
UNCOV
504
          return ret;
×
505
        }
506

507
        if (pSysTbl) *pSysTbl = metaTbInFilterCache(pMeta, stbEntry.name, 1) ? 1 : 0;
1,484!
508

509
        SSchema        *pTagColumn = NULL;
1,484✔
510
        SSchemaWrapper *pTagSchema = &stbEntry.stbEntry.schemaTag;
1,484✔
511
        if (pTagSchema->nCols == 1 && pTagSchema->pSchema[0].type == TSDB_DATA_TYPE_JSON) {
1,484!
UNCOV
512
          pTagColumn = &stbEntry.stbEntry.schemaTag.pSchema[0];
×
UNCOV
513
          ret = metaDelJsonVarFromIdx(pMeta, &e, pTagColumn);
×
UNCOV
514
          if (ret < 0) {
×
515
            metaError("vgId:%d, failed to delete json var from idx:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode),
×
516
                      e.name, e.uid, tstrerror(ret));
517
          }
518
        } else {
519
          for (int i = 0; i < pTagSchema->nCols; i++) {
3,854✔
520
            pTagColumn = &stbEntry.stbEntry.schemaTag.pSchema[i];
2,370✔
521
            if (!IS_IDX_ON(pTagColumn)) continue;
2,370✔
522
            STagIdxKey *pTagIdxKey = NULL;
1,484✔
523
            int32_t     nTagIdxKey;
524

525
            const void *pTagData = NULL;
1,484✔
526
            int32_t     nTagData = 0;
1,484✔
527

528
            STagVal tagVal = {.cid = pTagColumn->colId};
1,484✔
529
            if (tTagGet((const STag *)e.ctbEntry.pTags, &tagVal)) {
1,484!
530
              if (IS_VAR_DATA_TYPE(pTagColumn->type)) {
1,484!
UNCOV
531
                pTagData = tagVal.pData;
×
UNCOV
532
                nTagData = (int32_t)tagVal.nData;
×
533
              } else {
534
                pTagData = &(tagVal.i64);
1,484✔
535
                nTagData = tDataTypes[pTagColumn->type].bytes;
1,484✔
536
              }
537
            } else {
UNCOV
538
              if (!IS_VAR_DATA_TYPE(pTagColumn->type)) {
×
UNCOV
539
                nTagData = tDataTypes[pTagColumn->type].bytes;
×
540
              }
541
            }
542

543
            if (metaCreateTagIdxKey(e.ctbEntry.suid, pTagColumn->colId, pTagData, nTagData, pTagColumn->type, uid,
1,484!
544
                                    &pTagIdxKey, &nTagIdxKey) == 0) {
545
              ret = tdbTbDelete(pMeta->pTagIdx, pTagIdxKey, nTagIdxKey, pMeta->txn);
1,484✔
546
              if (ret < 0) {
1,484!
UNCOV
547
                metaError("vgId:%d, failed to delete tag idx key:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode),
×
548
                          e.name, e.uid, tstrerror(ret));
549
              }
550
            }
551
            metaDestroyTagIdxKey(pTagIdxKey);
1,484✔
552
            pTagIdxKey = NULL;
1,484✔
553
          }
554
        }
555
        tDecoderClear(&tdc);
1,484✔
556
      }
557
      tdbFree(tData);
1,484✔
558
    }
559
  }
560

561
  ret = tdbTbDelete(pMeta->pTbDb, &(STbDbKey){.version = version, .uid = uid}, sizeof(STbDbKey), pMeta->txn);
1,485✔
562
  if (ret < 0) {
1,485!
UNCOV
563
    metaError("vgId:%d, failed to delete table:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), e.name, e.uid,
×
564
              tstrerror(ret));
565
  }
566
  ret = tdbTbDelete(pMeta->pNameIdx, e.name, strlen(e.name) + 1, pMeta->txn);
1,485✔
567
  if (ret < 0) {
1,485!
UNCOV
568
    metaError("vgId:%d, failed to delete name idx:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), e.name, e.uid,
×
569
              tstrerror(ret));
570
  }
571
  ret = tdbTbDelete(pMeta->pUidIdx, &uid, sizeof(uid), pMeta->txn);
1,485✔
572
  if (ret < 0) {
1,485!
UNCOV
573
    metaError("vgId:%d, failed to delete uid idx:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), e.name, e.uid,
×
574
              tstrerror(ret));
575
  }
576

577
  if (e.type == TSDB_CHILD_TABLE || e.type == TSDB_NORMAL_TABLE) metaDeleteBtimeIdx(pMeta, &e);
1,485!
578
  if (e.type == TSDB_NORMAL_TABLE) metaDeleteNcolIdx(pMeta, &e);
1,485✔
579

580
  if (e.type != TSDB_SUPER_TABLE) metaDeleteTtl(pMeta, &e);
1,485!
581

582
  if (e.type == TSDB_CHILD_TABLE) {
1,485✔
583
    ret =
584
        tdbTbDelete(pMeta->pCtbIdx, &(SCtbIdxKey){.suid = e.ctbEntry.suid, .uid = uid}, sizeof(SCtbIdxKey), pMeta->txn);
1,484✔
585
    if (ret < 0) {
1,484!
UNCOV
586
      metaError("vgId:%d, failed to delete ctb idx:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), e.name, e.uid,
×
587
                tstrerror(ret));
588
    }
589

590
    --pMeta->pVnode->config.vndStats.numOfCTables;
1,484✔
591
    metaUpdateStbStats(pMeta, e.ctbEntry.suid, -1, 0);
1,484✔
592
    ret = metaUidCacheClear(pMeta, e.ctbEntry.suid);
1,484✔
593
    if (ret < 0) {
1,484!
UNCOV
594
      metaError("vgId:%d, failed to clear uid cache:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), e.name,
×
595
                e.ctbEntry.suid, tstrerror(ret));
596
    }
597
    ret = metaTbGroupCacheClear(pMeta, e.ctbEntry.suid);
1,484✔
598
    if (ret < 0) {
1,484!
UNCOV
599
      metaError("vgId:%d, failed to clear group cache:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), e.name,
×
600
                e.ctbEntry.suid, tstrerror(ret));
601
    }
602
    /*
603
    if (!TSDB_CACHE_NO(pMeta->pVnode->config)) {
604
      tsdbCacheDropTable(pMeta->pVnode->pTsdb, e.uid, e.ctbEntry.suid, NULL);
605
    }
606
    */
607
  } else if (e.type == TSDB_NORMAL_TABLE) {
1!
608
    // drop schema.db (todo)
609

610
    --pMeta->pVnode->config.vndStats.numOfNTables;
1✔
611
    pMeta->pVnode->config.vndStats.numOfNTimeSeries -= e.ntbEntry.schemaRow.nCols - 1;
1✔
612

613
    /*
614
    if (!TSDB_CACHE_NO(pMeta->pVnode->config)) {
615
      tsdbCacheDropTable(pMeta->pVnode->pTsdb, e.uid, -1, &e.ntbEntry.schemaRow);
616
    }
617
    */
UNCOV
618
  } else if (e.type == TSDB_SUPER_TABLE) {
×
UNCOV
619
    ret = tdbTbDelete(pMeta->pSuidIdx, &e.uid, sizeof(tb_uid_t), pMeta->txn);
×
UNCOV
620
    if (ret < 0) {
×
UNCOV
621
      metaError("vgId:%d, failed to delete suid idx:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), e.name, e.uid,
×
622
                tstrerror(ret));
623
    }
624
    // drop schema.db (todo)
625

UNCOV
626
    ret = metaStatsCacheDrop(pMeta, uid);
×
UNCOV
627
    if (ret < 0) {
×
UNCOV
628
      metaError("vgId:%d, failed to drop stats cache:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), e.name, e.uid,
×
629
                tstrerror(ret));
630
    }
UNCOV
631
    ret = metaUidCacheClear(pMeta, uid);
×
632
    if (ret < 0) {
×
633
      metaError("vgId:%d, failed to clear uid cache:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), e.name, e.uid,
×
634
                tstrerror(ret));
635
    }
UNCOV
636
    ret = metaTbGroupCacheClear(pMeta, uid);
×
UNCOV
637
    if (ret < 0) {
×
UNCOV
638
      metaError("vgId:%d, failed to clear group cache:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), e.name,
×
639
                e.uid, tstrerror(ret));
640
    }
641
    --pMeta->pVnode->config.vndStats.numOfSTables;
×
642
  }
643

644
  ret = metaCacheDrop(pMeta, uid);
1,485✔
645
  if (ret < 0) {
1,485!
646
    metaError("vgId:%d, failed to drop cache:%s uid:%" PRId64 " since %s", TD_VID(pMeta->pVnode), e.name, e.uid,
1,485!
647
              tstrerror(ret));
648
  }
649

650
  tDecoderClear(&dc);
1,485✔
651
  tdbFree(pData);
1,485✔
652

653
  return 0;
1,485✔
654
}
655

656
static int metaDeleteBtimeIdx(SMeta *pMeta, const SMetaEntry *pME) {
1,485✔
657
  SBtimeIdxKey btimeKey = {0};
1,485✔
658
  if (metaBuildBtimeIdxKey(&btimeKey, pME) < 0) {
1,485!
UNCOV
659
    return 0;
×
660
  }
661
  return tdbTbDelete(pMeta->pBtimeIdx, &btimeKey, sizeof(btimeKey), pMeta->txn);
1,485✔
662
}
663

664
int metaDeleteNcolIdx(SMeta *pMeta, const SMetaEntry *pME) {
1✔
665
  SNcolIdxKey ncolKey = {0};
1✔
666
  if (metaBuildNColIdxKey(&ncolKey, pME) < 0) {
1!
UNCOV
667
    return 0;
×
668
  }
669
  return tdbTbDelete(pMeta->pNcolIdx, &ncolKey, sizeof(ncolKey), pMeta->txn);
1✔
670
}
671

672
int metaAlterTable(SMeta *pMeta, int64_t version, SVAlterTbReq *pReq, STableMetaRsp *pMetaRsp) {
974✔
673
  pMeta->changed = true;
974✔
674
  switch (pReq->action) {
974!
675
    case TSDB_ALTER_TABLE_ADD_COLUMN:
82✔
676
    case TSDB_ALTER_TABLE_ADD_COLUMN_WITH_COMPRESS_OPTION:
677
      return metaAddTableColumn(pMeta, version, pReq, pMetaRsp);
82✔
678
    case TSDB_ALTER_TABLE_DROP_COLUMN:
72✔
679
      return metaDropTableColumn(pMeta, version, pReq, pMetaRsp);
72✔
680
    case TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES:
42✔
681
      return metaAlterTableColumnBytes(pMeta, version, pReq, pMetaRsp);
42✔
682
    case TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME:
32✔
683
      return metaAlterTableColumnName(pMeta, version, pReq, pMetaRsp);
32✔
684
    case TSDB_ALTER_TABLE_UPDATE_TAG_VAL:
656✔
685
      return metaUpdateTableTagValue(pMeta, version, pReq);
656✔
686
    case TSDB_ALTER_TABLE_UPDATE_MULTI_TAG_VAL:
5✔
687
      return metaUpdateTableMultiTagValue(pMeta, version, pReq);
5✔
688
    case TSDB_ALTER_TABLE_UPDATE_OPTIONS:
80✔
689
      return metaUpdateTableOptions2(pMeta, version, pReq);
80✔
690
    case TSDB_ALTER_TABLE_UPDATE_COLUMN_COMPRESS:
5✔
691
      return metaUpdateTableColCompress2(pMeta, version, pReq);
5✔
UNCOV
692
    default:
×
UNCOV
693
      return terrno = TSDB_CODE_VND_INVALID_TABLE_ACTION;
×
694
      break;
695
  }
696
}
697

UNCOV
698
static int metaUpdateChangeTime(SMeta *pMeta, tb_uid_t uid, int64_t changeTimeMs) {
×
UNCOV
699
  if (!tsTtlChangeOnWrite) return 0;
×
700

UNCOV
701
  if (changeTimeMs <= 0) {
×
UNCOV
702
    metaWarn("Skip to change ttl deletetion time on write, uid: %" PRId64, uid);
×
UNCOV
703
    return TSDB_CODE_VERSION_NOT_COMPATIBLE;
×
704
  }
705

706
  STtlUpdCtimeCtx ctx = {.uid = uid, .changeTimeMs = changeTimeMs, .pTxn = pMeta->txn};
×
707

UNCOV
708
  return ttlMgrUpdateChangeTime(pMeta->pTtlMgr, &ctx);
×
709
}
710

711
int metaUpdateChangeTimeWithLock(SMeta *pMeta, tb_uid_t uid, int64_t changeTimeMs) {
12,108,430✔
712
  if (!tsTtlChangeOnWrite) return 0;
12,108,430!
713

UNCOV
714
  metaWLock(pMeta);
×
715
  int ret = metaUpdateChangeTime(pMeta, uid, changeTimeMs);
×
716
  metaULock(pMeta);
×
717
  return ret;
×
718
}
719

720
int metaCreateTagIdxKey(tb_uid_t suid, int32_t cid, const void *pTagData, int32_t nTagData, int8_t type, tb_uid_t uid,
154,846✔
721
                        STagIdxKey **ppTagIdxKey, int32_t *nTagIdxKey) {
722
  if (IS_VAR_DATA_TYPE(type)) {
154,846!
723
    *nTagIdxKey = sizeof(STagIdxKey) + nTagData + VARSTR_HEADER_SIZE + sizeof(tb_uid_t);
24,872✔
724
  } else {
725
    *nTagIdxKey = sizeof(STagIdxKey) + nTagData + sizeof(tb_uid_t);
129,974✔
726
  }
727

728
  *ppTagIdxKey = (STagIdxKey *)taosMemoryMalloc(*nTagIdxKey);
154,846!
729
  if (*ppTagIdxKey == NULL) {
154,887!
730
    return terrno;
×
731
  }
732

733
  (*ppTagIdxKey)->suid = suid;
154,887✔
734
  (*ppTagIdxKey)->cid = cid;
154,887✔
735
  (*ppTagIdxKey)->isNull = (pTagData == NULL) ? 1 : 0;
154,887✔
736
  (*ppTagIdxKey)->type = type;
154,887✔
737

738
  // refactor
739
  if (IS_VAR_DATA_TYPE(type)) {
154,887!
740
    memcpy((*ppTagIdxKey)->data, (uint16_t *)&nTagData, VARSTR_HEADER_SIZE);
24,918✔
741
    if (pTagData != NULL) memcpy((*ppTagIdxKey)->data + VARSTR_HEADER_SIZE, pTagData, nTagData);
24,918✔
742
    *(tb_uid_t *)((*ppTagIdxKey)->data + VARSTR_HEADER_SIZE + nTagData) = uid;
24,918✔
743
  } else {
744
    if (pTagData != NULL) memcpy((*ppTagIdxKey)->data, pTagData, nTagData);
129,969✔
745
    *(tb_uid_t *)((*ppTagIdxKey)->data + nTagData) = uid;
129,969✔
746
  }
747

748
  return 0;
154,887✔
749
}
750

751
void metaDestroyTagIdxKey(STagIdxKey *pTagIdxKey) {
154,485✔
752
  if (pTagIdxKey) taosMemoryFree(pTagIdxKey);
154,485!
753
}
154,493✔
754

755
static void colCompressDebug(SHashObj *pColCmprObj) {
596,812✔
756
  void *p = taosHashIterate(pColCmprObj, NULL);
596,812✔
757
  while (p) {
4,374,964✔
758
    uint32_t cmprAlg = *(uint32_t *)p;
3,778,360✔
759
    col_id_t colId = *(col_id_t *)taosHashGetKey(p, NULL);
3,778,360✔
760
    p = taosHashIterate(pColCmprObj, p);
3,778,271✔
761

762
    uint8_t l1, l2, lvl;
763
    tcompressDebug(cmprAlg, &l1, &l2, &lvl);
3,779,837✔
764

765
    const char *l1str = columnEncodeStr(l1);
3,779,394✔
766
    const char *l2str = columnCompressStr(l2);
3,778,769✔
767
    const char *lvlstr = columnLevelStr(lvl);
3,778,355✔
768
    metaDebug("colId: %d, encode:%s, compress:%s,level:%s", colId, l1str, l2str, lvlstr);
3,778,190✔
769
  }
770
  return;
596,604✔
771
}
772

773
int32_t metaGetColCmpr(SMeta *pMeta, tb_uid_t uid, SHashObj **ppColCmprObj) {
596,805✔
774
  int rc = 0;
596,805✔
775

776
  SHashObj *pColCmprObj = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_SMALLINT), false, HASH_NO_LOCK);
596,805✔
777
  if (pColCmprObj == NULL) {
596,828!
UNCOV
778
    pColCmprObj = NULL;
×
UNCOV
779
    return TSDB_CODE_OUT_OF_MEMORY;
×
780
  }
781

782
  void      *pData = NULL;
596,828✔
783
  int        nData = 0;
596,828✔
784
  SMetaEntry e = {0};
596,828✔
785
  SDecoder   dc = {0};
596,828✔
786

787
  *ppColCmprObj = NULL;
596,828✔
788

789
  metaRLock(pMeta);
596,828✔
790
  rc = tdbTbGet(pMeta->pUidIdx, &uid, sizeof(uid), &pData, &nData);
596,865✔
791
  if (rc < 0) {
596,846!
792
    taosHashClear(pColCmprObj);
×
793
    metaULock(pMeta);
×
UNCOV
794
    return TSDB_CODE_FAILED;
×
795
  }
796
  int64_t version = ((SUidIdxVal *)pData)[0].version;
596,846✔
797
  rc = tdbTbGet(pMeta->pTbDb, &(STbDbKey){.version = version, .uid = uid}, sizeof(STbDbKey), &pData, &nData);
596,846✔
798
  if (rc < 0) {
596,837!
UNCOV
799
    metaULock(pMeta);
×
UNCOV
800
    taosHashClear(pColCmprObj);
×
UNCOV
801
    metaError("failed to get table entry");
×
UNCOV
802
    return rc;
×
803
  }
804

805
  tDecoderInit(&dc, pData, nData);
596,837✔
806
  rc = metaDecodeEntry(&dc, &e);
596,822✔
807
  if (rc < 0) {
596,758!
808
    tDecoderClear(&dc);
×
UNCOV
809
    tdbFree(pData);
×
UNCOV
810
    metaULock(pMeta);
×
UNCOV
811
    taosHashClear(pColCmprObj);
×
UNCOV
812
    return rc;
×
813
  }
814
  if (useCompress(e.type)) {
596,758!
815
    SColCmprWrapper *p = &e.colCmpr;
596,770✔
816
    for (int32_t i = 0; i < p->nCols; i++) {
4,376,968✔
817
      SColCmpr *pCmpr = &p->pColCmpr[i];
3,779,858✔
818
      rc = taosHashPut(pColCmprObj, &pCmpr->id, sizeof(pCmpr->id), &pCmpr->alg, sizeof(pCmpr->alg));
3,779,858✔
819
      if (rc < 0) {
3,780,198!
UNCOV
820
        tDecoderClear(&dc);
×
UNCOV
821
        tdbFree(pData);
×
822
        metaULock(pMeta);
×
823
        taosHashClear(pColCmprObj);
×
824
        return rc;
×
825
      }
826
    }
827
  } else {
UNCOV
828
    tDecoderClear(&dc);
×
UNCOV
829
    tdbFree(pData);
×
UNCOV
830
    metaULock(pMeta);
×
UNCOV
831
    taosHashClear(pColCmprObj);
×
UNCOV
832
    return 0;
×
833
  }
834
  tDecoderClear(&dc);
597,110✔
835
  tdbFree(pData);
596,807✔
836
  metaULock(pMeta);
596,852✔
837

838
  *ppColCmprObj = pColCmprObj;
596,839✔
839
  colCompressDebug(pColCmprObj);
596,839✔
840

841
  return 0;
596,733✔
842
}
843
// refactor later
844
void *metaGetIdx(SMeta *pMeta) { return pMeta->pTagIdx; }
75,110✔
845
void *metaGetIvtIdx(SMeta *pMeta) { return pMeta->pTagIvtIdx; }
74,984✔
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