parCalcConst.c 9.8 KB
Newer Older
X
Xiaoyu Wang 已提交
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/>.
 */

X
Xiaoyu Wang 已提交
16
#include "functionMgt.h"
X
Xiaoyu Wang 已提交
17 18
#include "parInt.h"
#include "scalar.h"
X
Xiaoyu Wang 已提交
19
#include "ttime.h"
X
Xiaoyu Wang 已提交
20 21

typedef struct SCalcConstContext {
X
Xiaoyu Wang 已提交
22
  SParseContext* pParseCxt;
X
Xiaoyu Wang 已提交
23 24
  SMsgBuf        msgBuf;
  int32_t        code;
X
Xiaoyu Wang 已提交
25 26
} SCalcConstContext;

27
static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery);
X
Xiaoyu Wang 已提交
28

29 30
static int32_t calcConstSubquery(SCalcConstContext* pCxt, STempTableNode* pTempTable) {
  return calcConstQuery(pCxt, pTempTable->pSubquery, true);
X
Xiaoyu Wang 已提交
31 32
}

33 34 35
static int32_t calcConstNode(SNode** pNode) {
  if (NULL == *pNode) {
    return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
36 37
  }

X
Xiaoyu Wang 已提交
38
  SNode*  pNew = NULL;
39 40 41
  int32_t code = scalarCalculateConstants(*pNode, &pNew);
  if (TSDB_CODE_SUCCESS == code) {
    *pNode = pNew;
X
Xiaoyu Wang 已提交
42
  }
43
  return code;
X
Xiaoyu Wang 已提交
44 45
}

46 47 48
static int32_t calcConstList(SNodeList* pList) {
  SNode* pNode = NULL;
  FOREACH(pNode, pList) {
X
Xiaoyu Wang 已提交
49
    SNode*  pNew = NULL;
50 51 52 53 54
    int32_t code = scalarCalculateConstants(pNode, &pNew);
    if (TSDB_CODE_SUCCESS == code) {
      REPLACE_NODE(pNew);
    } else {
      return code;
X
Xiaoyu Wang 已提交
55 56
    }
  }
57
  return TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
58 59
}

60 61 62 63 64 65 66 67 68 69 70 71 72 73
static bool isCondition(const SNode* pNode) {
  if (QUERY_NODE_OPERATOR == nodeType(pNode)) {
    return nodesIsComparisonOp((const SOperatorNode*)pNode);
  }
  return (QUERY_NODE_LOGIC_CONDITION == nodeType(pNode));
}

static int32_t rewriteIsTrue(SNode* pSrc, SNode** pIsTrue) {
  SOperatorNode* pOp = nodesMakeNode(QUERY_NODE_OPERATOR);
  if (NULL == pOp) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
  pOp->opType = OP_TYPE_IS_TRUE;
  pOp->pLeft = pSrc;
D
dapan1121 已提交
74 75
  pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
  pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
  *pIsTrue = (SNode*)pOp;
  return TSDB_CODE_SUCCESS;
}

static EDealRes doRewriteCondition(SNode** pNode, void* pContext) {
  if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pNode)) {
    SNode* pParam = NULL;
    FOREACH(pParam, ((SLogicConditionNode*)*pNode)->pParameterList) {
      if (!isCondition(pParam)) {
        SNode* pIsTrue = NULL;
        if (TSDB_CODE_SUCCESS != rewriteIsTrue(pParam, &pIsTrue)) {
          ((SCalcConstContext*)pContext)->code = TSDB_CODE_OUT_OF_MEMORY;
          return DEAL_RES_ERROR;
        }
        REPLACE_NODE(pIsTrue);
      }
    }
  }
  return DEAL_RES_CONTINUE;
}

static int32_t rewriteCondition(SCalcConstContext* pCxt, SNode** pNode) {
  if (!isCondition(*pNode)) {
    return rewriteIsTrue(*pNode, pNode);
  }
  nodesRewriteExprPostOrder(pNode, doRewriteCondition, pCxt);
  return pCxt->code;
}

