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

taosdata / TDengine / #3911

24 Apr 2025 11:36PM UTC coverage: 53.735% (-1.6%) from 55.295%
#3911

push

travis-ci

happyguoxy
Sync branches at 2025-04-25 07:35

170049 of 316459 relevant lines covered (53.73%)

1192430.54 hits per line

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

62.42
/source/libs/parser/src/parUtil.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 "parUtil.h"
17
#include "cJSON.h"
18
#include "querynodes.h"
19
#include "tarray.h"
20
#include "tlog.h"
21
#include "decimal.h"
22

23
#define USER_AUTH_KEY_MAX_LEN TSDB_USER_LEN + TSDB_TABLE_FNAME_LEN + 2
24

25
const void* nullPointer = NULL;
26

27
static char* getSyntaxErrFormat(int32_t errCode) {
338✔
28
  switch (errCode) {
338✔
29
    case TSDB_CODE_PAR_SYNTAX_ERROR:
30✔
30
      return "syntax error near \"%s\"";
30✔
31
    case TSDB_CODE_PAR_INCOMPLETE_SQL:
×
32
      return "Incomplete SQL statement";
×
33
    case TSDB_CODE_PAR_INVALID_COLUMN:
24✔
34
      return "Invalid column name: %s";
24✔
35
    case TSDB_CODE_PAR_TABLE_NOT_EXIST:
4✔
36
      return "Table does not exist: %s";
4✔
37
    case TSDB_CODE_PAR_GET_META_ERROR:
26✔
38
      return "Fail to get table info, error: %s";
26✔
39
    case TSDB_CODE_PAR_AMBIGUOUS_COLUMN:
12✔
40
      return "Column ambiguously defined: %s";
12✔
41
    case TSDB_CODE_PAR_WRONG_VALUE_TYPE:
4✔
42
      return "Invalid value type: %s";
4✔
43
    case TSDB_CODE_PAR_INVALID_VARBINARY:
×
44
      return "Invalid varbinary value: %s";
×
45
    case TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION:
8✔
46
      return "There mustn't be aggregation";
8✔
47
    case TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT:
8✔
48
      return "ORDER BY / GROUP BY item must be the number of a SELECT-list expression";
8✔
49
    case TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION:
28✔
50
      return "Not a GROUP BY expression";
28✔
51
    case TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION:
12✔
52
      return "Not SELECTed expression";
12✔
53
    case TSDB_CODE_PAR_NOT_SINGLE_GROUP:
66✔
54
      return "Not a single-group group function";
66✔
55
    case TSDB_CODE_PAR_TAGS_NOT_MATCHED:
×
56
      return "Tags number not matched";
×
57
    case TSDB_CODE_PAR_INVALID_TAG_NAME:
1✔
58
      return "Invalid tag name: %s";
1✔
59
    case TSDB_CODE_PAR_NAME_OR_PASSWD_TOO_LONG:
×
60
      return "Name or password too long";
×
61
    case TSDB_CODE_PAR_PASSWD_TOO_SHORT_OR_EMPTY:
1✔
62
      return "Password too short or empty";
1✔
63
    case TSDB_CODE_PAR_INVALID_PORT:
×
64
      return "Port should be an integer that is less than 65535 and greater than 0";
×
65
    case TSDB_CODE_PAR_INVALID_ENDPOINT:
×
66
      return "Endpoint should be in the format of 'fqdn:port'";
×
67
    case TSDB_CODE_PAR_EXPRIE_STATEMENT:
9✔
68
      return "This statement is no longer supported";
9✔
69
    case TSDB_CODE_PAR_INTER_VALUE_TOO_SMALL:
×
70
      return "Interval cannot be less than %d %s";
×
71
    case TSDB_CODE_PAR_INTER_VALUE_TOO_BIG:
×
72
      return "Interval cannot be more than %d %s";
×
73
    case TSDB_CODE_PAR_DB_NOT_SPECIFIED:
×
74
      return "Database not specified";
×
75
    case TSDB_CODE_PAR_INVALID_IDENTIFIER_NAME:
1✔
76
      return "Invalid identifier name: %s";
1✔
77
    case TSDB_CODE_PAR_CORRESPONDING_STABLE_ERR:
×
78
      return "Corresponding super table not in this db";
×
79
    case TSDB_CODE_PAR_GROUPBY_WINDOW_COEXIST:
×
80
      return "GROUP BY and WINDOW-clause can't be used together";
×
81
    case TSDB_CODE_PAR_AGG_FUNC_NESTING:
×
82
      return "Aggregate functions do not support nesting";
×
83
    case TSDB_CODE_PAR_INVALID_STATE_WIN_TYPE:
×
84
      return "Only support STATE_WINDOW on integer/bool/varchar column";
×
85
    case TSDB_CODE_PAR_INVALID_STATE_WIN_COL:
×
86
      return "Not support STATE_WINDOW on tag column";
×
87
    case TSDB_CODE_PAR_INVALID_STATE_WIN_TABLE:
×
88
      return "STATE_WINDOW not support for super table query";
×
89
    case TSDB_CODE_PAR_INTER_SESSION_GAP:
×
90
      return "SESSION gap should be fixed time window, and greater than 0";
×
91
    case TSDB_CODE_PAR_INTER_SESSION_COL:
×
92
      return "Only support SESSION on primary timestamp column";
×
93
    case TSDB_CODE_PAR_INTER_OFFSET_NEGATIVE:
×
94
      return "Interval offset cannot be negative";
×
95
    case TSDB_CODE_PAR_INTER_OFFSET_UNIT:
×
96
      return "Cannot use 'year' as offset when interval is 'month'";
×
97
    case TSDB_CODE_PAR_INTER_OFFSET_TOO_BIG:
×
98
      return "Interval offset should be shorter than interval";
×
99
    case TSDB_CODE_PAR_INTER_SLIDING_UNIT:
×
100
      return "Does not support sliding when interval is natural month/year";
×
101
    case TSDB_CODE_PAR_INTER_SLIDING_TOO_BIG:
×
102
      return "sliding value no larger than the interval value";
×
103
    case TSDB_CODE_PAR_INTER_SLIDING_TOO_SMALL:
×
104
      return "sliding value can not less than 1%% of interval value";
×
105
    case TSDB_CODE_PAR_ONLY_ONE_JSON_TAG:
×
106
      return "Only one tag if there is a json tag";
×
107
    case TSDB_CODE_PAR_INCORRECT_NUM_OF_COL:
×
108
      return "Query block has incorrect number of result columns";
×
109
    case TSDB_CODE_PAR_INCORRECT_TIMESTAMP_VAL:
×
110
      return "Incorrect TIMESTAMP value: %s";
×
111
    case TSDB_CODE_PAR_OFFSET_LESS_ZERO:
×
112
      return "soffset/offset can not be less than 0";
×
113
    case TSDB_CODE_PAR_SLIMIT_LEAK_PARTITION_GROUP_BY:
×
114
      return "slimit/soffset only available for PARTITION/GROUP BY query";
×
115
    case TSDB_CODE_PAR_INVALID_TOPIC_QUERY:
×
116
      return "Invalid topic query";
×
117
    case TSDB_CODE_PAR_INVALID_DROP_STABLE:
×
118
      return "Cannot drop super table in batch";
×
119
    case TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE:
4✔
120
      return "Start(end) time of query range required or time range too large";
4✔
121
    case TSDB_CODE_PAR_DUPLICATED_COLUMN:
×
122
      return "Duplicated column names";
×
123
    case TSDB_CODE_PAR_INVALID_TAGS_LENGTH:
×
124
      return "Tags length exceeds max length %d";
×
125
    case TSDB_CODE_PAR_INVALID_ROW_LENGTH:
×
126
      return "Row length exceeds max length %d";
×
127
    case TSDB_CODE_PAR_INVALID_COLUMNS_NUM:
4✔
128
      return "Illegal number of columns";
4✔
129
    case TSDB_CODE_PAR_TOO_MANY_COLUMNS:
4✔
130
      return "Too many columns";
4✔
131
    case TSDB_CODE_PAR_INVALID_FIRST_COLUMN:
×
132
      return "First column must be timestamp";
×
133
    case TSDB_CODE_PAR_INVALID_VAR_COLUMN_LEN:
×
134
      return "Invalid column length for var length type";
×
135
    case TSDB_CODE_PAR_INVALID_TAGS_NUM:
×
136
      return "Invalid number of tag columns";
×
137
    case TSDB_CODE_PAR_INVALID_INTERNAL_PK:
×
138
      return "Invalid _c0 or _rowts expression";
×
139
    case TSDB_CODE_PAR_INVALID_TIMELINE_FUNC:
×
140
      return "Invalid timeline function";
×
141
    case TSDB_CODE_PAR_INVALID_PASSWD:
×
142
      return "Invalid password";
×
143
    case TSDB_CODE_PAR_INVALID_ALTER_TABLE:
24✔
144
      return "Invalid alter table statement";
24✔
145
    case TSDB_CODE_PAR_CANNOT_DROP_PRIMARY_KEY:
×
146
      return "Primary timestamp column cannot be dropped";
×
147
    case TSDB_CODE_PAR_INVALID_MODIFY_COL:
8✔
148
      return "Only varbinary/binary/nchar/geometry column length could be modified, and the length can only be "
8✔
149
             "increased, not decreased";
150
    case TSDB_CODE_PAR_INVALID_TBNAME:
8✔
151
      return "Invalid tbname pseudo column";
8✔
152
    case TSDB_CODE_PAR_INVALID_FUNCTION_NAME:
×
153
      return "Invalid function name";
×
154
    case TSDB_CODE_PAR_COMMENT_TOO_LONG:
×
155
      return "Comment too long";
×
156
    case TSDB_CODE_PAR_NOT_ALLOWED_FUNC:
8✔
157
      return "Some functions are allowed only in the SELECT list of a query. "
8✔
158
             "And, cannot be mixed with other non scalar functions or columns.";
159
    case TSDB_CODE_PAR_NOT_ALLOWED_WIN_QUERY:
4✔
160
      return "Window query not supported, since not valid primary timestamp column as input";
4✔
161
    case TSDB_CODE_PAR_INVALID_DROP_COL:
×
162
      return "No columns can be dropped";
×
163
    case TSDB_CODE_PAR_INVALID_COL_JSON:
×
164
      return "Only tag can be json type";
×
165
    case TSDB_CODE_PAR_VALUE_TOO_LONG:
4✔
166
      return "Value too long for column/tag: %s";
4✔
167
    case TSDB_CODE_PAR_INVALID_DELETE_WHERE:
4✔
168
      return "The DELETE statement must only have a definite time window range";
4✔
169
    case TSDB_CODE_PAR_INVALID_REDISTRIBUTE_VG:
×
170
      return "The REDISTRIBUTE VGROUP statement only support 1 to 3 dnodes";
×
171
    case TSDB_CODE_PAR_FILL_NOT_ALLOWED_FUNC:
4✔
172
      return "%s function is not supported in fill query";
4✔
173
    case TSDB_CODE_PAR_INVALID_WINDOW_PC:
4✔
174
      return "_WSTART, _WEND and _WDURATION can only be used in window query";
4✔
175
    case TSDB_CODE_PAR_INVALID_TAGS_PC:
×
176
      return "Tags can only applied to super table and child table";
×
177
    case TSDB_CODE_PAR_WINDOW_NOT_ALLOWED_FUNC:
×
178
      return "%s function is not supported in time window query";
×
179
    case TSDB_CODE_PAR_STREAM_NOT_ALLOWED_FUNC:
4✔
180
      return "%s function is not supported in stream query";
4✔
181
    case TSDB_CODE_PAR_GROUP_BY_NOT_ALLOWED_FUNC:
×
182
      return "%s function is not supported in group query";
×
183
    case TSDB_CODE_PAR_SYSTABLE_NOT_ALLOWED_FUNC:
×
184
      return "%s function is not supported in system table query";
×
185
    case TSDB_CODE_PAR_SYSTABLE_NOT_ALLOWED:
8✔
186
      return "%s is not supported in system table query";
8✔
187
    case TSDB_CODE_PAR_INVALID_INTERP_CLAUSE:
×
188
      return "Invalid usage of RANGE clause, EVERY clause or FILL clause";
×
189
    case TSDB_CODE_PAR_INVALID_FORECAST_CLAUSE:
×
190
      return "Invalid usage of forecast clause";
×
191
    case TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN:
×
192
      return "No valid function in window query";
×
193
    case TSDB_CODE_PAR_INVALID_OPTR_USAGE:
8✔
194
      return "Invalid usage of expr: %s";
8✔
195
    case TSDB_CODE_PAR_INVALID_IP_RANGE:
×
196
      return "invalid ip range";
×
197
    case TSDB_CODE_OUT_OF_MEMORY:
×
198
      return "Out of memory";
×
199
    case TSDB_CODE_PAR_ORDERBY_AMBIGUOUS:
×
200
      return "ORDER BY \"%s\" is ambiguous";
×
201
    case TSDB_CODE_PAR_NOT_SUPPORT_MULTI_RESULT:
4✔
202
      return "Operator not supported multi result: %s";
4✔
203
    case TSDB_CODE_PAR_INVALID_WJOIN_HAVING_EXPR:
×
204
      return "Not supported window join having expr";
×
205
    case TSDB_CODE_PAR_INVALID_WIN_OFFSET_UNIT:
×
206
      return "Invalid WINDOW_OFFSET unit \"%c\"";
×
207
    case TSDB_CODE_PAR_VALID_PRIM_TS_REQUIRED:
×
208
      return "Valid primary timestamp required";
×
209
    case TSDB_CODE_PAR_NOT_WIN_FUNC:
×
210
      return "Column exists for window join with aggregation functions";
×
211
    case TSDB_CODE_PAR_TAG_IS_PRIMARY_KEY:
×
212
      return "tag %s can not be composite primary key";
×
213
    case TSDB_CODE_PAR_SECOND_COL_PK:
×
214
      return "composite primary key column must be second column";
×
215
    case TSDB_CODE_PAR_COL_PK_TYPE:
×
216
      return "composite primary key column must be of type int, uint, bigint, ubigint, and varchar";
×
217
    case TSDB_CODE_PAR_INVALID_PK_OP:
×
218
      return "composite primary key column can not be added, modified, and dropped";
×
219
    case TSDB_CODE_TSMA_NAME_TOO_LONG:
×
220
      return "Tsma name too long";
×
221
    case TSDB_CODE_PAR_TBNAME_ERROR:
×
222
      return "Pseudo tag tbname not set";
×
223
    case TSDB_CODE_PAR_TBNAME_DUPLICATED:
×
224
      return "Table name:%s duplicated";
×
225
    case TSDB_CODE_PAR_TAG_NAME_DUPLICATED:
×
226
      return "Tag name:%s duplicated";
×
227
    case TSDB_CODE_PAR_NOT_ALLOWED_DIFFERENT_BY_ROW_FUNC:
×
228
      return "Some functions cannot appear in the select list at the same time";
×
229
    case TSDB_CODE_PAR_REGULAR_EXPRESSION_ERROR:
×
230
      return "Syntax error in regular expression";
×
231
    case TSDB_CODE_PAR_TRUE_FOR_NEGATIVE:
×
232
      return "True_for duration cannot be negative";
×
233
    case TSDB_CODE_PAR_TRUE_FOR_UNIT:
×
234
      return "Cannot use 'year' or 'month' as true_for duration";
×
235
    case TSDB_CODE_PAR_INVALID_REF_COLUMN:
×
236
      return "Invalid virtual table's ref column";
×
237
    case TSDB_CODE_PAR_INVALID_TABLE_TYPE:
×
238
      return "Invalid table type";
×
239
    case TSDB_CODE_PAR_INVALID_REF_COLUMN_TYPE:
×
240
      return "Invalid virtual table's ref column type";
×
241
    case TSDB_CODE_PAR_MISMATCH_STABLE_TYPE:
×
242
      return "Create child table using virtual super table";
×
243
    default:
×
244
      return "Unknown error";
×
245
  }
246
}
247

