提交 216c5317 编写于 作者: D dapan1121

Merge remote-tracking branch 'origin/3.0_query_integrate' into feature/scheduler

......@@ -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 SCreateSubTableClause {
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;
} SCreateSubTableClause;
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_CLAUSE,
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;
......
......@@ -46,7 +46,6 @@ typedef struct SCmdMsgInfo {
typedef struct SQuery {
bool directRpc;
bool haveResultSet;
ENodeType sqlNodeType;
SNode* pRoot;
int32_t numOfResCols;
SSchema* pResSchema;
......
......@@ -469,6 +469,8 @@ int32_t* taosGetErrno();
#define TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION TAOS_DEF_ERROR_CODE(0, 0x260A)
#define TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION TAOS_DEF_ERROR_CODE(0, 0x260B)
#define TSDB_CODE_PAR_NOT_SINGLE_GROUP TAOS_DEF_ERROR_CODE(0, 0x260C)
#define TSDB_CODE_PAR_TAGS_NOT_MATCHED TAOS_DEF_ERROR_CODE(0, 0x260D)
#define TSDB_CODE_PAR_INVALID_TAG_NAME TAOS_DEF_ERROR_CODE(0, 0x260E)
#ifdef __cplusplus
}
......
......@@ -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_CLAUSE:
return makeNode(type, sizeof(SCreateSubTableClause));
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* createCreateSubTableClause(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* createCreateSubTableClause(SAstCreateContext* pCxt, bool ignoreExists,
const STokenPair* pFullTableName, const STokenPair* pUseFullTableName, SNodeList* pSpecificTags, SNodeList* pValsOfTags) {
SCreateSubTableClause* pStmt = nodesMakeNode(QUERY_NODE_CREATE_SUBTABLE_CLAUSE);
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;
}
......@@ -68,6 +68,10 @@ static char* getSyntaxErrFormat(int32_t errCode) {
return "Not SELECTed expression";
case TSDB_CODE_PAR_NOT_SINGLE_GROUP:
return "Not a single-group group function";
case TSDB_CODE_PAR_TAGS_NOT_MATCHED:
return "tags number not matched";
case TSDB_CODE_PAR_INVALID_TAG_NAME:
return "invalid tag name : %s";
case TSDB_CODE_OUT_OF_MEMORY:
return "Out of memory";
default:
......@@ -280,29 +284,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 +339,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 +349,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 +366,7 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
break;
}
}
pVal->translate = true;
return DEAL_RES_CONTINUE;
}
......@@ -687,7 +676,7 @@ static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pPro
SNode* pExpr = ((SOrderByExprNode*)pNode)->pExpr;
if (QUERY_NODE_VALUE == nodeType(pExpr)) {
SValueNode* pVal = (SValueNode*)pExpr;
if (!translateValue(pCxt, pVal)) {
if (DEAL_RES_ERROR == translateValue(pCxt, pVal)) {
return pCxt->errCode;
}
int32_t pos = getPositionValue(pVal);
......@@ -856,6 +845,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 translateCreateSuperTable(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));
......@@ -937,6 +967,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 = translateCreateSuperTable(pCxt, (SCreateTableStmt*)pNode);
break;
case QUERY_NODE_USE_DATABASE_STMT:
code = translateUseDatabase(pCxt, (SUseDatabaseStmt*)pNode);
break;
......@@ -1003,15 +1036,16 @@ static void toSchema(const SColumnDefNode* pCol, int32_t colId, SSchema* pSchema
strcpy(pSchema->name, pCol->colName);
}
static int32_t doBuildSingleTableBatchReq(SName* pTableName, SNodeList* pColumns, SVgroupInfo* pVgroupInfo, SVgroupTablesBatch* pBatch) {
static int32_t buildNormalTableBatchReq(
const char* pTableName, const SNodeList* pColumns, const SVgroupInfo* pVgroupInfo, SVgroupTablesBatch* pBatch) {
SVCreateTbReq req = {0};
req.type = TD_NORMAL_TABLE;
req.name = strdup(tNameGetTableName(pTableName));
req.name = strdup(pTableName);
req.ntbCfg.nCols = LIST_LENGTH(pColumns);
int32_t num = req.ntbCfg.nCols;
req.ntbCfg.pSchema = calloc(num, sizeof(SSchema));
req.ntbCfg.pSchema = calloc(req.ntbCfg.nCols, sizeof(SSchema));
if (NULL == req.name || NULL == req.ntbCfg.pSchema) {
return TSDB_CODE_OUT_OF_MEMORY;
}
SNode* pCol;
int32_t index = 0;
FOREACH(pCol, pColumns) {
......@@ -1021,34 +1055,36 @@ 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;
if (NULL == pBatch->req.pArray) {
return TSDB_CODE_OUT_OF_MEMORY;
}
taosArrayPush(pBatch->req.pArray, &req);
return TSDB_CODE_SUCCESS;
}
static int32_t serializeVgroupTablesBatchImpl(SVgroupTablesBatch* pTbBatch, SArray* pBufArray) {
static int32_t serializeVgroupTablesBatch(SVgroupTablesBatch* pTbBatch, SArray* pBufArray) {
int tlen = sizeof(SMsgHead) + tSerializeSVCreateTbBatchReq(NULL, &(pTbBatch->req));
void* buf = malloc(tlen);
if (buf == NULL) {
// TODO: handle error
if (NULL == buf) {
return TSDB_CODE_OUT_OF_MEMORY;
}
((SMsgHead*)buf)->vgId = htonl(pTbBatch->info.vgId);
((SMsgHead*)buf)->contLen = htonl(tlen);
void* pBuf = POINTER_SHIFT(buf, sizeof(SMsgHead));
tSerializeSVCreateTbBatchReq(&pBuf, &(pTbBatch->req));
SVgDataBlocks* pVgData = calloc(1, sizeof(SVgDataBlocks));
if (NULL == pVgData) {
return TSDB_CODE_OUT_OF_MEMORY;
}
pVgData->vg = pTbBatch->info;
pVgData->pData = buf;
pVgData->size = tlen;
pVgData->numOfTables = (int32_t) taosArrayGetSize(pTbBatch->req.pArray);
taosArrayPush(pBufArray, &pVgData);
return TSDB_CODE_SUCCESS;
}
static void destroyCreateTbReqBatch(SVgroupTablesBatch* pTbBatch) {
......@@ -1069,42 +1105,311 @@ static void destroyCreateTbReqBatch(SVgroupTablesBatch* pTbBatch) {
taosArrayDestroy(pTbBatch->req.pArray);
}
static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) {
if (QUERY_NODE_CREATE_TABLE_STMT == nodeType(pQuery->pRoot)) {
SCreateTableStmt* pStmt = (SCreateTableStmt*)pQuery->pRoot;
static int32_t getTableHashVgroup(SParseContext* pCxt, const char* pDbName, const char* pTableName, SVgroupInfo* pInfo) {
SName name = { .type = TSDB_TABLE_NAME_T, .acctId = pCxt->acctId };
strcpy(name.dbname, pDbName);
strcpy(name.tname, pTableName);
return catalogGetTableHashVgroup(pCxt->pCatalog, pCxt->pTransporter, &pCxt->mgmtEpSet, &name, pInfo);
}
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);
static int32_t rewriteToVnodeModifOpStmt(SQuery* pQuery, SArray* pBufArray) {
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;
nodesDestroyNode(pQuery->pRoot);
pQuery->pRoot = (SNode*)pNewStmt;
return TSDB_CODE_SUCCESS;
}
static int32_t buildCreateTableDataBlock(const SCreateTableStmt* pStmt, const SVgroupInfo* pInfo, SArray** pBufArray) {
SVgroupTablesBatch tbatch = {0};
int32_t code = buildNormalTableBatchReq(pStmt->tableName, pStmt->pCols, pInfo, &tbatch);
if (TSDB_CODE_SUCCESS == code) {
*pBufArray = taosArrayInit(1, POINTER_BYTES);
if (NULL == pBufArray) {
code = TSDB_CODE_OUT_OF_MEMORY;
}
}
if (TSDB_CODE_SUCCESS == code) {
code = serializeVgroupTablesBatch(&tbatch, *pBufArray);
}
destroyCreateTbReqBatch(&tbatch);
return code;
}
static int32_t rewriteCreateTable(STranslateContext* pCxt, SQuery* pQuery) {
SCreateTableStmt* pStmt = (SCreateTableStmt*)pQuery->pRoot;
SVgroupInfo info = {0};
int32_t code = getTableHashVgroup(pCxt->pParseCxt, pStmt->dbName, pStmt->tableName, &info);
SArray* pBufArray;
if (TSDB_CODE_SUCCESS == code) {
code = buildCreateTableDataBlock(pStmt, &info, &pBufArray);
}
if (TSDB_CODE_SUCCESS == code) {
code = rewriteToVnodeModifOpStmt(pQuery, pBufArray);
}
return code;
}
static void addCreateTbReqIntoVgroup(SHashObj* pVgroupHashmap, const char* pTableName, SKVRow row, uint64_t suid, SVgroupInfo* pVgInfo) {
struct SVCreateTbReq req = {0};
req.type = TD_CHILD_TABLE;
req.name = strdup(pTableName);
req.ctbCfg.suid = suid;
req.ctbCfg.pTag = row;
SVgroupTablesBatch* pTableBatch = taosHashGet(pVgroupHashmap, &pVgInfo->vgId, sizeof(pVgInfo->vgId));
if (pTableBatch == NULL) {
SVgroupTablesBatch tBatch = {0};
tBatch.info = *pVgInfo;
tBatch.req.pArray = taosArrayInit(4, sizeof(struct SVCreateTbReq));
taosArrayPush(tBatch.req.pArray, &req);
taosHashPut(pVgroupHashmap, &pVgInfo->vgId, sizeof(pVgInfo->vgId), &tBatch, sizeof(tBatch));
} else { // add to the correct vgroup
taosArrayPush(pTableBatch->req.pArray, &req);
}
}
static void valueNodeToVariant(const SValueNode* pNode, SVariant* pVal) {
pVal->nType = pNode->node.resType.type;
pVal->nLen = pNode->node.resType.bytes;
switch (pNode->node.resType.type) {
case TSDB_DATA_TYPE_NULL:
break;
case TSDB_DATA_TYPE_BOOL:
pVal->i = 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:
pVal->i = pNode->datum.i;
break;
case TSDB_DATA_TYPE_UTINYINT:
case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_UINT:
case TSDB_DATA_TYPE_UBIGINT:
pVal->u = pNode->datum.u;
break;
case TSDB_DATA_TYPE_FLOAT:
case TSDB_DATA_TYPE_DOUBLE:
pVal->d = pNode->datum.d;
break;
case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR:
case TSDB_DATA_TYPE_VARCHAR:
case TSDB_DATA_TYPE_VARBINARY:
pVal->pz = pNode->datum.p;
break;
case TSDB_DATA_TYPE_JSON:
case TSDB_DATA_TYPE_DECIMAL:
case TSDB_DATA_TYPE_BLOB:
// todo
default:
break;
}
}
static int32_t addValToKVRow(STranslateContext* pCxt, SValueNode* pVal, const SSchema* pSchema, SKVRowBuilder* pBuilder) {
if (DEAL_RES_ERROR == translateValue(pCxt, pVal)) {
return pCxt->errCode;
}
SVariant var;
valueNodeToVariant(pVal, &var);
char tagVal[TSDB_MAX_TAGS_LEN] = {0};
int32_t code = taosVariantDump(&var, tagVal, pSchema->type, true);
if (TSDB_CODE_SUCCESS == code) {
tdAddColToKVRow(pBuilder, pSchema->colId, pSchema->type, tagVal);
}
return code;
}
static int32_t buildKVRowForBindTags(STranslateContext* pCxt, SCreateSubTableClause* pStmt, STableMeta* pSuperTableMeta, SKVRowBuilder* pBuilder) {
int32_t numOfTags = getNumOfTags(pSuperTableMeta);
if (LIST_LENGTH(pStmt->pValsOfTags) != LIST_LENGTH(pStmt->pSpecificTags) || numOfTags < LIST_LENGTH(pStmt->pValsOfTags)) {
return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_TAGS_NOT_MATCHED);
}
SSchema* pTagSchema = getTableTagSchema(pSuperTableMeta);
SNode* pTag, *pVal;
FORBOTH(pTag, pStmt->pSpecificTags, pVal, pStmt->pValsOfTags) {
SColumnNode* pCol = (SColumnNode*)pTag;
SSchema* pSchema = NULL;
for (int32_t i = 0; i < numOfTags; ++i) {
if (0 == strcmp(pCol->colName, pTagSchema[i].name)) {
pSchema = pTagSchema + i;
break;
}
}
if (NULL == pSchema) {
return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_INVALID_TAG_NAME, pCol->colName);
}
int32_t code = addValToKVRow(pCxt, (SValueNode*)pVal, pSchema, pBuilder);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
strcpy(tableName.tname, pStmt->tableName);
SVgroupInfo info = {0};
catalogGetTableHashVgroup(pCxt->pParseCxt->pCatalog, pCxt->pParseCxt->pTransporter, &pCxt->pParseCxt->mgmtEpSet, &tableName, &info);
}
return TSDB_CODE_SUCCESS;
}
static int32_t buildKVRowForAllTags(STranslateContext* pCxt, SCreateSubTableClause* pStmt, STableMeta* pSuperTableMeta, SKVRowBuilder* pBuilder) {
if (getNumOfTags(pSuperTableMeta) != LIST_LENGTH(pStmt->pValsOfTags)) {
return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_TAGS_NOT_MATCHED);
}
SVgroupTablesBatch tbatch = {0};
int32_t code = doBuildSingleTableBatchReq(&tableName, pStmt->pCols, &info, &tbatch);
if (code != TSDB_CODE_SUCCESS) {
SSchema* pTagSchema = getTableTagSchema(pSuperTableMeta);
SNode* pVal;
int32_t index = 0;
FOREACH(pVal, pStmt->pValsOfTags) {
int32_t code = addValToKVRow(pCxt, (SValueNode*)pVal, pTagSchema + index++, pBuilder);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
}
return TSDB_CODE_SUCCESS;
}
SArray* pBufArray = taosArrayInit(1, POINTER_BYTES);
if (pBufArray == NULL) {
return TSDB_CODE_QRY_OUT_OF_MEMORY;
static int32_t rewriteCreateSubTable(STranslateContext* pCxt, SCreateSubTableClause* pStmt, SHashObj* pVgroupHashmap) {
SName name = { .type = TSDB_TABLE_NAME_T, .acctId = pCxt->pParseCxt->acctId };
strcpy(name.dbname, pStmt->useDbName);
strcpy(name.tname, pStmt->useTableName);
STableMeta* pSuperTableMeta = NULL;
int32_t code = catalogGetTableMeta(pCxt->pParseCxt->pCatalog, pCxt->pParseCxt->pTransporter, &pCxt->pParseCxt->mgmtEpSet, &name, &pSuperTableMeta);
SKVRowBuilder kvRowBuilder = {0};
if (TSDB_CODE_SUCCESS == code) {
code = tdInitKVRowBuilder(&kvRowBuilder);
}
if (TSDB_CODE_SUCCESS == code) {
if (NULL != pStmt->pSpecificTags) {
code = buildKVRowForBindTags(pCxt, pStmt, pSuperTableMeta, &kvRowBuilder);
} else {
code = buildKVRowForAllTags(pCxt, pStmt, pSuperTableMeta, &kvRowBuilder);
}
}
serializeVgroupTablesBatchImpl(&tbatch, pBufArray);
destroyCreateTbReqBatch(&tbatch);
SKVRow row = NULL;
if (TSDB_CODE_SUCCESS == code) {
row = tdGetKVRowFromBuilder(&kvRowBuilder);
if (NULL == row) {
code = TSDB_CODE_OUT_OF_MEMORY;
} else {
tdSortKVRowByColIdx(row);
}
}
SVnodeModifOpStmt* pNewStmt = nodesMakeNode(QUERY_NODE_VNODE_MODIF_STMT);
pNewStmt->sqlNodeType = nodeType(pQuery->pRoot);
pNewStmt->pDataBlocks = pBufArray;
pQuery->sqlNodeType = nodeType(pQuery->pRoot);
nodesDestroyNode(pQuery->pRoot);
pQuery->pRoot = (SNode*)pNewStmt;
SVgroupInfo info = {0};
if (TSDB_CODE_SUCCESS == code) {
code = getTableHashVgroup(pCxt->pParseCxt, pStmt->dbName, pStmt->tableName, &info);
}
return TSDB_CODE_SUCCESS;
if (TSDB_CODE_SUCCESS == code) {
addCreateTbReqIntoVgroup(pVgroupHashmap, pStmt->tableName, row, pSuperTableMeta->uid, &info);
}
tfree(pSuperTableMeta);
tdDestroyKVRowBuilder(&kvRowBuilder);
return code;
}
static SArray* serializeVgroupsTablesBatch(SHashObj* pVgroupHashmap) {
SArray* pBufArray = taosArrayInit(taosHashGetSize(pVgroupHashmap), sizeof(void*));
if (NULL == pBufArray) {
return NULL;
}
int32_t code = TSDB_CODE_SUCCESS;
SVgroupTablesBatch* pTbBatch = NULL;
do {
pTbBatch = taosHashIterate(pVgroupHashmap, pTbBatch);
if (pTbBatch == NULL) {
break;
}
serializeVgroupTablesBatch(pTbBatch, pBufArray);
destroyCreateTbReqBatch(pTbBatch);
} while (true);
return pBufArray;
}
static int32_t rewriteCreateMultiTable(STranslateContext* pCxt, SQuery* pQuery) {
SCreateMultiTableStmt* pStmt = (SCreateMultiTableStmt*)pQuery->pRoot;
SHashObj* pVgroupHashmap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK);
if (NULL == pVgroupHashmap) {
return TSDB_CODE_OUT_OF_MEMORY;
}
int32_t code = TSDB_CODE_SUCCESS;
SNode* pNode;
FOREACH(pNode, pStmt->pSubTables) {
code = rewriteCreateSubTable(pCxt, (SCreateSubTableClause*)pNode, pVgroupHashmap);
if (TSDB_CODE_SUCCESS != code) {
taosHashCleanup(pVgroupHashmap);
return code;
}
}
SArray* pBufArray = serializeVgroupsTablesBatch(pVgroupHashmap);
if (NULL == pBufArray) {
return TSDB_CODE_OUT_OF_MEMORY;
}
taosHashCleanup(pVgroupHashmap);
return rewriteToVnodeModifOpStmt(pQuery, pBufArray);
}
static int32_t rewriteQuery(STranslateContext* pCxt, SQuery* pQuery) {
int32_t code = TSDB_CODE_SUCCESS;
switch (nodeType(pQuery->pRoot)) {
case QUERY_NODE_CREATE_TABLE_STMT:
if (NULL == ((SCreateTableStmt*)pQuery->pRoot)->pTags) {
code = rewriteCreateTable(pCxt, pQuery);
}
break;
case QUERY_NODE_CREATE_MULTI_TABLE_STMT:
code = rewriteCreateMultiTable(pCxt, pQuery);
break;
default:
break;
}
return code;
}
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) {
......@@ -1124,13 +1429,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;
}
......@@ -29,32 +29,103 @@ typedef struct SKeyword {
// keywords in sql string
static SKeyword keywordTable[] = {
{"ALL", TK_ALL},
{"AND", TK_AND},
{"AS", TK_AS},
{"ASC", TK_ASC},
{"BETWEEN", TK_BETWEEN},
{"BINARY", TK_BINARY},
{"BIGINT", TK_BIGINT},
{"BLOCKS", TK_BLOCKS},
{"BOOL", TK_BOOL},
{"BY", TK_BY},
{"CACHE", TK_CACHE},
{"CACHELAST", TK_CACHELAST},
{"COMMENT", TK_COMMENT},
{"COMP", TK_COMP},
{"CREATE", TK_CREATE},
{"DATABASE", TK_DATABASE},
{"DATABASES", TK_DATABASES},
{"DAYS", TK_DAYS},
{"DESC", TK_DESC},
{"DISTINCT", TK_DISTINCT},
{"DOUBLE", TK_DOUBLE},
{"EXISTS", TK_EXISTS},
// {"FILE", TK_FILE},
{"FILL", TK_FILL},
{"FLOAT", TK_FLOAT},
{"FROM", TK_FROM},
{"FSYNC", TK_FSYNC},
{"GROUP", TK_GROUP},
{"HAVING", TK_HAVING},
{"IF", TK_IF},
{"IMPORT", TK_IMPORT},
{"IN", TK_IN},
{"INNER", TK_INNER},
{"INT", TK_INT},
{"INSERT", TK_INSERT},
{"INTEGER", TK_INTEGER},
{"INTERVAL", TK_INTERVAL},
{"INTO", TK_INTO},
{"IS", TK_IS},
{"JOIN", TK_JOIN},
{"JSON", TK_JSON},
{"KEEP", TK_KEEP},
{"LIKE", TK_LIKE},
{"LIMIT", TK_LIMIT},
{"LINEAR", TK_LINEAR},
{"MATCH", TK_MATCH},
{"MAXROWS", TK_MAXROWS},
{"MINROWS", TK_MINROWS},
{"MINUS", TK_MINUS},
{"NCHAR", TK_NCHAR},
{"NMATCH", TK_NMATCH},
{"NONE", TK_NONE},
{"NOT", TK_NOT},
{"NOW", TK_NOW},
{"NULL", TK_NULL},
{"OFFSET", TK_OFFSET},
{"PRECISION", TK_PRECISION},
{"PREV", TK_PREV},
{"ON", TK_ON},
{"OR", TK_OR},
{"ORDER", TK_ORDER},
{"QUORUM", TK_QUORUM},
{"REPLICA", TK_REPLICA},
{"SELECT", TK_SELECT},
{"SESSION", TK_SESSION},
{"SHOW", TK_SHOW},
{"SINGLE_STABLE", TK_SINGLE_STABLE},
{"SLIDING", TK_SLIDING},
{"SLIMIT", TK_SLIMIT},
{"SMA", TK_SMA},
{"SMALLINT", TK_SMALLINT},
{"SOFFSET", TK_SOFFSET},
{"STABLE", TK_STABLE},
{"STATE_WINDOW", TK_STATE_WINDOW},
{"STREAM_MODE", TK_STREAM_MODE},
{"TABLE", TK_TABLE},
{"TABLES", TK_TABLES},
{"TAGS", TK_TAGS},
{"TIMESTAMP", TK_TIMESTAMP},
{"TINYINT", TK_TINYINT},
{"TTL", TK_TTL},
{"UNION", TK_UNION},
{"UNSIGNED", TK_UNSIGNED},
{"USE", TK_USE},
{"USING", TK_USING},
{"VALUES", TK_VALUES},
{"VARCHAR", TK_VARCHAR},
{"VGROUPS", TK_VGROUPS},
{"WAL", TK_WAL},
{"WHERE", TK_WHERE},
// {"ID", TK_ID},
{"BOOL", TK_BOOL},
{"TINYINT", TK_TINYINT},
{"SMALLINT", TK_SMALLINT},
{"INTEGER", TK_INTEGER},
{"INT", TK_INTEGER},
{"BIGINT", TK_BIGINT},
{"FLOAT", TK_FLOAT},
{"DOUBLE", TK_DOUBLE},
// {"STRING", TK_STRING},
{"TIMESTAMP", TK_TIMESTAMP},
{"BINARY", TK_BINARY},
{"NCHAR", TK_NCHAR},
{"OR", TK_OR},
{"AND", TK_AND},
{"NOT", TK_NOT},
// {"EQ", TK_EQ},
// {"NE", TK_NE},
// {"ISNULL", TK_ISNULL},
// {"NOTNULL", TK_NOTNULL},
{"IS", TK_IS},
{"LIKE", TK_LIKE},
{"MATCH", TK_MATCH},
// {"GLOB", TK_GLOB},
{"BETWEEN", TK_BETWEEN},
{"IN", TK_IN},
// {"GT", TK_GT},
// {"GE", TK_GE},
// {"LT", TK_LT},
......@@ -64,7 +135,6 @@ static SKeyword keywordTable[] = {
// {"LSHIFT", TK_LSHIFT},
// {"RSHIFT", TK_RSHIFT},
// {"PLUS", TK_PLUS},
{"MINUS", TK_MINUS},
// {"DIVIDE", TK_DIVIDE},
// {"TIMES", TK_TIMES},
// {"STAR", TK_STAR},
......@@ -74,8 +144,6 @@ static SKeyword keywordTable[] = {
// {"UMINUS", TK_UMINUS},
// {"UPLUS", TK_UPLUS},
// {"BITNOT", TK_BITNOT},
{"SHOW", TK_SHOW},
{"DATABASES", TK_DATABASES},
// {"MNODES", TK_MNODES},
// {"DNODES", TK_DNODES},
// {"ACCOUNTS", TK_ACCOUNTS},
......@@ -88,25 +156,17 @@ static SKeyword keywordTable[] = {
// {"SCORES", TK_SCORES},
// {"GRANTS", TK_GRANTS},
// {"DOT", TK_DOT},
{"TABLES", TK_TABLES},
// {"STABLES", TK_STABLES},
{"VGROUPS", TK_VGROUPS},
// {"DROP", TK_DROP},
{"TABLE", TK_TABLE},
{"DATABASE", TK_DATABASE},
// {"DNODE", TK_DNODE},
// {"USER", TK_USER},
// {"ACCOUNT", TK_ACCOUNT},
{"USE", TK_USE},
// {"DESCRIBE", TK_DESCRIBE},
// {"SYNCDB", TK_SYNCDB},
// {"ALTER", TK_ALTER},
// {"PASS", TK_PASS},
// {"PRIVILEGE", TK_PRIVILEGE},
// {"LOCAL", TK_LOCAL},
{"IF", TK_IF},
{"EXISTS", TK_EXISTS},
{"CREATE", TK_CREATE},
// {"PPS", TK_PPS},
// {"TSERIES", TK_TSERIES},
// {"DBS", TK_DBS},
......@@ -114,51 +174,12 @@ static SKeyword keywordTable[] = {
// {"QTIME", TK_QTIME},
// {"CONNS", TK_CONNS},
// {"STATE", TK_STATE},
{"KEEP", TK_KEEP},
{"REPLICA", TK_REPLICA},
{"QUORUM", TK_QUORUM},
{"DAYS", TK_DAYS},
{"MINROWS", TK_MINROWS},
{"MAXROWS", TK_MAXROWS},
{"BLOCKS", TK_BLOCKS},
{"CACHE", TK_CACHE},
// {"CTIME", TK_CTIME},
{"WAL", TK_WAL},
{"FSYNC", TK_FSYNC},
{"COMP", TK_COMP},
{"PRECISION", TK_PRECISION},
// {"LP", TK_LP},
// {"RP", TK_RP},
// {"UNSIGNED", TK_UNSIGNED},
{"TAGS", TK_TAGS},
{"USING", TK_USING},
{"AS", TK_AS},
// {"COMMA", TK_COMMA},
{"NULL", TK_NULL},
{"SELECT", TK_SELECT},
// {"EVERY", TK_EVERY},
{"FROM", TK_FROM},
// {"VARIABLE", TK_VARIABLE},
{"INTERVAL", TK_INTERVAL},
{"SESSION", TK_SESSION},
{"STATE_WINDOW", TK_STATE_WINDOW},
{"FILL", TK_FILL},
{"SLIDING", TK_SLIDING},
{"ORDER", TK_ORDER},
{"BY", TK_BY},
{"ASC", TK_ASC},
{"DESC", TK_DESC},
{"GROUP", TK_GROUP},
{"HAVING", TK_HAVING},
{"LIMIT", TK_LIMIT},
{"OFFSET", TK_OFFSET},
{"SLIMIT", TK_SLIMIT},
{"SOFFSET", TK_SOFFSET},
{"WHERE", TK_WHERE},
{"NOW", TK_NOW},
{"INSERT", TK_INSERT},
{"INTO", TK_INTO},
{"VALUES", TK_VALUES},
// {"UPDATE", TK_UPDATE},
// {"RESET", TK_RESET},
// {"QUERY", TK_QUERY},
......@@ -192,8 +213,6 @@ static SKeyword keywordTable[] = {
// {"IMMEDIATE", TK_IMMEDIATE},
// {"INITIALLY", TK_INITIALLY},
// {"INSTEAD", TK_INSTEAD},
{"MATCH", TK_MATCH},
{"NMATCH", TK_NMATCH},
// {"KEY", TK_KEY},
// {"OF", TK_OF},
// {"RAISE", TK_RAISE},
......@@ -203,20 +222,9 @@ static SKeyword keywordTable[] = {
// {"STATEMENT", TK_STATEMENT},
// {"TRIGGER", TK_TRIGGER},
// {"VIEW", TK_VIEW},
{"ALL", TK_ALL},
// {"SEMI", TK_SEMI},
{"NONE", TK_NONE},
{"PREV", TK_PREV},
{"LINEAR", TK_LINEAR},
{"IMPORT", TK_IMPORT},
// {"TBNAME", TK_TBNAME},
{"JOIN", TK_JOIN},
// {"STABLE", TK_STABLE},
{"FILE", TK_FILE},
// {"VNODES", TK_VNODES},
{"UNION", TK_UNION},
{"CACHELAST", TK_CACHELAST},
{"DISTINCT", TK_DISTINCT},
// {"PARTITIONS", TK_PARTITIONS},
// {"TOPIC", TK_TOPIC},
// {"TOPICS", TK_TOPICS},
......@@ -228,8 +236,6 @@ static SKeyword keywordTable[] = {
// {"AGGREGATE", TK_AGGREGATE},
// {"BUFSIZE", TK_BUFSIZE},
// {"PORT", TK_PORT},
{"INNER", TK_INNER},
{"ON", TK_ON},
// {"MODE", TK_MODE},
};
......@@ -277,7 +283,7 @@ static int32_t tKeywordCode(const char* z, int n) {
}
if (keywordHashTable == NULL) {
return TK_ILLEGAL;
return TK_NK_ILLEGAL;
}
SKeyword** pKey = (SKeyword**)taosHashGet(keywordHashTable, key, n);
......@@ -298,7 +304,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) {
case '\r': {
for (i = 1; isspace(z[i]); i++) {
}
*tokenId = TK_SPACE;
*tokenId = TK_NK_SPACE;
return i;
}
case ':': {
......@@ -383,7 +389,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) {
}
case '!': {
if (z[1] != '=') {
*tokenId = TK_ILLEGAL;
*tokenId = TK_NK_ILLEGAL;
return 2;
} else {
*tokenId = TK_NK_NE;
......@@ -412,7 +418,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) {
return 1;
}
case '?': {
*tokenId = TK_QUESTION;
*tokenId = TK_NK_QUESTION;
return 1;
}
case '`':
......@@ -475,7 +481,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) {
char next = z[1];
if (next == 'b') { // bin number
*tokenId = TK_BIN;
*tokenId = TK_NK_BIN;
for (i = 2; (z[i] == '0' || z[i] == '1'); ++i) {
}
......@@ -485,7 +491,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) {
return i;
} else if (next == 'x') { //hex number
*tokenId = TK_HEX;
*tokenId = TK_NK_HEX;
for (i = 2; isdigit(z[i]) || (z[i] >= 'a' && z[i] <= 'f') || (z[i] >= 'A' && z[i] <= 'F'); ++i) {
}
......@@ -574,7 +580,7 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) {
}
}
*tokenId = TK_ILLEGAL;
*tokenId = TK_NK_ILLEGAL;
return 0;
}
......@@ -608,7 +614,7 @@ SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr) {
return t0;
}
// IGNORE TK_SPACE, TK_COMMA, and specified tokens
// IGNORE TK_NK_SPACE, TK_NK_COMMA, and specified tokens
while (1) {
*i += t0.n;
......@@ -656,7 +662,7 @@ SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr) {
// only id and string are valid
if ((TK_NK_STRING != t0.type) && (TK_NK_ID != t0.type)) {
t0.type = TK_ILLEGAL;
t0.type = TK_NK_ILLEGAL;
t0.n = 0;
return t0;
......
......@@ -70,7 +70,6 @@ void initMetaDataEnv() {
stub.set(catalogGetTableMeta, __catalogGetTableMeta);
stub.set(catalogGetTableHashVgroup, __catalogGetTableHashVgroup);
stub.set(catalogGetTableDistVgInfo, __catalogGetTableDistVgInfo);
{
AddrAny any("libcatalog.so");
std::map<std::string,void*> result;
......@@ -95,6 +94,14 @@ void initMetaDataEnv() {
stub.set(f.second, __catalogGetTableHashVgroup);
}
}
{
AddrAny any("libcatalog.so");
std::map<std::string,void*> result;
any.get_global_func_addr_dynsym("^catalogGetTableDistVgInfo$", result);
for (const auto& f : result) {
stub.set(f.second, __catalogGetTableDistVgInfo);
}
}
}
void generateMetaData() {
......
......@@ -42,457 +42,41 @@ protected:
bool run(int32_t parseCode = TSDB_CODE_SUCCESS, int32_t translateCode = TSDB_CODE_SUCCESS) {
int32_t code = doParse(&cxt_, &query_);
// cout << "doParse return " << code << endl;
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] code:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
cout << "sql:[" << cxt_.pSql << "] parser code:" << tstrerror(code) << ", msg:" << errMagBuf_ << endl;
return (TSDB_CODE_SUCCESS != parseCode);
}
if (TSDB_CODE_SUCCESS != parseCode) {
return false;
}
string parserStr = toString(query_->pRoot);
code = doTranslate(&cxt_, query_);
// cout << "doTranslate return " << code << endl;
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] code:" << code << ", " << translateCode << ", msg:" << errMagBuf_ << endl;
cout << "sql:[" << cxt_.pSql << "] translate code:" << code << ", " << translateCode << ", msg:" << errMagBuf_ << endl;
return (code == translateCode);
}
if (NULL != query_->pRoot && QUERY_NODE_SELECT_STMT == nodeType(query_->pRoot)) {
cout << "input sql : [" << cxt_.pSql << "]" << endl;
// string sql;
// selectToSql(query_.pRoot, sql);
// cout << "output sql : [" << sql << "]" << endl;
string str;
selectToStr(query_->pRoot, str);
cout << "translate str : \n" << str << endl;
}
cout << "input sql : [" << cxt_.pSql << "]" << endl;
cout << "parser output: " << endl;
cout << parserStr << endl;
cout << "translate output: " << endl;
cout << toString(query_->pRoot) << endl;
return (TSDB_CODE_SUCCESS == translateCode);
}
private:
static const int max_err_len = 1024;
void exprNodeToStr(const SNode* node, string& str, bool isProject) {
switch (nodeType(node)) {
case QUERY_NODE_COLUMN:
case QUERY_NODE_VALUE:
case QUERY_NODE_OPERATOR:
case QUERY_NODE_FUNCTION:
case QUERY_NODE_LOGIC_CONDITION: {
SExprNode* pExpr = (SExprNode*)node;
str.append(" [" + dataTypeToStr(pExpr->resType) + "]");
if (isProject) {
str.append(" AS " + string(pExpr->aliasName));
}
break;
}
default:
break;
}
}
string dataTypeToStr(const SDataType& dt) {
switch (dt.type) {
case TSDB_DATA_TYPE_NULL:
return "NULL";
case TSDB_DATA_TYPE_BOOL:
return "BOOL";
case TSDB_DATA_TYPE_TINYINT:
return "TINYINT";
case TSDB_DATA_TYPE_SMALLINT:
return "SMALLINT";
case TSDB_DATA_TYPE_INT:
return "INT";
case TSDB_DATA_TYPE_BIGINT:
return "BIGINT";
case TSDB_DATA_TYPE_FLOAT:
return "FLOAT";
case TSDB_DATA_TYPE_DOUBLE:
return "DOUBLE";
case TSDB_DATA_TYPE_BINARY:
return "BINART(" + to_string(dt.bytes) + ")";
case TSDB_DATA_TYPE_TIMESTAMP:
return "TIMESTAMP";
case TSDB_DATA_TYPE_NCHAR:
return "NCHAR(" + to_string(dt.bytes) + ")";
case TSDB_DATA_TYPE_UTINYINT:
return "UTINYINT";
case TSDB_DATA_TYPE_USMALLINT:
return "USMALLINT";
case TSDB_DATA_TYPE_UINT:
return "UINT";
case TSDB_DATA_TYPE_UBIGINT:
return "UBIGINT";
case TSDB_DATA_TYPE_VARCHAR:
return "VARCHAR(" + to_string(dt.bytes) + ")";
case TSDB_DATA_TYPE_VARBINARY:
return "VARBINARY(" + to_string(dt.bytes) + ")";
case TSDB_DATA_TYPE_JSON:
return "JSON";
case TSDB_DATA_TYPE_DECIMAL:
return "DECIMAL(" + to_string(dt.precision) + ", " + to_string(dt.scale) + ")";
case TSDB_DATA_TYPE_BLOB:
return "BLOB";
default:
break;
}
return "Unknown Data Type " + to_string(dt.type);
}
void valueNodeToStr(const SValueNode* pVal, string& str) {
switch (pVal->node.resType.type) {
case TSDB_DATA_TYPE_NULL:
str.append("null");
break;
case TSDB_DATA_TYPE_BOOL:
str.append(pVal->datum.b ? "true" : "false");
break;
case TSDB_DATA_TYPE_TINYINT:
case TSDB_DATA_TYPE_SMALLINT:
case TSDB_DATA_TYPE_INT:
case TSDB_DATA_TYPE_BIGINT:
str.append(to_string(pVal->datum.i));
break;
case TSDB_DATA_TYPE_FLOAT:
case TSDB_DATA_TYPE_DOUBLE:
str.append(to_string(pVal->datum.d));
break;
case TSDB_DATA_TYPE_BINARY:
case TSDB_DATA_TYPE_NCHAR:
case TSDB_DATA_TYPE_VARCHAR:
case TSDB_DATA_TYPE_VARBINARY:
str.append(pVal->datum.p);
break;
case TSDB_DATA_TYPE_TIMESTAMP:
str.append(to_string(pVal->datum.u));
break;
case TSDB_DATA_TYPE_UTINYINT:
case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_UINT:
case TSDB_DATA_TYPE_UBIGINT:
str.append(to_string(pVal->datum.u));
break;
case TSDB_DATA_TYPE_JSON:
case TSDB_DATA_TYPE_DECIMAL:
case TSDB_DATA_TYPE_BLOB:
str.append("JSON or DECIMAL or BLOB");
break;
default:
break;
}
}
void columnNodeToStr(const SColumnNode* pCol, string& str) {
if ('\0' != pCol->dbName[0]) {
str.append(pCol->dbName);
str.append(".");
}
if ('\0' != pCol->tableAlias[0]) {
str.append(pCol->tableAlias);
str.append(".");
}
str.append(pCol->colName);
}
void operatorToStr(const SOperatorNode* pOp, string& str) {
nodeToStr(pOp->pLeft, str, false);
str.append(opTypeToStr(pOp->opType));
nodeToStr(pOp->pRight, str, false);
}
void functionToStr(const SFunctionNode* pFunc, string& str) {
str.append(pFunc->functionName);
str.append("(");
nodeListToStr(pFunc->pParameterList, "", str, false, ", ");
str.append(")");
}
void groupingSetToStr(SGroupingSetNode* pGroup, string& str) {
nodeToStr((SNode*)nodesListGetNode(pGroup->pParameterList, 0), str, false);
}
void orderByExprToStr(SOrderByExprNode* pOrderBy, string& str) {
nodeToStr(pOrderBy->pExpr, str, false);
str.append((ORDER_ASC == pOrderBy->order ? " ASC" : " DESC"));
str.append((NULL_ORDER_FIRST == pOrderBy->nullOrder ? " NULLS FIRST" : " NULLS LAST"));
}
string logicConditionTypeToStr(ELogicConditionType type) {
switch (type) {
case LOGIC_COND_TYPE_AND:
return "AND";
case LOGIC_COND_TYPE_OR:
return "OR";
case LOGIC_COND_TYPE_NOT:
return "NOT";
default:
break;
}
return "Unknown logic cond type";
}
void logicCondToStr(SLogicConditionNode* pCond, string& str) {
SNode* node = nullptr;
bool first = true;
FOREACH(node, pCond->pParameterList) {
if (first && LOGIC_COND_TYPE_NOT == pCond->condType) {
str.append(logicConditionTypeToStr(pCond->condType) + " ");
} else if (!first && LOGIC_COND_TYPE_NOT != pCond->condType) {
str.append(" " + logicConditionTypeToStr(pCond->condType) + " ");
}
first = false;
nodeToStr(node, str, false);
}
}
void nodeToStr(const SNode* node, string& str, bool isProject) {
if (nullptr == node) {
return;
}
switch (nodeType(node)) {
case QUERY_NODE_COLUMN: {
columnNodeToStr((SColumnNode*)node, str);
break;
}
case QUERY_NODE_VALUE: {
valueNodeToStr((SValueNode*)node, str);
break;
}
case QUERY_NODE_OPERATOR: {
operatorToStr((SOperatorNode*)node, str);
break;
}
case QUERY_NODE_FUNCTION: {
functionToStr((SFunctionNode*)node, str);
break;
}
case QUERY_NODE_LOGIC_CONDITION: {
logicCondToStr((SLogicConditionNode*)node, str);
break;
}
case QUERY_NODE_GROUPING_SET: {
groupingSetToStr((SGroupingSetNode*)node, str);
break;
}
case QUERY_NODE_ORDER_BY_EXPR: {
orderByExprToStr((SOrderByExprNode*)node, str);
break;
}
default:
break;
}
exprNodeToStr(node, str, isProject);
}
void nodeListToStr(const SNodeList* nodelist, const string& prefix, string& str, bool isProject = false, const string& sep = string("\n")) {
SNode* node = nullptr;
FOREACH(node, nodelist) {
str.append(prefix);
nodeToStr(node, str, isProject);
str.append(sep);
}
}
void tableToStr(const SNode* node, const string& prefix, string& str) {
const STableNode* table = (const STableNode*)node;
switch (nodeType(node)) {
case QUERY_NODE_REAL_TABLE: {
SRealTableNode* realTable = (SRealTableNode*)table;
str.append(prefix);
if ('\0' != realTable->table.dbName[0]) {
str.append(realTable->table.dbName);
str.append(".");
}
str.append(realTable->table.tableName);
str.append(string(" ") + realTable->table.tableAlias);
break;
}
case QUERY_NODE_TEMP_TABLE: {
STempTableNode* tempTable = (STempTableNode*)table;
str.append(prefix + "(\n");
selectToStr(tempTable->pSubquery, str, prefix + "\t");
str.append("\n");
str.append(prefix + ") ");
str.append(tempTable->table.tableAlias);
break;
}
case QUERY_NODE_JOIN_TABLE: {
SJoinTableNode* joinTable = (SJoinTableNode*)table;
tableToStr(joinTable->pLeft, prefix, str);
str.append("\n" + prefix + "JOIN\n");
tableToStr(joinTable->pRight, prefix, str);
if (nullptr != joinTable->pOnCond) {
str.append("\n" + prefix + "\tON ");
nodeToStr(joinTable->pOnCond, str, false);
}
break;
}
default:
break;
}
}
void selectToStr(const SNode* node, string& str, const string& prefix = "") {
SSelectStmt* select = (SSelectStmt*)node;
str.append(prefix + "SELECT ");
if (select->isDistinct) {
str.append("DISTINCT");
}
str.append("\n");
nodeListToStr(select->pProjectionList, prefix + "\t", str, true);
str.append(prefix + "FROM\n");
tableToStr(select->pFromTable, prefix + "\t", str);
if (nullptr != select->pWhere) {
str.append("\n" + prefix + "WHERE\n\t");
nodeToStr(select->pWhere, str, false);
}
if (nullptr != select->pGroupByList) {
str.append("\n" + prefix + "GROUP BY\n");
nodeListToStr(select->pGroupByList, prefix + "\t", str, true);
}
if (nullptr != select->pOrderByList) {
str.append(prefix + "ORDER BY\n");
nodeListToStr(select->pOrderByList, prefix + "\t", str, true);
}
}
void selectToSql(const SNode* node, string& sql) {
SSelectStmt* select = (SSelectStmt*)node;
sql.append("SELECT ");
if (select->isDistinct) {
sql.append("DISTINCT ");
}
if (nullptr == select->pProjectionList) {
sql.append("* ");
} else {
nodeListToSql(select->pProjectionList, sql);
sql.append(" ");
}
sql.append("FROM ");
tableToSql(select->pFromTable, sql);
if (nullptr != select->pWhere) {
sql.append(" WHERE ");
nodeToSql(select->pWhere, sql);
}
}
void tableToSql(const SNode* node, string& sql) {
const STableNode* table = (const STableNode*)node;
switch (nodeType(node)) {
case QUERY_NODE_REAL_TABLE: {
SRealTableNode* realTable = (SRealTableNode*)table;
if ('\0' != realTable->table.dbName[0]) {
sql.append(realTable->table.dbName);
sql.append(".");
}
sql.append(realTable->table.tableName);
break;
}
case QUERY_NODE_TEMP_TABLE: {
STempTableNode* tempTable = (STempTableNode*)table;
sql.append("(");
selectToSql(tempTable->pSubquery, sql);
sql.append(") ");
sql.append(tempTable->table.tableAlias);
break;
}
case QUERY_NODE_JOIN_TABLE: {
SJoinTableNode* joinTable = (SJoinTableNode*)table;
tableToSql(joinTable->pLeft, sql);
sql.append(" JOIN ");
tableToSql(joinTable->pRight, sql);
if (nullptr != joinTable->pOnCond) {
sql.append(" ON ");
nodeToSql(joinTable->pOnCond, sql);
}
break;
}
default:
break;
}
}
string opTypeToStr(EOperatorType type) {
switch (type) {
case OP_TYPE_ADD:
return " + ";
case OP_TYPE_SUB:
return " - ";
case OP_TYPE_MULTI:
return " * ";
case OP_TYPE_DIV:
return " / ";
case OP_TYPE_MOD:
return " % ";
case OP_TYPE_GREATER_THAN:
return " > ";
case OP_TYPE_GREATER_EQUAL:
return " >= ";
case OP_TYPE_LOWER_THAN:
return " < ";
case OP_TYPE_LOWER_EQUAL:
return " <= ";
case OP_TYPE_EQUAL:
return " = ";
case OP_TYPE_NOT_EQUAL:
return " != ";
case OP_TYPE_IN:
case OP_TYPE_NOT_IN:
case OP_TYPE_LIKE:
case OP_TYPE_NOT_LIKE:
case OP_TYPE_MATCH:
case OP_TYPE_NMATCH:
case OP_TYPE_JSON_GET_VALUE:
case OP_TYPE_JSON_CONTAINS:
default:
break;
}
return " unknown operator ";
}
void nodeToSql(const SNode* node, string& sql) {
if (nullptr == node) {
return;
}
switch (nodeType(node)) {
case QUERY_NODE_COLUMN: {
SColumnNode* pCol = (SColumnNode*)node;
if ('\0' != pCol->dbName[0]) {
sql.append(pCol->dbName);
sql.append(".");
}
if ('\0' != pCol->tableAlias[0]) {
sql.append(pCol->tableAlias);
sql.append(".");
}
sql.append(pCol->colName);
break;
}
case QUERY_NODE_VALUE:
break;
case QUERY_NODE_OPERATOR: {
SOperatorNode* pOp = (SOperatorNode*)node;
nodeToSql(pOp->pLeft, sql);
sql.append(opTypeToStr(pOp->opType));
nodeToSql(pOp->pRight, sql);
break;
}
default:
break;
}
}
void nodeListToSql(const SNodeList* nodelist, string& sql, const string& seq = ",") {
SNode* node = nullptr;
bool firstNode = true;
FOREACH(node, nodelist) {
if (!firstNode) {
sql.append(", ");
}
firstNode = false;
nodeToSql(node, sql);
string toString(const SNode* pRoot, bool format = false) {
char* pStr = NULL;
int32_t len = 0;
int32_t code = nodesNodeToString(pRoot, format, &pStr, &len);
if (code != TSDB_CODE_SUCCESS) {
cout << "sql:[" << cxt_.pSql << "] toString code:" << code << ", strerror:" << tstrerror(code) << endl;
throw "nodesNodeToString failed!";
}
string str(pStr);
tfree(pStr);
return str;
}
void reset() {
......@@ -700,6 +284,27 @@ TEST_F(ParserTest, selectSemanticError) {
TEST_F(ParserTest, createDatabase) {
bind("create database wxy_db");
ASSERT_TRUE(run());
bind("create database if not exists wxy_db "
"BLOCKS 100 "
"CACHE 100 "
"CACHELAST 2 "
"COMP 1 "
"DAYS 100 "
"FSYNC 100 "
"MAXROWS 1000 "
"MINROWS 100 "
"KEEP 100 "
"PRECISION 'ms' "
"QUORUM 1 "
"REPLICA 3 "
"TTL 100 "
"WAL 2 "
"VGROUPS 100 "
"SINGLE_STABLE 0 "
"STREAM_MODE 1 "
);
ASSERT_TRUE(run());
}
TEST_F(ParserTest, showDatabase) {
......@@ -715,4 +320,42 @@ TEST_F(ParserTest, useDatabase) {
TEST_F(ParserTest, createTable) {
bind("create table t1(ts timestamp, c1 int)");
ASSERT_TRUE(run());
bind("create table if not exists test.t1("
"ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), c8 SMALLINT, "
"c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, c13 NCHAR(30), c14 JSON, c15 VARCHAR(50)) "
"KEEP 100 TTL 100 COMMENT 'test create table' SMA(c1, c2, c3)"
);
ASSERT_TRUE(run());
bind("create table if not exists test.t1("
"ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), c8 SMALLINT, "
"c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, c13 NCHAR(30), c14 JSON, c15 VARCHAR(50)) "
"TAGS (tsa TIMESTAMP, a1 INT, a2 INT UNSIGNED, a3 BIGINT, a4 BIGINT UNSIGNED, a5 FLOAT, a6 DOUBLE, a7 BINARY(20), a8 SMALLINT, "
"a9 SMALLINT UNSIGNED COMMENT 'test column comment', a10 TINYINT, a11 TINYINT UNSIGNED, a12 BOOL, a13 NCHAR(30), a14 JSON, a15 VARCHAR(50)) "
"KEEP 100 TTL 100 COMMENT 'test create table' SMA(c1, c2, c3)"
);
ASSERT_TRUE(run());
bind("create table if not exists t1 using st1 tags(1)");
ASSERT_TRUE(run());
bind("create table "
"if not exists test.t1 using test.st1 (tc1, tc2, tc3) tags(1, 2.0, 'abc', TIMESTAMP '2022-3-6 11:20:23') "
"if not exists test.t2 using test.st1 (tc1, tc2, tc3) tags(2, 2.0, 'abc', TIMESTAMP '2022-3-6 11:20:23') "
"if not exists test.t3 using test.st1 (tc1, tc2, tc3) tags(3, 2.0, 'abc', TIMESTAMP '2022-3-6 11:20:23')"
);
ASSERT_TRUE(run());
bind("create stable t1(ts timestamp, c1 int) TAGS(id int)");
ASSERT_TRUE(run());
bind("create stable if not exists test.t1("
"ts TIMESTAMP, c1 INT, c2 INT UNSIGNED, c3 BIGINT, c4 BIGINT UNSIGNED, c5 FLOAT, c6 DOUBLE, c7 BINARY(20), c8 SMALLINT, "
"c9 SMALLINT UNSIGNED COMMENT 'test column comment', c10 TINYINT, c11 TINYINT UNSIGNED, c12 BOOL, c13 NCHAR(30), c14 JSON, c15 VARCHAR(50)) "
"TAGS (tsa TIMESTAMP, a1 INT, a2 INT UNSIGNED, a3 BIGINT, a4 BIGINT UNSIGNED, a5 FLOAT, a6 DOUBLE, a7 BINARY(20), a8 SMALLINT, "
"a9 SMALLINT UNSIGNED COMMENT 'test column comment', a10 TINYINT, a11 TINYINT UNSIGNED, a12 BOOL, a13 NCHAR(30), a14 JSON, a15 VARCHAR(50)) "
"KEEP 100 TTL 100 COMMENT 'test create table' SMA(c1, c2, c3)"
);
ASSERT_TRUE(run());
}
......@@ -349,11 +349,15 @@ static SLogicNode* createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* p
return pRoot;
}
static int32_t getMsgType(ENodeType sqlType) {
return (QUERY_NODE_CREATE_TABLE_STMT == sqlType || QUERY_NODE_CREATE_MULTI_TABLE_STMT == sqlType) ? TDMT_VND_CREATE_TABLE : TDMT_VND_SUBMIT;
}
static SLogicNode* createVnodeModifLogicNode(SLogicPlanContext* pCxt, SVnodeModifOpStmt* pStmt) {
SVnodeModifLogicNode* pModif = (SVnodeModifLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_VNODE_MODIF);
CHECK_ALLOC(pModif, NULL);
pModif->pDataBlocks = pStmt->pDataBlocks;
pModif->msgType = (QUERY_NODE_CREATE_TABLE_STMT == pStmt->sqlNodeType ? TDMT_VND_CREATE_TABLE : TDMT_VND_SUBMIT);
pModif->msgType = getMsgType(pStmt->sqlNodeType);
return (SLogicNode*)pModif;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册