105 106 107 108 109 110 111 112
static int32_t calcConstCondition(SCalcConstContext* pCxt, SNode** pNode) {
  int32_t code = rewriteCondition(pCxt, pNode);
  if (TSDB_CODE_SUCCESS == code) {
    code = calcConstNode(pNode);
  }
  return code;
}

113
static int32_t rewriteConditionForFromTable(SCalcConstContext* pCxt, SNode* pTable) {
114 115 116 117 118
  int32_t code = TSDB_CODE_SUCCESS;
  switch (nodeType(pTable)) {
    case QUERY_NODE_TEMP_TABLE: {
      code = calcConstSubquery(pCxt, (STempTableNode*)pTable);
      break;
119
    }
120 121 122 123 124 125 126 127 128 129 130
    case QUERY_NODE_JOIN_TABLE: {
      SJoinTableNode* pJoin = (SJoinTableNode*)pTable;
      code = rewriteConditionForFromTable(pCxt, pJoin->pLeft);
      if (TSDB_CODE_SUCCESS == code) {
        code = rewriteConditionForFromTable(pCxt, pJoin->pRight);
      }
      if (TSDB_CODE_SUCCESS == code && NULL != pJoin->pOnCond) {
        code = calcConstCondition(pCxt, &pJoin->pOnCond);
      }
      // todo empty table
      break;
X
Xiaoyu Wang 已提交
131
    }
132 133
    default:
      break;
134
  }
135 136 137
  return code;
}

X
Xiaoyu Wang 已提交
138 139
static int32_t calcConstFromTable(SCalcConstContext* pCxt, SNode* pTable) {
  return rewriteConditionForFromTable(pCxt, pTable);
140 141
}

X
Xiaoyu Wang 已提交
142
static void rewriteConstCondition(SNode** pCond, bool* pAlwaysFalse) {
X
Xiaoyu Wang 已提交
143 144 145 146 147 148 149
  if (QUERY_NODE_VALUE != nodeType(*pCond)) {
    return;
  }
  if (((SValueNode*)*pCond)->datum.b) {
    nodesDestroyNode(*pCond);
    *pCond = NULL;
  } else {
X
Xiaoyu Wang 已提交
150
    *pAlwaysFalse = true;
X
Xiaoyu Wang 已提交
151 152 153
  }
}

X
Xiaoyu Wang 已提交
154
static int32_t calcConstStmtCondition(SCalcConstContext* pCxt, SNode** pCond, bool* pAlwaysFalse) {
155 156 157 158
  if (NULL == *pCond) {
    return TSDB_CODE_SUCCESS;
  }

159 160 161
  int32_t code = rewriteCondition(pCxt, pCond);
  if (TSDB_CODE_SUCCESS == code) {
    code = calcConstNode(pCond);
X
Xiaoyu Wang 已提交
162
  }
163
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
164
    rewriteConstCondition(pCond, pAlwaysFalse);
165
  }
166
  return code;
167 168
}

169 170 171
static int32_t calcConstProject(SNode* pProject, SNode** pNew) {
  SArray* pAssociation = NULL;
  if (NULL != ((SExprNode*)pProject)->pAssociation) {
X
fix  
Xiaoyu Wang 已提交
172
    pAssociation = taosArrayDup(((SExprNode*)pProject)->pAssociation);
173 174 175
    if (NULL == pAssociation) {
      return TSDB_CODE_OUT_OF_MEMORY;
    }
X
Xiaoyu Wang 已提交
176
  }
177 178

  int32_t code = scalarCalculateConstants(pProject, pNew);
X
Xiaoyu Wang 已提交
179
  if (TSDB_CODE_SUCCESS == code && QUERY_NODE_VALUE == nodeType(*pNew) && NULL != pAssociation) {
180 181
    int32_t size = taosArrayGetSize(pAssociation);
    for (int32_t i = 0; i < size; ++i) {
X
Xiaoyu Wang 已提交
182 183
      SNode** pCol = taosArrayGetP(pAssociation, i);
      *pCol = nodesCloneNode(*pNew);
184 185 186 187
      if (NULL == *pCol) {
        return TSDB_CODE_OUT_OF_MEMORY;
      }
    }
X
Xiaoyu Wang 已提交
188
  }
189 190 191
  return code;
}