248
int32_t generateSyntaxErrMsg(SMsgBuf* pBuf, int32_t errCode, ...) {
338✔
249
  va_list vArgList;
250
  va_start(vArgList, errCode);
338✔
251
  (void)vsnprintf(pBuf->buf, pBuf->len, getSyntaxErrFormat(errCode), vArgList);
338✔
252
  va_end(vArgList);
338✔
253
  return errCode;
338✔
254
}
255

256
int32_t generateSyntaxErrMsgExt(SMsgBuf* pBuf, int32_t errCode, const char* pFormat, ...) {
150✔
257
  va_list vArgList;
258
  va_start(vArgList, pFormat);
150✔
259
  (void)vsnprintf(pBuf->buf, pBuf->len, pFormat, vArgList);
150✔
260
  va_end(vArgList);
150✔
261
  return errCode;
150✔
262
}
263

264
int32_t buildInvalidOperationMsg(SMsgBuf* pBuf, const char* msg) {
9✔
265
  if (pBuf->buf) {
9✔
266
    tstrncpy(pBuf->buf, msg, pBuf->len);
9✔
267
  }
268

269
  return TSDB_CODE_TSC_INVALID_OPERATION;
9✔
270
}
271

272
int32_t buildInvalidOperationMsgExt(SMsgBuf* pBuf, const char* pFormat, ...) {
×
273
  va_list vArgList;
274
  va_start(vArgList, pFormat);
×
275
  (void)vsnprintf(pBuf->buf, pBuf->len, pFormat, vArgList);
×
276
  va_end(vArgList);
×
277
  return TSDB_CODE_TSC_INVALID_OPERATION;
×
278
}
279

280
int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr) {
81✔
281
  if (pBuf == NULL) return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
81✔
282
  const char* msgFormat1 = "syntax error near \'%s\'";
81✔
283
  const char* msgFormat2 = "syntax error near \'%s\' (%s)";
81✔
284
  const char* msgFormat3 = "%s";
81✔
285

286
  const char* prefix = "syntax error";
81✔
287
  if (sourceStr == NULL) {
81✔
288
    snprintf(pBuf->buf, pBuf->len, msgFormat1, additionalInfo);
×
289
    return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
×
290
  }
291

292
  char buf[64] = {0};  // only extract part of sql string
81✔
293
  tstrncpy(buf, sourceStr, tListLen(buf));
81✔
294

295
  if (additionalInfo != NULL) {
81✔
296
    snprintf(pBuf->buf, pBuf->len, msgFormat2, buf, additionalInfo);
81✔
297
  } else {
298
    const char* msgFormat = (0 == strncmp(sourceStr, prefix, strlen(prefix))) ? msgFormat3 : msgFormat1;
×
299
    snprintf(pBuf->buf, pBuf->len, msgFormat, buf);
×
300
  }
301

302
  return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
81✔
303
}
304

305
SSchema* getTableColumnSchema(const STableMeta* pTableMeta) { return (SSchema*)pTableMeta->schema; }
28,716,631✔
306

307
SSchemaExt* getTableColumnExtSchema(const STableMeta* pTableMeta) { return pTableMeta->schemaExt; }
27,508,711✔
308

309
static SSchema* getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex) {
50,969✔
310
  SSchema* pSchema = (SSchema*)pTableMeta->schema;
50,969✔
311
  return &pSchema[colIndex];
50,969✔
312
}
313

314
SSchema* getTableTagSchema(const STableMeta* pTableMeta) {
50,963✔
315
  return getOneColumnSchema(pTableMeta, getTableInfo(pTableMeta).numOfColumns);
50,963✔
316
}
317

318
int32_t getNumOfColumns(const STableMeta* pTableMeta) {
290✔
319
  // table created according to super table, use data from super table
320
  return getTableInfo(pTableMeta).numOfColumns;
290✔
321
}
322

323
int32_t getNumOfTags(const STableMeta* pTableMeta) { return getTableInfo(pTableMeta).numOfTags; }
50,810✔
324

325
STableComInfo getTableInfo(const STableMeta* pTableMeta) { return pTableMeta->tableInfo; }
298,170,621✔
326

327
int32_t getTableTypeFromTableNode(SNode* pTable) {
164✔
328
  if (NULL == pTable) {
164✔
329
    return -1;
×
330
  }
331
  if (QUERY_NODE_REAL_TABLE != nodeType(pTable)) {
164✔
332
    return -1;
9✔
333
  }
334
  return ((SRealTableNode*)pTable)->pMeta->tableType;
155✔
335
}
336

337
STableMeta* tableMetaDup(const STableMeta* pTableMeta) {
158,526✔
338
  int32_t numOfFields = TABLE_TOTAL_COL_NUM(pTableMeta);
158,526✔
339
  if (numOfFields > TSDB_MAX_COLUMNS || numOfFields < TSDB_MIN_COLUMNS) {
158,526✔
340
    return NULL;
×
341
  }
342

343
  bool   hasSchemaExt = pTableMeta->schemaExt == NULL ? false : true;
158,578✔
344
  size_t schemaExtSize = hasSchemaExt ? pTableMeta->tableInfo.numOfColumns * sizeof(SSchemaExt) : 0;
158,578✔
345
  bool   hasColRef = pTableMeta->colRef == NULL ? false : true;
158,578✔
346
  size_t colRefSize = hasColRef ? pTableMeta->numOfColRefs * sizeof(SColRef) : 0;
158,578✔
347

348
  size_t      size = sizeof(STableMeta) + numOfFields * sizeof(SSchema);
158,578✔
349
  STableMeta* p = taosMemoryMalloc(size + schemaExtSize + colRefSize);
158,578✔
350
  if (NULL == p) return NULL;
158,589✔
351

352
  memcpy(p, pTableMeta, colRefSize + schemaExtSize + size);
158,589✔
353
  if (hasSchemaExt) {
158,589✔
354
    p->schemaExt = (SSchemaExt*)(((char*)p) + size);
156,589✔
355
  } else {
356
    p->schemaExt = NULL;
2,000✔
357
  }
358
  if (hasColRef) {
158,589✔
359
    p->colRef = (SColRef*)(((char*)p) + size + schemaExtSize);
×
360
  } else {
361
    p->colRef = NULL;
158,589✔
362
  }
363
  return p;
158,589✔
364
}
365

366
int32_t trimString(const char* src, int32_t len, char* dst, int32_t dlen) {
41,513,588✔
367
  if (len <= 0 || dlen <= 0) return 0;
41,513,588✔
368

369
  char    delim = src[0];
41,579,683✔
370
  int32_t j = 0;
41,579,683✔
371
  for (uint32_t k = 1; k < len - 1; ++k) {
1,459,250,921✔
372
    if (j >= dlen) {
1,417,671,238✔
373
      dst[j - 1] = '\0';
×
374
      return j;
×
375
    }
376
    if (src[k] == delim && src[k + 1] == delim) {  // deal with "", ''
1,417,671,238✔
377
      dst[j] = src[k + 1];
×
378
      j++;
×
379
      k++;
×
380
      continue;
×
381
    }
382

383
    if (src[k] == '\\') {  // deal with escape character
1,417,671,238✔
384
      if (src[k + 1] == 'n') {
×
385
        dst[j] = '\n';
×
386
      } else if (src[k + 1] == 'r') {
×
387
        dst[j] = '\r';
×
388
      } else if (src[k + 1] == 't') {
×
389
        dst[j] = '\t';
×
390
      } else if (src[k + 1] == '\\') {
×
391
        dst[j] = '\\';
×
392
      } else if (src[k + 1] == '\'') {
×
393
        dst[j] = '\'';
×
394
      } else if (src[k + 1] == '"') {
×
395
        dst[j] = '"';
×
396
      } else if (src[k + 1] == '%' || src[k + 1] == '_' || src[k + 1] == 'x') {
×
397
        dst[j++] = src[k];
×
398
        dst[j] = src[k + 1];
×
399
      } else {
400
        dst[j] = src[k + 1];
×
401
      }
402
      j++;
×
403
      k++;
×
404
      continue;
×
405
    }
406

407
    dst[j] = src[k];
1,417,671,238✔
408
    j++;
1,417,671,238✔
409
  }
410
  if (j >= dlen) j = dlen - 1;
41,579,683✔
411
  dst[j] = '\0';
41,579,683✔
412
  return j;
41,579,683✔
413
}
414

415
static bool isValidateTag(char* input) {
31✔
416
  if (!input) return false;
31✔
417
  for (size_t i = 0; i < strlen(input); ++i) {
144✔
418
#ifdef WINDOWS
419
    if (input[i] < 0x20 || input[i] > 0x7E) return false;
420
#else
421
    if (isprint(input[i]) == 0) return false;
113✔
422
#endif
423
  }
424
  return true;
31✔
425
}
426

427
int32_t parseJsontoTagData(const char* json, SArray* pTagVals, STag** ppTag, void* pMsgBuf, void *charsetCxt) {
16✔
428
  int32_t   retCode = TSDB_CODE_SUCCESS;
16✔
429
  cJSON*    root = NULL;
16✔
430
  SHashObj* keyHash = NULL;
16✔
431
  int32_t   size = 0;
16✔
432
  // set json NULL data
433
  if (!json || strcasecmp(json, TSDB_DATA_NULL_STR_L) == 0 || strtrim((char*)json) == 0) {
16✔
434
    retCode = TSDB_CODE_SUCCESS;
1✔
435
    goto end;
1✔
436
  }
437

438
  // set json real data
439
  root = cJSON_Parse(json);
15✔
440
  if (root == NULL) {
15✔
441
    retCode = buildSyntaxErrMsg(pMsgBuf, "json parse error", json);
×
442
    goto end;
×
443
  }
444

445
  size = cJSON_GetArraySize(root);
15✔
446
  if (!cJSON_IsObject(root)) {
15✔
447
    retCode = buildSyntaxErrMsg(pMsgBuf, "json error invalide value", json);
×
448
    goto end;
×
449
  }
450

451
  keyHash = taosHashInit(8, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, false);
15✔
452
  if (!keyHash) {
15✔
453
    retCode = terrno;
×
454
    goto end;
×
455
  }
456
  for (int32_t i = 0; i < size; i++) {
46✔
457
    cJSON* item = cJSON_GetArrayItem(root, i);
31✔
458
    if (!item) {
31✔
459
      uError("json inner error:%d", i);
×
460
      retCode = buildSyntaxErrMsg(pMsgBuf, "json inner error", json);
×
461
      goto end;
×
462
    }
463

464
    char* jsonKey = item->string;
31✔
465
    if (!isValidateTag(jsonKey)) {
31✔
466
      retCode = buildSyntaxErrMsg(pMsgBuf, "json key not validate", jsonKey);
×
467
      goto end;
×
468
    }
469
    size_t keyLen = strlen(jsonKey);
31✔
470
    if (keyLen > TSDB_MAX_JSON_KEY_LEN) {
31✔
471
      uError("json key too long error");
×
472
      retCode = buildSyntaxErrMsg(pMsgBuf, "json key too long, more than 256", jsonKey);
×
473
      goto end;
×
474
    }
475
    if (keyLen == 0 || taosHashGet(keyHash, jsonKey, keyLen) != NULL) {
31✔
476
      continue;
×
477
    }
478
    STagVal val = {0};
31✔
479
    //    TSDB_DB_FNAME_LENme, colName);
480
    val.pKey = jsonKey;
31✔
481
    retCode = taosHashPut(keyHash, jsonKey, keyLen, &keyLen,
31✔
482
                          CHAR_BYTES);  // add key to hash to remove dumplicate, value is useless
483
    if (TSDB_CODE_SUCCESS != retCode) {
31✔
484
      goto end;
×
485
    }
486

487
    if (item->type == cJSON_String) {  // add json value  format: type|data
31✔
488
      char*   jsonValue = item->valuestring;
17✔
489
      int32_t valLen = (int32_t)strlen(jsonValue);
17✔
490
      char*   tmp = taosMemoryCalloc(1, valLen * TSDB_NCHAR_SIZE);
17✔
491
      if (!tmp) {
17✔
492
        retCode = terrno;
×
493
        goto end;
×
494
      }
495
      val.type = TSDB_DATA_TYPE_NCHAR;
17✔
496
      if (valLen > 0 && !taosMbsToUcs4(jsonValue, valLen, (TdUcs4*)tmp, (int32_t)(valLen * TSDB_NCHAR_SIZE), &valLen, charsetCxt)) {
17✔
497
        uError("charset:%s to %s. val:%s, errno:%s, convert failed.", DEFAULT_UNICODE_ENCODEC,
×
498
               charsetCxt != NULL ? ((SConvInfo *)(charsetCxt))->charset : tsCharset, jsonValue,
499
               strerror(terrno));
500
        retCode = buildSyntaxErrMsg(pMsgBuf, "charset convert json error", jsonValue);
×
501
        taosMemoryFree(tmp);
×
502
        goto end;
×
503
      }
504
      val.nData = valLen;
17✔
505
      val.pData = tmp;
17✔
506
    } else if (item->type == cJSON_Number) {
14✔
507
      if (!isfinite(item->valuedouble)) {
8✔
508
        uError("json value is invalidate");
×
509
        retCode = buildSyntaxErrMsg(pMsgBuf, "json value number is illegal", json);
×
510
        goto end;
×
511
      }
512
      val.type = TSDB_DATA_TYPE_DOUBLE;
8✔
513
      *((double*)&(val.i64)) = item->valuedouble;
8✔
514
    } else if (item->type == cJSON_True || item->type == cJSON_False) {
6✔
515
      val.type = TSDB_DATA_TYPE_BOOL;
4✔
516
      *((char*)&(val.i64)) = (char)(item->valueint);
4✔
517
    } else if (item->type == cJSON_NULL) {
2✔
518
      val.type = TSDB_DATA_TYPE_NULL;
2✔
519
    } else {
520
      retCode = buildSyntaxErrMsg(pMsgBuf, "invalidate json value", json);
×
521
      goto end;
×
522
    }
523
    if (NULL == taosArrayPush(pTagVals, &val)) {
31✔
524
      retCode = terrno;
×
525
      goto end;
×
526
    }
527
  }
528

529
end:
15✔
530
  taosHashCleanup(keyHash);
16✔
531
  if (retCode == TSDB_CODE_SUCCESS) {
16✔
532
    retCode = tTagNew(pTagVals, 1, true, ppTag);
16✔
533
  }
534
  for (int i = 0; i < taosArrayGetSize(pTagVals); ++i) {
47✔
535
    STagVal* p = (STagVal*)taosArrayGet(pTagVals, i);
31✔
536
    if (IS_VAR_DATA_TYPE(p->type)) {
31✔
537
      taosMemoryFreeClear(p->pData);
17✔
538
    }
539
  }
540
  cJSON_Delete(root);
16✔
541
  return retCode;
16✔
542
}
543

544
static int32_t getInsTagsTableTargetNameFromOp(int32_t acctId, SOperatorNode* pOper, SName* pName) {
900✔
545
  if (OP_TYPE_EQUAL != pOper->opType) {
900✔
546
    return TSDB_CODE_SUCCESS;
84✔
547
  }
548

549
  SColumnNode* pCol = NULL;
816✔
550
  SValueNode*  pVal = NULL;
816✔
551
  if (QUERY_NODE_COLUMN == nodeType(pOper->pLeft)) {
816✔
552
    pCol = (SColumnNode*)pOper->pLeft;
816✔
553
  } else if (QUERY_NODE_VALUE == nodeType(pOper->pLeft)) {
×
554
    pVal = (SValueNode*)pOper->pLeft;
×
555
  }
556
  if (QUERY_NODE_COLUMN == nodeType(pOper->pRight)) {
816✔
557
    pCol = (SColumnNode*)pOper->pRight;
×
558
  } else if (QUERY_NODE_VALUE == nodeType(pOper->pRight)) {
816✔
559
    pVal = (SValueNode*)pOper->pRight;
817✔
560
  }
561
  if (NULL == pCol || NULL == pVal || NULL == pVal->literal || 0 == strcmp(pVal->literal, "")) {
816✔
562
    return TSDB_CODE_SUCCESS;
×
563
  }
564

565
  if (0 == strcmp(pCol->colName, "db_name")) {
817✔
566
    return tNameSetDbName(pName, acctId, pVal->literal, strlen(pVal->literal));
489✔
567
  } else if (0 == strcmp(pCol->colName, "table_name")) {
328✔
568
    return tNameAddTbName(pName, pVal->literal, strlen(pVal->literal));
261✔
569
  }
570

571
  return TSDB_CODE_SUCCESS;
67✔
572
}
573

574
static int32_t getInsTagsTableTargetObjName(int32_t acctId, SNode* pNode, SName* pName) {
777✔
575
  if (QUERY_NODE_OPERATOR == nodeType(pNode)) {
777✔
576
    return getInsTagsTableTargetNameFromOp(acctId, (SOperatorNode*)pNode, pName);
777✔
577
  }
578
  return TSDB_CODE_SUCCESS;
×
579
}
580

581
static int32_t getInsTagsTableTargetNameFromCond(int32_t acctId, SLogicConditionNode* pCond, SName* pName) {
365✔
582
  if (LOGIC_COND_TYPE_AND != pCond->condType) {
365✔
583
    return TSDB_CODE_SUCCESS;
×
584
  }
585

586
  SNode* pNode = NULL;
365✔
587
  FOREACH(pNode, pCond->pParameterList) {
1,142✔
588
    int32_t code = getInsTagsTableTargetObjName(acctId, pNode, pName);
778✔
589
    if (TSDB_CODE_SUCCESS != code) {
777✔
590
      return code;
×
591
    }
592
  }
593
  if ('\0' == pName->dbname[0]) {
364✔
594
    pName->type = 0;
×
595
  }
596
  return TSDB_CODE_SUCCESS;
364✔
597
}
598

599
int32_t getVnodeSysTableTargetName(int32_t acctId, SNode* pWhere, SName* pName) {
497✔
600
  if (NULL == pWhere) {
497✔
601
    return TSDB_CODE_SUCCESS;
9✔
602
  }
603

604
  if (QUERY_NODE_OPERATOR == nodeType(pWhere)) {
488✔
605
    int32_t code = getInsTagsTableTargetNameFromOp(acctId, (SOperatorNode*)pWhere, pName);
123✔
606
    if (TSDB_CODE_SUCCESS == code && '\0' == pName->dbname[0]) {
123✔
607
      pName->type = 0;
×
608
    }
609
    return code;
123✔
610
  }
611

612
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(pWhere)) {
365✔
613
    return getInsTagsTableTargetNameFromCond(acctId, (SLogicConditionNode*)pWhere, pName);
365✔
614
  }
615

616
  return TSDB_CODE_SUCCESS;
×
617
}
618

619
static int32_t userAuthToString(int32_t acctId, const char* pUser, const char* pDb, const char* pTable, AUTH_TYPE type,
87,169✔
620
                                char* pStr, bool isView) {
621
  return snprintf(pStr, USER_AUTH_KEY_MAX_LEN, "`%s`*%d*`%s`*`%s`*%d*%d", pUser, acctId, pDb,
137,321✔
622
                  (NULL == pTable || '\0' == pTable[0]) ? "" : pTable, type, isView);
50,152✔
623
}
624

625
static int32_t getIntegerFromAuthStr(const char* pStart, char** pNext) {
126,471✔
626
  char* p = strchr(pStart, '*');
126,471✔
627
  char  buf[10] = {0};
126,471✔
628
  if (NULL == p) {
126,471✔
629
    tstrncpy(buf, pStart, 10);
42,174✔
630
    *pNext = NULL;
42,174✔
631
  } else {
632
    strncpy(buf, pStart, p - pStart);
84,297✔
633
    *pNext = ++p;
84,297✔
634
  }
635
  return taosStr2Int32(buf, NULL, 10);
126,471✔
636
}
637

638
static int32_t getBackQuotedStringFromAuthStr(const char* pStart, char* pStr, uint32_t dstLen, char** pNext) {
126,462✔
639
  const char* pBeginQuote = strchr(pStart, '`');
126,462✔
640
  if (!pBeginQuote) {
126,462✔
641
    qWarn("failed to get string from auth string, %s, should be quoted with `", pStart);
×
642
    return TSDB_CODE_INVALID_PARA;
×
643
  }
644
  const char* pEndQuote = strchr(pBeginQuote + 1, '`');
126,462✔
645
  if (!pEndQuote) {
126,462✔
646
    qWarn("failed to get string from auth string, %s, should be quoted with `", pStart);
×
647
    return TSDB_CODE_INVALID_PARA;
×
648
  }
649

650
  pStr[0] = '\0';
126,462✔
651
  strncpy(pStr, pBeginQuote + 1, TMIN(dstLen, pEndQuote - pBeginQuote - 1));
126,462✔
652

653
  char* pSeperator = strchr(pEndQuote + 1, '*');
126,462✔
654
  if (!pSeperator) {
126,462✔
655
    *pNext = NULL;
×
656
  } else {
657
    *pNext = ++pSeperator;
126,462✔
658
  }
659
  return 0;
126,462✔
660
}
661

662
static void getStringFromAuthStr(const char* pStart, char* pStr, uint32_t dstLen, char** pNext) {
×
663
  char* p = strchr(pStart, '*');
×
664
  if (NULL == p) {
×
665
    tstrncpy(pStr, pStart, dstLen);
×
666
    *pNext = NULL;
×
667
  } else {
668
    strncpy(pStr, pStart, p - pStart);
×
669
    *pNext = ++p;
×
670
  }
671
  if (*pStart == '`' && *(pStart + 1) == '`') {
×
672
    *pStr = 0;
×
673
  }
674
}
×
675

676
static int32_t stringToUserAuth(const char* pStr, int32_t len, SUserAuthInfo* pUserAuth) {
42,165✔
677
  char* p = NULL;
42,165✔
678
  int32_t code = getBackQuotedStringFromAuthStr(pStr, pUserAuth->user, TSDB_USER_LEN, &p);
42,165✔
679
  if (code == TSDB_CODE_SUCCESS) {
42,165✔
680
    pUserAuth->tbName.acctId = getIntegerFromAuthStr(p, &p);
42,168✔
681
    code = getBackQuotedStringFromAuthStr(p, pUserAuth->tbName.dbname, TSDB_DB_NAME_LEN, &p);
42,163✔
682
  }
683
  if (code == TSDB_CODE_SUCCESS) {
42,155✔
684
    code = getBackQuotedStringFromAuthStr(p, pUserAuth->tbName.tname, TSDB_TABLE_NAME_LEN, &p);
42,155✔
685
  }
686
  if (code == TSDB_CODE_SUCCESS) {
42,176✔
687
    if (pUserAuth->tbName.tname[0]) {
42,174✔
688
      pUserAuth->tbName.type = TSDB_TABLE_NAME_T;
7,447✔
689
    } else {
690
      pUserAuth->tbName.type = TSDB_DB_NAME_T;
34,727✔
691
    }
692
    pUserAuth->type = getIntegerFromAuthStr(p, &p);
42,174✔
693
    pUserAuth->isView = getIntegerFromAuthStr(p, &p);
42,177✔
694
  }
695
  return code;
42,162✔
696
}
697

698
static int32_t buildTableReq(SHashObj* pTablesHash, SArray** pTables) {
260,219✔
699
  if (NULL != pTablesHash) {
260,219✔
700
    *pTables = taosArrayInit(taosHashGetSize(pTablesHash), sizeof(SName));
169,870✔
701
    if (NULL == *pTables) {
169,721✔
702
      return terrno;
×
703
    }
704
    void* p = taosHashIterate(pTablesHash, NULL);
169,721✔
705
    while (NULL != p) {
342,379✔
706
      size_t len = 0;
172,487✔
707
      char*  pKey = taosHashGetKey(p, &len);
172,487✔
708
      char   fullName[TSDB_TABLE_FNAME_LEN] = {0};
172,472✔
709
      strncpy(fullName, pKey, len);
172,472✔
710
      SName   name = {0};
172,472✔
711
      int32_t code = tNameFromString(&name, fullName, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE);
172,472✔
712
      if (TSDB_CODE_SUCCESS == code) {
172,519✔
713
        if (NULL == taosArrayPush(*pTables, &name)) {
345,007✔
714
          code = terrno;
×
715
        }
716
      }
717
      if (TSDB_CODE_SUCCESS != code) {
172,502✔
718
        taosHashCancelIterate(pTablesHash, p);
×
719
        taosArrayDestroy(*pTables);
×
720
        *pTables = NULL;
×
721
        return code;
×
722
      }
723
      p = taosHashIterate(pTablesHash, p);
172,502✔
724
    }
725
  }
726
  return TSDB_CODE_SUCCESS;
260,241✔
727
}
728

729
static int32_t buildDbReq(SHashObj* pDbsHash, SArray** pDbs) {
135,682✔
730
  if (NULL != pDbsHash) {
135,682✔
731
    *pDbs = taosArrayInit(taosHashGetSize(pDbsHash), TSDB_DB_FNAME_LEN);
45,568✔
732
    if (NULL == *pDbs) {
45,487✔
733
      return terrno;
×
734
    }
735
    void* p = taosHashIterate(pDbsHash, NULL);
45,487✔
736
    while (NULL != p) {
91,241✔
737
      size_t len = 0;
45,669✔
738
      char*  pKey = taosHashGetKey(p, &len);
45,669✔
739
      char   fullName[TSDB_DB_FNAME_LEN] = {0};
45,669✔
740
      strncpy(fullName, pKey, len);
45,669✔
741
      if (NULL == taosArrayPush(*pDbs, fullName)) {
91,331✔
742
        taosHashCancelIterate(pDbsHash, p);
×
743
        taosArrayDestroy(*pDbs);
×
744
        *pDbs = NULL;
×
745
        return terrno;
×
746
      }
747
      p = taosHashIterate(pDbsHash, p);
45,662✔
748
    }
749
  }
750
  return TSDB_CODE_SUCCESS;
135,686✔
751
}
752

753
static int32_t buildTableReqFromDb(SHashObj* pDbsHash, SArray** pDbs) {
271,292✔
754
  if (NULL != pDbsHash) {
271,292✔
755
    if (NULL == *pDbs) {
169,638✔
756
      *pDbs = taosArrayInit(taosHashGetSize(pDbsHash), sizeof(STablesReq));
169,655✔
757
      if (NULL == *pDbs) {
169,261✔
758
        return terrno;
×
759
      }
760
    }
761
    SParseTablesMetaReq* p = taosHashIterate(pDbsHash, NULL);
169,244✔
762
    while (NULL != p) {
339,516✔
763
      STablesReq req = {0};
169,801✔
764
      tstrncpy(req.dbFName, p->dbFName, TSDB_DB_FNAME_LEN);
169,801✔
765
      int32_t code = buildTableReq(p->pTables, &req.pTables);
169,801✔
766
      if (TSDB_CODE_SUCCESS == code) {
169,823✔
767
        if (NULL == taosArrayPush(*pDbs, &req)) {
339,657✔
768
          code = terrno;
×
769
        }
770
      }
771
      if (TSDB_CODE_SUCCESS != code) {
169,808✔
772
        taosHashCancelIterate(pDbsHash, p);
×
773
        taosArrayDestroy(*pDbs);
×
774
        *pDbs = NULL;
×
775
        return code;
×
776
      }
777
      p = taosHashIterate(pDbsHash, p);
169,808✔
778
    }
779
  }
780
  return TSDB_CODE_SUCCESS;
271,369✔
781
}
782

783
static int32_t buildUserAuthReq(SHashObj* pUserAuthHash, SArray** pUserAuth) {
45,234✔
784
  if (NULL != pUserAuthHash) {
45,234✔
785
    *pUserAuth = taosArrayInit(taosHashGetSize(pUserAuthHash), sizeof(SUserAuthInfo));
42,104✔
786
    if (NULL == *pUserAuth) {
42,092✔
787
      return terrno;
×
788
    }
789
    void* p = taosHashIterate(pUserAuthHash, NULL);
42,092✔
790
    while (NULL != p) {
84,290✔
791
      size_t len = 0;
42,173✔
792
      char*  pKey = taosHashGetKey(p, &len);
42,173✔
793
      char   key[USER_AUTH_KEY_MAX_LEN] = {0};
42,173✔
794
      strncpy(key, pKey, len);
42,173✔
795
      SUserAuthInfo userAuth = {0};
42,173✔
796
      int32_t code = stringToUserAuth(key, len, &userAuth);
42,173✔
797
      if (TSDB_CODE_SUCCESS != code) terrno = code;
42,157✔
798
      if (code != 0 || NULL == taosArrayPush(*pUserAuth, &userAuth)) {
84,321✔
799
        taosHashCancelIterate(pUserAuthHash, p);
×
800
        taosArrayDestroy(*pUserAuth);
×
801
        *pUserAuth = NULL;
×
802
        return terrno;
×
803
      }
804
      p = taosHashIterate(pUserAuthHash, p);
42,166✔
805
    }
806
  }
807
  return TSDB_CODE_SUCCESS;
45,247✔
808
}
809

810
static int32_t buildUdfReq(SHashObj* pUdfHash, SArray** pUdf) {
45,228✔
811
  if (NULL != pUdfHash) {
45,228✔
812
    *pUdf = taosArrayInit(taosHashGetSize(pUdfHash), TSDB_FUNC_NAME_LEN);
431✔
813
    if (NULL == *pUdf) {
431✔
814
      return terrno;
×
815
    }
816
    void* p = taosHashIterate(pUdfHash, NULL);
431✔
817
    while (NULL != p) {
976✔
818
      size_t len = 0;
545✔
819
      char*  pFunc = taosHashGetKey(p, &len);
545✔
820
      char   func[TSDB_FUNC_NAME_LEN] = {0};
545✔
821
      strncpy(func, pFunc, len);
545✔
822
      if (NULL == taosArrayPush(*pUdf, func)) {
1,090✔
823
        taosHashCancelIterate(pUdfHash, p);
×
824
        taosArrayDestroy(*pUdf);
×
825
        *pUdf = NULL;
×
826
        return terrno;
×
827
      }
828
      p = taosHashIterate(pUdfHash, p);
545✔
829
    }
830
  }
831
  return TSDB_CODE_SUCCESS;
45,228✔
832
}
833

834
int32_t buildCatalogReq(SParseMetaCache* pMetaCache, SCatalogReq* pCatalogReq) {
45,228✔
835
  int32_t code = buildTableReqFromDb(pMetaCache->pTableMeta, &pCatalogReq->pTableMeta);
45,228✔
836
  if (TSDB_CODE_SUCCESS == code) {
45,246✔
837
    code = buildDbReq(pMetaCache->pDbVgroup, &pCatalogReq->pDbVgroup);
45,247✔
838
  }
839
  if (TSDB_CODE_SUCCESS == code) {
45,215✔
840
    code = buildTableReqFromDb(pMetaCache->pTableVgroup, &pCatalogReq->pTableHash);
45,200✔
841
  }
842
  if (TSDB_CODE_SUCCESS == code) {
45,262✔
843
    code = buildDbReq(pMetaCache->pDbCfg, &pCatalogReq->pDbCfg);
45,247✔
844
  }
845
  if (TSDB_CODE_SUCCESS == code) {
45,259✔
846
    code = buildDbReq(pMetaCache->pDbInfo, &pCatalogReq->pDbInfo);
45,245✔
847
  }
848
  if (TSDB_CODE_SUCCESS == code) {
45,256✔
849
    code = buildUserAuthReq(pMetaCache->pUserAuth, &pCatalogReq->pUser);
45,241✔
850
  }
851
  if (TSDB_CODE_SUCCESS == code) {
45,262✔
852
    code = buildUdfReq(pMetaCache->pUdf, &pCatalogReq->pUdf);
45,229✔
853
  }
854
  if (TSDB_CODE_SUCCESS == code) {
45,266✔
855
    code = buildTableReq(pMetaCache->pTableIndex, &pCatalogReq->pTableIndex);
45,240✔
856
  }
857
  if (TSDB_CODE_SUCCESS == code) {
45,268✔
858
    code = buildTableReq(pMetaCache->pTableCfg, &pCatalogReq->pTableCfg);
45,243✔
859
  }
860
  if (TSDB_CODE_SUCCESS == code) {
45,266✔
861
    code = buildTableReqFromDb(pMetaCache->pTableMeta, &pCatalogReq->pTableTSMAs);
45,241✔
862
  }
863
  if (TSDB_CODE_SUCCESS == code) {
45,272✔
864
    code = buildTableReqFromDb(pMetaCache->pTSMAs, &pCatalogReq->pTSMAs);
45,245✔
865
  }
866
  if (TSDB_CODE_SUCCESS == code) {
45,273✔
867
    code = buildTableReqFromDb(pMetaCache->pTableName, &pCatalogReq->pTableName);
45,247✔
868
  }
869
#ifdef TD_ENTERPRISE
870
  if (TSDB_CODE_SUCCESS == code) {
45,270✔
871
    code = buildTableReqFromDb(pMetaCache->pTableMeta, &pCatalogReq->pView);
45,244✔
872
  }
873
#endif
874

875
  TSWAP(pCatalogReq->pVSubTable, pMetaCache->pVSubTables);
45,246✔
876
  TSWAP(pCatalogReq->pVStbRefDbs, pMetaCache->pVStbRefDbs);
45,246✔
877
  pCatalogReq->dNodeRequired = pMetaCache->dnodeRequired;
45,246✔
878
  pCatalogReq->forceFetchViewMeta = pMetaCache->forceFetchViewMeta;
45,246✔
879
  return code;
45,246✔
880
}
881

