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

H
hjxilinx 已提交
16
#include "qast.h"
17 18
#include <tarray.h>
#include <tskiplist.h>
S
slguan 已提交
19
#include "os.h"
20 21
#include "qsqlparser.h"
#include "qsyntaxtreefunction.h"
22
#include "taosdef.h"
H
hzcheng 已提交
23 24 25
#include "taosmsg.h"
#include "tlog.h"
#include "tsqlfunction.h"
H
hjxilinx 已提交
26
#include "tstoken.h"
27
#include "ttokendef.h"
H
hzcheng 已提交
28 29 30 31 32 33 34 35 36 37 38 39 40 41
#include "tutil.h"

/*
 *
 * @date 2018-2-15
 * @version 0.2  operation for column filter
 * @author liaohj
 *
 * @Description parse tag query expression to build ast
 * ver 0.2, filter the result on first column with high priority to limit the candidate set
 * ver 0.3, pipeline filter in the form of: (a+2)/9 > 14
 *
 */

S
slguan 已提交
42
static tSQLSyntaxNode *tSQLSyntaxNodeCreate(SSchema *pSchema, int32_t numOfCols, SSQLToken *pToken);
H
hjxilinx 已提交
43
static void            tSQLSyntaxNodeDestroy(tSQLSyntaxNode *pNode, void (*fp)(void *));
H
hzcheng 已提交
44

S
slguan 已提交
45
static tSQLSyntaxNode *createSyntaxTree(SSchema *pSchema, int32_t numOfCols, char *str, int32_t *i);
H
hjxilinx 已提交
46
static void            destroySyntaxTree(tSQLSyntaxNode *);
H
hzcheng 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

static uint8_t isQueryOnPrimaryKey(const char *primaryColumnName, const tSQLSyntaxNode *pLeft,
                                   const tSQLSyntaxNode *pRight);

/*
 * Check the filter value type on the right hand side based on the column id on the left hand side,
 * the filter value type must be identical to field type for relational operation
 * As for binary arithmetic operation, it is not necessary to do so.
 */
static void reviseBinaryExprIfNecessary(tSQLSyntaxNode **pLeft, tSQLSyntaxNode **pRight, uint8_t *optr) {
  if (*optr >= TSDB_RELATION_LESS && *optr <= TSDB_RELATION_LIKE) {
    // make sure that the type of data on both sides of relational comparision are identical
    if ((*pLeft)->nodeType == TSQL_NODE_VALUE) {
      tVariantTypeSetType((*pLeft)->pVal, (*pRight)->pSchema->type);
    } else if ((*pRight)->nodeType == TSQL_NODE_VALUE) {
      tVariantTypeSetType((*pRight)->pVal, (*pLeft)->pSchema->type);
    }

  } else if (*optr >= TSDB_BINARY_OP_ADD && *optr <= TSDB_BINARY_OP_REMAINDER) {
    if ((*pLeft)->nodeType == TSQL_NODE_VALUE) {
      /* convert to int/bigint may cause the precision loss */
      tVariantTypeSetType((*pLeft)->pVal, TSDB_DATA_TYPE_DOUBLE);
    } else if ((*pRight)->nodeType == TSQL_NODE_VALUE) {
      /* convert to int/bigint may cause the precision loss */
      tVariantTypeSetType((*pRight)->pVal, TSDB_DATA_TYPE_DOUBLE);
    }
  }

S
slguan 已提交
75 76 77 78
  /*
   * for expressions that are suitable for switch principle,
   * switch left and left and right hand side in expr if possible
   */
H
hzcheng 已提交
79
  if ((*pLeft)->nodeType == TSQL_NODE_VALUE && (*pRight)->nodeType == TSQL_NODE_COL) {
S
slguan 已提交
80 81 82
    if (*optr >= TSDB_RELATION_LARGE && *optr <= TSDB_RELATION_LARGE_EQUAL && *optr != TSDB_RELATION_EQUAL) {
      SWAP(*pLeft, *pRight, tSQLSyntaxNode *);
    }
H
hzcheng 已提交
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

    switch (*optr) {
      case TSDB_RELATION_LARGE:
        (*optr) = TSDB_RELATION_LESS;
        break;
      case TSDB_RELATION_LESS:
        (*optr) = TSDB_RELATION_LARGE;
        break;
      case TSDB_RELATION_LARGE_EQUAL:
        (*optr) = TSDB_RELATION_LESS_EQUAL;
        break;
      case TSDB_RELATION_LESS_EQUAL:
        (*optr) = TSDB_RELATION_LARGE_EQUAL;
        break;
      default:;
        // for other type of operations, do nothing
    }
  }
}

