physicalPlan.c 8.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * 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/>.
 */

#include "plannerInt.h"
17
#include "parser.h"
18

19 20 21
#define STORE_CURRENT_SUBPLAN(cxt) SSubplan* _ = cxt->pCurrentSubplan
#define RECOVERY_CURRENT_SUBPLAN(cxt) cxt->pCurrentSubplan = _

22 23 24 25 26 27 28
typedef struct SPlanContext {
  struct SCatalog* pCatalog;
  struct SQueryDag* pDag;
  SSubplan* pCurrentSubplan;
  SSubplanId nextId;
} SPlanContext;

29 30 31 32 33 34
static const char* gOpName[] = {
  "Unknown",
#define INCLUDE_AS_NAME
#include "plannerOp.h"
#undef INCLUDE_AS_NAME
};
X
Xiaoyu Wang 已提交
35

36 37 38 39
const char* opTypeToOpName(int32_t type) {
  return gOpName[type];
}

40 41 42 43 44 45 46 47
int32_t opNameToOpType(const char* name) {
  for (int32_t i = 1; i < sizeof(gOpName) / sizeof(gOpName[0]); ++i) {
    if (strcmp(name, gOpName[i])) {
      return i;
    }
  }
  return OP_Unknown;
}
X
Xiaoyu Wang 已提交
48

49
static bool toDataBlockSchema(SQueryPlanNode* pPlanNode, SDataBlockSchema* dataBlockSchema) {
X
Xiaoyu Wang 已提交
50
  dataBlockSchema->numOfCols = pPlanNode->numOfCols;
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
  dataBlockSchema->pSchema = malloc(sizeof(SSlotSchema) * pPlanNode->numOfCols);
  if (NULL == dataBlockSchema->pSchema) {
    return false;
  }
  memcpy(dataBlockSchema->pSchema, pPlanNode->pSchema, sizeof(SSlotSchema) * pPlanNode->numOfCols);
  return true;
}

static bool cloneExprArray(SArray** dst, SArray* src) {
  if (NULL == src) {
    return true;
  }
  size_t size = taosArrayGetSize(src);
  if (0 == size) {
    return true;
  }
  *dst = taosArrayInit(size, POINTER_BYTES);
  if (NULL == *dst) {
    return false;
  }
  return (TSDB_CODE_SUCCESS == copyAllExprInfo(*dst, src, true) ? true : false);
X
Xiaoyu Wang 已提交
72 73
}

74 75
static SPhyNode* initPhyNode(SQueryPlanNode* pPlanNode, int32_t type, int32_t size) {
  SPhyNode* node = (SPhyNode*)calloc(1, size);
76 77 78
  if (NULL == node) {
    return NULL;
  }
X
Xiaoyu Wang 已提交
79
  node->info.type = type;
80 81 82 83 84 85
  node->info.name = opTypeToOpName(type);
  if (!cloneExprArray(&node->pTargets, pPlanNode->pExpr) || !toDataBlockSchema(pPlanNode, &(node->targetSchema))) {
    free(node);
    return NULL;
  }
  return node;
86 87
}

88 89 90 91 92 93 94 95 96 97 98
static SPhyNode* initScanNode(SQueryPlanNode* pPlanNode, SQueryTableInfo* pTable, int32_t type, int32_t size) {
  SScanPhyNode* node = (SScanPhyNode*)initPhyNode(pPlanNode, type, size);
  node->uid = pTable->pMeta->pTableMeta->uid;
  node->tableType = pTable->pMeta->pTableMeta->tableType;
  return (SPhyNode*)node;
}

static SPhyNode* createPseudoScanNode(SQueryPlanNode* pPlanNode, SQueryTableInfo* pTable, int32_t op) {
  return initScanNode(pPlanNode, pTable, op, sizeof(SScanPhyNode));
}

99
static SPhyNode* createTagScanNode(SQueryPlanNode* pPlanNode) {
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
  SQueryTableInfo* pTable = (SQueryTableInfo*)pPlanNode->pExtInfo;
  return createPseudoScanNode(pPlanNode, pTable, OP_TagScan);
}

static uint8_t getScanFlag(SQueryPlanNode* pPlanNode, SQueryTableInfo* pTable) {
  // todo
  return MASTER_SCAN;
}

static SPhyNode* createUserTableScanNode(SQueryPlanNode* pPlanNode, SQueryTableInfo* pTable, int32_t op) {
  STableScanPhyNode* node = (STableScanPhyNode*)initScanNode(pPlanNode, pTable, op, sizeof(STableScanPhyNode));
  node->scanFlag = getScanFlag(pPlanNode, pTable);
  node->window = pTable->window;
  // todo tag cond
  return (SPhyNode*)node;
}

static SPhyNode* createSingleTableScanNode(SQueryPlanNode* pPlanNode, SQueryTableInfo* pTable) {
  return createUserTableScanNode(pPlanNode, pTable, OP_TableScan);
}

static bool isSystemTable(SQueryTableInfo* pTable) {
  // todo
  return false;
}

static bool needSeqScan(SQueryPlanNode* pPlanNode) {
  // todo
  return false;
}

static SPhyNode* createMultiTableScanNode(SQueryPlanNode* pPlanNode, SQueryTableInfo* pTable) {
  if (isSystemTable(pTable)) {
    return createPseudoScanNode(pPlanNode, pTable, OP_SystemTableScan);
  } else if (needSeqScan(pPlanNode)) {
    return createUserTableScanNode(pPlanNode, pTable, OP_TableSeqScan);
  }
  return createUserTableScanNode(pPlanNode, pTable, OP_DataBlocksOptScan);
138 139 140 141 142 143 144 145 146 147 148 149 150
}

static SSubplan* initSubplan(SPlanContext* pCxt, int32_t type) {
  SSubplan* subplan = calloc(1, sizeof(SSubplan));
  subplan->id = pCxt->nextId;
  ++(pCxt->nextId.subplanId);
  subplan->type = type;
  subplan->level = 0;
  if (NULL != pCxt->pCurrentSubplan) {
    subplan->level = pCxt->pCurrentSubplan->level + 1;
    if (NULL == pCxt->pCurrentSubplan->pChildern) {
      pCxt->pCurrentSubplan->pChildern = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES);
    }
151
    taosArrayPush(pCxt->pCurrentSubplan->pChildern, &subplan);
152
    subplan->pParents = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES);
153 154 155 156 157 158 159 160
    taosArrayPush(subplan->pParents, &pCxt->pCurrentSubplan);
  }
  SArray* currentLevel;
  if (subplan->level >= taosArrayGetSize(pCxt->pDag->pSubplans)) {
    currentLevel = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES);
    taosArrayPush(pCxt->pDag->pSubplans, &currentLevel);
  } else {
    currentLevel = taosArrayGetP(pCxt->pDag->pSubplans, subplan->level);
161
  }
162
  taosArrayPush(currentLevel, &subplan);
163 164 165 166 167
  pCxt->pCurrentSubplan = subplan;
  return subplan;
}

static void vgroupToEpSet(const SVgroupMsg* vg, SEpSet* epSet) {
168 169 170 171 172 173 174
  epSet->inUse = 0; // todo
  epSet->numOfEps = vg->numOfEps;
  for (int8_t i = 0; i < vg->numOfEps; ++i) {
    epSet->port[i] = vg->epAddr[i].port;
    strcpy(epSet->fqdn[i], vg->epAddr[i].fqdn);
  }
  return;
X
Xiaoyu Wang 已提交
175 176
}

177
static uint64_t splitSubplanByTable(SPlanContext* pCxt, SQueryPlanNode* pPlanNode, SQueryTableInfo* pTable) {
178 179
  SVgroupsInfo* vgroupList = pTable->pMeta->vgroupList;
  for (int32_t i = 0; i < pTable->pMeta->vgroupList->numOfVgroups; ++i) {
180
    STORE_CURRENT_SUBPLAN(pCxt);
181 182
    SSubplan* subplan = initSubplan(pCxt, QUERY_TYPE_SCAN);
    vgroupToEpSet(&(pTable->pMeta->vgroupList->vgroups[i]), &subplan->execEpSet);
183 184
    subplan->pNode = createMultiTableScanNode(pPlanNode, pTable);
    RECOVERY_CURRENT_SUBPLAN(pCxt);
185
  }
186
  return pCxt->nextId.templateId++;
X
Xiaoyu Wang 已提交
187 188
}

189 190 191 192 193
static SPhyNode* createExchangeNode(SPlanContext* pCxt, SQueryPlanNode* pPlanNode, uint64_t srcTemplateId) {
  SExchangePhyNode* node = (SExchangePhyNode*)initPhyNode(pPlanNode, OP_Exchange, sizeof(SExchangePhyNode));
  node->srcTemplateId = srcTemplateId;
  return (SPhyNode*)node;
}
194

195 196 197
static bool needMultiNodeScan(SQueryTableInfo* pTable) {
  // todo system table, for instance, user_tables
  return (TSDB_SUPER_TABLE == pTable->pMeta->pTableMeta->tableType);
198 199
}

200
static SPhyNode* createTableScanNode(SPlanContext* pCxt, SQueryPlanNode* pPlanNode) {
201
  SQueryTableInfo* pTable = (SQueryTableInfo*)pPlanNode->pExtInfo;
202 203
  if (needMultiNodeScan(pTable)) {
    return createExchangeNode(pCxt, pPlanNode, splitSubplanByTable(pCxt, pPlanNode, pTable));
204
  }
205
  return createSingleTableScanNode(pPlanNode, pTable);
206 207 208
}

static SPhyNode* createPhyNode(SPlanContext* pCxt, SQueryPlanNode* pPlanNode) {
X
Xiaoyu Wang 已提交
209 210 211 212 213 214
  SPhyNode* node = NULL;
  switch (pPlanNode->info.type) {
    case QNODE_TAGSCAN:
      node = createTagScanNode(pPlanNode);
      break;
    case QNODE_TABLESCAN:
215
      node = createTableScanNode(pCxt, pPlanNode);
X
Xiaoyu Wang 已提交
216 217 218 219 220
      break;
    default:
      assert(false);
  }
  if (pPlanNode->pChildren != NULL && taosArrayGetSize(pPlanNode->pChildren) > 0) {
X
Xiaoyu Wang 已提交
221
    node->pChildren = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES);
X
Xiaoyu Wang 已提交
222 223
    size_t size = taosArrayGetSize(pPlanNode->pChildren);
    for(int32_t i = 0; i < size; ++i) {
224
      SPhyNode* child = createPhyNode(pCxt, taosArrayGetP(pPlanNode->pChildren, i));
X
Xiaoyu Wang 已提交
225 226 227
      child->pParent = node;
      taosArrayPush(node->pChildren, &child);
    }
228
  }
X
Xiaoyu Wang 已提交
229
  return node;
230 231
}

232 233
static void createSubplanByLevel(SPlanContext* pCxt, SQueryPlanNode* pRoot) {
  SSubplan* subplan = initSubplan(pCxt, QUERY_TYPE_MERGE);
234
  ++(pCxt->nextId.templateId);
235 236 237 238 239 240 241 242
  subplan->pNode = createPhyNode(pCxt, pRoot);
  // todo deal subquery
}

int32_t createDag(SQueryPlanNode* pQueryNode, struct SCatalog* pCatalog, SQueryDag** pDag) {
  SPlanContext context = {
    .pCatalog = pCatalog,
    .pDag = calloc(1, sizeof(SQueryDag)),
243 244
    .pCurrentSubplan = NULL,
    .nextId = {0} // todo queryid
245 246 247 248 249 250 251 252
  };
  if (NULL == context.pDag) {
    return TSDB_CODE_TSC_OUT_OF_MEMORY;
  }
  context.pDag->pSubplans = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES);
  createSubplanByLevel(&context, pQueryNode);
  *pDag = context.pDag;
  return TSDB_CODE_SUCCESS;
253
}
X
Xiaoyu Wang 已提交
254

D
dapan 已提交
255
int32_t setSubplanExecutionNode(SSubplan* subplan, uint64_t templateId, SEpAddr* ep) {
256
  //todo
X
Xiaoyu Wang 已提交
257
}