882
int32_t createSelectStmtImpl(bool isDistinct, SNodeList* pProjectionList, SNode* pTable, SNodeList* pHint,
7,369✔
883
                             SNode** ppSelect) {
884
  SSelectStmt* select = NULL;
7,369✔
885
  int32_t      code = nodesMakeNode(QUERY_NODE_SELECT_STMT, (SNode**)&select);
7,369✔
886
  if (NULL == select) {
7,370✔
887
    return code;
×
888
  }
889
  select->isDistinct = isDistinct;
7,370✔
890
  select->pProjectionList = pProjectionList;
7,370✔
891
  select->pFromTable = pTable;
7,370✔
892
  snprintf(select->stmtName, TSDB_TABLE_NAME_LEN, "%p", select);
7,370✔
893
  select->timeLineResMode = select->isDistinct ? TIME_LINE_NONE : TIME_LINE_GLOBAL;
7,370✔
894
  select->timeLineCurMode = TIME_LINE_GLOBAL;
7,370✔
895
  select->onlyHasKeepOrderFunc = true;
7,370✔
896
  TAOS_SET_OBJ_ALIGNED(&select->timeRange, TSWINDOW_INITIALIZER); 
7,370✔
897
  select->pHint = pHint;
7,370✔
898
  select->lastProcessByRowFuncId = -1;
7,370✔
899
  *ppSelect = (SNode*)select;
7,370✔
900
  return code;
7,370✔
901
}
902

903
static int32_t putMetaDataToHash(const char* pKey, int32_t len, const SArray* pData, int32_t index, SHashObj** pHash) {
218,083✔
904
  if (NULL == *pHash) {
218,083✔
905
    *pHash = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
215,153✔
906
    if (NULL == *pHash) {
215,178✔
907
      return terrno;
×
908
    }
909
  }
910
  SMetaRes* pRes = taosArrayGet(pData, index);
218,108✔
911
  return taosHashPut(*pHash, pKey, len, &pRes, POINTER_BYTES);
218,136✔
912
}
913

914
int32_t getMetaDataFromHash(const char* pKey, int32_t len, SHashObj* pHash, void** pOutput) {
101,281✔
915
  SMetaRes** pRes = taosHashGet(pHash, pKey, len);
101,281✔
916
  if (NULL == pRes || NULL == *pRes) {
101,297✔
917
    return TSDB_CODE_PAR_INTERNAL_ERROR;
690✔
918
  }
919
  if (TSDB_CODE_SUCCESS == (*pRes)->code) {
100,607✔
920
    *pOutput = (*pRes)->pRes;
100,115✔
921
  }
922
  return (*pRes)->code;
100,607✔
923
}
924

925
static int32_t putTableDataToCache(const SArray* pTableReq, const SArray* pTableData, SHashObj** pTable) {
90,473✔
926
  int32_t ntables = taosArrayGetSize(pTableReq);
90,473✔
927
  for (int32_t i = 0; i < ntables; ++i) {
90,535✔
928
    char    fullName[TSDB_TABLE_FNAME_LEN];
929
    int32_t code = tNameExtractFullName(taosArrayGet(pTableReq, i), fullName);
59✔
930
    if (TSDB_CODE_SUCCESS != code) {
59✔
931
      return code;
×
932
    }
933
    if (TSDB_CODE_SUCCESS != putMetaDataToHash(fullName, strlen(fullName), pTableData, i, pTable)) {
59✔
934
      return TSDB_CODE_OUT_OF_MEMORY;
×
935
    }
936
  }
937
  return TSDB_CODE_SUCCESS;
90,476✔
938
}
939

940
static int32_t putDbDataToCache(const SArray* pDbReq, const SArray* pDbData, SHashObj** pDb) {
135,718✔
941
  int32_t nvgs = taosArrayGetSize(pDbReq);
135,718✔
942
  for (int32_t i = 0; i < nvgs; ++i) {
181,383✔
943
    char* pDbFName = taosArrayGet(pDbReq, i);
45,668✔
944
    if (TSDB_CODE_SUCCESS != putMetaDataToHash(pDbFName, strlen(pDbFName), pDbData, i, pDb)) {
45,669✔
945
      return TSDB_CODE_OUT_OF_MEMORY;
×
946
    }
947
  }
948
  return TSDB_CODE_SUCCESS;
135,715✔
949
}
950

951
static int32_t putDbTableDataToCache(const SArray* pDbReq, const SArray* pTableData, SHashObj** pTable) {
271,309✔
952
  if (!pTableData || pTableData->size == 0) return TSDB_CODE_SUCCESS;
271,309✔
953
  int32_t ndbs = taosArrayGetSize(pDbReq);
169,663✔
954
  int32_t tableNo = 0;
169,665✔
955
  for (int32_t i = 0; i < ndbs; ++i) {
296,878✔
956
    STablesReq* pReq = taosArrayGet(pDbReq, i);
127,155✔
957
    int32_t     ntables = taosArrayGetSize(pReq->pTables);
127,148✔
958
    for (int32_t j = 0; j < ntables; ++j) {
256,917✔
959
      char    fullName[TSDB_TABLE_FNAME_LEN];
960
      int32_t code = tNameExtractFullName(taosArrayGet(pReq->pTables, j), fullName);
129,704✔
961
      if (TSDB_CODE_SUCCESS != code) {
129,731✔
962
        return code;
×
963
      }
964
      if (TSDB_CODE_SUCCESS != putMetaDataToHash(fullName, strlen(fullName), pTableData, tableNo, pTable)) {
129,731✔
965
        return TSDB_CODE_OUT_OF_MEMORY;
×
966
      }
967
      ++tableNo;
129,760✔
968
    }
969
  }
970
  return TSDB_CODE_SUCCESS;
169,723✔
971
}
972

973
static int32_t putUserAuthToCache(const SArray* pUserAuthReq, const SArray* pUserAuthData, SHashObj** pUserAuth) {
45,245✔
974
  int32_t nvgs = taosArrayGetSize(pUserAuthReq);
45,245✔
975
  for (int32_t i = 0; i < nvgs; ++i) {
87,422✔
976
    SUserAuthInfo* pUser = taosArrayGet(pUserAuthReq, i);
42,176✔
977
    char           key[USER_AUTH_KEY_MAX_LEN] = {0};
42,175✔
978
    int32_t        len = userAuthToString(pUser->tbName.acctId, pUser->user, pUser->tbName.dbname, pUser->tbName.tname,
42,175✔
979
                                          pUser->type, key, pUser->isView);
42,175✔
980
    if (TSDB_CODE_SUCCESS != putMetaDataToHash(key, len, pUserAuthData, i, pUserAuth)) {
42,171✔
981
      return TSDB_CODE_OUT_OF_MEMORY;
×
982
    }
983
  }
984
  return TSDB_CODE_SUCCESS;
45,246✔
985
}
986

987
static int32_t putUdfToCache(const SArray* pUdfReq, const SArray* pUdfData, SHashObj** pUdf) {
45,247✔
988
  int32_t num = taosArrayGetSize(pUdfReq);
45,247✔
989
  for (int32_t i = 0; i < num; ++i) {
45,791✔
990
    char* pFunc = taosArrayGet(pUdfReq, i);
545✔
991
    if (TSDB_CODE_SUCCESS != putMetaDataToHash(pFunc, strlen(pFunc), pUdfData, i, pUdf)) {
545✔
992
      return TSDB_CODE_OUT_OF_MEMORY;
×
993
    }
994
  }
995
  return TSDB_CODE_SUCCESS;
45,246✔
996
}
997

998
int32_t putMetaDataToCache(const SCatalogReq* pCatalogReq, SMetaData* pMetaData, SParseMetaCache* pMetaCache) {
45,225✔
999
  int32_t code = putDbTableDataToCache(pCatalogReq->pTableMeta, pMetaData->pTableMeta, &pMetaCache->pTableMeta);
45,225✔
1000
  if (TSDB_CODE_SUCCESS == code) {
45,244✔
1001
    code = putDbDataToCache(pCatalogReq->pDbVgroup, pMetaData->pDbVgroup, &pMetaCache->pDbVgroup);
45,244✔
1002
  }
1003
  if (TSDB_CODE_SUCCESS == code) {
45,245✔
1004
    code = putDbTableDataToCache(pCatalogReq->pTableHash, pMetaData->pTableHash, &pMetaCache->pTableVgroup);
45,238✔
1005
  }
1006
  if (TSDB_CODE_SUCCESS == code) {
45,254✔
1007
    code = putDbDataToCache(pCatalogReq->pDbCfg, pMetaData->pDbCfg, &pMetaCache->pDbCfg);
45,248✔
1008
  }
1009
  if (TSDB_CODE_SUCCESS == code) {
45,255✔
1010
    code = putDbDataToCache(pCatalogReq->pDbInfo, pMetaData->pDbInfo, &pMetaCache->pDbInfo);
45,249✔
1011
  }
1012
  if (TSDB_CODE_SUCCESS == code) {
45,255✔
1013
    code = putUserAuthToCache(pCatalogReq->pUser, pMetaData->pUser, &pMetaCache->pUserAuth);
45,249✔
1014
  }
1015
  if (TSDB_CODE_SUCCESS == code) {
45,253✔
1016
    code = putUdfToCache(pCatalogReq->pUdf, pMetaData->pUdfList, &pMetaCache->pUdf);
45,246✔
1017
  }
1018
  if (TSDB_CODE_SUCCESS == code) {
45,253✔
1019
    code = putTableDataToCache(pCatalogReq->pTableIndex, pMetaData->pTableIndex, &pMetaCache->pTableIndex);
45,247✔
1020
  }
1021
  if (TSDB_CODE_SUCCESS == code) {
45,250✔
1022
    code = putTableDataToCache(pCatalogReq->pTableCfg, pMetaData->pTableCfg, &pMetaCache->pTableCfg);
45,243✔
1023
  }
1024
  if (TSDB_CODE_SUCCESS == code) {
45,246✔
1025
    code = putDbTableDataToCache(pCatalogReq->pTableTSMAs, pMetaData->pTableTsmas, &pMetaCache->pTableTSMAs);
45,240✔
1026
  }
1027
  if (TSDB_CODE_SUCCESS == code) {
45,247✔
1028
    code = putDbTableDataToCache(pCatalogReq->pTSMAs, pMetaData->pTsmas, &pMetaCache->pTSMAs);
45,240✔
1029
  }
1030
  if (TSDB_CODE_SUCCESS == code) {
45,250✔
1031
    code = putDbTableDataToCache(pCatalogReq->pTableName, pMetaData->pTableMeta, &pMetaCache->pTableName);
45,243✔
1032
  }
1033
#ifdef TD_ENTERPRISE
1034
  if (TSDB_CODE_SUCCESS == code) {
45,250✔
1035
    code = putDbTableDataToCache(pCatalogReq->pView, pMetaData->pView, &pMetaCache->pViews);
45,245✔
1036
  }
1037
#endif
1038

1039
  pMetaCache->pVSubTables = pMetaData->pVSubTables;
45,246✔
1040
  pMetaData->pVSubTables = NULL;
45,246✔
1041

1042
  pMetaCache->pVStbRefDbs = pMetaData->pVStbRefDbs;
45,246✔
1043
  pMetaData->pVStbRefDbs = NULL;
45,246✔
1044

1045
  pMetaCache->pDnodes = pMetaData->pDnodeList;
45,246✔
1046
  return code;
45,246✔
1047
}
1048

1049
static int32_t reserveTableReqInCacheImpl(const char* pTbFName, int32_t len, SHashObj** pTables) {
89,412✔
1050
  if (NULL == *pTables) {
89,412✔
1051
    *pTables = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
84,569✔
1052
    if (NULL == *pTables) {
84,603✔
1053
      return terrno;
×
1054
    }
1055
  }
1056
  return taosHashPut(*pTables, pTbFName, len, &nullPointer, POINTER_BYTES);
89,446✔
1057
}
1058

1059
static int32_t reserveTableReqInCache(int32_t acctId, const char* pDb, const char* pTable, SHashObj** pTables) {
89,434✔
1060
  char    fullName[TSDB_TABLE_FNAME_LEN];
1061
  int32_t len = tsnprintf(fullName, sizeof(fullName), "%d.%s.%s", acctId, pDb, pTable);
89,434✔
1062
  return reserveTableReqInCacheImpl(fullName, len, pTables);
89,448✔
1063
}
1064

1065
static int32_t reserveTableReqInDbCacheImpl(int32_t acctId, const char* pDb, const char* pTable, SHashObj* pDbs) {
84,486✔
1066
  SParseTablesMetaReq req = {0};
84,486✔
1067
  int32_t             len = tsnprintf(req.dbFName, sizeof(req.dbFName), "%d.%s", acctId, pDb);
84,486✔
1068
  int32_t             code = reserveTableReqInCache(acctId, pDb, pTable, &req.pTables);
84,530✔
1069
  if (TSDB_CODE_SUCCESS == code) {
84,540✔
1070
    code = taosHashPut(pDbs, req.dbFName, len, &req, sizeof(SParseTablesMetaReq));
84,540✔
1071
  }
1072
  return code;
84,544✔
1073
}
1074

1075
static int32_t reserveTableReqInDbCache(int32_t acctId, const char* pDb, const char* pTable, SHashObj** pDbs) {
89,295✔
1076
  if (NULL == *pDbs) {
89,295✔
1077
    *pDbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
84,318✔
1078
    if (NULL == *pDbs) {
84,397✔
1079
      return terrno;
×
1080
    }
1081
  }
1082
  char                 fullName[TSDB_DB_FNAME_LEN];
1083
  int32_t              len = tsnprintf(fullName, sizeof(fullName), "%d.%s", acctId, pDb);
89,374✔
1084
  SParseTablesMetaReq* pReq = taosHashGet(*pDbs, fullName, len);
89,374✔
1085
  if (NULL == pReq) {
89,376✔
1086
    return reserveTableReqInDbCacheImpl(acctId, pDb, pTable, *pDbs);
84,516✔
1087
  }
1088
  return reserveTableReqInCache(acctId, pDb, pTable, &pReq->pTables);
4,860✔
1089
}
1090

1091
int32_t reserveTableMetaInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
45,043✔
1092
  return reserveTableReqInDbCache(acctId, pDb, pTable, &pMetaCache->pTableMeta);
45,043✔
1093
}
1094

1095
int32_t reserveTableMetaInCacheExt(const SName* pName, SParseMetaCache* pMetaCache) {
×
1096
  return reserveTableReqInDbCache(pName->acctId, pName->dbname, pName->tname, &pMetaCache->pTableMeta);
×
1097
}
1098

1099
int32_t reserveTableUidInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
×
1100
  return reserveTableReqInDbCache(acctId, pDb, pTable, &pMetaCache->pTableName);
×
1101
}
1102

1103
int32_t getTableMetaFromCache(SParseMetaCache* pMetaCache, const SName* pName, STableMeta** pMeta) {
50,935✔
1104
  char    fullName[TSDB_TABLE_FNAME_LEN];
1105
  int32_t code = tNameExtractFullName(pName, fullName);
50,935✔
1106
  if (TSDB_CODE_SUCCESS != code) {
50,953✔
1107
    return code;
×
1108
  }
1109
  STableMeta* pTableMeta = NULL;
50,953✔
1110
  code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pTableMeta, (void**)&pTableMeta);
50,953✔
1111
  if (TSDB_CODE_SUCCESS == code) {
50,944✔
1112
    *pMeta = tableMetaDup(pTableMeta);
50,678✔
1113
    if (NULL == *pMeta) {
50,635✔
1114
      code = TSDB_CODE_OUT_OF_MEMORY;
×
1115
    }
1116
  }
1117
  return code;
50,901✔
1118
}
1119

1120
int32_t getTableNameFromCache(SParseMetaCache* pMetaCache, const SName* pName, char* pTbName) {
×
1121
  char    fullName[TSDB_TABLE_FNAME_LEN];
1122
  int32_t code = tNameExtractFullName(pName, fullName);
×
1123
  if (TSDB_CODE_SUCCESS != code) {
×
1124
    return code;
×
1125
  }
1126
  const STableMeta* pMeta = NULL;
×
1127
  code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pTableName, (void**)&pMeta);
×
1128
  if (TSDB_CODE_SUCCESS == code) {
×
1129
    if (!pMeta) code = TSDB_CODE_PAR_INTERNAL_ERROR;
×
1130
    int32_t metaSize =
×
1131
        sizeof(STableMeta) + sizeof(SSchema) * (pMeta->tableInfo.numOfColumns + pMeta->tableInfo.numOfTags);
×
1132
    int32_t schemaExtSize =
×
1133
        (withExtSchema(pMeta->tableType) && pMeta->schemaExt) ? sizeof(SSchemaExt) * pMeta->tableInfo.numOfColumns : 0;
×
1134
    int32_t colRefSize = (hasRefCol(pMeta->tableType) && pMeta->colRef) ? sizeof(SColRef) * pMeta->numOfColRefs : 0;
×
1135
    const char* pTableName = (const char*)pMeta + metaSize + schemaExtSize + colRefSize;
×
1136
    tstrncpy(pTbName, pTableName, TSDB_TABLE_NAME_LEN);
×
1137
  }
1138

1139
  return code;
×
1140
}
1141

1142
int32_t buildTableMetaFromViewMeta(STableMeta** pMeta, SViewMeta* pViewMeta) {
×
1143
  *pMeta = taosMemoryCalloc(1, sizeof(STableMeta) + pViewMeta->numOfCols * sizeof(SSchema));
×
1144
  if (NULL == *pMeta) {
×
1145
    return terrno;
×
1146
  }
1147
  (*pMeta)->uid = pViewMeta->viewId;
×
1148
  (*pMeta)->vgId = MNODE_HANDLE;
×
1149
  (*pMeta)->tableType = TSDB_VIEW_TABLE;
×
1150
  (*pMeta)->sversion = pViewMeta->version;
×
1151
  (*pMeta)->tversion = pViewMeta->version;
×
1152
  (*pMeta)->tableInfo.precision = pViewMeta->precision;
×
1153
  (*pMeta)->tableInfo.numOfColumns = pViewMeta->numOfCols;
×
1154
  memcpy((*pMeta)->schema, pViewMeta->pSchema, sizeof(SSchema) * pViewMeta->numOfCols);
×
1155

1156
  for (int32_t i = 0; i < pViewMeta->numOfCols; ++i) {
×
1157
    (*pMeta)->tableInfo.rowSize += (*pMeta)->schema[i].bytes;
×
1158
  }
1159
  return TSDB_CODE_SUCCESS;
×
1160
}
1161

1162
int32_t getViewMetaFromCache(SParseMetaCache* pMetaCache, const SName* pName, STableMeta** pMeta) {
34✔
1163
  char    fullName[TSDB_TABLE_FNAME_LEN];
1164
  int32_t code = tNameExtractFullName(pName, fullName);
34✔
1165
  if (TSDB_CODE_SUCCESS != code) {
34✔
1166
    return code;
×
1167
  }
1168
  SViewMeta* pViewMeta = NULL;
34✔
1169
  code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pViews, (void**)&pViewMeta);
34✔
1170
  if (TSDB_CODE_SUCCESS == code) {
34✔
1171
    code = buildTableMetaFromViewMeta(pMeta, pViewMeta);
×
1172
  }
1173
  return code;
34✔
1174
}
1175

1176
static int32_t reserveDbReqInCache(int32_t acctId, const char* pDb, SHashObj** pDbs) {
47,998✔
1177
  if (NULL == *pDbs) {
47,998✔
1178
    *pDbs = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
45,516✔
1179
    if (NULL == *pDbs) {
45,547✔
1180
      return terrno;
×
1181
    }
1182
  }
1183
  char    fullName[TSDB_TABLE_FNAME_LEN];
1184
  int32_t len = tsnprintf(fullName, sizeof(fullName), "%d.%s", acctId, pDb);
48,029✔
1185
  return taosHashPut(*pDbs, fullName, len, &nullPointer, POINTER_BYTES);
48,072✔
1186
}
1187

1188
int32_t reserveDbVgInfoInCache(int32_t acctId, const char* pDb, SParseMetaCache* pMetaCache) {
6,906✔
1189
  return reserveDbReqInCache(acctId, pDb, &pMetaCache->pDbVgroup);
6,906✔
1190
}
1191

1192
int32_t getDbVgInfoFromCache(SParseMetaCache* pMetaCache, const char* pDbFName, SArray** pVgInfo) {
1,255✔
1193
  SArray* pVgList = NULL;
1,255✔
1194
  int32_t code = getMetaDataFromHash(pDbFName, strlen(pDbFName), pMetaCache->pDbVgroup, (void**)&pVgList);
1,255✔
1195
  // pVgList is null, which is a legal value, indicating that the user DB has not been created
1196
  if (TSDB_CODE_SUCCESS == code && NULL != pVgList) {
1,255✔
1197
    *pVgInfo = taosArrayDup(pVgList, NULL);
1,228✔
1198
    if (NULL == *pVgInfo) {
1,228✔
1199
      code = terrno;
×
1200
    }
1201
  }
1202
  return code;
1,255✔
1203
}
1204

1205
int32_t reserveTableVgroupInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
44,115✔
1206
  return reserveTableReqInDbCache(acctId, pDb, pTable, &pMetaCache->pTableVgroup);
44,115✔
1207
}
1208

1209
int32_t reserveTableVgroupInCacheExt(const SName* pName, SParseMetaCache* pMetaCache) {
127✔
1210
  return reserveTableReqInDbCache(pName->acctId, pName->dbname, pName->tname, &pMetaCache->pTableVgroup);
127✔
1211
}
1212

1213
int32_t getTableVgroupFromCache(SParseMetaCache* pMetaCache, const SName* pName, SVgroupInfo* pVgroup) {
42,416✔
1214
  char    fullName[TSDB_TABLE_FNAME_LEN];
1215
  int32_t code = tNameExtractFullName(pName, fullName);
42,416✔
1216
  if (TSDB_CODE_SUCCESS != code) {
42,440✔
1217
    return code;
×
1218
  }
1219
  SVgroupInfo* pVg = NULL;
42,440✔
1220
  code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pTableVgroup, (void**)&pVg);
42,440✔
1221
  if (TSDB_CODE_SUCCESS == code) {
42,442✔
1222
    memcpy(pVgroup, pVg, sizeof(SVgroupInfo));
42,435✔
1223
  }
1224
  return code;
42,442✔
1225
}
1226

