[td-10564] add more code for query module.
This commit is contained in:
parent
04c53c2939
commit
eba7327888
|
@ -36,6 +36,8 @@ typedef struct SVariant {
|
|||
};
|
||||
} SVariant;
|
||||
|
||||
int32_t toInteger(const char* z, int32_t n, int32_t base, int64_t* value, bool* issigned);
|
||||
|
||||
bool taosVariantIsValid(SVariant *pVar);
|
||||
|
||||
void taosVariantCreate(SVariant *pVar, char* z, int32_t n, int32_t type);
|
||||
|
|
|
@ -10,4 +10,6 @@ target_link_libraries(
|
|||
PUBLIC os
|
||||
PUBLIC util
|
||||
INTERFACE api
|
||||
)
|
||||
)
|
||||
|
||||
ADD_SUBDIRECTORY(test)
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
#include "os.h"
|
||||
|
||||
#include "taos.h"
|
||||
#include "thash.h"
|
||||
#include "taosdef.h"
|
||||
#include "thash.h"
|
||||
#include "ttime.h"
|
||||
#include "ttokendef.h"
|
||||
#include "ttypes.h"
|
||||
|
@ -39,6 +39,42 @@
|
|||
assert(0); \
|
||||
} while (0)
|
||||
|
||||
int32_t toInteger(const char* z, int32_t n, int32_t base, int64_t* value, bool* isSigned) {
|
||||
errno = 0;
|
||||
char* endPtr = NULL;
|
||||
|
||||
int32_t index = 0;
|
||||
|
||||
bool specifiedSign = (z[0] == '+' || z[0] == '-');
|
||||
if (specifiedSign) {
|
||||
*isSigned = true;
|
||||
index = 1;
|
||||
}
|
||||
|
||||
uint64_t val = strtoull(&z[index], &endPtr, base);
|
||||
if (errno == ERANGE || errno == EINVAL) {
|
||||
errno = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (specifiedSign && val > INT64_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (endPtr - &z[index] != n - index) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*isSigned = specifiedSign || (val <= INT64_MAX);
|
||||
if (*isSigned) {
|
||||
*value = (z[0] == '-')? -val:val;
|
||||
} else {
|
||||
*(uint64_t*) value = val;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void taosVariantCreate(SVariant *pVar, char* z, int32_t n, int32_t type) {
|
||||
int32_t ret = 0;
|
||||
memset(pVar, 0, sizeof(SVariant));
|
||||
|
@ -52,7 +88,6 @@ void taosVariantCreate(SVariant *pVar, char* z, int32_t n, int32_t type) {
|
|||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -60,38 +95,38 @@ void taosVariantCreate(SVariant *pVar, char* z, int32_t n, int32_t type) {
|
|||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_INT:{
|
||||
// ret = tStrToInteger(token->z, token->type, token->n, &pVar->i64, true);
|
||||
// if (ret != 0) {
|
||||
// SToken t = {0};
|
||||
// tGetToken(token->z, &t.type);
|
||||
// if (t.type == TK_MINUS) { // it is a signed number which is greater than INT64_MAX or less than INT64_MIN
|
||||
// pVar->nType = -1; // -1 means error type
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // data overflow, try unsigned parse the input number
|
||||
// ret = tStrToInteger(token->z, token->type, token->n, &pVar->i64, false);
|
||||
// if (ret != 0) {
|
||||
// pVar->nType = -1; // -1 means error type
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
bool sign = true;
|
||||
|
||||
int32_t base = 10;
|
||||
if (type == TK_HEX) {
|
||||
base = 16;
|
||||
} else if (type == TK_OCT) {
|
||||
base = 8;
|
||||
} else if (type == TK_BIN) {
|
||||
base = 2;
|
||||
}
|
||||
|
||||
ret = toInteger(z, n, base, &pVar->i64, &sign);
|
||||
if (ret != 0) {
|
||||
pVar->nType = -1; // -1 means error type
|
||||
return;
|
||||
}
|
||||
|
||||
pVar->nType = (sign)? TSDB_DATA_TYPE_BIGINT:TSDB_DATA_TYPE_UBIGINT;
|
||||
break;
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
pVar->d = strtod(z, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
pVar->pz = strndup(z, n);
|
||||
pVar->nLen = strRmquote(pVar->pz, n);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||
assert(0);
|
||||
pVar->i64 = taosGetTimestamp(TSDB_TIME_PRECISION_NANO);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
MESSAGE(STATUS "build parser unit test")
|
||||
|
||||
# GoogleTest requires at least C++11
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
|
||||
|
||||
ADD_EXECUTABLE(commonTest ${SOURCE_LIST})
|
||||
TARGET_LINK_LIBRARIES(
|
||||
commonTest
|
||||
PUBLIC os util common gtest
|
||||
)
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(
|
||||
commonTest
|
||||
PUBLIC "${CMAKE_SOURCE_DIR}/include/libs/common/"
|
||||
PRIVATE "${CMAKE_SOURCE_DIR}/source/libs/common/inc"
|
||||
)
|
|
@ -0,0 +1,96 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include <iostream>
|
||||
#pragma GCC diagnostic ignored "-Wwrite-strings"
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#include "os.h"
|
||||
|
||||
#include "taos.h"
|
||||
#include "tvariant.h"
|
||||
#include "tdef.h"
|
||||
|
||||
namespace {
|
||||
//
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
TEST(testCase, toInteger_test) {
|
||||
char* s = "123";
|
||||
uint32_t type = 0;
|
||||
|
||||
int64_t val = 0;
|
||||
bool sign = true;
|
||||
|
||||
int32_t ret = toInteger(s, strlen(s), 10, &val, &sign);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 123);
|
||||
ASSERT_EQ(sign, true);
|
||||
|
||||
s = "9223372036854775807";
|
||||
ret = toInteger(s, strlen(s), 10, &val, &sign);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 9223372036854775807);
|
||||
ASSERT_EQ(sign, true);
|
||||
|
||||
s = "9323372036854775807";
|
||||
ret = toInteger(s, strlen(s), 10, &val, &sign);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 9323372036854775807u);
|
||||
ASSERT_EQ(sign, false);
|
||||
|
||||
s = "-9323372036854775807";
|
||||
ret = toInteger(s, strlen(s), 10, &val, &sign);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
s = "-1";
|
||||
ret = toInteger(s, strlen(s), 10, &val, &sign);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, -1);
|
||||
ASSERT_EQ(sign, true);
|
||||
|
||||
s = "-9223372036854775807";
|
||||
ret = toInteger(s, strlen(s), 10, &val, &sign);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, -9223372036854775807);
|
||||
ASSERT_EQ(sign, true);
|
||||
|
||||
s = "1000u";
|
||||
ret = toInteger(s, strlen(s), 10, &val, &sign);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
s = "0x10";
|
||||
ret = toInteger(s, strlen(s), 16, &val, &sign);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 16);
|
||||
ASSERT_EQ(sign, true);
|
||||
|
||||
s = "110";
|
||||
ret = toInteger(s, strlen(s), 2, &val, &sign);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 6);
|
||||
ASSERT_EQ(sign, true);
|
||||
|
||||
s = "110";
|
||||
ret = toInteger(s, strlen(s), 8, &val, &sign);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 72);
|
||||
ASSERT_EQ(sign, true);
|
||||
|
||||
//18446744073709551615 UINT64_MAX
|
||||
s = "18446744073709551615";
|
||||
ret = toInteger(s, strlen(s), 10, &val, &sign);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 18446744073709551615u);
|
||||
ASSERT_EQ(sign, false);
|
||||
|
||||
s = "18446744073709551616";
|
||||
ret = toInteger(s, strlen(s), 10, &val, &sign);
|
||||
ASSERT_EQ(ret, -1);
|
||||
}
|
|
@ -277,6 +277,7 @@ bool tSqlExprIsParentOfLeaf(tSqlExpr *pExpr);
|
|||
void tSqlExprDestroy(tSqlExpr *pExpr);
|
||||
SArray * tSqlExprListAppend(SArray *pList, tSqlExpr *pNode, SToken *pDistinct, SToken *pToken);
|
||||
void tSqlExprListDestroy(SArray *pList);
|
||||
void tSqlExprEvaluate(tSqlExpr* pExpr);
|
||||
|
||||
SSqlNode *tSetQuerySqlNode(SToken *pSelectToken, SArray *pSelNodeList, SRelationInfo *pFrom, tSqlExpr *pWhere,
|
||||
SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval, SSessionWindowVal *ps,
|
||||
|
|
|
@ -46,6 +46,16 @@ typedef struct SInsertStmtInfo {
|
|||
*/
|
||||
int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pSqlInfo, SQueryStmtInfo* pQueryInfo, int64_t id, char* msg, int32_t msgLen);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pNode
|
||||
* @param tsPrecision
|
||||
* @param msg
|
||||
* @param msgBufLen
|
||||
* @return
|
||||
*/
|
||||
int32_t evaluateSqlNode(SSqlNode* pNode, int32_t tsPrecision, char* msg, int32_t msgBufLen);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pSqlNode
|
||||
|
|
|
@ -23,7 +23,8 @@ extern "C" {
|
|||
#include "os.h"
|
||||
#include "ttoken.h"
|
||||
|
||||
int32_t parserValidateNameToken(SToken* pToken);
|
||||
int32_t parserValidateIdToken(SToken* pToken);
|
||||
int32_t parserSetInvalidOperatorMsg(char* dst, int32_t dstBufLen, const char* msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -18,52 +18,6 @@
|
|||
#include "astGenerator.h"
|
||||
#include "tmsgtype.h"
|
||||
|
||||
int32_t tStrToInteger(const char* z, int16_t type, int32_t n, int64_t* value, bool issigned) {
|
||||
errno = 0;
|
||||
int32_t ret = 0;
|
||||
|
||||
char* endPtr = NULL;
|
||||
if (type == TK_FLOAT) {
|
||||
double v = strtod(z, &endPtr);
|
||||
if ((errno == ERANGE && v == HUGE_VALF) || isinf(v) || isnan(v)) {
|
||||
ret = -1;
|
||||
} else if ((issigned && (v < INT64_MIN || v > INT64_MAX)) || ((!issigned) && (v < 0 || v > UINT64_MAX))) {
|
||||
ret = -1;
|
||||
} else {
|
||||
*value = (int64_t) round(v);
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t radix = 10;
|
||||
if (type == TK_HEX) {
|
||||
radix = 16;
|
||||
} else if (type == TK_BIN) {
|
||||
radix = 2;
|
||||
}
|
||||
|
||||
// the string may be overflow according to errno
|
||||
if (!issigned) {
|
||||
const char *p = z;
|
||||
while(*p != 0 && *p == ' ') p++;
|
||||
if (*p != 0 && *p == '-') { return -1;}
|
||||
|
||||
*value = strtoull(z, &endPtr, radix);
|
||||
} else {
|
||||
*value = strtoll(z, &endPtr, radix);
|
||||
}
|
||||
|
||||
// not a valid integer number, return error
|
||||
if (endPtr - z != n || errno == ERANGE) {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
SArray *tListItemAppend(SArray *pList, SVariant *pVar, uint8_t sortOrder) {
|
||||
if (pList == NULL) {
|
||||
pList = taosArrayInit(4, sizeof(SListItem));
|
||||
|
@ -173,7 +127,6 @@ SRelationInfo *addSubquery(SRelationInfo *pRelationInfo, SArray *pSub, SToken *p
|
|||
}
|
||||
|
||||
// sql expr leaf node
|
||||
// todo Evalute the value during the validation process of AST.
|
||||
tSqlExpr *tSqlExprCreateIdValue(SToken *pToken, int32_t optrType) {
|
||||
tSqlExpr *pSqlExpr = calloc(1, sizeof(tSqlExpr));
|
||||
|
||||
|
@ -189,34 +142,10 @@ tSqlExpr *tSqlExprCreateIdValue(SToken *pToken, int32_t optrType) {
|
|||
pSqlExpr->tokenId = optrType;
|
||||
pSqlExpr->type = SQL_NODE_VALUE;
|
||||
} else if (optrType == TK_INTEGER || optrType == TK_STRING || optrType == TK_FLOAT || optrType == TK_BOOL) {
|
||||
// if (pToken) {
|
||||
// toTSDBType(pToken->type);
|
||||
// tVariantCreate(&pSqlExpr->value, pToken);
|
||||
// }
|
||||
pSqlExpr->tokenId = optrType;
|
||||
pSqlExpr->type = SQL_NODE_VALUE;
|
||||
} else if (optrType == TK_NOW) {
|
||||
// use nanosecond by default TODO set value after getting database precision
|
||||
// pSqlExpr->value.i64 = taosGetTimestamp(TSDB_TIME_PRECISION_NANO);
|
||||
// pSqlExpr->value.nType = TSDB_DATA_TYPE_BIGINT;
|
||||
pSqlExpr->tokenId = TK_TIMESTAMP; // TK_TIMESTAMP used to denote the time value is in microsecond
|
||||
pSqlExpr->type = SQL_NODE_VALUE;
|
||||
// pSqlExpr->flags |= 1 << EXPR_FLAG_NS_TIMESTAMP;
|
||||
} else if (optrType == TK_VARIABLE) {
|
||||
// use nanosecond by default
|
||||
// TODO set value after getting database precision
|
||||
// if (pToken) {
|
||||
// char unit = 0;
|
||||
// int32_t ret = parseAbsoluteDuration(pToken->z, pToken->n, &pSqlExpr->value.i64, &unit, TSDB_TIME_PRECISION_NANO);
|
||||
// if (ret != TSDB_CODE_SUCCESS) {
|
||||
// terrno = TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
||||
// }
|
||||
// }
|
||||
|
||||
// pSqlExpr->flags |= 1 << EXPR_FLAG_NS_TIMESTAMP;
|
||||
// pSqlExpr->flags |= 1 << EXPR_FLAG_TIMESTAMP_VAR;
|
||||
// pSqlExpr->value.nType = TSDB_DATA_TYPE_BIGINT;
|
||||
pSqlExpr->tokenId = TK_TIMESTAMP;
|
||||
} else if (optrType == TK_NOW || optrType == TK_VARIABLE) {
|
||||
pSqlExpr->tokenId = optrType; // TK_TIMESTAMP used to denote this is a timestamp value
|
||||
pSqlExpr->type = SQL_NODE_VALUE;
|
||||
} else {
|
||||
// Here it must be the column name (tk_id) if it is not a number or string.
|
||||
|
@ -269,87 +198,7 @@ tSqlExpr *tSqlExprCreate(tSqlExpr *pLeft, tSqlExpr *pRight, int32_t optrType) {
|
|||
pExpr->exprToken.type = pLeft->exprToken.type;
|
||||
}
|
||||
|
||||
if ((pLeft != NULL && pRight != NULL) &&
|
||||
(optrType == TK_PLUS || optrType == TK_MINUS || optrType == TK_STAR || optrType == TK_DIVIDE || optrType == TK_REM)) {
|
||||
/*
|
||||
* if a exprToken is noted as the TK_TIMESTAMP, the time precision is microsecond
|
||||
* Otherwise, the time precision is adaptive, determined by the time precision from databases.
|
||||
*/
|
||||
if ((pLeft->tokenId == TK_INTEGER && pRight->tokenId == TK_INTEGER) ||
|
||||
(pLeft->tokenId == TK_TIMESTAMP && pRight->tokenId == TK_TIMESTAMP)) {
|
||||
pExpr->value.nType = TSDB_DATA_TYPE_BIGINT;
|
||||
pExpr->tokenId = pLeft->tokenId;
|
||||
pExpr->type = SQL_NODE_VALUE;
|
||||
|
||||
switch (optrType) {
|
||||
case TK_PLUS: {
|
||||
pExpr->value.i64 = pLeft->value.i64 + pRight->value.i64;
|
||||
break;
|
||||
}
|
||||
case TK_MINUS: {
|
||||
pExpr->value.i64 = pLeft->value.i64 - pRight->value.i64;
|
||||
break;
|
||||
}
|
||||
case TK_STAR: {
|
||||
pExpr->value.i64 = pLeft->value.i64 * pRight->value.i64;
|
||||
break;
|
||||
}
|
||||
case TK_DIVIDE: {
|
||||
pExpr->tokenId = TK_FLOAT;
|
||||
pExpr->value.nType = TSDB_DATA_TYPE_DOUBLE;
|
||||
pExpr->value.d = (double)pLeft->value.i64 / pRight->value.i64;
|
||||
break;
|
||||
}
|
||||
case TK_REM: {
|
||||
pExpr->value.i64 = pLeft->value.i64 % pRight->value.i64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tSqlExprDestroy(pLeft);
|
||||
tSqlExprDestroy(pRight);
|
||||
} else if ((pLeft->tokenId == TK_FLOAT && pRight->tokenId == TK_INTEGER) ||
|
||||
(pLeft->tokenId == TK_INTEGER && pRight->tokenId == TK_FLOAT) ||
|
||||
(pLeft->tokenId == TK_FLOAT && pRight->tokenId == TK_FLOAT)) {
|
||||
pExpr->value.nType = TSDB_DATA_TYPE_DOUBLE;
|
||||
pExpr->tokenId = TK_FLOAT;
|
||||
pExpr->type = SQL_NODE_VALUE;
|
||||
|
||||
double left = (pLeft->value.nType == TSDB_DATA_TYPE_DOUBLE) ? pLeft->value.d : pLeft->value.i64;
|
||||
double right = (pRight->value.nType == TSDB_DATA_TYPE_DOUBLE) ? pRight->value.d : pRight->value.i64;
|
||||
|
||||
switch (optrType) {
|
||||
case TK_PLUS: {
|
||||
pExpr->value.d = left + right;
|
||||
break;
|
||||
}
|
||||
case TK_MINUS: {
|
||||
pExpr->value.d = left - right;
|
||||
break;
|
||||
}
|
||||
case TK_STAR: {
|
||||
pExpr->value.d = left * right;
|
||||
break;
|
||||
}
|
||||
case TK_DIVIDE: {
|
||||
pExpr->value.d = left / right;
|
||||
break;
|
||||
}
|
||||
case TK_REM: {
|
||||
pExpr->value.d = left - ((int64_t)(left / right)) * right;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tSqlExprDestroy(pLeft);
|
||||
tSqlExprDestroy(pRight);
|
||||
|
||||
} else {
|
||||
pExpr->tokenId = optrType;
|
||||
pExpr->pLeft = pLeft;
|
||||
pExpr->pRight = pRight;
|
||||
}
|
||||
} else if (optrType == TK_IN) {
|
||||
if (optrType == TK_IN) {
|
||||
pExpr->tokenId = optrType;
|
||||
pExpr->pLeft = pLeft;
|
||||
|
||||
|
@ -501,6 +350,105 @@ void tSqlExprListDestroy(SArray *pList) {
|
|||
taosArrayDestroyEx(pList, freeExprElem);
|
||||
}
|
||||
|
||||
void tSqlExprEvaluate(tSqlExpr* pExpr) {
|
||||
tSqlExpr *pLeft = pExpr->pLeft;
|
||||
tSqlExpr *pRight = pExpr->pRight;
|
||||
|
||||
if (pLeft == NULL || pRight == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t optrType = pExpr->tokenId;
|
||||
|
||||
if ((optrType == TK_PLUS || optrType == TK_MINUS || optrType == TK_STAR || optrType == TK_DIVIDE ||
|
||||
optrType == TK_REM)) {
|
||||
/*
|
||||
* if a exprToken is noted as the TK_TIMESTAMP, the time precision is microsecond
|
||||
* Otherwise, the time precision is adaptive, determined by the time precision from databases.
|
||||
*/
|
||||
int32_t ltoken = pLeft->tokenId;
|
||||
int32_t rtoken = pRight->tokenId;
|
||||
|
||||
if ((ltoken == TK_INTEGER && rtoken == TK_INTEGER) || (ltoken == TK_TIMESTAMP && rtoken == TK_TIMESTAMP)) {
|
||||
pExpr->value.nType = TSDB_DATA_TYPE_BIGINT;
|
||||
pExpr->tokenId = ltoken;
|
||||
pExpr->type = SQL_NODE_VALUE;
|
||||
|
||||
switch (optrType) {
|
||||
case TK_PLUS: {
|
||||
pExpr->value.i64 = pLeft->value.i64 + pRight->value.i64;
|
||||
break;
|
||||
}
|
||||
case TK_MINUS: {
|
||||
pExpr->value.i64 = pLeft->value.i64 - pRight->value.i64;
|
||||
break;
|
||||
}
|
||||
case TK_STAR: {
|
||||
pExpr->value.i64 = pLeft->value.i64 * pRight->value.i64;
|
||||
break;
|
||||
}
|
||||
case TK_DIVIDE: {
|
||||
pExpr->tokenId = TK_FLOAT;
|
||||
pExpr->value.nType = TSDB_DATA_TYPE_DOUBLE;
|
||||
pExpr->value.d = (double)pLeft->value.i64 / pRight->value.i64;
|
||||
break;
|
||||
}
|
||||
case TK_REM: {
|
||||
pExpr->value.i64 = pLeft->value.i64 % pRight->value.i64;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
tSqlExprDestroy(pLeft);
|
||||
tSqlExprDestroy(pRight);
|
||||
|
||||
pExpr->pLeft = NULL;
|
||||
pExpr->pRight = NULL;
|
||||
} else if ((ltoken == TK_FLOAT && rtoken == TK_INTEGER) || (ltoken == TK_INTEGER && rtoken == TK_FLOAT) ||
|
||||
(ltoken == TK_FLOAT && rtoken == TK_FLOAT)) {
|
||||
pExpr->value.nType = TSDB_DATA_TYPE_DOUBLE;
|
||||
pExpr->tokenId = TK_FLOAT;
|
||||
pExpr->type = SQL_NODE_VALUE;
|
||||
|
||||
double left = (pLeft->value.nType == TSDB_DATA_TYPE_DOUBLE) ? pLeft->value.d : pLeft->value.i64;
|
||||
double right = (pRight->value.nType == TSDB_DATA_TYPE_DOUBLE) ? pRight->value.d : pRight->value.i64;
|
||||
|
||||
switch (optrType) {
|
||||
case TK_PLUS: {
|
||||
pExpr->value.d = left + right;
|
||||
break;
|
||||
}
|
||||
case TK_MINUS: {
|
||||
pExpr->value.d = left - right;
|
||||
break;
|
||||
}
|
||||
case TK_STAR: {
|
||||
pExpr->value.d = left * right;
|
||||
break;
|
||||
}
|
||||
case TK_DIVIDE: {
|
||||
pExpr->value.d = left / right;
|
||||
break;
|
||||
}
|
||||
case TK_REM: {
|
||||
pExpr->value.d = left - ((int64_t)(left / right)) * right;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
tSqlExprDestroy(pLeft);
|
||||
tSqlExprDestroy(pRight);
|
||||
|
||||
pExpr->pLeft = NULL;
|
||||
pExpr->pRight = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SSqlNode *tSetQuerySqlNode(SToken *pSelectToken, SArray *pSelNodeList, SRelationInfo *pFrom, tSqlExpr *pWhere,
|
||||
SArray *pGroupby, SArray *pSortOrder, SIntervalVal *pInterval,
|
||||
SSessionWindowVal *pSession, SWindowStateVal *pWindowStateVal, SToken *pSliding, SArray *pFill, SLimit *pLimit,
|
||||
|
|
|
@ -13,13 +13,82 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ttime.h"
|
||||
#include "parserInt.h"
|
||||
#include "parserUtil.h"
|
||||
#include "tmsgtype.h"
|
||||
|
||||
static int32_t setInvalidOperatorErrMsg(char* dst, int32_t dstBufLen, const char* msg) {
|
||||
strncpy(dst, msg, dstBufLen);
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
static int32_t evaluateImpl(tSqlExpr* pExpr, int32_t tsPrecision) {
|
||||
int32_t code = 0;
|
||||
if (pExpr->type == SQL_NODE_EXPR) {
|
||||
code = evaluateImpl(pExpr->pLeft, tsPrecision);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
code = evaluateImpl(pExpr->pRight, tsPrecision);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
if (pExpr->pLeft->type == SQL_NODE_VALUE && pExpr->pRight->type == SQL_NODE_VALUE) {
|
||||
tSqlExpr* pLeft = pExpr->pLeft;
|
||||
tSqlExpr* pRight = pExpr->pRight;
|
||||
if ((pLeft->tokenId == TK_TIMESTAMP && (pRight->tokenId == TK_INTEGER || pRight->tokenId == TK_FLOAT)) ||
|
||||
((pRight->tokenId == TK_TIMESTAMP && (pLeft->tokenId == TK_INTEGER || pLeft->tokenId == TK_FLOAT)))) {
|
||||
return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
||||
} else if (pLeft->tokenId == TK_TIMESTAMP && pRight->tokenId == TK_TIMESTAMP) {
|
||||
tSqlExprEvaluate(pExpr);
|
||||
} else {
|
||||
tSqlExprEvaluate(pExpr);
|
||||
}
|
||||
} else {
|
||||
// Other types of expressions are not evaluated, they will be handled during the validation of the abstract syntax tree.
|
||||
}
|
||||
} else if (pExpr->type == SQL_NODE_VALUE) {
|
||||
if (pExpr->tokenId == TK_NOW) {
|
||||
pExpr->value.i64 = taosGetTimestamp(tsPrecision);
|
||||
pExpr->value.nType = TSDB_DATA_TYPE_BIGINT;
|
||||
pExpr->tokenId = TK_TIMESTAMP;
|
||||
} else if (pExpr->tokenId == TK_VARIABLE) {
|
||||
char unit = 0;
|
||||
SToken* pToken = &pExpr->exprToken;
|
||||
int32_t ret = parseAbsoluteDuration(pToken->z, pToken->n, &pExpr->value.i64, &unit, tsPrecision);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
||||
}
|
||||
|
||||
pExpr->value.nType = TSDB_DATA_TYPE_BIGINT;
|
||||
pExpr->tokenId = TK_TIMESTAMP;
|
||||
} else if (pExpr->tokenId == TK_NULL) {
|
||||
pExpr->value.nType = TSDB_DATA_TYPE_NULL;
|
||||
} else if (pExpr->tokenId == TK_INTEGER || pExpr->tokenId == TK_STRING || pExpr->tokenId == TK_FLOAT || pExpr->tokenId == TK_BOOL) {
|
||||
SToken* pToken = &pExpr->exprToken;
|
||||
|
||||
int32_t tokenType = pToken->type;
|
||||
toTSDBType(tokenType);
|
||||
taosVariantCreate(&pExpr->value, pToken->z, pToken->n, tokenType);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
// other types of data are handled in the parent level.
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t evaluateSqlNode(SSqlNode* pNode, int32_t tsPrecision, char* msg, int32_t msgBufLen) {
|
||||
assert(pNode != NULL && msg != NULL && msgBufLen > 0);
|
||||
if (pNode->pWhere == NULL) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t code = evaluateImpl(pNode->pWhere, tsPrecision);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
strncpy(msg, "invalid time expression in sql", msgBufLen);
|
||||
return code;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQueryStmtInfo* pQueryInfo, int64_t id, char* msgBuf, int32_t msgBufLen) {
|
||||
|
@ -37,15 +106,15 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
const char* msg2 = "invalid name";
|
||||
|
||||
SToken* pzName = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
||||
if ((pInfo->type != TSDB_SQL_DROP_DNODE) && (parserValidateNameToken(pzName) != TSDB_CODE_SUCCESS)) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg2);
|
||||
if ((pInfo->type != TSDB_SQL_DROP_DNODE) && (parserValidateIdToken(pzName) != TSDB_CODE_SUCCESS)) {
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg2);
|
||||
}
|
||||
|
||||
if (pInfo->type == TSDB_SQL_DROP_DB) {
|
||||
assert(taosArrayGetSize(pInfo->pMiscInfo->a) == 1);
|
||||
code = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pzName);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg2);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg2);
|
||||
}
|
||||
|
||||
} else if (pInfo->type == TSDB_SQL_DROP_TABLE) {
|
||||
|
@ -62,7 +131,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
strncpy(pCmd->payload, pzName->z, pzName->n);
|
||||
} else { // drop user/account
|
||||
if (pzName->n >= TSDB_USER_LEN) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg3);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg3);
|
||||
}
|
||||
|
||||
strncpy(pCmd->payload, pzName->z, pzName->n);
|
||||
|
@ -76,12 +145,12 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
||||
|
||||
if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg);
|
||||
}
|
||||
|
||||
int32_t ret = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pToken);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -116,19 +185,19 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
|
||||
SCreateDbInfo* pCreateDB = &(pInfo->pMiscInfo->dbOpt);
|
||||
if (pCreateDB->dbname.n >= TSDB_DB_NAME_LEN) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg2);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg2);
|
||||
}
|
||||
|
||||
char buf[TSDB_DB_NAME_LEN] = {0};
|
||||
SToken token = taosTokenDup(&pCreateDB->dbname, buf, tListLen(buf));
|
||||
|
||||
if (tscValidateName(&token) != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg1);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg1);
|
||||
}
|
||||
|
||||
int32_t ret = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), &token);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg2);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg2);
|
||||
}
|
||||
|
||||
if (parseCreateDBOptions(pCmd, pCreateDB) != TSDB_CODE_SUCCESS) {
|
||||
|
@ -142,7 +211,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
const char* msg = "invalid host name (ip address)";
|
||||
|
||||
if (taosArrayGetSize(pInfo->pMiscInfo->a) > 1) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg);
|
||||
}
|
||||
|
||||
SToken* id = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
||||
|
@ -166,11 +235,11 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
}
|
||||
|
||||
if (pName->n >= TSDB_USER_LEN) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg3);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg3);
|
||||
}
|
||||
|
||||
if (tscValidateName(pName) != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg2);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg2);
|
||||
}
|
||||
|
||||
SCreateAcctInfo* pAcctOpt = &pInfo->pMiscInfo->acctOpt;
|
||||
|
@ -180,7 +249,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
} else if (strncmp(pAcctOpt->stat.z, "all", 3) == 0 && pAcctOpt->stat.n == 3) {
|
||||
} else if (strncmp(pAcctOpt->stat.z, "no", 2) == 0 && pAcctOpt->stat.n == 2) {
|
||||
} else {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg1);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +261,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
|
||||
SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
||||
if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg1);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg1);
|
||||
}
|
||||
// additional msg has been attached already
|
||||
code = tscSetTableFullName(&pTableMetaInfo->name, pToken, pSql);
|
||||
|
@ -208,7 +277,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
|
||||
SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
||||
if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg1);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg1);
|
||||
}
|
||||
|
||||
code = tscSetTableFullName(&pTableMetaInfo->name, pToken, pSql);
|
||||
|
@ -223,11 +292,11 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
|
||||
SToken* pToken = taosArrayGet(pInfo->pMiscInfo->a, 0);
|
||||
if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg1);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg1);
|
||||
}
|
||||
|
||||
if (pToken->n > TSDB_DB_NAME_LEN) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg1);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg1);
|
||||
}
|
||||
return tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pToken);
|
||||
}
|
||||
|
@ -240,7 +309,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
|
||||
/* validate the parameter names and options */
|
||||
if (validateDNodeConfig(pMiscInfo) != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg2);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg2);
|
||||
}
|
||||
|
||||
char* pMsg = pCmd->payload;
|
||||
|
@ -254,7 +323,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
strncpy(pCfg->ep, t0->z, t0->n);
|
||||
|
||||
if (validateEp(pCfg->ep) != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg3);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg3);
|
||||
}
|
||||
|
||||
strncpy(pCfg->config, t1->z, t1->n);
|
||||
|
@ -283,11 +352,11 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
SToken* pPwd = &pUser->passwd;
|
||||
|
||||
if (pName->n >= TSDB_USER_LEN) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg3);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg3);
|
||||
}
|
||||
|
||||
if (tscValidateName(pName) != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg2);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg2);
|
||||
}
|
||||
|
||||
if (pCmd->command == TSDB_SQL_CREATE_USER) {
|
||||
|
@ -311,10 +380,10 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
} else if (strncasecmp(pPrivilege->z, "write", 5) == 0 && pPrivilege->n == 5) {
|
||||
pCmd->count = 3;
|
||||
} else {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg5);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg5);
|
||||
}
|
||||
} else {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg7);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg7);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,7 +396,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
|
||||
// validate the parameter names and options
|
||||
if (validateLocalConfig(pMiscInfo) != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg);
|
||||
}
|
||||
|
||||
int32_t numOfToken = (int32_t) taosArrayGetSize(pMiscInfo->a);
|
||||
|
@ -382,7 +451,7 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
tscTrace("0x%"PRIx64" start to parse the %dth subclause, total:%"PRIzu, pSql->self, i, size);
|
||||
|
||||
if (size > 1 && pSqlNode->from && pSqlNode->from->type == SQL_NODE_FROM_SUBQUERY) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg1);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg1);
|
||||
}
|
||||
|
||||
// normalizeSqlNode(pSqlNode); // normalize the column name in each function
|
||||
|
@ -448,19 +517,19 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
|
|||
assert(taosArrayGetSize(pInfo->pMiscInfo->a) == 1);
|
||||
code = tNameSetDbName(&pTableMetaInfo->name, getAccountId(pSql), pzName);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg1);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TSDB_SQL_COMPACT_VNODE:{
|
||||
const char* msg = "invalid compact";
|
||||
if (setCompactVnodeInfo(pSql, pInfo) != TSDB_CODE_SUCCESS) {
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, msg);
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, msg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return setInvalidOperatorErrMsg(msgBuf, msgBufLen, "not support sql expression");
|
||||
return setInvalidOperatorMsg(msgBuf, msgBufLen, "not support sql expression");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "parserInt.h"
|
||||
#include "ttoken.h"
|
||||
#include "astGenerator.h"
|
||||
#include "parserUtil.h"
|
||||
|
||||
bool qIsInsertSql(const char* pStr, size_t length) {
|
||||
return false;
|
||||
|
@ -50,6 +51,216 @@ int32_t qParserConvertSql(const char* pStr, size_t length, char** pConvertSql) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t qParserExtractRequestedMetaInfo(const SArray* pSqlNodeList, SMetaReq* pMetaInfo) {
|
||||
return 0;
|
||||
static int32_t getTableNameFromSubquery(SSqlNode* pSqlNode, SArray* tableNameList, char* msgBuf) {
|
||||
int32_t numOfSub = (int32_t)taosArrayGetSize(pSqlNode->from->list);
|
||||
|
||||
for (int32_t j = 0; j < numOfSub; ++j) {
|
||||
SRelElementPair* sub = taosArrayGet(pSqlNode->from->list, j);
|
||||
|
||||
int32_t num = (int32_t)taosArrayGetSize(sub->pSubquery);
|
||||
for (int32_t i = 0; i < num; ++i) {
|
||||
SSqlNode* p = taosArrayGetP(sub->pSubquery, i);
|
||||
if (p->from->type == SQL_NODE_FROM_TABLELIST) {
|
||||
int32_t code = getTableNameFromSqlNode(p, tableNameList, msgBuf);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
} else {
|
||||
getTableNameFromSubquery(p, tableNameList, msgBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t getTableNameFromSqlNode(SSqlNode* pSqlNode, SArray* tableNameList, char* msg, int32_t msgBufLen) {
|
||||
const char* msg1 = "invalid table name";
|
||||
|
||||
int32_t numOfTables = (int32_t) taosArrayGetSize(pSqlNode->from->list);
|
||||
assert(pSqlNode->from->type == SQL_NODE_FROM_TABLELIST);
|
||||
|
||||
for(int32_t j = 0; j < numOfTables; ++j) {
|
||||
SRelElementPair* item = taosArrayGet(pSqlNode->from->list, j);
|
||||
|
||||
SToken* t = &item->tableName;
|
||||
if (t->type == TK_INTEGER || t->type == TK_FLOAT) {
|
||||
return parserSetInvalidOperatorMsg(msg, msgBufLen, msg1);
|
||||
}
|
||||
|
||||
tscDequoteAndTrimToken(t);
|
||||
if (parserValidateIdToken(t) != TSDB_CODE_SUCCESS) {
|
||||
return parserSetInvalidOperatorMsg(msg, msgBufLen, msg1);
|
||||
}
|
||||
|
||||
SName name = {0};
|
||||
int32_t code = tscSetTableFullName(&name, t, pSql);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
taosArrayPush(tableNameList, &name);
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t qParserExtractRequestedMetaInfo(const SArray* pSqlNodeList, SMetaReq* pMetaInfo, char* msg, int32_t msgBufLen) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
SArray* tableNameList = NULL;
|
||||
SArray* pVgroupList = NULL;
|
||||
SArray* plist = NULL;
|
||||
STableMeta* pTableMeta = NULL;
|
||||
// size_t tableMetaCapacity = 0;
|
||||
// SQueryInfo* pQueryInfo = tscGetQueryInfo(pCmd);
|
||||
|
||||
// pCmd->pTableMetaMap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
|
||||
|
||||
tableNameList = taosArrayInit(4, sizeof(SName));
|
||||
size_t size = taosArrayGetSize(pSqlNodeList);
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
SSqlNode* pSqlNode = taosArrayGetP(pSqlNodeList, i);
|
||||
if (pSqlNode->from == NULL) {
|
||||
goto _end;
|
||||
}
|
||||
|
||||
// load the table meta in the from clause
|
||||
if (pSqlNode->from->type == SQL_NODE_FROM_TABLELIST) {
|
||||
code = getTableNameFromSqlNode(pSqlNode, tableNameList, msg, msgBufLen);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _end;
|
||||
}
|
||||
} else {
|
||||
code = getTableNameFromSubquery(pSqlNode, tableNameList, msg, msgBufLen);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char name[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
|
||||
plist = taosArrayInit(4, POINTER_BYTES);
|
||||
pVgroupList = taosArrayInit(4, POINTER_BYTES);
|
||||
|
||||
taosArraySort(tableNameList, tnameComparFn);
|
||||
taosArrayRemoveDuplicate(tableNameList, tnameComparFn, NULL);
|
||||
|
||||
STableMeta* pSTMeta = (STableMeta *)(pSql->pBuf);
|
||||
size_t numOfTables = taosArrayGetSize(tableNameList);
|
||||
for (int32_t i = 0; i < numOfTables; ++i) {
|
||||
SName* pname = taosArrayGet(tableNameList, i);
|
||||
tNameExtractFullName(pname, name);
|
||||
|
||||
size_t len = strlen(name);
|
||||
|
||||
if (NULL == taosHashGetCloneExt(tscTableMetaMap, name, len, NULL, (void **)&pTableMeta, &tableMetaCapacity)) {
|
||||
// not found
|
||||
tfree(pTableMeta);
|
||||
}
|
||||
|
||||
if (pTableMeta && pTableMeta->id.uid > 0) {
|
||||
tscDebug("0x%"PRIx64" retrieve table meta %s from local buf", pSql->self, name);
|
||||
|
||||
// avoid mem leak, may should update pTableMeta
|
||||
void* pVgroupIdList = NULL;
|
||||
if (pTableMeta->tableType == TSDB_CHILD_TABLE) {
|
||||
code = tscCreateTableMetaFromSTableMeta((STableMeta **)(&pTableMeta), name, &tableMetaCapacity, (STableMeta **)(&pSTMeta));
|
||||
pSql->pBuf = (void *)pSTMeta;
|
||||
|
||||
// create the child table meta from super table failed, try load it from mnode
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
char* t = strdup(name);
|
||||
taosArrayPush(plist, &t);
|
||||
continue;
|
||||
}
|
||||
} else if (pTableMeta->tableType == TSDB_SUPER_TABLE) {
|
||||
// the vgroup list of super table is not kept in local buffer, so here need retrieve it from the mnode each time
|
||||
tscDebug("0x%"PRIx64" try to acquire cached super table %s vgroup id list", pSql->self, name);
|
||||
void* pv = taosCacheAcquireByKey(tscVgroupListBuf, name, len);
|
||||
if (pv == NULL) {
|
||||
char* t = strdup(name);
|
||||
taosArrayPush(pVgroupList, &t);
|
||||
tscDebug("0x%"PRIx64" failed to retrieve stable %s vgroup id list in cache, try fetch from mnode", pSql->self, name);
|
||||
} else {
|
||||
tFilePage* pdata = (tFilePage*) pv;
|
||||
pVgroupIdList = taosArrayInit((size_t) pdata->num, sizeof(int32_t));
|
||||
if (pVgroupIdList == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
taosArrayAddBatch(pVgroupIdList, pdata->data, (int32_t) pdata->num);
|
||||
taosCacheRelease(tscVgroupListBuf, &pv, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (taosHashGet(pCmd->pTableMetaMap, name, len) == NULL) {
|
||||
STableMeta* pMeta = tscTableMetaDup(pTableMeta);
|
||||
STableMetaVgroupInfo tvi = { .pTableMeta = pMeta, .vgroupIdList = pVgroupIdList};
|
||||
taosHashPut(pCmd->pTableMetaMap, name, len, &tvi, sizeof(STableMetaVgroupInfo));
|
||||
}
|
||||
} else {
|
||||
// Add to the retrieve table meta array list.
|
||||
// If the tableMeta is missing, the cached vgroup list for the corresponding super table will be ignored.
|
||||
tscDebug("0x%"PRIx64" failed to retrieve table meta %s from local buf", pSql->self, name);
|
||||
|
||||
char* t = strdup(name);
|
||||
taosArrayPush(plist, &t);
|
||||
}
|
||||
}
|
||||
|
||||
size_t funcSize = 0;
|
||||
if (pInfo->funcs) {
|
||||
funcSize = taosArrayGetSize(pInfo->funcs);
|
||||
}
|
||||
|
||||
if (funcSize > 0) {
|
||||
for (size_t i = 0; i < funcSize; ++i) {
|
||||
SToken* t = taosArrayGet(pInfo->funcs, i);
|
||||
if (NULL == t) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t->n >= TSDB_FUNC_NAME_LEN) {
|
||||
code = tscSQLSyntaxErrMsg(tscGetErrorMsgPayload(pCmd), "too long function name", t->z);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _end;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t functionId = isValidFunction(t->z, t->n);
|
||||
if (functionId < 0) {
|
||||
struct SUdfInfo info = {0};
|
||||
info.name = strndup(t->z, t->n);
|
||||
if (pQueryInfo->pUdfInfo == NULL) {
|
||||
pQueryInfo->pUdfInfo = taosArrayInit(4, sizeof(struct SUdfInfo));
|
||||
}
|
||||
|
||||
info.functionId = (int32_t)taosArrayGetSize(pQueryInfo->pUdfInfo) * (-1) - 1;;
|
||||
taosArrayPush(pQueryInfo->pUdfInfo, &info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// load the table meta for a given table name list
|
||||
if (taosArrayGetSize(plist) > 0 || taosArrayGetSize(pVgroupList) > 0 || (pQueryInfo->pUdfInfo && taosArrayGetSize(pQueryInfo->pUdfInfo) > 0)) {
|
||||
code = getMultiTableMetaFromMnode(pSql, plist, pVgroupList, pQueryInfo->pUdfInfo, tscTableMetaCallBack, true);
|
||||
}
|
||||
|
||||
_end:
|
||||
if (plist != NULL) {
|
||||
taosArrayDestroyEx(plist, freeElem);
|
||||
}
|
||||
|
||||
if (pVgroupList != NULL) {
|
||||
taosArrayDestroyEx(pVgroupList, freeElem);
|
||||
}
|
||||
|
||||
if (tableNameList != NULL) {
|
||||
taosArrayDestroy(tableNameList);
|
||||
}
|
||||
|
||||
tfree(pTableMeta);
|
||||
return code;
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
#include "taoserror.h"
|
||||
#include "tutil.h"
|
||||
|
||||
int32_t parserValidateNameToken(SToken* pToken) {
|
||||
int32_t parserValidateIdToken(SToken* pToken) {
|
||||
if (pToken == NULL || pToken->z == NULL || pToken->type != TK_ID) {
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
||||
|
@ -57,4 +57,9 @@ int32_t parserValidateNameToken(SToken* pToken) {
|
|||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t parserSetInvalidOperatorMsg(char* dst, int32_t dstBufLen, const char* msg) {
|
||||
strncpy(dst, msg, dstBufLen);
|
||||
return TSDB_CODE_TSC_INVALID_OPERATION;
|
||||
}
|
|
@ -411,6 +411,7 @@ uint32_t tGetToken(char* z, uint32_t* tokenId) {
|
|||
*tokenId = TK_QUESTION;
|
||||
return 1;
|
||||
}
|
||||
case '`':
|
||||
case '\'':
|
||||
case '"': {
|
||||
int delim = z[0];
|
||||
|
@ -434,7 +435,7 @@ uint32_t tGetToken(char* z, uint32_t* tokenId) {
|
|||
if (z[i]) i++;
|
||||
|
||||
if (strEnd) {
|
||||
*tokenId = TK_STRING;
|
||||
*tokenId = (delim == '`')? TK_ID:TK_STRING;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "ttoken.h"
|
||||
#include "astGenerator.h"
|
||||
#include "parserUtil.h"
|
||||
#include "parserInt.h"
|
||||
|
||||
namespace {
|
||||
int32_t testValidateName(char* name) {
|
||||
|
@ -23,7 +24,7 @@ int32_t testValidateName(char* name) {
|
|||
token.type = 0;
|
||||
|
||||
tGetToken(name, &token.type);
|
||||
return parserValidateNameToken(&token);
|
||||
return parserValidateIdToken(&token);
|
||||
}
|
||||
|
||||
SToken createToken(char* s) {
|
||||
|
@ -667,4 +668,29 @@ TEST(testCase, isValidNumber_test) {
|
|||
TEST(testCase, generateAST_test) {
|
||||
SSqlInfo info = doGenerateAST("select * from t1 where ts < now");
|
||||
ASSERT_EQ(info.valid, true);
|
||||
}
|
||||
|
||||
SSqlInfo info1 = doGenerateAST("select * from `t.1abc` where ts<now+2h and col < 20+99");
|
||||
ASSERT_EQ(info1.valid, true);
|
||||
|
||||
char msg[128] = {0};
|
||||
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, msg, sizeof(msg));
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
SSqlInfo info2 = doGenerateAST("select * from abc where ts<now+2");
|
||||
SSqlNode* pNode2 = (SSqlNode*) taosArrayGetP(((SArray*)info2.list), 0);
|
||||
code = evaluateSqlNode(pNode2, TSDB_TIME_PRECISION_MILLI, msg, sizeof(msg));
|
||||
ASSERT_NE(code, 0);
|
||||
}
|
||||
|
||||
TEST(testCase, evaluateAST_test) {
|
||||
SSqlInfo info1 = doGenerateAST("select a, b+22 from `t.1abc` where ts<now+2h and col < 20 + 99");
|
||||
ASSERT_EQ(info1.valid, true);
|
||||
|
||||
char msg[128] = {0};
|
||||
SSqlNode* pNode = (SSqlNode*) taosArrayGetP(((SArray*)info1.list), 0);
|
||||
int32_t code = evaluateSqlNode(pNode, TSDB_TIME_PRECISION_NANO, msg, sizeof(msg));
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue