You need to sign in or sign up before continuing.
planSpliter.c 6.1 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 "planInt.h"
X
Xiaoyu Wang 已提交
17 18 19 20 21 22 23 24 25 26

#define SPLIT_FLAG_MASK(n)    (1 << n)

#define SPLIT_FLAG_STS SPLIT_FLAG_MASK(0)

#define SPLIT_FLAG_SET_MASK(val, mask) (val) |= (mask)
#define SPLIT_FLAG_TEST_MASK(val, mask) (((val) & (mask)) != 0)

typedef struct SSplitContext {
  int32_t groupId;
27
  bool split;
X
Xiaoyu Wang 已提交
28 29
} SSplitContext;

30
typedef int32_t (*FSplit)(SSplitContext* pCxt, SLogicSubplan* pSubplan);
X
Xiaoyu Wang 已提交
31 32 33 34 35 36 37 38

typedef struct SSplitRule {
  char* pName;
  FSplit splitFunc;
} SSplitRule;

typedef struct SStsInfo {
  SScanLogicNode* pScan;
X
Xiaoyu Wang 已提交
39
  SLogicSubplan* pSubplan;
X
Xiaoyu Wang 已提交
40 41 42
} SStsInfo;

static SLogicNode* stsMatchByNode(SLogicNode* pNode) {
X
Xiaoyu Wang 已提交
43 44
  if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode) &&
      NULL != ((SScanLogicNode*)pNode)->pVgroupList && ((SScanLogicNode*)pNode)->pVgroupList->numOfVgroups > 1) {
X
Xiaoyu Wang 已提交
45 46 47 48 49 50 51 52 53 54 55 56
    return pNode;
  }
  SNode* pChild;
  FOREACH(pChild, pNode->pChildren) {
    SLogicNode* pSplitNode = stsMatchByNode((SLogicNode*)pChild);
    if (NULL != pSplitNode) {
      return pSplitNode;
    }
  }
  return NULL;
}

57
static void stsFindSplitNode(SLogicSubplan* pSubplan, SStsInfo* pInfo) {
X
Xiaoyu Wang 已提交
58 59 60 61
  SLogicNode* pSplitNode = stsMatchByNode(pSubplan->pNode);
  if (NULL != pSplitNode) {
    pInfo->pScan = (SScanLogicNode*)pSplitNode;
    pInfo->pSubplan = pSubplan;
62 63 64 65 66
  }
}
static void stsMatch(SSplitContext* pCxt, SLogicSubplan* pSubplan, SStsInfo* pInfo) {
  if (!SPLIT_FLAG_TEST_MASK(pSubplan->splitFlag, SPLIT_FLAG_STS)) {
    stsFindSplitNode(pSubplan, pInfo);
X
Xiaoyu Wang 已提交
67 68 69
  }
  SNode* pChild;
  FOREACH(pChild, pSubplan->pChildren) {
70 71 72
    stsMatch(pCxt, (SLogicSubplan*)pChild, pInfo);
    if (NULL != pInfo->pScan) {
      break;
X
Xiaoyu Wang 已提交
73 74
    }
  }
75
  return;
X
Xiaoyu Wang 已提交
76 77
}

X
Xiaoyu Wang 已提交
78 79
static SLogicSubplan* stsCreateScanSubplan(SSplitContext* pCxt, SScanLogicNode* pScan) {
  SLogicSubplan* pSubplan = nodesMakeNode(QUERY_NODE_LOGIC_SUBPLAN);
X
Xiaoyu Wang 已提交
80 81 82 83 84 85
  if (NULL == pSubplan) {
    return NULL;
  }
  pSubplan->id.groupId = pCxt->groupId;
  pSubplan->subplanType = SUBPLAN_TYPE_SCAN;
  pSubplan->pNode = (SLogicNode*)nodesCloneNode(pScan);
86
  TSWAP(pSubplan->pVgroupList, ((SScanLogicNode*)pSubplan->pNode)->pVgroupList, SVgroupsInfo*);
X
Xiaoyu Wang 已提交
87 88 89 90
  SPLIT_FLAG_SET_MASK(pSubplan->splitFlag, SPLIT_FLAG_STS);
  return pSubplan;
}

X
Xiaoyu Wang 已提交
91
static int32_t stsCreateExchangeNode(SSplitContext* pCxt, SLogicSubplan* pSubplan, SScanLogicNode* pScan) {
X
Xiaoyu Wang 已提交
92 93 94 95 96
  SExchangeLogicNode* pExchange = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_EXCHANGE);
  if (NULL == pExchange) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }
  pExchange->srcGroupId = pCxt->groupId;
97
  pExchange->precision = pScan->pMeta->tableInfo.precision;
X
Xiaoyu Wang 已提交
98 99 100 101 102
  pExchange->node.pTargets = nodesCloneList(pScan->node.pTargets);
  if (NULL == pExchange->node.pTargets) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }

X
bugfix  
Xiaoyu Wang 已提交
103 104
  pSubplan->subplanType = SUBPLAN_TYPE_MERGE;

X
Xiaoyu Wang 已提交
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
  if (NULL == pScan->node.pParent) {
    pSubplan->pNode = (SLogicNode*)pExchange;
    return TSDB_CODE_SUCCESS;
  }

  SNode* pNode;
  FOREACH(pNode, pScan->node.pParent->pChildren) {
    if (nodesEqualNode(pNode, pScan)) {
      REPLACE_NODE(pExchange);
      nodesDestroyNode(pNode);
      return TSDB_CODE_SUCCESS;
    }
  }
  nodesDestroyNode(pExchange);
  return TSDB_CODE_FAILED;
}

122 123 124 125 126 127 128 129 130
static int32_t stsSplit(SSplitContext* pCxt, SLogicSubplan* pSubplan) {
  SStsInfo info = {0};
  stsMatch(pCxt, pSubplan, &info);
  if (NULL == info.pScan) {
    return TSDB_CODE_SUCCESS;
  }
  if (NULL == info.pSubplan->pChildren) {
    info.pSubplan->pChildren = nodesMakeList();
    if (NULL == info.pSubplan->pChildren) {
X
Xiaoyu Wang 已提交
131 132 133
      return TSDB_CODE_OUT_OF_MEMORY;
    }
  }
134
  int32_t code = nodesListStrictAppend(info.pSubplan->pChildren, stsCreateScanSubplan(pCxt, info.pScan));
X
Xiaoyu Wang 已提交
135
  if (TSDB_CODE_SUCCESS == code) {
136
    code = stsCreateExchangeNode(pCxt, info.pSubplan, info.pScan);
X
Xiaoyu Wang 已提交
137 138
  }
  ++(pCxt->groupId);
139
  pCxt->split = true;
X
Xiaoyu Wang 已提交
140 141 142 143
  return code;
}

static const SSplitRule splitRuleSet[] = {
144
  { .pName = "SuperTableScan", .splitFunc = stsSplit }
X
Xiaoyu Wang 已提交
145 146 147 148
};

static const int32_t splitRuleNum = (sizeof(splitRuleSet) / sizeof(SSplitRule));

X
Xiaoyu Wang 已提交
149
static int32_t applySplitRule(SLogicSubplan* pSubplan) {
150
  SSplitContext cxt = { .groupId = pSubplan->id.groupId + 1, .split = false };
X
Xiaoyu Wang 已提交
151
  do {
152
    cxt.split = false;
X
Xiaoyu Wang 已提交
153
    for (int32_t i = 0; i < splitRuleNum; ++i) {
154
      int32_t code = splitRuleSet[i].splitFunc(&cxt, pSubplan);
X
Xiaoyu Wang 已提交
155 156 157 158
      if (TSDB_CODE_SUCCESS != code) {
        return code;
      }
    }
159
  } while (cxt.split);
X
Xiaoyu Wang 已提交
160 161
  return TSDB_CODE_SUCCESS;
}
X
Xiaoyu Wang 已提交
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192

static void doSetLogicNodeParent(SLogicNode* pNode, SLogicNode* pParent) {
  pNode->pParent = pParent;
  SNode* pChild;
  FOREACH(pChild, pNode->pChildren) {
    doSetLogicNodeParent((SLogicNode*)pChild, pNode);
  }
}

static void setLogicNodeParent(SLogicNode* pNode) {
  doSetLogicNodeParent(pNode, NULL);
}

int32_t splitLogicPlan(SPlanContext* pCxt, SLogicNode* pLogicNode, SLogicSubplan** pLogicSubplan) {
  SLogicSubplan* pSubplan = (SLogicSubplan*)nodesMakeNode(QUERY_NODE_LOGIC_SUBPLAN);
  if (NULL == pSubplan) {
    return TSDB_CODE_OUT_OF_MEMORY;
  }

  pSubplan->pNode = nodesCloneNode(pLogicNode);
  if (NULL == pSubplan->pNode) {
    nodesDestroyNode(pSubplan);
    return TSDB_CODE_OUT_OF_MEMORY;
  }
  if (QUERY_NODE_LOGIC_PLAN_VNODE_MODIF == nodeType(pLogicNode)) {
    pSubplan->subplanType = SUBPLAN_TYPE_MODIFY;
    TSWAP(((SVnodeModifLogicNode*)pLogicNode)->pDataBlocks, ((SVnodeModifLogicNode*)pSubplan->pNode)->pDataBlocks, SArray*);
  } else {
    pSubplan->subplanType = SUBPLAN_TYPE_SCAN;
  }
  pSubplan->id.queryId = pCxt->queryId;
193
  pSubplan->id.groupId = 1;
X
Xiaoyu Wang 已提交
194 195 196 197 198 199 200 201 202 203 204
  setLogicNodeParent(pSubplan->pNode);

  int32_t code = applySplitRule(pSubplan);
  if (TSDB_CODE_SUCCESS == code) {
    *pLogicSubplan = pSubplan;
  } else {
    nodesDestroyNode(pSubplan);
  }

  return code;
}