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

16
#include "parserUtil.h"
17

X
Xiaoyu Wang 已提交
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
int32_t buildInvalidOperationMsg(SMsgBuf* pBuf, const char* msg) {
  strncpy(pBuf->buf, msg, pBuf->len);
  return TSDB_CODE_TSC_INVALID_OPERATION;
}

int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr) {
  const char* msgFormat1 = "syntax error near \'%s\'";
  const char* msgFormat2 = "syntax error near \'%s\' (%s)";
  const char* msgFormat3 = "%s";

  const char* prefix = "syntax error";
  if (sourceStr == NULL) {
    assert(additionalInfo != NULL);
    snprintf(pBuf->buf, pBuf->len, msgFormat1, additionalInfo);
    return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
  }
34

X
Xiaoyu Wang 已提交
35 36 37 38 39 40 41 42 43 44 45 46
  char buf[64] = {0};  // only extract part of sql string
  strncpy(buf, sourceStr, tListLen(buf) - 1);

  if (additionalInfo != NULL) {
    snprintf(pBuf->buf, pBuf->len, msgFormat2, buf, additionalInfo);
  } else {
    const char* msgFormat = (0 == strncmp(sourceStr, prefix, strlen(prefix))) ? msgFormat3 : msgFormat1;
    snprintf(pBuf->buf, pBuf->len, msgFormat, buf);
  }

  return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
}
47

48
int32_t parserValidateIdToken(SToken* pToken) {
49
  if (pToken == NULL || pToken->z == NULL || pToken->type != TK_NK_ID) {
50 51 52
    return TSDB_CODE_TSC_INVALID_OPERATION;
  }

53 54 55 56 57
  // it is a token quoted with escape char '`'
  if (pToken->z[0] == TS_ESCAPE_CHAR && pToken->z[pToken->n - 1] == TS_ESCAPE_CHAR) {
    return TSDB_CODE_SUCCESS;
  }

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
  char* sep = strnchr(pToken->z, TS_PATH_DELIMITER[0], pToken->n, true);
  if (sep == NULL) {  // It is a single part token, not a complex type
    if (isNumber(pToken)) {
      return TSDB_CODE_TSC_INVALID_OPERATION;
    }

    strntolower(pToken->z, pToken->z, pToken->n);
  } else {  // two part
    int32_t oldLen = pToken->n;
    char*   pStr = pToken->z;

    if (pToken->type == TK_SPACE) {
      pToken->n = (uint32_t)strtrim(pToken->z);
    }

    pToken->n = tGetToken(pToken->z, &pToken->type);
    if (pToken->z[pToken->n] != TS_PATH_DELIMITER[0]) {
      return TSDB_CODE_TSC_INVALID_OPERATION;
    }

78
    if (pToken->type != TK_NK_ID) {
79 80 81 82 83 84 85 86
      return TSDB_CODE_TSC_INVALID_OPERATION;
    }

    int32_t firstPartLen = pToken->n;

    pToken->z = sep + 1;
    pToken->n = (uint32_t)(oldLen - (sep - pStr) - 1);
    int32_t len = tGetToken(pToken->z, &pToken->type);
87
    if (len != pToken->n || pToken->type != TK_NK_ID) {
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
      return TSDB_CODE_TSC_INVALID_OPERATION;
    }

    // re-build the whole name string
    if (pStr[firstPartLen] == TS_PATH_DELIMITER[0]) {
      // first part do not have quote do nothing
    } else {
      pStr[firstPartLen] = TS_PATH_DELIMITER[0];
      memmove(&pStr[firstPartLen + 1], pToken->z, pToken->n);
      uint32_t offset = (uint32_t)(pToken->z - (pStr + firstPartLen + 1));
      memset(pToken->z + pToken->n - offset, ' ', offset);
    }

    pToken->n += (firstPartLen + sizeof(TS_PATH_DELIMITER[0]));
    pToken->z = pStr;

    strntolower(pToken->z, pToken->z, pToken->n);
  }

  return TSDB_CODE_SUCCESS;
108 109
}

