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

taosdata / TDengine / #3531

19 Nov 2024 10:42AM UTC coverage: 60.213% (-0.006%) from 60.219%
#3531

push

travis-ci

web-flow
Merge pull request #28777 from taosdata/fix/3.0/TD-32366

fix:TD-32366/stmt add geometry datatype check

118529 of 252344 branches covered (46.97%)

Branch coverage included in aggregate %.

7 of 48 new or added lines in 3 files covered. (14.58%)

2282 existing lines in 115 files now uncovered.

199096 of 275161 relevant lines covered (72.36%)

6067577.83 hits per line

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

75.26
/source/libs/executor/src/tfill.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 "filter.h"
17
#include "os.h"
18
#include "query.h"
19
#include "taosdef.h"
20
#include "tmsg.h"
21
#include "ttypes.h"
22

23
#include "executorInt.h"
24
#include "tcommon.h"
25
#include "thash.h"
26
#include "ttime.h"
27

28
#include "executorInt.h"
29
#include "function.h"
30
#include "querynodes.h"
31
#include "querytask.h"
32
#include "tdatablock.h"
33
#include "tfill.h"
34

35
#define FILL_IS_ASC_FILL(_f) ((_f)->order == TSDB_ORDER_ASC)
36
#define DO_INTERPOLATION(_v1, _v2, _k1, _k2, _k) \
37
  ((_v1) + ((_v2) - (_v1)) * (((double)(_k)) - ((double)(_k1))) / (((double)(_k2)) - ((double)(_k1))))
38

39
static int32_t doSetVal(SColumnInfoData* pDstColInfoData, int32_t rowIndex, const SGroupKeys* pKey);
40

41
static void setNotFillColumn(SFillInfo* pFillInfo, SColumnInfoData* pDstColInfo, int32_t rowIndex, int32_t colIdx) {
2,552,379✔
42
  SFillColInfo* pCol = &pFillInfo->pFillCol[colIdx];
2,552,379✔
43
  if (pCol->fillNull) {
2,552,379✔
44
    colDataSetNULL(pDstColInfo, rowIndex);
443!
45
  } else {
46
    SRowVal* p = NULL;
2,551,936✔
47
    if (pFillInfo->type == TSDB_FILL_NEXT) {
2,551,936✔
48
      p = FILL_IS_ASC_FILL(pFillInfo) ? &pFillInfo->next : &pFillInfo->prev;
81,828✔
49
    } else {
50
      p = FILL_IS_ASC_FILL(pFillInfo) ? &pFillInfo->prev : &pFillInfo->next;
2,470,108✔
51
    }
52

53
    SGroupKeys* pKey = taosArrayGet(p->pRowVal, colIdx);
2,551,936✔
54
    if (!pKey) {
2,549,156!
55
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(terrno));
×
56
      T_LONG_JMP(pFillInfo->pTaskInfo->env, terrno);
×
57
    }
58
    int32_t     code = doSetVal(pDstColInfo, rowIndex, pKey);
2,549,156✔
59
    if (code != TSDB_CODE_SUCCESS) {
2,552,943!
60
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
61
      T_LONG_JMP(pFillInfo->pTaskInfo->env, code);
×
62
    }
63
  }
64
}
2,553,386✔
65

66
static void setNullRow(SSDataBlock* pBlock, SFillInfo* pFillInfo, int32_t rowIndex) {
1,206,979✔
67
  for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
5,666,185✔
68
    SFillColInfo*    pCol = &pFillInfo->pFillCol[i];
4,457,723✔
69
    int32_t          dstSlotId = GET_DEST_SLOT_ID(pCol);
4,457,723✔
70
    SColumnInfoData* pDstColInfo = taosArrayGet(pBlock->pDataBlock, dstSlotId);
4,457,723✔
71
    if (pCol->notFillCol) {
4,457,507✔
72
      bool filled = fillIfWindowPseudoColumn(pFillInfo, pCol, pDstColInfo, rowIndex);
3,234,600✔
73
      if (!filled) {
3,242,848✔
74
        setNotFillColumn(pFillInfo, pDstColInfo, rowIndex, i);
2,038,203✔
75
      }
76
    } else {
77
      colDataSetNULL(pDstColInfo, rowIndex);
1,222,907✔
78
    }
79
  }
80
}
1,208,462✔
81

82
static int32_t doSetUserSpecifiedValue(SColumnInfoData* pDst, SVariant* pVar, int32_t rowIndex, int64_t currentKey) {
980,078✔
83
  int32_t code = TSDB_CODE_SUCCESS;
980,078✔
84
  int32_t lino = 0;
980,078✔
85
  bool    isNull = (TSDB_DATA_TYPE_NULL == pVar->nType) ? true : false;
980,078✔
86
  if (pDst->info.type == TSDB_DATA_TYPE_FLOAT) {
980,078✔
87
    float v = 0;
182✔
88
    GET_TYPED_DATA(v, float, pVar->nType, &pVar->f);
182!
89
    code = colDataSetVal(pDst, rowIndex, (char*)&v, isNull);
182✔
90
    QUERY_CHECK_CODE(code, lino, _end);
182!
91
  } else if (pDst->info.type == TSDB_DATA_TYPE_DOUBLE) {
979,896✔
92
    double v = 0;
444,599✔
93
    GET_TYPED_DATA(v, double, pVar->nType, &pVar->d);
444,599!
94
    code = colDataSetVal(pDst, rowIndex, (char*)&v, isNull);
444,599✔
95
    QUERY_CHECK_CODE(code, lino, _end);
444,599!
96
  } else if (IS_SIGNED_NUMERIC_TYPE(pDst->info.type) || pDst->info.type == TSDB_DATA_TYPE_BOOL) {
880,109✔
97
    int64_t v = 0;
344,812✔
98
    GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->i);
344,812!
99
    code = colDataSetVal(pDst, rowIndex, (char*)&v, isNull);
344,812✔
100
    QUERY_CHECK_CODE(code, lino, _end);
344,812!
101
  } else if (IS_UNSIGNED_NUMERIC_TYPE(pDst->info.type)) {
190,679✔
102
    uint64_t v = 0;
194✔
103
    GET_TYPED_DATA(v, uint64_t, pVar->nType, &pVar->u);
194!
104
    code = colDataSetVal(pDst, rowIndex, (char*)&v, isNull);
194✔
105
    QUERY_CHECK_CODE(code, lino, _end);
194!
106
  } else if (pDst->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
190,291✔
107
    int64_t v = 0;
16,592✔
108
    GET_TYPED_DATA(v, int64_t, pVar->nType, &pVar->u);
16,592!
109
    code = colDataSetVal(pDst, rowIndex, (const char*)&v, isNull);
16,592✔
110
    QUERY_CHECK_CODE(code, lino, _end);
16,592!
111
  } else if (pDst->info.type == TSDB_DATA_TYPE_NCHAR || pDst->info.type == TSDB_DATA_TYPE_VARCHAR ||
173,699✔
112
             pDst->info.type == TSDB_DATA_TYPE_VARBINARY) {
24!
113
    code = colDataSetVal(pDst, rowIndex, pVar->pz, isNull);
173,699✔
114
    QUERY_CHECK_CODE(code, lino, _end);
173,699!
115
  } else {  // others data
116
    colDataSetNULL(pDst, rowIndex);
×
117
  }
118

119
_end:
980,078✔
120
  if (code != TSDB_CODE_SUCCESS) {
980,078!
121
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
122
  }
123
  return code;
980,078✔
124
}
125

126
// fill windows pseudo column, _wstart, _wend, _wduration and return true, otherwise return false
127
bool fillIfWindowPseudoColumn(SFillInfo* pFillInfo, SFillColInfo* pCol, SColumnInfoData* pDstColInfoData,
18,352,602✔
128
                              int32_t rowIndex) {
129
  int32_t code = TSDB_CODE_SUCCESS;
18,352,602✔
130
  int32_t lino = 0;
18,352,602✔
131
  if (!pCol->notFillCol) {
18,352,602✔
132
    return false;
320,184✔
133
  }
134
  if (pCol->pExpr->pExpr->nodeType == QUERY_NODE_COLUMN) {
18,032,418!
135
    if (pCol->pExpr->base.numOfParams != 1) {
18,035,810!
136
      return false;
×
137
    }
138
    if (pCol->pExpr->base.pParam[0].pCol->colType == COLUMN_TYPE_WINDOW_START) {
18,035,810✔
139
      code = colDataSetVal(pDstColInfoData, rowIndex, (const char*)&pFillInfo->currentKey, false);
8,788,194✔
140
      QUERY_CHECK_CODE(code, lino, _end);
8,790,721!
141
      return true;
8,790,721✔
142
    } else if (pCol->pExpr->base.pParam[0].pCol->colType == COLUMN_TYPE_WINDOW_END) {
9,247,616✔
143
      // TODO: include endpoint
144
      SInterval* pInterval = &pFillInfo->interval;
6,950,066✔
145
      int64_t    windowEnd =
6,950,066✔
146
          taosTimeAdd(pFillInfo->currentKey, pInterval->interval, pInterval->intervalUnit, pInterval->precision);
6,950,066✔
147
      code = colDataSetVal(pDstColInfoData, rowIndex, (const char*)&windowEnd, false);
6,950,066✔
148
      QUERY_CHECK_CODE(code, lino, _end);
6,950,067!
149
      return true;
6,950,067✔
150
    } else if (pCol->pExpr->base.pParam[0].pCol->colType == COLUMN_TYPE_WINDOW_DURATION) {
2,297,550!
151
      // TODO: include endpoint
152
      code = colDataSetVal(pDstColInfoData, rowIndex, (const char*)&pFillInfo->interval.sliding, false);
×
153
      QUERY_CHECK_CODE(code, lino, _end);
×
154
      return true;
×
155
    }
156
  }
157

158
_end:
2,294,158✔
159
  if (code != TSDB_CODE_SUCCESS) {
2,294,158!
160
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
161
    T_LONG_JMP(pFillInfo->pTaskInfo->env, code);
×
162
  }
163
  return false;
2,294,158✔
164
}
165

166
static void doFillOneRow(SFillInfo* pFillInfo, SSDataBlock* pBlock, SSDataBlock* pSrcBlock, int64_t ts,
8,741,325✔
167
                         bool outOfBound) {
168
  int32_t code = TSDB_CODE_SUCCESS;
8,741,325✔
169
  int32_t lino = 0;
8,741,325✔
170
  SPoint  point1, point2, point;
171
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pFillInfo->order);
8,741,325✔
172

173
  // set the primary timestamp column value
174
  int32_t index = pBlock->info.rows;
8,741,325✔
175

176
  // set the other values
177
  if (pFillInfo->type == TSDB_FILL_PREV) {
8,741,325✔
178
    for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
357,142✔
179
      SFillColInfo* pCol = &pFillInfo->pFillCol[i];
266,148✔
180

181
      SColumnInfoData* pDstColInfoData = taosArrayGet(pBlock->pDataBlock, GET_DEST_SLOT_ID(pCol));
266,148✔
182
      bool             filled = fillIfWindowPseudoColumn(pFillInfo, pCol, pDstColInfoData, index);
265,993✔
183
      if (!filled) {
266,161✔
184
        setNotFillColumn(pFillInfo, pDstColInfoData, index, i);
177,474✔
185
      }
186
    }
187
  } else if (pFillInfo->type == TSDB_FILL_NEXT) {
8,650,532✔
188
    // todo  refactor: start from 0 not 1
189
    for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
219,878✔
190
      SFillColInfo*    pCol = &pFillInfo->pFillCol[i];
150,854✔
191
      SColumnInfoData* pDstColInfoData = taosArrayGet(pBlock->pDataBlock, GET_DEST_SLOT_ID(pCol));
150,854✔
192
      bool             filled = fillIfWindowPseudoColumn(pFillInfo, pCol, pDstColInfoData, index);
150,854✔
193
      if (!filled) {
150,854✔
194
        setNotFillColumn(pFillInfo, pDstColInfoData, index, i);
81,828✔
195
      }
196
    }
197
  } else if (pFillInfo->type == TSDB_FILL_LINEAR) {
8,581,508✔
198
    // TODO : linear interpolation supports NULL value
199
    if (outOfBound) {
7,046,674✔
200
      setNullRow(pBlock, pFillInfo, index);
60,131✔
201
    } else {
202
      for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
48,953,743✔
203
        SFillColInfo* pCol = &pFillInfo->pFillCol[i];
41,966,975✔
204

205
        int32_t          dstSlotId = GET_DEST_SLOT_ID(pCol);
41,966,975✔
206
        SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId);
41,966,975✔
207
        int16_t          type = pDstCol->info.type;
41,966,843✔
208

209
        if (pCol->notFillCol) {
41,966,843✔
210
          bool filled = fillIfWindowPseudoColumn(pFillInfo, pCol, pDstCol, index);
13,946,583✔
211
          if (!filled) {
13,946,867✔
212
            setNotFillColumn(pFillInfo, pDstCol, index, i);
11,567✔
213
          }
214
        } else {
215
          SRowVal*    pRVal = &pFillInfo->prev;
28,020,260✔
216
          SGroupKeys* pKey = taosArrayGet(pRVal->pRowVal, i);
28,020,260✔
217
          if (IS_VAR_DATA_TYPE(type) || type == TSDB_DATA_TYPE_BOOL || pKey->isNull) {
28,021,393!
218
            colDataSetNULL(pDstCol, index);
58,869✔
219
            continue;
58,869✔
220
          }
221

222
          SGroupKeys* pKey1 = taosArrayGet(pRVal->pRowVal, pFillInfo->tsSlotId);
27,962,524✔
223

224
          int64_t prevTs = *(int64_t*)pKey1->pData;
27,962,165✔
225
          int32_t srcSlotId = GET_DEST_SLOT_ID(pCol);
27,962,165✔
226

227
          SColumnInfoData* pSrcCol = taosArrayGet(pSrcBlock->pDataBlock, srcSlotId);
27,962,165✔
228
          char*            data = colDataGetData(pSrcCol, pFillInfo->index);
27,962,095!
229

230
          point1 = (SPoint){.key = prevTs, .val = pKey->pData};
27,962,095✔
231
          point2 = (SPoint){.key = ts, .val = data};
27,962,095✔
232

233
          int64_t out = 0;
27,962,095✔
234
          point = (SPoint){.key = pFillInfo->currentKey, .val = &out};
27,962,095✔
235
          taosGetLinearInterpolationVal(&point, type, &point1, &point2, type);
27,962,095✔
236

237
          code = colDataSetVal(pDstCol, index, (const char*)&out, false);
27,962,457✔
238
          QUERY_CHECK_CODE(code, lino, _end);
27,962,524!
239
        }
240
      }
241
    }
242
  } else if (pFillInfo->type == TSDB_FILL_NULL || pFillInfo->type == TSDB_FILL_NULL_F) {  // fill with NULL
1,534,834✔
243
    setNullRow(pBlock, pFillInfo, index);
1,147,184✔
244
  } else {  // fill with user specified value for each column
245
    for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
1,946,850✔
246
      SFillColInfo* pCol = &pFillInfo->pFillCol[i];
1,559,201✔
247

248
      int32_t          slotId = GET_DEST_SLOT_ID(pCol);
1,559,201✔
249
      SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, slotId);
1,559,201✔
250

251
      if (pCol->notFillCol) {
1,559,199✔
252
        bool filled = fillIfWindowPseudoColumn(pFillInfo, pCol, pDst, index);
629,349✔
253
        if (!filled) {
629,349✔
254
          setNotFillColumn(pFillInfo, pDst, index, i);
241,500✔
255
        }
256
      } else {
257
        SVariant* pVar = &pFillInfo->pFillCol[i].fillVal;
929,850✔
258
        code = doSetUserSpecifiedValue(pDst, pVar, index, pFillInfo->currentKey);
929,850✔
259
        QUERY_CHECK_CODE(code, lino, _end);
929,853!
260
      }
261
    }
262
  }
263

264
  //  setTagsValue(pFillInfo, data, index);
265
  SInterval* pInterval = &pFillInfo->interval;
8,741,745✔
266
  pFillInfo->currentKey =
8,741,084✔
267
      taosTimeAdd(pFillInfo->currentKey, pInterval->sliding * step, pInterval->slidingUnit, pInterval->precision);
8,741,745✔
268
  pBlock->info.rows += 1;
8,741,084✔
269
  pFillInfo->numOfCurrent++;
8,741,084✔
270

271
_end:
8,741,084✔
272
  if (code != TSDB_CODE_SUCCESS) {
8,741,084!
273
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
274
    T_LONG_JMP(pFillInfo->pTaskInfo->env, code);
×
275
  }
276
}
8,741,084✔
277

278
int32_t doSetVal(SColumnInfoData* pDstCol, int32_t rowIndex, const SGroupKeys* pKey) {
2,549,330✔
279
  int32_t code = TSDB_CODE_SUCCESS;
2,549,330✔
280
  int32_t lino = 0;
2,549,330✔
281
  if (pKey->isNull) {
2,549,330✔
282
    colDataSetNULL(pDstCol, rowIndex);
67,363✔
283
  } else {
284
    code = colDataSetVal(pDstCol, rowIndex, pKey->pData, false);
2,481,967✔
285
    QUERY_CHECK_CODE(code, lino, _end);
2,486,028!
286
  }
287

288
_end:
2,486,028✔
289
  if (code != TSDB_CODE_SUCCESS) {
2,553,391!
290
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
291
  }
292
  return code;
2,553,150✔
293
}
294

295
static int32_t initBeforeAfterDataBuf(SFillInfo* pFillInfo) {
15,649✔
296
  int32_t code = TSDB_CODE_SUCCESS;
15,649✔
297
  int32_t lino = 0;
15,649✔
298
  if (taosArrayGetSize(pFillInfo->next.pRowVal) > 0) {
15,649!
299
    goto _end;
×
300
  }
301

302
  for (int i = 0; i < pFillInfo->numOfCols; i++) {
57,717✔
303
    SFillColInfo* pCol = &pFillInfo->pFillCol[i];
42,060✔
304

305
    SGroupKeys  key = {0};
42,060✔
306
    SResSchema* pSchema = &pCol->pExpr->base.resSchema;
42,060✔
307
    key.pData = taosMemoryMalloc(pSchema->bytes);
42,060✔
308
    QUERY_CHECK_NULL(key.pData, code, lino, _end, terrno);
42,072!
309
    key.isNull = true;
42,072✔
310
    key.bytes = pSchema->bytes;
42,072✔
311
    key.type = pSchema->type;
42,072✔
312

313
    void* tmp = taosArrayPush(pFillInfo->next.pRowVal, &key);
42,072✔
314
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
42,070!
315

316
    key.pData = taosMemoryMalloc(pSchema->bytes);
42,070✔
317
    QUERY_CHECK_NULL(key.pData, code, lino, _end, terrno);
42,070!
318

319
    tmp = taosArrayPush(pFillInfo->prev.pRowVal, &key);
42,070✔
320
    QUERY_CHECK_NULL(tmp, code, lino, _end, terrno);
42,064!
321
  }
322

323
_end:
15,657✔
324
  if (code != TSDB_CODE_SUCCESS) {
15,657!
325
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
326
  }
327
  return code;
15,653✔
328
}
329

330
static void saveColData(SArray* rowBuf, int32_t columnIndex, const char* src, bool isNull);
331

332
static int32_t copyCurrentRowIntoBuf(SFillInfo* pFillInfo, int32_t rowIndex, SRowVal* pRowVal, bool reset) {
889,171✔
333
  int32_t          code = TSDB_CODE_SUCCESS;
889,171✔
334
  int32_t          lino = 0;
889,171✔
335
  SColumnInfoData* pTsCol = taosArrayGet(pFillInfo->pSrcBlock->pDataBlock, pFillInfo->srcTsSlotId);
889,171✔
336
  QUERY_CHECK_NULL(pTsCol, code, lino, _end, terrno);
889,169!
337
  pRowVal->key = ((int64_t*)pTsCol->pData)[rowIndex];
889,169✔
338

339
  for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
6,205,320✔
340
    int32_t type = pFillInfo->pFillCol[i].pExpr->pExpr->nodeType;
5,316,197✔
341
    if (type == QUERY_NODE_COLUMN || type == QUERY_NODE_OPERATOR || type == QUERY_NODE_FUNCTION) {
6,214,940!
342
      if (!pFillInfo->pFillCol[i].notFillCol) {
5,316,197✔
343
        if (FILL_IS_ASC_FILL(pFillInfo) && pFillInfo->type != TSDB_FILL_NEXT) continue;
3,636,343✔
344
        if (!FILL_IS_ASC_FILL(pFillInfo) && pFillInfo->type != TSDB_FILL_PREV) continue;
919,160✔
345
      }
346
      int32_t srcSlotId = GET_DEST_SLOT_ID(&pFillInfo->pFillCol[i]);
1,683,848✔
347

348
      if (srcSlotId == pFillInfo->srcTsSlotId && pFillInfo->type == TSDB_FILL_LINEAR) {
1,683,848✔
349
        continue;
785,171✔
350
      }
351

352
      SColumnInfoData* pSrcCol = taosArrayGet(pFillInfo->pSrcBlock->pDataBlock, srcSlotId);
898,677✔
353
      QUERY_CHECK_NULL(pSrcCol, code, lino, _end, terrno);
898,745!
354

355
      bool  isNull = colDataIsNull_s(pSrcCol, rowIndex);
898,745✔
356
      char* p = colDataGetData(pSrcCol, rowIndex);
898,745!
357

358
      saveColData(pRowVal->pRowVal, i, p, reset ? true : isNull);
898,745✔
359
    } else {
360
      code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
×
361
      qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
×
362
      QUERY_CHECK_CODE(code, lino, _end);
×
363
    }
364
  }
365

366
_end:
889,123✔
367
  if (code != TSDB_CODE_SUCCESS) {
889,123!
368
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
369
  }
370
  return code;
889,140✔
371
}
372

373
static int32_t fillResultImpl(SFillInfo* pFillInfo, SSDataBlock* pBlock, int32_t outputRows) {
26,419✔
374
  pFillInfo->numOfCurrent = 0;
26,419✔
375
  int32_t          code = TSDB_CODE_SUCCESS;
26,419✔
376
  int32_t          lino = 0;
26,419✔
377
  SColumnInfoData* pTsCol = taosArrayGet(pFillInfo->pSrcBlock->pDataBlock, pFillInfo->srcTsSlotId);
26,419✔
378

379
  int32_t step = GET_FORWARD_DIRECTION_FACTOR(pFillInfo->order);
26,419✔
380
  bool    ascFill = FILL_IS_ASC_FILL(pFillInfo);
26,419✔
381

382
  while (pFillInfo->numOfCurrent < outputRows) {
9,304,184!
383
    int64_t ts = ((int64_t*)pTsCol->pData)[pFillInfo->index];
9,306,484✔
384

385
    // set the next value for interpolation
386
    if (pFillInfo->currentKey < ts && ascFill) {
9,966,487!
387
      SRowVal* pRVal = pFillInfo->type == TSDB_FILL_NEXT ? &pFillInfo->next : &pFillInfo->prev;
660,035✔
388
      code = copyCurrentRowIntoBuf(pFillInfo, pFillInfo->index, pRVal, false);
660,035✔
389
      QUERY_CHECK_CODE(code, lino, _end);
660,003!
390
    } else if (pFillInfo->currentKey > ts && !ascFill) {
8,646,449!
391
      SRowVal* pRVal = pFillInfo->type == TSDB_FILL_NEXT ? &pFillInfo->prev : &pFillInfo->next;
228,819✔
392
      code = copyCurrentRowIntoBuf(pFillInfo, pFillInfo->index, pRVal, false);
228,819✔
393
      QUERY_CHECK_CODE(code, lino, _end);
228,819!
394
    }
395

396
    if (((pFillInfo->currentKey < ts && ascFill) || (pFillInfo->currentKey > ts && !ascFill)) &&
9,306,452!
397
        pFillInfo->numOfCurrent < outputRows) {
888,822✔
398
      // fill the gap between two input rows
399
      while (((pFillInfo->currentKey < ts && ascFill) || (pFillInfo->currentKey > ts && !ascFill)) &&
8,769,834!
400
             pFillInfo->numOfCurrent < outputRows) {
7,882,479✔
401
        doFillOneRow(pFillInfo, pBlock, pFillInfo->pSrcBlock, ts, false);
7,880,978✔
402
      }
403

404
      // output buffer is full, abort
405
      if (pFillInfo->numOfCurrent == outputRows) {
888,856✔
406
        pFillInfo->numOfTotal += pFillInfo->numOfCurrent;
1,580✔
407
        goto _end;
1,580✔
408
      }
409
    } else {
410
      QUERY_CHECK_CONDITION((pFillInfo->currentKey == ts), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
8,417,631!
411
      int32_t index = pBlock->info.rows;
8,417,631✔
412

413
      int32_t nextRowIndex = pFillInfo->index + 1;
8,417,631✔
414
      if (pFillInfo->type == TSDB_FILL_NEXT) {
8,417,631✔
415
        if ((pFillInfo->index + 1) < pFillInfo->numOfRows) {
312✔
416
          code = copyCurrentRowIntoBuf(pFillInfo, nextRowIndex, &pFillInfo->next, false);
244✔
417
          QUERY_CHECK_CODE(code, lino, _end);
244!
418
        } else {
419
          // reset to null after last row
420
          code = copyCurrentRowIntoBuf(pFillInfo, nextRowIndex, &pFillInfo->next, true);
68✔
421
          QUERY_CHECK_CODE(code, lino, _end);
68!
422
        }
423
      }
424
      if (pFillInfo->type == TSDB_FILL_PREV) {
8,417,631✔
425
        if (nextRowIndex + 1 >= pFillInfo->numOfRows && !FILL_IS_ASC_FILL(pFillInfo)) {
10,515✔
426
          code = copyCurrentRowIntoBuf(pFillInfo, nextRowIndex, &pFillInfo->next, true);
4✔
427
          QUERY_CHECK_CODE(code, lino, _end);
4!
428
        }
429
      }
430

431
      // copy rows to dst buffer
432
      for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
29,966,843✔
433
        SFillColInfo* pCol = &pFillInfo->pFillCol[i];
21,611,427✔
434

435
        int32_t dstSlotId = GET_DEST_SLOT_ID(pCol);
21,611,427✔
436

437
        SColumnInfoData* pDst = taosArrayGet(pBlock->pDataBlock, dstSlotId);
21,611,427✔
438
        SColumnInfoData* pSrc = taosArrayGet(pFillInfo->pSrcBlock->pDataBlock, dstSlotId);
21,458,968✔
439

440
        char* src = colDataGetData(pSrc, pFillInfo->index);
21,366,247!
441
        if (!colDataIsNull_s(pSrc, pFillInfo->index)) {
42,732,494✔
442
          code = colDataSetVal(pDst, index, src, false);
21,323,572✔
443
          QUERY_CHECK_CODE(code, lino, _end);
21,707,090!
444
          SRowVal* pRVal = &pFillInfo->prev;
21,707,090✔
445
          saveColData(pRVal->pRowVal, i, src, false);
21,707,090✔
446
          if (pFillInfo->srcTsSlotId == dstSlotId) {
21,524,236✔
447
            pRVal->key = *(int64_t*)src;
8,370,557✔
448
          }
449
        } else {  // the value is null
450
          if (pDst->info.type == TSDB_DATA_TYPE_TIMESTAMP) {
42,675!
451
            code = colDataSetVal(pDst, index, (const char*)&pFillInfo->currentKey, false);
×
452
            QUERY_CHECK_CODE(code, lino, _end);
×
453
          } else {  // i > 0 and data is null , do interpolation
454
            if (pFillInfo->type == TSDB_FILL_PREV) {
42,675✔
455
              SArray*     p = FILL_IS_ASC_FILL(pFillInfo) ? pFillInfo->prev.pRowVal : pFillInfo->next.pRowVal;
116!
456
              SGroupKeys* pKey = taosArrayGet(p, i);
116✔
457
              QUERY_CHECK_NULL(pKey, code, lino, _end, terrno);
116!
458
              code = doSetVal(pDst, index, pKey);
116✔
459
              QUERY_CHECK_CODE(code, lino, _end);
116!
460
            } else if (pFillInfo->type == TSDB_FILL_LINEAR) {
42,559✔
461
              bool isNull = colDataIsNull_s(pSrc, pFillInfo->index);
200!
462
              code = colDataSetVal(pDst, index, src, isNull);
200✔
463
              QUERY_CHECK_CODE(code, lino, _end);
200!
464

465
              SArray* p = pFillInfo->prev.pRowVal;
200✔
466
              saveColData(p, i, src, isNull);  // todo:
200✔
467
            } else if (pFillInfo->type == TSDB_FILL_NULL || pFillInfo->type == TSDB_FILL_NULL_F) {
42,359!
468
              colDataSetNULL(pDst, index);
×
469
            } else if (pFillInfo->type == TSDB_FILL_NEXT) {
50,258✔
470
              SArray*     p = FILL_IS_ASC_FILL(pFillInfo) ? pFillInfo->next.pRowVal : pFillInfo->prev.pRowVal;
33!
471
              SGroupKeys* pKey = taosArrayGet(p, i);
33✔
472
              QUERY_CHECK_NULL(pKey, code, lino, _end, terrno);
33!
473
              code = doSetVal(pDst, index, pKey);
33✔
474
              QUERY_CHECK_CODE(code, lino, _end);
33!
475
            } else {
476
              SVariant* pVar = &pFillInfo->pFillCol[i].fillVal;
50,225✔
477
              code = doSetUserSpecifiedValue(pDst, pVar, index, pFillInfo->currentKey);
50,225✔
478
              QUERY_CHECK_CODE(code, lino, _end);
50,225!
479
            }
480
          }
481
        }
482
      }
483

484
      // set the tag value for final result
485
      SInterval* pInterval = &pFillInfo->interval;
8,355,416✔
486
      pFillInfo->currentKey =
8,415,326✔
487
          taosTimeAdd(pFillInfo->currentKey, pInterval->sliding * step, pInterval->slidingUnit, pInterval->precision);
8,355,416✔
488

489
      pBlock->info.rows += 1;
8,415,326✔
490
      pFillInfo->index += 1;
8,415,326✔
491
      pFillInfo->numOfCurrent += 1;
8,415,326✔
492
    }
493

494
    if (pFillInfo->index >= pFillInfo->numOfRows || pFillInfo->numOfCurrent >= outputRows) {
9,302,602✔
495
      pFillInfo->numOfTotal += pFillInfo->numOfCurrent;
24,837✔
496
      goto _end;
24,837✔
497
    }
498
  }
499

UNCOV
500
_end:
×
501
  if (code != TSDB_CODE_SUCCESS) {
24,117!
502
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
503
  }
504
  return code;
26,417✔
505
}
506