S
slguan 已提交
103
static tSQLSyntaxNode *tSQLSyntaxNodeCreate(SSchema *pSchema, int32_t numOfCols, SSQLToken *pToken) {
H
hzcheng 已提交
104 105 106 107 108 109 110 111 112 113
  /* if the token is not a value, return false */
  if (pToken->type == TK_RP || (pToken->type != TK_INTEGER && pToken->type != TK_FLOAT && pToken->type != TK_ID &&
                                pToken->type != TK_TBNAME && pToken->type != TK_STRING && pToken->type != TK_BOOL)) {
    return NULL;
  }

  size_t          nodeSize = sizeof(tSQLSyntaxNode);
  tSQLSyntaxNode *pNode = NULL;

  if (pToken->type == TK_ID || pToken->type == TK_TBNAME) {
H
hjxilinx 已提交
114
    int32_t i = 0;
H
hzcheng 已提交
115 116
    if (pToken->type == TK_ID) {
      do {
117 118
        SSQLToken tableToken = {0};
        extractTableNameFromToken(pToken, &tableToken);
119

H
hzcheng 已提交
120 121 122 123
        size_t len = strlen(pSchema[i].name);
        if (strncmp(pToken->z, pSchema[i].name, pToken->n) == 0 && pToken->n == len) break;
      } while (++i < numOfCols);

S
slguan 已提交
124
      if (i == numOfCols) {  // column name is not valid, parse the expression failed
H
hzcheng 已提交
125 126 127 128
        return NULL;
      }
    }

S
slguan 已提交
129
    nodeSize += sizeof(SSchema);
H
hzcheng 已提交
130

S
slguan 已提交
131
    pNode = calloc(1, nodeSize);
S
slguan 已提交
132
    pNode->pSchema = (struct SSchema *)((char *)pNode + sizeof(tSQLSyntaxNode));
H
hzcheng 已提交
133 134 135 136
    pNode->nodeType = TSQL_NODE_COL;

    if (pToken->type == TK_ID) {
      pNode->colId = (int16_t)pSchema[i].colId;
S
slguan 已提交
137
      memcpy(pNode->pSchema, &pSchema[i], sizeof(SSchema));
H
hzcheng 已提交
138 139 140
    } else {
      pNode->colId = -1;
      pNode->pSchema->type = TSDB_DATA_TYPE_BINARY;
S
slguan 已提交
141
      pNode->pSchema->bytes = TSDB_TABLE_NAME_LEN;
H
hzcheng 已提交
142 143 144 145 146 147
      strcpy(pNode->pSchema->name, TSQL_TBNAME_L);
      pNode->pSchema->colId = -1;
    }

  } else {
    nodeSize += sizeof(tVariant);
S
slguan 已提交
148
    pNode = calloc(1, nodeSize);
H
hzcheng 已提交
149 150 151 152 153 154 155 156 157 158 159
    pNode->pVal = (tVariant *)((char *)pNode + sizeof(tSQLSyntaxNode));

    toTSDBType(pToken->type);
    tVariantCreate(pNode->pVal, pToken);
    pNode->nodeType = TSQL_NODE_VALUE;
    pNode->colId = -1;
  }

  return pNode;
}

H
hjxilinx 已提交
160
uint8_t getBinaryExprOptr(SSQLToken *pToken) {
H
hzcheng 已提交
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
  switch (pToken->type) {
    case TK_LT:
      return TSDB_RELATION_LESS;
    case TK_LE:
      return TSDB_RELATION_LESS_EQUAL;
    case TK_GT:
      return TSDB_RELATION_LARGE;
    case TK_GE:
      return TSDB_RELATION_LARGE_EQUAL;
    case TK_NE:
      return TSDB_RELATION_NOT_EQUAL;
    case TK_AND:
      return TSDB_RELATION_AND;
    case TK_OR:
      return TSDB_RELATION_OR;
    case TK_EQ:
      return TSDB_RELATION_EQUAL;
    case TK_PLUS:
      return TSDB_BINARY_OP_ADD;
    case TK_MINUS:
      return TSDB_BINARY_OP_SUBTRACT;
    case TK_STAR:
      return TSDB_BINARY_OP_MULTIPLY;
    case TK_SLASH:
H
hjxilinx 已提交
185
    case TK_DIVIDE:
H
hzcheng 已提交
186 187 188 189 190 191 192 193 194 195
      return TSDB_BINARY_OP_DIVIDE;
    case TK_REM:
      return TSDB_BINARY_OP_REMAINDER;
    case TK_LIKE:
      return TSDB_RELATION_LIKE;
    default: { return 0; }
  }
}

// previous generated expr is reduced as the left child
S
slguan 已提交
196
static tSQLSyntaxNode *parseRemainStr(char *pstr, tSQLBinaryExpr *pExpr, SSchema *pSchema, int32_t optr,
H
hzcheng 已提交
197 198 199 200 201 202 203 204 205 206
                                      int32_t numOfCols, int32_t *i) {
  // set the previous generated node as the left child of new root
  tSQLSyntaxNode *pLeft = malloc(sizeof(tSQLSyntaxNode));
  pLeft->nodeType = TSQL_NODE_EXPR;
  pLeft->pExpr = pExpr;

  // remain is the right child
  tSQLSyntaxNode *pRight = createSyntaxTree(pSchema, numOfCols, pstr, i);
  if (pRight == NULL || (pRight->nodeType == TSQL_NODE_COL && pLeft->nodeType != TSQL_NODE_VALUE) ||
      (pLeft->nodeType == TSQL_NODE_VALUE && pRight->nodeType != TSQL_NODE_COL)) {
S
slguan 已提交
207 208
    tSQLSyntaxNodeDestroy(pLeft, NULL);
    tSQLSyntaxNodeDestroy(pRight, NULL);
H
hzcheng 已提交
209 210 211
    return NULL;
  }

S
slguan 已提交
212
  tSQLBinaryExpr *pNewExpr = (tSQLBinaryExpr *)calloc(1, sizeof(tSQLBinaryExpr));
H
hzcheng 已提交
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
  uint8_t         k = optr;
  reviseBinaryExprIfNecessary(&pLeft, &pRight, &k);
  pNewExpr->pLeft = pLeft;
  pNewExpr->pRight = pRight;
  pNewExpr->nSQLBinaryOptr = k;

  pNewExpr->filterOnPrimaryKey = isQueryOnPrimaryKey(pSchema[0].name, pLeft, pRight);

  tSQLSyntaxNode *pn = malloc(sizeof(tSQLSyntaxNode));
  pn->nodeType = TSQL_NODE_EXPR;
  pn->pExpr = pNewExpr;

  return pn;
}

uint8_t isQueryOnPrimaryKey(const char *primaryColumnName, const tSQLSyntaxNode *pLeft, const tSQLSyntaxNode *pRight) {
  if (pLeft->nodeType == TSQL_NODE_COL) {
    // if left node is the primary column,return true
    return (strcmp(primaryColumnName, pLeft->pSchema->name) == 0) ? 1 : 0;
  } else {
S
slguan 已提交
233
    // if any children have query on primary key, their parents are also keep this value
H
hzcheng 已提交
234 235 236 237 238 239 240
    return ((pLeft->nodeType == TSQL_NODE_EXPR && pLeft->pExpr->filterOnPrimaryKey == 1) ||
            (pRight->nodeType == TSQL_NODE_EXPR && pRight->pExpr->filterOnPrimaryKey == 1)) == true
               ? 1
               : 0;
  }
}

S
slguan 已提交
241
static tSQLSyntaxNode *createSyntaxTree(SSchema *pSchema, int32_t numOfCols, char *str, int32_t *i) {
S
slguan 已提交
242
  SSQLToken t0;
H
hzcheng 已提交
243

S
slguan 已提交
244
  t0 = tStrGetToken(str, i, false, 0, NULL);
H
hzcheng 已提交
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
  if (t0.n == 0) {
    return NULL;
  }

  tSQLSyntaxNode *pLeft = NULL;
  if (t0.type == TK_LP) {  // start new left child branch
    pLeft = createSyntaxTree(pSchema, numOfCols, str, i);
  } else {
    if (t0.type == TK_RP) {
      return NULL;
    }
    pLeft = tSQLSyntaxNodeCreate(pSchema, numOfCols, &t0);
  }

  if (pLeft == NULL) {
    return NULL;
  }

S
slguan 已提交
263
  t0 = tStrGetToken(str, i, false, 0, NULL);
H
hzcheng 已提交
264
  if (t0.n == 0 || t0.type == TK_RP) {
H
hjxilinx 已提交
265
    if (pLeft->nodeType != TSQL_NODE_EXPR) {  // if left is not the expr, it is not a legal expr
S
slguan 已提交
266
      tSQLSyntaxNodeDestroy(pLeft, NULL);
H
hzcheng 已提交
267 268 269 270 271 272 273
      return NULL;
    }

    return pLeft;
  }

  // get the operator of expr
274
  uint8_t optr = getBinaryExprOptr(&t0);
S
slguan 已提交
275
  if (optr == 0) {
H
hzcheng 已提交
276
    pError("not support binary operator:%d", t0.type);
S
slguan 已提交
277
    tSQLSyntaxNodeDestroy(pLeft, NULL);
H
hzcheng 已提交
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
    return NULL;
  }

  assert(pLeft != NULL);
  tSQLSyntaxNode *pRight = NULL;

  if (t0.type == TK_AND || t0.type == TK_OR || t0.type == TK_LP) {
    pRight = createSyntaxTree(pSchema, numOfCols, str, i);
  } else {
    /*
     * In case that pLeft is a field identification,
     * we parse the value in expression according to queried field type,
     * if we do not get the information, in case of value of field presented first,
     * we revised the value after the binary expression is completed.
     */
S
slguan 已提交
293
    t0 = tStrGetToken(str, i, true, 0, NULL);
H
hzcheng 已提交
294
    if (t0.n == 0) {
S
slguan 已提交
295
      tSQLSyntaxNodeDestroy(pLeft, NULL);  // illegal expression
H
hzcheng 已提交
296 297 298 299 300 301 302 303 304 305 306
      return NULL;
    }

    if (t0.type == TK_LP) {
      pRight = createSyntaxTree(pSchema, numOfCols, str, i);
    } else {
      pRight = tSQLSyntaxNodeCreate(pSchema, numOfCols, &t0);
    }
  }

  if (pRight == NULL) {
S
slguan 已提交
307
    tSQLSyntaxNodeDestroy(pLeft, NULL);
H
hzcheng 已提交
308 309 310 311
    return NULL;
  }

  /* create binary expr as the child of new parent node */
S
slguan 已提交
312
  tSQLBinaryExpr *pBinExpr = (tSQLBinaryExpr *)calloc(1, sizeof(tSQLBinaryExpr));
H
hzcheng 已提交
313 314 315 316 317 318 319
  reviseBinaryExprIfNecessary(&pLeft, &pRight, &optr);

  pBinExpr->filterOnPrimaryKey = isQueryOnPrimaryKey(pSchema[0].name, pLeft, pRight);
  pBinExpr->pLeft = pLeft;
  pBinExpr->pRight = pRight;
  pBinExpr->nSQLBinaryOptr = optr;

S
slguan 已提交
320
  t0 = tStrGetToken(str, i, true, 0, NULL);
H
hzcheng 已提交
321 322 323 324 325 326 327 328

  if (t0.n == 0 || t0.type == TK_RP) {
    tSQLSyntaxNode *pn = malloc(sizeof(tSQLSyntaxNode));
    pn->nodeType = TSQL_NODE_EXPR;
    pn->pExpr = pBinExpr;
    pn->colId = -1;
    return pn;
  } else {
329
    uint8_t localOptr = getBinaryExprOptr(&t0);
S
slguan 已提交
330
    if (localOptr == 0) {
H
hzcheng 已提交
331
      pError("not support binary operator:%d", t0.type);
H
hjxilinx 已提交
332
      free(pBinExpr);
H
hzcheng 已提交
333 334 335
      return NULL;
    }

336
    return parseRemainStr(str, pBinExpr, pSchema, localOptr, numOfCols, i);
H
hzcheng 已提交
337 338 339
  }
}

S
slguan 已提交
340
void tSQLBinaryExprFromString(tSQLBinaryExpr **pExpr, SSchema *pSchema, int32_t numOfCols, char *src, int32_t len) {
H
hzcheng 已提交
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
  *pExpr = NULL;
  if (len <= 0 || src == NULL || pSchema == NULL || numOfCols <= 0) {
    return;
  }

  int32_t         pos = 0;
  tSQLSyntaxNode *pStxNode = createSyntaxTree(pSchema, numOfCols, src, &pos);
  if (pStxNode != NULL) {
    assert(pStxNode->nodeType == TSQL_NODE_EXPR);
    *pExpr = pStxNode->pExpr;
    free(pStxNode);
  }
}

int32_t tSQLBinaryExprToStringImpl(tSQLSyntaxNode *pNode, char *dst, uint8_t type) {
  int32_t len = 0;
  if (type == TSQL_NODE_EXPR) {
    *dst = '(';
    tSQLBinaryExprToString(pNode->pExpr, dst + 1, &len);
    len += 2;
    *(dst + len - 1) = ')';
  } else if (type == TSQL_NODE_COL) {
    len = sprintf(dst, "%s", pNode->pSchema->name);
  } else {
    len = tVariantToString(pNode->pVal, dst);
  }
  return len;
}

S
slguan 已提交
370
// TODO REFACTOR WITH SQL PARSER
H
hzcheng 已提交
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
static char *tSQLOptrToString(uint8_t optr, char *dst) {
  switch (optr) {
    case TSDB_RELATION_LESS: {
      *dst = '<';
      dst += 1;
      break;
    }
    case TSDB_RELATION_LESS_EQUAL: {
      *dst = '<';
      *(dst + 1) = '=';
      dst += 2;
      break;
    }
    case TSDB_RELATION_EQUAL: {
      *dst = '=';
      dst += 1;
      break;
    }
    case TSDB_RELATION_LARGE: {
      *dst = '>';
      dst += 1;
      break;
    }
    case TSDB_RELATION_LARGE_EQUAL: {
      *dst = '>';
      *(dst + 1) = '=';
      dst += 2;
      break;
    }
    case TSDB_RELATION_NOT_EQUAL: {
      *dst = '<';
      *(dst + 1) = '>';
      dst += 2;
      break;
    }
    case TSDB_RELATION_OR: {
      memcpy(dst, "or", 2);
      dst += 2;
      break;
    }
    case TSDB_RELATION_AND: {
      memcpy(dst, "and", 3);
      dst += 3;
      break;
    }
    default:;
  }
  return dst;
}

void tSQLBinaryExprToString(tSQLBinaryExpr *pExpr, char *dst, int32_t *len) {
  if (pExpr == NULL) {
    *dst = 0;
    *len = 0;
425
    return;
H
hzcheng 已提交
426 427
  }

428
  int32_t lhs = tSQLBinaryExprToStringImpl(pExpr->pLeft, dst, pExpr->pLeft->nodeType);
H
hzcheng 已提交
429 430 431
  dst += lhs;
  *len = lhs;

432
  char *start = tSQLOptrToString(pExpr->nSQLBinaryOptr, dst);
H
hzcheng 已提交
433 434
  *len += (start - dst);

435
  *len += tSQLBinaryExprToStringImpl(pExpr->pRight, start, pExpr->pRight->nodeType);
H
hzcheng 已提交
436 437
}

S
slguan 已提交
438
static void UNUSED_FUNC destroySyntaxTree(tSQLSyntaxNode *pNode) { tSQLSyntaxNodeDestroy(pNode, NULL); }
H
hzcheng 已提交
439

S
slguan 已提交
440 441 442 443
static void tSQLSyntaxNodeDestroy(tSQLSyntaxNode *pNode, void (*fp)(void *)) {
  if (pNode == NULL) {
    return;
  }
H
hzcheng 已提交
444 445

  if (pNode->nodeType == TSQL_NODE_EXPR) {
S
slguan 已提交
446
    tSQLBinaryExprDestroy(&pNode->pExpr, fp);
H
hzcheng 已提交
447 448 449 450 451 452 453
  } else if (pNode->nodeType == TSQL_NODE_VALUE) {
    tVariantDestroy(pNode->pVal);
  }

  free(pNode);
}

S
slguan 已提交
454 455 456
void tSQLBinaryExprDestroy(tSQLBinaryExpr **pExpr, void (*fp)(void *)) {
  if (*pExpr == NULL) {
    return;
H
hzcheng 已提交
457 458
  }

S
slguan 已提交
459 460
  tSQLSyntaxNodeDestroy((*pExpr)->pLeft, fp);
  tSQLSyntaxNodeDestroy((*pExpr)->pRight, fp);
H
hzcheng 已提交
461

S
slguan 已提交
462 463
  if (fp != NULL) {
    fp((*pExpr)->info);
H
hzcheng 已提交
464 465
  }

S
slguan 已提交
466 467
  free(*pExpr);
  *pExpr = NULL;
H
hzcheng 已提交
468 469
}

470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
//static void setInitialValueForRangeQueryCondition(tSKipListQueryCond *q, int8_t type) {
//  q->lowerBndRelOptr = TSDB_RELATION_LARGE;
//  q->upperBndRelOptr = TSDB_RELATION_LESS;
//
//  switch (type) {
//    case TSDB_DATA_TYPE_BOOL:
//    case TSDB_DATA_TYPE_TINYINT:
//    case TSDB_DATA_TYPE_SMALLINT:
//    case TSDB_DATA_TYPE_INT:
//    case TSDB_DATA_TYPE_BIGINT: {
//      q->upperBnd.nType = TSDB_DATA_TYPE_BIGINT;
//      q->lowerBnd.nType = TSDB_DATA_TYPE_BIGINT;
//
//      q->upperBnd.i64Key = INT64_MAX;
//      q->lowerBnd.i64Key = INT64_MIN;
//      break;
//    };
//    case TSDB_DATA_TYPE_FLOAT:
//    case TSDB_DATA_TYPE_DOUBLE: {
//      q->upperBnd.nType = TSDB_DATA_TYPE_DOUBLE;
//      q->lowerBnd.nType = TSDB_DATA_TYPE_DOUBLE;
//      q->upperBnd.dKey = DBL_MAX;
//      q->lowerBnd.dKey = -DBL_MIN;
//      break;
//    };
//    case TSDB_DATA_TYPE_NCHAR:
//    case TSDB_DATA_TYPE_BINARY: {
//      q->upperBnd.nType = type;
//      q->upperBnd.pz = NULL;
//      q->upperBnd.nLen = -1;
//
//      q->lowerBnd.nType = type;
//      q->lowerBnd.pz = NULL;
//      q->lowerBnd.nLen = -1;
//    }
//  }
//}

//static void tSQLDoFilterInitialResult(tSkipList *pSkipList, bool (*fp)(), tQueryInfo *queryColInfo,
//                                      tQueryResultset *result) {
//  // primary key filter, search according to skiplist
//  if (queryColInfo->colIdx == 0 && queryColInfo->optr != TSDB_RELATION_LIKE) {
//    tSKipListQueryCond q;
//    setInitialValueForRangeQueryCondition(&q, queryColInfo->q.nType);
//
//    switch (queryColInfo->optr) {
//      case TSDB_RELATION_EQUAL: {
//        result->num =
//            tSkipListPointQuery(pSkipList, &queryColInfo->q, 1, INCLUDE_POINT_QUERY, (tSkipListNode ***)&result->pRes);
//        break;
//      }
//      case TSDB_RELATION_NOT_EQUAL: {
//        result->num =
//            tSkipListPointQuery(pSkipList, &queryColInfo->q, 1, EXCLUDE_POINT_QUERY, (tSkipListNode ***)&result->pRes);
//        break;
//      }
//      case TSDB_RELATION_LESS_EQUAL: {
//        tVariantAssign(&q.upperBnd, &queryColInfo->q);
//        q.upperBndRelOptr = queryColInfo->optr;
//        result->num = tSkipListQuery(pSkipList, &q, (tSkipListNode ***)&result->pRes);
//        break;
//      }
//      case TSDB_RELATION_LESS: {
//        tVariantAssign(&q.upperBnd, &queryColInfo->q);
//        result->num = tSkipListQuery(pSkipList, &q, (tSkipListNode ***)&result->pRes);
//        break;
//      }
//      case TSDB_RELATION_LARGE: {
//        tVariantAssign(&q.lowerBnd, &queryColInfo->q);
//        result->num = tSkipListQuery(pSkipList, &q, (tSkipListNode ***)&result->pRes);
//        break;
//      }
//      case TSDB_RELATION_LARGE_EQUAL: {
//        tVariantAssign(&q.lowerBnd, &queryColInfo->q);
//        q.lowerBndRelOptr = queryColInfo->optr;
//        result->num = tSkipListQuery(pSkipList, &q, (tSkipListNode ***)&result->pRes);
//        break;
//      }
//      default:
//        pTrace("skiplist:%p, unsupport query operator:%d", pSkipList, queryColInfo->optr);
//    }
//
//    tSkipListDestroyKey(&q.upperBnd);
//    tSkipListDestroyKey(&q.lowerBnd);
//  } else {
//    /*
//     * Brutal force scan the whole skiplit to find the appropriate result,
//     * since the filter is not applied to indexed column.
//     */
//    result->num = tSkipListIterateList(pSkipList, (tSkipListNode ***)&result->pRes, fp, queryColInfo);
//  }
//}
H
hzcheng 已提交
562 563 564 565 566

/*
 * qsort comparator
 * sort the result to ensure meters with the same gid is grouped together
 */
567 568 569 570 571 572
//static int32_t compareByAddr(const void *pLeft, const void *pRight) {
//  int64_t p1 = (int64_t) * ((tSkipListNode **)pLeft);
//  int64_t p2 = (int64_t) * ((tSkipListNode **)pRight);
//
//  DEFAULT_COMP(p1, p2);
//}
H
hzcheng 已提交
573 574

int32_t merge(tQueryResultset *pLeft, tQueryResultset *pRight, tQueryResultset *pFinalRes) {
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
//  assert(pFinalRes->pRes == 0);
//
//  pFinalRes->pRes = calloc((size_t)(pLeft->num + pRight->num), POINTER_BYTES);
//  pFinalRes->num = 0;
//
//  // sort according to address
//  tSkipListNode **pLeftNodes = (tSkipListNode **)pLeft->pRes;
//  qsort(pLeftNodes, pLeft->num, sizeof(pLeft->pRes[0]), compareByAddr);
//
//  tSkipListNode **pRightNodes = (tSkipListNode **)pRight->pRes;
//  qsort(pRightNodes, pRight->num, sizeof(pRight->pRes[0]), compareByAddr);
//
//  int32_t i = 0, j = 0;
//
//  // merge two sorted arrays in O(n) time
//  while (i < pLeft->num && j < pRight->num) {
//    int64_t ret = (int64_t)pLeftNodes[i] - (int64_t)pRightNodes[j];
//
//    if (ret < 0) {
//      pFinalRes->pRes[pFinalRes->num++] = pLeftNodes[i++];
//    } else if (ret > 0) {
//      pFinalRes->pRes[pFinalRes->num++] = pRightNodes[j++];
//    } else {  // pNode->key > pkey[i]
//      pFinalRes->pRes[pFinalRes->num++] = pRightNodes[j++];
//      i++;
//    }
//  }
//
//  while (i < pLeft->num) {
//    pFinalRes->pRes[pFinalRes->num++] = pLeftNodes[i++];
//  }
//
//  while (j < pRight->num) {
//    pFinalRes->pRes[pFinalRes->num++] = pRightNodes[j++];
//  }
//
//  return pFinalRes->num;
H
hjxilinx 已提交
612
  return 0;
H
hzcheng 已提交
613 614 615
}

int32_t intersect(tQueryResultset *pLeft, tQueryResultset *pRight, tQueryResultset *pFinalRes) {
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
//  int64_t num = MIN(pLeft->num, pRight->num);
//
//  assert(pFinalRes->pRes == 0);
//
//  pFinalRes->pRes = calloc(num, POINTER_BYTES);
//  pFinalRes->num = 0;
//
//  // sort according to address
//  tSkipListNode **pLeftNodes = (tSkipListNode **)pLeft->pRes;
//  qsort(pLeftNodes, pLeft->num, sizeof(pLeft->pRes[0]), compareByAddr);
//
//  tSkipListNode **pRightNodes = (tSkipListNode **)pRight->pRes;
//  qsort(pRightNodes, pRight->num, sizeof(pRight->pRes[0]), compareByAddr);
//
//  int32_t i = 0, j = 0;
//  // merge two sorted arrays in O(n) time
//  while (i < pLeft->num && j < pRight->num) {
//    int64_t ret = (int64_t)pLeftNodes[i] - (int64_t)pRightNodes[j];
//
//    if (ret < 0) {
//      i++;
//    } else if (ret > 0) {
//      j++;
//    } else {  // pNode->key > pkey[i]
//      pFinalRes->pRes[pFinalRes->num++] = pRightNodes[j];
//      i++;
//      j++;
//    }
//  }
//
//  return pFinalRes->num;
H
hjxilinx 已提交
647
 return 0;
H
hzcheng 已提交
648 649 650
}

/*
H
hjxilinx 已提交
651
 * traverse the result and apply the function to each item to check if the item is qualified or not
H
hzcheng 已提交
652
 */
653
static UNUSED_FUNC void tSQLListTraverseOnResult(struct tSQLBinaryExpr *pExpr, __result_filter_fn_t fp, tQueryResultset *pResult) {
H
hzcheng 已提交
654 655
  assert(pExpr->pLeft->nodeType == TSQL_NODE_COL && pExpr->pRight->nodeType == TSQL_NODE_VALUE);

H
hjxilinx 已提交
656
  // brutal force scan the result list and check for each item in the list
S
slguan 已提交
657
  int64_t num = pResult->num;
H
hzcheng 已提交
658
  for (int32_t i = 0, j = 0; i < pResult->num; ++i) {
H
hjxilinx 已提交
659
    if (fp == NULL || (fp(pResult->pRes[i], pExpr->info) == true)) {
H
hzcheng 已提交
660 661 662 663 664 665 666 667 668
      pResult->pRes[j++] = pResult->pRes[i];
    } else {
      num--;
    }
  }

  pResult->num = num;
}

S
slguan 已提交
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
static bool filterItem(tSQLBinaryExpr *pExpr, const void *pItem, SBinaryFilterSupp *param) {
  tSQLSyntaxNode *pLeft = pExpr->pLeft;
  tSQLSyntaxNode *pRight = pExpr->pRight;

  /*
   * non-leaf nodes, recursively traverse the syntax tree in the post-root order
   */
  if (pLeft->nodeType == TSQL_NODE_EXPR && pRight->nodeType == TSQL_NODE_EXPR) {
    if (pExpr->nSQLBinaryOptr == TSDB_RELATION_OR) {  // or
      if (filterItem(pLeft->pExpr, pItem, param)) {
        return true;
      }

      // left child does not satisfy the query condition, try right child
      return filterItem(pRight->pExpr, pItem, param);
    } else {  // and
      if (!filterItem(pLeft->pExpr, pItem, param)) {
        return false;
      }

      return filterItem(pRight->pExpr, pItem, param);
    }
  }

  // handle the leaf node
  assert(pLeft->nodeType == TSQL_NODE_COL && pRight->nodeType == TSQL_NODE_VALUE);
  param->setupInfoFn(pExpr, param->pExtInfo);

  return param->fp(pItem, pExpr->info);
}

/**
 * Apply the filter expression on non-indexed tag columns to each element in the result list, which is generated
 * by filtering on indexed tag column. So the whole result set only needs to be iterated once to generate
 * result that is satisfied to the filter expression, no matter how the filter expression consisting of.
 *
 * @param pExpr     filter expression on non-indexed tag columns.
 * @param pResult   results from filter on the indexed tag column, which is usually the first tag column
 * @param pSchema   tag schemas
 * @param fp        filter callback function
 */
710 711 712 713 714 715
static void tSQLBinaryTraverseOnResult(tSQLBinaryExpr *pExpr, SArray *pResult, SBinaryFilterSupp *param) {
  size_t size = taosArrayGetSize(pResult);
  
  SArray* array = taosArrayInit(size, POINTER_BYTES);
  for (int32_t i = 0; i < size; ++i) {
    void *pItem = taosArrayGetP(pResult, i);
S
slguan 已提交
716 717

    if (filterItem(pExpr, pItem, param)) {
718
      taosArrayPush(array, &pItem);
S
slguan 已提交
719 720
    }
  }
721 722
  
  taosArrayCopy(pResult, array);
S
slguan 已提交
723 724
}

