提交 08fb912a 编写于 作者: X Xiaoyu Wang

TD-13852 create super table implement

上级 be73f15a
......@@ -55,102 +55,104 @@
#define TK_TTL 37
#define TK_WAL 38
#define TK_VGROUPS 39
#define TK_SINGLESTABLE 40
#define TK_STREAMMODE 41
#define TK_SINGLE_STABLE 40
#define TK_STREAM_MODE 41
#define TK_USE 42
#define TK_TABLE 43
#define TK_NK_LP 44
#define TK_NK_RP 45
#define TK_NK_ID 46
#define TK_NK_DOT 47
#define TK_NK_COMMA 48
#define TK_COMMENT 49
#define TK_BOOL 50
#define TK_TINYINT 51
#define TK_SMALLINT 52
#define TK_INT 53
#define TK_INTEGER 54
#define TK_BIGINT 55
#define TK_FLOAT 56
#define TK_DOUBLE 57
#define TK_BINARY 58
#define TK_TIMESTAMP 59
#define TK_NCHAR 60
#define TK_UNSIGNED 61
#define TK_JSON 62
#define TK_VARCHAR 63
#define TK_MEDIUMBLOB 64
#define TK_BLOB 65
#define TK_VARBINARY 66
#define TK_DECIMAL 67
#define TK_SHOW 68
#define TK_DATABASES 69
#define TK_TABLES 70
#define TK_NK_FLOAT 71
#define TK_NK_BOOL 72
#define TK_NK_VARIABLE 73
#define TK_BETWEEN 74
#define TK_IS 75
#define TK_NULL 76
#define TK_NK_LT 77
#define TK_NK_GT 78
#define TK_NK_LE 79
#define TK_NK_GE 80
#define TK_NK_NE 81
#define TK_NK_EQ 82
#define TK_LIKE 83
#define TK_MATCH 84
#define TK_NMATCH 85
#define TK_IN 86
#define TK_FROM 87
#define TK_AS 88
#define TK_JOIN 89
#define TK_ON 90
#define TK_INNER 91
#define TK_SELECT 92
#define TK_DISTINCT 93
#define TK_WHERE 94
#define TK_PARTITION 95
#define TK_BY 96
#define TK_SESSION 97
#define TK_STATE_WINDOW 98
#define TK_INTERVAL 99
#define TK_SLIDING 100
#define TK_FILL 101
#define TK_VALUE 102
#define TK_NONE 103
#define TK_PREV 104
#define TK_LINEAR 105
#define TK_NEXT 106
#define TK_GROUP 107
#define TK_HAVING 108
#define TK_ORDER 109
#define TK_SLIMIT 110
#define TK_SOFFSET 111
#define TK_LIMIT 112
#define TK_OFFSET 113
#define TK_ASC 114
#define TK_DESC 115
#define TK_NULLS 116
#define TK_FIRST 117
#define TK_LAST 118
#define TK_STABLE 46
#define TK_USING 47
#define TK_TAGS 48
#define TK_NK_ID 49
#define TK_NK_DOT 50
#define TK_NK_COMMA 51
#define TK_COMMENT 52
#define TK_BOOL 53
#define TK_TINYINT 54
#define TK_SMALLINT 55
#define TK_INT 56
#define TK_INTEGER 57
#define TK_BIGINT 58
#define TK_FLOAT 59
#define TK_DOUBLE 60
#define TK_BINARY 61
#define TK_TIMESTAMP 62
#define TK_NCHAR 63
#define TK_UNSIGNED 64
#define TK_JSON 65
#define TK_VARCHAR 66
#define TK_MEDIUMBLOB 67
#define TK_BLOB 68
#define TK_VARBINARY 69
#define TK_DECIMAL 70
#define TK_SMA 71
#define TK_SHOW 72
#define TK_DATABASES 73
#define TK_TABLES 74
#define TK_NK_FLOAT 75
#define TK_NK_BOOL 76
#define TK_NK_VARIABLE 77
#define TK_BETWEEN 78
#define TK_IS 79
#define TK_NULL 80
#define TK_NK_LT 81
#define TK_NK_GT 82
#define TK_NK_LE 83
#define TK_NK_GE 84
#define TK_NK_NE 85
#define TK_NK_EQ 86
#define TK_LIKE 87
#define TK_MATCH 88
#define TK_NMATCH 89
#define TK_IN 90
#define TK_FROM 91
#define TK_AS 92
#define TK_JOIN 93
#define TK_ON 94
#define TK_INNER 95
#define TK_SELECT 96
#define TK_DISTINCT 97
#define TK_WHERE 98
#define TK_PARTITION 99
#define TK_BY 100
#define TK_SESSION 101
#define TK_STATE_WINDOW 102
#define TK_INTERVAL 103
#define TK_SLIDING 104
#define TK_FILL 105
#define TK_VALUE 106
#define TK_NONE 107
#define TK_PREV 108
#define TK_LINEAR 109
#define TK_NEXT 110
#define TK_GROUP 111
#define TK_HAVING 112
#define TK_ORDER 113
#define TK_SLIMIT 114
#define TK_SOFFSET 115
#define TK_LIMIT 116
#define TK_OFFSET 117
#define TK_ASC 118
#define TK_DESC 119
#define TK_NULLS 120
#define TK_FIRST 121
#define TK_LAST 122
#define TK_SPACE 300
#define TK_NK_COMMENT 301
#define TK_ILLEGAL 302
#define TK_HEX 303 // hex number 0x123
#define TK_OCT 304 // oct number
#define TK_BIN 305 // bin format data 0b111
#define TK_FILE 306
#define TK_QUESTION 307 // denoting the placeholder of "?",when invoking statement bind query
#define TK_NK_SPACE 300
#define TK_NK_COMMENT 301
#define TK_NK_ILLEGAL 302
#define TK_NK_HEX 303 // hex number 0x123
#define TK_NK_OCT 304 // oct number
#define TK_NK_BIN 305 // bin format data 0b111
#define TK_NK_FILE 306
#define TK_NK_QUESTION 307 // denoting the placeholder of "?",when invoking statement bind query
#define TK_NK_COLON 500
#define TK_NK_BITNOT 501
#define TK_INSERT 502
#define TK_INTO 503
#define TK_NOW 504
#define TK_TAGS 505
#define TK_USING 506
#define TK_VALUES 507
#define TK_IMPORT 507
#define TK_SEMI 508
......
......@@ -58,6 +58,7 @@ typedef struct STableOptions {
int32_t keep;
int32_t ttl;
char comments[TSDB_STB_COMMENT_LEN];
SNodeList* pSma;
} STableOptions;
typedef struct SColumnDefNode {
......@@ -73,10 +74,25 @@ typedef struct SCreateTableStmt {
char tableName[TSDB_TABLE_NAME_LEN];
bool ignoreExists;
SNodeList* pCols;
SNodeList* pTags;
STableOptions options;
} SCreateTableStmt;
// CREATE TABLE [IF NOT EXISTS] [db_name.]tb_name (create_definition [, create_definitionn] ...) [table_options]
typedef struct SCreateSubTableStmt {
ENodeType type;
char dbName[TSDB_DB_NAME_LEN];
char tableName[TSDB_TABLE_NAME_LEN];
char useDbName[TSDB_DB_NAME_LEN];
char useTableName[TSDB_TABLE_NAME_LEN];
bool ignoreExists;
SNodeList* pSpecificTags;
SNodeList* pValsOfTags;
} SCreateSubTableStmt;
typedef struct SCreateMultiTableStmt {
ENodeType type;
SNodeList* pSubTables;
} SCreateMultiTableStmt;
#ifdef __cplusplus
}
......
......@@ -73,6 +73,8 @@ typedef enum ENodeType {
QUERY_NODE_VNODE_MODIF_STMT,
QUERY_NODE_CREATE_DATABASE_STMT,
QUERY_NODE_CREATE_TABLE_STMT,
QUERY_NODE_CREATE_SUBTABLE_STMT,
QUERY_NODE_CREATE_MULTI_TABLE_STMT,
QUERY_NODE_USE_DATABASE_STMT,
QUERY_NODE_SHOW_DATABASES_STMT, // temp
QUERY_NODE_SHOW_TABLES_STMT, // temp
......
......@@ -74,6 +74,7 @@ typedef struct SValueNode {
SExprNode node; // QUERY_NODE_VALUE
char* literal;
bool isDuration;
bool translate;
union {
bool b;
int64_t i;
......
......@@ -94,11 +94,11 @@ void taosVariantCreate(SVariant *pVar, const char *z, int32_t n, int32_t type) {
bool sign = true;
int32_t base = 10;
if (type == TK_HEX) {
if (type == TK_NK_HEX) {
base = 16;
} else if (type == TK_OCT) {
} else if (type == TK_NK_OCT) {
base = 8;
} else if (type == TK_BIN) {
} else if (type == TK_NK_BIN) {
base = 2;
}
......
/*
* 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/>.
*/
#ifndef _TD_NODES_INT_H_
#define _TD_NODES_INT_H_
#ifdef __cplusplus
extern "C" {
#endif
#define nodesFatal(param, ...) qFatal("NODES: " param, __VA_ARGS__)
#define nodesError(param, ...) qError("NODES: " param, __VA_ARGS__)
#define nodesWarn(param, ...) qWarn("NODES: " param, __VA_ARGS__)
#define nodesInfo(param, ...) qInfo("NODES: " param, __VA_ARGS__)
#define nodesDebug(param, ...) qDebug("NODES: " param, __VA_ARGS__)
#define nodesTrace(param, ...) qTrace("NODES: " param, __VA_ARGS__)
#ifdef __cplusplus
}
#endif
#endif /*_TD_NODES_INT_H_*/
......@@ -13,6 +13,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "nodesint.h"
#include "plannodes.h"
#include "querynodes.h"
#include "taos.h"
......@@ -221,7 +222,7 @@ SNodeptr nodesCloneNode(const SNodeptr pNode) {
default:
break;
}
printf("nodesCloneNode unknown node = %s\n", nodesNodeName(nodeType(pNode)));
nodesWarn("nodesCloneNode unknown node = %s", nodesNodeName(nodeType(pNode)));
return pDst;
}
......
......@@ -13,6 +13,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "nodesint.h"
#include "plannodes.h"
#include "querynodes.h"
#include "query.h"
......@@ -127,9 +128,8 @@ const char* nodesNodeName(ENodeType type) {
default:
break;
}
static char tmp[20];
snprintf(tmp, sizeof(tmp), "Unknown %d", type);
return tmp;
nodesWarn("nodesNodeName unknown node = %d", type);
return "UnknownNode";
}
static int32_t nodeListToJson(SJson* pJson, const char* pName, const SNodeList* pList) {
......@@ -871,8 +871,53 @@ static int32_t jsonToColumnNode(const SJson* pJson, void* pObj) {
static const char* jkValueLiteral = "Literal";
static const char* jkValueDuration = "Duration";
static const char* jkValueTranslate = "Translate";
static const char* jkValueDatum = "Datum";
static int32_t datumToJson(const void* pObj, SJson* pJson) {
const SValueNode* pNode = (const SValueNode*)pObj;
int32_t code = TSDB_CODE_SUCCESS;
switch (pNode->node.resType.type) {
case TSDB_DATA_TYPE_NULL:
break;
case TSDB_DATA_TYPE_BOOL:
code = tjsonAddIntegerToObject(pJson, jkValueDatum, pNode->datum.b);
break;
case TSDB_DATA_TYPE_TINYINT:
case TSDB_DATA_TYPE_SMALLINT:
case TSDB_DATA_TYPE_INT:
case TSDB_DATA_TYPE_BIGINT:
case TSDB_DATA_TYPE_TIMESTAMP:
code = tjsonAddIntegerToObject(pJson, jkValueDatum, pNode->datum.i);
break;
case TSDB_DATA_TYPE_UTINYINT:
case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_UINT:
case TSDB_DATA_TYPE_UBIGINT:
code = tjsonAddIntegerToObject(pJson, jkValueDatum, pNode->datum.u);
break;
case TSDB_DATA_TYPE_FLOAT:
case TSDB_DATA_TYPE_DOUBLE:
code = tjsonAddDoubleToObject(pJson, jkValueDatum, pNode->datum.d);
break;
case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR:
case TSDB_DATA_TYPE_VARCHAR:
case TSDB_DATA_TYPE_VARBINARY:
code = tjsonAddStringToObject(pJson, jkValueDatum, pNode->datum.p);
break;
case TSDB_DATA_TYPE_JSON:
case TSDB_DATA_TYPE_DECIMAL:
case TSDB_DATA_TYPE_BLOB:
// todo
default:
break;
}
return code ;
}
static int32_t valueNodeToJson(const void* pObj, SJson* pJson) {
const SValueNode* pNode = (const SValueNode*)pObj;
......@@ -884,42 +929,54 @@ static int32_t valueNodeToJson(const void* pObj, SJson* pJson) {
code = tjsonAddBoolToObject(pJson, jkValueDuration, pNode->isDuration);
}
if (TSDB_CODE_SUCCESS == code) {
switch (pNode->node.resType.type) {
case TSDB_DATA_TYPE_NULL:
break;
case TSDB_DATA_TYPE_BOOL:
code = tjsonAddIntegerToObject(pJson, jkValueDatum, pNode->datum.b);
break;
case TSDB_DATA_TYPE_TINYINT:
case TSDB_DATA_TYPE_SMALLINT:
case TSDB_DATA_TYPE_INT:
case TSDB_DATA_TYPE_BIGINT:
case TSDB_DATA_TYPE_TIMESTAMP:
code = tjsonAddIntegerToObject(pJson, jkValueDatum, pNode->datum.i);
break;
case TSDB_DATA_TYPE_UTINYINT:
case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_UINT:
case TSDB_DATA_TYPE_UBIGINT:
code = tjsonAddIntegerToObject(pJson, jkValueDatum, pNode->datum.u);
break;
case TSDB_DATA_TYPE_FLOAT:
case TSDB_DATA_TYPE_DOUBLE:
code = tjsonAddDoubleToObject(pJson, jkValueDatum, pNode->datum.d);
break;
case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR:
case TSDB_DATA_TYPE_VARCHAR:
case TSDB_DATA_TYPE_VARBINARY:
code = tjsonAddStringToObject(pJson, jkValueDatum, pNode->datum.p);
break;
case TSDB_DATA_TYPE_JSON:
case TSDB_DATA_TYPE_DECIMAL:
case TSDB_DATA_TYPE_BLOB:
// todo
default:
break;
}
code = tjsonAddBoolToObject(pJson, jkValueTranslate, pNode->translate);
}
if (TSDB_CODE_SUCCESS == code && pNode->translate) {
code = datumToJson(pNode, pJson);
}
return code;
}
static int32_t jsonToDatum(const SJson* pJson, void* pObj) {
SValueNode* pNode = (SValueNode*)pObj;
int32_t code = TSDB_CODE_SUCCESS;
switch (pNode->node.resType.type) {
case TSDB_DATA_TYPE_NULL:
break;
case TSDB_DATA_TYPE_BOOL:
code = tjsonGetBoolValue(pJson, jkValueDatum, &pNode->datum.b);
break;
case TSDB_DATA_TYPE_TINYINT:
case TSDB_DATA_TYPE_SMALLINT:
case TSDB_DATA_TYPE_INT:
case TSDB_DATA_TYPE_BIGINT:
case TSDB_DATA_TYPE_TIMESTAMP:
code = tjsonGetBigIntValue(pJson, jkValueDatum, &pNode->datum.i);
break;
case TSDB_DATA_TYPE_UTINYINT:
case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_UINT:
case TSDB_DATA_TYPE_UBIGINT:
code = tjsonGetUBigIntValue(pJson, jkValueDatum, &pNode->datum.u);
break;
case TSDB_DATA_TYPE_FLOAT:
case TSDB_DATA_TYPE_DOUBLE:
code = tjsonGetDoubleValue(pJson, jkValueDatum, &pNode->datum.d);
break;
case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR:
case TSDB_DATA_TYPE_VARCHAR:
case TSDB_DATA_TYPE_VARBINARY:
code = tjsonDupStringValue(pJson, jkValueDatum, &pNode->datum.p);
break;
case TSDB_DATA_TYPE_JSON:
case TSDB_DATA_TYPE_DECIMAL:
case TSDB_DATA_TYPE_BLOB:
// todo
default:
break;
}
return code;
......@@ -936,42 +993,10 @@ static int32_t jsonToValueNode(const SJson* pJson, void* pObj) {
code = tjsonGetBoolValue(pJson, jkValueDuration, &pNode->isDuration);
}
if (TSDB_CODE_SUCCESS == code) {
switch (pNode->node.resType.type) {
case TSDB_DATA_TYPE_NULL:
break;
case TSDB_DATA_TYPE_BOOL:
code = tjsonGetBoolValue(pJson, jkValueDatum, &pNode->datum.b);
break;
case TSDB_DATA_TYPE_TINYINT:
case TSDB_DATA_TYPE_SMALLINT:
case TSDB_DATA_TYPE_INT:
case TSDB_DATA_TYPE_BIGINT:
case TSDB_DATA_TYPE_TIMESTAMP:
code = tjsonGetBigIntValue(pJson, jkValueDatum, &pNode->datum.i);
break;
case TSDB_DATA_TYPE_UTINYINT:
case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_UINT:
case TSDB_DATA_TYPE_UBIGINT:
code = tjsonGetUBigIntValue(pJson, jkValueDatum, &pNode->datum.u);
break;
case TSDB_DATA_TYPE_FLOAT:
case TSDB_DATA_TYPE_DOUBLE:
code = tjsonGetDoubleValue(pJson, jkValueDatum, &pNode->datum.d);
break;
case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR:
case TSDB_DATA_TYPE_VARCHAR:
case TSDB_DATA_TYPE_VARBINARY:
code = tjsonDupStringValue(pJson, jkValueDatum, &pNode->datum.p);
break;
case TSDB_DATA_TYPE_JSON:
case TSDB_DATA_TYPE_DECIMAL:
case TSDB_DATA_TYPE_BLOB:
// todo
default:
break;
}
code = tjsonGetBoolValue(pJson, jkValueTranslate, &pNode->translate);
}
if (TSDB_CODE_SUCCESS == code && pNode->translate) {
code = jsonToDatum(pJson, pNode);
}
return code;
......@@ -1365,7 +1390,7 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
default:
break;
}
printf("================================ specificNodeToJson unknown node = %s\n", nodesNodeName(nodeType(pObj)));
nodesWarn("specificNodeToJson unknown node = %s", nodesNodeName(nodeType(pObj)));
return TSDB_CODE_SUCCESS;
}
......@@ -1434,7 +1459,7 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
default:
break;
}
printf("================================ jsonToSpecificNode unknown node = %s\n", nodesNodeName(nodeType(pObj)));
nodesWarn("jsonToSpecificNode unknown node = %s", nodesNodeName(nodeType(pObj)));
return TSDB_CODE_SUCCESS;
}
......@@ -1450,6 +1475,9 @@ static int32_t nodeToJson(const void* pObj, SJson* pJson) {
}
if (TSDB_CODE_SUCCESS == code) {
code = tjsonAddObject(pJson, nodesNodeName(pNode->type), specificNodeToJson, pNode);
if (TSDB_CODE_SUCCESS != code) {
nodesError("%s ToJson error", nodesNodeName(pNode->type));
}
}
return code;
......@@ -1464,7 +1492,7 @@ static int32_t jsonToNode(const SJson* pJson, void* pObj) {
if (TSDB_CODE_SUCCESS == code) {
code = tjsonToObject(pJson, nodesNodeName(pNode->type), jsonToSpecificNode, pNode);
if (TSDB_CODE_SUCCESS != code) {
printf("%s toNode error\n", nodesNodeName(pNode->type));
nodesError("%s toNode error", nodesNodeName(pNode->type));
}
}
......
......@@ -14,11 +14,11 @@
*/
#include "cmdnodes.h"
#include "querynodes.h"
#include "nodesint.h"
#include "plannodes.h"
#include "querynodes.h"
#include "taos.h"
#include "taoserror.h"
#include "taos.h"
#include "thash.h"
static SNode* makeNode(ENodeType type, size_t size) {
......@@ -84,6 +84,10 @@ SNodeptr nodesMakeNode(ENodeType type) {
return makeNode(type, sizeof(SCreateDatabaseStmt));
case QUERY_NODE_CREATE_TABLE_STMT:
return makeNode(type, sizeof(SCreateTableStmt));
case QUERY_NODE_CREATE_SUBTABLE_STMT:
return makeNode(type, sizeof(SCreateSubTableStmt));
case QUERY_NODE_CREATE_MULTI_TABLE_STMT:
return makeNode(type, sizeof(SCreateMultiTableStmt));
case QUERY_NODE_USE_DATABASE_STMT:
return makeNode(type, sizeof(SUseDatabaseStmt));
case QUERY_NODE_SHOW_DATABASES_STMT:
......@@ -132,7 +136,7 @@ SNodeptr nodesMakeNode(ENodeType type) {
default:
break;
}
printf("================================ nodesMakeNode unknown node = %s\n", nodesNodeName(type));
nodesError("nodesMakeNode unknown node = %s", nodesNodeName(type));
return NULL;
}
......
......@@ -110,15 +110,20 @@ typedef enum ETableOptionType {
TABLE_OPTION_KEEP = 0,
TABLE_OPTION_TTL,
TABLE_OPTION_COMMENT,
TABLE_OPTION_SMA,
TABLE_OPTION_MAX
} ETableOptionType;
STableOptions* createDefaultTableOptions(SAstCreateContext* pCxt);
STableOptions* setTableOption(SAstCreateContext* pCxt, STableOptions* pOptions, ETableOptionType type, const SToken* pVal);
STableOptions* setTableSmaOption(SAstCreateContext* pCxt, STableOptions* pOptions, SNodeList* pSma);
SNode* createColumnDefNode(SAstCreateContext* pCxt, const SToken* pColName, SDataType dataType, const SToken* pComment);
SDataType createDataType(uint8_t type);
SDataType createVarLenDataType(uint8_t type, const SToken* pLen);
SNode* createCreateTableStmt(SAstCreateContext* pCxt, bool ignoreExists, const STokenPair* pFullTableName, SNodeList* pCols, STableOptions* pOptions);
SNode* createCreateTableStmt(SAstCreateContext* pCxt, bool ignoreExists, const STokenPair* pFullTableName, SNodeList* pCols, SNodeList* pTags, STableOptions* pOptions);
SNode* createCreateSubTableStmt(SAstCreateContext* pCxt, bool ignoreExists,
const STokenPair* pFullTableName, const STokenPair* pUseFullTableName, SNodeList* pSpecificTags, SNodeList* pValsOfTags);
SNode* createCreateMultiTableStmt(SAstCreateContext* pCxt, SNodeList* pSubTables);
SNode* createUseDatabaseStmt(SAstCreateContext* pCxt, const SToken* pDbName);
......
此差异已折叠。
......@@ -32,16 +32,6 @@ typedef struct SMsgBuf {
int32_t buildInvalidOperationMsg(SMsgBuf* pMsgBuf, const char* msg);
int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char* sourceStr);
int32_t parserValidateIdToken(SToken* pToken);
typedef struct SKvParam {
SKVRowBuilder *builder;
SSchema *schema;
char buf[TSDB_MAX_TAGS_LEN];
} SKvParam;
int32_t KvRowAppend(const void *value, int32_t len, void *param);
STableMeta* tableMetaDup(const STableMeta* pTableMeta);
SSchema *getTableColumnSchema(const STableMeta *pTableMeta);
SSchema *getTableTagSchema(const STableMeta* pTableMeta);
......@@ -49,6 +39,8 @@ int32_t getNumOfColumns(const STableMeta* pTableMeta);
int32_t getNumOfTags(const STableMeta* pTableMeta);
STableComInfo getTableInfo(const STableMeta* pTableMeta);
int32_t trimString(const char* src, int32_t len, char* dst, int32_t dlen);
#ifdef __cplusplus
}
#endif
......
......@@ -36,7 +36,7 @@ typedef struct SToken {
* @return
*/
#define isNumber(tk) \
((tk)->type == TK_NK_INTEGER || (tk)->type == TK_NK_FLOAT || (tk)->type == TK_HEX || (tk)->type == TK_BIN)
((tk)->type == TK_NK_INTEGER || (tk)->type == TK_NK_FLOAT || (tk)->type == TK_NK_HEX || (tk)->type == TK_NK_BIN)
/**
* tokenizer for sql string
......@@ -67,11 +67,11 @@ bool taosIsKeyWordToken(const char *z, int32_t len);
/**
* check if it is a token or not
* @param pToken
* @return token type, if it is not a number, TK_ILLEGAL will return
* @return token type, if it is not a number, TK_NK_ILLEGAL will return
*/
static FORCE_INLINE int32_t tGetNumericStringType(const SToken* pToken) {
const char* z = pToken->z;
int32_t type = TK_ILLEGAL;
int32_t type = TK_NK_ILLEGAL;
uint32_t i = 0;
for(; i < pToken->n; ++i) {
......@@ -88,7 +88,7 @@ static FORCE_INLINE int32_t tGetNumericStringType(const SToken* pToken) {
* .123e4
*/
if (!isdigit(z[i+1])) {
return TK_ILLEGAL;
return TK_NK_ILLEGAL;
}
for (i += 2; isdigit(z[i]); i++) {
......@@ -109,13 +109,13 @@ static FORCE_INLINE int32_t tGetNumericStringType(const SToken* pToken) {
case '0': {
char next = z[i + 1];
if (next == 'b') { // bin number
type = TK_BIN;
type = TK_NK_BIN;
for (i += 2; (z[i] == '0' || z[i] == '1'); ++i) {
}
goto _end;
} else if (next == 'x') { //hex number
type = TK_HEX;
type = TK_NK_HEX;
for (i += 2; isdigit(z[i]) || (z[i] >= 'a' && z[i] <= 'f') || (z[i] >= 'A' && z[i] <= 'F'); ++i) {
}
......@@ -148,7 +148,7 @@ static FORCE_INLINE int32_t tGetNumericStringType(const SToken* pToken) {
}
if (seg > 1) {
return TK_ILLEGAL;
return TK_NK_ILLEGAL;
}
if ((z[i] == 'e' || z[i] == 'E') &&
......@@ -164,12 +164,12 @@ static FORCE_INLINE int32_t tGetNumericStringType(const SToken* pToken) {
goto _end;
}
default:
return TK_ILLEGAL;
return TK_NK_ILLEGAL;
}
}
_end:
return (i < pToken->n)? TK_ILLEGAL:type;
return (i < pToken->n)? TK_NK_ILLEGAL:type;
}
void taosCleanupKeywordsTable();
......
......@@ -15,6 +15,7 @@
*/
#include "astCreateFuncs.h"
#include "parserUtil.h"
#define CHECK_OUT_OF_MEM(p) \
do { \
......@@ -149,16 +150,16 @@ static SDatabaseOptions* setDbKeep(SAstCreateContext* pCxt, SDatabaseOptions* pO
}
static SDatabaseOptions* setDbPrecision(SAstCreateContext* pCxt, SDatabaseOptions* pOptions, const SToken* pVal) {
if (0 == strncmp(pVal->z, TSDB_TIME_PRECISION_MILLI_STR, pVal->n) && strlen(TSDB_TIME_PRECISION_MILLI_STR) == pVal->n) {
char val[10] = {0};
trimString(pVal->z, pVal->n, val, sizeof(val));
if (0 == strcmp(val, TSDB_TIME_PRECISION_MILLI_STR)) {
pOptions->precision = TSDB_TIME_PRECISION_MILLI;
} else if (0 == strncmp(pVal->z, TSDB_TIME_PRECISION_MICRO_STR, pVal->n) && strlen(TSDB_TIME_PRECISION_MICRO_STR) == pVal->n) {
} else if (0 == strcmp(val, TSDB_TIME_PRECISION_MICRO_STR)) {
pOptions->precision = TSDB_TIME_PRECISION_MICRO;
} else if (0 == strncmp(pVal->z, TSDB_TIME_PRECISION_NANO_STR, pVal->n) && strlen(TSDB_TIME_PRECISION_NANO_STR) == pVal->n) {
} else if (0 == strcmp(val, TSDB_TIME_PRECISION_NANO_STR)) {
pOptions->precision = TSDB_TIME_PRECISION_NANO;
} else {
char tmp[10];
strncpy(tmp, pVal->z, pVal->n);
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "invalid db option precision: %s", tmp);
snprintf(pCxt->pQueryCxt->pMsg, pCxt->pQueryCxt->msgLen, "invalid db option precision: %s", val);
pCxt->valid = false;
}
return pOptions;
......@@ -296,7 +297,7 @@ static STableOptions* setTableComment(SAstCreateContext* pCxt, STableOptions* pO
pCxt->valid = false;
return pOptions;
}
strncpy(pOptions->comments, pVal->z, pVal->n);
trimString(pVal->z, pVal->n, pOptions->comments, sizeof(pOptions->comments));
return pOptions;
}
......@@ -413,6 +414,8 @@ SNode* createValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken*
if (TSDB_DATA_TYPE_TIMESTAMP == dataType) {
val->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
}
val->isDuration = false;
val->translate = false;
return (SNode*)val;
}
......@@ -422,6 +425,7 @@ SNode* createDurationValueNode(SAstCreateContext* pCxt, const SToken* pLiteral)
val->literal = strndup(pLiteral->z, pLiteral->n);
CHECK_OUT_OF_MEM(val->literal);
val->isDuration = true;
val->translate = false;
val->node.resType.type = TSDB_DATA_TYPE_BIGINT;
val->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes;
val->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
......@@ -708,13 +712,18 @@ STableOptions* setTableOption(SAstCreateContext* pCxt, STableOptions* pOptions,
return setTableOptionFuncs[type](pCxt, pOptions, pVal);
}
STableOptions* setTableSmaOption(SAstCreateContext* pCxt, STableOptions* pOptions, SNodeList* pSma) {
pOptions->pSma = pSma;
return pOptions;
}
SNode* createColumnDefNode(SAstCreateContext* pCxt, const SToken* pColName, SDataType dataType, const SToken* pComment) {
SColumnDefNode* pCol = (SColumnDefNode*)nodesMakeNode(QUERY_NODE_COLUMN_DEF);
CHECK_OUT_OF_MEM(pCol);
strncpy(pCol->colName, pColName->z, pColName->n);
pCol->dataType = dataType;
if (NULL != pComment) {
strncpy(pCol->comments, pComment->z, pComment->n);
trimString(pComment->z, pComment->n, pCol->comments, sizeof(pCol->comments));
}
return (SNode*)pCol;
}
......@@ -730,19 +739,51 @@ SDataType createVarLenDataType(uint8_t type, const SToken* pLen) {
}
SNode* createCreateTableStmt(SAstCreateContext* pCxt,
bool ignoreExists, const STokenPair* pFullTableName, SNodeList* pCols, STableOptions* pOptions) {
bool ignoreExists, const STokenPair* pFullTableName, SNodeList* pCols, SNodeList* pTags, STableOptions* pOptions) {
SCreateTableStmt* pStmt = (SCreateTableStmt*)nodesMakeNode(QUERY_NODE_CREATE_TABLE_STMT);
CHECK_OUT_OF_MEM(pStmt);
if (TK_NIL != pFullTableName->first.type) {
strncpy(pStmt->dbName, pFullTableName->first.z, pFullTableName->first.n);
} else {
strcpy(pStmt->dbName, pCxt->pQueryCxt->db);
}
strncpy(pStmt->tableName, pFullTableName->second.z, pFullTableName->second.n);
pStmt->ignoreExists = ignoreExists;
pStmt->pCols = pCols;
pStmt->pTags = pTags;
pStmt->options = *pOptions;
return (SNode*)pStmt;
}
SNode* createCreateSubTableStmt(SAstCreateContext* pCxt, bool ignoreExists,
const STokenPair* pFullTableName, const STokenPair* pUseFullTableName, SNodeList* pSpecificTags, SNodeList* pValsOfTags) {
SCreateSubTableStmt* pStmt = nodesMakeNode(QUERY_NODE_CREATE_SUBTABLE_STMT);
CHECK_OUT_OF_MEM(pStmt);
if (TK_NIL != pFullTableName->first.type) {
strncpy(pStmt->dbName, pFullTableName->first.z, pFullTableName->first.n);
} else {
strcpy(pStmt->dbName, pCxt->pQueryCxt->db);
}
strncpy(pStmt->tableName, pFullTableName->second.z, pFullTableName->second.n);
if (TK_NIL != pUseFullTableName->first.type) {
strncpy(pStmt->useDbName, pUseFullTableName->first.z, pUseFullTableName->first.n);
} else {
strcpy(pStmt->useDbName, pCxt->pQueryCxt->db);
}
strncpy(pStmt->useTableName, pUseFullTableName->second.z, pUseFullTableName->second.n);
pStmt->ignoreExists = ignoreExists;
pStmt->pSpecificTags = pSpecificTags;
pStmt->pValsOfTags = pValsOfTags;
return (SNode*)pStmt;
}
SNode* createCreateMultiTableStmt(SAstCreateContext* pCxt, SNodeList* pSubTables) {
SCreateMultiTableStmt* pStmt = nodesMakeNode(QUERY_NODE_CREATE_MULTI_TABLE_STMT);
CHECK_OUT_OF_MEM(pStmt);
pStmt->pSubTables = pSubTables;
return (SNode*)pStmt;
}
SNode* createUseDatabaseStmt(SAstCreateContext* pCxt, const SToken* pDbName) {
SUseDatabaseStmt* pStmt = (SUseDatabaseStmt*)nodesMakeNode(QUERY_NODE_USE_DATABASE_STMT);
CHECK_OUT_OF_MEM(pStmt);
......
......@@ -26,22 +26,6 @@ extern void NewParse(void*, int, SToken, void*);
extern void NewParseFree(void*, FFree);
extern void NewParseTrace(FILE*, char*);
static void setQuery(SAstCreateContext* pCxt, SQuery* pQuery) {
pQuery->pRoot = pCxt->pRootNode;
ENodeType type = nodeType(pCxt->pRootNode);
if (QUERY_NODE_SELECT_STMT == type) {
pQuery->haveResultSet = true;
pQuery->directRpc = false;
} else if (QUERY_NODE_CREATE_TABLE_STMT == type) {
pQuery->haveResultSet = false;
pQuery->directRpc = false;
} else {
pQuery->haveResultSet = false;
pQuery->directRpc = true;
}
pQuery->msgType = (QUERY_NODE_CREATE_TABLE_STMT == type ? TDMT_VND_CREATE_TABLE : TDMT_VND_QUERY);
}
int32_t doParse(SParseContext* pParseCxt, SQuery** pQuery) {
SAstCreateContext cxt;
initAstCreateContext(pParseCxt, &cxt);
......@@ -58,23 +42,23 @@ int32_t doParse(SParseContext* pParseCxt, SQuery** pQuery) {
i += t0.n;
switch (t0.type) {
case TK_SPACE:
case TK_COMMENT: {
case TK_NK_SPACE:
case TK_NK_COMMENT: {
break;
}
case TK_SEMI: {
NewParse(pParser, 0, t0, &cxt);
goto abort_parse;
}
case TK_QUESTION:
case TK_ILLEGAL: {
case TK_NK_QUESTION:
case TK_NK_ILLEGAL: {
snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unrecognized token: \"%s\"", t0.z);
cxt.valid = false;
goto abort_parse;
}
case TK_HEX:
case TK_OCT:
case TK_BIN: {
case TK_NK_HEX:
case TK_NK_OCT:
case TK_NK_BIN: {
snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unsupported token: \"%s\"", t0.z);
cxt.valid = false;
goto abort_parse;
......@@ -95,7 +79,7 @@ abort_parse:
if (NULL == *pQuery) {
return TSDB_CODE_OUT_OF_MEMORY;
}
setQuery(&cxt, *pQuery);
(*pQuery)->pRoot = cxt.pRootNode;
}
return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED;
}
......@@ -280,29 +280,13 @@ static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode* pCol) {
return found ? DEAL_RES_CONTINUE : translateColumnWithoutPrefix(pCxt, pCol);
}
static int32_t trimStringCopy(const char* src, int32_t len, bool format, char* dst) {
static int32_t trimStringWithVarFormat(const char* src, int32_t len, bool format, char* dst) {
char* dstVal = dst;
if (format) {
varDataSetLen(dst, len);
dstVal = varDataVal(dst);
}
// delete escape character: \\, \', \"
char delim = src[0];
int32_t cnt = 0;
int32_t j = 0;
for (uint32_t k = 1; k < len - 1; ++k) {
if (src[k] == '\\' || (src[k] == delim && src[k + 1] == delim)) {
dstVal[j] = src[k + 1];
cnt++;
j++;
k++;
continue;
}
dstVal[j] = src[k];
j++;
}
dstVal[j] = '\0';
return j;
return trimString(src, len, dstVal, len);
}
static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
......@@ -351,7 +335,7 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
return DEAL_RES_ERROR;
}
trimStringCopy(pVal->literal, n, true, pVal->datum.p);
trimStringWithVarFormat(pVal->literal, n, true, pVal->datum.p);
break;
}
case TSDB_DATA_TYPE_TIMESTAMP: {
......@@ -361,7 +345,7 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY);
return DEAL_RES_ERROR;
}
int32_t len = trimStringCopy(pVal->literal, n, false, tmp);
int32_t len = trimStringWithVarFormat(pVal->literal, n, false, tmp);
if (taosParseTime(tmp, &pVal->datum.i, len, pVal->node.resType.precision, tsDaylight) != TSDB_CODE_SUCCESS) {
tfree(tmp);
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
......@@ -378,6 +362,7 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
break;
}
}
pVal->translate = true;
return DEAL_RES_CONTINUE;
}
......@@ -856,6 +841,47 @@ static int32_t translateCreateDatabase(STranslateContext* pCxt, SCreateDatabaseS
return TSDB_CODE_SUCCESS;
}
static int32_t columnNodeToField(SNodeList* pList, SArray** pArray) {
*pArray = taosArrayInit(LIST_LENGTH(pList), sizeof(SField));
SNode* pNode;
FOREACH(pNode, pList) {
SColumnDefNode* pCol = (SColumnDefNode*)pNode;
SField field = { .type = pCol->dataType.type, .bytes = pCol->dataType.bytes };
strcpy(field.name, pCol->colName);
taosArrayPush(*pArray, &field);
}
return TSDB_CODE_SUCCESS;
}
static int32_t translateCreateSTable(STranslateContext* pCxt, SCreateTableStmt* pStmt) {
SMCreateStbReq createReq = {0};
createReq.igExists = pStmt->ignoreExists;
columnNodeToField(pStmt->pCols, &createReq.pColumns);
columnNodeToField(pStmt->pTags, &createReq.pTags);
createReq.numOfColumns = LIST_LENGTH(pStmt->pCols);
createReq.numOfTags = LIST_LENGTH(pStmt->pTags);
SName tableName = { .type = TSDB_TABLE_NAME_T, .acctId = pCxt->pParseCxt->acctId };
strcpy(tableName.dbname, pStmt->dbName);
strcpy(tableName.tname, pStmt->tableName);
tNameExtractFullName(&tableName, createReq.name);
pCxt->pCmdMsg = malloc(sizeof(SCmdMsgInfo));
if (NULL== pCxt->pCmdMsg) {
return TSDB_CODE_OUT_OF_MEMORY;
}
pCxt->pCmdMsg->epSet = pCxt->pParseCxt->mgmtEpSet;
pCxt->pCmdMsg->msgType = TDMT_MND_CREATE_STB;
pCxt->pCmdMsg->msgLen = tSerializeSMCreateStbReq(NULL, 0, &createReq);
pCxt->pCmdMsg->pMsg = malloc(pCxt->pCmdMsg->msgLen);
if (NULL== pCxt->pCmdMsg->pMsg) {
return TSDB_CODE_OUT_OF_MEMORY;
}
tSerializeSMCreateStbReq(pCxt->pCmdMsg->pMsg, pCxt->pCmdMsg->msgLen, &createReq);
return TSDB_CODE_SUCCESS;
}
static int32_t translateUseDatabase(STranslateContext* pCxt, SUseDatabaseStmt* pStmt) {
SName name = {0};
tNameSetDbName(&name, pCxt->pParseCxt->acctId, pStmt->dbName, strlen(pStmt->dbName));
......@@ -935,6 +961,9 @@ static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) {
case QUERY_NODE_CREATE_DATABASE_STMT:
code = translateCreateDatabase(pCxt, (SCreateDatabaseStmt*)pNode);
break;
case QUERY_NODE_CREATE_TABLE_STMT:
code = translateCreateSTable(pCxt, (SCreateTableStmt*)pNode);
break;
case QUERY_NODE_USE_DATABASE_STMT:
code = translateUseDatabase(pCxt, (SUseDatabaseStmt*)pNode);
break;
......@@ -1020,7 +1049,7 @@ static int32_t doBuildSingleTableBatchReq(SName* pTableName, SNodeList* pColumns
pBatch->info = *pVgroupInfo;
pBatch->req.pArray = taosArrayInit(1, sizeof(struct SVCreateTbReq));
if (pBatch->req.pArray == NULL) {
return TSDB_CODE_QRY_OUT_OF_MEMORY;
return TSDB_CODE_OUT_OF_MEMORY;
}
taosArrayPush(pBatch->req.pArray, &req);
......@@ -1031,7 +1060,7 @@ static int32_t serializeVgroupTablesBatchImpl(SVgroupTablesBatch* pTbBatch, SArr
int tlen = sizeof(SMsgHead) + tSerializeSVCreateTbBatchReq(NULL, &(pTbBatch->req));
void* buf = malloc(tlen);
if (buf == NULL) {
// TODO: handle error
return TSDB_CODE_OUT_OF_MEMORY;
}
((SMsgHead*)buf)->vgId = htonl(pTbBatch->info.vgId);
......@@ -1068,15 +1097,11 @@ static void destroyCreateTbReqBatch(SVgroupTablesBatch* pTbBatch) {
}
static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) {
if (QUERY_NODE_CREATE_TABLE_STMT == nodeType(pQuery->pRoot)) {
if (QUERY_NODE_CREATE_TABLE_STMT == nodeType(pQuery->pRoot) && NULL == ((SCreateTableStmt*)pQuery->pRoot)->pTags) {
SCreateTableStmt* pStmt = (SCreateTableStmt*)pQuery->pRoot;
SName tableName = { .type = TSDB_TABLE_NAME_T, .acctId = pCxt->pParseCxt->acctId };
if ('\0' == pStmt->dbName[0]) {
strcpy(tableName.dbname, pCxt->pParseCxt->db);
} else {
strcpy(tableName.dbname, pStmt->dbName);
}
strcpy(tableName.dbname, pStmt->dbName);
strcpy(tableName.tname, pStmt->tableName);
SVgroupInfo info = {0};
catalogGetTableHashVgroup(pCxt->pParseCxt->pCatalog, pCxt->pParseCxt->pTransporter, &pCxt->pParseCxt->mgmtEpSet, &tableName, &info);
......@@ -1089,13 +1114,16 @@ static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) {
SArray* pBufArray = taosArrayInit(1, POINTER_BYTES);
if (pBufArray == NULL) {
return TSDB_CODE_QRY_OUT_OF_MEMORY;
return TSDB_CODE_OUT_OF_MEMORY;
}
serializeVgroupTablesBatchImpl(&tbatch, pBufArray);
destroyCreateTbReqBatch(&tbatch);
SVnodeModifOpStmt* pNewStmt = nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT);
if (pNewStmt == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
}
pNewStmt->sqlNodeType = nodeType(pQuery->pRoot);
pNewStmt->pDataBlocks = pBufArray;
pQuery->sqlNodeType = nodeType(pQuery->pRoot);
......@@ -1105,6 +1133,31 @@ static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) {
return TSDB_CODE_SUCCESS;
}
static int32_t setQuery(STranslateContext* pCxt, SQuery* pQuery) {
int32_t code = TSDB_CODE_SUCCESS;
switch (nodeType(pQuery->pRoot)) {
case QUERY_NODE_SELECT_STMT:
pQuery->haveResultSet = true;
pQuery->directRpc = false;
pQuery->msgType = TDMT_VND_QUERY;
code = setReslutSchema(pCxt, pQuery);
break;
case QUERY_NODE_VNODE_MODIF_STMT:
pQuery->haveResultSet = false;
pQuery->directRpc = false;
pQuery->msgType = TDMT_VND_CREATE_TABLE;
break;
default:
pQuery->haveResultSet = false;
pQuery->directRpc = true;
pQuery->pCmdMsg = pCxt->pCmdMsg;
pCxt->pCmdMsg = NULL;
pQuery->msgType = pQuery->pCmdMsg->msgType;
break;
}
return code;
}
int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery) {
STranslateContext cxt = {
.pParseCxt = pParseCxt,
......@@ -1122,13 +1175,7 @@ int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery) {
code = translateQuery(&cxt, pQuery->pRoot);
}
if (TSDB_CODE_SUCCESS == code) {
if (pQuery->directRpc) {
pQuery->pCmdMsg = cxt.pCmdMsg;
cxt.pCmdMsg = NULL;
}
if (pQuery->haveResultSet) {
code = setReslutSchema(&cxt, pQuery);
}
code = setQuery(&cxt, pQuery);
}
destroyTranslateContext(&cxt);
return code;
......
......@@ -80,6 +80,68 @@ static int32_t skipInsertInto(SInsertParseContext* pCxt) {
return TSDB_CODE_SUCCESS;
}
static int32_t parserValidateIdToken(SToken* pToken) {
if (pToken == NULL || pToken->z == NULL || pToken->type != TK_NK_ID) {
return TSDB_CODE_TSC_INVALID_OPERATION;
}
// 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;
}
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_NK_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;
}
if (pToken->type != TK_NK_ID) {
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);
if (len != pToken->n || pToken->type != TK_NK_ID) {
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;
}
static int32_t buildName(SInsertParseContext* pCxt, SToken* pStname, char* fullDbName, char* tableName) {
if (parserValidateIdToken(pStname) != TSDB_CODE_SUCCESS) {
return buildSyntaxErrMsg(&pCxt->msg, "invalid table name", pStname->z);
......@@ -320,7 +382,7 @@ static int parseTime(char **end, SToken *pToken, int16_t timePrec, int64_t *time
static FORCE_INLINE int32_t checkAndTrimValue(SToken* pToken, uint32_t type, char* tmpTokenBuf, SMsgBuf* pMsgBuf) {
if ((pToken->type != TK_NOW && pToken->type != TK_NK_INTEGER && pToken->type != TK_NK_STRING && pToken->type != TK_NK_FLOAT && pToken->type != TK_NK_BOOL &&
pToken->type != TK_NULL && pToken->type != TK_HEX && pToken->type != TK_OCT && pToken->type != TK_BIN) ||
pToken->type != TK_NULL && pToken->type != TK_NK_HEX && pToken->type != TK_NK_OCT && pToken->type != TK_NK_BIN) ||
(pToken->n == 0) || (pToken->type == TK_NK_RP)) {
return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z);
}
......@@ -370,7 +432,7 @@ static FORCE_INLINE int32_t toDouble(SToken *pToken, double *value, char **endPt
// not a valid integer number, return error
if ((*endPtr - pToken->z) != pToken->n) {
return TK_ILLEGAL;
return TK_NK_ILLEGAL;
}
return pToken->type;
......@@ -496,7 +558,7 @@ static int32_t parseValueToken(char** end, SToken* pToken, SSchema* pSchema, int
case TSDB_DATA_TYPE_FLOAT: {
double dv;
if (TK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
}
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
......@@ -508,7 +570,7 @@ static int32_t parseValueToken(char** end, SToken* pToken, SSchema* pSchema, int
case TSDB_DATA_TYPE_DOUBLE: {
double dv;
if (TK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z);
}
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) {
......@@ -646,6 +708,37 @@ static int32_t parseBoundColumns(SInsertParseContext* pCxt, SParsedDataColInfo*
return TSDB_CODE_SUCCESS;
}
typedef struct SKvParam {
SKVRowBuilder *builder;
SSchema *schema;
char buf[TSDB_MAX_TAGS_LEN];
} SKvParam;
static int32_t KvRowAppend(const void *value, int32_t len, void *param) {
SKvParam* pa = (SKvParam*) param;
int32_t type = pa->schema->type;
int32_t colId = pa->schema->colId;
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;
}
varDataSetLen(pa->buf, output);
tdAddColToKVRow(pa->builder, colId, type, pa->buf);
} else {
tdAddColToKVRow(pa->builder, colId, type, value);
}
return TSDB_CODE_SUCCESS;
}
// pSql -> tag1_value, ...)
static int32_t parseTagsClause(SInsertParseContext* pCxt, SSchema* pTagsSchema, uint8_t precision) {
if (tdInitKVRowBuilder(&pCxt->tagsBuilder) < 0) {
......@@ -893,7 +986,7 @@ static int32_t parseInsertBody(SInsertParseContext* pCxt) {
}
// FILE csv_file_path
if (TK_FILE == sToken.type) {
if (TK_NK_FILE == sToken.type) {
// pSql -> csv_file_path
NEXT_TOKEN(pCxt->pSql, sToken);
if (0 == sToken.n || (TK_NK_STRING != sToken.type && TK_NK_ID != sToken.type)) {
......
此差异已折叠。
......@@ -45,93 +45,6 @@ int32_t buildSyntaxErrMsg(SMsgBuf* pBuf, const char* additionalInfo, const char*
return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
}
int32_t parserValidateIdToken(SToken* pToken) {
if (pToken == NULL || pToken->z == NULL || pToken->type != TK_NK_ID) {
return TSDB_CODE_TSC_INVALID_OPERATION;
}
// 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;
}
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;
}
if (pToken->type != TK_NK_ID) {
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);
if (len != pToken->n || pToken->type != TK_NK_ID) {
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;
}
int32_t KvRowAppend(const void *value, int32_t len, void *param) {
SKvParam* pa = (SKvParam*) param;
int32_t type = pa->schema->type;
int32_t colId = pa->schema->colId;
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;
}
varDataSetLen(pa->buf, output);
tdAddColToKVRow(pa->builder, colId, type, pa->buf);
} else {
tdAddColToKVRow(pa->builder, colId, type, value);
}
return TSDB_CODE_SUCCESS;
}
static uint32_t getTableMetaSize(const STableMeta* pTableMeta) {
assert(pTableMeta != NULL);
......@@ -184,3 +97,26 @@ STableComInfo getTableInfo(const STableMeta* pTableMeta) {
assert(pTableMeta != NULL);
return pTableMeta->tableInfo;
}
int32_t trimString(const char* src, int32_t len, char* dst, int32_t dlen) {
// delete escape character: \\, \', \"
char delim = src[0];
int32_t cnt = 0;
int32_t j = 0;
for (uint32_t k = 1; k < len - 1; ++k) {
if (j >= dlen) {
break;
}
if (src[k] == '\\' || (src[k] == delim && src[k + 1] == delim)) {
dst[j] = src[k + 1];
cnt++;
j++;
k++;
continue;
}
dst[j] = src[k];
j++;
}
dst[j] = '\0';
return j;
}
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册