parser.c 7.7 KB
Newer Older
H
refact  
Hongze Cheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * 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
Haojun Liao 已提交
14 15
 */

16
#include "astGenerator.h"
17
#include "parserInt.h"
18
#include "parserUtil.h"
19
#include "ttoken.h"
20
#include "function.h"
21
#include "insertParser.h"
22

X
Xiaoyu Wang 已提交
23
bool isInsertSql(const char* pStr, size_t length) {
24 25 26
  int32_t index = 0;

  do {
27
    SToken t0 = tStrGetToken((char*) pStr, &index, false);
28 29 30 31
    if (t0.type != TK_LP) {
      return t0.type == TK_INSERT || t0.type == TK_IMPORT;
    }
  } while (1);
32 33
}

H
Haojun Liao 已提交
34 35
bool qIsDdlQuery(const SQueryNode* pQueryNode) {
  return TSDB_SQL_INSERT != pQueryNode->type && TSDB_SQL_SELECT != pQueryNode->type && TSDB_SQL_CREATE_TABLE != pQueryNode->type;
X
Xiaoyu Wang 已提交
36 37 38
}

int32_t parseQuerySql(SParseContext* pCxt, SQueryNode** pQuery) {
H
Haojun Liao 已提交
39 40
  int32_t code = TSDB_CODE_SUCCESS;

X
Xiaoyu Wang 已提交
41
  SSqlInfo info = doGenerateAST(pCxt->pSql);
42
  if (!info.valid) {
X
Xiaoyu Wang 已提交
43
    strncpy(pCxt->pMsg, info.msg, pCxt->msgLen);
H
Haojun Liao 已提交
44 45
    code = TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
    goto _end;
46 47
  }

48
  if (!isDqlSqlStatement(&info)) {
49
    if (info.type == TSDB_SQL_CREATE_TABLE) {
H
Haojun Liao 已提交
50
      SVnodeModifOpStmtInfo * pModifStmtInfo = qParserValidateCreateTbSqlNode(&info, pCxt, pCxt->pMsg, pCxt->msgLen);
51
      if (pModifStmtInfo == NULL) {
H
Haojun Liao 已提交
52 53
        code = terrno;
        goto _end;
54 55
      }

56
      *pQuery = (SQueryNode*)pModifStmtInfo;
57
    } else {
H
Haojun Liao 已提交
58
      SDclStmtInfo* pDcl = qParserValidateDclSqlNode(&info, pCxt, pCxt->pMsg, pCxt->msgLen);
59
      if (pDcl == NULL) {
H
Haojun Liao 已提交
60 61
        code = terrno;
        goto _end;
62 63
      }

X
Xiaoyu Wang 已提交
64
      *pQuery = (SQueryNode*)pDcl;
65
      pDcl->nodeType = info.type;
66 67
    }
  } else {
H
Haojun Liao 已提交
68
    SQueryStmtInfo* pQueryInfo = createQueryInfo();
H
Haojun Liao 已提交
69
    if (pQueryInfo == NULL) {
H
Haojun Liao 已提交
70 71
      code = TSDB_CODE_QRY_OUT_OF_MEMORY; // set correct error code.
      goto _end;
H
Haojun Liao 已提交
72 73
    }

H
Haojun Liao 已提交
74
    code = qParserValidateSqlNode(pCxt, &info, pQueryInfo, pCxt->pMsg, pCxt->msgLen);
75
    if (code == TSDB_CODE_SUCCESS) {
X
Xiaoyu Wang 已提交
76
      *pQuery = (SQueryNode*)pQueryInfo;
77
    } else {
H
Haojun Liao 已提交
78
      goto _end;
79
    }
80 81
  }

H
Haojun Liao 已提交
82
  _end:
H
Haojun Liao 已提交
83
  destroySqlInfo(&info);
H
Haojun Liao 已提交
84 85
  terrno = code;
  return code;
86 87
}

H
Haojun Liao 已提交
88
int32_t qParseQuerySql(SParseContext* pCxt, SQueryNode** pQueryNode) {
X
Xiaoyu Wang 已提交
89
  if (isInsertSql(pCxt->pSql, pCxt->sqlLen)) {
H
Haojun Liao 已提交
90
    return parseInsertSql(pCxt, (SVnodeModifOpStmtInfo**)pQueryNode);
X
Xiaoyu Wang 已提交
91
  } else {
H
Haojun Liao 已提交
92
    return parseQuerySql(pCxt, pQueryNode);
X
Xiaoyu Wang 已提交
93
  }
94 95 96 97 98 99
}

int32_t qParserConvertSql(const char* pStr, size_t length, char** pConvertSql) {
  return 0;
}

H
Haojun Liao 已提交
100
static int32_t getTableNameFromSqlNode(SSqlNode* pSqlNode, SArray* tableNameList, SParseContext *pCtx, SMsgBuf* pMsgBuf);
101 102 103 104 105

static int32_t tnameComparFn(const void* p1, const void* p2) {
  SName* pn1 = (SName*)p1;
  SName* pn2 = (SName*)p2;

H
Haojun Liao 已提交
106
  int32_t ret = pn1->acctId - pn2->acctId;
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
  if (ret != 0) {
    return ret > 0? 1:-1;
  } else {
    ret = strncmp(pn1->dbname, pn2->dbname, tListLen(pn1->dbname));
    if (ret != 0) {
      return ret > 0? 1:-1;
    } else {
      ret = strncmp(pn1->tname, pn2->tname, tListLen(pn1->tname));
      if (ret != 0) {
        return ret > 0? 1:-1;
      } else {
        return 0;
      }
    }
  }
}

H
Haojun Liao 已提交
124
static int32_t getTableNameFromSubquery(SSqlNode* pSqlNode, SArray* tableNameList, SParseContext *pCtx, SMsgBuf* pMsgBuf) {
125 126 127
  int32_t numOfSub = (int32_t)taosArrayGetSize(pSqlNode->from->list);

  for (int32_t j = 0; j < numOfSub; ++j) {
128
    SRelElement* sub = taosArrayGet(pSqlNode->from->list, j);
129

130
    int32_t num = (int32_t)taosArrayGetSize(sub->pSubquery->node);
131
    for (int32_t i = 0; i < num; ++i) {
132 133
      SSqlNode* p = taosArrayGetP(sub->pSubquery->node, i);
      if (p->from->type == SQL_FROM_NODE_TABLES) {
H
Haojun Liao 已提交
134
        int32_t code = getTableNameFromSqlNode(p, tableNameList, pCtx, pMsgBuf);
135 136 137 138
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
      } else {
H
Haojun Liao 已提交
139
        getTableNameFromSubquery(p, tableNameList, pCtx, pMsgBuf);
140 141 142 143 144 145 146
      }
    }
  }

  return TSDB_CODE_SUCCESS;
}

H
Haojun Liao 已提交
147
int32_t getTableNameFromSqlNode(SSqlNode* pSqlNode, SArray* tableNameList, SParseContext *pParseCtx, SMsgBuf* pMsgBuf) {
148 149 150
  const char* msg1 = "invalid table name";

  int32_t numOfTables = (int32_t) taosArrayGetSize(pSqlNode->from->list);
151
  assert(pSqlNode->from->type == SQL_FROM_NODE_TABLES);
152 153

  for(int32_t j = 0; j < numOfTables; ++j) {
154
    SRelElement* item = taosArrayGet(pSqlNode->from->list, j);
155 156

    SToken* t = &item->tableName;
157
    if (t->type == TK_INTEGER || t->type == TK_FLOAT || t->type == TK_STRING) {
158
      return buildInvalidOperationMsg(pMsgBuf, msg1);
159 160 161
    }

    if (parserValidateIdToken(t) != TSDB_CODE_SUCCESS) {
162
      return buildInvalidOperationMsg(pMsgBuf, msg1);
163 164 165
    }

    SName name = {0};
H
Haojun Liao 已提交
166 167 168 169 170
    int32_t code = createSName(&name, t, pParseCtx, pMsgBuf);
    if (code != TSDB_CODE_SUCCESS) {
      return buildInvalidOperationMsg(pMsgBuf, msg1);
    }

171 172 173 174 175 176
    taosArrayPush(tableNameList, &name);
  }

  return TSDB_CODE_SUCCESS;
}

177 178 179
static void freePtrElem(void* p) {
  tfree(*(char**)p);
}
180