725 726 727 728 729 730 731 732 733 734 735 736
static void tSQLBinaryTraverseOnSkipList(tSQLBinaryExpr *pExpr, SArray *pResult, SSkipList *pSkipList,
    SBinaryFilterSupp *param) {
  SSkipListIterator* iter = tSkipListCreateIter(pSkipList);

  while (tSkipListIterNext(iter)) {
    SSkipListNode *pNode = tSkipListIterGet(iter);
    
    if (filterItem(pExpr, pNode, param)) {
      taosArrayPush(pResult, SL_GET_NODE_DATA(pNode));
    }
  }
}
S
slguan 已提交
737

H
hzcheng 已提交
738
// post-root order traverse syntax tree
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
void tSQLBinaryExprTraverse(tSQLBinaryExpr *pExpr, SSkipList *pSkipList, SArray *result, SBinaryFilterSupp *param) {
  if (pExpr == NULL) {
    return;
  }

  tSQLSyntaxNode *pLeft = pExpr->pLeft;
  tSQLSyntaxNode *pRight = pExpr->pRight;

  // recursive traverse left child branch
  if (pLeft->nodeType == TSQL_NODE_EXPR || pRight->nodeType == TSQL_NODE_EXPR) {
    uint8_t weight = pLeft->pExpr->filterOnPrimaryKey + pRight->pExpr->filterOnPrimaryKey;

    if (weight == 0 && taosArrayGetSize(result) > 0 && pSkipList == NULL) {
      /**
       * Perform the filter operation based on the initial filter result, which is obtained from filtering from index.
       * Since no index presented, the filter operation is done by scan all elements in the result set.
       *
       * if the query is a high selectivity filter, only small portion of meters are retrieved.
       */
      tSQLBinaryTraverseOnResult(pExpr, result, param);
    } else if (weight == 0) {
      /**
       * apply the hierarchical expression to every node in skiplist for find the qualified nodes
       */
      assert(taosArrayGetSize(result) == 0);
      tSQLBinaryTraverseOnSkipList(pExpr, result, pSkipList, param);
    } else if (weight == 2 || (weight == 1 && pExpr->nSQLBinaryOptr == TSDB_RELATION_OR)) {
      tQueryResultset rLeft = {0};
      tQueryResultset rRight = {0};

      tSQLBinaryExprTraverse(pLeft->pExpr, pSkipList, &rLeft, param);
      tSQLBinaryExprTraverse(pRight->pExpr, pSkipList, &rRight, param);

      if (pExpr->nSQLBinaryOptr == TSDB_RELATION_AND) {  // CROSS
        intersect(&rLeft, &rRight, result);
      } else if (pExpr->nSQLBinaryOptr == TSDB_RELATION_OR) {  // or
        merge(&rLeft, &rRight, result);
      } else {
        assert(false);
      }

      free(rLeft.pRes);
      free(rRight.pRes);
    } else {
      /*
       * (weight == 1 && pExpr->nSQLBinaryOptr == TSDB_RELATION_AND) is handled here
       *
       * first, we filter results based on the skiplist index, which is the initial filter stage,
       * then, we conduct the secondary filter operation based on the result from the initial filter stage.
       */
      assert(pExpr->nSQLBinaryOptr == TSDB_RELATION_AND);

      tSQLBinaryExpr *pFirst = NULL;
      tSQLBinaryExpr *pSecond = NULL;
      if (pLeft->pExpr->filterOnPrimaryKey == 1) {
        pFirst = pLeft->pExpr;
        pSecond = pRight->pExpr;
      } else {
        pFirst = pRight->pExpr;
        pSecond = pLeft->pExpr;
      }

      assert(pFirst != pSecond && pFirst != NULL && pSecond != NULL);

      // we filter the result based on the skiplist index in the first place
      tSQLBinaryExprTraverse(pFirst, pSkipList, result, param);

      /*
       * recursively perform the filter operation based on the initial results,
       * So, we do not set the skiplist index as a parameter
       */
      tSQLBinaryExprTraverse(pSecond, NULL, result, param);
    }
  } else {  // column project
    assert(pLeft->nodeType == TSQL_NODE_COL && pRight->nodeType == TSQL_NODE_VALUE);

    param->setupInfoFn(pExpr, param->pExtInfo);
    if (pSkipList == NULL) {
      tSQLListTraverseOnResult(pExpr, param->fp, result);
    } else {
819
//      assert(result->num == 0);
820 821 822 823
//      tSQLDoFilterInitialResult(pSkipList, param->fp, pExpr->info, result);
    }
  }
}
H
hzcheng 已提交
824 825 826 827 828 829 830 831 832 833 834