192 193 194 195 196 197 198 199
static bool isUselessCol(bool hasSelectValFunc, SExprNode* pProj) {
  if (hasSelectValFunc && QUERY_NODE_FUNCTION == nodeType(pProj) && fmIsSelectFunc(((SFunctionNode*)pProj)->funcId)) {
    return false;
  }
  return NULL == ((SExprNode*)pProj)->pAssociation;
}

static int32_t calcConstProjections(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
200
  SNode* pProj = NULL;
201 202 203
  WHERE_EACH(pProj, pSelect->pProjectionList) {
    if (subquery && isUselessCol(pSelect->hasSelectValFunc, (SExprNode*)pProj)) {
      ERASE_NODE(pSelect->pProjectionList);
204 205
      continue;
    }
X
Xiaoyu Wang 已提交
206
    SNode*  pNew = NULL;
207 208 209 210 211 212 213
    int32_t code = calcConstProject(pProj, &pNew);
    if (TSDB_CODE_SUCCESS == code) {
      REPLACE_NODE(pNew);
    } else {
      return code;
    }
    WHERE_NEXT;
X
Xiaoyu Wang 已提交
214
  }
215 216 217
  return TSDB_CODE_SUCCESS;
}

218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
static int32_t calcConstGroupBy(SCalcConstContext* pCxt, SSelectStmt* pSelect) {
  int32_t code = calcConstList(pSelect->pGroupByList);
  if (TSDB_CODE_SUCCESS == code) {
    SNode* pNode = NULL;
    FOREACH(pNode, pSelect->pGroupByList) {
      SNode* pGroupPara = NULL;
      FOREACH(pGroupPara, ((SGroupingSetNode*)pNode)->pParameterList) {
        if (QUERY_NODE_VALUE != nodeType(pGroupPara)) {
          return code;
        }
      }
    }
    DESTORY_LIST(pSelect->pGroupByList);
  }
  return code;
}

235
static int32_t calcConstSelect(SCalcConstContext* pCxt, SSelectStmt* pSelect, bool subquery) {
X
Xiaoyu Wang 已提交
236
  int32_t code = calcConstFromTable(pCxt, pSelect->pFromTable);
237
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
238
    code = calcConstProjections(pCxt, pSelect, subquery);
X
Xiaoyu Wang 已提交
239
  }
240
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
241
    code = calcConstStmtCondition(pCxt, &pSelect->pWhere, &pSelect->isEmptyResult);
X
Xiaoyu Wang 已提交
242
  }
243 244
  if (TSDB_CODE_SUCCESS == code) {
    code = calcConstList(pSelect->pPartitionByList);
X
Xiaoyu Wang 已提交
245
  }
246 247
  if (TSDB_CODE_SUCCESS == code) {
    code = calcConstNode(&pSelect->pWindow);
X
Xiaoyu Wang 已提交
248
  }
249
  if (TSDB_CODE_SUCCESS == code) {
250
    code = calcConstGroupBy(pCxt, pSelect);
251 252
  }
  if (TSDB_CODE_SUCCESS == code) {
X
Xiaoyu Wang 已提交
253
    code = calcConstStmtCondition(pCxt, &pSelect->pHaving, &pSelect->isEmptyResult);
254 255 256 257 258
  }
  if (TSDB_CODE_SUCCESS == code) {
    code = calcConstList(pSelect->pOrderByList);
  }
  return code;
X
Xiaoyu Wang 已提交
259 260
}

X
Xiaoyu Wang 已提交
261 262 263 264 265 266 267 268
static int32_t calcConstDelete(SCalcConstContext* pCxt, SDeleteStmt* pDelete) {
  int32_t code = calcConstFromTable(pCxt, pDelete->pFromTable);
  if (TSDB_CODE_SUCCESS == code) {
    code = calcConstStmtCondition(pCxt, &pDelete->pWhere, &pDelete->deleteZeroRows);
  }
  return code;
}

269 270
static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery) {
  int32_t code = TSDB_CODE_SUCCESS;
X
Xiaoyu Wang 已提交
271 272
  switch (nodeType(pStmt)) {
    case QUERY_NODE_SELECT_STMT:
273 274
      code = calcConstSelect(pCxt, (SSelectStmt*)pStmt, subquery);
      break;
D
dapan1121 已提交
275
    case QUERY_NODE_EXPLAIN_STMT:
276 277 278 279
      code = calcConstQuery(pCxt, ((SExplainStmt*)pStmt)->pQuery, subquery);
      break;
    case QUERY_NODE_SET_OPERATOR: {
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
280
      code = calcConstQuery(pCxt, pSetOp->pLeft, false);
281
      if (TSDB_CODE_SUCCESS == code) {
282
        code = calcConstQuery(pCxt, pSetOp->pRight, false);
283 284 285
      }
      break;
    }
X
Xiaoyu Wang 已提交
286 287 288
    case QUERY_NODE_DELETE_STMT:
      code = calcConstDelete(pCxt, (SDeleteStmt*)pStmt);
      break;
X
Xiaoyu Wang 已提交
289 290 291
    default:
      break;
  }
292
  return code;
X
Xiaoyu Wang 已提交
293 294
}

X
Xiaoyu Wang 已提交
295
static bool isEmptyResultQuery(SNode* pStmt) {
296
  bool isEmptyResult = false;
X
Xiaoyu Wang 已提交
297 298
  switch (nodeType(pStmt)) {
    case QUERY_NODE_SELECT_STMT:
299 300
      isEmptyResult = ((SSelectStmt*)pStmt)->isEmptyResult;
      break;
X
Xiaoyu Wang 已提交
301
    case QUERY_NODE_EXPLAIN_STMT:
302 303 304 305 306 307 308 309 310 311
      isEmptyResult = isEmptyResultQuery(((SExplainStmt*)pStmt)->pQuery);
      break;
    case QUERY_NODE_SET_OPERATOR: {
      SSetOperator* pSetOp = (SSetOperator*)pStmt;
      isEmptyResult = isEmptyResultQuery(pSetOp->pLeft);
      if (isEmptyResult) {
        isEmptyResult = isEmptyResultQuery(pSetOp->pRight);
      }
      break;
    }
X
Xiaoyu Wang 已提交
312 313 314
    default:
      break;
  }
315
  return isEmptyResult;
X
Xiaoyu Wang 已提交
316 317
}

X
Xiaoyu Wang 已提交
318
int32_t calculateConstant(SParseContext* pParseCxt, SQuery* pQuery) {
X
Xiaoyu Wang 已提交
319 320 321 322 323
  SCalcConstContext cxt = {.pParseCxt = pParseCxt,
                           .msgBuf.buf = pParseCxt->pMsg,
                           .msgBuf.len = pParseCxt->msgLen,
                           .code = TSDB_CODE_SUCCESS};
  int32_t           code = calcConstQuery(&cxt, pQuery->pRoot, false);
324 325
  if (TSDB_CODE_SUCCESS == code && isEmptyResultQuery(pQuery->pRoot)) {
    pQuery->execMode = QUERY_EXEC_MODE_EMPTY_RESULT;
X
Xiaoyu Wang 已提交
326 327
  }
  return code;
X
Xiaoyu Wang 已提交
328
}