H
Haojun Liao 已提交
181
int32_t qParserExtractRequestedMetaInfo(const SSqlInfo* pSqlInfo, SCatalogReq* pMetaInfo, SParseContext *pCtx, char* msg, int32_t msgBufLen) {
182
  int32_t code  = TSDB_CODE_SUCCESS;
183
  SMsgBuf msgBuf = {.buf = msg, .len = msgBufLen};
184

185 186
  pMetaInfo->pTableName = taosArrayInit(4, sizeof(SName));
  pMetaInfo->pUdf = taosArrayInit(4, POINTER_BYTES);
187

188
  size_t size = taosArrayGetSize(pSqlInfo->sub.node);
189
  for (int32_t i = 0; i < size; ++i) {
190
    SSqlNode* pSqlNode = taosArrayGetP(pSqlInfo->sub.node, i);
191
    if (pSqlNode->from == NULL) {
192
      return buildInvalidOperationMsg(&msgBuf, "invalid from clause");
193 194
    }

195
    // load the table meta in the FROM clause
196
    if (pSqlNode->from->type == SQL_FROM_NODE_TABLES) {
H
Haojun Liao 已提交
197
      code = getTableNameFromSqlNode(pSqlNode, pMetaInfo->pTableName, pCtx, &msgBuf);
198
      if (code != TSDB_CODE_SUCCESS) {
199
        return code;
200 201
      }
    } else {
H
Haojun Liao 已提交
202
      code = getTableNameFromSubquery(pSqlNode, pMetaInfo->pTableName, pCtx, &msgBuf);
203
      if (code != TSDB_CODE_SUCCESS) {
204
        return code;
205 206 207 208
      }
    }
  }

209 210
  taosArraySort(pMetaInfo->pTableName, tnameComparFn);
  taosArrayRemoveDuplicate(pMetaInfo->pTableName, tnameComparFn, NULL);
211 212

  size_t funcSize = 0;
213 214
  if (pSqlInfo->funcs) {
    funcSize = taosArrayGetSize(pSqlInfo->funcs);
215 216 217 218
  }

  if (funcSize > 0) {
    for (size_t i = 0; i < funcSize; ++i) {
219 220
      SToken* t = taosArrayGet(pSqlInfo->funcs, i);
      assert(t != NULL);
221 222

      if (t->n >= TSDB_FUNC_NAME_LEN) {
223
        return buildSyntaxErrMsg(&msgBuf, "too long function name", t->z);
224 225
      }

226
      // Let's assume that it is an UDF/UDAF, if it is not a built-in function.
227 228
      bool scalarFunc = false;
      if (qIsBuiltinFunction(t->z, t->n, &scalarFunc) < 0) {
229 230
        char* fname = strndup(t->z, t->n);
        taosArrayPush(pMetaInfo->pUdf, &fname);
231 232 233
      }
    }
  }
234 235

  return code;
236 237
}

238
void qParserCleanupMetaRequestInfo(SCatalogReq* pMetaReq) {
239 240 241 242 243 244 245
  if (pMetaReq == NULL) {
    return;
  }

  taosArrayDestroy(pMetaReq->pTableName);
  taosArrayDestroy(pMetaReq->pUdf);
}
X
Xiaoyu Wang 已提交
246

247
void qDestroyQuery(SQueryNode* pQueryNode) {
X
Xiaoyu Wang 已提交
248 249 250
  if (NULL == pQueryNode) {
    return;
  }
251

X
Xiaoyu Wang 已提交
252
  int32_t type = queryNodeType(pQueryNode);
253
  if (type == TSDB_SQL_INSERT || type == TSDB_SQL_CREATE_TABLE) {
254 255
    SVnodeModifOpStmtInfo* pModifInfo = (SVnodeModifOpStmtInfo*)pQueryNode;
    taosArrayDestroy(pModifInfo->pDataBlocks);
H
Haojun Liao 已提交
256

257 258 259 260
    tfree(pQueryNode);
  } else if (type == TSDB_SQL_SELECT) {
    SQueryStmtInfo* pQueryStmtInfo = (SQueryStmtInfo*) pQueryNode;
    destroyQueryInfo(pQueryStmtInfo);
261
  }
X
Xiaoyu Wang 已提交
262
}