TD-13338 SELECT statement translate code
This commit is contained in:
parent
69d196815b
commit
090250f994
|
@ -121,6 +121,14 @@ typedef struct SColumnNode {
|
||||||
typedef struct SValueNode {
|
typedef struct SValueNode {
|
||||||
SExprNode node; // QUERY_NODE_VALUE
|
SExprNode node; // QUERY_NODE_VALUE
|
||||||
char* literal;
|
char* literal;
|
||||||
|
bool isDuration;
|
||||||
|
union {
|
||||||
|
bool b;
|
||||||
|
int64_t i;
|
||||||
|
uint64_t u;
|
||||||
|
double d;
|
||||||
|
char* p;
|
||||||
|
} datum;
|
||||||
} SValueNode;
|
} SValueNode;
|
||||||
|
|
||||||
typedef enum EOperatorType {
|
typedef enum EOperatorType {
|
||||||
|
@ -181,7 +189,7 @@ typedef struct SNodeListNode {
|
||||||
} SNodeListNode;
|
} SNodeListNode;
|
||||||
|
|
||||||
typedef struct SFunctionNode {
|
typedef struct SFunctionNode {
|
||||||
SExprNode type; // QUERY_NODE_FUNCTION
|
SExprNode node; // QUERY_NODE_FUNCTION
|
||||||
char functionName[TSDB_FUNC_NAME_LEN];
|
char functionName[TSDB_FUNC_NAME_LEN];
|
||||||
int32_t funcId;
|
int32_t funcId;
|
||||||
SNodeList* pParameterList;
|
SNodeList* pParameterList;
|
||||||
|
|
|
@ -441,10 +441,13 @@ int32_t* taosGetErrno();
|
||||||
#define TSDB_CODE_SCH_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2502) //scheduler internal error
|
#define TSDB_CODE_SCH_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2502) //scheduler internal error
|
||||||
|
|
||||||
//parser
|
//parser
|
||||||
#define TSDB_CODE_PARSER_INVALID_COLUMN TAOS_DEF_ERROR_CODE(0, 0x2601) //invalid column name
|
#define TSDB_CODE_PAR_INVALID_COLUMN TAOS_DEF_ERROR_CODE(0, 0x2601) //invalid column name
|
||||||
#define TSDB_CODE_PARSER_TABLE_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x2602) //table not exist
|
#define TSDB_CODE_PAR_TABLE_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x2602) //table not exist
|
||||||
#define TSDB_CODE_PARSER_AMBIGUOUS_COLUMN TAOS_DEF_ERROR_CODE(0, 0x2603) //ambiguous column
|
#define TSDB_CODE_PAR_AMBIGUOUS_COLUMN TAOS_DEF_ERROR_CODE(0, 0x2603) //ambiguous column
|
||||||
#define TSDB_CODE_PARSER_WRONG_VALUE_TYPE TAOS_DEF_ERROR_CODE(0, 0x2604) //wrong value type
|
#define TSDB_CODE_PAR_WRONG_VALUE_TYPE TAOS_DEF_ERROR_CODE(0, 0x2604) //wrong value type
|
||||||
|
#define TSDB_CODE_PAR_FUNTION_PARA_NUM TAOS_DEF_ERROR_CODE(0, 0x2605) //invalid number of arguments
|
||||||
|
#define TSDB_CODE_PAR_FUNTION_PARA_TYPE TAOS_DEF_ERROR_CODE(0, 0x2606) //inconsistent datatypes
|
||||||
|
#define TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION TAOS_DEF_ERROR_CODE(0, 0x2607) //there mustn't be aggregation
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,3 +78,11 @@ FuncDef setExecFuncs(FuncDef def, FExecGetEnv getEnv, FExecInit init, FExecProce
|
||||||
int32_t registerFunc(FuncDef func) {
|
int32_t registerFunc(FuncDef func) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t fmGetFuncResultType(FuncMgtHandle handle, SFunctionNode* pFunc) {
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fmIsAggFunc(int32_t funcId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -118,14 +118,22 @@ SNode* createValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken*
|
||||||
val->literal = strndup(pLiteral->z, pLiteral->n);
|
val->literal = strndup(pLiteral->z, pLiteral->n);
|
||||||
CHECK_OUT_OF_MEM(val->literal);
|
CHECK_OUT_OF_MEM(val->literal);
|
||||||
val->node.resType.type = dataType;
|
val->node.resType.type = dataType;
|
||||||
val->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes;
|
val->node.resType.bytes = tDataTypes[dataType].bytes;
|
||||||
|
if (TSDB_DATA_TYPE_TIMESTAMP == dataType) {
|
||||||
|
val->node.resType.precision = TSDB_TIME_PRECISION_MILLI;
|
||||||
|
}
|
||||||
return (SNode*)val;
|
return (SNode*)val;
|
||||||
}
|
}
|
||||||
|
|
||||||
SNode* createDurationValueNode(SAstCreateContext* pCxt, const SToken* pLiteral) {
|
SNode* createDurationValueNode(SAstCreateContext* pCxt, const SToken* pLiteral) {
|
||||||
SValueNode* val = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
|
SValueNode* val = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
|
||||||
CHECK_OUT_OF_MEM(val);
|
CHECK_OUT_OF_MEM(val);
|
||||||
// todo : calc, for example, 10s
|
val->literal = strndup(pLiteral->z, pLiteral->n);
|
||||||
|
CHECK_OUT_OF_MEM(val->literal);
|
||||||
|
val->isDuration = true;
|
||||||
|
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;
|
||||||
return (SNode*)val;
|
return (SNode*)val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,10 @@
|
||||||
#include "parserImpl.h"
|
#include "parserImpl.h"
|
||||||
|
|
||||||
#include "astCreateContext.h"
|
#include "astCreateContext.h"
|
||||||
|
#include "functionMgt.h"
|
||||||
#include "parserInt.h"
|
#include "parserInt.h"
|
||||||
|
#include "tglobal.h"
|
||||||
|
#include "ttime.h"
|
||||||
#include "ttoken.h"
|
#include "ttoken.h"
|
||||||
|
|
||||||
typedef void* (*FMalloc)(size_t);
|
typedef void* (*FMalloc)(size_t);
|
||||||
|
@ -240,6 +243,7 @@ typedef enum ESqlClause {
|
||||||
|
|
||||||
typedef struct STranslateContext {
|
typedef struct STranslateContext {
|
||||||
SParseContext* pParseCxt;
|
SParseContext* pParseCxt;
|
||||||
|
FuncMgtHandle fmgt;
|
||||||
int32_t errCode;
|
int32_t errCode;
|
||||||
SMsgBuf msgBuf;
|
SMsgBuf msgBuf;
|
||||||
SArray* pNsLevel; // element is SArray*, the element of this subarray is STableNode*
|
SArray* pNsLevel; // element is SArray*, the element of this subarray is STableNode*
|
||||||
|
@ -251,21 +255,30 @@ static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode);
|
||||||
|
|
||||||
static char* getSyntaxErrFormat(int32_t errCode) {
|
static char* getSyntaxErrFormat(int32_t errCode) {
|
||||||
switch (errCode) {
|
switch (errCode) {
|
||||||
case TSDB_CODE_PARSER_INVALID_COLUMN:
|
case TSDB_CODE_PAR_INVALID_COLUMN:
|
||||||
return "Invalid column name : %s";
|
return "Invalid column name : %s";
|
||||||
case TSDB_CODE_PARSER_TABLE_NOT_EXIST:
|
case TSDB_CODE_PAR_TABLE_NOT_EXIST:
|
||||||
return "Table does not exist : %s";
|
return "Table does not exist : %s";
|
||||||
case TSDB_CODE_PARSER_AMBIGUOUS_COLUMN:
|
case TSDB_CODE_PAR_AMBIGUOUS_COLUMN:
|
||||||
return "Column ambiguously defined : %s";
|
return "Column ambiguously defined : %s";
|
||||||
case TSDB_CODE_PARSER_WRONG_VALUE_TYPE:
|
case TSDB_CODE_PAR_WRONG_VALUE_TYPE:
|
||||||
return "Invalid value type : %s";
|
return "Invalid value type : %s";
|
||||||
|
case TSDB_CODE_PAR_FUNTION_PARA_NUM:
|
||||||
|
return "Invalid number of arguments : %s";
|
||||||
|
case TSDB_CODE_PAR_FUNTION_PARA_TYPE:
|
||||||
|
return "Inconsistent datatypes : %s";
|
||||||
|
case TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION:
|
||||||
|
return "There mustn't be aggregation";
|
||||||
default:
|
default:
|
||||||
return "Unknown error";
|
return "Unknown error";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t generateSyntaxErrMsg(STranslateContext* pCxt, int32_t errCode, const char* additionalInfo) {
|
static int32_t generateSyntaxErrMsg(STranslateContext* pCxt, int32_t errCode, ...) {
|
||||||
snprintf(pCxt->msgBuf.buf, pCxt->msgBuf.len, getSyntaxErrFormat(errCode), additionalInfo);
|
va_list vArgList;
|
||||||
|
va_start(vArgList, errCode);
|
||||||
|
vsnprintf(pCxt->msgBuf.buf, pCxt->msgBuf.len, getSyntaxErrFormat(errCode), vArgList);
|
||||||
|
va_end(vArgList);
|
||||||
pCxt->errCode = errCode;
|
pCxt->errCode = errCode;
|
||||||
return errCode;
|
return errCode;
|
||||||
}
|
}
|
||||||
|
@ -394,7 +407,7 @@ static bool translateColumnWithPrefix(STranslateContext* pCxt, SColumnNode* pCol
|
||||||
if (findAndSetColumn(pCol, pTable)) {
|
if (findAndSetColumn(pCol, pTable)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
generateSyntaxErrMsg(pCxt, TSDB_CODE_PARSER_INVALID_COLUMN, pCol->colName);
|
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, pCol->colName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,14 +422,14 @@ static bool translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNode* p
|
||||||
STableNode* pTable = taosArrayGetP(pTables, i);
|
STableNode* pTable = taosArrayGetP(pTables, i);
|
||||||
if (findAndSetColumn(pCol, pTable)) {
|
if (findAndSetColumn(pCol, pTable)) {
|
||||||
if (found) {
|
if (found) {
|
||||||
generateSyntaxErrMsg(pCxt, TSDB_CODE_PARSER_AMBIGUOUS_COLUMN, pCol->colName);
|
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_AMBIGUOUS_COLUMN, pCol->colName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
generateSyntaxErrMsg(pCxt, TSDB_CODE_PARSER_INVALID_COLUMN, pCol->colName);
|
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_INVALID_COLUMN, pCol->colName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -429,8 +442,72 @@ static bool translateColumn(STranslateContext* pCxt, SColumnNode* pCol) {
|
||||||
return translateColumnWithoutPrefix(pCxt, pCol);
|
return translateColumnWithoutPrefix(pCxt, pCol);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check literal format
|
static int32_t trimStringCopy(const char* src, int32_t len, char* 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)) {
|
||||||
|
dst[j] = src[k + 1];
|
||||||
|
cnt++;
|
||||||
|
j++;
|
||||||
|
k++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dst[j] = src[k];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
dst[j] = '\0';
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
static bool translateValue(STranslateContext* pCxt, SValueNode* pVal) {
|
static bool translateValue(STranslateContext* pCxt, SValueNode* pVal) {
|
||||||
|
if (pVal->isDuration) {
|
||||||
|
char unit = 0;
|
||||||
|
if (parseAbsoluteDuration(pVal->literal, strlen(pVal->literal), &pVal->datum.i, &unit, pVal->node.resType.precision) != TSDB_CODE_SUCCESS) {
|
||||||
|
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (pVal->node.resType.type) {
|
||||||
|
case TSDB_DATA_TYPE_NULL:
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_BOOL:
|
||||||
|
pVal->datum.b = (0 == strcasecmp(pVal->literal, "true"));
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_BIGINT: {
|
||||||
|
char* endPtr = NULL;
|
||||||
|
pVal->datum.i = strtoull(pVal->literal, &endPtr, 10);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TSDB_DATA_TYPE_DOUBLE: {
|
||||||
|
char* endPtr = NULL;
|
||||||
|
pVal->datum.d = strtold(pVal->literal, &endPtr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TSDB_DATA_TYPE_BINARY: {
|
||||||
|
int32_t n = strlen(pVal->literal);
|
||||||
|
pVal->datum.p = calloc(1, n);
|
||||||
|
trimStringCopy(pVal->literal, n, pVal->datum.p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||||
|
int32_t n = strlen(pVal->literal);
|
||||||
|
char* tmp = calloc(1, n);
|
||||||
|
int32_t len = trimStringCopy(pVal->literal, n, tmp);
|
||||||
|
if (taosParseTime(tmp, &pVal->datum.u, len, pVal->node.resType.precision, tsDaylight) != TSDB_CODE_SUCCESS) {
|
||||||
|
tfree(tmp);
|
||||||
|
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, pVal->literal);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tfree(tmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +517,7 @@ static bool translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||||
if (nodesIsArithmeticOp(pOp)) {
|
if (nodesIsArithmeticOp(pOp)) {
|
||||||
if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type ||
|
if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type ||
|
||||||
TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
|
TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
|
||||||
generateSyntaxErrMsg(pCxt, TSDB_CODE_PARSER_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
|
pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE;
|
||||||
|
@ -449,7 +526,7 @@ static bool translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||||
} else if (nodesIsComparisonOp(pOp)) {
|
} else if (nodesIsComparisonOp(pOp)) {
|
||||||
if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type ||
|
if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type ||
|
||||||
TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
|
TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) {
|
||||||
generateSyntaxErrMsg(pCxt, TSDB_CODE_PARSER_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
|
pOp->node.resType.type = TSDB_DATA_TYPE_BOOL;
|
||||||
|
@ -463,6 +540,15 @@ static bool translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) {
|
static bool translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) {
|
||||||
|
int32_t code = fmGetFuncResultType(pCxt->fmgt, pFunc);
|
||||||
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
generateSyntaxErrMsg(pCxt, code, pFunc->functionName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (fmIsAggFunc(pFunc->funcId) && (SQL_CLAUSE_FROM == pCxt->currClause || SQL_CLAUSE_WHERE == pCxt->currClause)) {
|
||||||
|
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,7 +590,7 @@ static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) {
|
||||||
code = catalogGetTableMeta(pCxt->pParseCxt->pCatalog, pCxt->pParseCxt->pTransporter, &(pCxt->pParseCxt->mgmtEpSet),
|
code = catalogGetTableMeta(pCxt->pParseCxt->pCatalog, pCxt->pParseCxt->pTransporter, &(pCxt->pParseCxt->mgmtEpSet),
|
||||||
toName(pCxt->pParseCxt->acctId, pRealTable, &name), &(pRealTable->pMeta));
|
toName(pCxt->pParseCxt->acctId, pRealTable, &name), &(pRealTable->pMeta));
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
return generateSyntaxErrMsg(pCxt, TSDB_CODE_PARSER_TABLE_NOT_EXIST, pRealTable->table.tableName);
|
return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_TABLE_NOT_EXIST, pRealTable->table.tableName);
|
||||||
}
|
}
|
||||||
code = addNamespace(pCxt, pRealTable);
|
code = addNamespace(pCxt, pRealTable);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -118,6 +118,53 @@ private:
|
||||||
return "Unknown Data Type " + to_string(dt.type);
|
return "Unknown Data Type " + to_string(dt.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void valueNodeToStr(const SValueNode* pVal, string& str, bool isProject) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
str.append(" [" + dataTypeToStr(pVal->node.resType) + "]");
|
||||||
|
if (isProject) {
|
||||||
|
str.append(" AS " + string(pVal->node.aliasName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void nodeToStr(const SNode* node, string& str, bool isProject) {
|
void nodeToStr(const SNode* node, string& str, bool isProject) {
|
||||||
if (nullptr == node) {
|
if (nullptr == node) {
|
||||||
return;
|
return;
|
||||||
|
@ -142,12 +189,7 @@ private:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QUERY_NODE_VALUE: {
|
case QUERY_NODE_VALUE: {
|
||||||
SValueNode* pVal = (SValueNode*)node;
|
valueNodeToStr((SValueNode*)node, str, isProject);
|
||||||
str.append(pVal->literal);
|
|
||||||
str.append(" [" + dataTypeToStr(pVal->node.resType) + "]");
|
|
||||||
if (isProject) {
|
|
||||||
str.append(" AS " + string(pVal->node.aliasName));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QUERY_NODE_OPERATOR: {
|
case QUERY_NODE_OPERATOR: {
|
||||||
|
@ -391,10 +433,20 @@ TEST_F(NewParserTest, selectSimple) {
|
||||||
ASSERT_TRUE(run());
|
ASSERT_TRUE(run());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(NewParserTest, selectConstant) {
|
||||||
|
setDatabase("root", "test");
|
||||||
|
|
||||||
|
bind("SELECT 123, 20.4, 'abc', \"wxy\", TIMESTAMP '2022-02-09 17:30:20', true, false, 10s FROM t1");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
|
||||||
|
bind("SELECT 1234567890123456789012345678901234567890, 20.1234567890123456789012345678901234567890, 'abc', \"wxy\", TIMESTAMP '2022-02-09 17:30:20', true, false, 15s FROM t1");
|
||||||
|
ASSERT_TRUE(run());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(NewParserTest, selectExpression) {
|
TEST_F(NewParserTest, selectExpression) {
|
||||||
setDatabase("root", "test");
|
setDatabase("root", "test");
|
||||||
|
|
||||||
bind("SELECT c1 + 10, c2 FROM t1");
|
bind("SELECT ts + 10s, c1 + 10, concat(c2, 'abc') FROM t1");
|
||||||
ASSERT_TRUE(run());
|
ASSERT_TRUE(run());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue