parser.c 5.8 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 22

bool qIsInsertSql(const char* pStr, size_t length) {
23 24 25
  int32_t index = 0;

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

H
Haojun Liao 已提交
33
int32_t qParseQuerySql(const char* pStr, size_t length, struct SQueryStmtInfo** pQueryInfo, int64_t id, char* msg, int32_t msgLen) {
34 35
  *pQueryInfo = calloc(1, sizeof(SQueryStmtInfo));
  if (*pQueryInfo == NULL) {
36
    return TSDB_CODE_TSC_OUT_OF_MEMORY; // set correct error code.
37 38
  }

H
Haojun Liao 已提交
39
  SSqlInfo info = doGenerateAST(pStr);
40
  if (!info.valid) {
41 42
    strncpy(msg, info.msg, msgLen);
    return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
43 44 45
  }

  struct SCatalog* pCatalog = getCatalogHandle(NULL);
46
  int32_t code = qParserValidateSqlNode(pCatalog, &info, *pQueryInfo, id, msg, msgLen);
47 48 49 50 51 52 53
  if (code != 0) {
    return code;
  }

  return 0;
}

H
Haojun Liao 已提交
54
int32_t qParseInsertSql(const char* pStr, size_t length, struct SInsertStmtInfo** pInsertInfo, int64_t id, char* msg, int32_t msgLen) {
55 56 57 58 59 60 61
  return 0;
}

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

62
static int32_t getTableNameFromSqlNode(SSqlNode* pSqlNode, SArray* tableNameList, SMsgBuf* pMsgBuf);
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

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

  int32_t ret = strncmp(pn1->acctId, pn2->acctId, tListLen(pn1->acctId));
  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;
      }
    }
  }
}

86
static int32_t getTableNameFromSubquery(SSqlNode* pSqlNode, SArray* tableNameList, SMsgBuf* pMsgBuf) {
87 88 89 90 91 92 93 94 95
  int32_t numOfSub = (int32_t)taosArrayGetSize(pSqlNode->from->list);

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

    int32_t num = (int32_t)taosArrayGetSize(sub->pSubquery);
    for (int32_t i = 0; i < num; ++i) {
      SSqlNode* p = taosArrayGetP(sub->pSubquery, i);
      if (p->from->type == SQL_NODE_FROM_TABLELIST) {
96
        int32_t code = getTableNameFromSqlNode(p, tableNameList, pMsgBuf);
97 98 99 100
        if (code != TSDB_CODE_SUCCESS) {
          return code;
        }
      } else {
101
        getTableNameFromSubquery(p, tableNameList, pMsgBuf);
102 103 104 105 106 107 108
      }
    }
  }

  return TSDB_CODE_SUCCESS;
}

109
int32_t getTableNameFromSqlNode(SSqlNode* pSqlNode, SArray* tableNameList, SMsgBuf* pMsgBuf) {
110 111 112 113 114 115 116 117 118
  const char* msg1 = "invalid table name";

  int32_t numOfTables = (int32_t) taosArrayGetSize(pSqlNode->from->list);
  assert(pSqlNode->from->type == SQL_NODE_FROM_TABLELIST);

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

    SToken* t = &item->tableName;
119
    if (t->type == TK_INTEGER || t->type == TK_FLOAT || t->type == TK_STRING) {
120
      return buildInvalidOperationMsg(pMsgBuf, msg1);
121 122 123
    }

    if (parserValidateIdToken(t) != TSDB_CODE_SUCCESS) {
124
      return buildInvalidOperationMsg(pMsgBuf, msg1);
125 126 127
    }

    SName name = {0};
128
    strndequote(name.tname, t->z, t->n);
129 130 131 132 133 134
    taosArrayPush(tableNameList, &name);
  }

  return TSDB_CODE_SUCCESS;
}

135 136 137
static void freePtrElem(void* p) {
  tfree(*(char**)p);
}
138

139 140
int32_t qParserExtractRequestedMetaInfo(const SSqlInfo* pSqlInfo, SMetaReq* pMetaInfo, char* msg, int32_t msgBufLen) {
  int32_t code  = TSDB_CODE_SUCCESS;
141
  SMsgBuf msgBuf = {.buf = msg, .len = msgBufLen};
142

143 144
  pMetaInfo->pTableName = taosArrayInit(4, sizeof(SName));
  pMetaInfo->pUdf = taosArrayInit(4, POINTER_BYTES);
145

146
  size_t size = taosArrayGetSize(pSqlInfo->list);
147
  for (int32_t i = 0; i < size; ++i) {
148
    SSqlNode* pSqlNode = taosArrayGetP(pSqlInfo->list, i);
149
    if (pSqlNode->from == NULL) {
150
      return buildInvalidOperationMsg(&msgBuf, "invalid from clause");
151 152
    }

153
    // load the table meta in the FROM clause
154
    if (pSqlNode->from->type == SQL_NODE_FROM_TABLELIST) {
155
      code = getTableNameFromSqlNode(pSqlNode, pMetaInfo->pTableName, &msgBuf);
156
      if (code != TSDB_CODE_SUCCESS) {
157
        return code;
158 159
      }
    } else {
160
      code = getTableNameFromSubquery(pSqlNode, pMetaInfo->pTableName, &msgBuf);
161
      if (code != TSDB_CODE_SUCCESS) {
162
        return code;
163 164 165 166
      }
    }
  }

167 168
  taosArraySort(pMetaInfo->pTableName, tnameComparFn);
  taosArrayRemoveDuplicate(pMetaInfo->pTableName, tnameComparFn, NULL);
169 170

  size_t funcSize = 0;
171 172
  if (pSqlInfo->funcs) {
    funcSize = taosArrayGetSize(pSqlInfo->funcs);
173 174 175 176
  }

  if (funcSize > 0) {
    for (size_t i = 0; i < funcSize; ++i) {
177 178
      SToken* t = taosArrayGet(pSqlInfo->funcs, i);
      assert(t != NULL);
179 180

      if (t->n >= TSDB_FUNC_NAME_LEN) {
181
        return buildSyntaxErrMsg(msg, msgBufLen, "too long function name", t->z);
182 183
      }

184
      // Let's assume that it is an UDF/UDAF, if it is not a built-in function.
185
      if (!qIsBuiltinFunction(t->z, t->n)) {
186 187
        char* fname = strndup(t->z, t->n);
        taosArrayPush(pMetaInfo->pUdf, &fname);
188 189 190
      }
    }
  }
191 192

  return code;
193
}