507
static void saveColData(SArray* rowBuf, int32_t columnIndex, const char* src, bool isNull) {
22,604,953✔
508
  SGroupKeys* pKey = taosArrayGet(rowBuf, columnIndex);
22,604,953✔
509
  if (isNull) {
22,401,222✔
510
    pKey->isNull = true;
854✔
511
  } else {
512
    if (IS_VAR_DATA_TYPE(pKey->type)) {
22,400,368!
513
      memcpy(pKey->pData, src, varDataTLen(src));
1,576,350✔
514
    } else {
515
      memcpy(pKey->pData, src, pKey->bytes);
20,824,018✔
516
    }
517
    pKey->isNull = false;
22,400,368✔
518
  }
519
}
22,401,222✔
520

521
static int32_t appendFilledResult(SFillInfo* pFillInfo, SSDataBlock* pBlock, int64_t resultCapacity) {
19,995✔
522
  int32_t code = TSDB_CODE_SUCCESS;
19,995✔
523
  int32_t lino = 0;
19,995✔
524
  /*
525
   * These data are generated according to fill strategy, since the current timestamp is out of the time window of
526
   * real result set. Note that we need to keep the direct previous result rows, to generated the filled data.
527
   */
528
  pFillInfo->numOfCurrent = 0;
19,995✔
529
  while (pFillInfo->numOfCurrent < resultCapacity) {
880,507✔
530
    doFillOneRow(pFillInfo, pBlock, pFillInfo->pSrcBlock, pFillInfo->start, true);
860,512✔
531
  }
532

533
  pFillInfo->numOfTotal += pFillInfo->numOfCurrent;
19,995✔
534

535
  QUERY_CHECK_CONDITION((pFillInfo->numOfCurrent == resultCapacity), code, lino, _end,
19,995!
536
                        TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
537

538
_end:
19,995✔
539
  if (code != TSDB_CODE_SUCCESS) {
19,995!
540
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
541
  }
542
  return code;
19,995✔
543
}
544

545
static int32_t taosNumOfRemainRows(SFillInfo* pFillInfo) {
182,070✔
546
  if (pFillInfo->numOfRows == 0 || (pFillInfo->numOfRows > 0 && pFillInfo->index >= pFillInfo->numOfRows)) {
182,070!
547
    return 0;
127,712✔
548
  }
549

550
  return pFillInfo->numOfRows - pFillInfo->index;
54,358✔
551
}
552

553
int32_t taosCreateFillInfo(TSKEY skey, int32_t numOfFillCols, int32_t numOfNotFillCols, int32_t fillNullCols,
15,651✔
554
                           int32_t capacity, SInterval* pInterval, int32_t fillType, struct SFillColInfo* pCol,
555
                           int32_t primaryTsSlotId, int32_t order, const char* id, SExecTaskInfo* pTaskInfo,
556
                           SFillInfo** ppFillInfo) {
557
  int32_t code = TSDB_CODE_SUCCESS;
15,651✔
558
  int32_t lino = 0;
15,651✔
559
  if (fillType == TSDB_FILL_NONE) {
15,651!
560
    (*ppFillInfo) = NULL;
×
561
    return code;
×
562
  }
563

564
  SFillInfo* pFillInfo = taosMemoryCalloc(1, sizeof(SFillInfo));
15,651✔
565
  QUERY_CHECK_NULL(pFillInfo, code, lino, _end, terrno);
15,656!
566

567
  pFillInfo->order = order;
15,656✔
568
  pFillInfo->srcTsSlotId = primaryTsSlotId;
15,656✔
569

570
  for (int32_t i = 0; i < numOfNotFillCols; ++i) {
16,209✔
571
    SFillColInfo* p = &pCol[i + numOfFillCols];
16,208✔
572
    int32_t       srcSlotId = GET_DEST_SLOT_ID(p);
16,208✔
573
    if (srcSlotId == primaryTsSlotId) {
16,208✔
574
      pFillInfo->tsSlotId = i + numOfFillCols;
15,655✔
575
      break;
15,655✔
576
    }
577
  }
578

579
  taosResetFillInfo(pFillInfo, skey);
15,656✔
580

581
  pFillInfo->type = fillType;
15,655✔
582
  pFillInfo->pFillCol = pCol;
15,655✔
583
  pFillInfo->numOfCols = numOfFillCols + numOfNotFillCols + fillNullCols;
15,655✔
584
  pFillInfo->alloc = capacity;
15,655✔
585
  pFillInfo->id = id;
15,655✔
586
  pFillInfo->interval = *pInterval;
15,655✔
587

588
  pFillInfo->next.pRowVal = taosArrayInit(pFillInfo->numOfCols, sizeof(SGroupKeys));
15,655✔
589
  QUERY_CHECK_NULL(pFillInfo->next.pRowVal, code, lino, _end, terrno);
15,656!
590

591
  pFillInfo->prev.pRowVal = taosArrayInit(pFillInfo->numOfCols, sizeof(SGroupKeys));
15,656✔
592
  QUERY_CHECK_NULL(pFillInfo->prev.pRowVal, code, lino, _end, terrno);
15,656!
593

594
  code = initBeforeAfterDataBuf(pFillInfo);
15,656✔
595
  QUERY_CHECK_CODE(code, lino, _end);
15,654!
596

597
  pFillInfo->pTaskInfo = pTaskInfo;
15,654✔
598

599
_end:
15,654✔
600
  if (code != TSDB_CODE_SUCCESS) {
15,654!
601
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
602
    pFillInfo = taosDestroyFillInfo(pFillInfo);
×
603
  }
604
  (*ppFillInfo) = pFillInfo;
15,654✔
605
  return code;
15,654✔
606
}
607

608
void taosResetFillInfo(SFillInfo* pFillInfo, TSKEY startTimestamp) {
22,868✔
609
  pFillInfo->start = startTimestamp;
22,868✔
610
  pFillInfo->currentKey = startTimestamp;
22,868✔
611
  pFillInfo->end = startTimestamp;
22,868✔
612
  pFillInfo->index = -1;
22,868✔
613
  pFillInfo->numOfRows = 0;
22,868✔
614
  pFillInfo->numOfCurrent = 0;
22,868✔
615
  pFillInfo->numOfTotal = 0;
22,868✔
616
}
22,868✔
617

618
void* taosDestroyFillInfo(SFillInfo* pFillInfo) {
15,656✔
619
  if (pFillInfo == NULL) {
15,656!
620
    return NULL;
×
621
  }
622
  for (int32_t i = 0; i < taosArrayGetSize(pFillInfo->prev.pRowVal); ++i) {
57,728✔
623
    SGroupKeys* pKey = taosArrayGet(pFillInfo->prev.pRowVal, i);
42,071✔
624
    if (pKey) taosMemoryFree(pKey->pData);
42,070!
625
  }
626
  taosArrayDestroy(pFillInfo->prev.pRowVal);
15,655✔
627
  for (int32_t i = 0; i < taosArrayGetSize(pFillInfo->next.pRowVal); ++i) {
57,726✔
628
    SGroupKeys* pKey = taosArrayGet(pFillInfo->next.pRowVal, i);
42,071✔
629
    if (pKey) taosMemoryFree(pKey->pData);
42,069!
630
  }
631
  taosArrayDestroy(pFillInfo->next.pRowVal);
15,654✔
632

633
  //  for (int32_t i = 0; i < pFillInfo->numOfTags; ++i) {
634
  //    taosMemoryFreeClear(pFillInfo->pTags[i].tagVal);
635
  //  }
636

637
  // free pFillCol
638
  if (pFillInfo->pFillCol) {
15,656!
639
    for (int32_t i = 0; i < pFillInfo->numOfCols; i++) {
57,729✔
640
      SFillColInfo* pCol = &pFillInfo->pFillCol[i];
42,073✔
641
      if (!pCol->notFillCol) {
42,073✔
642
        if (pCol->fillVal.nType == TSDB_DATA_TYPE_VARBINARY || pCol->fillVal.nType == TSDB_DATA_TYPE_VARCHAR ||
25,521✔
643
            pCol->fillVal.nType == TSDB_DATA_TYPE_NCHAR || pCol->fillVal.nType == TSDB_DATA_TYPE_JSON) {
25,473!
644
          if (pCol->fillVal.pz) {
87!
645
            taosMemoryFree(pCol->fillVal.pz);
87✔
646
            pCol->fillVal.pz = NULL;
87✔
647
          }
648
        }
649
      }
650
    }
651
  }
652

653
  taosMemoryFreeClear(pFillInfo->pTags);
15,656!
654
  taosMemoryFreeClear(pFillInfo->pFillCol);
15,656!
655
  taosMemoryFreeClear(pFillInfo);
15,656!
656
  return NULL;
15,656✔
657
}
658

659
void taosFillSetStartInfo(SFillInfo* pFillInfo, int32_t numOfRows, TSKEY endKey) {
44,736✔
660
  if (pFillInfo->type == TSDB_FILL_NONE) {
44,736!
661
    return;
×
662
  }
663

664
  // the endKey is now the aligned time window value. truncate time window isn't correct.
665
  pFillInfo->end = endKey;
44,736✔
666
  pFillInfo->index = 0;
44,736✔
667
  pFillInfo->numOfRows = numOfRows;
44,736✔
668
}
669

670
void taosFillSetInputDataBlock(SFillInfo* pFillInfo, const SSDataBlock* pInput) {
24,891✔
671
  pFillInfo->pSrcBlock = (SSDataBlock*)pInput;
24,891✔
672
}
24,891✔
673

674
void taosFillUpdateStartTimestampInfo(SFillInfo* pFillInfo, int64_t ts) {
14,013✔
675
  pFillInfo->start = ts;
14,013✔
676
  pFillInfo->currentKey = ts;
14,013✔
677
}
14,013✔
678

679
bool taosFillNotStarted(const SFillInfo* pFillInfo) { return pFillInfo->start == pFillInfo->currentKey; }
9,363✔
680

681
bool taosFillHasMoreResults(SFillInfo* pFillInfo) {
53,423✔
682
  int32_t remain = taosNumOfRemainRows(pFillInfo);
53,423✔
683
  if (remain > 0) {
53,423✔
684
    return true;
1,528✔
685
  }
686

687
  bool ascFill = FILL_IS_ASC_FILL(pFillInfo);
51,895✔
688
  if (pFillInfo->numOfTotal > 0 &&
51,895✔
689
      (((pFillInfo->end > pFillInfo->start) && ascFill) || (pFillInfo->end < pFillInfo->start && !ascFill))) {
36,243!
690
    return getNumOfResultsAfterFillGap(pFillInfo, pFillInfo->end, 4096) > 0;
35,832✔
691
  }
692

693
  return false;
16,063✔
694
}
695

696
int64_t getNumOfResultsAfterFillGap(SFillInfo* pFillInfo, TSKEY ekey, int32_t maxNumOfRows) {
82,245✔
697
  int32_t numOfRows = taosNumOfRemainRows(pFillInfo);
82,245✔
698

699
  TSKEY ekey1 = ekey;
82,244✔
700

701
  int64_t numOfRes = -1;
82,244✔
702
  if (numOfRows > 0) {  // still fill gap within current data block, not generating data after the result set.
82,244✔
703
    SColumnInfoData* pCol = taosArrayGet(pFillInfo->pSrcBlock->pDataBlock, pFillInfo->srcTsSlotId);
26,419✔
704
    int64_t*         tsList = (int64_t*)pCol->pData;
26,417✔
705
    TSKEY            lastKey = tsList[pFillInfo->numOfRows - 1];
26,417✔
706
    numOfRes =
26,418✔
707
        taosTimeCountIntervalForFill(lastKey, pFillInfo->currentKey, pFillInfo->interval.sliding,
26,417✔
708
                                     pFillInfo->interval.slidingUnit, pFillInfo->interval.precision, pFillInfo->order);
26,417✔
709
  } else {  // reach the end of data
710
    if ((ekey1 < pFillInfo->currentKey && FILL_IS_ASC_FILL(pFillInfo)) ||
55,825✔
711
        (ekey1 > pFillInfo->currentKey && !FILL_IS_ASC_FILL(pFillInfo))) {
6,885✔
712
      return 0;
52,862✔
713
    }
714

715
    numOfRes =
2,966✔
716
        taosTimeCountIntervalForFill(ekey1, pFillInfo->currentKey, pFillInfo->interval.sliding,
2,963✔
717
                                     pFillInfo->interval.slidingUnit, pFillInfo->interval.precision, pFillInfo->order);
2,963✔
718
  }
719

720
  return (numOfRes > maxNumOfRows) ? maxNumOfRows : numOfRes;
29,384✔
721
}
722

723
void taosGetLinearInterpolationVal(SPoint* point, int32_t outputType, SPoint* point1, SPoint* point2,
28,201,326✔
724
                                   int32_t inputType) {
725
  double v1 = -1, v2 = -1;
28,201,326✔
726
  GET_TYPED_DATA(v1, double, inputType, point1->val);
28,201,326!
727
  GET_TYPED_DATA(v2, double, inputType, point2->val);
28,201,326!
728

729
  double r = 0;
28,201,326✔
730
  if (!IS_BOOLEAN_TYPE(inputType)) {
28,201,326✔
731
    r = DO_INTERPOLATION(v1, v2, point1->key, point2->key, point->key);
28,201,306✔
732
  } else {
733
    r = (v1 < 1 || v2 < 1) ? 0 : 1;
20✔
734
  }
735
  SET_TYPED_DATA(point->val, outputType, r);
28,201,326!
736
}
28,201,326✔
737

738
int32_t taosFillResultDataBlock(SFillInfo* pFillInfo, SSDataBlock* p, int32_t capacity) {
46,413✔
739
  int32_t code = TSDB_CODE_SUCCESS;
46,413✔
740
  int32_t lino = 0;
46,413✔
741
  int32_t remain = taosNumOfRemainRows(pFillInfo);
46,413✔
742

743
  int64_t numOfRes = getNumOfResultsAfterFillGap(pFillInfo, pFillInfo->end, capacity);
46,413✔
744
  QUERY_CHECK_CONDITION((numOfRes <= capacity), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
46,414!
745

746
  // no data existed for fill operation now, append result according to the fill strategy
747
  if (remain == 0) {
46,414✔
748
    code = appendFilledResult(pFillInfo, p, numOfRes);
19,995✔
749
    QUERY_CHECK_CODE(code, lino, _end);
19,995!
750
  } else {
751
    code = fillResultImpl(pFillInfo, p, (int32_t)numOfRes);
26,419✔
752
    QUERY_CHECK_CODE(code, lino, _end);
26,417!
753
    QUERY_CHECK_CONDITION((numOfRes == pFillInfo->numOfCurrent), code, lino, _end, TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR);
26,417!
754
  }
755

756
  qDebug("fill:%p, generated fill result, src block:%d, index:%d, brange:%" PRId64 "-%" PRId64 ", currentKey:%" PRId64
46,412✔
757
         ", current : % d, total : % d, %s",
758
         pFillInfo, pFillInfo->numOfRows, pFillInfo->index, pFillInfo->start, pFillInfo->end, pFillInfo->currentKey,
759
         pFillInfo->numOfCurrent, pFillInfo->numOfTotal, pFillInfo->id);
760
_end:
39,473✔
761
  if (code != TSDB_CODE_SUCCESS) {
46,412!
762
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
763
  }
764
  return code;
46,412✔
765
}
766

767
int64_t getFillInfoStart(struct SFillInfo* pFillInfo) { return pFillInfo->start; }
7,215✔
768

769
SFillColInfo* createFillColInfo(SExprInfo* pExpr, int32_t numOfFillExpr, SExprInfo* pNotFillExpr,
19,181✔
770
                                int32_t numOfNoFillExpr, SExprInfo* pFillNullExpr, int32_t numOfFillNullExpr,
771
                                const struct SNodeListNode* pValNode) {
772
  int32_t       code = TSDB_CODE_SUCCESS;
19,181✔
773
  int32_t       lino = 0;
19,181✔
774
  SFillColInfo* pFillCol = taosMemoryCalloc(numOfFillExpr + numOfNoFillExpr + numOfFillNullExpr, sizeof(SFillColInfo));
19,181✔
775
  if (pFillCol == NULL) {
19,186!
776
    return NULL;
×
777
  }
778

779
  size_t len = (pValNode != NULL) ? LIST_LENGTH(pValNode->pNodeList) : 0;
19,186!
780
  for (int32_t i = 0; i < numOfFillExpr; ++i) {
56,414✔
781
    SExprInfo* pExprInfo = &pExpr[i];
37,229✔
782
    pFillCol[i].pExpr = pExprInfo;
37,229✔
783
    pFillCol[i].notFillCol = false;
37,229✔
784

785
    // todo refactor
786
    if (len > 0) {
37,229✔
787
      // if the user specified value is less than the column, alway use the last one as the fill value
788
      int32_t index = (i >= len) ? (len - 1) : i;
4,860✔
789

790
      SValueNode* pv = (SValueNode*)nodesListGetNode(pValNode->pNodeList, index);
4,860✔
791
      QUERY_CHECK_NULL(pv, code, lino, _end, terrno);
4,859!
792
      code = nodesValueNodeToVariant(pv, &pFillCol[i].fillVal);
4,859✔
793
      QUERY_CHECK_CODE(code, lino, _end);
4,859!
794
    }
795
    if (TSDB_CODE_SUCCESS != code) {
37,228!
796
      goto _end;
×
797
    }
798
  }
799
  pFillCol->numOfFillExpr = numOfFillExpr;
19,185✔
800

801
  for (int32_t i = 0; i < numOfNoFillExpr; ++i) {
35,947✔
802
    SExprInfo* pExprInfo = &pNotFillExpr[i];
16,762✔
803
    pFillCol[i + numOfFillExpr].pExpr = pExprInfo;
16,762✔
804
    pFillCol[i + numOfFillExpr].notFillCol = true;
16,762✔
805
  }
806

807
  for (int32_t i = 0; i < numOfFillNullExpr; ++i) {
19,225✔
808
    SExprInfo* pExprInfo = &pFillNullExpr[i];
40✔
809
    pFillCol[i + numOfFillExpr + numOfNoFillExpr].pExpr = pExprInfo;
40✔
810
    pFillCol[i + numOfFillExpr + numOfNoFillExpr].notFillCol = true;
40✔
811
    pFillCol[i + numOfFillExpr + numOfNoFillExpr].fillNull = true;
40✔
812
  }
813

814
  return pFillCol;
19,185✔
815

816
_end:
×
817
  for (int32_t i = 0; i < numOfFillExpr; ++i) {
×
818
    taosVariantDestroy(&pFillCol[i].fillVal);
×
819
  }
820
  taosMemoryFree(pFillCol);
×
821
  if (code != TSDB_CODE_SUCCESS) {
×
822
    qError("%s failed at line %d since %s", __func__, lino, tstrerror(code));
×
823
  }
824
  return NULL;
×
825
}
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