void tSQLBinaryExprCalcTraverse(tSQLBinaryExpr *pExprs, int32_t numOfRows, char *pOutput, void *param, int32_t order,
                                char *(*getSourceDataBlock)(void *, char *, int32_t)) {
  if (pExprs == NULL) {
    return;
  }

  tSQLSyntaxNode *pLeft = pExprs->pLeft;
  tSQLSyntaxNode *pRight = pExprs->pRight;

  /* the left output has result from the left child syntax tree */
L
lihui 已提交
835
  char *pLeftOutput = (char*)malloc(sizeof(int64_t) * numOfRows);
H
hzcheng 已提交
836 837 838 839 840 841 842 843 844 845 846
  if (pLeft->nodeType == TSQL_NODE_EXPR) {
    tSQLBinaryExprCalcTraverse(pLeft->pExpr, numOfRows, pLeftOutput, param, order, getSourceDataBlock);
  }

  /* the right output has result from the right child syntax tree */
  char *pRightOutput = malloc(sizeof(int64_t) * numOfRows);
  if (pRight->nodeType == TSQL_NODE_EXPR) {
    tSQLBinaryExprCalcTraverse(pRight->pExpr, numOfRows, pRightOutput, param, order, getSourceDataBlock);
  }

  if (pLeft->nodeType == TSQL_NODE_EXPR) {
S
slguan 已提交
847 848 849 850 851
    if (pRight->nodeType == TSQL_NODE_EXPR) {
      /*
       * exprLeft + exprRight
       * the type of returned value of one expression is always double float precious
       */
H
hzcheng 已提交
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
      _bi_consumer_fn_t fp = tGetBiConsumerFn(TSDB_DATA_TYPE_DOUBLE, TSDB_DATA_TYPE_DOUBLE, pExprs->nSQLBinaryOptr);
      fp(pLeftOutput, pRightOutput, numOfRows, numOfRows, pOutput, order);

    } else if (pRight->nodeType == TSQL_NODE_COL) {  // exprLeft + columnRight
      _bi_consumer_fn_t fp = tGetBiConsumerFn(TSDB_DATA_TYPE_DOUBLE, pRight->pSchema->type, pExprs->nSQLBinaryOptr);
      // set input buffer
      char *pInputData = getSourceDataBlock(param, pRight->pSchema->name, pRight->colId);
      fp(pLeftOutput, pInputData, numOfRows, numOfRows, pOutput, order);

    } else if (pRight->nodeType == TSQL_NODE_VALUE) {  // exprLeft + 12
      _bi_consumer_fn_t fp = tGetBiConsumerFn(TSDB_DATA_TYPE_DOUBLE, pRight->pVal->nType, pExprs->nSQLBinaryOptr);
      fp(pLeftOutput, &pRight->pVal->i64Key, numOfRows, 1, pOutput, order);
    }
  } else if (pLeft->nodeType == TSQL_NODE_COL) {
    // column data specified on left-hand-side
    char *pLeftInputData = getSourceDataBlock(param, pLeft->pSchema->name, pLeft->colId);
    if (pRight->nodeType == TSQL_NODE_EXPR) {  // columnLeft + expr2
      _bi_consumer_fn_t fp = tGetBiConsumerFn(pLeft->pSchema->type, TSDB_DATA_TYPE_DOUBLE, pExprs->nSQLBinaryOptr);
      fp(pLeftInputData, pRightOutput, numOfRows, numOfRows, pOutput, order);

    } else if (pRight->nodeType == TSQL_NODE_COL) {  // columnLeft + columnRight
      // column data specified on right-hand-side
      char *pRightInputData = getSourceDataBlock(param, pRight->pSchema->name, pRight->colId);

      _bi_consumer_fn_t fp = tGetBiConsumerFn(pLeft->pSchema->type, pRight->pSchema->type, pExprs->nSQLBinaryOptr);
      fp(pLeftInputData, pRightInputData, numOfRows, numOfRows, pOutput, order);

    } else if (pRight->nodeType == TSQL_NODE_VALUE) {  // columnLeft + 12
      _bi_consumer_fn_t fp = tGetBiConsumerFn(pLeft->pSchema->type, pRight->pVal->nType, pExprs->nSQLBinaryOptr);
      fp(pLeftInputData, &pRight->pVal->i64Key, numOfRows, 1, pOutput, order);
    }
  } else {
    // column data specified on left-hand-side
    if (pRight->nodeType == TSQL_NODE_EXPR) {  // 12 + expr2
      _bi_consumer_fn_t fp = tGetBiConsumerFn(pLeft->pVal->nType, TSDB_DATA_TYPE_DOUBLE, pExprs->nSQLBinaryOptr);
      fp(&pLeft->pVal->i64Key, pRightOutput, 1, numOfRows, pOutput, order);

    } else if (pRight->nodeType == TSQL_NODE_COL) {  // 12 + columnRight
      // column data specified on right-hand-side
S
slguan 已提交
891
      char *            pRightInputData = getSourceDataBlock(param, pRight->pSchema->name, pRight->colId);
H
hzcheng 已提交
892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
      _bi_consumer_fn_t fp = tGetBiConsumerFn(pLeft->pVal->nType, pRight->pSchema->type, pExprs->nSQLBinaryOptr);
      fp(&pLeft->pVal->i64Key, pRightInputData, 1, numOfRows, pOutput, order);

    } else if (pRight->nodeType == TSQL_NODE_VALUE) {  // 12 + 12
      _bi_consumer_fn_t fp = tGetBiConsumerFn(pLeft->pVal->nType, pRight->pVal->nType, pExprs->nSQLBinaryOptr);
      fp(&pLeft->pVal->i64Key, &pRight->pVal->i64Key, 1, 1, pOutput, order);
    }
  }

  free(pLeftOutput);
  free(pRightOutput);
}

void tSQLBinaryExprTrv(tSQLBinaryExpr *pExprs, int32_t *val, int16_t *ids) {
  if (pExprs == NULL) {
    return;
  }

  tSQLSyntaxNode *pLeft = pExprs->pLeft;
  tSQLSyntaxNode *pRight = pExprs->pRight;

  // recursive traverse left child branch
  if (pLeft->nodeType == TSQL_NODE_EXPR) {
    tSQLBinaryExprTrv(pLeft->pExpr, val, ids);
  } else if (pLeft->nodeType == TSQL_NODE_COL) {
    ids[*val] = pLeft->pSchema->colId;
    (*val) += 1;
  }

  if (pRight->nodeType == TSQL_NODE_EXPR) {
    tSQLBinaryExprTrv(pRight->pExpr, val, ids);
  } else if (pRight->nodeType == TSQL_NODE_COL) {
    ids[*val] = pRight->pSchema->colId;
    (*val) += 1;
  }
S
slguan 已提交
927 928 929 930 931 932 933 934 935
}

void tQueryResultClean(tQueryResultset *pRes) {
  if (pRes == NULL) {
    return;
  }

  tfree(pRes->pRes);
  pRes->num = 0;
L
lihui 已提交
936
}