X
Xiaoyu Wang 已提交
110 111
int32_t KvRowAppend(const void *value, int32_t len, void *param) {
  SKvParam* pa = (SKvParam*) param;
112

X
Xiaoyu Wang 已提交
113 114
  int32_t type  = pa->schema->type;
  int32_t colId = pa->schema->colId;
115

X
Xiaoyu Wang 已提交
116 117 118 119 120 121 122 123
  if (TSDB_DATA_TYPE_BINARY == type) {
    STR_WITH_SIZE_TO_VARSTR(pa->buf, value, len);
    tdAddColToKVRow(pa->builder, colId, type, pa->buf);
  } else if (TSDB_DATA_TYPE_NCHAR == type) {
    // if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long'
    int32_t output = 0;
    if (!taosMbsToUcs4(value, len, varDataVal(pa->buf), pa->schema->bytes - VARSTR_HEADER_SIZE, &output)) {
      return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
124 125
    }

X
Xiaoyu Wang 已提交
126 127
    varDataSetLen(pa->buf, output);
    tdAddColToKVRow(pa->builder, colId, type, pa->buf);
128
  } else {
X
Xiaoyu Wang 已提交
129
    tdAddColToKVRow(pa->builder, colId, type, value);
130 131
  }

X
Xiaoyu Wang 已提交
132
  return TSDB_CODE_SUCCESS;
133 134
}

X
Xiaoyu Wang 已提交
135 136
static uint32_t getTableMetaSize(const STableMeta* pTableMeta) {
  assert(pTableMeta != NULL);
137

X
Xiaoyu Wang 已提交
138 139 140
  int32_t totalCols = 0;
  if (pTableMeta->tableInfo.numOfColumns >= 0) {
    totalCols = pTableMeta->tableInfo.numOfColumns + pTableMeta->tableInfo.numOfTags;
141 142
  }

X
Xiaoyu Wang 已提交
143
  return sizeof(STableMeta) + totalCols * sizeof(SSchema);
144 145
}

X
Xiaoyu Wang 已提交
146 147 148
STableMeta* tableMetaDup(const STableMeta* pTableMeta) {
  assert(pTableMeta != NULL);
  size_t size = getTableMetaSize(pTableMeta);
149

X
Xiaoyu Wang 已提交
150 151 152
  STableMeta* p = malloc(size);
  memcpy(p, pTableMeta, size);
  return p;
153 154
}

X
Xiaoyu Wang 已提交
155 156 157
SSchema *getTableColumnSchema(const STableMeta *pTableMeta) {
  assert(pTableMeta != NULL);
  return (SSchema*) pTableMeta->schema;
158 159
}

X
Xiaoyu Wang 已提交
160 161
static SSchema* getOneColumnSchema(const STableMeta* pTableMeta, int32_t colIndex) {
  assert(pTableMeta != NULL && pTableMeta->schema != NULL && colIndex >= 0 && colIndex < (getNumOfColumns(pTableMeta) + getNumOfTags(pTableMeta)));
162

X
Xiaoyu Wang 已提交
163 164
  SSchema* pSchema = (SSchema*) pTableMeta->schema;
  return &pSchema[colIndex];
165
}
166

X
Xiaoyu Wang 已提交
167 168 169
SSchema* getTableTagSchema(const STableMeta* pTableMeta) {
  assert(pTableMeta != NULL && (pTableMeta->tableType == TSDB_SUPER_TABLE || pTableMeta->tableType == TSDB_CHILD_TABLE));
  return getOneColumnSchema(pTableMeta, getTableInfo(pTableMeta).numOfColumns);
170 171
}

X
Xiaoyu Wang 已提交
172 173 174 175
int32_t getNumOfColumns(const STableMeta* pTableMeta) {
  assert(pTableMeta != NULL);
  // table created according to super table, use data from super table
  return getTableInfo(pTableMeta).numOfColumns;
176 177
}

X
Xiaoyu Wang 已提交
178 179 180
int32_t getNumOfTags(const STableMeta* pTableMeta) {
  assert(pTableMeta != NULL);
  return getTableInfo(pTableMeta).numOfTags;
181 182
}

X
Xiaoyu Wang 已提交
183
STableComInfo getTableInfo(const STableMeta* pTableMeta) {
184
  assert(pTableMeta != NULL);
X
Xiaoyu Wang 已提交
185
  return pTableMeta->tableInfo;
H
Haojun Liao 已提交
186
}