1227
int32_t getDbTableVgroupFromCache(SParseMetaCache* pMetaCache, const SName* pName, SVgroupInfo* pVgroup) {
×
1228
  char    fullName[TSDB_TABLE_FNAME_LEN];
1229
  int32_t code = tNameExtractFullName(pName, fullName);
×
1230
  if (TSDB_CODE_SUCCESS != code) {
×
1231
    return code;
×
1232
  }
1233
  const char* pDb = strstr(fullName, ".");
×
1234
  if (pDb == NULL) return TSDB_CODE_PAR_INTERNAL_ERROR;
×
1235
  pDb = strstr(pDb + 1, ".");
×
1236
  if (pDb == NULL) return TSDB_CODE_PAR_INTERNAL_ERROR;
×
1237
  int32_t fullDbLen = pDb - fullName;
×
1238
  int32_t fullTbLen = strlen(fullName);
×
1239

1240
  SArray*     pVgArray = NULL;
×
1241
  SDbCfgInfo* pDbCfg = NULL;
×
1242
  code = getMetaDataFromHash(fullName, fullDbLen, pMetaCache->pDbVgroup, (void**)&pVgArray);
×
1243
  if (TSDB_CODE_SUCCESS == code) {
×
1244
    code = getMetaDataFromHash(fullName, fullDbLen, pMetaCache->pDbCfg, (void**)&pDbCfg);
×
1245
  }
1246
  if (TSDB_CODE_SUCCESS == code) {
×
1247
    uint32_t hashValue =
×
1248
        taosGetTbHashVal(fullName, fullTbLen, pDbCfg->hashMethod, pDbCfg->hashPrefix, pDbCfg->hashSuffix);
×
1249
    SVgroupInfo* pVg = taosArraySearch(pVgArray, &hashValue, ctgHashValueComp, TD_EQ);
×
1250
    if (pVg) {
×
1251
      memcpy(pVgroup, pVg, sizeof(SVgroupInfo));
×
1252
    } else {
1253
      code = TSDB_CODE_PAR_INTERNAL_ERROR;
×
1254
    }
1255
  }
1256
  return code;
×
1257
}
1258

1259
int32_t reserveDbVgVersionInCache(int32_t acctId, const char* pDb, SParseMetaCache* pMetaCache) {
617✔
1260
  return reserveDbReqInCache(acctId, pDb, &pMetaCache->pDbInfo);
617✔
1261
}
1262

1263
int32_t getDbVgVersionFromCache(SParseMetaCache* pMetaCache, const char* pDbFName, int32_t* pVersion, int64_t* pDbId,
616✔
1264
                                int32_t* pTableNum, int64_t* pStateTs) {
1265
  SDbInfo* pDbInfo = NULL;
616✔
1266
  int32_t  code = getMetaDataFromHash(pDbFName, strlen(pDbFName), pMetaCache->pDbInfo, (void**)&pDbInfo);
616✔
1267
  if (TSDB_CODE_SUCCESS == code) {
616✔
1268
    *pVersion = pDbInfo->vgVer;
616✔
1269
    taosSetInt64Aligned(pDbId, pDbInfo->dbId);
616✔
1270
    *pTableNum = pDbInfo->tbNum;
616✔
1271
    taosSetInt64Aligned(pStateTs, pDbInfo->stateTs);
616✔
1272
  }
1273
  return code;
616✔
1274
}
1275

1276
int32_t reserveDbCfgInCache(int32_t acctId, const char* pDb, SParseMetaCache* pMetaCache) {
40,482✔
1277
  return reserveDbReqInCache(acctId, pDb, &pMetaCache->pDbCfg);
40,482✔
1278
}
1279

1280
int32_t getDbCfgFromCache(SParseMetaCache* pMetaCache, const char* pDbFName, SDbCfgInfo* pInfo) {
3,899✔
1281
  SDbCfgInfo* pDbCfg = NULL;
3,899✔
1282
  int32_t     code = getMetaDataFromHash(pDbFName, strlen(pDbFName), pMetaCache->pDbCfg, (void**)&pDbCfg);
3,899✔
1283
  if (TSDB_CODE_SUCCESS == code) {
3,901✔
1284
    memcpy(pInfo, pDbCfg, sizeof(SDbCfgInfo));
3,900✔
1285
  }
1286
  return code;
3,901✔
1287
}
1288

1289
static int32_t reserveUserAuthInCacheImpl(const char* pKey, int32_t len, SParseMetaCache* pMetaCache) {
44,512✔
1290
  if (NULL == pMetaCache->pUserAuth) {
44,512✔
1291
    pMetaCache->pUserAuth = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
42,095✔
1292
    if (NULL == pMetaCache->pUserAuth) {
42,110✔
1293
      return terrno;
×
1294
    }
1295
  }
1296
  return taosHashPut(pMetaCache->pUserAuth, pKey, len, &nullPointer, POINTER_BYTES);
44,527✔
1297
}
1298

1299
int32_t reserveUserAuthInCache(int32_t acctId, const char* pUser, const char* pDb, const char* pTable, AUTH_TYPE type,
44,521✔
1300
                               SParseMetaCache* pMetaCache) {
1301
  char    key[USER_AUTH_KEY_MAX_LEN] = {0};
44,521✔
1302
  int32_t len = userAuthToString(acctId, pUser, pDb, pTable, type, key, false);
44,521✔
1303
  return reserveUserAuthInCacheImpl(key, len, pMetaCache);
44,524✔
1304
}
1305

1306
int32_t reserveViewUserAuthInCache(int32_t acctId, const char* pUser, const char* pDb, const char* pTable,
×
1307
                                   AUTH_TYPE type, SParseMetaCache* pMetaCache) {
1308
  char    key[USER_AUTH_KEY_MAX_LEN] = {0};
×
1309
  int32_t len = userAuthToString(acctId, pUser, pDb, pTable, type, key, true);
×
1310
  return reserveUserAuthInCacheImpl(key, len, pMetaCache);
×
1311
}
1312

1313
int32_t getUserAuthFromCache(SParseMetaCache* pMetaCache, SUserAuthInfo* pAuthReq, SUserAuthRes* pAuthRes) {
496✔
1314
  char          key[USER_AUTH_KEY_MAX_LEN] = {0};
496✔
1315
  int32_t       len = userAuthToString(pAuthReq->tbName.acctId, pAuthReq->user, pAuthReq->tbName.dbname,
496✔
1316
                                       pAuthReq->tbName.tname, pAuthReq->type, key, pAuthReq->isView);
496✔
1317
  SUserAuthRes* pAuth = NULL;
496✔
1318
  int32_t       code = getMetaDataFromHash(key, len, pMetaCache->pUserAuth, (void**)&pAuth);
496✔
1319
  if (TSDB_CODE_SUCCESS == code) {
496✔
1320
    memcpy(pAuthRes, pAuth, sizeof(SUserAuthRes));
496✔
1321
  }
1322
  return code;
496✔
1323
}
1324

1325
int32_t reserveUdfInCache(const char* pFunc, SParseMetaCache* pMetaCache) {
675✔
1326
  if (NULL == pMetaCache->pUdf) {
675✔
1327
    pMetaCache->pUdf = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK);
431✔
1328
    if (NULL == pMetaCache->pUdf) {
431✔
1329
      return terrno;
×
1330
    }
1331
  }
1332
  return taosHashPut(pMetaCache->pUdf, pFunc, strlen(pFunc), &nullPointer, POINTER_BYTES);
675✔
1333
}
1334

1335
int32_t getUdfInfoFromCache(SParseMetaCache* pMetaCache, const char* pFunc, SFuncInfo* pInfo) {
670✔
1336
  SFuncInfo* pFuncInfo = NULL;
670✔
1337
  int32_t    code = getMetaDataFromHash(pFunc, strlen(pFunc), pMetaCache->pUdf, (void**)&pFuncInfo);
670✔
1338
  if (TSDB_CODE_SUCCESS == code) {
670✔
1339
    memcpy(pInfo, pFuncInfo, sizeof(SFuncInfo));
670✔
1340
  }
1341
  return code;
670✔
1342
}
1343

1344
static void destroySmaIndex(void* p) { taosMemoryFree(((STableIndexInfo*)p)->expr); }
×
1345

1346
static SArray* smaIndexesDup(SArray* pSrc) {
×
1347
  SArray* pDst = taosArrayDup(pSrc, NULL);
×
1348
  if (NULL == pDst) {
×
1349
    return NULL;
×
1350
  }
1351
  int32_t size = taosArrayGetSize(pDst);
×
1352
  for (int32_t i = 0; i < size; ++i) {
×
1353
    ((STableIndexInfo*)taosArrayGet(pDst, i))->expr = NULL;
×
1354
  }
1355
  for (int32_t i = 0; i < size; ++i) {
×
1356
    STableIndexInfo* pIndex = taosArrayGet(pDst, i);
×
1357
    pIndex->expr = taosStrdup(((STableIndexInfo*)taosArrayGet(pSrc, i))->expr);
×
1358
    if (NULL == pIndex->expr) {
×
1359
      taosArrayDestroyEx(pDst, destroySmaIndex);
×
1360
      return NULL;
×
1361
    }
1362
  }
1363
  return pDst;
×
1364
}
1365

1366
int32_t reserveTableIndexInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
8✔
1367
  return reserveTableReqInCache(acctId, pDb, pTable, &pMetaCache->pTableIndex);
8✔
1368
}
1369

1370
int32_t reserveTableCfgInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
51✔
1371
  return reserveTableReqInCache(acctId, pDb, pTable, &pMetaCache->pTableCfg);
51✔
1372
}
1373

1374
int32_t reserveTableTSMAInfoInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
8✔
1375
  return reserveTableReqInCache(acctId, pDb, pTable, &pMetaCache->pTableTSMAs);
8✔
1376
}
1377

1378
int32_t reserveTSMAInfoInCache(int32_t acctId, const char* pDb, const char* pTsmaName, SParseMetaCache* pMetaCache) {
×
1379
  return reserveTableReqInDbCache(acctId, pDb, pTsmaName, &pMetaCache->pTSMAs);
×
1380
}
1381

1382
int32_t reserveVSubTableInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
26✔
1383
  SName fullName = {0};
26✔
1384
  toName(acctId, pDb, pTable, &fullName);
26✔
1385
  
1386
  if (NULL == pMetaCache->pVSubTables) {
26✔
1387
    pMetaCache->pVSubTables = taosArrayInit(1, sizeof(fullName));
26✔
1388
    if (NULL == pMetaCache->pVSubTables) {
26✔
1389
      return terrno;
×
1390
    }
1391
  }
1392
  if (NULL == taosArrayPush(pMetaCache->pVSubTables, &fullName)) {
52✔
1393
    return terrno;
×
1394
  }
1395
  
1396
  return TSDB_CODE_SUCCESS;
26✔
1397
}
1398

1399
int32_t reserveVStbRefDbsInCache(int32_t acctId, const char* pDb, const char* pTable, SParseMetaCache* pMetaCache) {
6,346✔
1400
  int32_t code = TSDB_CODE_SUCCESS;
6,346✔
1401
  int32_t line = 0;
6,346✔
1402
  SName   fullName = {0};
6,346✔
1403
  toName(acctId, pDb, pTable, &fullName);
6,346✔
1404

1405
  if (NULL == pMetaCache->pVStbRefDbs) {
6,350✔
1406
    pMetaCache->pVStbRefDbs = taosArrayInit(1, sizeof(fullName));
6,317✔
1407
    QUERY_CHECK_NULL(pMetaCache->pVStbRefDbs, code, line, _return, terrno);
6,320✔
1408
  }
1409

1410
  QUERY_CHECK_NULL(taosArrayPush(pMetaCache->pVStbRefDbs, &fullName), code, line, _return, terrno);
12,707✔
1411
  return code;
6,354✔
1412

1413
_return:
×
1414
  if (code) {
×
1415
    qError("%s failed, code:%d", __func__, code);
×
1416
  }
1417
  return code;
×
1418
}
1419

1420
int32_t getTableIndexFromCache(SParseMetaCache* pMetaCache, const SName* pName, SArray** pIndexes) {
×
1421
  char    fullName[TSDB_TABLE_FNAME_LEN];
1422
  int32_t code = tNameExtractFullName(pName, fullName);
×
1423
  if (TSDB_CODE_SUCCESS != code) return code;
×
1424
  ;
1425
  SArray* pSmaIndexes = NULL;
×
1426
  code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pTableIndex, (void**)&pSmaIndexes);
×
1427
  if (TSDB_CODE_SUCCESS == code && NULL != pSmaIndexes) {
×
1428
    *pIndexes = smaIndexesDup(pSmaIndexes);
×
1429
    if (NULL == *pIndexes) {
×
1430
      code = TSDB_CODE_OUT_OF_MEMORY;
×
1431
    }
1432
  }
1433
  return code;
×
1434
}
1435

1436
int32_t getTableTsmasFromCache(SParseMetaCache* pMetaCache, const SName* pTbName, SArray** pTsmas) {
702✔
1437
  char    tbFName[TSDB_TABLE_FNAME_LEN];
1438
  int32_t code = tNameExtractFullName(pTbName, tbFName);
702✔
1439
  if (TSDB_CODE_SUCCESS != code) {
702✔
1440
    return code;
×
1441
  }
1442
  STableTSMAInfoRsp* pTsmasRsp = NULL;
702✔
1443
  code = getMetaDataFromHash(tbFName, strlen(tbFName), pMetaCache->pTableTSMAs, (void**)&pTsmasRsp);
702✔
1444
  if (TSDB_CODE_SUCCESS == code && pTsmasRsp) {
702✔
1445
    *pTsmas = pTsmasRsp->pTsmas;
×
1446
  }
1447
  return TSDB_CODE_SUCCESS;
702✔
1448
}
1449

1450
int32_t getTsmaFromCache(SParseMetaCache* pMetaCache, const SName* pTsmaName, STableTSMAInfo** pTsma) {
×
1451
  char    tsmaFName[TSDB_TABLE_FNAME_LEN];
1452
  int32_t code = tNameExtractFullName(pTsmaName, tsmaFName);
×
1453
  if (TSDB_CODE_SUCCESS != code) {
×
1454
    return code;
×
1455
  }
1456
  STableTSMAInfoRsp* pTsmaRsp = NULL;
×
1457
  code = getMetaDataFromHash(tsmaFName, strlen(tsmaFName), pMetaCache->pTSMAs, (void**)&pTsmaRsp);
×
1458
  if (TSDB_CODE_SUCCESS == code) {
×
1459
    if (!pTsmaRsp || pTsmaRsp->pTsmas->size != 1) {
×
1460
      return TSDB_CODE_PAR_INTERNAL_ERROR;
×
1461
    }
1462
    *pTsma = taosArrayGetP(pTsmaRsp->pTsmas, 0);
×
1463
  } else if (code == TSDB_CODE_PAR_INTERNAL_ERROR) {
×
1464
    code = TSDB_CODE_MND_SMA_NOT_EXIST;
×
1465
  }
1466
  return code;
×
1467
}
1468

1469
STableCfg* tableCfgDup(STableCfg* pCfg) {
49✔
1470
  STableCfg* pNew = taosMemoryMalloc(sizeof(*pNew));
49✔
1471
  if (!pNew) {
49✔
1472
    return NULL;
×
1473
  }
1474
  memcpy(pNew, pCfg, sizeof(*pNew));
49✔
1475
  pNew->pComment = NULL;
49✔
1476
  pNew->pFuncs = NULL;
49✔
1477
  pNew->pTags = NULL;
49✔
1478
  pNew->pSchemas = NULL;
49✔
1479
  pNew->pSchemaExt = NULL;
49✔
1480
  pNew->pColRefs = NULL;
49✔
1481
  if (NULL != pCfg->pComment) {
49✔
1482
    pNew->pComment = taosMemoryCalloc(pNew->commentLen + 1, 1);
×
1483
    if (!pNew->pComment) goto err;
×
1484
    memcpy(pNew->pComment, pCfg->pComment, pNew->commentLen);
×
1485
  }
1486
  if (NULL != pCfg->pFuncs) {
49✔
1487
    pNew->pFuncs = taosArrayDup(pCfg->pFuncs, NULL);
×
1488
    if (!pNew->pFuncs) goto err;
×
1489
  }
1490
  if (NULL != pCfg->pTags) {
49✔
1491
    pNew->pTags = taosMemoryCalloc(pCfg->tagsLen + 1, 1);
×
1492
    if (!pNew->pTags) goto err;
×
1493
    memcpy(pNew->pTags, pCfg->pTags, pNew->tagsLen);
×
1494
  }
1495

1496
  int32_t schemaSize = (pCfg->numOfColumns + pCfg->numOfTags) * sizeof(SSchema);
49✔
1497

1498
  SSchema* pSchema = taosMemoryMalloc(schemaSize);
49✔
1499
  if (!pSchema) goto err;
49✔
1500
  memcpy(pSchema, pCfg->pSchemas, schemaSize);
49✔
1501
  pNew->pSchemas = pSchema;
49✔
1502

1503
  SSchemaExt* pSchemaExt = NULL;
49✔
1504
  if (withExtSchema(pCfg->tableType) && pCfg->pSchemaExt) {
49✔
1505
    int32_t schemaExtSize = pCfg->numOfColumns * sizeof(SSchemaExt);
47✔
1506
    pSchemaExt = taosMemoryMalloc(schemaExtSize);
47✔
1507
    if (!pSchemaExt) goto err;
47✔
1508
    memcpy(pSchemaExt, pCfg->pSchemaExt, schemaExtSize);
47✔
1509
  }
1510

1511
  pNew->pSchemaExt = pSchemaExt;
49✔
1512

1513
  SColRef *pColRef = NULL;
49✔
1514
  if (hasRefCol(pCfg->tableType) && pCfg->pColRefs) {
49✔
1515
    int32_t colRefSize = pCfg->numOfColumns * sizeof(SColRef);
×
1516
    pColRef = taosMemoryMalloc(colRefSize);
×
1517
    if (!pColRef) goto err;
×
1518
    memcpy(pColRef, pCfg->pColRefs, colRefSize);
×
1519
  }
1520

1521
  pNew->pColRefs = pColRef;
49✔
1522

1523
  return pNew;
49✔
1524
err:
×
1525
  if (pNew->pComment) taosMemoryFreeClear(pNew->pComment);
×
1526
  if (pNew->pFuncs) taosArrayDestroy(pNew->pFuncs);
×
1527
  if (pNew->pTags) taosMemoryFreeClear(pNew->pTags);
×
1528
  if (pNew->pSchemas) taosMemoryFreeClear(pNew->pSchemas);
×
1529
  if (pNew->pSchemaExt) taosMemoryFreeClear(pNew->pSchemaExt);
×
1530
  taosMemoryFreeClear(pNew);
×
1531
  return NULL;
×
1532
}
1533

1534
int32_t getTableCfgFromCache(SParseMetaCache* pMetaCache, const SName* pName, STableCfg** pOutput) {
49✔
1535
  char    fullName[TSDB_TABLE_FNAME_LEN];
1536
  int32_t code = tNameExtractFullName(pName, fullName);
49✔
1537
  if (TSDB_CODE_SUCCESS != code) {
49✔
1538
    return code;
×
1539
  }
1540
  STableCfg* pCfg = NULL;
49✔
1541
  code = getMetaDataFromHash(fullName, strlen(fullName), pMetaCache->pTableCfg, (void**)&pCfg);
49✔
1542
  if (TSDB_CODE_SUCCESS == code && NULL != pCfg) {
49✔
1543
    *pOutput = tableCfgDup(pCfg);
49✔
1544
    if (NULL == *pOutput) {
49✔
1545
      code = TSDB_CODE_OUT_OF_MEMORY;
×
1546
    }
1547
  }
1548
  return code;
49✔
1549
}
1550

1551
int32_t reserveDnodeRequiredInCache(SParseMetaCache* pMetaCache) {
4✔
1552
  pMetaCache->dnodeRequired = true;
4✔
1553
  return TSDB_CODE_SUCCESS;
4✔
1554
}
1555

1556
int32_t getDnodeListFromCache(SParseMetaCache* pMetaCache, SArray** pDnodes) {
2✔
1557
  SMetaRes* pRes = taosArrayGet(pMetaCache->pDnodes, 0);
2✔
1558
  if (TSDB_CODE_SUCCESS != pRes->code) {
2✔
1559
    return pRes->code;
×
1560
  }
1561

1562
  *pDnodes = taosArrayDup((SArray*)pRes->pRes, NULL);
2✔
1563
  if (NULL == *pDnodes) {
2✔
1564
    return terrno;
×
1565
  }
1566
  return TSDB_CODE_SUCCESS;
2✔
1567
}
1568

1569
void destoryParseTablesMetaReqHash(SHashObj* pHash) {
226,284✔
1570
  SParseTablesMetaReq* p = taosHashIterate(pHash, NULL);
226,284✔
1571
  while (NULL != p) {
310,838✔
1572
    taosHashCleanup(p->pTables);
84,533✔
1573
    p = taosHashIterate(pHash, p);
84,526✔
1574
  }
1575
  taosHashCleanup(pHash);
226,305✔
1576
}
226,315✔
1577

1578
void destoryParseMetaCache(SParseMetaCache* pMetaCache, bool request) {
90,382✔
1579
  if (request) {
90,382✔
1580
    destoryParseTablesMetaReqHash(pMetaCache->pTableMeta);
45,261✔
1581
    destoryParseTablesMetaReqHash(pMetaCache->pTableVgroup);
45,274✔
1582
    destoryParseTablesMetaReqHash(pMetaCache->pViews);
45,273✔
1583
    destoryParseTablesMetaReqHash(pMetaCache->pTSMAs);
45,273✔
1584
    destoryParseTablesMetaReqHash(pMetaCache->pTableName);
45,275✔
1585
  } else {
1586
    taosHashCleanup(pMetaCache->pTableMeta);
45,121✔
1587
    taosHashCleanup(pMetaCache->pTableVgroup);
45,244✔
1588
    taosHashCleanup(pMetaCache->pViews);
45,242✔
1589
    taosHashCleanup(pMetaCache->pTSMAs);
45,247✔
1590
    taosHashCleanup(pMetaCache->pTableName);
45,245✔
1591
  }
1592
  taosHashCleanup(pMetaCache->pDbVgroup);
90,520✔
1593
  taosHashCleanup(pMetaCache->pDbCfg);
90,499✔
1594
  taosHashCleanup(pMetaCache->pDbInfo);
90,522✔
1595
  taosHashCleanup(pMetaCache->pUserAuth);
90,523✔
1596
  taosHashCleanup(pMetaCache->pUdf);
90,522✔
1597
  taosHashCleanup(pMetaCache->pTableIndex);
90,510✔
1598
  taosHashCleanup(pMetaCache->pTableCfg);
90,514✔
1599
  taosHashCleanup(pMetaCache->pTableTSMAs);
90,520✔
1600
  taosArrayDestroyEx(pMetaCache->pVSubTables, tDestroySVSubTablesRsp);
90,521✔
1601
  taosArrayDestroyEx(pMetaCache->pVStbRefDbs, tDestroySVStbRefDbsRsp);
90,493✔
1602
}
90,499✔
1603

1604
int64_t int64SafeSub(int64_t a, int64_t b) {
31✔
1605
  int64_t res = (uint64_t)a - (uint64_t)b;
31✔
1606

1607
  if (a >= 0 && b < 0) {
31✔
1608
    if ((uint64_t)res > (uint64_t)INT64_MAX) {
×
1609
      // overflow
1610
      res = INT64_MAX;
×
1611
    }
1612
  } else if (a < 0 && b > 0 && res >= 0) {
31✔
1613
    // underflow
1614
    res = INT64_MIN;
×
1615
  }
1616
  return res;
31✔
1617
}
1618

1619
STypeMod calcTypeMod(const SDataType* pType) {
38,615✔
1620
  if (IS_DECIMAL_TYPE(pType->type)) {
38,615✔
1621
    return decimalCalcTypeMod(pType->precision, pType->scale);
284✔
1622
  }
1623
  return 0;
38,331✔
1624
}
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